105 def __new__(cls, TileSetName, Nb):
106 self = super().__new__(cls)
107 TilesSet._alive.append(self)
108 self.
init(TileSetName, Nb)
109 return weakref.proxy(self)
112 def init(self, TileSetName, Nb):
113 threading.Thread.__init__(self)
114 self.
thread = threading.Thread(target=self.
run, args=(TileSetName,Nb,))
120 serverLogger.warning(f
"Remove TileSet {self.TileSetName}, thread {self.thread} and id {self.id}")
122 serverLogger.warning(f
"Remove tile {tileconnection[0]}")
123 tileconnection[0].remove()
125 serverLogger.warning(f
"Remove Thread {TSthreads[self.TileSetName]}")
130 def removeTile(self,Id):
131 serverLogger.warning(f
"Remove Tile {Id} in TileSet {self.TileSetName} ( thread {self.thread} and id {self.id} )")
134 if(tileconnection[0].Id == Id):
135 serverLogger.warning(f
"Remove tile {tileconnection[0]}")
136 tileconnection[0].remove()
142 def run(self, TileSetName, Nb):
154 TSthreads[TileSetName]=self.
thread
156 self.
lock = threading.Lock()
160 self.
id=IdTS-sock.PORTServer
168 serverLogger.warning(
"for TileSet "+TileSetName
169 +
" TSthreads is modified with thread "+str(self.
thread)
170 +
" and id "+str(self.
id))
171 serverLogger.warning(
"Port "+str(self.
TileSetPort)+
" for TileSet "+TileSetName+
".")
175 except OSError
as oserror:
176 logging.error(
"Error with connection to TileSet "+TileSetName+
" and PORT "+str(self.
TileSetPort)+
" : "+str(oserror))
180 while count < self.
Nb:
183 +
" with "+str(self.
Nb)
184 +
" tiles id "+str(id)
185 +
" Listening to clients ...")
186 TSconnect.new_connect(id)
190 data = TSconnect.recv(id)
193 serverLogger.info(
"Hello from tile "+data)
194 TSconnect.send_client(id,data)
197 data = TSconnect.recv(id)
199 serverLogger.debug(
"msg password "+data)
200 (container, password) = data.split(
':')
204 self.
ListClient.append((thisTile, self, TileSetName, id, container, password))
208 +
" tile "+str(id)+
" over "+str(self.
Nb)
209 +
" container %s password %s " % (str(container), str(password)))
211 except Exception
as err:
212 serverLogger.error(
"Exception with list of tiles : "+str(err))
213 traceback.print_exc(file=sys.stderr)
230 def wait_client(self,callfun,command):
233 serverLogger.warning(
"%d wait for clients. call %s command %s " % (self.
id,callfun,command))
234 time.sleep(waitsleep)
236 if (count > MaxWaitExecute):
237 serverLogger.error(self.
TileSetName+
" %d : Wait too much on command %s " % (self.
id,command))
240 def execute_all(self,command):
241 serverLogger.warning(self.
TileSetName+
" : Command on all tiles : "+command)
251 import ipdb; ipdb.set_trace()
252 for (client, TSserver, TSName, id, container, password)
in self.
ListClient:
253 client.execute(command)
257 def get_laststate_execute_all(self):
258 serverLogger.warning(self.
TileSetName+
" %d : Get state on all tiles." % (self.
id))
268 for (client, TSserver, TSName, id, container, password)
in self.
ListClient:
271 laststate=client.get_laststate()
272 if (type(laststate) == int):
276 time.sleep(waitsleep)
278 serverLogger.debug(self.
TileSetName+
" : Wait for state on all tiles %d." % (count))
279 if (count > MaxWaitExecute):
280 serverLogger.error(self.
TileSetName+
" : No state on all tiles %d." % (count))
283 serverLogger.warning(self.
TileSetName+
" : State on all tiles : "+str(RET))
288 def execute_list(self,tilesId,command):
289 serverLogger.warning(self.
TileSetName+
" : Command on list "+str(tilesId)+
" of tiles : "+command)
299 import ipdb; ipdb.set_trace()
301 for tileId
in tilesId:
302 AllTileId=list(filter(
lambda x:tileId
in x, self.
ListClient))
303 serverLogger.debug(self.
TileSetName+
" : execute on "+str(tileId)+
" in client : "+str(AllTileId))
304 if (len(AllTileId) == 1):
305 (client, TSserv, TSName, id, container, password)=AllTileId[0]
306 client.execute(command)
308 serverLogger.error(
"Error with list "+str(tileId)+
" of tiles : "+str(AllTileId))
309 serverLogger.error(
"tileId %s AllTileId %s ListClient : %s " % (str(tileId),str(AllTileId),str(self.
ListClient)))
311 except Exception
as err:
313 serverLogger.error(
"Exception with list of tiles : "+str(err))
317 def get_laststate_execute_list(self,tilesId):
318 serverLogger.warning(self.
TileSetName+
" : Get state on list "+str(tilesId)+
" of tiles.")
327 import ipdb; ipdb.set_trace()
330 for tileId
in tilesId:
331 AllTileId=list(filter(
lambda x:tileId
in x, self.
ListClient))
332 serverLogger.debug(self.
TileSetName+
" : laststate on "+str(tileId)+
" in client : "+str(AllTileId))
333 if (len(AllTileId) == 1):
334 (client, TSserv, TSName, id, container, password)=AllTileId[0]
337 laststate=client.get_laststate()
338 if (type(laststate) == int):
342 time.sleep(waitsleep)
344 serverLogger.debug(self.
TileSetName+
" : Wait for state on list "+str(tilesId)+
" of tiles %d." % (count))
345 if (count > MaxWaitExecute):
346 serverLogger.error(self.
TileSetName+
" : No state on list "+str(tilesId)+
" of tiles %d." % (count))
351 serverLogger.warning(self.
TileSetName+
" : State on list "+str(tilesId)+
" of tiles : "+str(RET))
360 def __new__(cls,id, Connect):
361 self = super().__new__(cls)
362 ClientConnect._alive.append(self)
363 self.
init(id, Connect)
364 return weakref.proxy(self)
366 def init(self, id, Connect):
367 threading.Thread.__init__(self)
368 self.
thread = threading.Thread(target=self.
run, args=(id, Connect),)
371 def run(self, id, connect):
377 serverLogger.warning(
"Listen to connection socket to send commands to tiles")
379 serverLogger.debug(
"Wait for command in server run.")
384 if (re.search(
r'create TS',CommandRecv)):
385 p=re.compile(
r'create TS=(\w*) Nb=([0-9]*)')
386 TSName=p.sub(
r'\1',CommandRecv)
387 self.
Nb=int(p.sub(
r'\2',CommandRecv))
388 serverLogger.warning(
"Create TileSet "+TSName+
" with "+str(self.
Nb)+
" tiles.")
395 elif (re.search(
r'remove TS',CommandRecv)):
396 p=re.compile(
r'remove TS=(\w*)')
397 TSName=p.sub(
r'\1',CommandRecv)
398 serverLogger.warning(
'Receive remove command for TileSet "'+TSName+
'".')
400 serverLogger.warning(f
"del TileSet {self.TileSets[TSName]} {self.id}")
409 elif (re.search(
r'remove TTile',CommandRecv)):
410 p=re.compile(
r'remove TTile=(\w*) Tiles=(\w*) ')
411 TSName=p.sub(
r'\1',CommandRecv)
412 TileId=p.sub(
r'\2',CommandRecv)
413 serverLogger.warning(f
'Receive remove command for Tile {TileId} in Set {TSName}.')
414 self.
TileSets[TSName].removeTile(Id)
418 elif (re.search(
r'execute all',CommandRecv)):
419 p=re.compile(
r'execute all (.*)')
420 serverLogger.warning(
'Execute all TileSets command "'+CommandTS+
'"')
423 CommandTS=p.sub(
r'\1',CommandRecv)
424 serverLogger.debug(
'Execute all command on tileset '+TheTS)
425 TheTS.execute_all(CommandTS)
431 laststate=TheTS.get_laststate_execute_all()
432 if (type(laststate) == int):
436 time.sleep(waitsleep)
438 serverLogger.debug(str(TheTS)+
" : Wait for state on list command "+CommandRecv+
" %d." % (count))
439 if (count > MaxWaitExecute):
440 CommandTS=p.sub(
r'\1',CommandRecv)
441 serverLogger.error(str(TheTS)+
" : No state on list command "+CommandRecv+
"\n"+
442 "command send "+CommandTS+
" %d." % (count))
445 serverLogger.debug(str(TheTS)+
" : Get state on list command "+CommandRecv+
" %d." % (RET))
446 serverLogger.debug(str(TheTS)+
" : Get Send OK for command "+CommandRecv+
" %d." % (RET))
450 elif (re.search(
r'execute TS',CommandRecv)):
451 p0=re.compile(
r'execute TS=(\w*) (.*)')
452 TSName=p0.sub(
r'\1',CommandRecv)
453 CommandTS=p0.sub(
r'\2',CommandRecv)
454 p=re.compile(
r"Tiles=[(\[]([0-9, ']*)[)\]] (.*)")
456 if (re.match(p,CommandTS)):
457 StrTiles=p.sub(
r'\1',CommandTS)
461 ListTiles=list(map(
lambda x:x.replace(
"'",
""), StrTiles.split(
', ')))
462 serverLogger.warning(
'Execute command "'+CommandTS+
'" on tileset '+TSName+
' on list '+str(ListTiles))
463 CommandTile=p.sub(
r'\2',CommandTS)
464 self.
TileSets[TSName].execute_list(ListTiles,CommandTile)
466 serverLogger.debug(
'Get laststate on list '+str(ListTiles))
470 laststate=self.
TileSets[TSName].get_laststate_execute_list(ListTiles)
471 serverLogger.debug(
'laststate for '+TSName+
' is '+str(laststate))
472 if (type(laststate) == int):
476 time.sleep(waitsleep)
478 serverLogger.warning(TSName+
" : Wait for state on list command "+CommandRecv+
" %d." % (count))
479 if (count > MaxWaitExecute):
480 serverLogger.error(TSName+
" : No state "+str(laststate)+
" on list command "+CommandRecv+
"\n"+
481 "CommandTS "+CommandTS+
" StrTiles "+str(StrTiles)+
" \n"+
485 serverLogger.debug(TSName+
" : Get state on list command "+CommandRecv+
" %d." % (RET))
487 serverLogger.warning(
'Execute all command "'+CommandTS+
'" on tileset '+TSName)
489 self.
TileSets[TSName].execute_all(CommandTS)
494 laststate=self.
TileSets[TSName].get_laststate_execute_all()
495 serverLogger.debug(
'laststate for '+TSName+
' is '+str(laststate))
496 if (type(laststate) == int):
500 time.sleep(waitsleep)
502 serverLogger.debug(TSName+
" : Wait for state on all command "+CommandRecv+
" %d." % (count))
503 if (count > MaxWaitExecute):
504 serverLogger.error(TSName+
" : No state on all command "+CommandRecv+
"\n"+
505 "CommandTS "+CommandTS+
"\n"+
509 serverLogger.debug(TSName+
" : Get state on all command "+CommandRecv+
" %d." % (RET))
510 except KeyError
as err:
511 serverLogger.error(
"KeyError exception "+str(err)+
"\n for "+TSName+
" tileset and command :\n"+CommandTS)
514 serverLogger.debug(TSName+
" : Send OK for command "+CommandRecv+
" %d." % (RET))
518 elif (re.search(
r'launch TS',CommandRecv)):
519 p=re.compile(
r'launch TS=(\w*) (.*)')
520 TSName=p.sub(
r'\1',CommandRecv)
521 CommandTS=p.sub(
r'\2',CommandRecv)
522 serverLogger.warning(
'Launch on tileset "'+TSName+
'" and command "'+CommandTS+
'"')
524 p=re.compile(
r'([^ ]*) (.*)')
525 CommandPATH=p.sub(
r'\1',CommandTS)
526 CommandEXE=p.sub(
r'\2',CommandTS)
529 if (re.search(
r'TileSetPort',CommandEXE)):
530 CommandEXE=CommandEXE.replace(
'TileSetPort',str(self.
TileSets[TSName].TileSetPort))
531 serverLogger.warning(
'Change TileSetPort on tileset "'+TSName+
'" and command "'+CommandEXE+
'"')
534 serverLogger.info(
'Launch command "'+CommandEXE+
'" with path "'+CommandPATH+
'" on tileset '+TSName)
535 args=
'cd '+CommandPATH+
'; bash -vxc '+shlex.quote(CommandEXE)
536 p=subp.Popen(args, shell=
True,stdout=subp.PIPE,stderr=subp.PIPE)
537 output, errors = p.communicate()
540 serverLogger.info(
"stderr : "+errors.decode(
'utf-8'))
542 self.
Connect.send_OK(self.
id,p.returncode)
545 elif (re.search(
r'putfile TS',CommandRecv)):
546 p=re.compile(
r'putfile TS=(\w*) (.*)')
547 TSName=p.sub(
r'\1',CommandRecv)
548 FileInfos=p.sub(
r'\2',CommandRecv)
550 p=re.compile(
r'([^ ]*) ([^ ]*) ([0-9]*) ([a-z0-9]*)')
551 CommandPath=p.sub(
r'\1',FileInfos)
552 CommandFilename=p.sub(
r'\2',FileInfos)
553 CommandSize=p.sub(
r'\3',FileInfos)
554 CommandSha256=p.sub(
r'\4',FileInfos)
556 serverLogger.warning(
'Put file for tileset "'+TSName+
'" : '+CommandFilename)
558 serverLogger.info(
'Put file in path "'+CommandPath+
' with filename '+CommandFilename+
' and size '+CommandSize+
' MD5sum : '+CommandSha256)
561 self.
Connect.get_file(self.
id,CommandPath,CommandFilename,int(CommandSize),CommandSha256)
564 elif (re.search(
r'askfile TS',CommandRecv)):
565 p=re.compile(
r'askfile TS=(\w*) (.*)')
566 TSName=p.sub(
r'\1',CommandRecv)
567 FileInfos=p.sub(
r'\2',CommandRecv)
569 p=re.compile(
r'([^ ]*) (.*)')
570 CommandPath=p.sub(
r'\1',FileInfos)
571 CommandFilename=p.sub(
r'\2',FileInfos)
573 serverLogger.warning(
'Ask for a file from server on tileset "%s" and file name "%s" in path "%s" ' %\
574 (TSName,CommandFilename,CommandPath))
576 (FileSize, FileSha256) = self.
Connect.send_file(self.
id,CommandPath,CommandFilename)
577 serverLogger.warning(
'File sent with size %d and sha256 %s ' % (FileSize,FileSha256))
581 serverLogger.error(
"*********** UNRECOGNIZED COMMAND FROM CLIENT "+str(self.
Connect.clientinfos[self.
id])+
" *********** :")
582 serverLogger.error(CommandRecv)