Working start/reload/reset/stop from launcher
This commit is contained in:
parent
ef999362c7
commit
5133034b4b
7 changed files with 136 additions and 56 deletions
|
|
@ -192,15 +192,21 @@ class AMPServerClientProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
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
|
||||||
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
|
||||||
# shut down in reload mode
|
# shut down in reload mode
|
||||||
|
server_sessionhandler.all_sessions_portal_sync()
|
||||||
server_sessionhandler.server.shutdown(mode='reload')
|
server_sessionhandler.server.shutdown(mode='reload')
|
||||||
|
|
||||||
elif operation == amp.SRESET:
|
elif operation == amp.SRESET:
|
||||||
# shut down in reset mode
|
# shut down in reset mode
|
||||||
|
server_sessionhandler.all_sessions_portal_sync()
|
||||||
server_sessionhandler.server.shutdown(mode='reset')
|
server_sessionhandler.server.shutdown(mode='reset')
|
||||||
|
|
||||||
elif operation == amp.SSHUTD: # server shutdown
|
elif operation == amp.SSHUTD: # server shutdown
|
||||||
# shutdown in stop mode
|
# shutdown in stop mode
|
||||||
server_sessionhandler.server.shutdown(mode='shutdown')
|
server_sessionhandler.server.shutdown(mode='shutdown')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("operation %(op)s not recognized." % {'op': operation})
|
raise Exception("operation %(op)s not recognized." % {'op': operation})
|
||||||
return {}
|
return {}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import shutil
|
||||||
import importlib
|
import importlib
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from subprocess import Popen, check_output, call, CalledProcessError, STDOUT
|
from subprocess import Popen, check_output, call, CalledProcessError, STDOUT, PIPE
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
|
|
@ -88,6 +88,7 @@ SSTART = chr(15) # server start
|
||||||
PSHUTD = chr(16) # portal (+server) shutdown
|
PSHUTD = chr(16) # portal (+server) shutdown
|
||||||
SSHUTD = chr(17) # server-only shutdown
|
SSHUTD = chr(17) # server-only shutdown
|
||||||
PSTATUS = chr(18) # ping server or portal status
|
PSTATUS = chr(18) # ping server or portal status
|
||||||
|
SRESET = chr(19) # shutdown server in reset mode
|
||||||
|
|
||||||
# requirements
|
# requirements
|
||||||
PYTHON_MIN = '2.7'
|
PYTHON_MIN = '2.7'
|
||||||
|
|
@ -519,13 +520,18 @@ def _get_twistd_cmdline(pprofiler, sprofiler):
|
||||||
Compile the command line for starting a Twisted application using the 'twistd' executable.
|
Compile the command line for starting a Twisted application using the 'twistd' executable.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
portal_cmd = [TWISTED_BINARY,
|
portal_cmd = [TWISTED_BINARY,
|
||||||
"--logfile={}".format(PORTAL_LOGFILE),
|
"--logfile={}".format(PORTAL_LOGFILE),
|
||||||
"--python={}".format(PORTAL_PY_FILE)]
|
"--python={}".format(PORTAL_PY_FILE)]
|
||||||
server_cmd = [TWISTED_BINARY,
|
server_cmd = [TWISTED_BINARY,
|
||||||
"--logfile={}".format(PORTAL_LOGFILE),
|
"--logfile={}".format(SERVER_LOGFILE),
|
||||||
"--python={}".format(PORTAL_PY_FILE)]
|
"--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:
|
if pprofiler:
|
||||||
portal_cmd.extend(["--savestats",
|
portal_cmd.extend(["--savestats",
|
||||||
"--profiler=cprofiler",
|
"--profiler=cprofiler",
|
||||||
|
|
@ -534,6 +540,8 @@ def _get_twistd_cmdline(pprofiler, sprofiler):
|
||||||
server_cmd.extend(["--savestats",
|
server_cmd.extend(["--savestats",
|
||||||
"--profiler=cprofiler",
|
"--profiler=cprofiler",
|
||||||
"--profile={}".format(SPROFILER_LOGFILE)])
|
"--profile={}".format(SPROFILER_LOGFILE)])
|
||||||
|
|
||||||
|
|
||||||
return portal_cmd, server_cmd
|
return portal_cmd, server_cmd
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -552,7 +560,6 @@ def query_status(repeat=False):
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
def _errback(fail):
|
def _errback(fail):
|
||||||
print("status fail: %s", fail)
|
|
||||||
pstatus, sstatus = False, False
|
pstatus, sstatus = False, False
|
||||||
print("Portal: {}\nServer: {}".format(wmap[pstatus], wmap[sstatus]))
|
print("Portal: {}\nServer: {}".format(wmap[pstatus], wmap[sstatus]))
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
@ -591,7 +598,7 @@ def wait_for_status(portal_running=True, server_running=True, callback=None, err
|
||||||
if errback:
|
if errback:
|
||||||
errback(prun, srun)
|
errback(prun, srun)
|
||||||
else:
|
else:
|
||||||
print("Timeout.")
|
print("Connection to Evennia timed out. Try again.")
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
else:
|
else:
|
||||||
reactor.callLater(rate, wait_for_status,
|
reactor.callLater(rate, wait_for_status,
|
||||||
|
|
@ -613,7 +620,7 @@ def wait_for_status(portal_running=True, server_running=True, callback=None, err
|
||||||
if errback:
|
if errback:
|
||||||
errback(portal_running, server_running)
|
errback(portal_running, server_running)
|
||||||
else:
|
else:
|
||||||
print("Timeout.")
|
print("Connection to Evennia timed out. Try again.")
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
else:
|
else:
|
||||||
reactor.callLater(rate, wait_for_status,
|
reactor.callLater(rate, wait_for_status,
|
||||||
|
|
@ -622,14 +629,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
|
||||||
|
|
@ -638,8 +644,12 @@ def start_evennia(pprofiler=False, sprofiler=False):
|
||||||
"""
|
"""
|
||||||
portal_cmd, server_cmd = _get_twistd_cmdline(pprofiler, sprofiler)
|
portal_cmd, server_cmd = _get_twistd_cmdline(pprofiler, sprofiler)
|
||||||
|
|
||||||
|
def _fail(fail):
|
||||||
|
print(fail)
|
||||||
|
reactor.stop()
|
||||||
|
|
||||||
def _server_started(*args):
|
def _server_started(*args):
|
||||||
print("... Server started.\nEvennia running.", args)
|
print("... Server started.\nEvennia running.")
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
def _portal_started(*args):
|
def _portal_started(*args):
|
||||||
|
|
@ -653,21 +663,22 @@ def start_evennia(pprofiler=False, sprofiler=False):
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
else:
|
else:
|
||||||
print("Server starting {}...".format("(under cProfile)" if pprofiler else ""))
|
print("Server starting {}...".format("(under cProfile)" if pprofiler else ""))
|
||||||
send_instruction(SSTART, server_cmd, _server_started)
|
send_instruction(SSTART, server_cmd, _server_started, _fail)
|
||||||
|
|
||||||
def _portal_not_running(fail):
|
def _portal_not_running(fail):
|
||||||
print("Portal starting {}...".format("(under cProfile)" if sprofiler else ""))
|
print("Portal starting {}...".format("(under cProfile)" if sprofiler else ""))
|
||||||
try:
|
try:
|
||||||
Popen(portal_cmd, env=getenv())
|
Popen(portal_cmd, env=getenv(), bufsize=-1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(PROCESS_ERROR.format(component="Portal", traceback=e))
|
print(PROCESS_ERROR.format(component="Portal", traceback=e))
|
||||||
|
reactor.stop()
|
||||||
wait_for_status(True, None, _portal_started)
|
wait_for_status(True, None, _portal_started)
|
||||||
|
|
||||||
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
||||||
|
|
||||||
def reload_evennia(sprofiler=False):
|
def reload_evennia(sprofiler=False, reset=False):
|
||||||
"""
|
"""
|
||||||
This will instruct the Portal to reboot the Server component.
|
This will instruct the Portal to reboot the Server component.
|
||||||
|
|
||||||
|
|
@ -675,18 +686,23 @@ def reload_evennia(sprofiler=False):
|
||||||
_, server_cmd = _get_twistd_cmdline(False, sprofiler)
|
_, server_cmd = _get_twistd_cmdline(False, sprofiler)
|
||||||
|
|
||||||
def _server_restarted(*args):
|
def _server_restarted(*args):
|
||||||
print("... Server re-started.", args)
|
print("... Server re-started.")
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
def _server_reloaded(*args):
|
def _server_reloaded(*args):
|
||||||
print("... Server reloaded.", args)
|
print("... Server {}.".format("reset" if reset else "reloaded"))
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
|
def _server_not_running(*args):
|
||||||
|
send_instruction(SSTART, server_cmd)
|
||||||
|
wait_for_status(True, True, _server_reloaded)
|
||||||
|
|
||||||
def _portal_running(response):
|
def _portal_running(response):
|
||||||
_, srun, _, _ = _parse_status(response)
|
_, srun, _, _ = _parse_status(response)
|
||||||
if srun:
|
if srun:
|
||||||
print("Server reloading ...")
|
print("Server {}...".format("resetting" if reset else "reloading"))
|
||||||
send_instruction(SRELOAD, server_cmd, _server_reloaded)
|
send_instruction(SRESET if reset else SRELOAD, server_cmd)
|
||||||
|
wait_for_status(True, False, _server_not_running)
|
||||||
else:
|
else:
|
||||||
print("Server down. Re-starting ...")
|
print("Server down. Re-starting ...")
|
||||||
send_instruction(SSTART, server_cmd, _server_restarted)
|
send_instruction(SSTART, server_cmd, _server_restarted)
|
||||||
|
|
@ -710,7 +726,7 @@ def stop_evennia():
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
def _server_stopped(*args):
|
def _server_stopped(*args):
|
||||||
print("... Server stopped.\nStopping Portal ...", args)
|
print("... Server stopped.\nStopping Portal ...")
|
||||||
send_instruction(PSHUTD, {})
|
send_instruction(PSHUTD, {})
|
||||||
wait_for_status(False, None, _portal_stopped)
|
wait_for_status(False, None, _portal_stopped)
|
||||||
|
|
||||||
|
|
@ -718,7 +734,8 @@ def stop_evennia():
|
||||||
prun, srun, ppid, spid = _parse_status(response)
|
prun, srun, ppid, spid = _parse_status(response)
|
||||||
if srun:
|
if srun:
|
||||||
print("Server stopping ...")
|
print("Server stopping ...")
|
||||||
send_instruction(SSHUTD, {}, _server_stopped)
|
send_instruction(SSHUTD, {})
|
||||||
|
wait_for_status(True, False, _server_stopped)
|
||||||
else:
|
else:
|
||||||
print("Server already stopped.\nStopping Portal ...")
|
print("Server already stopped.\nStopping Portal ...")
|
||||||
send_instruction(PSHUTD, {})
|
send_instruction(PSHUTD, {})
|
||||||
|
|
@ -726,6 +743,7 @@ def stop_evennia():
|
||||||
|
|
||||||
def _portal_not_running(fail):
|
def _portal_not_running(fail):
|
||||||
print("Evennia is not running.")
|
print("Evennia is not running.")
|
||||||
|
reactor.stop()
|
||||||
|
|
||||||
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
@ -741,8 +759,8 @@ def stop_server_only():
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
def _portal_running(response):
|
def _portal_running(response):
|
||||||
_, server_running = [stat == 'RUNNING' for stat in response['status'].split("|")]
|
_, srun, _, _ = _parse_status(response)
|
||||||
if server_running:
|
if srun:
|
||||||
print("Server stopping ...")
|
print("Server stopping ...")
|
||||||
send_instruction(SSHUTD, {})
|
send_instruction(SSHUTD, {})
|
||||||
wait_for_status(True, False, _server_stopped)
|
wait_for_status(True, False, _server_stopped)
|
||||||
|
|
@ -1239,7 +1257,7 @@ def init_game_directory(path, check_db=True):
|
||||||
AMP_INTERFACE = settings.AMP_INTERFACE
|
AMP_INTERFACE = settings.AMP_INTERFACE
|
||||||
|
|
||||||
SERVER_PY_FILE = os.path.join(EVENNIA_LIB, "server", "server.py")
|
SERVER_PY_FILE = os.path.join(EVENNIA_LIB, "server", "server.py")
|
||||||
PORTAL_PY_FILE = os.path.join(EVENNIA_LIB, "portal", "portal", "portal.py")
|
PORTAL_PY_FILE = os.path.join(EVENNIA_LIB, "server", "portal", "portal.py")
|
||||||
|
|
||||||
SERVER_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "server.pid")
|
SERVER_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "server.pid")
|
||||||
PORTAL_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "portal.pid")
|
PORTAL_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "portal.pid")
|
||||||
|
|
@ -1602,9 +1620,6 @@ def main():
|
||||||
"service", metavar="component", nargs='?', default="all",
|
"service", metavar="component", nargs='?', default="all",
|
||||||
help=("Which component to operate on: "
|
help=("Which component to operate on: "
|
||||||
"'server', 'portal' or 'all' (default if not set)."))
|
"'server', 'portal' or 'all' (default if not set)."))
|
||||||
parser.add_argument(
|
|
||||||
"--status", action='store_true', dest='get_status',
|
|
||||||
default=None, help='Get current server status.')
|
|
||||||
parser.epilog = (
|
parser.epilog = (
|
||||||
"Common usage: evennia start|stop|reload. Django-admin database commands:"
|
"Common usage: evennia start|stop|reload. Django-admin database commands:"
|
||||||
"evennia migration|flush|shell|dbshell (see the django documentation for more "
|
"evennia migration|flush|shell|dbshell (see the django documentation for more "
|
||||||
|
|
@ -1656,11 +1671,6 @@ def main():
|
||||||
print(ERROR_INITSETTINGS)
|
print(ERROR_INITSETTINGS)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
if args.get_status:
|
|
||||||
init_game_directory(CURRENT_DIR, check_db=True)
|
|
||||||
query_status()
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
if args.dummyrunner:
|
if args.dummyrunner:
|
||||||
# launch the dummy runner
|
# launch the dummy runner
|
||||||
init_game_directory(CURRENT_DIR, check_db=True)
|
init_game_directory(CURRENT_DIR, check_db=True)
|
||||||
|
|
@ -1673,13 +1683,17 @@ 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 ('sstart', 'sreload', 'sstop', 'ssstop', 'start', 'reload', 'stop'):
|
elif option in ('status', 'sstart', 'sreload', 'sreset', 'sstop', 'ssstop', 'start', 'reload', 'stop'):
|
||||||
# operate the server directly
|
# operate the server directly
|
||||||
init_game_directory(CURRENT_DIR, check_db=True)
|
init_game_directory(CURRENT_DIR, check_db=True)
|
||||||
|
if option == "status":
|
||||||
|
query_status()
|
||||||
if option == "sstart":
|
if option == "sstart":
|
||||||
start_evennia(False, args.profiler)
|
start_evennia(False, args.profiler)
|
||||||
elif option == 'sreload':
|
elif option == 'sreload':
|
||||||
reload_evennia(args.profiler)
|
reload_evennia(args.profiler)
|
||||||
|
elif option == 'sreset':
|
||||||
|
reload_evennia(args.profiler, reset=True)
|
||||||
elif option == 'sstop':
|
elif option == 'sstop':
|
||||||
stop_evennia()
|
stop_evennia()
|
||||||
elif option == 'ssstop':
|
elif option == 'ssstop':
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,7 @@ def main():
|
||||||
del portal_argv[-2]
|
del portal_argv[-2]
|
||||||
|
|
||||||
# Start processes
|
# Start processes
|
||||||
|
print("server_argv:", server_argv, portal_argv)
|
||||||
start_services(server_argv, portal_argv, doexit=args.doexit)
|
start_services(server_argv, portal_argv, doexit=args.doexit)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ def catch_traceback(func):
|
||||||
if not _LOGGER:
|
if not _LOGGER:
|
||||||
from evennia.utils import logger as _LOGGER
|
from evennia.utils import logger as _LOGGER
|
||||||
_LOGGER.log_trace()
|
_LOGGER.log_trace()
|
||||||
print("error", err)
|
|
||||||
raise # make sure the error is visible on the other side of the connection too
|
raise # make sure the error is visible on the other side of the connection too
|
||||||
|
print(err)
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
from twisted.internet import protocol
|
from twisted.internet import protocol
|
||||||
from evennia.server.portal import amp
|
from evennia.server.portal import amp
|
||||||
from subprocess import Popen
|
from subprocess import Popen, STDOUT, PIPE
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -48,6 +48,8 @@ class AMPServerFactory(protocol.ServerFactory):
|
||||||
self.portal = portal
|
self.portal = portal
|
||||||
self.protocol = AMPServerProtocol
|
self.protocol = AMPServerProtocol
|
||||||
self.broadcasts = []
|
self.broadcasts = []
|
||||||
|
self.server_connection = None
|
||||||
|
self.disconnect_callbacks = {}
|
||||||
|
|
||||||
def buildProtocol(self, addr):
|
def buildProtocol(self, addr):
|
||||||
"""
|
"""
|
||||||
|
|
@ -80,12 +82,45 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# start the Server
|
# start the Server
|
||||||
process = Popen(server_twistd_cmd, env=getenv())
|
try:
|
||||||
# store the pid for future reference
|
process = Popen(server_twistd_cmd, env=getenv(), bufsize=-1, stdout=PIPE, stderr=STDOUT)
|
||||||
|
except Exception:
|
||||||
|
self.factory.portal.server_process_id = None
|
||||||
|
logger.log_trace()
|
||||||
|
return 0
|
||||||
|
# there is a short window before the server logger is up where we must
|
||||||
|
# catch the stdout of the Server or eventual tracebacks will be lost.
|
||||||
|
with process.stdout as out:
|
||||||
|
logger.log_server(out.read())
|
||||||
|
|
||||||
|
# store the pid and launch argument for future reference
|
||||||
self.factory.portal.server_process_id = process.pid
|
self.factory.portal.server_process_id = process.pid
|
||||||
self.factory.portal.server_twistd_cmd = server_twistd_cmd
|
self.factory.portal.server_twistd_cmd = server_twistd_cmd
|
||||||
return process.pid
|
return process.pid
|
||||||
|
|
||||||
|
def connectionLost(self, reason):
|
||||||
|
"""
|
||||||
|
Set up a simple callback mechanism to let the amp-server wait for a connection to close.
|
||||||
|
|
||||||
|
"""
|
||||||
|
callback, args, kwargs = self.factory.disconnect_callbacks.pop(self, (None, None, None))
|
||||||
|
if callback:
|
||||||
|
try:
|
||||||
|
callback(*args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
logger.log_trace()
|
||||||
|
|
||||||
|
def wait_for_disconnect(self, callback, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Add a callback for when this connection is lost.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callback (callable): Will be called with *args, **kwargs
|
||||||
|
once this protocol is disconnected.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.factory.disconnect_callbacks[self] = (callback, args, kwargs)
|
||||||
|
|
||||||
def stop_server(self, mode='shutdown'):
|
def stop_server(self, mode='shutdown'):
|
||||||
"""
|
"""
|
||||||
Shut down server in one or more modes.
|
Shut down server in one or more modes.
|
||||||
|
|
@ -95,11 +130,11 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if mode == 'reload':
|
if mode == 'reload':
|
||||||
self.send_AdminPortal2Server(amp.DUMMYSESSION, amp.SRELOAD)
|
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SRELOAD)
|
||||||
if mode == 'reset':
|
elif mode == 'reset':
|
||||||
self.send_AdminPortal2Server(amp.DUMMYSESSION, amp.SRESET)
|
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SRESET)
|
||||||
if mode == 'shutdown':
|
elif mode == 'shutdown':
|
||||||
self.send_AdminPortal2Server(amp.DUMMYSESSION, amp.SSHUTD)
|
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SSHUTD)
|
||||||
|
|
||||||
# sending amp data
|
# sending amp data
|
||||||
|
|
||||||
|
|
@ -148,8 +183,8 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# check if the server is connected
|
# check if the server is connected
|
||||||
server_connected = any(1 for prtcl in self.factory.broadcasts
|
server_connected = (self.factory.server_connection and
|
||||||
if prtcl is not self and prtcl.transport.connected)
|
self.factory.server_connection.transport.connected)
|
||||||
server_pid = self.factory.portal.server_process_id
|
server_pid = self.factory.portal.server_process_id
|
||||||
portal_pid = os.getpid()
|
portal_pid = os.getpid()
|
||||||
|
|
||||||
|
|
@ -180,14 +215,14 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
def _retval(success, txt):
|
def _retval(success, txt):
|
||||||
return {"result": amp.dumps((success, txt))}
|
return {"result": amp.dumps((success, txt))}
|
||||||
|
|
||||||
server_connected = any(1 for prtcl in self.factory.broadcasts
|
server_connected = (self.factory.server_connection and
|
||||||
if prtcl is not self and prtcl.transport.connected)
|
self.factory.server_connection.transport.connected)
|
||||||
server_pid = self.factory.portal.server_process_id
|
server_pid = self.factory.portal.server_process_id
|
||||||
|
|
||||||
logger.log_msg("AMP SERVER operation == %s received" % (ord(operation)))
|
logger.log_msg("AMP SERVER operation == %s received" % (ord(operation)))
|
||||||
logger.log_msg("AMP SERVER arguments: %s" % (amp.loads(arguments)))
|
logger.log_msg("AMP SERVER arguments: %s" % (amp.loads(arguments)))
|
||||||
|
|
||||||
if operation == amp.SSTART: # portal start
|
if operation == amp.SSTART: # portal start #15
|
||||||
# first, check if server is already running
|
# first, check if server is already running
|
||||||
if server_connected:
|
if server_connected:
|
||||||
return _retval(False,
|
return _retval(False,
|
||||||
|
|
@ -195,27 +230,36 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
else:
|
else:
|
||||||
spid = self.start_server(amp.loads(arguments))
|
spid = self.start_server(amp.loads(arguments))
|
||||||
return _retval(True, "Server started with PID {spid}.".format(spid=spid))
|
return _retval(True, "Server started with PID {spid}.".format(spid=spid))
|
||||||
elif operation == amp.SRELOAD: # reload server
|
|
||||||
|
elif operation == amp.SRELOAD: # reload server #14
|
||||||
if server_connected:
|
if server_connected:
|
||||||
self.stop(mode='reload')
|
# don't restart until the server connection goes down
|
||||||
spid = self.start_server(amp.loads(arguments))
|
self.stop_server(mode='reload')
|
||||||
return _retval(True, "Server restarted with PID {spid}.".format(spid=spid))
|
|
||||||
else:
|
else:
|
||||||
spid = self.start_server(amp.loads(arguments))
|
spid = self.start_server(amp.loads(arguments))
|
||||||
return _retval(True, "Server started with PID {spid}.".format(spid=spid))
|
return _retval(True, "Server started with PID {spid}.".format(spid=spid))
|
||||||
elif operation == amp.SRESET: # reload server
|
|
||||||
|
elif operation == amp.SRESET: # reload server #19
|
||||||
if server_connected:
|
if server_connected:
|
||||||
self.stop_server(mode='reset')
|
self.stop_server(mode='reset')
|
||||||
spid = self.start_server(amp.loads(arguments))
|
|
||||||
return _retval(True, "Server restarted with PID {spid}.".format(spid=spid))
|
return _retval(True, "Server restarted with PID {spid}.".format(spid=spid))
|
||||||
else:
|
else:
|
||||||
spid = self.start_server(amp.loads(arguments))
|
spid = self.start_server(amp.loads(arguments))
|
||||||
return _retval(True, "Server started with PID {spid}.".format(spid=spid))
|
return _retval(True, "Server started with PID {spid}.".format(spid=spid))
|
||||||
elif operation == amp.PSHUTD: # portal + server shutdown
|
|
||||||
|
elif operation == amp.SSHUTD: # server-only shutdown #17
|
||||||
|
if server_connected:
|
||||||
|
self.stop_server(mode='shutdown')
|
||||||
|
return _retval(True, "Server stopped.")
|
||||||
|
else:
|
||||||
|
return _retval(False, "Server not running")
|
||||||
|
|
||||||
|
elif operation == amp.PSHUTD: # portal + server shutdown #16
|
||||||
if server_connected:
|
if server_connected:
|
||||||
self.stop_server(mode='shutdown')
|
self.stop_server(mode='shutdown')
|
||||||
return _retval(True, "Server stopped.")
|
return _retval(True, "Server stopped.")
|
||||||
self.factory.portal.shutdown(restart=False)
|
self.factory.portal.shutdown(restart=False)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("operation %(op)s not recognized." % {'op': operation})
|
raise Exception("operation %(op)s not recognized." % {'op': operation})
|
||||||
# fallback
|
# fallback
|
||||||
|
|
@ -254,6 +298,9 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
operation = kwargs.pop("operation")
|
operation = kwargs.pop("operation")
|
||||||
portal_sessionhandler = self.factory.portal.sessions
|
portal_sessionhandler = self.factory.portal.sessions
|
||||||
|
|
||||||
|
# store this transport since we know it comes from the Server
|
||||||
|
self.factory.server_connection = self
|
||||||
|
|
||||||
if operation == amp.SLOGIN: # server_session_login
|
if operation == amp.SLOGIN: # server_session_login
|
||||||
# a session has authenticated; sync it.
|
# a session has authenticated; sync it.
|
||||||
session = portal_sessionhandler.get(sessid)
|
session = portal_sessionhandler.get(sessid)
|
||||||
|
|
@ -271,12 +318,14 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
portal_sessionhandler.server_disconnect_all(reason=kwargs.get("reason"))
|
portal_sessionhandler.server_disconnect_all(reason=kwargs.get("reason"))
|
||||||
|
|
||||||
elif operation == amp.SRELOAD: # server reload
|
elif operation == amp.SRELOAD: # server reload
|
||||||
|
self.factory.server_connection.wait_for_disconnect(
|
||||||
|
self.start_server, self.factory.portal.server_twisted_cmd)
|
||||||
self.stop_server(mode='reload')
|
self.stop_server(mode='reload')
|
||||||
self.start(self.factory.portal.server_twisted_cmd)
|
|
||||||
|
|
||||||
elif operation == amp.SRESET: # server reset
|
elif operation == amp.SRESET: # server reset
|
||||||
|
self.factory.server_connection.wait_for_disconnect(
|
||||||
|
self.start_server, self.factory.portal.server_twisted_cmd)
|
||||||
self.stop_server(mode='reset')
|
self.stop_server(mode='reset')
|
||||||
self.start(self.factory.portal.server_twisted_cmd)
|
|
||||||
|
|
||||||
elif operation == amp.SSHUTD: # server-only shutdown
|
elif operation == amp.SSHUTD: # server-only shutdown
|
||||||
self.stop_server(mode='shutdown')
|
self.stop_server(mode='shutdown')
|
||||||
|
|
|
||||||
|
|
@ -366,6 +366,7 @@ class Evennia(object):
|
||||||
once - in both cases the reactor is
|
once - in both cases the reactor is
|
||||||
dead/stopping already.
|
dead/stopping already.
|
||||||
"""
|
"""
|
||||||
|
print("server.shutdown mode=", mode)
|
||||||
if _reactor_stopping and hasattr(self, "shutdown_complete"):
|
if _reactor_stopping and hasattr(self, "shutdown_complete"):
|
||||||
# this means we have already passed through this method
|
# this means we have already passed through this method
|
||||||
# once; we don't need to run the shutdown procedure again.
|
# once; we don't need to run the shutdown procedure again.
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,15 @@ def log_err(errmsg):
|
||||||
log_errmsg = log_err
|
log_errmsg = log_err
|
||||||
|
|
||||||
|
|
||||||
|
def log_server(servermsg):
|
||||||
|
try:
|
||||||
|
servermsg = str(servermsg)
|
||||||
|
except Exception as e:
|
||||||
|
servermsg = str(e)
|
||||||
|
for line in servermsg.splitlines():
|
||||||
|
log_msg('[SRV] %s' % line)
|
||||||
|
|
||||||
|
|
||||||
def log_warn(warnmsg):
|
def log_warn(warnmsg):
|
||||||
"""
|
"""
|
||||||
Prints/logs any warnings that aren't critical but should be noted.
|
Prints/logs any warnings that aren't critical but should be noted.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue