Start reworking launcher for sending instructions
This commit is contained in:
parent
84e0f463a5
commit
b4d2fe7284
5 changed files with 231 additions and 67 deletions
|
|
@ -125,6 +125,10 @@ class AMPServerClientProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
|
|
||||||
# receiving AMP data
|
# receiving AMP data
|
||||||
|
|
||||||
|
@amp.MsgStatus.responder
|
||||||
|
def server_receive_status(self, question):
|
||||||
|
return {"status": "OK"}
|
||||||
|
|
||||||
@amp.MsgPortal2Server.responder
|
@amp.MsgPortal2Server.responder
|
||||||
@amp.catch_traceback
|
@amp.catch_traceback
|
||||||
def server_receive_msgportal2server(self, packed_data):
|
def server_receive_msgportal2server(self, packed_data):
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,12 @@ 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
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cPickle as pickle
|
||||||
|
except ImportError:
|
||||||
|
import pickle
|
||||||
|
|
||||||
from twisted.protocols import amp
|
from twisted.protocols import amp
|
||||||
from twisted.internet import reactor, endpoints
|
from twisted.internet import reactor, endpoints
|
||||||
import django
|
import django
|
||||||
|
|
@ -67,15 +73,19 @@ PORTAL_RESTART = None
|
||||||
SERVER_PY_FILE = None
|
SERVER_PY_FILE = None
|
||||||
PORTAL_PY_FILE = None
|
PORTAL_PY_FILE = None
|
||||||
|
|
||||||
|
SPROFILER_LOGFILE = os.path.join(GAMEDIR, SERVERDIR, "logs", "server.prof")
|
||||||
|
PPROFILER_LOGFILE = os.path.join(GAMEDIR, SERVERDIR, "logs", "portal.prof")
|
||||||
|
|
||||||
TEST_MODE = False
|
TEST_MODE = False
|
||||||
ENFORCED_SETTING = False
|
ENFORCED_SETTING = False
|
||||||
|
|
||||||
# communication constants
|
# communication constants
|
||||||
|
|
||||||
SRELOAD = chr(14) # server reloading (have portal start a new server)
|
SRELOAD = chr(14) # server reloading (have portal start a new server)
|
||||||
PSTART = chr(15) # server+portal start
|
SSTART = chr(15) # server start
|
||||||
PSHUTD = chr(16) # portal (+server) shutdown
|
PSHUTD = chr(16) # portal (+server) shutdown
|
||||||
PSTATUS = chr(17) # ping server or portal status
|
SSHUTD = chr(17) # server-only shutdown
|
||||||
|
PSTATUS = chr(18) # ping server or portal status
|
||||||
|
|
||||||
# requirements
|
# requirements
|
||||||
PYTHON_MIN = '2.7'
|
PYTHON_MIN = '2.7'
|
||||||
|
|
@ -85,11 +95,11 @@ DJANGO_REC = '1.11'
|
||||||
|
|
||||||
sys.path[1] = EVENNIA_ROOT
|
sys.path[1] = EVENNIA_ROOT
|
||||||
|
|
||||||
#------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Messages
|
# Messages
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
CREATED_NEW_GAMEDIR = \
|
CREATED_NEW_GAMEDIR = \
|
||||||
"""
|
"""
|
||||||
|
|
@ -416,6 +426,10 @@ NOTE_TEST_CUSTOM = \
|
||||||
on the game dir.)
|
on the game dir.)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
PROCESS_ERROR = \
|
||||||
|
"""
|
||||||
|
{component} process error: {traceback}.
|
||||||
|
"""
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
|
@ -429,8 +443,8 @@ class MsgStatus(amp.Command):
|
||||||
Ping between AMP services
|
Ping between AMP services
|
||||||
|
|
||||||
"""
|
"""
|
||||||
key = "AMPPing"
|
key = "MsgStatus"
|
||||||
arguments = [('question', amp.String())]
|
arguments = [('status', amp.String())]
|
||||||
errors = {Exception: 'EXCEPTION'}
|
errors = {Exception: 'EXCEPTION'}
|
||||||
response = [('status', amp.String())]
|
response = [('status', amp.String())]
|
||||||
|
|
||||||
|
|
@ -442,12 +456,12 @@ class MsgLauncher2Portal(amp.Command):
|
||||||
"""
|
"""
|
||||||
key = "MsgLauncher2Portal"
|
key = "MsgLauncher2Portal"
|
||||||
arguments = [('operation', amp.String()),
|
arguments = [('operation', amp.String()),
|
||||||
('argument', amp.String())]
|
('arguments', amp.String())]
|
||||||
errors = {Exception: 'EXCEPTION'}
|
errors = {Exception: 'EXCEPTION'}
|
||||||
response = [('result', amp.String())]
|
response = [('result', amp.String())]
|
||||||
|
|
||||||
|
|
||||||
def send_instruction(instruction, argument, callback, errback):
|
def send_instruction(instruction, arguments, callback, errback):
|
||||||
"""
|
"""
|
||||||
Send instruction and handle the response.
|
Send instruction and handle the response.
|
||||||
|
|
||||||
|
|
@ -473,14 +487,22 @@ def send_instruction(instruction, argument, callback, errback):
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
if instruction == PSTATUS:
|
if instruction == PSTATUS:
|
||||||
prot.callRemote(MsgStatus, question="").addCallbacks(_callback, _errback)
|
prot.callRemote(MsgStatus, status="").addCallbacks(_callback, _errback)
|
||||||
else:
|
else:
|
||||||
prot.callRemote(MsgLauncher2Portal, instruction, argument).addCallbacks(
|
prot.callRemote(
|
||||||
_callback, _errback)
|
MsgLauncher2Portal,
|
||||||
|
instruction=instruction,
|
||||||
|
arguments=pickle.dumps(arguments, pickle.HIGHEST_PROTOCOL).addCallbacks(
|
||||||
|
_callback, _errback))
|
||||||
|
|
||||||
|
def _on_connect_fail(fail):
|
||||||
|
"This is called if portal is not reachable."
|
||||||
|
errback(fail)
|
||||||
|
reactor.stop()
|
||||||
|
|
||||||
point = endpoints.TCP4ClientEndpoint(reactor, AMP_HOST, AMP_PORT)
|
point = endpoints.TCP4ClientEndpoint(reactor, AMP_HOST, AMP_PORT)
|
||||||
deferred = endpoints.connectProtocol(point, amp.AMP())
|
deferred = endpoints.connectProtocol(point, amp.AMP())
|
||||||
deferred.addCallbacks(_on_connect, errback)
|
deferred.addCallbacks(_on_connect, _on_connect_fail)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -489,16 +511,33 @@ def send_status():
|
||||||
Send ping to portal
|
Send ping to portal
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import time
|
def _callback(response):
|
||||||
t0 = time.time()
|
pstatus, sstatus = response['status'].split("|")
|
||||||
def _callback(status):
|
print("Portal: {}\nServer: {}".format(pstatus, sstatus))
|
||||||
print("STATUS returned: %s (%gms)" % (status, (time.time()-t0) * 1000))
|
|
||||||
|
|
||||||
def _errback(err):
|
def _errback(fail):
|
||||||
print("STATUS returned: %s" % err)
|
pstatus, sstatus = "NOT RUNNING", "NOT RUNNING"
|
||||||
|
print("Portal: {}\nServer: {}".format(pstatus, sstatus))
|
||||||
|
|
||||||
send_instruction(PSTATUS, None, _callback, _errback)
|
send_instruction(PSTATUS, None, _callback, _errback)
|
||||||
|
|
||||||
|
|
||||||
|
def send_repeating_status(callback=None):
|
||||||
|
"""
|
||||||
|
Repeat the status ping until a reply is returned or timeout is reached.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callback (callable): Takes the response on a successful status-reply
|
||||||
|
"""
|
||||||
|
def _callback(response):
|
||||||
|
pstatus, sstatus = response['status'].split("|")
|
||||||
|
print("Portal: {}\nServer: {}".format(pstatus, sstatus))
|
||||||
|
|
||||||
|
def _errback(fail):
|
||||||
|
send_instruction(PSTATUS, None, _callback, _errback)
|
||||||
|
|
||||||
|
send_instruction(PSTATUS, None, callback or _callback, _errback)
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Helper functions
|
# Helper functions
|
||||||
|
|
@ -506,6 +545,118 @@ def send_status():
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def get_twistd_cmdline(pprofiler, sprofiler):
|
||||||
|
|
||||||
|
portal_cmd = [TWISTED_BINARY,
|
||||||
|
"--logfile={}".format(PORTAL_LOGFILE),
|
||||||
|
"--python={}".format(PORTAL_PY_FILE)]
|
||||||
|
server_cmd = [TWISTED_BINARY,
|
||||||
|
"--logfile={}".format(PORTAL_LOGFILE),
|
||||||
|
"--python={}".format(PORTAL_PY_FILE)]
|
||||||
|
if pprofiler:
|
||||||
|
portal_cmd.extend(["--savestats",
|
||||||
|
"--profiler=cprofiler",
|
||||||
|
"--profile={}".format(PPROFILER_LOGFILE)])
|
||||||
|
if sprofiler:
|
||||||
|
server_cmd.extend(["--savestats",
|
||||||
|
"--profiler=cprofiler",
|
||||||
|
"--profile={}".format(SPROFILER_LOGFILE)])
|
||||||
|
return portal_cmd, server_cmd
|
||||||
|
|
||||||
|
|
||||||
|
def start_evennia(pprofiler=False, sprofiler=False):
|
||||||
|
"""
|
||||||
|
This will start Evennia anew by launching the Evennia Portal (which in turn
|
||||||
|
will start the Server)
|
||||||
|
|
||||||
|
"""
|
||||||
|
portal_cmd, server_cmd = get_twistd_cmdline(pprofiler, sprofiler)
|
||||||
|
|
||||||
|
def _portal_running(response):
|
||||||
|
_, server_running = [stat == 'RUNNING' for stat in response['status'].split("|")]
|
||||||
|
print("Portal is already running as process {pid}. Not restarted.".format(pid=0)) # TODO PID
|
||||||
|
if server_running:
|
||||||
|
print("Server is already running as process {pid}. Not restarted.".format(pid=0)) # TODO PID
|
||||||
|
else:
|
||||||
|
print("Server starting {}...".format("(under cProfile)" if pprofiler else ""))
|
||||||
|
send_instruction(SSTART, server_cmd, lambda x: 0, lambda e: 0) # TODO
|
||||||
|
|
||||||
|
def _portal_cold_started(response):
|
||||||
|
"Called once the portal is up after a cold boot. It needs to know how to start the Server."
|
||||||
|
send_instruction(SSTART, server_cmd, lambda x: 0, lambda e: 0) # TODO
|
||||||
|
|
||||||
|
def _portal_not_running(fail):
|
||||||
|
print("Portal starting {}...".format("(under cProfile)" if sprofiler else ""))
|
||||||
|
try:
|
||||||
|
Popen(portal_cmd)
|
||||||
|
except Exception as e:
|
||||||
|
print(PROCESS_ERROR.format(component="Portal", traceback=e))
|
||||||
|
send_repeating_status(_portal_cold_started)
|
||||||
|
|
||||||
|
# first, check if the portal/server is running already
|
||||||
|
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
||||||
|
|
||||||
|
|
||||||
|
def reload_evennia(sprofiler=False):
|
||||||
|
"""
|
||||||
|
This will instruct the Portal to reboot the Server component.
|
||||||
|
|
||||||
|
"""
|
||||||
|
_, server_cmd = get_twistd_cmdline(False, sprofiler)
|
||||||
|
|
||||||
|
def _portal_running(response):
|
||||||
|
_, server_running = [stat == 'RUNNING' for stat in response['status'].split("|")]
|
||||||
|
if server_running:
|
||||||
|
print("Server reloading ...")
|
||||||
|
else:
|
||||||
|
print("Server down. Starting anew.")
|
||||||
|
send_instruction(SRELOAD, server_cmd, lambda x: 0, lambda e: 0) # TODO
|
||||||
|
|
||||||
|
def _portal_not_running(fail):
|
||||||
|
print("Evennia not running. Starting from scratch ...")
|
||||||
|
start_evennia()
|
||||||
|
|
||||||
|
# get portal status
|
||||||
|
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
||||||
|
|
||||||
|
|
||||||
|
def stop_evennia():
|
||||||
|
"""
|
||||||
|
This instructs the Portal to stop the Server and then itself.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def _portal_running(response):
|
||||||
|
_, server_running = [stat == 'RUNNING' for stat in response['status'].split("|")]
|
||||||
|
print("Portal stopping ...")
|
||||||
|
if server_running:
|
||||||
|
print("Server stopping ...")
|
||||||
|
send_instruction(PSHUTD, {}, lambda x: 0, lambda e: 0) # TODO
|
||||||
|
|
||||||
|
def _portal_not_running(fail):
|
||||||
|
print("Evennia is not running.")
|
||||||
|
|
||||||
|
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
||||||
|
|
||||||
|
|
||||||
|
def stop_server_only():
|
||||||
|
"""
|
||||||
|
Only stop the Server-component of Evennia (this is not useful except for debug)
|
||||||
|
|
||||||
|
"""
|
||||||
|
def _portal_running(response):
|
||||||
|
_, server_running = [stat == 'RUNNING' for stat in response['status'].split("|")]
|
||||||
|
if server_running:
|
||||||
|
print("Server stopping ...")
|
||||||
|
send_instruction(SSHUTD, {}, lambda x: 0, lambda e: 0) # TODO
|
||||||
|
else:
|
||||||
|
print("Server is not running.")
|
||||||
|
|
||||||
|
def _portal_not_running(fail):
|
||||||
|
print("Evennia is not running.")
|
||||||
|
|
||||||
|
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
||||||
|
|
||||||
|
|
||||||
def evennia_version():
|
def evennia_version():
|
||||||
"""
|
"""
|
||||||
Get the Evennia version info from the main package.
|
Get the Evennia version info from the main package.
|
||||||
|
|
@ -645,10 +796,10 @@ def create_settings_file(init=True, secret_settings=False):
|
||||||
if os.path.exists(settings_path):
|
if os.path.exists(settings_path):
|
||||||
inp = input("%s already exists. Do you want to reset it? y/[N]> " % settings_path)
|
inp = input("%s already exists. Do you want to reset it? y/[N]> " % settings_path)
|
||||||
if not inp.lower() == 'y':
|
if not inp.lower() == 'y':
|
||||||
print ("Aborted.")
|
print("Aborted.")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
print ("Reset the settings file.")
|
print("Reset the settings file.")
|
||||||
|
|
||||||
default_settings_path = os.path.join(EVENNIA_TEMPLATE, "server", "conf", "settings.py")
|
default_settings_path = os.path.join(EVENNIA_TEMPLATE, "server", "conf", "settings.py")
|
||||||
shutil.copy(default_settings_path, settings_path)
|
shutil.copy(default_settings_path, settings_path)
|
||||||
|
|
@ -912,7 +1063,7 @@ def error_check_python_modules():
|
||||||
_imp(settings.COMMAND_PARSER)
|
_imp(settings.COMMAND_PARSER)
|
||||||
_imp(settings.SEARCH_AT_RESULT)
|
_imp(settings.SEARCH_AT_RESULT)
|
||||||
_imp(settings.CONNECTION_SCREEN_MODULE)
|
_imp(settings.CONNECTION_SCREEN_MODULE)
|
||||||
#imp(settings.AT_INITIAL_SETUP_HOOK_MODULE, split=False)
|
# imp(settings.AT_INITIAL_SETUP_HOOK_MODULE, split=False)
|
||||||
for path in settings.LOCK_FUNC_MODULES:
|
for path in settings.LOCK_FUNC_MODULES:
|
||||||
_imp(path, split=False)
|
_imp(path, split=False)
|
||||||
|
|
||||||
|
|
@ -1280,7 +1431,7 @@ def server_operation(mode, service, interactive, profiler, logserver=False, doex
|
||||||
|
|
||||||
elif mode == 'stop':
|
elif mode == 'stop':
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
print (
|
print(
|
||||||
"(Obs: You can use a single Ctrl-C to skip "
|
"(Obs: You can use a single Ctrl-C to skip "
|
||||||
"Windows' annoying 'Terminate batch job (Y/N)?' prompts.)")
|
"Windows' annoying 'Terminate batch job (Y/N)?' prompts.)")
|
||||||
# stop processes, avoiding reload
|
# stop processes, avoiding reload
|
||||||
|
|
@ -1357,7 +1508,8 @@ def main():
|
||||||
default=None, help='Get current server 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 django-admin commands.)")
|
"evennia migration|flush|shell|dbshell (see the django documentation for more "
|
||||||
|
"django-admin commands.)")
|
||||||
|
|
||||||
args, unknown_args = parser.parse_known_args()
|
args, unknown_args = parser.parse_known_args()
|
||||||
|
|
||||||
|
|
@ -1422,10 +1574,20 @@ 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 ('start', 'reload', 'stop'):
|
elif option in ('sstart', 'sreload', '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)
|
||||||
server_operation(option, service, args.interactive, args.profiler, args.logserver, doexit=args.doexit)
|
if option == "sstart":
|
||||||
|
start_evennia(False, args.profiler)
|
||||||
|
elif option == 'sreload':
|
||||||
|
reload_evennia(args.profiler)
|
||||||
|
elif option == 'sstop':
|
||||||
|
stop_evennia()
|
||||||
|
elif option == 'ssstop':
|
||||||
|
stop_server_only()
|
||||||
|
else:
|
||||||
|
server_operation(option, service, args.interactive,
|
||||||
|
args.profiler, args.logserver, doexit=args.doexit)
|
||||||
elif option != "noop":
|
elif option != "noop":
|
||||||
# pass-through to django manager
|
# pass-through to django manager
|
||||||
check_db = False
|
check_db = False
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,6 @@ CMDLINE_HELP = \
|
||||||
are stored in the game's server/ directory.
|
are stored in the game's server/ directory.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PROCESS_ERROR = \
|
|
||||||
"""
|
|
||||||
{component} process error: {traceback}.
|
|
||||||
"""
|
|
||||||
|
|
||||||
PROCESS_IOERROR = \
|
PROCESS_IOERROR = \
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,10 @@ SCONN = chr(11) # server creating new connection (for irc bots and etc)
|
||||||
PCONNSYNC = chr(12) # portal post-syncing a session
|
PCONNSYNC = chr(12) # portal post-syncing a session
|
||||||
PDISCONNALL = chr(13) # portal session disconnect all
|
PDISCONNALL = chr(13) # portal session disconnect all
|
||||||
SRELOAD = chr(14) # server reloading (have portal start a new server)
|
SRELOAD = chr(14) # server reloading (have portal start a new server)
|
||||||
PSTART = chr(15) # server+portal start
|
SSTART = chr(15) # server start (portal must already be running anyway)
|
||||||
PSHUTD = chr(16) # portal (+server) shutdown
|
PSHUTD = chr(16) # portal (+server) shutdown
|
||||||
PSTATUS = chr(17) # ping server or portal status
|
SSHUTD = chr(17) # server-only shutdown
|
||||||
|
PSTATUS = chr(18) # ping server or portal status
|
||||||
|
|
||||||
AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed)
|
AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed)
|
||||||
BATCH_RATE = 250 # max commands/sec before switching to batch-sending
|
BATCH_RATE = 250 # max commands/sec before switching to batch-sending
|
||||||
|
|
@ -150,7 +151,7 @@ class MsgLauncher2Portal(amp.Command):
|
||||||
"""
|
"""
|
||||||
key = "MsgLauncher2Portal"
|
key = "MsgLauncher2Portal"
|
||||||
arguments = [('operation', amp.String()),
|
arguments = [('operation', amp.String()),
|
||||||
('argument', amp.String())]
|
('arguments', amp.String())]
|
||||||
errors = {Exception: 'EXCEPTION'}
|
errors = {Exception: 'EXCEPTION'}
|
||||||
response = [('result', amp.String())]
|
response = [('result', amp.String())]
|
||||||
|
|
||||||
|
|
@ -210,8 +211,8 @@ class MsgStatus(amp.Command):
|
||||||
Check Status between AMP services
|
Check Status between AMP services
|
||||||
|
|
||||||
"""
|
"""
|
||||||
key = "AMPPing"
|
key = "MsgStatus"
|
||||||
arguments = [('question', amp.String())]
|
arguments = [('status', amp.String())]
|
||||||
errors = {Exception: 'EXCEPTION'}
|
errors = {Exception: 'EXCEPTION'}
|
||||||
response = [('status', amp.String())]
|
response = [('status', amp.String())]
|
||||||
|
|
||||||
|
|
@ -342,23 +343,6 @@ class AMPMultiConnectionProtocol(amp.AMP):
|
||||||
self.errback, command.key))
|
self.errback, command.key))
|
||||||
return DeferredList(deferreds)
|
return DeferredList(deferreds)
|
||||||
|
|
||||||
def send_status(self, port, callback, errback):
|
|
||||||
"""
|
|
||||||
Ping to the given AMP port.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
port (int): The port to ping
|
|
||||||
callback (callable): This will be called with the port that replied to the ping.
|
|
||||||
errback (callable0: This will be called with the port that failed to reply.
|
|
||||||
|
|
||||||
"""
|
|
||||||
targets = [(protcl, protcl.getHost()[1]) for protcl in self.factory.broadcasts]
|
|
||||||
deferreds = []
|
|
||||||
for protcl, port in ((protcl, prt) for protcl, prt in targets if prt == port):
|
|
||||||
deferreds.append(protcl.callRemote(MsgStatus, status=True).addCallback(
|
|
||||||
callback, port).addErrback(errback, port))
|
|
||||||
return DeferredList(deferreds)
|
|
||||||
|
|
||||||
# generic function send/recvs
|
# generic function send/recvs
|
||||||
|
|
||||||
def send_FunctionCall(self, modulepath, functionname, *args, **kwargs):
|
def send_FunctionCall(self, modulepath, functionname, *args, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -96,43 +96,61 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
||||||
"""
|
"""
|
||||||
return self.data_out(amp.AdminPortal2Server, session.sessid, operation=operation, **kwargs)
|
return self.data_out(amp.AdminPortal2Server, session.sessid, operation=operation, **kwargs)
|
||||||
|
|
||||||
def sendPingPortal2Server(self, callback):
|
|
||||||
"""
|
|
||||||
Send ping to check if Server is alive.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# receive amp data
|
# receive amp data
|
||||||
|
|
||||||
@amp.MsgStatus.responder
|
@amp.MsgStatus.responder
|
||||||
def portal_receive_status(self, question):
|
@amp.catch_traceback
|
||||||
return {"status": "All well"}
|
def portal_receive_status(self, status):
|
||||||
|
"""
|
||||||
|
Check if Server is running
|
||||||
|
"""
|
||||||
|
# check if the server is connected
|
||||||
|
server_connected = any(1 for prtcl in self.factory.broadcasts
|
||||||
|
if prtcl is not self and prtcl.transport.connected)
|
||||||
|
# return portal|server RUNNING/NOT RUNNING
|
||||||
|
if server_connected:
|
||||||
|
return {"status": "RUNNING|RUNNING"}
|
||||||
|
else:
|
||||||
|
return {"status": "RUNNING|NOT RUNNING"}
|
||||||
|
|
||||||
@amp.MsgLauncher2Portal.responder
|
@amp.MsgLauncher2Portal.responder
|
||||||
@amp.catch_traceback
|
@amp.catch_traceback
|
||||||
def portal_receive_launcher2portal(self, operation, argument):
|
def portal_receive_launcher2portal(self, operation, arguments):
|
||||||
"""
|
"""
|
||||||
Receives message arriving from evennia_launcher.
|
Receives message arriving from evennia_launcher.
|
||||||
This method is executed on the Portal.
|
This method is executed on the Portal.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
operation (str): The action to perform.
|
operation (str): The action to perform.
|
||||||
argument (str): A possible argument to the instruction, or the empty string.
|
arguments (str): Possible argument to the instruction, or the empty string.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
result (dict): The result back to the launcher.
|
result (dict): The result back to the launcher.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
This is the entrypoint for controlling the entire Evennia system from the
|
This is the entrypoint for controlling the entire Evennia system from the evennia
|
||||||
evennia launcher.
|
launcher. It can obviously only accessed when the Portal is already up and running.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if operation == amp.PSTART: # portal start (server start or reload)
|
server_connected = any(1 for prtcl in self.factory.broadcasts
|
||||||
pass
|
if prtcl is not self and prtcl.transport.connected)
|
||||||
|
|
||||||
|
if operation == amp.SSTART: # portal start (server start or reload)
|
||||||
|
# first, check if server is already running
|
||||||
|
if server_connected:
|
||||||
|
return {"result": "Server already running (PID {}).".format(0)} # TODO store and send PID
|
||||||
|
else:
|
||||||
|
self.start_server(amp.loads(arguments))
|
||||||
|
return {"result": "Server started with PID {}.".format(0)} # TODO
|
||||||
elif operation == amp.SRELOAD: # reload server
|
elif operation == amp.SRELOAD: # reload server
|
||||||
pass
|
if server_connected:
|
||||||
|
self.reload_server(amp.loads(arguments))
|
||||||
|
else:
|
||||||
|
self.start_server(amp.loads(arguments))
|
||||||
elif operation == amp.PSHUTD: # portal + server shutdown
|
elif operation == amp.PSHUTD: # portal + server shutdown
|
||||||
pass
|
if server_connected:
|
||||||
|
self.stop_server(amp.loads(arguments))
|
||||||
|
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue