update feature #1

This commit is contained in:
AleaJactaEst 2018-10-09 12:21:50 +02:00
parent 41b23d2e66
commit ef3cc5347d
4 changed files with 357 additions and 276 deletions

View file

@ -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'

View file

@ -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:
child.terminate()
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__':

View file

@ -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

View file

@ -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)
logging.debug("queue")
item = queueOut.get()
semaphore.release()
print("Lecture STDOUT")
print("sleep")
logging.debug("Lecture STDOUT")
time.sleep(1)
signal.alarm(30)
print("semaphore")
logging.debug("semaphore")
semaphore.acquire()
print("stdout")
logging.debug("stdout")
queueIn.put("STDOUT")
print("Attend le retour STDOUT")
logging.debug("Attend le retour STDOUT")
item = queueOut.get()
semaphore.release()
print("Resultat STDOUT")
print(item)
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,44 +902,61 @@ class TestManager(unittest.TestCase):
config.set('command:test', 'autostart', 'yes')
manage = Manager.Manager(False)
manage.serverHttp = MockServerHttp()
manage._load_config(config)
manage.launch_command()
time.sleep(5)
try:
manage.serverHttp = MockServerHttp()
manage._load_config(config)
manage.launch_command()
time.sleep(5)
key = list(manage.info.keys())[0]
queueIn = manage.info[key]['queueIn']
queueOut = manage.info[key]['queueOut']
semaphore = manage.info[key]['semaphore']
key = list(manage.info.keys())[0]
queueIn = manage.info[key]['queueIn']
queueOut = manage.info[key]['queueOut']
semaphore = manage.info[key]['semaphore']
signal.alarm(10)
semaphore.acquire()
queueIn.put("STATUS")
item = queueOut.get(timeout=4)
semaphore.release()
self.assertEqual(item, "started", 'program not started')
time.sleep(1)
signal.alarm(10)
semaphore.acquire()
queueIn.put("SHUTDOWN")
with self.assertRaises(queue.Empty):
signal.alarm(10)
semaphore.acquire()
queueIn.put("STATUS")
item = queueOut.get(timeout=4)
semaphore.release()
#threadCommand.join()
manage.receive_signal(15, 1)
manage.wait_children_commands()
#Disable timeout
signal.alarm(0)
semaphore.release()
self.assertEqual(item["state"], "started", 'program not started')
time.sleep(1)
signal.alarm(10)
semaphore.acquire()
queueIn.put("SHUTDOWN")
with self.assertRaises(queue.Empty):
item = queueOut.get(timeout=4)
semaphore.release()
#threadCommand.join()
manage.receive_signal(15, 1)
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)