update feature #1
This commit is contained in:
parent
41b23d2e66
commit
ef3cc5347d
4 changed files with 357 additions and 276 deletions
|
@ -17,4 +17,4 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__version__ = '1.0.0'
|
||||
__version__ = '1.1.0'
|
||||
|
|
|
@ -70,12 +70,12 @@ This script need configuration file (see below for model)::
|
|||
bufsize = 100
|
||||
# It's possible to collect some message on output (example player conected) with regex command
|
||||
# keep some data on array/dict state
|
||||
keep_state = yes
|
||||
activate_filter = yes
|
||||
# size array/dict state
|
||||
size_max_state = 1000
|
||||
size_max_filter = 1000
|
||||
# search regex to add state (python regex)
|
||||
add_state = "^((.*)(setActiveCharForPlayer).*(: set active char )[\d]+( for )(?P<ActivePlayer>.*)|(.*)(disconnectPlayer)(.+:.+<.+>){0,1}[\s]+(?P<InactivePlayer>.*)[\s]+(is disconnected))"
|
||||
del_state = "^((.*)(setActiveCharForPlayer).*(: set active char )[\d]+( for )(?P<InactivePlayer>.*)|(.*)(disconnectPlayer)(.+:.+<.+>){0,1}[\s]+(?P<ActivePlayer>.*)[\s]+(is disconnected))"
|
||||
add_filter = "^((.*)(setActiveCharForPlayer).*(: set active char )[\d]+( for )(?P<ActivePlayer>.*)|(.*)(disconnectPlayer)(.+:.+<.+>){0,1}[\s]+(?P<InactivePlayer>.*)[\s]+(is disconnected))"
|
||||
del_filter = "^((.*)(setActiveCharForPlayer).*(: set active char )[\d]+( for )(?P<InactivePlayer>.*)|(.*)(disconnectPlayer)(.+:.+<.+>){0,1}[\s]+(?P<ActivePlayer>.*)[\s]+(is disconnected))"
|
||||
# autostart (when start OpenNelManager, launch this program)
|
||||
autostart = no
|
||||
# restart after crash
|
||||
|
@ -111,37 +111,37 @@ Design
|
|||
http(s) command :
|
||||
-----------------
|
||||
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **Html command** | **Path** | **Argument** {json format} | **Comment** |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **POST** | /SHUTDOWN | | Stop all process and stop pymanager |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **POST** | /STARTALL | | Start all processes |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /STATUSALL | | Get status all processes |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **POST** | /STOPALL | | Stop all processes |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **POST** | /START | {'name': program} | Start for one program |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **POST** | /STDIN | {'name': program, 'action': action} | Send action for one program (send to input) |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /STATUS | {'name': program} | Get status for one program |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **POST** | /STOP | {'name': program} | Stop for one program |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /STDOUT | {'name': program, 'first-line': firstline } | Get log for one program |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /GETSTATE | {'name': program } | Get all state (key find in stdout add/remove) |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /CONFIG | {'name': program } | Get configuration |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /INFO | {'name': program } | Get Information (number player, ...) |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /PLAYER | {'name': program } | Get active player |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
| **GET** | /ADMINCOMMAND | {'name': program } | Get admin commmand |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **Html command** | **Path** | **Argument** {json format} | **Comment** | **Return*** |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **POST** | /SHUTDOWN | | Stop all process and stop pymanager | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **POST** | /STARTALL | | Start all processes | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /STATUSALL | | Get status all processes | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **POST** | /STOPALL | | Stop all processes | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **POST** | /START | {'name': program} | Start for one program | {'state': '<STATE>'} |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **POST** | /STDIN | {'name': program, 'action': action} | Send action for one program (send to input) | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /STATUS | {'name': program} | Get status for one program | {'state': '<STATE>'} |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **POST** | /STOP | {'name': program} | Stop for one program | {'state': '<STATE>'} |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /STDOUT | {'name': program, 'first-line': firstline } | Get log for one program | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /FILTER | {'name': program } | Get all state (key find in stdout add/remove) | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /CONFIG | {'name': program } | Get configuration | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /INFO | {'name': program } | Get Information (number player, ...) | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /PLAYER | {'name': program } | Get active player | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
| **GET** | /ADMINCOMMAND | {'name': program } | Get admin commmand | |
|
||||
+------------------+------------------+---------------------------------------------+-----------------------------------------------+------------------------------+
|
||||
|
||||
Example ::
|
||||
|
||||
|
@ -275,7 +275,7 @@ class ManageHttpRequest(http.server.SimpleHTTPRequestHandler):
|
|||
return
|
||||
self.server.listSemaphore[name].release()
|
||||
self._set_headers()
|
||||
self.wfile.write(bytes(item, "utf-8"))
|
||||
self.wfile.write(bytes(json.dumps(item), "utf-8"))
|
||||
logging.debug("item : %s" % item)
|
||||
|
||||
def _send_list(self):
|
||||
|
@ -343,15 +343,21 @@ class ManageHttpRequest(http.server.SimpleHTTPRequestHandler):
|
|||
logging.debug("%s:%s" % (name, action))
|
||||
self.server.listSemaphore[name].acquire()
|
||||
self.server.listQueueIn[name].put("STDIN %s" % action)
|
||||
logging.debug("message envoye: %s" % (name))
|
||||
logging.debug("message sent: %s" % (name))
|
||||
|
||||
try:
|
||||
result = self.server.listQueueOut[name].get(timeout=4)
|
||||
outjson = self.server.listQueueOut[name].get(timeout=4)
|
||||
except queue.Empty:
|
||||
logging.debug("pas de message recu pour %s" % name)
|
||||
logging.debug("no return %s" % name)
|
||||
self.server.listSemaphore[name].release()
|
||||
return
|
||||
except Exception as e:
|
||||
# Trap all error (release semaphore)
|
||||
self.send_error(500, 'Internal Error')
|
||||
logging.error("unknown error %s (%s)" % (name, e))
|
||||
self.server.listSemaphore[name].release()
|
||||
return
|
||||
self.server.listSemaphore[name].release()
|
||||
outjson = {'state': result}
|
||||
self._set_headers()
|
||||
self.wfile.write(bytes(json.dumps(outjson), "utf-8"))
|
||||
|
||||
|
@ -377,15 +383,20 @@ class ManageHttpRequest(http.server.SimpleHTTPRequestHandler):
|
|||
self.server.listSemaphore[name].acquire()
|
||||
self.server.listQueueIn[name].put(command)
|
||||
try:
|
||||
result = self.server.listQueueOut[name].get(timeout=4)
|
||||
outjson = self.server.listQueueOut[name].get(timeout=4)
|
||||
except queue.Empty:
|
||||
self.send_error(500, 'Missing return')
|
||||
logging.debug("[%s %s] Missing return" % (command, name))
|
||||
self.server.listSemaphore[name].release()
|
||||
return
|
||||
except Exception as e:
|
||||
# Trap all error (release semaphore)
|
||||
self.send_error(500, 'Internal Error')
|
||||
logging.error("unknown error %s (%s)" % (name, e))
|
||||
self.server.listSemaphore[name].release()
|
||||
return
|
||||
self.server.listSemaphore[name].release()
|
||||
logging.debug("[%s %s] => %s" % (command, name, result))
|
||||
|
||||
outjson = {'state': result}
|
||||
logging.debug("[%s %s] => %s" % (command, name, outjson))
|
||||
self._set_headers()
|
||||
self.wfile.write(bytes(json.dumps(outjson), "utf-8"))
|
||||
|
||||
|
@ -426,8 +437,8 @@ class ManageHttpRequest(http.server.SimpleHTTPRequestHandler):
|
|||
logging.error("Wrong authentication")
|
||||
elif self.path == '/STDOUT':
|
||||
self._command_log()
|
||||
elif self.path == "/STATE":
|
||||
self._send_command("STATE")
|
||||
elif self.path == "/FILTER":
|
||||
self._send_command("FILTER")
|
||||
elif self.path == "/INFO":
|
||||
self._send_command("INFO")
|
||||
elif self.path == "/PLAYER":
|
||||
|
@ -571,8 +582,9 @@ class ServerHttp(multiprocessing.Process):
|
|||
logging.error("Bad value 'method' (%s)" % str(self.method))
|
||||
raise ValueError
|
||||
httpd.serve_forever()
|
||||
logging.info("End")
|
||||
|
||||
def append(self, name, queueIn, queueOut, semaphore):
|
||||
def appendchild(self, name, queueIn, queueOut, semaphore):
|
||||
self.listQueueIn.setdefault(name, queueIn)
|
||||
self.listQueueOut.setdefault(name, queueOut)
|
||||
self.listSemaphore.setdefault(name, semaphore)
|
||||
|
@ -588,7 +600,7 @@ class ManageCommand():
|
|||
def __init__(self, name,
|
||||
command, path,
|
||||
logsize, bufsize, queueIn, queueOut, semaphore,
|
||||
keep_state, size_max_state, add_state, del_state,
|
||||
activate_filter, size_max_filter, add_filter, del_filter,
|
||||
autostart, restart_after_crash, restart_delay,
|
||||
egs_filter,
|
||||
maxWaitEnd=10, waitDelay=1):
|
||||
|
@ -605,36 +617,38 @@ class ManageCommand():
|
|||
self.bufsize = bufsize
|
||||
self.threadRead = None
|
||||
self.running = False
|
||||
self.state = multiprocessing.Queue()
|
||||
# self.state = multiprocessing.Queue()
|
||||
self.pipeIn, self.pipeOut = multiprocessing.Pipe()
|
||||
self.eventRunningReader = threading.Event()
|
||||
self.eventRunningRestart = threading.Event()
|
||||
self.maxWaitEnd = maxWaitEnd
|
||||
self.waitDelay = waitDelay
|
||||
self.keep_state = keep_state
|
||||
self.size_max_state = size_max_state
|
||||
self.add_state_cmd = add_state[1:-1]
|
||||
self.del_state_cmd = del_state[1:-1]
|
||||
self.filter_add_state = re.compile(self.add_state_cmd)
|
||||
self.filter_del_state = re.compile(self.del_state_cmd)
|
||||
self.state = {}
|
||||
self.activate_filter = activate_filter
|
||||
self.size_max_filter = size_max_filter
|
||||
self.add_filter_cmd = add_filter[1:-1]
|
||||
self.del_filter_cmd = del_filter[1:-1]
|
||||
self.filter_add_filter = re.compile(self.add_filter_cmd)
|
||||
self.filter_del_filter = re.compile(self.del_filter_cmd)
|
||||
self.filter = {}
|
||||
self.autostart = autostart
|
||||
self.restart_after_crash = restart_after_crash
|
||||
self.restart_delay = restart_delay
|
||||
self.threadRestart = None
|
||||
self.egs_filter = egs_filter
|
||||
self.egs_filter_load_character = re.compile(".*(LOADED User )'(?P<UID>[\d]+)' Character '(?P<NameDomain>[^']+)' from BS stream file 'characters/([\d]+)/account_(?P<UIDBIS>[\d]+)_(?P<IDCHAR>[\d]+)_pdr.bin")
|
||||
self.egs_filter_load_character = re.compile(".*(egs_plinfo).*(: LOADED User )'(?P<UID>[\d]+)' Character '(?P<NameDomain>[^']+)' from BS stream file 'characters/([\d]+)/account_(?P<UIDBIS>[\d]+)_(?P<IDCHAR>[\d]+)_pdr.bin")
|
||||
self.egs_filter_active_character = re.compile(".*(setActiveCharForPlayer).*(: set active char )(?P<IDCHAR>[\d]+)( for player )(?P<UID>[\d]+)")
|
||||
self.egs_filter_sid = re.compile(".*(Mapping UID )(?P<UID>[\d]+)( => Sid )\((?P<SID>.*)\)")
|
||||
self.egs_filter_client_ready = re.compile(".*(Updating IS_NEWBIE flag for character: )\((?P<ID>.*)\)")
|
||||
self.egs_filter_disconnected = re.compile(".*(disconnectPlayer).+[\s]+(player )(?P<UID>[\d]+)[\s]+(is disconnected)")
|
||||
self.egs_filter_admin = re.compile("(.*)(cbClientAdmin EGS-136 : )(ADMIN)(: Player )\((?P<SID>.*)\)(?P<ACTION>.+)")
|
||||
self.state_load_character = {}
|
||||
self.state_active_character = {}
|
||||
self.state_admin = []
|
||||
self.egs_filter_admin = re.compile("(.*)(cbClientAdmin).*(: ADMIN)(: Player )\((?P<SID>.*)\)(?P<ACTION>.+)")
|
||||
# cbClientAdmin EGS-133 : ADMIN: Player (0x0000000021:00:00:86) tried to execute a no valid client admin command 'info'
|
||||
self.filter_load_character = {}
|
||||
self.filter_active_character = {}
|
||||
self.filter_admin = {}
|
||||
self.number_start = 0
|
||||
self.first_line = 0
|
||||
self.last_line = 0
|
||||
self.pos_admin = 0
|
||||
|
||||
def _analyze_line(self, msg):
|
||||
now = time.strftime('%Y/%m/%d %H:%M:%S %Z')
|
||||
|
@ -646,40 +660,40 @@ class ManageCommand():
|
|||
self.last_line = self.last_line + 1
|
||||
# If option sate is defined, analyze message and keep state (example , all player connected)
|
||||
logging.debug("recu: '%s'" % (msg))
|
||||
if self.keep_state:
|
||||
res = self.filter_add_state.match(msg)
|
||||
if self.activate_filter:
|
||||
res = self.filter_add_filter.match(msg)
|
||||
if res:
|
||||
logging.debug("add_state found")
|
||||
if len(self.state) < self.size_max_state:
|
||||
logging.debug("include add_state found")
|
||||
logging.debug("add_filter found")
|
||||
if len(self.filter) < self.size_max_filter:
|
||||
logging.debug("include add_filter found")
|
||||
dico = res.groupdict()
|
||||
for key in dico:
|
||||
logging.debug("set add_state found [%s]" % (str(key)))
|
||||
logging.debug("set add_filter found [%s]" % (str(key)))
|
||||
if dico[key]:
|
||||
logging.debug("set1 add_state found [%s][%s]" % (str(key), str(dico[key])))
|
||||
self.state.setdefault(key, {})
|
||||
self.state[key].setdefault(dico[key], now)
|
||||
res = self.filter_del_state.match(msg)
|
||||
logging.debug("set1 add_filter found [%s][%s]" % (str(key), str(dico[key])))
|
||||
self.filter.setdefault(key, {})
|
||||
self.filter[key].setdefault(dico[key], now)
|
||||
res = self.filter_del_filter.match(msg)
|
||||
if res:
|
||||
logging.debug("del_state found")
|
||||
logging.debug("del_filter found")
|
||||
dico = res.groupdict()
|
||||
for key in dico:
|
||||
logging.debug("prepare del_state found %s" % str(key))
|
||||
logging.debug("prepare del_filter found %s" % str(key))
|
||||
if dico[key]:
|
||||
self.state.setdefault(key, {})
|
||||
if dico[key] in self.state[key]:
|
||||
logging.debug("del1 del_state found [%s][%s][%s]" % (str(key), str(dico[key]), str(self.state[key])))
|
||||
del self.state[key][dico[key]]
|
||||
self.filter.setdefault(key, {})
|
||||
if dico[key] in self.filter[key]:
|
||||
logging.debug("del1 del_filter found [%s][%s][%s]" % (str(key), str(dico[key]), str(self.filter[key])))
|
||||
del self.filter[key][dico[key]]
|
||||
if self.egs_filter:
|
||||
res = self.egs_filter_load_character.match(msg)
|
||||
if res:
|
||||
logging.debug("egs_filter_load_character found")
|
||||
if len(self.state_load_character) < self.size_max_state:
|
||||
logging.debug("include add_state found")
|
||||
if len(self.filter_load_character) < self.size_max_filter:
|
||||
logging.debug("include add_filter found")
|
||||
dico = res.groupdict()
|
||||
try:
|
||||
self.state_load_character.setdefault(dico['UID'], {})
|
||||
self.state_load_character[dico['UID']].setdefault(dico['IDCHAR'], {'NameDomain': dico['NameDomain'], 'UIDBIS': dico['UIDBIS'], 'when': now})
|
||||
self.filter_load_character.setdefault(dico['UID'], {})
|
||||
self.filter_load_character[dico['UID']].setdefault(dico['IDCHAR'], {'NameDomain': dico['NameDomain'], 'UID': dico['UIDBIS'], 'when': now})
|
||||
except KeyError as e:
|
||||
logging.error('Missing key when read "load_character" (%s)' % e)
|
||||
else:
|
||||
|
@ -688,12 +702,12 @@ class ManageCommand():
|
|||
res = self.egs_filter_active_character.match(msg)
|
||||
if res:
|
||||
logging.debug("egs_filter_active_character found")
|
||||
if len(self.state_active_character) < self.size_max_state:
|
||||
if len(self.filter_active_character) < self.size_max_filter:
|
||||
dico = res.groupdict()
|
||||
try:
|
||||
self.state_active_character.setdefault(dico['UID'], {})
|
||||
self.state_active_character[dico['UID']] = self.state_load_character[dico['UID']][dico['IDCHAR']]
|
||||
del self.state_load_character[dico['UID']]
|
||||
self.filter_active_character.setdefault(dico['UID'], {})
|
||||
self.filter_active_character[dico['UID']] = self.filter_load_character[dico['UID']][dico['IDCHAR']]
|
||||
del self.filter_load_character[dico['UID']]
|
||||
except KeyError as e:
|
||||
logging.error('Missing key when read "active_character" (%s)' % e)
|
||||
else:
|
||||
|
@ -704,8 +718,8 @@ class ManageCommand():
|
|||
logging.debug("egs_filter_sid found")
|
||||
dico = res.groupdict()
|
||||
try:
|
||||
if dico['UID'] in self.state_active_character:
|
||||
self.state_active_character[dico['UID']].setdefault("SID", dico['SID'])
|
||||
if dico['UID'] in self.filter_active_character:
|
||||
self.filter_active_character[dico['UID']].setdefault("SID", dico['SID'])
|
||||
else:
|
||||
logging.error('Impossible to add SID on player %s (Player not found)' % dico['UID'])
|
||||
except KeyError as e:
|
||||
|
@ -716,28 +730,30 @@ class ManageCommand():
|
|||
logging.debug("egs_filter_sid found")
|
||||
dico = res.groupdict()
|
||||
try:
|
||||
if dico['UID'] in self.state_active_character:
|
||||
del self.state_active_character[dico['UID']]
|
||||
if dico['UID'] in self.filter_active_character:
|
||||
del self.filter_active_character[dico['UID']]
|
||||
else:
|
||||
logging.error('Impossible to remove player %s (Player not found)' % dico['UID'])
|
||||
except KeyError as e:
|
||||
logging.error('Missing key when remove player (%s)' % e)
|
||||
return
|
||||
res =self.egs_filter_admin.match(msg)
|
||||
res = self.egs_filter_admin.match(msg)
|
||||
if res:
|
||||
logging.debug("egs_filter_admin found")
|
||||
while len(self.state_admin) >= self.maxlog:
|
||||
self.state_admin.pop(0)
|
||||
while len(self.filter_admin) >= self.maxlog:
|
||||
print(self.pos_admin, self.pos_admin - self.maxlog )
|
||||
del self.filter_admin[self.pos_admin - self.maxlog]
|
||||
try:
|
||||
dico = res.groupdict()
|
||||
username = ''
|
||||
try:
|
||||
for key in self.state_active_character:
|
||||
if self.state_active_character[key]['SID'] == dico['SID']:
|
||||
username = self.state_active_character[key]['NameDomain']
|
||||
for key in self.filter_active_character:
|
||||
if self.filter_active_character[key]['SID'] == dico['SID']:
|
||||
username = self.filter_active_character[key]['NameDomain']
|
||||
break
|
||||
except KeyError:
|
||||
pass
|
||||
self.state_admin.append( {'pos': self.pos_admin, 'when': now, 'SID': dico['SID'], 'ACTION': dico['ACTION'], 'USER': username})
|
||||
self.filter_admin.setdefault( self.pos_admin, {'when': now, 'SID': dico['SID'], 'ACTION': dico['ACTION'], 'USER': username})
|
||||
except KeyError as e:
|
||||
logging.error('Missing key when admin player (%s)' % e)
|
||||
self.pos_admin = self.pos_admin + 1
|
||||
|
@ -789,9 +805,9 @@ class ManageCommand():
|
|||
if wait_semaphore == True:
|
||||
self.queueIn.put("STOPPED")
|
||||
self.semaphore.release()
|
||||
if self.keep_state:
|
||||
self.state_load_character = {}
|
||||
self.state_active_character = {}
|
||||
if self.activate_filter:
|
||||
self.filter_load_character = {}
|
||||
self.filter_active_character = {}
|
||||
logging.debug("End reader: '%s'" % self.name)
|
||||
|
||||
def restart(self):
|
||||
|
@ -812,14 +828,11 @@ class ManageCommand():
|
|||
self.semaphore.release()
|
||||
logging.debug('Prepare restart service %s (step 3)' % (self.name))
|
||||
|
||||
def handler(self, signum, frame):
|
||||
def receive_signal(self, signum, frame):
|
||||
""" Managed signal (not used) """
|
||||
if self.process:
|
||||
# logging.debug("Send signal %d to '%s'" %(signum, self.name))
|
||||
self.process.send_signal(signum)
|
||||
else:
|
||||
logging.error("Impossible to send signal %d to '%s'" % (signum, self.name))
|
||||
raise IOError("signal received")
|
||||
logging.info("Received signal %s (%d)" % (self.name, signum))
|
||||
self.queueIn.put("SHUTDOWN")
|
||||
self.queueIn.put("SHUTDOWN")
|
||||
|
||||
def start(self):
|
||||
""" Start program """
|
||||
|
@ -956,40 +969,40 @@ class ManageCommand():
|
|||
pos += 1
|
||||
outjson.setdefault('first-line', firstlinefound)
|
||||
outjson.setdefault('last-line', pos - 1)
|
||||
return json.dumps(outjson)
|
||||
return outjson
|
||||
|
||||
def getstate(self):
|
||||
""" Get state """
|
||||
return json.dumps(self.state)
|
||||
def getfilter(self):
|
||||
""" Get filter """
|
||||
return self.filter
|
||||
|
||||
def getconfig(self):
|
||||
outjson = { 'keep_state': str(self.keep_state),
|
||||
outjson = { 'activate_filter': str(self.activate_filter),
|
||||
'bufsize': str(self.bufsize),
|
||||
'size_max_state': str(self.size_max_state),
|
||||
'size_max_filter': str(self.size_max_filter),
|
||||
'path': str(self.path),
|
||||
'add_state': str(self.add_state_cmd),
|
||||
'del_state': str(self.del_state_cmd),
|
||||
'add_filter': str(self.add_filter_cmd),
|
||||
'del_filter': str(self.del_filter_cmd),
|
||||
'command': str(self.command),
|
||||
'maxWaitEnd': str(self.maxWaitEnd),
|
||||
'waitDelay': str(self.waitDelay),
|
||||
'maxlog': str(self.maxlog),
|
||||
'state': str(self.keep_state),
|
||||
'filter': str(self.activate_filter),
|
||||
'egs': str(self.egs_filter) }
|
||||
return json.dumps(outjson)
|
||||
return outjson
|
||||
|
||||
def getinfo(self):
|
||||
outjson = { 'number_launch': str(self.number_start),
|
||||
'first_line': str(self.first_line),
|
||||
'last_line': str(self.last_line),
|
||||
'number_state': len(self.state),
|
||||
'player_connected': len(self.state_active_character) }
|
||||
return json.dumps(outjson)
|
||||
'number_filter': len(self.filter),
|
||||
'player_connected': len(self.filter_active_character) }
|
||||
return outjson
|
||||
|
||||
def getplayer(self):
|
||||
return json.dumps(self.state_active_character)
|
||||
return self.filter_active_character
|
||||
|
||||
def getadmincommand(self):
|
||||
return json.dumps(self.state_admin)
|
||||
return self.filter_admin
|
||||
|
||||
def action(self, action):
|
||||
""" Send action to program (send input to stdin) """
|
||||
|
@ -1005,6 +1018,8 @@ class ManageCommand():
|
|||
|
||||
def run(self):
|
||||
""" loop, run child (wait command) """
|
||||
signal.signal(signal.SIGABRT, self.receive_signal)
|
||||
signal.signal(signal.SIGTERM, self.receive_signal)
|
||||
statuscmd = {0:'started', 1:'stopped', 2:'crashed'}
|
||||
loop = True
|
||||
if self.autostart:
|
||||
|
@ -1022,18 +1037,22 @@ class ManageCommand():
|
|||
elif command == "START":
|
||||
#if savedstate != 0:
|
||||
savedstate = self.start()
|
||||
self.queueOut.put(statuscmd[savedstate])
|
||||
self.queueOut.put({'state': statuscmd[savedstate]})
|
||||
elif command == "STATUS":
|
||||
currentstate = self.status()
|
||||
if currentstate != 1 or savedstate != 2:
|
||||
savedstate = currentstate
|
||||
self.queueOut.put(statuscmd[savedstate])
|
||||
self.queueOut.put({'state': statuscmd[savedstate],
|
||||
'last_line': str(self.last_line),
|
||||
'number_launch': str(self.number_start),
|
||||
'filter': str(self.activate_filter),
|
||||
'egs': str(self.egs_filter)})
|
||||
elif command == "STOP":
|
||||
savedstate = self.stop()
|
||||
self.queueOut.put(statuscmd[savedstate])
|
||||
self.queueOut.put({'state': statuscmd[savedstate]})
|
||||
elif command == "STDIN":
|
||||
data = msg.split(maxsplit=1)[1]
|
||||
self.queueOut.put(self.action(data))
|
||||
self.queueOut.put({'state': self.action(data)})
|
||||
elif command == "STDOUT":
|
||||
try:
|
||||
firstline = int(msg.split(maxsplit=1)[1])
|
||||
|
@ -1043,8 +1062,8 @@ class ManageCommand():
|
|||
except IndexError:
|
||||
firstline = 0
|
||||
self.queueOut.put(self.getlog(firstline))
|
||||
elif command == "STATE":
|
||||
self.queueOut.put(self.getstate())
|
||||
elif command == "FILTER":
|
||||
self.queueOut.put(self.getfilter())
|
||||
elif command == "CONFIG":
|
||||
self.queueOut.put(self.getconfig())
|
||||
elif command == "INFO":
|
||||
|
@ -1072,7 +1091,7 @@ class ManageCommand():
|
|||
self.threadRestart.start()
|
||||
else:
|
||||
logging.warning("Bad command (%s)" % command)
|
||||
self.queueOut.put("error : command unknown")
|
||||
self.queueOut.put( {"error" : "command unknown"} )
|
||||
logging.debug('Stop %s' % self.name)
|
||||
self.stop()
|
||||
logging.debug('prepare end')
|
||||
|
@ -1211,42 +1230,42 @@ class Manager():
|
|||
raise ValueError
|
||||
else:
|
||||
bufsize = 100
|
||||
if 'keep_state' in config[name]:
|
||||
if 'activate_filter' in config[name]:
|
||||
try:
|
||||
tmp = config[name]['keep_state']
|
||||
tmp = config[name]['activate_filter']
|
||||
if tmp.upper().strip() == 'YES':
|
||||
keep_state = True
|
||||
activate_filter = True
|
||||
else:
|
||||
keep_state = False
|
||||
activate_filter = False
|
||||
except (TypeError, KeyError, ValueError):
|
||||
logging.error("Impossible to read param keep_state (command:%s)", name)
|
||||
logging.error("Impossible to read param activate_filter (command:%s)", name)
|
||||
raise ValueError
|
||||
else:
|
||||
keep_state = False
|
||||
if 'size_max_state' in config[name]:
|
||||
activate_filter = False
|
||||
if 'size_max_filter' in config[name]:
|
||||
try:
|
||||
size_max_state = int(config[name]['size_max_state'])
|
||||
size_max_filter = int(config[name]['size_max_filter'])
|
||||
except (TypeError, KeyError, ValueError):
|
||||
logging.error("Impossible to read param size_max_state (command:%s)", name)
|
||||
logging.error("Impossible to read param size_max_filter (command:%s)", name)
|
||||
raise ValueError
|
||||
else:
|
||||
size_max_state = 100
|
||||
if 'add_state' in config[name]:
|
||||
size_max_filter = 100
|
||||
if 'add_filter' in config[name]:
|
||||
try:
|
||||
add_state = config[name]['add_state']
|
||||
add_filter = config[name]['add_filter']
|
||||
except (TypeError, KeyError, ValueError):
|
||||
logging.error("Impossible to read param add_state (command:%s)", name)
|
||||
logging.error("Impossible to read param add_filter (command:%s)", name)
|
||||
raise ValueError
|
||||
else:
|
||||
add_state = ''
|
||||
if 'del_state' in config[name]:
|
||||
add_filter = ''
|
||||
if 'del_filter' in config[name]:
|
||||
try:
|
||||
del_state = config[name]['del_state']
|
||||
del_filter = config[name]['del_filter']
|
||||
except (TypeError, KeyError, ValueError):
|
||||
logging.error("Impossible to read param del_state (command:%s)", name)
|
||||
logging.error("Impossible to read param del_filter (command:%s)", name)
|
||||
raise ValueError
|
||||
else:
|
||||
del_state = ''
|
||||
del_filter = ''
|
||||
if 'autostart' in config[name]:
|
||||
try:
|
||||
tmp = config[name]['autostart']
|
||||
|
@ -1295,10 +1314,10 @@ class Manager():
|
|||
'path': path,
|
||||
'logsize': logsize,
|
||||
'bufsize': bufsize,
|
||||
'keep_state': keep_state,
|
||||
'size_max_state': size_max_state,
|
||||
'add_state': add_state,
|
||||
'del_state': del_state,
|
||||
'activate_filter': activate_filter,
|
||||
'size_max_filter': size_max_filter,
|
||||
'add_filter': add_filter,
|
||||
'del_filter': del_filter,
|
||||
'autostart': autostart,
|
||||
'restart_after_crash': restart_after_crash,
|
||||
'restart_delay': restart_delay,
|
||||
|
@ -1308,6 +1327,7 @@ class Manager():
|
|||
"""
|
||||
Initialize object serverHttp
|
||||
"""
|
||||
logging.debug("Initialize server http(s)")
|
||||
self.serverHttp = ServerHttp(self.keyfile,
|
||||
self.certfile,
|
||||
self.ca_cert,
|
||||
|
@ -1318,7 +1338,7 @@ class Manager():
|
|||
users=self.users)
|
||||
|
||||
def runCommand(self, name, command, path, logsize, bufsize, queueIn, queueOut, semaphore,
|
||||
keep_state, size_max_state, add_state, del_state,
|
||||
activate_filter, size_max_filter, add_filter, del_filter,
|
||||
autostart, restart_after_crash, restart_delay, egs_filter):
|
||||
"""
|
||||
Thread to manage khaganat program
|
||||
|
@ -1332,10 +1352,10 @@ class Manager():
|
|||
queueIn=queueIn,
|
||||
queueOut=queueOut,
|
||||
semaphore=semaphore,
|
||||
keep_state=keep_state,
|
||||
size_max_state=size_max_state,
|
||||
add_state=add_state,
|
||||
del_state=del_state,
|
||||
activate_filter=activate_filter,
|
||||
size_max_filter=size_max_filter,
|
||||
add_filter=add_filter,
|
||||
del_filter=del_filter,
|
||||
autostart=autostart,
|
||||
restart_after_crash=restart_after_crash,
|
||||
restart_delay=restart_delay,
|
||||
|
@ -1355,7 +1375,7 @@ class Manager():
|
|||
queueOut = multiprocessing.Queue()
|
||||
# semaphore = multiprocessing.Semaphore()
|
||||
semaphore = multiprocessing.BoundedSemaphore()
|
||||
self.serverHttp.append(name, queueIn, queueOut, semaphore)
|
||||
self.serverHttp.appendchild(name, queueIn, queueOut, semaphore)
|
||||
if self.launch_program:
|
||||
autostart = True
|
||||
else:
|
||||
|
@ -1369,10 +1389,10 @@ class Manager():
|
|||
queueIn,
|
||||
queueOut,
|
||||
semaphore,
|
||||
self.param[name]['keep_state'],
|
||||
self.param[name]['size_max_state'],
|
||||
self.param[name]['add_state'],
|
||||
self.param[name]['del_state'],
|
||||
self.param[name]['activate_filter'],
|
||||
self.param[name]['size_max_filter'],
|
||||
self.param[name]['add_filter'],
|
||||
self.param[name]['del_filter'],
|
||||
autostart,
|
||||
self.param[name]['restart_after_crash'],
|
||||
self.param[name]['restart_delay'],
|
||||
|
@ -1387,10 +1407,10 @@ class Manager():
|
|||
'path': self.param[name]['path'],
|
||||
'logsize': self.param[name]['logsize'],
|
||||
'bufsize': self.param[name]['bufsize'],
|
||||
'keep_state': self.param[name]['keep_state'],
|
||||
'size_max_state': self.param[name]['size_max_state'],
|
||||
'add_state': self.param[name]['add_state'],
|
||||
'del_state': self.param[name]['del_state'],
|
||||
'activate_filter': self.param[name]['activate_filter'],
|
||||
'size_max_filter': self.param[name]['size_max_filter'],
|
||||
'add_filter': self.param[name]['add_filter'],
|
||||
'del_filter': self.param[name]['del_filter'],
|
||||
'autostart': autostart,
|
||||
'restart_after_crash': self.param[name]['restart_after_crash'],
|
||||
'restart_delay': self.param[name]['restart_delay'],
|
||||
|
@ -1398,10 +1418,19 @@ class Manager():
|
|||
|
||||
def receive_signal(self, signum, frame):
|
||||
""" Managed signal """
|
||||
logging.info("Received signal (%d)" % (signum))
|
||||
for child in self.threadCommand:
|
||||
logging.info("send signal to child %s" % (child.name))
|
||||
try:
|
||||
child.terminate()
|
||||
child.join()
|
||||
except AttributeError:
|
||||
logging.info("child not started")
|
||||
pass
|
||||
if self.serverHttp:
|
||||
logging.info("send signal to server http")
|
||||
self.serverHttp.terminate()
|
||||
logging.info("Finalize signal (%d)" % (signum))
|
||||
|
||||
def wait_children_commands(self):
|
||||
for child in self.threadCommand:
|
||||
|
@ -1413,6 +1442,8 @@ class Manager():
|
|||
|
||||
def run(self):
|
||||
""" launch all """
|
||||
signal.signal(signal.SIGABRT, self.receive_signal)
|
||||
signal.signal(signal.SIGTERM, self.receive_signal)
|
||||
self.launch_command()
|
||||
self.launch_server_http()
|
||||
logging.info('started')
|
||||
|
@ -1478,6 +1509,7 @@ def main(args=sys.argv[1:]):
|
|||
logLevel=param.log,
|
||||
launch_program=param.launch_program,
|
||||
show_log_console=param.show_log_console)
|
||||
logging.debug("End")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -73,6 +73,12 @@ class SimulateProgram():
|
|||
if pos > n:
|
||||
self.print_output("alpha finalizeClientReady EGS-132 : Updating IS_NEWBIE flag for character: (0x0000000021:00:00:81)")
|
||||
n = n + 1
|
||||
if pos > n:
|
||||
self.print_output("cbClientAdmin EGS-136 : ADMIN: Player (0x0000000021:00:00:81) doesn't have privilege to execute the client admin command 'infos'")
|
||||
n = n + 1
|
||||
if pos > n:
|
||||
self.print_output("cbClientAdmin EGS-136 : ADMIN: Player (0x0000000021:00:00:81) tried to execute a no valid client admin command 'INFO'")
|
||||
n = n + 1
|
||||
if pos > n:
|
||||
self.print_output("alpha 1383 disconnectPlayer EGS-132 : (EGS) player 2 (Row 90501) removed")
|
||||
n = n + 1
|
||||
|
|
|
@ -28,7 +28,6 @@ import queue
|
|||
import signal
|
||||
import http.server
|
||||
import logging
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock
|
||||
import traceback
|
||||
|
@ -47,6 +46,9 @@ except ImportError:
|
|||
# sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
# import pymanager.certificate as cert
|
||||
|
||||
class TimeoutError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def handlerCrash(signum, frame):
|
||||
print("handlerCrash - TimeOut !")
|
||||
|
@ -60,7 +62,7 @@ def handlerRaise(signum, frame):
|
|||
print("handlerRaise - TimeOut !")
|
||||
for line in traceback.format_stack():
|
||||
print(line.strip())
|
||||
raise "Timeout"
|
||||
raise TimeoutError
|
||||
|
||||
class TestManager(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -103,10 +105,10 @@ class TestManager(unittest.TestCase):
|
|||
config.set('command:test', 'command', '/bin/sleep 10')
|
||||
config.set('command:test', 'logsize', '10')
|
||||
config.set('command:test', 'bufsize', '10')
|
||||
config.set('command:test', 'keep_state', 'yes')
|
||||
config.set('command:test', 'size_max_state', '1000')
|
||||
config.set('command:test', 'add_state', '"^(.*)(setActiveCharForPlayer).*(: set active char )[\d]+( for )(?P<ActivePlayer>.*)"')
|
||||
config.set('command:test', 'del_state', '"^(.*)(disconnectPlayer).+[\s]+(?P<ActivePlayer>.*)[\s]+(is disconnected)"')
|
||||
config.set('command:test', 'keep_filter', 'yes')
|
||||
config.set('command:test', 'size_max_filter', '1000')
|
||||
config.set('command:test', 'add_filter', '"^(.*)(setActiveCharForPlayer).*(: set active char )[\d]+( for )(?P<ActivePlayer>.*)"')
|
||||
config.set('command:test', 'del_filter', '"^(.*)(disconnectPlayer).+[\s]+(?P<ActivePlayer>.*)[\s]+(is disconnected)"')
|
||||
config.add_section('config:user')
|
||||
config.set('config:user', 'usename', 'filter_all, filter_admin')
|
||||
try:
|
||||
|
@ -267,37 +269,42 @@ class TestManager(unittest.TestCase):
|
|||
True)
|
||||
manage._analyze_line("message 1")
|
||||
manage._analyze_line("alpha egs_plinfo EGS-132 : LOADED User '2' Character 'Kezxaa(Lirria)' from BS stream file 'characters/002/account_2_0_pdr.bin'")
|
||||
if '2' not in manage.state_load_character:
|
||||
if '2' not in manage.filter_load_character:
|
||||
self.assertTrue(False, "LOADED - Missing player 2")
|
||||
if '0' not in manage.state_load_character['2']:
|
||||
if '0' not in manage.filter_load_character['2']:
|
||||
self.assertTrue(False, "LOADED - Missing charactere 0 for player 2")
|
||||
manage._analyze_line("alpha egs_plinfo EGS-132 : LOADED User '2' Character 'Puskle(Lirria)' from BS stream file 'characters/002/account_2_1_pdr.bin'")
|
||||
if '1' not in manage.state_load_character['2']:
|
||||
if '1' not in manage.filter_load_character['2']:
|
||||
self.assertTrue(False, "LOADED - Missing charactere 1 for player 2")
|
||||
manage._analyze_line("alpha egs_plinfo EGS-132 : LOADED User '3' Character 'Puskle(Lirria)' from BS stream file 'characters/003/account_3_4_pdr.bin'")
|
||||
if '3' not in manage.state_load_character:
|
||||
if '3' not in manage.filter_load_character:
|
||||
self.assertTrue(False, "LOADED - Missing player 2")
|
||||
manage._analyze_line("alpha egs_ecinfo EGS-132 : setActiveCharForPlayer EGS-132 : set active char 1 for player 2")
|
||||
if '2' not in manage.state_active_character:
|
||||
if '2' not in manage.filter_active_character:
|
||||
self.assertTrue(False, "setActiveCharForPlayer - Missing player 2")
|
||||
if 'NameDomain' not in manage.state_active_character['2']:
|
||||
if 'NameDomain' not in manage.filter_active_character['2']:
|
||||
self.assertTrue(False, "setActiveCharForPlayer - Missing info player 2")
|
||||
manage._analyze_line("alpha egs_ecinfo EGS-132 : Mapping UID 2 => Sid (0x0000000021:00:00:81)")
|
||||
if 'SID' not in manage.state_active_character['2']:
|
||||
manage._analyze_line("alpha egs_ecinfo EGS-132 : Mapping UID 2 => Sid (0x0000000021:00:00:83)")
|
||||
if 'SID' not in manage.filter_active_character['2']:
|
||||
self.assertTrue(False, "setActiveCharForPlayer - Missing SID player 2")
|
||||
manage._analyze_line("alpha egs_ecinfo EGS-132 : Client ready (entity (0x0000000021:00:00:81) (Row 90501) added to mirror)")
|
||||
manage._analyze_line("alpha finalizeClientReady EGS-132 : Updating IS_NEWBIE flag for character: (0x0000000021:00:00:81)")
|
||||
manage._analyze_line("alpha egs_ecinfo EGS-132 : Client ready (entity (0x0000000021:00:00:83) (Row 90501) added to mirror)")
|
||||
manage._analyze_line("alpha finalizeClientReady EGS-132 : Updating IS_NEWBIE flag for character: (0x0000000021:00:00:83)")
|
||||
manage._analyze_line("alpha 1383 disconnectPlayer EGS-132 : (EGS) player 2 (Row 90501) removed")
|
||||
manage._analyze_line("alpha egs_plinfo EGS-132 : Player with userId = 2 removed")
|
||||
manage._analyze_line("cbClientAdmin EGS-133 : ADMIN: Player (0x0000000021:00:00:83) doesn't have privilege to execute the client admin command 'infos'")
|
||||
manage._analyze_line("cbClientAdmin EGS-133 : ADMIN: Player (0x0000000021:00:00:83) tried to execute a no valid client admin command 'INFO'")
|
||||
for i in range(0, 2000):
|
||||
manage._analyze_line("cbClientAdmin EGS-133 : ADMIN: Player (0x0000000021:00:00:83) tried to execute a no valid client admin command 'INFO' %d" % i)
|
||||
self.assertTrue(len(manage.filter_admin), 1000)
|
||||
manage._analyze_line("alpha disconnectPlayer EGS-132 : player 2 is disconnected")
|
||||
if '2' in manage.state_active_character:
|
||||
if '2' in manage.filter_active_character:
|
||||
self.assertTrue(False, "disconnectPlayer - player 2 always live")
|
||||
|
||||
def test_manager_command_player(self):
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(30)
|
||||
class MockServerHttp:
|
||||
def append(self, name, queueIn, queueOut, semaphore):
|
||||
def appendchild(self, name, queueIn, queueOut, semaphore):
|
||||
pass
|
||||
def terminate(self):
|
||||
pass
|
||||
|
@ -317,6 +324,7 @@ class TestManager(unittest.TestCase):
|
|||
manage._load_config(config)
|
||||
manage.launch_command()
|
||||
|
||||
signal.alarm(10)
|
||||
key = list(manage.info.keys())[0]
|
||||
queueIn = manage.info[key]['queueIn']
|
||||
queueOut = manage.info[key]['queueOut']
|
||||
|
@ -325,29 +333,26 @@ class TestManager(unittest.TestCase):
|
|||
signal.alarm(30)
|
||||
item = "started"
|
||||
while item == "started":
|
||||
print("sleep")
|
||||
logging.debug("sleep")
|
||||
time.sleep(1)
|
||||
print("semaphore")
|
||||
logging.debug("semaphore")
|
||||
semaphore.acquire()
|
||||
print("status")
|
||||
logging.debug("status")
|
||||
queueIn.put("STATUS")
|
||||
print("queue")
|
||||
item = queueOut.get(timeout=4)
|
||||
print(item)
|
||||
semaphore.release()
|
||||
print("Lecture STDOUT")
|
||||
print("sleep")
|
||||
time.sleep(1)
|
||||
signal.alarm(30)
|
||||
print("semaphore")
|
||||
semaphore.acquire()
|
||||
print("stdout")
|
||||
queueIn.put("STDOUT")
|
||||
print("Attend le retour STDOUT")
|
||||
logging.debug("queue")
|
||||
item = queueOut.get()
|
||||
semaphore.release()
|
||||
print("Resultat STDOUT")
|
||||
print(item)
|
||||
logging.debug("Lecture STDOUT")
|
||||
time.sleep(1)
|
||||
signal.alarm(30)
|
||||
logging.debug("semaphore")
|
||||
semaphore.acquire()
|
||||
logging.debug("stdout")
|
||||
queueIn.put("STDOUT")
|
||||
logging.debug("Attend le retour STDOUT")
|
||||
item = queueOut.get()
|
||||
semaphore.release()
|
||||
logging.debug("Resultat STDOUT")
|
||||
time.sleep(1)
|
||||
signal.alarm(10)
|
||||
semaphore.acquire()
|
||||
|
@ -362,17 +367,26 @@ class TestManager(unittest.TestCase):
|
|||
signal.alarm(0)
|
||||
self.assertTrue(True)
|
||||
signal.alarm(0)
|
||||
except:
|
||||
except TimeoutError:
|
||||
print("Prepare Crash - TimeOut !")
|
||||
#self.fail('Error initialize object ManageCommand')
|
||||
manage.receive_signal(15, 1)
|
||||
manage.wait_children_commands()
|
||||
print("Force Crash - TimeOut !")
|
||||
os._exit(2)
|
||||
except Exception as e:
|
||||
print("Prepare Crash - %s" % e)
|
||||
#self.fail('Error initialize object ManageCommand')
|
||||
manage.receive_signal(15, 1)
|
||||
manage.wait_children_commands()
|
||||
handlerCrash(15, 1)
|
||||
print("Force Crash - TimeOut !")
|
||||
os._exit(2)
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(0)
|
||||
signal.signal(signal.SIGALRM, handlerCrash)
|
||||
|
||||
def test_execute_manager_command(self):
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(10)
|
||||
try:
|
||||
logsize = 10
|
||||
|
@ -406,10 +420,10 @@ class TestManager(unittest.TestCase):
|
|||
while loop > 0:
|
||||
time.sleep(1)
|
||||
out = manageCommand.getlog(0)
|
||||
if foundEnd.match(out):
|
||||
if foundEnd.match(str(out)):
|
||||
break
|
||||
loop -= 1
|
||||
if not foundEnd.match(out):
|
||||
if not foundEnd.match(str(out)):
|
||||
manageCommand.stop()
|
||||
self.assertTrue(False, 'Missing message in log')
|
||||
manageCommand.list_thread()
|
||||
|
@ -424,10 +438,10 @@ class TestManager(unittest.TestCase):
|
|||
while loop > 0:
|
||||
time.sleep(1)
|
||||
out = manageCommand.getlog(0)
|
||||
if foundY.match(out):
|
||||
if foundY.match(str(out)):
|
||||
break
|
||||
loop -= 1
|
||||
if not foundY.match(out):
|
||||
if not foundY.match(str(out)):
|
||||
manageCommand.stop()
|
||||
self.assertTrue(False, 'Missing message in log')
|
||||
|
||||
|
@ -439,9 +453,11 @@ class TestManager(unittest.TestCase):
|
|||
self.assertTrue(True)
|
||||
except:
|
||||
self.fail('Error initialize object ManageCommand')
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(0)
|
||||
|
||||
def test_execute_crash_manager_command(self):
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(10)
|
||||
try:
|
||||
logsize = 10
|
||||
|
@ -480,10 +496,12 @@ class TestManager(unittest.TestCase):
|
|||
self.assertTrue(True)
|
||||
except:
|
||||
self.fail('Error initialize object ManageCommand')
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(0)
|
||||
|
||||
def test_execute_not_kill_manager_command(self):
|
||||
signal.alarm(30)
|
||||
signal.signal(signal.SIGALRM, handlerCrash)
|
||||
try:
|
||||
logsize = 10
|
||||
bufsize = 10
|
||||
|
@ -519,9 +537,8 @@ class TestManager(unittest.TestCase):
|
|||
self.assertEqual(res, 0)
|
||||
res = manageCommand.getlog(0)
|
||||
try:
|
||||
resjson = json.loads(res)
|
||||
if 'last-line' in res:
|
||||
if resjson['last-line'] == 5:
|
||||
if res['last-line'] == 5:
|
||||
wait = False
|
||||
except:
|
||||
pass
|
||||
|
@ -532,6 +549,7 @@ class TestManager(unittest.TestCase):
|
|||
self.assertTrue(True)
|
||||
except Exception as e:
|
||||
self.fail('Error when run test (%s)' % str(e))
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(0)
|
||||
|
||||
def test_execute_command_crashed(self):
|
||||
|
@ -658,10 +676,10 @@ class TestManager(unittest.TestCase):
|
|||
queueIn=queueIn,
|
||||
queueOut=queueOut,
|
||||
semaphore=semaphore,
|
||||
keep_state=False,
|
||||
size_max_state=1,
|
||||
add_state="",
|
||||
del_state="",
|
||||
keep_filter=False,
|
||||
size_max_filter=1,
|
||||
add_filter="",
|
||||
del_filter="",
|
||||
autostart=False,
|
||||
restart_after_crash=False,
|
||||
restart_delay=1,
|
||||
|
@ -691,11 +709,15 @@ class TestManager(unittest.TestCase):
|
|||
signal.alarm(0)
|
||||
|
||||
def test_main(self):
|
||||
signal.signal(signal.SIGALRM, handlerCrash)
|
||||
signal.alarm(10)
|
||||
config = tempfile.NamedTemporaryFile(suffix="password.cfg", mode='w+t')
|
||||
config.write('[config:server]\nauthentification=no\n')
|
||||
config.flush()
|
||||
logging.debug("load")
|
||||
Manager.main(['--conf=' + config.name])
|
||||
logging.debug("end")
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(0)
|
||||
|
||||
def test_run_manager_command(self):
|
||||
|
@ -703,7 +725,7 @@ class TestManager(unittest.TestCase):
|
|||
signal.signal(signal.SIGALRM, handlerCrash)
|
||||
signal.alarm(10)
|
||||
class MockServerHttp:
|
||||
def append(self, name, queueIn, queueOut, semaphore):
|
||||
def appendchild(self, name, queueIn, queueOut, semaphore):
|
||||
pass
|
||||
def terminate(self):
|
||||
pass
|
||||
|
@ -730,9 +752,9 @@ class TestManager(unittest.TestCase):
|
|||
queueIn.put("START")
|
||||
# Enable timeout
|
||||
signal.alarm(10)
|
||||
item = queueOut.get(timeout=4)
|
||||
item = queueOut.get()
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "started", 'Error impossible to start program')
|
||||
self.assertEqual(item['state'], 'started', 'Error impossible to start program')
|
||||
signal.alarm(0)
|
||||
time.sleep(1)
|
||||
logging.debug("[2] --------- send STATUS")
|
||||
|
@ -741,7 +763,7 @@ class TestManager(unittest.TestCase):
|
|||
queueIn.put("STATUS")
|
||||
item = queueOut.get()
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "started", 'Error impossible to read status')
|
||||
self.assertEqual(item['state'], 'started', 'Error impossible to read status')
|
||||
signal.alarm(0)
|
||||
time.sleep(1)
|
||||
logging.debug("[3] --------- send STDIN arg")
|
||||
|
@ -750,7 +772,7 @@ class TestManager(unittest.TestCase):
|
|||
queueIn.put("STDIN arg")
|
||||
item = queueOut.get()
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "ok", 'Error when send STDIN')
|
||||
self.assertEqual(item['state'], 'ok', 'Error when send STDIN')
|
||||
signal.alarm(0)
|
||||
time.sleep(1)
|
||||
logging.debug("[4] --------- send STDOUT 4")
|
||||
|
@ -765,14 +787,12 @@ class TestManager(unittest.TestCase):
|
|||
logging.debug("[4.4] --------- send STDOUT 4")
|
||||
signal.alarm(0)
|
||||
logging.debug("[4.5] --------- send STDOUT 4")
|
||||
self.assertRegex(item,
|
||||
'^[{](.*)("first-line": 4)(.*)[}]$',
|
||||
'Error when read STDOUT (Missing first-line)')
|
||||
self.assertRegex(item,
|
||||
'^[{](.*)("last-line": 6)(.*)[}]$',
|
||||
'Error when read STDOUT (Missing last-line)')
|
||||
self.assertRegex(item,
|
||||
'^[{](.*)(6 arg")(.*)[}]$',
|
||||
self.assertEqual(item['first-line'], 4, 'Error when read STDOUT (Missing first-line)')
|
||||
self.assertEqual(item['last-line'], 6, 'Error when read STDOUT (Missing first-line)')
|
||||
# self.assertRegex(item, '^[{](.*)("first-line": 4)(.*)[}]$', 'Error when read STDOUT (Missing first-line)')
|
||||
# self.assertRegex(item, '^[{](.*)("last-line": 6)(.*)[}]$', 'Error when read STDOUT (Missing last-line)')
|
||||
self.assertRegex(str(item),
|
||||
'^(.*)(6 arg)(.*)$',
|
||||
'Error when read STDOUT (bad record)')
|
||||
time.sleep(1)
|
||||
logging.debug("[5] --------- send BADCOMMAND")
|
||||
|
@ -781,7 +801,7 @@ class TestManager(unittest.TestCase):
|
|||
queueIn.put("BADCOMMAND")
|
||||
item = queueOut.get()
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "error : command unknown", 'Error impossible to read status')
|
||||
self.assertEqual(item['error'], 'command unknown', 'Error impossible to read status')
|
||||
signal.alarm(0)
|
||||
time.sleep(1)
|
||||
logging.debug("[6] --------- send STOP")
|
||||
|
@ -790,7 +810,7 @@ class TestManager(unittest.TestCase):
|
|||
queueIn.put("STOP")
|
||||
item = queueOut.get()
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "stopped", 'Error impossible to read status')
|
||||
self.assertEqual(item["state"], "stopped", 'Error impossible to read status')
|
||||
signal.alarm(0)
|
||||
time.sleep(1)
|
||||
logging.debug("[7] --------- send SHUTDOWN")
|
||||
|
@ -816,13 +836,13 @@ class TestManager(unittest.TestCase):
|
|||
print("test_run_manager_command - Force Crash - TimeOut !")
|
||||
os._exit(2)
|
||||
signal.alarm(0)
|
||||
signal.signal(signal.SIGALRM, handlerCrash)
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
|
||||
def test_run_manager_command_autostart(self):
|
||||
# Enable timeout
|
||||
signal.alarm(10)
|
||||
class MockServerHttp:
|
||||
def append(self, name, queueIn, queueOut, semaphore):
|
||||
def appendchild(self, name, queueIn, queueOut, semaphore):
|
||||
pass
|
||||
def terminate(self):
|
||||
pass
|
||||
|
@ -848,7 +868,7 @@ class TestManager(unittest.TestCase):
|
|||
queueIn.put("STATUS")
|
||||
item = queueOut.get(timeout=4)
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "started", 'Error impossible to read status')
|
||||
self.assertEqual(item['state'], "started", 'Error impossible to read status')
|
||||
time.sleep(1)
|
||||
signal.alarm(10)
|
||||
semaphore.acquire()
|
||||
|
@ -866,9 +886,10 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
def test_run_manager_command_autostart_option(self):
|
||||
# Enable timeout
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(10)
|
||||
class MockServerHttp:
|
||||
def append(self, name, queueIn, queueOut, semaphore):
|
||||
def appendchild(self, name, queueIn, queueOut, semaphore):
|
||||
pass
|
||||
def terminate(self):
|
||||
pass
|
||||
|
@ -881,6 +902,7 @@ class TestManager(unittest.TestCase):
|
|||
config.set('command:test', 'autostart', 'yes')
|
||||
|
||||
manage = Manager.Manager(False)
|
||||
try:
|
||||
manage.serverHttp = MockServerHttp()
|
||||
manage._load_config(config)
|
||||
manage.launch_command()
|
||||
|
@ -896,7 +918,7 @@ class TestManager(unittest.TestCase):
|
|||
queueIn.put("STATUS")
|
||||
item = queueOut.get(timeout=4)
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "started", 'program not started')
|
||||
self.assertEqual(item["state"], "started", 'program not started')
|
||||
time.sleep(1)
|
||||
signal.alarm(10)
|
||||
semaphore.acquire()
|
||||
|
@ -909,16 +931,32 @@ class TestManager(unittest.TestCase):
|
|||
manage.wait_children_commands()
|
||||
#Disable timeout
|
||||
signal.alarm(0)
|
||||
except TimeoutError:
|
||||
print("test_run_manager_command_restart_after_crash - Prepare Crash - TimeOut !")
|
||||
#self.fail('Error initialize object ManageCommand')
|
||||
manage.receive_signal(15, 1)
|
||||
manage.wait_children_commands()
|
||||
print("test_run_manager_command_restart_after_crash - Force Crash - TimeOut !")
|
||||
os._exit(2)
|
||||
except Exception as e:
|
||||
print("test_run_manager_command_restart_after_crash - Prepare Crash - %s" % e)
|
||||
#self.fail('Error initialize object ManageCommand')
|
||||
manage.receive_signal(15, 1)
|
||||
manage.wait_children_commands()
|
||||
handlerCrash(15, 1)
|
||||
print("test_run_manager_command_restart_after_crash - Force Crash - TimeOut !")
|
||||
os._exit(2)
|
||||
self.assertTrue(True)
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(0)
|
||||
|
||||
def test_run_manager_command_restart_after_crash(self):
|
||||
# Enable timeout
|
||||
signal.signal(signal.SIGALRM, handlerCrash)
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(10)
|
||||
logging.debug("--------- test_run_manager_command_restart_after_crash => Start")
|
||||
class MockServerHttp:
|
||||
def append(self, name, queueIn, queueOut, semaphore):
|
||||
def appendchild(self, name, queueIn, queueOut, semaphore):
|
||||
pass
|
||||
def terminate(self):
|
||||
pass
|
||||
|
@ -946,22 +984,21 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
logging.debug("--------- wait not started")
|
||||
signal.alarm(20)
|
||||
item = "started"
|
||||
while item == "started":
|
||||
item = {"state": "started"}
|
||||
while item['state'] == "started":
|
||||
time.sleep(1)
|
||||
semaphore.acquire()
|
||||
queueIn.put("STATUS")
|
||||
try:
|
||||
item = queueOut.get(timeout=4)
|
||||
item = queueOut.get()
|
||||
except queue.Empty:
|
||||
pass
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "crashed", 'program not started')
|
||||
self.assertEqual(item['state'], "crashed", 'program not started')
|
||||
signal.alarm(20)
|
||||
|
||||
logging.debug("--------- wait not crashed")
|
||||
# item = "crashed"
|
||||
while item == "crashed":
|
||||
while item['state'] == "crashed":
|
||||
time.sleep(1)
|
||||
semaphore.acquire()
|
||||
queueIn.put("STATUS")
|
||||
|
@ -972,12 +1009,11 @@ class TestManager(unittest.TestCase):
|
|||
semaphore.release()
|
||||
signal.alarm(20)
|
||||
|
||||
self.assertEqual(item, "started", 'program not started')
|
||||
self.assertEqual(item['state'], "started", 'program not started')
|
||||
|
||||
logging.debug("--------- wait not started")
|
||||
signal.alarm(20)
|
||||
item = "started"
|
||||
while item == "started":
|
||||
while item['state'] == "started":
|
||||
time.sleep(1)
|
||||
semaphore.acquire()
|
||||
queueIn.put("STATUS")
|
||||
|
@ -986,20 +1022,17 @@ class TestManager(unittest.TestCase):
|
|||
except queue.Empty:
|
||||
pass
|
||||
semaphore.release()
|
||||
self.assertEqual(item, "crashed", 'program not started')
|
||||
signal.alarm(20)
|
||||
|
||||
self.assertEqual(item, "crashed", 'program not started')
|
||||
self.assertEqual(item['state'], "crashed", 'program not started')
|
||||
signal.alarm(20)
|
||||
|
||||
logging.debug("--------- wait not crashed")
|
||||
# item = "crashed"
|
||||
while item == "crashed":
|
||||
while item['state'] == "crashed":
|
||||
time.sleep(1)
|
||||
semaphore.acquire()
|
||||
queueIn.put("STATUS")
|
||||
try:
|
||||
item = queueOut.get(timeout=4)
|
||||
item = queueOut.get()
|
||||
except queue.Empty:
|
||||
pass
|
||||
semaphore.release()
|
||||
|
@ -1016,14 +1049,23 @@ class TestManager(unittest.TestCase):
|
|||
manage.wait_children_commands()
|
||||
#Disable timeout
|
||||
signal.alarm(0)
|
||||
except:
|
||||
print("Prepare Crash - TimeOut !")
|
||||
except TimeoutError:
|
||||
print("test_run_manager_command_restart_after_crash - Prepare Crash - TimeOut !")
|
||||
#self.fail('Error initialize object ManageCommand')
|
||||
manage.receive_signal(15, 1)
|
||||
manage.wait_children_commands()
|
||||
print("Force Crash - TimeOut !")
|
||||
print("test_run_manager_command_restart_after_crash - Force Crash - TimeOut !")
|
||||
os._exit(2)
|
||||
except Exception as e:
|
||||
print("test_run_manager_command_restart_after_crash - Prepare Crash - %s" % e)
|
||||
#self.fail('Error initialize object ManageCommand')
|
||||
manage.receive_signal(15, 1)
|
||||
manage.wait_children_commands()
|
||||
handlerCrash(15, 1)
|
||||
print("test_run_manager_command_restart_after_crash - Force Crash - TimeOut !")
|
||||
os._exit(2)
|
||||
self.assertTrue(True)
|
||||
signal.signal(signal.SIGALRM, handlerRaise)
|
||||
signal.alarm(0)
|
||||
|
||||
class MockStreamRequestHandler():
|
||||
|
@ -1222,7 +1264,8 @@ class TestManager(unittest.TestCase):
|
|||
manage.rfile.define_return( '{"name": "test", "first-line" : "1"}' )
|
||||
manage.headers = {'content-length' : '1000', 'content-type' : 'application/json'}
|
||||
manage._command_log()
|
||||
self.assertEqual(b'empty',manage.wfile.message)
|
||||
print(manage.wfile.message)
|
||||
self.assertEqual(b'"empty"',manage.wfile.message)
|
||||
signal.alarm(0)
|
||||
|
||||
@patch.object(http.server.SimpleHTTPRequestHandler, '__init__')
|
||||
|
@ -1417,7 +1460,7 @@ class TestManager(unittest.TestCase):
|
|||
manage.server.listSemaphore = {'test': multiprocessing.Semaphore() }
|
||||
manage.server.listQueueIn = {'test': multiprocessing.Queue() }
|
||||
manage.server.listQueueOut = {'test': multiprocessing.Queue()}
|
||||
manage.server.listQueueOut['test'].put("empty")
|
||||
manage.server.listQueueOut['test'].put({"state": "empty"})
|
||||
manage.rfile.define_return( '{"name": "test", "action": "example"}' )
|
||||
manage.headers = {'content-length' : '1000', 'content-type' : 'application/json'}
|
||||
manage._send_action()
|
||||
|
@ -1494,7 +1537,7 @@ class TestManager(unittest.TestCase):
|
|||
manage.server.listQueueIn = {'test': multiprocessing.Queue() }
|
||||
manage.server.listQueueOut = {'test': multiprocessing.Queue()}
|
||||
manage.headers = {'content-length' : '1000', 'content-type' : 'application/json'}
|
||||
manage.server.listQueueOut['test'].put("empty")
|
||||
manage.server.listQueueOut['test'].put({"state": "empty"})
|
||||
manage.rfile.define_return( '{"name": "test"}' )
|
||||
manage._send_command("STATUS")
|
||||
self.assertEqual(b'{"state": "empty"}',manage.wfile.message)
|
||||
|
|
Loading…
Reference in a new issue