mirror of
https://github.com/evennia/evennia.git
synced 2026-03-27 10:16:32 +01:00
Add ability to ping Portal from launcher over AMP
This commit is contained in:
parent
d89fbf1943
commit
3fde374703
3 changed files with 137 additions and 16 deletions
|
|
@ -20,6 +20,8 @@ import importlib
|
|||
from distutils.version import LooseVersion
|
||||
from argparse import ArgumentParser
|
||||
from subprocess import Popen, check_output, call, CalledProcessError, STDOUT
|
||||
from twisted.protocols import amp
|
||||
from twisted.internet import reactor, endpoints
|
||||
import django
|
||||
|
||||
# Signal processing
|
||||
|
|
@ -49,18 +51,32 @@ CURRENT_DIR = os.getcwd()
|
|||
GAMEDIR = CURRENT_DIR
|
||||
|
||||
# Operational setup
|
||||
AMP_PORT = None
|
||||
AMP_HOST = None
|
||||
AMP_INTERFACE = None
|
||||
|
||||
SERVER_LOGFILE = None
|
||||
PORTAL_LOGFILE = None
|
||||
HTTP_LOGFILE = None
|
||||
|
||||
SERVER_PIDFILE = None
|
||||
PORTAL_PIDFILE = None
|
||||
SERVER_RESTART = None
|
||||
PORTAL_RESTART = None
|
||||
|
||||
SERVER_PY_FILE = None
|
||||
PORTAL_PY_FILE = None
|
||||
|
||||
TEST_MODE = False
|
||||
ENFORCED_SETTING = False
|
||||
|
||||
# communication constants
|
||||
|
||||
SRELOAD = chr(14) # server reloading (have portal start a new server)
|
||||
PSTART = chr(15) # server+portal start
|
||||
PSHUTD = chr(16) # portal (+server) shutdown
|
||||
PSTATUS = chr(17) # ping server or portal status
|
||||
|
||||
# requirements
|
||||
PYTHON_MIN = '2.7'
|
||||
TWISTED_MIN = '16.0.0'
|
||||
|
|
@ -303,6 +319,15 @@ MENU = \
|
|||
+---------------------------------------------------------------+
|
||||
"""
|
||||
|
||||
ERROR_AMP_UNCONFIGURED = \
|
||||
"""
|
||||
Can't find server info for connecting. Either run this command from
|
||||
the game dir (it will then use the game's settings file) or specify
|
||||
the path to your game's settings file manually with the --settings
|
||||
option.
|
||||
|
||||
"""
|
||||
|
||||
ERROR_LOGDIR_MISSING = \
|
||||
"""
|
||||
ERROR: One or more log-file directory locations could not be
|
||||
|
|
@ -391,11 +416,94 @@ NOTE_TEST_CUSTOM = \
|
|||
on the game dir.)
|
||||
"""
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
||||
# ------------------------------------------------------------
|
||||
#
|
||||
# Functions
|
||||
# Protocol Evennia launcher - Portal/Server communication
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
# ------------------------------------------------------------
|
||||
|
||||
|
||||
class MsgStatus(amp.Command):
|
||||
"""
|
||||
Ping between AMP services
|
||||
|
||||
"""
|
||||
key = "AMPPing"
|
||||
arguments = [('question', amp.String())]
|
||||
errors = {Exception: 'EXCEPTION'}
|
||||
response = [('status', amp.String())]
|
||||
|
||||
|
||||
class MsgLauncher2Portal(amp.Command):
|
||||
"""
|
||||
Message Launcher -> Portal
|
||||
|
||||
"""
|
||||
key = "MsgLauncher2Portal"
|
||||
arguments = [('operation', amp.String()),
|
||||
('argument', amp.String())]
|
||||
errors = {Exception: 'EXCEPTION'}
|
||||
response = [('result', amp.String())]
|
||||
|
||||
|
||||
def send_instruction(instruction, argument, callback, errback):
|
||||
"""
|
||||
Send instruction and handle the response.
|
||||
|
||||
"""
|
||||
if None in (AMP_HOST, AMP_PORT, AMP_INTERFACE):
|
||||
print(ERROR_AMP_UNCONFIGURED)
|
||||
sys.exit()
|
||||
|
||||
def _on_connect(prot):
|
||||
"""
|
||||
This fires with the protocol when connection is established. We
|
||||
immediately send off the instruction then shut down.
|
||||
|
||||
"""
|
||||
def _callback(result):
|
||||
callback(result)
|
||||
prot.transport.loseConnection()
|
||||
reactor.stop()
|
||||
|
||||
def _errback(fail):
|
||||
errback(fail)
|
||||
prot.transport.loseConnection()
|
||||
reactor.stop()
|
||||
|
||||
if instruction == PSTATUS:
|
||||
prot.callRemote(MsgStatus, question="").addCallbacks(_callback, _errback)
|
||||
else:
|
||||
prot.callRemote(MsgLauncher2Portal, instruction, argument).addCallbacks(
|
||||
_callback, _errback)
|
||||
|
||||
point = endpoints.TCP4ClientEndpoint(reactor, AMP_HOST, AMP_PORT)
|
||||
deferred = endpoints.connectProtocol(point, amp.AMP())
|
||||
deferred.addCallbacks(_on_connect, errback)
|
||||
reactor.run()
|
||||
|
||||
|
||||
def send_status():
|
||||
"""
|
||||
Send ping to portal
|
||||
|
||||
"""
|
||||
import time
|
||||
t0 = time.time()
|
||||
def _callback(status):
|
||||
print("STATUS returned: %s (%gms)" % (status, (time.time()-t0) * 1000))
|
||||
|
||||
def _errback(err):
|
||||
print("STATUS returned: %s" % err)
|
||||
|
||||
send_instruction(PSTATUS, None, _callback, _errback)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
# ------------------------------------------------------------
|
||||
|
||||
|
||||
def evennia_version():
|
||||
|
|
@ -869,12 +977,17 @@ def init_game_directory(path, check_db=True):
|
|||
check_database()
|
||||
|
||||
# set up the Evennia executables and log file locations
|
||||
global AMP_PORT, AMP_HOST, AMP_INTERFACE
|
||||
global SERVER_PY_FILE, PORTAL_PY_FILE
|
||||
global SERVER_LOGFILE, PORTAL_LOGFILE, HTTP_LOGFILE
|
||||
global SERVER_PIDFILE, PORTAL_PIDFILE
|
||||
global SERVER_RESTART, PORTAL_RESTART
|
||||
global EVENNIA_VERSION
|
||||
|
||||
AMP_PORT = settings.AMP_PORT
|
||||
AMP_HOST = settings.AMP_HOST
|
||||
AMP_INTERFACE = settings.AMP_INTERFACE
|
||||
|
||||
SERVER_PY_FILE = os.path.join(EVENNIA_LIB, "server", "server.py")
|
||||
PORTAL_PY_FILE = os.path.join(EVENNIA_LIB, "portal", "portal", "portal.py")
|
||||
|
||||
|
|
@ -1239,6 +1352,9 @@ def main():
|
|||
"service", metavar="component", nargs='?', default="all",
|
||||
help=("Which component to operate on: "
|
||||
"'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 = (
|
||||
"Common usage: evennia start|stop|reload. Django-admin database commands:"
|
||||
"evennia migration|flush|shell|dbshell (see the django documentation for more django-admin commands.)")
|
||||
|
|
@ -1289,6 +1405,11 @@ def main():
|
|||
print(ERROR_INITSETTINGS)
|
||||
sys.exit()
|
||||
|
||||
if args.get_status:
|
||||
init_game_directory(CURRENT_DIR, check_db=True)
|
||||
send_status()
|
||||
sys.exit()
|
||||
|
||||
if args.dummyrunner:
|
||||
# launch the dummy runner
|
||||
init_game_directory(CURRENT_DIR, check_db=True)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ PDISCONNALL = chr(13) # portal session disconnect all
|
|||
SRELOAD = chr(14) # server reloading (have portal start a new server)
|
||||
PSTART = chr(15) # server+portal start
|
||||
PSHUTD = chr(16) # portal (+server) shutdown
|
||||
PPING = chr(17) # server or portal status
|
||||
PSTATUS = chr(17) # ping server or portal status
|
||||
|
||||
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
|
||||
|
|
@ -205,15 +205,15 @@ class AdminServer2Portal(amp.Command):
|
|||
response = []
|
||||
|
||||
|
||||
class MsgPing(amp.Command):
|
||||
class MsgStatus(amp.Command):
|
||||
"""
|
||||
Ping between AMP services
|
||||
Check Status between AMP services
|
||||
|
||||
"""
|
||||
key = "AMPPing"
|
||||
arguments = [('ping', amp.Boolean())]
|
||||
arguments = [('question', amp.String())]
|
||||
errors = {Exception: 'EXCEPTION'}
|
||||
response = [('pong', amp.Boolean())]
|
||||
response = [('status', amp.String())]
|
||||
|
||||
|
||||
class FunctionCall(amp.Command):
|
||||
|
|
@ -271,9 +271,7 @@ class AMPMultiConnectionProtocol(amp.AMP):
|
|||
|
||||
def connectionMade(self):
|
||||
"""
|
||||
This is called when an AMP connection is (re-)established
|
||||
between server and portal. AMP calls it on both sides, so we
|
||||
need to make sure to only trigger resync from the portal side.
|
||||
This is called when an AMP connection is (re-)established AMP calls it on both sides.
|
||||
|
||||
"""
|
||||
self.factory.broadcasts.append(self)
|
||||
|
|
@ -344,7 +342,7 @@ class AMPMultiConnectionProtocol(amp.AMP):
|
|||
self.errback, command.key))
|
||||
return DeferredList(deferreds)
|
||||
|
||||
def send_ping(self, port, callback, errback):
|
||||
def send_status(self, port, callback, errback):
|
||||
"""
|
||||
Ping to the given AMP port.
|
||||
|
||||
|
|
@ -357,7 +355,7 @@ class AMPMultiConnectionProtocol(amp.AMP):
|
|||
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(MsgPing, ping=True).addCallback(
|
||||
deferreds.append(protcl.callRemote(MsgStatus, status=True).addCallback(
|
||||
callback, port).addErrback(errback, port))
|
||||
return DeferredList(deferreds)
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,10 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
|
||||
# receive amp data
|
||||
|
||||
@amp.MsgStatus.responder
|
||||
def portal_receive_status(self, question):
|
||||
return {"status": "All well"}
|
||||
|
||||
@amp.MsgLauncher2Portal.responder
|
||||
@amp.catch_traceback
|
||||
def portal_receive_launcher2portal(self, operation, argument):
|
||||
|
|
@ -123,9 +127,7 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
evennia launcher.
|
||||
|
||||
"""
|
||||
if operation == amp.PPING: # check portal and server status
|
||||
pass
|
||||
elif operation == amp.PSTART: # portal start (server start or reload)
|
||||
if operation == amp.PSTART: # portal start (server start or reload)
|
||||
pass
|
||||
elif operation == amp.SRELOAD: # reload server
|
||||
pass
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue