185 POSTGRES_HOST=POSTGRES_HOST, POSTGRES_IP=POSTGRES_IP, POSTGRES_PORT=POSTGRES_PORT,
186 POSTGRES_DB=POSTGRES_DB, POSTGRES_USER=POSTGRES_USER, POSTGRES_PASSWORD=POSTGRES_PASSWORD,
187 SMTP_PASSWORD=SMTP_PASSWORD,
188 secretKey=secretKey):
190 self.
thread = threading.Thread(target=self.
run, name=
"TVSecureServer",
191 args=( POSTGRES_HOST, POSTGRES_IP, POSTGRES_PORT,
192 POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD,
196 logging.debug(
"After def thread.")
197 threads[
"flaskdock"]=self.
thread
201 POSTGRES_HOST=POSTGRES_HOST, POSTGRES_IP=POSTGRES_IP, POSTGRES_PORT=POSTGRES_PORT,
202 POSTGRES_DB=POSTGRES_DB, POSTGRES_USER=POSTGRES_USER, POSTGRES_PASSWORD=POSTGRES_PASSWORD,
203 SMTP_PASSWORD=SMTP_PASSWORD,
204 secretKey=secretKey ):
206 logging.debug(
"In thread "+threading.current_thread().name)
213 self.
commandFlask=[POSTGRES_HOST,POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, flaskaddr, str(os.getuid()),str(os.getgid()), SMTP_PASSWORD, secretKey]
235 self.
flaskPORT={
'443/tcp':(
'0.0.0.0',443),
'80/tcp':(
'0.0.0.0',80),
'5000/tcp':(
'0.0.0.0',5000)}
238 logging.warning(
"Add rules for %s" % (str(self.
flaskPORT)))
239 nft.cmd(
"add rule ip filter TILEDVIZ tcp dport 443 accept")
240 nft.cmd(
"add rule ip filter TILEDVIZ tcp dport 80 accept")
242 nft.cmd(
"add rule ip filter TILEDVIZ tcp dport " + str(ConnectionPort) +
" accept")
244 for i
in range(NbSecureConnection):
245 self.
flaskPORT[str(ConnectionPort+i)+
'/tcp']=(
'0.0.0.0',ConnectionPort+i)
249 logging.warning(
"Add rule for port %d" % (ConnectionPort+i))
250 nft.cmd(
"add rule ip filter TILEDVIZ tcp dport " + str(ConnectionPort+i) +
" accept")
254 ENVFlask=[
"debug_Flask=true"]
256 ENVFlask=[
"debug_Flask=false"]
264 name=
"flaskdock", image=
"flaskimage",
265 mounts=[TVvolume,TVWconf,TVssl,TVnginx], extra_hosts=self.
postgresHost,
268 environment=ENVFlask,
274 except docker.errors.ContainerError:
275 logging.error(
"The container exits with a non-zero exit code and detach is False.", exc_info=
True)
276 sys.exit(listerrors[
"createError"])
277 except docker.errors.ImageNotFound:
278 logging.error(
"The specified image does not exist.", exc_info=
True)
279 sys.exit(listerrors[
"ImageError"])
280 except docker.errors.APIError:
281 logging.error(
"The server returns an error.", exc_info=
True)
282 sys.exit(listerrors[
"APIError"])
285 self.
home=
"/home/flaskusr"
288 self.
daterun=datetime.datetime.now()
289 logging.warning(
"Ready to start flaskdock.")
292 except docker.errors.APIError :
293 logging.error(
"Error start Flask", exc_info=
True)
294 sys.exit(listerrors[
"start"])
296 logging.warning(
"After start Flask, containers list :"+str(client.containers.list()))
299 ipFlask = self.
containerFlask.attrs[
"NetworkSettings"][
"Networks"][
"bridge"][
"IPAddress"]
300 logging.debug(
"We have built container for user "+self.
user+
" with postgresql user "+POSTGRES_USER+
" and password '"+POSTGRES_PASSWORD+
"' with IP "+ipFlask+
".")
301 logging.warning(
"Flask container status :"+str(self.
containerFlask.status))
305 createnewconnection=
r'WARNING:.*addconnection:\s*(?P<username>\w+)\s*;\s*(?P<hostname>[^ ;]+)\s*;\s*(?P<connection>\w+)\s*;\s*(?P<containers>\w+)\s*;\s*(?P<scheduler>\w+)\s*;\s*(?P<idTS>\d+)\s*;\s*(?P<idCon>\d+)\s*;\s*(?P<nbTiles>\d+)\s*;\s*(?P<Debug>\d)'
306 create_newconnection = re.compile(
r''+createnewconnection)
309 editoldconnection=
r'WARNING:.*editconnection:\s*(?P<username>\w+)\s*;\s*(?P<hostname>[^ ;]+)\s*;\s*(?P<connection>\w+)\s*;\s*(?P<containers>\w+)\s*;\s*(?P<scheduler>\w+)\s*;\s*(?P<idTS>\d+)\s*;\s*(?P<idCon>\d+)'
310 edit_oldconnection = re.compile(
r''+editoldconnection)
313 quitoldconnection=
r'WARNING:.*removeconnection:\s*(?P<username>\w+)\s*;\s*(?P<idTS>\d+)\s*;\s*(?P<idCon>\d+)'
314 quit_oldconnection = re.compile(
r''+quitoldconnection)
317 killoldconnection=
r'WARNING:.*killconnection:\s*(?P<username>\w+)\s*;\s*(?P<idTS>\d+)\s*;\s*(?P<idCon>\d+)'
318 kill_oldconnection = re.compile(
r''+killoldconnection)
321 actionoldconnection=
r'WARNING:.*action:\s*(?P<username>\w+)\s*;\s*(?P<idTS>\d+)\s*;\s*(?P<idCon>\d+)\s*;\s*(?P<selection>[0-9,]*)'
322 action_oldconnection = re.compile(
r''+actionoldconnection)
327 logging.warning(
"Start log detection loop.")
331 NewLog=NewStringFinder(oldLogs, Logs)
333 if (len(NewLog) > 0):
334 logging.error(
"Get new log "+NewLog)
337 create_newconnect=
False
339 edit_oldconnect=
False
341 quit_oldconnect=
False
343 kill_oldconnect=
False
345 action_oldconnect=
False
346 if (len(NewLog) > 0):
348 create_newconnect=create_newconnection.search(NewLog)
349 if (
not create_newconnect): create_newconnect=
False
351 edit_oldconnect=edit_oldconnection.search(NewLog)
352 if (
not edit_oldconnect): edit_oldconnect=
False
354 quit_oldconnect=quit_oldconnection.search(NewLog)
355 if (
not quit_oldconnect): quit_oldconnect=
False
357 kill_oldconnect=kill_oldconnection.search(NewLog)
358 if (
not kill_oldconnect): kill_oldconnect=
False
362 action_oldconnect=action_oldconnection.search(NewLog)
363 if (
not action_oldconnect): action_oldconnect=
False
369 if (create_newconnect):
371 logging.error(
"Match create connection ")
372 match_connect=create_newconnect
373 elif (edit_oldconnect):
375 logging.error(
"Match edit connection ")
376 match_connect=edit_oldconnect
377 elif (quit_oldconnect):
379 logging.error(
"Match quit connection ")
380 match_connect=quit_oldconnect
381 elif (kill_oldconnect):
383 logging.error(
"Match edit connection ")
384 match_connect=kill_oldconnect
385 elif (action_oldconnect):
387 logging.error(
"Match action connection :"+NewLog)
388 match_connect=action_oldconnect
392 test_notconnect=
False
395 logging.error(
"After test create_newconnect :"+str(match_connect.groups()))
397 boolTestNotAlreadyConnect=(
not any([ (match_connect.group(
"username") == theConnection[
"username"]
and
398 match_connect.group(
"idCon") == theConnection[
"connectionid"])
399 for theConnection
in Connections]))
400 test_notconnect=(len(Connections) == 0
or boolTestNotAlreadyConnect)
403 logging.error(
"after test_notconnect "+str(test_notconnect))
405 if create_newconnect:
406 logging.warning(
"Create new connect :"+str(create_newconnect.groups()))
414 logging.debug(
"Connection container type :"+create_newconnect.group(
"containers"))
416 logging.warning(f
"Connection table count {countConnections} free {usedConnections}")
419 notUsedConnections=[i
for i,x
in enumerate(usedConnections)
if not x]
420 if (len(notUsedConnections) == 0):
422 logging.error(
"ERROR : Full Connection pool. No new connection possible.", exc_info=
True)
425 notUsedCountConnections=[ countConnections[i]
for i
in notUsedConnections ]
427 numConnects=min(notUsedCountConnections)
428 indices = [i
for i, x
in enumerate(notUsedCountConnections)
if x == numConnects]
430 firstFree=notUsedConnections[indices[0]]
432 logging.warning(
"Connection pool slot :"+str(firstFree))
435 countConnections[firstFree]+=1
436 usedConnections[firstFree]=
True
437 logging.warning(f
"Connection table for new connection count {countConnections} free {usedConnections}")
440 Connections[firstFree]=({
"username":create_newconnect.group(
"username"),
441 "hostname":create_newconnect.group(
"hostname"),
442 "connection":create_newconnect.group(
"connection"),
443 "containers":create_newconnect.group(
"containers"),
444 "tilesetid":create_newconnect.group(
"idTS"),
445 "connectionid":create_newconnect.group(
"idCon"),
446 "ThisConnection":
""})
448 nbTiles=int(create_newconnect.group(
"nbTiles"))
449 debug=bool(int(create_newconnect.group(
"Debug")))
451 logging.warning(
"Debug mode for connection.")
453 POSTGRES_HOST, POSTGRES_IP, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD)
454 Connections[firstFree][
"ThisConnection"]=ThisConnection
456 logging.warning(
"A connection already exists with parameters :"+create_newconnect.group(
"username")+
" "+create_newconnect.group(
"hostname")+
" "+str(create_newconnect.group(
"idCon")))
457 logging.error(
"connections : "+str( [ theConnection[
"username"]+
" "+theConnection[
"hostname"]+
" "+str(theConnection[
"connectionid"])
for theConnection
in Connections] ))
459 elif (edit_oldconnect):
460 logging.warning(
"Edit old connect :"+str(edit_oldconnect.groups()))
461 if (
not test_notconnect ):
462 logging.warning(
"Edit connection parameters :"
463 +
" "+edit_oldconnect.group(
"username")+
" "+edit_oldconnect.group(
"hostname")
464 +
" "+edit_oldconnect.group(
"connection")+
" "+edit_oldconnect.group(
"containers")
465 +
" "+edit_oldconnect.group(
"scheduler")+
" "+edit_oldconnect.group(
"idTS")
466 +
" "+edit_oldconnect.group(
"idCon") )
467 logging.debug(
"Connection container type :"+edit_oldconnect.group(
"containers"))
468 for theConnection
in Connections:
469 if( edit_oldconnect.group(
"username") == theConnection[
"username"]
and
470 edit_oldconnect.group(
"hostname") == theConnection[
"hostname"]
and
471 edit_oldconnect.group(
"idCon") == theConnection[
"connectionid"] ):
472 logging.warning(
"Update script for connection "+str(theConnection[
"connectionid"]))
473 theConnection[
"ThisConnection"].callfunction(
"updateScripts")
474 logging.warning(
"Reconnect "+str(theConnection[
"connectionid"]))
475 theConnection[
"ThisConnection"].callfunction(
"reconnect")
477 logging.warning(
"No connection found with parameters :"+edit_oldconnect.group(
"username")+
" "+edit_oldconnect.group(
"hostname")+
" "+str(edit_oldconnect.group(
"idCon")))
480 elif (quit_oldconnect):
481 logging.warning(
"Quit old connect :"+str(quit_oldconnect.groups()))
482 if (
not test_notconnect ):
483 logging.warning(
"Quit connection parameters :"+quit_oldconnect.group(
"username")
484 +
" "+quit_oldconnect.group(
"idTS")+
" "+quit_oldconnect.group(
"idCon"))
485 logging.debug(
"Connection container type :"+quit_oldconnect.group(
"idCon"))
486 for theConnection
in Connections:
487 if( quit_oldconnect.group(
"username") == theConnection[
"username"]
and
488 quit_oldconnect.group(
"idCon") == theConnection[
"connectionid"] ):
489 logging.warning(
"Before quit connection "+str(theConnection[
"connectionid"]))
491 ThisConnection=theConnection[
"ThisConnection"]
492 theConnection[
"ThisConnection"].callfunction(
"quitConnection")
494 ConnectName=ThisConnection.threadName
495 ConnectNum=ThisConnection.ConnectNum
498 while (
not ThisConnection.hasQuit ):
502 logging.error(f
"Connection {ConnectName} has never quitted : {ConnectNum}")
503 ThisConnection.quitConnection()
505 logging.warning(f
"Connection table count {countConnections} free {usedConnections}")
507 except Exception
as err:
508 logging.error(
"Error while stoping Connection with id "+str(quit_oldconnect.group(
"idCon"))+
" : "+str(err), exc_info=
True)
511 logging.error(
"No connection found with parameters :"+quit_oldconnect.group(
"username")+
" "+str(quit_oldconnect.group(
"idCon")))
514 elif (kill_oldconnect):
515 logging.warning(
"Kill old connect :"+str(kill_oldconnect.groups()))
516 if (
not test_notconnect ):
517 logging.warning(
"Kill connection parameters :"+kill_oldconnect.group(
"username")
518 +
" "+kill_oldconnect.group(
"idTS")+
" "+kill_oldconnect.group(
"idCon"))
519 logging.debug(
"Connection container type :"+kill_oldconnect.group(
"idCon"))
520 for theConnection
in Connections:
521 if( kill_oldconnect.group(
"username") == theConnection[
"username"]
and
522 kill_oldconnect.group(
"idCon") == theConnection[
"connectionid"] ):
523 logging.warning(
"Kill connection "+str(theConnection[
"connectionid"]))
524 theConnection[
"ThisConnection"].callfunction(
"killTunnel")
526 logging.error(
"No connection found with parameters :"+kill_oldconnect.group(
"username")+
" "+str(kill_oldconnect.group(
"idCon")))
529 elif (action_oldconnect):
530 logging.warning(
"action old connect :"+str(action_oldconnect.groups()))
531 if (
not test_notconnect ):
532 logging.warning(
"Action connection parameters :"+action_oldconnect.group(
"username")
533 +
" "+action_oldconnect.group(
"idTS")+
" "+action_oldconnect.group(
"idCon")
534 +
" "+action_oldconnect.group(
"selection"))
535 logging.debug(
"Connection container type :"+action_oldconnect.group(
"idCon"))
536 for theConnection
in Connections:
537 if( action_oldconnect.group(
"username") == theConnection[
"username"]
and
538 action_oldconnect.group(
"idCon") == theConnection[
"connectionid"] ):
540 logging.warning(
"Action connection "+str(theConnection[
"connectionid"])+
" function "+str(
"action="+action_oldconnect.group(
"selection")))
541 theConnection[
"ThisConnection"].callfunction(
"action="+action_oldconnect.group(
"selection"))
543 logging.error(
"No connection found with parameters :"+action_oldconnect.group(
"username")+
" "+str(action_oldconnect.group(
"idCon")))
546 time.sleep(timeAliveServ)
561 logging.debug(
"Flask container status :"+str(self.
containerFlask.status))
564 def getLog(self,nbLines):
569 logging.warning(str(self.
Logs))
571 def getContainerFlask(self):
576 def __init__(self,containerFlask, userflask, nbTiles, debug, ConnectNum,
577 POSTGRES_HOST=POSTGRES_HOST, POSTGRES_IP=POSTGRES_IP, POSTGRES_PORT=POSTGRES_PORT,
578 POSTGRES_DB=POSTGRES_DB, POSTGRES_USER=POSTGRES_USER, POSTGRES_PASSWORD=POSTGRES_PASSWORD):
579 threading.Thread.__init__(self)
580 logging.warning(
"Thread Connection creation Num :"+str(ConnectNum))
584 args=(containerFlask, userflask, nbTiles, debug, ConnectNum,
585 POSTGRES_HOST, POSTGRES_IP, POSTGRES_PORT,
586 POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD,))
591 logging.warning(
"Thread Connection creation : %s with name %s" % (str(self.
thread),self.
threadName))
594 def run(self,containerFlask, userflask, nbTiles, debug, ConnectNum,
595 POSTGRES_HOST=POSTGRES_HOST, POSTGRES_IP=POSTGRES_IP, POSTGRES_PORT=POSTGRES_PORT,
596 POSTGRES_DB=POSTGRES_DB, POSTGRES_USER=POSTGRES_USER, POSTGRES_PASSWORD=POSTGRES_PASSWORD):
609 self.
name=
"connectiondock"+str(Connections[self.
ConnectNum][
"connectionid"])
620 logging.warning(
"Name of thread : %s " % (threading.current_thread().name))
621 logging.warning(
"Connection creation :"+self.
name)
623 if (
not os.path.isdir(self.
dir)): os.mkdir(self.
dir)
628 self.
PORTssh=s.getsockname()[1]
632 logging.warning(
"Create the ConnectionDocker's Firewall CHAIN")
633 nft.cmd(
"destroy chain ip filter " + str(self.
name))
634 nft.cmd(
"add chain ip filter " + str(self.
name))
635 nft.cmd(
"add rule ip filter " + str(self.
name) +
" tcp dport " + str(self.
PORTssh) +
" accept")
636 nft.cmd(
"add rule ip filter TILEDVIZ jump " + str(self.
name))
638 VncVolume=docker.types.Mount(source=self.
dir,target=self.
home+
"/.vnc",type=
'bind',read_only=
False)
642 self.
commandConnect=[str(self.
connectionId),POSTGRES_HOST,POSTGRES_PORT,POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD,
'-r',CONNECTION_RESOL,
'-u',str(os.getuid()),
'-g',str(os.getgid()),
'-p',str(self.
PORTssh),
'-d']
645 self.
commandConnect=[str(self.
connectionId),POSTGRES_HOST,POSTGRES_PORT,POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD,
'-r',CONNECTION_RESOL,
'-u',str(os.getuid()),
'-g',str(os.getgid()),
'-p',str(self.
PORTssh)]
648 logging.debug(
"Input param commandConnect : '"+str(self.
commandConnect)+
"'")
652 if ( os.path.exists(
"/dev/nvidia0" ) ):
653 list_gpu_dev=[
"/dev/nvidia0:/dev/nvidia0:rw",
"/dev/nvidiactl:/dev/nvidiactl:rw"]
655 logging.debug(
"ConnectionDocker : no GPU device find in /dev")
673 port=s.getsockname()[1]
681 NFTcmd=
"add rule ip filter " + str(self.
name) +
" tcp dport " + str(port) +
" accept"
682 logging.warning(NFTcmd)
685 logging.error(
"Build %d find again port %d ports list %s" % (t,port,str(self.
listPorts)))
693 logging.warning(f
"Build connection with {self.nbTiles} ports and action port {self.actionPort} : {self.listConnectPorts}")
695 NFTcmd=f
"add rule ip filter {self.name} iif lo tcp dport {self.actionPort} accept"
696 logging.warning(NFTcmd)
703 logging.warning(
"Before start "+self.
name+
", containers list :"+str(client.containers.list()))
711 name=self.
name, image=
"mageiaconnect",
712 mounts=[VncVolume,TVssl,TVconf],
716 devices=list_gpu_dev,
721 except docker.errors.ContainerError:
722 logging.error(
"The container exits with a non-zero exit code and detach is False.", exc_info=
True)
723 sys.exit(listerrors[
"createError"])
724 except docker.errors.ImageNotFound:
725 logging.error(
"The specified image does not exist.", exc_info=
True)
726 sys.exit(listerrors[
"ImageError"])
727 except docker.errors.APIError:
728 logging.error(
"The server returns an APIError.", exc_info=
True)
729 sys.exit(listerrors[
"APIError"])
730 except Exception
as err:
731 logging.error(
"Another error during container creation : ", exc_info=
True)
733 self.
daterun=datetime.datetime.now()
734 logging.warning(
"Ready to start "+self.
name+
".")
737 logging.warning(f
"Connection started {Outstart}.")
738 except docker.errors.APIError :
739 logging.error(
"The container can't start.", exc_info=
True)
740 sys.exit(listerrors[
"start"])
742 logging.warning(
"After start "+self.
name+
", containers list :"+str(client.containers.list()))
744 searchpassword=
r'Random Password Generated:\s*(?P<passwd>[-._+0-9a-zA-Z]+)'
745 search_passwd = re.compile(
r''+searchpassword)
747 info_passwd=self.
grepLog(100,search_passwd)
749 self.
password=info_passwd.group(
"passwd")
752 logging.warning(
"After password.")
755 ipconnect = self.
containerConnect.attrs[
"NetworkSettings"][
"Networks"][
"bridge"][
"IPAddress"]
756 logging.debug(
"We have built container for user '"+self.
user+
"' with IP "+ipconnect+
".")
757 logging.warning(
"User container status :"+str(self.
containerConnect.status))
767 commandAdduser=
"bash -c 'groupadd -r -g "+gid+
" "+self.
flaskusr+ \
768 " && useradd -r -u "+uid+
" -g "+self.
flaskusr+
" "+self.
flaskusr+
" && cp -rp /etc/skel "+flaskhome+\
771 logging.debug(
"Add user "+self.
flaskusr+
" on Flask container."+re.sub(
r'\*n',
r'\\n',str(self.
LogAddUser)))
774 authorized_key=
"No such file or directory"
775 re_wrong_key=re.compile(
r''+authorized_key)
776 match_authorized=re_wrong_key.search(authorized_key)
778 while(match_authorized):
780 commandAuthKey =
"cat "+self.
home+
"/.ssh/id_ed25519.pub"
785 match_authorized=re_wrong_key.search(authorized_key)
786 logging.debug(
"Authorized_key from connection container : \n'"+authorized_key+
"'")
787 count_authorized=count_authorized+1
788 if (count_authorized > 20):
789 logging.error(
"Authorized_key error from connection container : \n'"+authorized_key+
"'")
793 commandBuildSsh=
"mkdir "+flaskhome+
"/.ssh"
795 logging.debug(
"Create .ssh to Flask docker :\n'"+re.sub(
r'\*n',
r'\\n',str(self.
LogBuildSsh))+
"'")
796 commandBuildSsh=
"chmod 700 "+flaskhome+
"/.ssh"
798 logging.debug(
"Protect .ssh to Flask docker :\n'"+re.sub(
r'\*n',
r'\\n',str(self.
LogBuildSsh))+
"'")
801 commandBuildSsh=
"awk 'BEGIN {print \""+authorized_key+
"\" >>\""+flaskhome+
"/.ssh/authorized_keys\"}' /dev/null"
803 logging.debug(
"Add autorized_key to Flask docker :\n'"+re.sub(
r'\*n',
r'\\n',str(self.
LogBuildSsh))+
"'")
814 commandTestFreePort=
"bash -c 'echo \"PORT=\"$(python -c \"import socket; s=socket.socket(); s.bind((\\\"\\\", 0)); print(s.getsockname()[1]); s.close()\" )'"
817 logging.warning(
"Free port for ssh/websockify for user "+self.
flaskusr+
" on Flask container. "+str(internPort))
830 vnc_command=
"if [ X\\\"\\$( pgrep -fla x11vnc )\\\" == X\\\"\\\" ]; then /opt/vnccommand; fi &"
832 self.
tunnel_command=
"ssh -4 -T -N -nf -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -R 0.0.0.0:"+str(internPort)+
":localhost:5902 "+self.
flaskusr+
"@"+self.
IPFlask+
" &"
834 logging.debug(
"awk command to build tunnel script : "+scriptTunnel)
843 out_kill_tunnel=os.path.join(self.
home,
".vnc",
"out_killtunnel")
844 killTunnel=
'Tunnel=$(pgrep -f \\"ssh.*@'+self.
IPFlask+
'\\" );\\nif [ X\\"$Tunnel\\" != X\\"\\" ]; '+\
845 'then \\n pgrep -fla \\"ssh.*@'+self.
IPFlask+
'\\" > '+out_kill_tunnel+
';\\n'+\
846 ' kill -9 $Tunnel 2>&1 >> '+out_kill_tunnel+
';\\n fi'
848 scriptTunnel=
"awk 'BEGIN {print \""+killTunnel+
"\" >>\""+self.
kill_tunnel_script+
"\"}' > "+out_kill_tunnel
850 logging.debug(
"awk command to build kill tunnel script : "+scriptTunnel)
855 logging.warning(
"tunnel script built.")
862 commandBuildVNC=
"awk 'BEGIN {print \""+self.
password+
"\" >>\""+flaskhome+
"/vncpassword\"}' /dev/null"
864 logging.debug(
"Add VNC password to Flask docker :\n"+re.sub(
r'\*n',
r'\\n',str(self.
LogBuildVNC)))
871 logging.error(
"Can't commit connection in DB !", exc_info=
True)
872 logging.debug(
"Connection VNC port saved : "+str(self.
ConnectionDB.connection_vnc)+
" real : "+str(self.
ConnectionDB.connection_vnc+32768))
878 commandTestOldWebsockify=
"bash -c 'pgrep -fa websockify |grep "+str(externPort)+
"| grep -v pgrep'"
880 logging.warning(
"Test already in use extern port from old websockify process "+str(self.
LogTestOldWebsockify.output,
"utf-8"))
881 if( re.sub(
r'.*('+str(externPort)+
').*',
r'\1',str(self.
LogTestOldWebsockify)) == str(externPort) ):
882 PIDoldwebsockify=int(re.sub(
r'^([0-9]*) .*',
r'\1',str(self.
LogTestOldWebsockify.output,
"utf-8")))
883 commandKillOldWebsockify=
"bash -c 'kill -9 "+str(PIDoldwebsockify)+
"'"
886 except Exception
as err:
887 logging.error(
"Error while testing or killing old websockify process "+str(externPort)+
" : "+str(err), exc_info=
True)
893 commandLaunchWebsockify=
"bash -c 'cd /TiledViz/TVConnections/; source /flask_venv/bin/activate; "+\
895 " "+str(externPort)+
" "+str(internPort)+
" /TiledViz/TVWeb"+ \
896 " 2>&1 > /tmp/websockify_$(date +%F_%H-%M-%S).log &'"
897 logging.debug(
"commandLaunchWebsockify : "+commandLaunchWebsockify)
898 logging.warning(
"commandLaunchWebsockify.")
904 commandWebsockifyPID=
"bash -c 'echo $(pgrep -f \"^python3 .*"+str(internPort)+
"\" |sort |head -1)'"
922 logging.warning(
"PID for websockify for user "+self.
flaskusr+
" on Flask container. "+str(self.
websockifyPID))
926 search_docker0_ip=
"ip -4 addr show docker0 | grep -Po 'inet \\K[\\d.]+'"
927 p=subprocess.Popen(search_docker0_ip, shell=
True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
928 output, errs = p.communicate()
929 ipdocker0=output.decode(
'utf-8').replace(
'\n',
'')
930 logging.warning(
"ConnectionDocker : connection for actions with port %d and ip for docker0 %s" % (self.
actionPort,ipdocker0))
932 listPortsTilesFile=os.path.join(self.
dir_out,
"listPortsTiles.pickle")
933 logging.warning(
"Launch websockify and save "+listPortsTilesFile+
" on Connection "+self.
name)
949 if ( externPort == self.
PORTssh ):
957 s.bind((
"127.0.0.1", 0));
958 internPort=s.getsockname()[1];
960 if (internPort
in listInterPort):
964 commandLaunchWebsockify=
"bash -c 'cd /TiledViz/TVConnections/; source /TiledViz/TiledVizEnv_*/bin/activate; "+\
966 " "+str(externPort)+
" "+str(internPort)+
" /TiledViz/TVWeb"+ \
967 " 2>&1 > /tmp/websockify_"+str(inode)+
"_"+str(externPort)+
"_"+str(internPort)+
"_$(date +%F_%H-%M-%S).log &'"
968 logging.debug(
"commandLaunchWebsockify : "+commandLaunchWebsockify)
969 logging.warning(
"commandLaunchWebsockify : "+commandLaunchWebsockify)
980 with open(listPortsTilesFile,
'wb')
as portsf:
982 except Exception
as err:
983 logging.error(
"Error with launch websockify and save "+listPortsTilesFile+
" on Connection "+self.
name+
" : "+str(err), exc_info=
True)
988 intar = tarfile.TarFile(fileobj=filetar, mode=
'w')
989 with open(listPortsTilesFile,
'rb')
as tf:
991 filename=os.path.basename(listPortsTilesFile)
992 tarinfo = tarfile.TarInfo(name=filename)
993 tarinfo.size = len(tfd)
994 tarinfo.mtime = time.time()
995 tarinfo.uid = os.getuid()
996 tarinfo.gid = os.getgid()
997 intar.addfile(tarinfo, BytesIO(tfd))
1004 logging.warning(
"Put "+listPortsTilesFile+
" to connection docker :\n"+str(self.
LogPut))
1006 except Exception
as err:
1007 logging.error(
"Error while putting "+listPortsTilesFile+
" on Connection "+self.
name+
" : "+str(err), exc_info=
True)
1010 time.sleep(timeAliveConn)
1013 search_action = re.compile(
r''+
"action=")
1015 logging.warning(
"Wait for commands.")
1019 logging.warning(
"Container "+self.
name+
" call list : "+str(self.
call_list))
1022 if callfunc ==
"updateScripts":
1024 elif callfunc ==
"quitConnection":
1026 elif callfunc ==
"killTunnel":
1028 elif callfunc ==
"reconnect":
1029 logging.warning(f
"Call reconnect in {self.ConnectionDB.id_users}/{self.ConnectionDB.id}.")
1030 HasNodes=os.path.exists(os.path.join(self.
dir_out,
"nodes.json"))
1031 logging.warning(f
"Test nodes.json : {HasNodes}")
1034 logging.warning(
"Before connect.")
1036 elif (search_action.search(callfunc)):
1037 logging.warning(
"Action detected "+str(callfunc))
1042 logging.error(
"Error with calling function "+callfunc+
" for Connection "+self.
name+
" .")
1050 time.sleep(timeAliveConn)
1052 time.sleep(timeAliveConn)
1055 def get_nodesjson(self):
1056 path_nodesjson=os.path.join(self.
home,
"nodes.json")
1057 path_nodesTVFile=os.path.join(self.
dir_out,
"nodes.json")
1058 logging.warning(
"New get nodes.json instance for "+str(self.
connectionId)+
" connection.")
1064 while (notlaunched
and not self.
_stop_event.is_set()):
1066 if (
not os.path.exists(path_nodesTVFile)):
1067 logging.warning(
"TRY GET "+path_nodesjson+
" file from Connection %s." % (self.
name))
1069 logging.warning(
"ALREADY GET "+path_nodesTVFile+
" file from Connection Docker.")
1070 os.system(
"ls -la "+path_nodesTVFile)
1074 if(iter > Mwait/Swait):
1075 logging.warning(
"Is job started : "+str(self.
nodes_ok))
1076 logging.error(
"Wait too much "+path_nodesjson+
" file for Connection %s to tiledset %s %d %d %d " % (self.
name,str(self.
TileSetDB.name),iter,Swait,Mwait))
1087 logging.warning(
"GET "+path_nodesjson+
" file from Connection Docker.")
1090 logging.error(
"Infos "+str(stat))
1092 logging.warning(
"Infos "+str(stat))
1096 if stat[
"size"]==0 :
1097 logging.error(
" nodes.json size == 0")
1104 filetar.write(chunk)
1112 mytar=tarfile.TarFile(fileobj=filetar, mode=
'r')
1113 mytar.extractall(self.
dir_out)
1123 logging.warning(
"Job started.")
1124 except ValueError
as err:
1125 logging.warning(path_nodesjson+
" ValueError for iter %d." % (iter))
1129 except Exception
as err:
1130 logging.error(
"Error with GET "+path_nodesjson+
". tar error.", exc_info=
True)
1135 except (docker.errors.NotFound, requests.exceptions.HTTPError)
as err:
1136 logging.warning(path_nodesjson+
" NotFound for iter %d." % (iter))
1142 logging.error(
"Job not correctly started", exc_info=
True)
1148 def callfunction (self,myfunc):
1149 logging.debug(
"From Flask thread calling function "+myfunc+
" for Connection "+self.
name+
" .")
1153 def updateScripts(self):
1154 logging.warning(
"updateScripts : Config files for tileset "+str(self.
TileSetDB.config_files)+
" and connection "+str(self.
ConnectionDB.config_files))
1159 intar = tarfile.TarFile(fileobj=filetar, mode=
'w')
1161 for filename
in ConnConfigFiles:
1162 tmpfile=ConnConfigFiles[filename].replace(
"/TiledViz",
".")
1163 tf=open(tmpfile,
'rb')
1165 tarinfo = tarfile.TarInfo(name=filename)
1166 tarinfo.size = len(tfd)
1167 tarinfo.mtime = time.time()
1168 tarinfo.uid = os.getuid()
1169 tarinfo.gid = os.getgid()
1170 intar.addfile(tarinfo, BytesIO(tfd))
1174 TSConfigFiles=self.
TileSetDB.config_files
1175 for filename
in TSConfigFiles:
1176 tmpfile=TSConfigFiles[filename].replace(
"/TiledViz",
".")
1177 tf=open(tmpfile,
'rb')
1179 tarinfo = tarfile.TarInfo(name=filename)
1180 tarinfo.size = len(tfd)
1181 tarinfo.mtime = time.time()
1182 tarinfo.uid = os.getuid()
1183 tarinfo.gid = os.getgid()
1184 intar.addfile(tarinfo, BytesIO(tfd))
1187 logging.warning(
"Config files for tileset "+str(self.
TileSetDB.name)+
" and connection "+str(self.
ConnectionDB.id))
1188 logging.warning(str(intar.getnames()))
1195 logging.warning(
"Put config file to connection docker :\n"+str(self.
LogPut))
1199 def killTunnel(self):
1203 logging.warning(
"Kill tunnel end to Flask docker")
1206 def startActionConnection(self):
1209 logging.warning(f
"Try start ActionConnection on port {self.actionPort}")
1212 logging.warning(f
"Action client connection on {self.actionPort}.")
1216 except Exception
as err:
1217 print(exc_info=
True)
1218 logging.error(f
"Error with Action server {self.ConnectionDB.id} : {err}")
1220 def quitConnection(self):
1225 self.
action(
"action=1,,")
1226 logging.warning(
"Remove TiledSet on HPC server.")
1231 commandKillWebsockify=
"bash -c 'kill "+str(self.
websockifyPID)+
"'"
1237 commandRmuser=
"bash -c 'userdel -r -f "+self.
flaskusr+
"'"
1239 logging.warning(
"Rm user "+self.
flaskusr+
" on Flask container."+re.sub(
r'\*n',
r'\\n',str(self.
LogRmUser)))
1243 if (
"ActionConnect" in dir(self)):
1246 except Exception
as err:
1247 logging.error(
"Error while stoping Action connection "+str(self.
ConnectionDB.id)+
" : "+str(err), exc_info=
True)
1255 except Exception
as err:
1262 logging.warning(f
"remove jump {self.name} rule in TILEDVIZ chain")
1263 nft.set_handle_output(
"True")
1264 rc, output, error = nft.cmd(
"list table ip filter")
1265 jumprule=
"jump " + self.
name +
" # handle "
1266 logging.warning(f
"remove {jumprule}.")
1267 matches = re.findall(jumprule+
"[0-9]+",output)
1269 handle_num = re.sub(jumprule,
"", matches[0])
1270 nft.cmd(
"delete rule ip filter TILEDVIZ handle " + handle_num)
1272 logging.warning(f
"Rule {jumprule} not found.")
1273 nft.cmd(f
"destroy chain ip filter {self.name}")
1275 logging.warning(f
"Connection {self.name} clean usedConnections list for {self.ConnectNum}." )
1279 logging.warning(
"End of quitConnection for "+self.
name+
", containers list :"+str(client.containers.list()))
1282 logging.warning(f
"Connection {self.name} suppression thread {self.ConnectNum}." )
1284 threads[self.
name].join(timeout=1)
1297 logging.warning(f
"Container connected : {self.LogTunnel}")
1302 def action(self,callfunct):
1304 actionlist=re.sub(
r'action=',
r'',callfunct)
1306 logging.warning(
"Action for tileset %s. command %s" % (self.
tilesetId,actionlist))
1308 if (re.sub(
r',.*',
r'',actionlist)==
"0"):
1309 path_nodesjson=os.path.join(self.
home,
"nodes.json")
1311 count_exist_new_nodes=0
1313 while(not_loaded
and not self.
_stop_event.is_set()):
1318 logging.warning(
"GET renew "+path_nodesjson+
" file from Connection Docker.")
1319 logging.warning(
"Infos "+str(stat))
1324 filetar.write(chunk)
1333 mytar=tarfile.TarFile(fileobj=filetar, mode=
'r')
1334 mytar.extractall(self.
dir_out)
1337 logging.warning(
"New nodes.json downloaded from %s to %s." % (path_nodesjson,self.
dir_out))
1341 except Exception
as err:
1342 count_exist_new_nodes=count_exist_new_nodes+1
1344 if ( count_exist_new_nodes > NbIter):
1345 logging.error(
"Fail to renew "+path_nodesjson+
" from Connection Docker.", exc_info=
True)
1354 logging.debug(
"User container "+self.
name+
" status :"+str(self.
containerFlask.status))
1357 def grepLog(self,nbLines,re_searchstr):
1362 m = re_searchstr.search(self.
Logs)
1366 for g
in m.groups():