Remove dependence on .restart file, add reboot option to launcher

This commit is contained in:
Griatch 2018-01-20 12:41:27 +01:00
parent 9dfd1f5ea8
commit d6105f6d6c
7 changed files with 173 additions and 131 deletions

View file

@ -104,7 +104,7 @@ class AMPServerClientProtocol(amp.AMPMultiConnectionProtocol):
info_dict = self.factory.server.get_info_dict() info_dict = self.factory.server.get_info_dict()
super(AMPServerClientProtocol, self).connectionMade() super(AMPServerClientProtocol, self).connectionMade()
# first thing we do is to request the Portal to sync all sessions # first thing we do is to request the Portal to sync all sessions
# back with the Server side # back with the Server side. We also need the startup mode (reload, reset, shutdown)
self.send_AdminServer2Portal(amp.DUMMYSESSION, operation=amp.PSYNC, info_dict=info_dict) self.send_AdminServer2Portal(amp.DUMMYSESSION, operation=amp.PSYNC, info_dict=info_dict)
def data_to_portal(self, command, sessid, **kwargs): def data_to_portal(self, command, sessid, **kwargs):
@ -212,7 +212,10 @@ class AMPServerClientProtocol(amp.AMPMultiConnectionProtocol):
server_sessionhandler.portal_disconnect_all() server_sessionhandler.portal_disconnect_all()
elif operation == amp.PSYNC: # portal_session_sync elif operation == amp.PSYNC: # portal_session_sync
# force a resync of sessions from the portal side # force a resync of sessions from the portal side. This happens on
# first server-connect.
server_restart_mode = kwargs.get("server_restart_mode", "shutdown")
self.factory.server.run_init_hooks(server_restart_mode)
server_sessionhandler.portal_sessions_sync(kwargs.get("sessiondata")) server_sessionhandler.portal_sessions_sync(kwargs.get("sessiondata"))
elif operation == amp.SRELOAD: # server reload elif operation == amp.SRELOAD: # server reload

View file

@ -305,20 +305,24 @@ HELP_ENTRY = \
MENU = \ MENU = \
""" """
+----Evennia Launcher-------------------------------------------+ +----Evennia Launcher-------------------------------------------+
| | {gameinfo}
+--- Common operations -----------------------------------------+ +--- Common operations -----------------------------------------+
| 1) Start Portal and Server (also restart downed Server) | | 1) Start (also restart stopped Server) |
| 2) Reload Server (update on code changes) | | 2) Reload (stop/start Server in 'reload' mode) |
| 3) Stop Portal and Server (full shutdown) | | 3) Stop (shutdown Portal and Server) |
| 4) Reboot (shutdown then restart) |
+--- Other -----------------------------------------------------+ +--- Other -----------------------------------------------------+
| 4) Reset Server (Server shutdown with restart) | | 5) Reset (stop/start Server in 'shutdown' mode) |
| 5) Stop Server only | | 6) Stop Server only |
| 6) Kill Portal + Server (send kill signal to process) | | 7) Kill Server only (send kill signal to process) |
| 7) Kill Server only | | 8) Kill Portal + Server |
+--- Information -----------------------------------------------+ +--- Information -----------------------------------------------+
| 8) Tail log file | | 9) Tail log file |
| 9) Run status | | 10) Run status |
| 10) Port info | | 11) Port info |
+--- Testing ---------------------------------------------------+
| 12) Test gamedir (run gamedir test suite, if any) |
| 13) Test Evennia (run evennia test suite) |
+---------------------------------------------------------------+ +---------------------------------------------------------------+
| h) Help i) About info q) Abort | | h) Help i) About info q) Abort |
+---------------------------------------------------------------+""" +---------------------------------------------------------------+"""
@ -452,7 +456,8 @@ ARG_OPTIONS = \
start - launch server+portal if not running start - launch server+portal if not running
reload - restart server (code refresh) reload - restart server (code refresh)
stop - shutdown server+portal stop - shutdown server+portal
reset - mimic server shutdown but with auto-restart reboot - shutdown server+portal, then start again
reset - restart server in shutdown-mode (not reload mode)
sstart - start only server (requires portal) sstart - start only server (requires portal)
kill - send kill signal to portal+server (force) kill - send kill signal to portal+server (force)
skill = send kill signal only to server skill = send kill signal only to server
@ -461,10 +466,13 @@ ARG_OPTIONS = \
menu - show a menu of options menu - show a menu of options
Other input, like migrate and shell is passed on to Django.""" Other input, like migrate and shell is passed on to Django."""
# ------------------------------------------------------------
#
# Private helper functions
#
# ------------------------------------------------------------
# Info formatting def _print_info(portal_info_dict, server_info_dict):
def print_info(portal_info_dict, server_info_dict):
""" """
Format info dicts from the Portal/Server for display Format info dicts from the Portal/Server for display
@ -498,6 +506,43 @@ def print_info(portal_info_dict, server_info_dict):
print(top_border + "\n" + info + '\n' + border) print(top_border + "\n" + info + '\n' + border)
def _parse_status(response):
"Unpack the status information"
return pickle.loads(response['status'])
def _get_twistd_cmdline(pprofiler, sprofiler):
"""
Compile the command line for starting a Twisted application using the 'twistd' executable.
"""
portal_cmd = [TWISTED_BINARY,
"--python={}".format(PORTAL_PY_FILE)]
server_cmd = [TWISTED_BINARY,
"--python={}".format(SERVER_PY_FILE)]
if os.name != 'nt':
# PID files only for UNIX
portal_cmd.append("--pidfile={}".format(PORTAL_PIDFILE))
server_cmd.append("--pidfile={}".format(SERVER_PIDFILE))
if pprofiler:
portal_cmd.extend(["--savestats",
"--profiler=cprofile",
"--profile={}".format(PPROFILER_LOGFILE)])
if sprofiler:
server_cmd.extend(["--savestats",
"--profiler=cprofile",
"--profile={}".format(SPROFILER_LOGFILE)])
return portal_cmd, server_cmd
def _reactor_stop():
if not NO_REACTOR_STOP:
reactor.stop()
# ------------------------------------------------------------ # ------------------------------------------------------------
# #
# Protocol Evennia launcher - Portal/Server communication # Protocol Evennia launcher - Portal/Server communication
@ -560,11 +605,6 @@ class AMPLauncherProtocol(amp.AMP):
return {"status": ""} return {"status": ""}
def _reactor_stop():
if not NO_REACTOR_STOP:
reactor.stop()
def send_instruction(operation, arguments, callback=None, errback=None): def send_instruction(operation, arguments, callback=None, errback=None):
""" """
Send instruction and handle the response. Send instruction and handle the response.
@ -579,12 +619,10 @@ def send_instruction(operation, arguments, callback=None, errback=None):
def _callback(result): def _callback(result):
if callback: if callback:
callback(result) callback(result)
# prot.transport.loseConnection()
def _errback(fail): def _errback(fail):
if errback: if errback:
errback(fail) errback(fail)
# prot.transport.loseConnection()
def _on_connect(prot): def _on_connect(prot):
""" """
@ -620,37 +658,6 @@ def send_instruction(operation, arguments, callback=None, errback=None):
deferred.addCallbacks(_on_connect, _on_connect_fail) deferred.addCallbacks(_on_connect, _on_connect_fail)
REACTOR_RUN = True REACTOR_RUN = True
def _parse_status(response):
"Unpack the status information"
return pickle.loads(response['status'])
def _get_twistd_cmdline(pprofiler, sprofiler):
"""
Compile the command line for starting a Twisted application using the 'twistd' executable.
"""
portal_cmd = [TWISTED_BINARY,
"--python={}".format(PORTAL_PY_FILE)]
server_cmd = [TWISTED_BINARY,
"--python={}".format(SERVER_PY_FILE)]
if os.name != 'nt':
# PID files only for UNIX
portal_cmd.append("--pidfile={}".format(PORTAL_PIDFILE))
server_cmd.append("--pidfile={}".format(SERVER_PIDFILE))
if pprofiler:
portal_cmd.extend(["--savestats",
"--profiler=cprofile",
"--profile={}".format(PPROFILER_LOGFILE)])
if sprofiler:
server_cmd.extend(["--savestats",
"--profiler=cprofile",
"--profile={}".format(SPROFILER_LOGFILE)])
return portal_cmd, server_cmd
def query_status(callback=None): def query_status(callback=None):
""" """
@ -693,9 +700,10 @@ def wait_for_status(portal_running=True, server_running=True, callback=None, err
Repeat the status ping until the desired state combination is achieved. Repeat the status ping until the desired state combination is achieved.
Args: Args:
portal_running (bool or None): Desired portal run-state. If None, any state is accepted. portal_running (bool or None): Desired portal run-state. If None, any state
server_running (bool or None): Desired server run-state. If None, any state is accepted. is accepted.
the portal must be running. server_running (bool or None): Desired server run-state. If None, any state
is accepted. The portal must be running.
callback (callable): Will be called with portal_state, server_state when callback (callable): Will be called with portal_state, server_state when
condition is fulfilled. condition is fulfilled.
errback (callable): Will be called with portal_state, server_state if the errback (callable): Will be called with portal_state, server_state if the
@ -748,13 +756,13 @@ def wait_for_status(portal_running=True, server_running=True, callback=None, err
return send_instruction(PSTATUS, None, _callback, _errback) return send_instruction(PSTATUS, None, _callback, _errback)
# ------------------------------------------------------------ # ------------------------------------------------------------
# #
# Operational functions # Operational functions
# #
# ------------------------------------------------------------ # ------------------------------------------------------------
def start_evennia(pprofiler=False, sprofiler=False): def start_evennia(pprofiler=False, sprofiler=False):
""" """
This will start Evennia anew by launching the Evennia Portal (which in turn This will start Evennia anew by launching the Evennia Portal (which in turn
@ -771,7 +779,7 @@ def start_evennia(pprofiler=False, sprofiler=False):
print("... Server started.\nEvennia running.") print("... Server started.\nEvennia running.")
if response: if response:
_, _, _, _, pinfo, sinfo = response _, _, _, _, pinfo, sinfo = response
print_info(pinfo, sinfo) _print_info(pinfo, sinfo)
_reactor_stop() _reactor_stop()
def _portal_started(*args): def _portal_started(*args):
@ -836,10 +844,9 @@ def reload_evennia(sprofiler=False, reset=False):
send_instruction(SSTART, server_cmd) send_instruction(SSTART, server_cmd)
def _portal_not_running(fail): def _portal_not_running(fail):
print("Evennia not running. Starting from scratch ...") print("Evennia not running. Starting up ...")
start_evennia() start_evennia()
# get portal status
send_instruction(PSTATUS, None, _portal_running, _portal_not_running) send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
@ -869,12 +876,51 @@ def stop_evennia():
wait_for_status(False, None, _portal_stopped) wait_for_status(False, None, _portal_stopped)
def _portal_not_running(fail): def _portal_not_running(fail):
print("Evennia is not running.") print("Evennia not running.")
_reactor_stop() _reactor_stop()
send_instruction(PSTATUS, None, _portal_running, _portal_not_running) send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
def reboot_evennia(pprofiler=False, sprofiler=False):
"""
This is essentially an evennia stop && evennia start except we make sure
the system has successfully shut down before starting it again.
If evennia was not running, start it.
"""
global AMP_CONNECTION
def _portal_stopped(*args):
print("... Portal stopped. Evennia shut down. Rebooting ...")
global AMP_CONNECTION
AMP_CONNECTION = None
start_evennia(pprofiler, sprofiler)
def _server_stopped(*args):
print("... Server stopped.\nStopping Portal ...")
send_instruction(PSHUTD, {})
wait_for_status(False, None, _portal_stopped)
def _portal_running(response):
prun, srun, ppid, spid, _, _ = _parse_status(response)
if srun:
print("Server stopping ...")
send_instruction(SSHUTD, {})
wait_for_status_reply(_server_stopped)
else:
print("Server already stopped.\nStopping Portal ...")
send_instruction(PSHUTD, {})
wait_for_status(False, None, _portal_stopped)
def _portal_not_running(fail):
print("Evennia not running. Starting up ...")
start_evennia()
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
def stop_server_only(): def stop_server_only():
""" """
Only stop the Server-component of Evennia (this is not useful except for debug) Only stop the Server-component of Evennia (this is not useful except for debug)
@ -908,7 +954,7 @@ def query_info():
""" """
def _got_status(status): def _got_status(status):
_, _, _, _, pinfo, sinfo = _parse_status(status) _, _, _, _, pinfo, sinfo = _parse_status(status)
print_info(pinfo, sinfo) _print_info(pinfo, sinfo)
_reactor_stop() _reactor_stop()
def _portal_running(response): def _portal_running(response):
@ -1435,6 +1481,12 @@ def error_check_python_modules():
_imp(settings.BASE_SCRIPT_TYPECLASS) _imp(settings.BASE_SCRIPT_TYPECLASS)
# ------------------------------------------------------------
#
# Options
#
# ------------------------------------------------------------
def init_game_directory(path, check_db=True): def init_game_directory(path, check_db=True):
""" """
Try to analyze the given path to find settings.py - this defines Try to analyze the given path to find settings.py - this defines
@ -1623,8 +1675,11 @@ def run_menu():
""" """
while True: while True:
# menu loop # menu loop
gamedir = "/{}".format(os.path.basename(GAMEDIR))
leninfo = len(gamedir)
line = "|" + " " * (60 - leninfo) + gamedir + " " * 3 + "|"
print(MENU) print(MENU.format(gameinfo=line))
inp = input(" option > ") inp = input(" option > ")
# quitting and help # quitting and help
@ -1652,22 +1707,24 @@ def run_menu():
elif inp == 3: elif inp == 3:
stop_evennia() stop_evennia()
elif inp == 4: elif inp == 4:
reload_evennia(False, True) reboot_evennia(False, False)
elif inp == 5: elif inp == 5:
stop_server_only() reload_evennia(False, True)
elif inp == 6: elif inp == 6:
kill(PORTAL_PIDFILE, 'Portal') stop_server_only()
kill(SERVER_PIDFILE, 'Server')
elif inp == 7: elif inp == 7:
kill(SERVER_PIDFILE, 'Server') kill(SERVER_PIDFILE, 'Server')
elif inp == 8: elif inp == 8:
kill(PORTAL_PIDFILE, 'Portal')
kill(SERVER_PIDFILE, 'Server')
elif inp == 9:
if not SERVER_LOGFILE: if not SERVER_LOGFILE:
init_game_directory(CURRENT_DIR, check_db=False) init_game_directory(CURRENT_DIR, check_db=False)
tail_server_log(SERVER_LOGFILE) tail_server_log(SERVER_LOGFILE)
print(" Tailing logfile {} ...".format(SERVER_LOGFILE)) print(" Tailing logfile {} ...".format(SERVER_LOGFILE))
elif inp == 9:
query_status()
elif inp == 10: elif inp == 10:
query_status()
elif inp == 11:
query_info() query_info()
else: else:
print("Not a valid option.") print("Not a valid option.")
@ -1686,37 +1743,36 @@ def main():
parser.add_argument( parser.add_argument(
'--gamedir', nargs=1, action='store', dest='altgamedir', '--gamedir', nargs=1, action='store', dest='altgamedir',
metavar="<path>", metavar="<path>",
help="Location of gamedir (default: current location)") help="location of gamedir (default: current location)")
parser.add_argument( parser.add_argument(
'--init', action='store', dest="init", metavar="<gamename>", '--init', action='store', dest="init", metavar="<gamename>",
help="Creates a new gamedir 'name' at current location.") help="creates a new gamedir 'name' at current location")
parser.add_argument( parser.add_argument(
'--log', '-l', action='store_true', dest='tail_log', default=False, '--log', '-l', action='store_true', dest='tail_log', default=False,
help="Tail the server logfile to standard out.") help="tail the server logfile to console")
parser.add_argument( parser.add_argument(
'--list', nargs='+', action='store', dest='listsetting', metavar="all|<key>", '--list', nargs='+', action='store', dest='listsetting', metavar="all|<key>",
help=("List values for one or more server settings. Use 'all' to \n list all " help=("list settings, use 'all' to list all available keys"))
"available keys."))
parser.add_argument( parser.add_argument(
'--settings', nargs=1, action='store', dest='altsettings', '--settings', nargs=1, action='store', dest='altsettings',
default=None, metavar="<path>", default=None, metavar="<path>",
help=("Start evennia with alternative settings file from\n" help=("start evennia with alternative settings file from\n"
" gamedir/server/conf/. (default is settings.py)")) " gamedir/server/conf/. (default is settings.py)"))
parser.add_argument( parser.add_argument(
'--initsettings', action='store_true', dest="initsettings", '--initsettings', action='store_true', dest="initsettings",
default=False, default=False,
help="Create a new, empty settings file as\n gamedir/server/conf/settings.py.") help="create a new, empty settings file as\n gamedir/server/conf/settings.py")
parser.add_argument( parser.add_argument(
'--profiler', action='store_true', dest='profiler', default=False, '--profiler', action='store_true', dest='profiler', default=False,
help="Start given server component under the Python profiler.") help="start given server component under the Python profiler")
parser.add_argument( parser.add_argument(
'--dummyrunner', nargs=1, action='store', dest='dummyrunner', '--dummyrunner', nargs=1, action='store', dest='dummyrunner',
metavar="<N>", metavar="<N>",
help="Test a server by connecting <N> dummy accounts to it.") help="test a server by connecting <N> dummy accounts to it")
parser.add_argument( parser.add_argument(
'-v', '--version', action='store_true', '-v', '--version', action='store_true',
dest='show_version', default=False, dest='show_version', default=False,
help="Show version info.") help="show version info")
parser.add_argument( parser.add_argument(
"operation", nargs='?', default="noop", "operation", nargs='?', default="noop",
@ -1800,7 +1856,8 @@ def main():
# launch menu for operation # launch menu for operation
init_game_directory(CURRENT_DIR, check_db=True) init_game_directory(CURRENT_DIR, check_db=True)
run_menu() run_menu()
elif option in ('status', 'info', 'start', 'reload', 'reset', 'stop', 'sstop', 'kill', 'skill'): elif option in ('status', 'info', 'start', 'reload', 'reboot',
'reset', 'stop', 'sstop', 'kill', 'skill'):
# operate the server directly # operate the server directly
if not SERVER_LOGFILE: if not SERVER_LOGFILE:
init_game_directory(CURRENT_DIR, check_db=True) init_game_directory(CURRENT_DIR, check_db=True)
@ -1812,6 +1869,8 @@ def main():
start_evennia(args.profiler, args.profiler) start_evennia(args.profiler, args.profiler)
elif option == 'reload': elif option == 'reload':
reload_evennia(args.profiler) reload_evennia(args.profiler)
elif option == 'reboot':
reboot_evennia(args.profiler, args.profiler)
elif option == 'reset': elif option == 'reset':
reload_evennia(args.profiler, reset=True) reload_evennia(args.profiler, reset=True)
elif option == 'stop': elif option == 'stop':

View file

@ -202,6 +202,7 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SRESET) self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SRESET)
elif mode == 'shutdown': elif mode == 'shutdown':
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SSHUTD) self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SSHUTD)
self.factory.portal.server_restart_mode = mode
# sending amp data # sending amp data
@ -233,8 +234,7 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
def send_AdminPortal2Server(self, session, operation="", **kwargs): def send_AdminPortal2Server(self, session, operation="", **kwargs):
""" """
Send Admin instructions from the Portal to the Server. Send Admin instructions from the Portal to the Server.
Executed Executed on the Portal.
on the Portal.
Args: Args:
session (Session): Session. session (Session): Session.
@ -403,9 +403,13 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
elif operation == amp.PSYNC: # portal sync elif operation == amp.PSYNC: # portal sync
# Server has (re-)connected and wants the session data from portal # Server has (re-)connected and wants the session data from portal
self.factory.server_info_dict = kwargs.get("info_dict", {}) self.factory.server_info_dict = kwargs.get("info_dict", {})
# this defaults to 'shutdown' or whatever value set in server_stop
server_restart_mode = self.factory.portal.server_restart_mode
sessdata = self.factory.portal.sessions.get_all_sync_data() sessdata = self.factory.portal.sessions.get_all_sync_data()
self.send_AdminPortal2Server(amp.DUMMYSESSION, self.send_AdminPortal2Server(amp.DUMMYSESSION,
amp.PSYNC, amp.PSYNC,
server_restart_mode=server_restart_mode,
sessiondata=sessdata) sessiondata=sessdata)
self.factory.portal.sessions.at_server_connection() self.factory.portal.sessions.at_server_connection()

View file

@ -85,8 +85,9 @@ INFO_DICT = {"servername": SERVERNAME, "version": VERSION, "errors": "", "info":
# ------------------------------------------------------------- # -------------------------------------------------------------
# Portal Service object # Portal Service object
# ------------------------------------------------------------- # -------------------------------------------------------------
class Portal(object): class Portal(object):
""" """
@ -113,13 +114,12 @@ class Portal(object):
self.sessions.portal = self self.sessions.portal = self
self.process_id = os.getpid() self.process_id = os.getpid()
self.server_process_id = None self.server_process_id = None
self.server_restart_mode = "shutdown"
# set a callback if the server is killed abruptly, # set a callback if the server is killed abruptly,
# by Ctrl-C, reboot etc. # by Ctrl-C, reboot etc.
reactor.addSystemEventTrigger('before', 'shutdown', self.shutdown, _reactor_stopping=True) reactor.addSystemEventTrigger('before', 'shutdown', self.shutdown, _reactor_stopping=True)
self.game_running = False
def get_info_dict(self): def get_info_dict(self):
"Return the Portal info, for display." "Return the Portal info, for display."
return INFO_DICT return INFO_DICT

View file

@ -203,11 +203,6 @@ class Evennia(object):
reactor.callLater(1, d.callback, None) reactor.callLater(1, d.callback, None)
reactor.sigInt = _wrap_sigint_handler reactor.sigInt = _wrap_sigint_handler
self.game_running = True
# track the server time
self.run_init_hooks()
# Server startup methods # Server startup methods
def sqlite3_prep(self): def sqlite3_prep(self):
@ -299,9 +294,13 @@ class Evennia(object):
last=last_initial_setup_step) last=last_initial_setup_step)
initial_setup.handle_setup(int(last_initial_setup_step)) initial_setup.handle_setup(int(last_initial_setup_step))
def run_init_hooks(self): def run_init_hooks(self, mode):
""" """
Called every server start Called by the amp client once receiving sync back from Portal
Args:
mode (str): One of shutdown, reload or reset
""" """
from evennia.objects.models import ObjectDB from evennia.objects.models import ObjectDB
@ -311,47 +310,24 @@ class Evennia(object):
[o.at_init() for o in ObjectDB.get_all_cached_instances()] [o.at_init() for o in ObjectDB.get_all_cached_instances()]
[p.at_init() for p in AccountDB.get_all_cached_instances()] [p.at_init() for p in AccountDB.get_all_cached_instances()]
mode = self.getset_restart_mode()
# call correct server hook based on start file value # call correct server hook based on start file value
if mode == 'reload': if mode == 'reload':
# True was the old reload flag, kept for compatibilty logger.log_msg("Server successfully reloaded.")
self.at_server_reload_start() self.at_server_reload_start()
elif mode == 'reset': elif mode == 'reset':
# only run hook, don't purge sessions # only run hook, don't purge sessions
self.at_server_cold_start() self.at_server_cold_start()
elif mode in ('reset', 'shutdown'): logger.log_msg("Evennia Server successfully restarted in 'reset' mode.")
elif mode == 'shutdown':
self.at_server_cold_start() self.at_server_cold_start()
# clear eventual lingering session storages # clear eventual lingering session storages
ObjectDB.objects.clear_all_sessids() ObjectDB.objects.clear_all_sessids()
logger.log_msg("Evennia Server successfully started.")
# always call this regardless of start type # always call this regardless of start type
self.at_server_start() self.at_server_start()
def getset_restart_mode(self, mode=None):
"""
This manages the flag file that tells the runner if the server is
reloading, resetting or shutting down.
Args:
mode (string or None, optional): Valid values are
'reload', 'reset', 'shutdown' and `None`. If mode is `None`,
no change will be done to the flag file.
Returns:
mode (str): The currently active restart mode, either just
set or previously set.
"""
if mode is None:
with open(SERVER_RESTART, 'r') as f:
# mode is either shutdown, reset or reload
mode = f.read()
else:
with open(SERVER_RESTART, 'w') as f:
f.write(str(mode))
return mode
@defer.inlineCallbacks @defer.inlineCallbacks
def shutdown(self, mode=None, _reactor_stopping=False): def shutdown(self, mode='reload', _reactor_stopping=False):
""" """
Shuts down the server from inside it. Shuts down the server from inside it.
@ -362,7 +338,6 @@ class Evennia(object):
at_shutdown hooks called but sessions will not at_shutdown hooks called but sessions will not
be disconnected. be disconnected.
'shutdown' - like reset, but server will not auto-restart. 'shutdown' - like reset, but server will not auto-restart.
None - keep currently set flag from flag file.
_reactor_stopping - this is set if server is stopped by a kill _reactor_stopping - this is set if server is stopped by a kill
command OR this method was already called command OR this method was already called
once - in both cases the reactor is once - in both cases the reactor is
@ -373,10 +348,7 @@ class Evennia(object):
# once; we don't need to run the shutdown procedure again. # once; we don't need to run the shutdown procedure again.
defer.returnValue(None) defer.returnValue(None)
mode = self.getset_restart_mode(mode)
from evennia.objects.models import ObjectDB from evennia.objects.models import ObjectDB
#from evennia.accounts.models import AccountDB
from evennia.server.models import ServerConfig from evennia.server.models import ServerConfig
from evennia.utils import gametime as _GAMETIME_MODULE from evennia.utils import gametime as _GAMETIME_MODULE
@ -455,13 +427,15 @@ class Evennia(object):
if SERVER_STARTSTOP_MODULE: if SERVER_STARTSTOP_MODULE:
SERVER_STARTSTOP_MODULE.at_server_reload_start() SERVER_STARTSTOP_MODULE.at_server_reload_start()
def at_post_portal_sync(self): def at_post_portal_sync(self, mode):
""" """
This is called just after the portal has finished syncing back data to the server This is called just after the portal has finished syncing back data to the server
after reconnecting. after reconnecting.
Args:
mode (str): One of reload, reset or shutdown.
""" """
# one of reload, reset or shutdown
mode = self.getset_restart_mode()
from evennia.scripts.monitorhandler import MONITOR_HANDLER from evennia.scripts.monitorhandler import MONITOR_HANDLER
MONITOR_HANDLER.restore(mode == 'reload') MONITOR_HANDLER.restore(mode == 'reload')

View file

@ -379,8 +379,10 @@ class ServerSessionHandler(SessionHandler):
self[sessid] = sess self[sessid] = sess
sess.at_sync() sess.at_sync()
mode = 'reload'
# tell the server hook we synced # tell the server hook we synced
self.server.at_post_portal_sync() self.server.at_post_portal_sync(mode)
# announce the reconnection # announce the reconnection
self.announce_all(_(" ... Server restarted.")) self.announce_all(_(" ... Server restarted."))

View file

@ -197,7 +197,7 @@ def log_server(servermsg):
except Exception as e: except Exception as e:
servermsg = str(e) servermsg = str(e)
for line in servermsg.splitlines(): for line in servermsg.splitlines():
log_msg('[SRV] %s' % line) log_msg('[Server] %s' % line)
def log_warn(warnmsg): def log_warn(warnmsg):