Add external-runner option to the launcher to allow for replacing the native evennia runner with an external process manager (like Linux' start-stop-daemon). Note that without a replacement, this option will make evennia un-reloadable.

This commit is contained in:
Griatch 2016-12-08 23:24:14 +01:00
parent ad13594a46
commit 293c3b077d
2 changed files with 29 additions and 7 deletions

View file

@ -1084,7 +1084,7 @@ def run_menu():
return
def server_operation(mode, service, interactive, profiler, logserver=False):
def server_operation(mode, service, interactive, profiler, logserver=False, doexit=False):
"""
Handle argument options given on the command line.
@ -1095,6 +1095,10 @@ def server_operation(mode, service, interactive, profiler, logserver=False):
profiler (bool): Run the service under the profiler.
logserver (bool, optional): Log Server data to logfile
specified by settings.SERVER_LOG_FILE.
doexit (bool, optional): If True, immediately exit the runner after
starting the relevant processes. If the runner exits, Evennia
cannot be reloaded. This is meant to be used with an external
process manager like Linux' start-stop-daemon.
"""
@ -1136,6 +1140,8 @@ def server_operation(mode, service, interactive, profiler, logserver=False):
cmdstr.append('--logserver')
django.core.management.call_command(
'collectstatic', verbosity=1, interactive=False)
if doexit:
cmdstr.append('--doexit')
cmdstr.extend([
GAMEDIR, TWISTED_BINARY, SERVER_LOGFILE,
PORTAL_LOGFILE, HTTP_LOGFILE])
@ -1242,6 +1248,10 @@ def main():
'--initsettings', action='store_true', dest="initsettings",
default=False,
help="Create a new, empty settings file as gamedir/server/conf/settings.py.")
parser.add_argument(
'--external-runner', action='store_true', dest="doexit",
default=False,
help="Handle server restart with an external process manager.")
parser.add_argument(
"operation", nargs='?', default="noop",
help="Operation to perform: 'start', 'stop', 'reload' or 'menu'.")
@ -1315,7 +1325,7 @@ def main():
elif option in ('start', 'reload', 'stop'):
# operate the server directly
init_game_directory(CURRENT_DIR, check_db=True)
server_operation(option, service, args.interactive, args.profiler, args.logserver)
server_operation(option, service, args.interactive, args.profiler, args.logserver, doexit=args.doexit)
elif option != "noop":
# pass-through to django manager
check_db = False

View file

@ -75,6 +75,7 @@ PROCESS_IOERROR = \
PROCESS_RESTART = "{component} restarting ..."
PROCESS_DOEXIT = "Deferring to external runner."
# Functions
@ -134,7 +135,7 @@ def cycle_logfile(logfile):
# Start program management
def start_services(server_argv, portal_argv):
def start_services(server_argv, portal_argv, doexit=False):
"""
This calls a threaded loop that launces the Portal and Server
and then restarts them when they finish.
@ -162,7 +163,7 @@ def start_services(server_argv, portal_argv):
if portal_argv:
try:
if get_restart_mode(PORTAL_RESTART) == "True":
if not doexit and get_restart_mode(PORTAL_RESTART) == "True":
# start portal as interactive, reloadable thread
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
else:
@ -175,12 +176,19 @@ def start_services(server_argv, portal_argv):
try:
if server_argv:
# start server as a reloadable thread
SERVER = thread.start_new_thread(server_waiter, (processes, ))
if doexit:
SERVER = Popen(server_argv, env=getenv())
else:
# start server as a reloadable thread
SERVER = thread.start_new_thread(server_waiter, (processes, ))
except IOError as e:
print(PROCESS_IOERROR.format(component="Server", traceback=e))
return
if doexit:
# Exit immediately
return
# Reload loop
while True:
@ -234,6 +242,8 @@ def main():
default=False, help='Profile Portal')
parser.add_argument('--nologcycle', action='store_false', dest='nologcycle',
default=True, help='Do not cycle log files')
parser.add_argument('--doexit', action='store_true', dest='doexit',
default=False, help='Immediately exit after processes have started.')
parser.add_argument('gamedir', help="path to game dir")
parser.add_argument('twistdbinary', help="path to twistd binary")
parser.add_argument('slogfile', help="path to server log file")
@ -327,6 +337,8 @@ def main():
if args.pportal:
portal_argv.extend(pportal_argv)
print("\nRunning Evennia Portal under cProfile.")
if args.doexit:
print(PROCESS_DOEXIT)
# Windows fixes (Windows don't support pidfiles natively)
if os.name == 'nt':
@ -336,7 +348,7 @@ def main():
del portal_argv[-2]
# Start processes
start_services(server_argv, portal_argv)
start_services(server_argv, portal_argv, doexit=args.doexit)
if __name__ == '__main__':
main()