TiledViz
Loading...
Searching...
No Matches
TVConnection.py
1#!/bin/env python3
2
3import datetime,time
4import argparse
5
6import sys,os,traceback
7import pexpect,re
8import platform
9import configparser
10import threading
11import pickle
12
13import code
14import IPython
15from IPython.terminal.embed import InteractiveShellEmbed
16
17from traitlets.config import get_config
18
19from getpass import getpass
20
21import logging
22
23import inspect
24
25Home=os.environ['HOME']
26user=os.environ["USER"]
27TiledVizPath='/TiledViz'
28
29TilesScriptsPath='/opt'
30
31sys.path.append("/usr/local/lib/python3.10/site-packages")
32sys.path.append("/usr/local/lib64/python3.10/site-packages")
33
34sys.path.append(os.path.abspath(TiledVizPath+'/TVDatabase'))
35from TVDb import tvdb
36from TVDb import models
37
38# Add connect module directory
39sys.path.append(os.path.realpath(TiledVizPath+'/TVConnections/'))
40from connect import sock
41from connect.transfer import send_file_server, get_file_client
42
43# Read TiledViz config
44TVrunDir=Home+'/.tiledviz'
45TVconf=TVrunDir+"/tiledviz.conf"
46
47config = configparser.ConfigParser()
48config.optionxform = str
49config.read(TVconf)
50ActionPort=int(config['TVSecure']['ActionPort'])
51
52# Default port for connection between client in sock.py and TVSecure.py
53#PORTServer=int(config['sock']['PORTServer'])
54
55# Message fix size for data transfert through socket
56MSGsize=int(config['sock']['MSGsize'])
57
58MaxSessionDuration=21600
59NbActionDetect=36000
60
61# Key name for this connection built in main :
62sshKeyName=""
63
64# Usefull fuction for debugging CASE script:
65def cat_between(b,e,f):
66 os.system('/cat_between %d %d %s' % ( b, e, f))
67
68def containerId(num):
69 return '{:03d}'.format(num)
70
71def parse_args(argv):
72 parser = argparse.ArgumentParser(
73 'From a connection Id in PostgreSQL DB get connection parameters from TiledViz database.')
74 parser.add_argument('--host', default='localhost',
75 help='Database host (default: localhost)')
76 parser.add_argument('--port', default='6431',
77 help='Port (default: 6431)')
78 parser.add_argument('-l', '--login', default='tiledviz',
79 help='Database login (default: tiledviz)')
80 parser.add_argument('-n', '--databasename', default='TiledViz',
81 help='Database name (default: TiledViz)')
82 parser.add_argument('-u', '--usertest', default='ddurandi',
83 help='User name for test (default: ddurandi)')
84 parser.add_argument('-c', '--connectionId',
85 help='Connection Id in DB.')
86 parser.add_argument('--debug', action='store_true',
87 help='Debug switch for new job.',default=False)
88
89 args = parser.parse_args(argv[1:])
90 return args
91
92
93
94class ServerAction(threading.Thread):
95
96 def __init__(self,connectionId,globals,locals):
97 threading.Thread.__init__(self)
98 self.thread = threading.Thread(target=self.run, name="ServerAction",
99 args=(connectionId,globals,locals,)).start()
100
101 def run(self,connectionId,globals,locals):
102 global tiles_actions
103 tiles_actions["action0"]=["get_new_nodes","system_update_alt"]
104
105 try:
106 self.actionserver=sock.server(ActionPort)
107 logging.warning(f"Launch server for action on {ActionPort}.")
108 outHandler.flush()
109
110 self.actionserver.new_connect(1)
111 logging.warning(f"New connection detected on action server.")
112 outHandler.flush()
113
114 # Send Not an action message after Hello
115 HelloMsg=self.actionserver.recv(1)
116 logging.warning(f"Action server hello message : {HelloMsg}")
117 self.actionserver.send_client(1,HelloMsg)
118 logging.warning("Action server send back hello message")
119 outHandler.flush()
120
121 except:
122 logging.error("ServerAction : can't connect to client TVSecure")
123 traceback.print_exc(file=sys.stderr)
124
125 self.iter=0
126 # Wait for commands by TVSecure.py
127 while True:
128 detectActionConnection=self.detect()
129 if (detectActionConnection):
130 self.execute(globals,locals)
131 elif (detectActionConnection == -1):
132 return
133 time.sleep(0.1)
134 if (self.iter > NbActionDetect):
135 logging.warning(f"No ActionServer detected after {NbActionDetect} tries.")
136 return
137
138 def detect(self):
139 global tiles_actions
140 self.IsActionConnected=False
141 self.iter=self.iter+1
142 #logging.warning("ServerAction : detect")
143 if ("actionserver" in dir(self)):
144 data=self.actionserver.recv(1)
145 if not data:
146 return False
147 else:
148 # No ActionConnection server
149 logging.error("ServerAction : No more Action connection to server connectiondock")
150 return -1
151 self.actionserver.send_OK(1,self.iter)
152 self.IsActionConnected=True
153
154 try:
155 actiontiles=list(map(int,data.replace(',,','').split(",")))
156 logging.warning("ServerAction : get actionTile message "+str(actiontiles))
157 actionId=actiontiles.pop(0)
158 except:
159 logging.warning("ServerAction : not an action "+data)
160 return False
161 # test if it is a valid action command
162 self.thisAction="action"+str(actionId)
163 if (self.thisAction in tiles_actions):
164 self.isSelection=False
165 if (len(actiontiles) > 0):
166 self.isSelection=True
167 try:
168 self.thisSelection=list(map(int,actiontiles))
169 logging.debug("ServerAction : detect a valid selection "+str(self.thisSelection))
170 except:
171 return False
172 else:
173 logging.warning("ServerAction : detect a global action ")
174 return True
175 else:
176 logging.error("ServerAction : error reading "+self.thisAction)
177 self.isSelection=False
178 return False
179
180 def execute(self,globals,locals):
181 # Separate Execute
182 logging.debug("ServerAction : run")
183 if (not self.IsActionConnected):
184 return
185 try:
186 funaction=tiles_actions[self.thisAction][0]
187 functionAction=eval(funaction)
188 search_tileNum=inspect.signature(functionAction).parameters
189 logging.debug("ServerAction : "+funaction+" parameters :"+str(search_tileNum))
190 if ("tileNum" in search_tileNum):
191 if (self.isSelection):
192 for num in self.thisSelection:
193 action=funaction+"(tileNum="+str(num)+")"
194 logging.warning("ServerAction : send action "+action)
195 eval(action,globals,locals)
196 else:
197 logging.warning("ServerAction : Apply this action "+funaction+" on all tiles.")
198 for num in range(NUM_DOCKERS):
199 action=funaction+"(tileNum="+str(num)+")"
200 logging.warning("ServerAction : send action "+action)
201 eval(action,globals,locals)
202 else:
203 action=funaction+"()"
204 logging.warning("ServerAction : No tile for this action "+action)
205 eval(action,globals,locals)
206 logging.warning("ServerAction : action "+action+" launched.")
207 except:
208 traceback.print_exc(file=sys.stderr)
209 logging.warning("ServerAction : problem with action "+funaction+" launch.")
210 pass
211
212
213
214# Those functions must be overlap in CASE job script for specific request.
215
216# Launch dockers
217def Run_dockers():
218 COMMAND="bash -c \""+os.path.join(TILEDOCKERS_path,"launch_dockers")+" "+REF_CAS+" "+GPU_FILE+" "+SSH_FRONTEND+":"+SSH_IP+\
219 " "+network+" "+nethost+" "+domain+" "+init_IP+" TileSetPort "+UserFront+"@"+Frontend+" "+OPTIONS+\
220 " > "+os.path.join(JOBPath,"output_launch")+" 2>&1 \""
221 logging.warning("\nCommand dockers : "+COMMAND)
222 client.send_server(LaunchTS+' '+COMMAND)
223 state=client.get_OK()
224 logging.warning("Out of launch docker : "+ str(state))
225 sys.stdout.flush()
226 stateVM=(state == 0)
227 return stateVM
228
229# Launch singularitys
230def Run_singularitys():
231 COMMAND="bash -c \""+os.path.join(TILESINGULARITYS_DIR,"launch_singularitys")+" "+REF_CAS+" "+GPU_FILE+" "+SSH_FRONTEND+":"+SSH_IP+" "+TILEDVIZ_DIR+" "+TILESINGULARITYS_DIR+\
232 " TileSetPort "+UserFront+"@"+Frontend+" "+OPTIONS+\
233 " > "+os.path.join(JOBPath,"output_launch")+" 2>&1 \""
234
235 # logging.warning("\nCommand singularitys : "+COMMAND)
236 # logging.warning("\nclient.send_server("+LaunchTS+' '+COMMAND)
237 # logging.warning("\nstate=client.get_OK()")
238 # logging.warning("\nlogging.warning('Out of launch singularity : '+ str(state))")
239 # logging.warning("\nsys.stdout.flush()")
240 # try:
241 # code.interact(banner="Before launch_singularity :",local=dict(globals(), **locals()))
242 # except SystemExit:
243 # pass
244 client.send_server(LaunchTS+' '+COMMAND)
245 state=client.get_OK()
246 logging.warning("Out of launch singularity : "+ str(state))
247 sys.stdout.flush()
248 stateVM=(state == 0)
249 return stateVM
250
251# Build nodes.json file from new dockers list
252def build_nodes_file():
253 logging.warning("Build nodes.json file from new dockers list.")
254 COMMAND=LaunchTS+' ./build_nodes_file '+os.path.join(JOBPath,CASE_config)+' '+os.path.join(JOBPath,SITE_config)+' '+TileSet
255 logging.warning("\nCommand dockers : "+COMMAND)
256 client.send_server(COMMAND)
257 state=client.get_OK()
258 logging.warning("Out of build_nodes_file : "+ str(state))
259 time.sleep(2)
260 stateVM=(state == 0)
261 state=launch_nodes_json()
262 stateVM=stateVM and (state == 0)
263 os.system("mv nodes.json nodes.json_init")
264 return stateVM
265
266def replaceconf(x):
267 if (re.search('}',x)):
268 varname=x.replace("{","").replace("}","")
269 return config['CASE'][varname]
270 else:
271 return x
272
273def kill_all_containers():
274 stateVM=True
275 #client.send_server(LaunchTS+" "+COMMANDStop)
276 #print("Out of COMMANDStop.")
277 #sys.stdout.flush()
278 #time.sleep(2)
279 Remove_TileSet()
280 return stateVM
281
282# return the IP of a client tileNum or tileId
283def Get_client_IP(tileNum=-1,tileId='001'):
284 if ( tileNum > -1 ):
285 TilesStr=' Tiles=('+containerId(tileNum+1)+') '
286 Id=containerId(tileNum+1)
287 else:
288 TilesStr=' Tiles=('+tileId+') '
289 Id=tileId
290 fileIP='IP_'+Id
291 client.send_server(ExecuteTS+TilesStr+
292 'bash -c "/usr/local/bin/get_ip.sh;' +
293 'scp .vnc/myip '+HTTP_LOGIN+'@'+HTTP_FRONTEND+':'+JOBPath+'/'+fileIP+'"')
294 logging.debug("Out of get %s ip : %s " % ( Id,str(client.get_OK()) ))
295 get_file_client(client,TileSet,JOBPath,fileIP,".")
296 # while( get_file_client(client,TileSet,JOBPath,"serverip",".") < 0):
297 # time.sleep(1)
298 # pass
299 try:
300 with open(fileIP,'r') as fip:
301 IP=fip.read().replace(domain+'.',"").replace("\n","")
302 logging.warning("%s ip : "+domain+'.'+IP)
303 sys.stdout.flush()
304 return IP
305 except:
306 logging.error("Cannot retreive ip from %s." % (Id) )
307 return "-1"
308
309def read_nodes_init():
310 # Update nodes.json locally
311 JsonFile="nodes.json_init"
312 logging.warning("Before read : "+ str(JsonFile))
313 try:
314 with open(JsonFile) as json_tiles_file:
315 nodes_json=json.loads(json_tiles_file.read())
316 except:
317 sys.stdout.flush()
318 traceback.print_exc(file=sys.stdout)
319 os.system('ls -la '+JsonFile)
320 kill_all_containers()
321 return nodes_json
322
323def nodes_json_init():
324 with open("listPortsTiles.pickle", 'rb') as file_pi:
325 listPortsTilesIE=pickle.load(file_pi)
326
327 nodes_json=read_nodes_init()
328
329 for tilei in range(NUM_DOCKERS):
330 nodeurl=nodes_json["nodes"][tilei]["url"]
331 nodeurl=re.sub(r'https://[^/]*',r'https://'+listPortsTilesIE["TiledVizHost"],nodeurl)
332 nodeurl=re.sub(r'host=[^&]*',r'host='+listPortsTilesIE["TiledVizHost"],nodeurl)
333 oldport=int(re.sub(r'.*port=([^&]*)&.*',r'\1',nodeurl))
334 tileip=oldport % 1000 - 1
335 #logging.warning("tile %d update nodes.json : new url %s with old port %d" % (tilei, nodeurl, oldport))
336 if ( str(tileip) in listPortsTilesIE):
337 extern=listPortsTilesIE[str(tileip)][1]
338 nodes_json["nodes"][tilei]["url"]=re.sub(r'port=[^&]*',r'port='+str(extern),nodeurl)
339 logging.warning("tile %d : new url %s" % (tilei,nodes_json["nodes"][tilei]["url"]))
340 sys.stdout.flush()
341 logging.warning("Before write nodes.json")
342 with open("nodes.json",'w') as nodesf:
343 nodesf.write(json.dumps(nodes_json))
344 return True
345
346# share ssh key for each docker
347def share_ssh_key_docker():
348 # Share ssh connection keys whith tiles
349 stateVM=True
350 # TODO : secure that action ?
351 totbyte=0
352 filesize=os.path.getsize(sshKeyPath)
353 connectionkey=os.path.join(Home,".ssh/"+sshKeyName)
354 os.system("cp "+sshKeyPath+".pub "+os.path.join(Home,".ssh/authorized_keys"))
355 packet_id_length=MSGsize-200
356 with open(sshKeyPath,'rb') as privatek:
357 l = '\\\"'+str(privatek.read(packet_id_length).replace(b"\n",b""),"utf-8")+'\\\"'
358 COMMANDid=ExecuteTS+' bash -c "echo '+l+' > '+connectionkey+'; chmod 600 '+connectionkey+'"'
359 logging.warning("Send id_ed with %s." % (COMMANDid) )
360 client.send_server(COMMANDid)
361 state=client.get_OK()
362 stateVM=stateVM and (state == 0)
363 while (l):
364 totbyte=totbyte+packet_id_length
365 rest=filesize-totbyte;
366 if (rest > packet_id_length ):
367 l = '\\\"'+str(privatek.read(packet_id_length).replace(b"\n",b""),"utf-8")+'\\\"'
368 COMMANDid=ExecuteTS+' bash -c "echo '+l+' >> '+connectionkey+'"'
369 logging.warning("Send id_ed with %s." % (COMMANDid) )
370 client.send_server(COMMANDid)
371 state=client.get_OK()
372 stateVM=stateVM and (state == 0)
373 else:
374 if (rest > 0):
375 l = '\\\"'+str(privatek.read(rest).replace(b"\n",b""),"utf-8")+'\\\"'
376 COMMANDid=ExecuteTS+' bash -c "echo '+l+' >> '+connectionkey+'"'
377 logging.warning("Send id_ed with %s." % (COMMANDid) )
378 client.send_server(COMMANDid)
379 state=client.get_OK()
380 stateVM=stateVM and (state == 0)
381 break
382 logging.warning("Out of id_ed : "+ str(stateVM))
383 COMMANDid=ExecuteTS+' bash -c "sed -e \\\"s&KEY-----&KEY-----\\\\n&\\\" -e \\\"s&-----END&\\\\n-----END&\\\" -i '+connectionkey+'"'
384 logging.warning("Send id_ed with %s." % (COMMANDid) )
385 client.send_server(COMMANDid)
386 state=client.get_OK()
387 stateVM=stateVM and (state == 0)
388 with open(sshKeyPath+'.pub','rb') as publick:
389 l = '\\\"'+str(publick.read().replace(b"\n",b""),"utf-8")+'\\\"'
390 COMMANDid=ExecuteTS+' bash -c "echo '+l+' > '+connectionkey+'.pub"'
391 logging.warning("Send id_ed.pub with %s." % (COMMANDid) )
392 client.send_server(COMMANDid)
393 state=client.get_OK()
394 stateVM=stateVM and (state == 0)
395 logging.warning("Out of id_ed.pub : "+ str(stateVM))
396 if (not stateVM):
397 logging.error("!! Error send id_ed.!!")
398 return stateVM
399
400# share ssh key on home for singularity
401def share_ssh_key_singularity():
402 stateVM=True
403
404 # Share ssh connection keys whith tiles
405 connectionkey=os.path.join(HomeFront,".ssh/"+sshKeyName)
406 os.system("cp "+sshKeyPath+".pub "+os.path.join(Home,".ssh/authorized_keys"))
407 send_file_server(client,TileSet,os.path.join(Home,".ssh"), sshKeyName, JOBPath)
408 COMMANDid=LaunchTS+' bash -c "mv '+os.path.join(JOBPath,sshKeyName)+' '+connectionkey+'; chmod 600 '+connectionkey+'"'
409 logging.warning("Send id_ed with \"%s\"." % (COMMANDid) )
410 client.send_server(COMMANDid)
411 state=client.get_OK()
412 stateVM=stateVM and (state == 0)
413
414 send_file_server(client,TileSet,os.path.join(Home,".ssh"), sshKeyName+".pub", JOBPath)
415 COMMANDid=LaunchTS+' bash -c "mv '+os.path.join(JOBPath,sshKeyName+".pub")+' '+connectionkey+".pub"+'; chmod 666 '+connectionkey+".pub"+'"'
416 logging.warning("Send id_ed with \"%s\"." % (COMMANDid) )
417 client.send_server(COMMANDid)
418 state=client.get_OK()
419 stateVM=stateVM and (state == 0)
420 logging.warning("Out of id_ed.pub : "+ str(stateVM))
421 if (not stateVM):
422 logging.error("!! Error send id_ed.!!")
423 return stateVM
424
425share_ssh_key=share_ssh_key_docker
426
427# commande de tunnel :
428def launch_tunnel_docker():
429 global TilesScriptsPath
430 logging.warning("TilesScriptsPath : %s" % (TilesScriptsPath))
431 stateVM=True
432
433 connectionkey="/home/myuser/.ssh/"+sshKeyName
434
435 with open("listPortsTiles.pickle", 'rb') as file_pi:
436 listPortsTilesIE=pickle.load(file_pi)
437 # Call tunnel for VNC
438 for i in range(NUM_DOCKERS):
439 i0="%0.3d" % (i+1)
440 TILEi=ExecuteTS+' Tiles=('+containerId(i+1)+') '
441 internPort=listPortsTilesIE[str(i)][0]
442 WebServerHost=listPortsTilesIE["TiledVizHost"]
443 ServerTSPortSSH=listPortsTilesIE["TiledVizConnectionPort"]
444 COMMANDi=' ssh-agent '+TilesScriptsPath+'/tunnel_ssh '+SSH_FRONTEND+' '+SSH_LOGIN+' '+str(internPort)+' '+WebServerHost+' '+str(ServerTSPortSSH)+' -i '+connectionkey
445 client.send_server(TILEi+COMMANDi)
446 state=client.get_OK()
447 logging.warning("%s | %s : %s" % (TILEi, COMMANDi,state))
448 stateVM=stateVM and (state == 0)
449 if (not stateVM):
450 print("!! Error launch_tunnel.!!")
451 return stateVM
452 sys.stdout.flush()
453
454 logging.warning("Out of tunnel_ssh : "+ str(stateVM))
455 return stateVM
456
457# Launch singularity tunnels
458def launch_tunnel_singularity():
459 global TilesScriptsPath
460 logging.warning("Singularity TilesScriptsPath : %s" % (TilesScriptsPath))
461 logging.warning("Frontend Home in anatomist_job: "+HomeFront)
462 stateVM=True
463
464 connectionkey=os.path.join(HomeFront,".ssh/"+sshKeyName)
465
466 with open("listPortsTiles.pickle", 'rb') as file_pi:
467 listPortsTilesIE=pickle.load(file_pi)
468 # Call tunnel for VNC
469 for i in range(NUM_DOCKERS):
470 i0="%0.3d" % (i+1)
471 TILEi=ExecuteTS+' Tiles=('+containerId(i+1)+') '
472 internPort=listPortsTilesIE[str(i)][0]
473 WebServerHost=listPortsTilesIE["TiledVizHost"]
474 ServerTSPortSSH=listPortsTilesIE["TiledVizConnectionPort"]
475 #COMMANDi=' '+TilesScriptsPath+'/tunnel_ssh '+SSH_FRONTEND+' '+SSH_LOGIN+' '+str(internPort)+' '+WebServerHost+' '+str(ServerTSPortSSH)+' -i '+connectionkey
476 #COMMANDi=' ssh-agent '+TilesScriptsPath+'/tunnel_ssh '+SSH_FRONTEND+' '+SSH_LOGIN+' '+str(internPort)+' '+WebServerHost+' '+str(ServerTSPortSSH)+' -i '+connectionkey
477 COMMANDi=" nohup bash -c ' ssh-agent "+TilesScriptsPath+'/tunnel_ssh '+SSH_FRONTEND+' '+SSH_LOGIN+' '+str(internPort)+' '+WebServerHost+' '+str(ServerTSPortSSH)+' -i '+connectionkey+" '&"
478 client.send_server(TILEi+COMMANDi)
479 state=client.get_OK()
480 logging.warning("%s | %s : %s" % (TILEi, COMMANDi,state))
481 stateVM=stateVM and (state == 0)
482 if (not stateVM):
483 print("!! Error launch_tunnel.!!")
484 return stateVM
485 sys.stdout.flush()
486 #time.sleep(2)
487
488 logging.warning("Out of tunnel_ssh : "+ str(stateVM))
489 return stateVM
490
491launch_tunnel=launch_tunnel_docker
492
493def launch_vnc():
494 client.send_server(ExecuteTS+' '+TilesScriptsPath+'/vnccommand')
495 state=client.get_OK()
496 logging.warning("Out of vnccommand : "+ str(state))
497 stateVM=(state == 0)
498 return stateVM
499
500
501def init_wmctrl():
502 client.send_server(ExecuteTS+' wmctrl -l -G')
503 state=client.get_OK()
504 logging.warning("Out of wmctrl : "+ str(state))
505 stateVM=(state == 0)
506 return stateVM
507
508
509def clear_vnc(tileNum=-1,tileId='001'):
510 if ( tileNum > -1 ):
511 TilesStr=' Tiles=('+containerId(tileNum+1)+') '
512 else:
513 TilesStr=' Tiles=('+tileId+') '
514 client.send_server(ExecuteTS+TilesStr+' x11vnc -R clear-all')
515 state=client.get_OK()
516 logging.warning("Out of clear-vnc : "+ str(state))
517 stateVM=(state == 0)
518 return stateVM
519
520
521def clear_vnc_all():
522 os.system('x11vnc -R clear-all')
523 stateVM=True
524 for i in range(NUM_DOCKERS):
525 stateVM=stateVM and clear_vnc(i)
526 #clear_vnc(tileId=containerId(i))
527 return stateVM
528
529def changeSize(RESOL="1920x1080",tileNum=-1,tileId='001'):
530 if ( tileNum > -1 ):
531 TilesStr=' Tiles=('+containerId(tileNum+1)+') '
532 else:
533 TilesStr=' Tiles=('+tileId+') '
534 COMMAND=ExecuteTS+TilesStr+' xrandr --fb '+RESOL
535 logging.warning("call server with : "+COMMAND)
536 client.send_server(COMMAND)
537 state=client.get_OK()
538 logging.warning("server answer is "+str(state))
539 stateVM=(state == 0)
540 return stateVM
541
542def all_resize(RESOL="1280x800"): #"1440x900"
543 client.send_server(ExecuteTS+' bash -c "export DISPLAY=:1; xrandr --fb '+RESOL+'"')
544 state=client.get_OK()
545 logging.warning("Out of xrandr : "+ str(state))
546 stateVM=(state == 0)
547 return stateVM
548
549# def fullscreenThisApp(App="xterm",tileNum=-1,tileId='001'):
550# COMMAND=TilesScriptsPath+'/movewindows '+App+' -b toggle,fullscreen'
551# if ( tileNum > -1 ):
552# TilesStr=' Tiles=('+containerId(tileNum+1)+') '
553# else:
554# TilesStr=' Tiles=('+tileId+') '
555# client.send_server(ExecuteTS+TilesStr+COMMAND)
556# client.get_OK()
557
558App="N/A"
559def fullscreenApp(windowname=App,tileNum=-1,tileId='001'):
560 if ( tileNum > -1 ):
561 stateVM=movewindows(windowname=windowname,wmctrl_option='toggle,fullscreen',tileNum=tileNum)
562 else:
563 stateVM=movewindows(windowname=windowname,wmctrl_option='toggle,fullscreen',tileId=tileId)
564 return stateVM
565
566def movewindows(windowname=App,wmctrl_option='toggle,fullscreen',tileNum=-1,tileId='001'):
567 COMMAND=TilesScriptsPath+'/movewindows '+windowname+' -b '+wmctrl_option
568 #remove,maximized_vert,maximized_horz
569 #toggle,above
570 if ( tileNum > -1 ):
571 TilesStr=' Tiles=('+containerId(tileNum+1)+') '
572 else:
573 TilesStr=' Tiles=('+tileId+') '
574 client.send_server(ExecuteTS+TilesStr+COMMAND)
575 state=client.get_OK()
576 stateVM=(state == 0)
577 return stateVM
578
579def showThisGUI(App="xterm",tileNum=-1,tileId='001'):
580 COMMAND=TilesScriptsPath+'/movewindows '+App+' -b toggle,above'
581 if ( tileNum > -1 ):
582 TilesStr=' Tiles=('+containerId(tileNum+1)+') '
583 else:
584 TilesStr=' Tiles=('+tileId+') '
585 client.send_server(ExecuteTS+TilesStr+COMMAND)
586 state=client.get_OK()
587 stateVM=(state == 0)
588 return stateVM
589
590def click_point(tileNum=-1,tileId='001',X=0,Y=0):
591 if ( tileNum > -1 ):
592 TilesStr=' Tiles=('+containerId(tileNum+1)+') '
593 else:
594 TilesStr=' Tiles=('+tileId+') '
595 COMMAND=" xdotool mousemove "+str(X)+" "+str(Y)+" click 1 mousemove restore"
596 # -> xdotool getmouselocation
597 client.send_server(ExecuteTS+TilesStr+COMMAND)
598 state=client.get_OK()
599 logging.warning("Out of click_point : "+ str(state))
600 stateVM=(state == 0)
601 return stateVM
602
603
604if __name__ == '__main__':
605 args = parse_args(sys.argv)
606
607 logFormatter = logging.Formatter("TVConnection %(asctime)s - %(threadName)s - %(levelname)s: %(message)s ")
608 rootLogger = logging.getLogger()
609 rootLogger.setLevel(logging.WARNING)
610 fileHandler = logging.FileHandler(Home+"/.vnc/TVConnection.log")
611 fileHandler.setLevel(logging.DEBUG)
612 fileHandler.setFormatter(logFormatter)
613 rootLogger.addHandler(fileHandler)
614 outHandler = logging.StreamHandler(sys.stdout)
615 outLevel=logging.DEBUG
616 #=logging.WARNING
617 outHandler.setLevel(outLevel)
618 outHandler.setFormatter(logFormatter)
619 rootLogger.addHandler(outHandler)
620 #rootLogger.handlers[0].flush()
621 #outHandler.flush()
622
623 # Hack to see thread names in htop
624 try:
625 import prctl
626 def set_thread_name(name):
627 logging.debug("For thread "+threading.current_thread().name+ " give name %s " % (name))
628 prctl.set_name(name)
629
630 def _thread_name_hack(self):
631 set_thread_name(self.name)
632 logging.debug("For thread "+threading.current_thread().name+ " hack name %s " % (self.name))
633 try:
634 self._bootstrap_inner()
635 except:
636 if self._daemonic and _sys is None:
637 return
638 raise
639 #threading.Thread.__bootstrap_original(self)
640 logging.debug("For thread "+threading.current_thread().name+ " end of hack name %s " % (self.name))
641
642 # threading.Thread._bootstrap_original = threading.Thread._bootstrap
643 threading.Thread._bootstrap = _thread_name_hack
644
645 except ImportError:
646 logging.debug('No python-prctl module. No thread names')
647 def set_thread_name(name): pass
648
649 # Connection to DB
650 metadata, conn, engine, pool, session = tvdb.SQLconnector(args)
651 os.environ["POSTGRES_PASSWORD"]=""
652 os.environ["passwordDB"]=""
653 connectionId=int(args.connectionId)
654 logging.warning("Build connection number "+args.connectionId)
655
656 TVconnection=session.query(models.Connections).filter(models.Connections.id == connectionId).one()
657 auth_type=TVconnection.auth_type
658
659 logging.warning("From DB connection informations : "+str((auth_type,TVconnection.host_address,TVconnection.scheduler)))
660 TileSetDB=session.query(models.TileSets).filter_by(id_connections=args.connectionId).order_by(models.TileSets.id.desc()).first()
661 TileSet=TileSetDB.name
662
663 DATE=re.sub(r'\..*','',datetime.datetime.isoformat(datetime.datetime.now(),sep='_').replace(":","-"))
664
665 myhostname=os.getenv('HOSTNAME', os.getenv('COMPUTERNAME', platform.node())).split('.')[0]
666
667 # Default values for TileSet
668 CreateTS='create TS='+TileSet+' Nb='+str(1)
669
670 # Execute on each/a set of tiles
671 ExecuteTS='execute TS='+TileSet+" "
672 # Launch a command on the frontend
673 LaunchTS='launch TS='+TileSet+" ."
674
675 def Remove_TileSet():
676 # Remove TileSet in TileServer
677 RemoveTS='remove TS='+TileSet
678 client.send_server(RemoveTS)
679
680 # Clean key :
681 if (auth_type == "ssh" or auth_frontend):
682 CleanKeyFrontend = "ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+'@localhost bash -cvx \'\"sed -i.'+DATE+' /'+myhostname+'/d ~/.ssh/authorized_keys; rm .ssh/'+sshKeyName+'* \"\''
683 logging.warning(CleanKeyFrontend)
684 #logging.debug(CleanKeyFrontend)
685 os.system(CleanKeyFrontend)
686
687 if (auth_type == "rebound"):
688 for iFront in reversed(range(NbFrontendTo)):
689 CleanKeyFrontend = "ssh -o ForwardX11=no -i "+sshKeyPath+" "+lUserFront[iFront]+"@"+lFrontend[iFront]+' bash -cvx \'\"sed -i.'+DATE+' /'+myhostname+'/d ~/.ssh/authorized_keys; rm .ssh/'+sshKeyName+'* \"\''
690 logging.warning(CleanKeyFrontend)
691 #logging.debug(CleanKeyFrontend)
692 os.system(CleanKeyFrontend)
693 # On localhost (no need) "ssh-keygen -R "+Frontend+" -f ~/.ssh/known_hosts"
694 logging.warning("TileSet "+TileSet+" removed on server")
695
696 # User not used
697 TVuser=session.query(models.Users).filter(models.Users.id==TVconnection.id_users).first().name
698
699 session.close()
700 engine.dispose()
701 metadata=""
702 conn=""
703 engine=""
704 pool=""
705 session=""
706
707 NbFrontendTo=0
708 NbFrontendFrom=0
709 if (auth_type == "rebound"):
710 while True:
711 try:
712 NbFrontendTo = int(input("Give the number of gateways to go to the HPC frontend (0 if direct connection - ssh auth_type option) : "))
713 # TODO
714 #NbFrontendFrom = int(input("Give the number of gateways to go back from HPC nodes to the Flask server (1 if they need to rebound from the HPC frontend) :"))
715 break
716 except ValueError as err:
717 logging.error("Error : number of gateways - Only one integer.")
718 print(f"Error : {err}\n Number of gateways - Only one integer is acceptable here please. Try again.")
719
720 # Define Key name and local path
721 Frontend = TVconnection.host_address
722 sshKeyName="id_ed_"+Frontend+'_'+myhostname
723 sshKeyPath=os.path.join(Home,".ssh",sshKeyName)
724
725 # Detect ANSI ESC characters in passwords
726 #ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\‍[[0-?]*[ -/]*[@-~])')
727 ansi_escape = re.compile(r'''
728 \x1B # ESC
729 (?: # 7-bit C1 Fe (except CSI)
730 [@-Z\\-_]
731 | # or [ for CSI, followed by a control sequence
732 \‍[
733 [0-?]* # Parameter bytes
734 [ -/]* # Intermediate bytes
735 [@-~] # Final byte
736 )
737''', re.VERBOSE)
738
739 NOT_CONNECTED=True
740 OK_Key=False
741 while NOT_CONNECTED:
742
743 if (auth_type == "rebound"):
744
745 if (NbFrontendTo == 0):
746 auth_type="ssh"
747
748 if (auth_type == "rebound"):
749 lFrontend=[]
750 lUserFront=[]
751 lPassword=[]
752
753 # Build ssh config chain to HPC Frontend
754 #Only Config on Connection container
755 sshconfig="\nStrictHostKeyChecking no\n"
756 config_init="Config for connection for TileSet %s at date %s " % (TileSet, DATE)
757 sshconfig+="\n#---- "+config_init+"\n"
758
759 for iFront in range(NbFrontendTo):
760 while True:
761 try:
762 nFront = input(f"Enter the remote machine name number {iFront+1} : \n")
763 nFront = nFront.encode('ascii').decode()
764 break
765 except Exception as err:
766 logging.error(f"Error : remote machine {iFront+1} name - only ascii chars are available.")
767 print(f"Error : {err}\n Remote machine {iFront+1} name - only ascii chars are available. Try again.")
768
769 lFrontend.append(nFront)
770
771 while True:
772 try:
773 UserFront = input("Enter your remote machine number %d user name \n" % (iFront+1))
774 UserFront = UserFront.encode('ascii').decode()
775 break
776 except Exception as err:
777 logging.error(f"Error : remote machine {iFront+1} Username - only ascii chars are available.")
778 print(f"Error : {err}\n Remote machine {iFront+1} Username - only ascii chars are available. Try again.")
779
780
781 lUserFront.append(UserFront)
782
783 # Add if to ssh chain
784 # First machine is on internet
785 if (iFront > 0):
786 sshconfig +="\n"
787 sshconfig +="Host "+lFrontend[iFront]+"\n"
788 sshconfig +=" User "+lUserFront[iFront]+"\n"
789 sshconfig +=" IdentityFile ~/.ssh/"+sshKeyName+"\n"
790 sshconfig +=" IdentitiesOnly yes"+"\n"
791 sshconfig +=" ProxyJump "+lUserFront[iFront-1]+'@'+lFrontend[iFront-1]+"\n"
792 else:
793 sshconfig +="\n"
794 sshconfig +="Host "+lFrontend[iFront]+"\n"
795 sshconfig +=" User "+lUserFront[iFront]+"\n"
796 sshconfig +=" IdentityFile ~/.ssh/"+sshKeyName+"\n"
797 sshconfig +=" IdentitiesOnly yes"+"\n"
798
799 while True:
800 try:
801 if (sys.version_info[0:3] > (3,14,0)):
802 Password = getpass(f"Enter your password for this machine {iFront+1} for user {UserFront} :\n", echo_char='_')
803 else:
804 Password = getpass(f"Enter your password for this machine {iFront+1} for user {UserFront} :\n")
805 Password=ansi_escape.sub('', Password)
806 break
807 except Exception as err:
808 logging.error(f"Error : remote machine {iFront+1} {UserFront} password - error with password.")
809 print(f"Error : {err}\n remote machine {iFront+1} {UserFront} password - error with password. Try again.")
810
811 lPassword.append(Password)
812
813 if (auth_type == "ssh" or auth_type == "rebound"):
814 logging.warning("Remote machine frontend : "+Frontend)
815 while True:
816 try:
817 UserFront = input(f"Enter your frontend machine {Frontend} user name \n")
818 UserFront = UserFront.encode('ascii').decode()
819 break
820 except Exception as err:
821 logging.error(f"Error : frontend machine {Frontend} Username. only ascii chars are available.")
822 print(f"Error : {err}\n Frontend machine {Frontend} Username - Only ascii chars are available. Try again.")
823
824 while True:
825 try:
826 if (sys.version_info[0:3] > (3,14,0)):
827 Password = getpass(f"Enter your frontend {Frontend} password for this user {UserFront} :\n", echo_char='_')
828 else:
829 Password = getpass(f"Enter your frontend {Frontend} password for this user {UserFront} :\n")
830 Password=ansi_escape.sub('', Password)
831 break
832 except Exception as err:
833 logging.error(f"Error : frontend {Frontend} {UserFront} password error.")
834 print(f"Error : {err}\n Frontend {Frontend} {UserFront} password error. Try again.")
835
836 if (auth_type == "rebound"):
837
838 lFrontend.append(Frontend)
839 lUserFront.append(UserFront)
840 lPassword.append(Password)
841
842 # Write ssh config chain to HPC frontend
843 sshconfig +="\n"
844 sshconfig +="Host "+Frontend+"\n"
845 sshconfig +=" User "+UserFront+"\n"
846 sshconfig +=" IdentityFile ~/.ssh/"+sshKeyName+"\n"
847 sshconfig +=" IdentitiesOnly yes"+"\n"
848 sshconfig +=" ProxyJump "+lUserFront[NbFrontendTo-1]+'@'+lFrontend[NbFrontendTo-1]+"\n"
849 config_end="End config for connection for TileSet %s at date %s" % (TileSet, DATE)
850 sshconfig +="\n#---- "+config_end+"\n"
851
852 # Copy to the end of .ssh/config
853 sshconfigname=".ssh/config"
854 with open(sshconfigname,"w+") as sshconfigf:
855 sshconfigf.write(str(sshconfig))
856 os.system('chmod 600 '+sshconfigname)
857
858 # After connection save (test save/restore container)
859 resp=input("Hit enter or save connection data now of 'n' to change remote login/password.\n")
860
861 if (resp != 'n'):
862
863 if (not OK_Key):
864 cmdgen="ssh-keygen -t ed25519 -N '' -f "+sshKeyPath
865 childgen=pexpect.spawn(cmdgen)
866 childgen.expect('Generating public/private ed25519 key pair.')
867 childgen.expect(pexpect.EOF)
868 childgen.close(force=True)
869 logging.warning("ssh key for this connection OK.")
870 os.system("cp -f "+sshKeyPath+".pub .ssh/authorized_keys")
871 OK_Key=True
872
873 # extract config files for ssh
874 if (os.path.exists("config.tar")):
875 os.system("tar xf config.tar")
876 # On can add a rebound.sh executed on the connection container to build rebound chain
877 if (os.path.exists("rebound.sh")):
878 os.system("bash -c 'chmod u+x rebound.sh; ./rebound.sh 2>&1 > .vnc/out_rebound'")
879
880 auth_frontend=False
881 if (auth_type == "rebound"):
882 lCONNECTED=[]
883 for iFront in range(NbFrontendTo):
884 cmdcopy="ssh-copy-id -f -o ForwardX11=no -o StrictHostKeyChecking=no -i "+sshKeyPath+" "+lUserFront[iFront]+"@"+lFrontend[iFront]
885 #-o UserKnownHostsFile=/dev/null
886 logging.warning("ssh-copy-id command :"+cmdcopy)
887 childcopy=pexpect.spawn(cmdcopy)
888 #out1=childcopy.expect('.*')
889 expindex=childcopy.expect([lUserFront[iFront]+"@"+lFrontend[iFront]+"\'s password: ", ".*Password: ",pexpect.EOF, pexpect.TIMEOUT])
890 if (expindex == 0 or expindex == 1 ):
891 outpass = childcopy.sendline(lPassword[iFront])
892 if outpass < len(lPassword[iFront]):
893 Password = getpass("Wrong password for "+lUserFront[iFront]+"@"+lFrontend[iFront]+". Try again enter your password for this user :\n")
894 Password=ansi_escape.sub('', Password)
895 childcopy.close(force=True)
896 else:
897 expindex=childcopy.expect([pexpect.EOF, pexpect.TIMEOUT])
898 if (expindex != 0):
899 try:
900 logging.error("Error respond from server : "+str(childcopy.before,"utf-8"))
901 except:
902 logging.error("Error respond from server. "+str(expindex))
903 else:
904 logging.warning("ssh authorized key copied on the server.")
905 childcopy.close(force=True)
906 if (childcopy.exitstatus == 0):
907 lCONNECTED.append(True)
908 else:
909 lCONNECTED.append(False)
910 else:
911 try:
912 logging.error("Error with copy id "+str(expindex))
913 logging.error("Spawn output : |"+str(childcopy.before,"utf-8")+"|")
914 if (expindex == 3):
915 logging.warning("after TIMEOUT ")
916 else:
917 logging.warning("after "+str(childcopy.after,"utf-8"))
918 logging.warning("existstatus : ",childcopy.exitstatus, " signalestatus : ",childcopy.signalstatus)
919 except:
920 logging.warning("ssh authorized key copied on the server after password.")
921
922 try:
923 logging.error("load interact prompt to test by hand :")
924 code.interact(banner="Try connection :",local=dict(globals(), **locals()))
925 except SystemExit:
926 pass
927 childcopy.close(force=True)
928 if (childcopy.exitstatus == 0):
929 NOT_CONNECTED=False
930 cmdcopy="scp -p -o ForwardX11=no -o StrictHostKeyChecking=no -i "+sshKeyPath+" "+sshKeyPath+" "+lUserFront[iFront]+"@"+lFrontend[iFront]+":.ssh/"
931 # -o UserKnownHostsFile=/dev/null
932 childcopy=pexpect.spawn(cmdcopy)
933 expindex=childcopy.expect([lUserFront[iFront]+"@"+lFrontend[iFront]+"\'s password: ", ".*Password: ",pexpect.EOF, pexpect.TIMEOUT])
934 if (expindex == 2):
935 logging.warning("ssh private key copied on the server %s." % (lFrontend[iFront]))
936 elif( expindex == 0 or expindex == 1 ):
937 logging.warning("Problem : ssh authorized key NOT copied on the server %s." % (lFrontend[iFront]))
938 outpass = childcopy.sendline(lPassword[iFront])
939 expindex=childcopy.expect([pexpect.EOF, pexpect.TIMEOUT])
940 if (expindex != 0):
941 try:
942 logging.error("Error respond from server : "+str(childcopy.before,"utf-8"))
943 except:
944 logging.error("Error respond from server. "+str(expindex))
945 else:
946 logging.warning("ssh private key copied on the server after password.")
947 childcopy.close(force=True)
948
949 cmdcopy="scp -p -o ForwardX11=no -o StrictHostKeyChecking=no -i "+sshKeyPath+" "+sshKeyPath+".pub "+lUserFront[iFront]+"@"+lFrontend[iFront]+":.ssh/"
950 #-o UserKnownHostsFile=/dev/null
951 childcopy=pexpect.spawn(cmdcopy)
952 expindex=childcopy.expect([lUserFront[iFront]+"@"+lFrontend[iFront]+"\'s password: ", ".*Password: ",pexpect.EOF, pexpect.TIMEOUT])
953 if (expindex == 2):
954 logging.warning("ssh public key copied on the server %s." % (lFrontend[iFront]))
955 elif( expindex == 0 or expindex == 1 ):
956 logging.warning("Problem : ssh authorized key NOT copied on the server %s." % (lFrontend[iFront]))
957 outpass = childcopy.sendline(lPassword[iFront])
958 expindex=childcopy.expect([pexpect.EOF, pexpect.TIMEOUT])
959 if (expindex != 0):
960 try:
961 logging.error("Error respond from server : "+str(childcopy.before,"utf-8"))
962 except:
963 logging.error("Error respond from server. "+str(expindex))
964 else:
965 logging.warning("ssh public key copied on the server after password.")
966 childcopy.close(force=True)
967
968 auth_frontend=True
969
970 if (auth_type == "ssh" or auth_frontend):
971 cmdcopy="ssh-copy-id -f -o ForwardX11=no -o StrictHostKeyChecking=no -i "+sshKeyPath+" "+UserFront+"@"+Frontend
972 # -o UserKnownHostsFile=/dev/null
973 #cmdcopy="bash -c 'ssh-copy-id -f -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "+sshKeyPath+" "+UserFront+"@"+Frontend+ " 2>&1 $HOME/.vnc/out_copy_id'"
974 logging.warning("ssh-copy-id command :"+cmdcopy)
975 childcopy=pexpect.spawn(cmdcopy)
976 #out1=childcopy.expect('.*')
977 expindex=childcopy.expect([UserFront+"@"+Frontend+"\'s password: ", ".*Password: ",pexpect.EOF, pexpect.TIMEOUT]+[lUserFront[iFront]+"@"+lFrontend[iFront]+"\'s password: " for iFront in range(NbFrontendTo)])
978 if (expindex == 0 or expindex == 1 ):
979 outpass = childcopy.sendline(Password)
980 if outpass < len(Password):
981 Password = getpass("Wrong password for "+UserFront+"@"+Frontend+". Try again enter your password for this user :\n")
982 Password=ansi_escape.sub('', Password)
983 childcopy.close(force=True)
984 else:
985 expindex=childcopy.expect([pexpect.EOF, pexpect.TIMEOUT])
986 if (expindex != 0):
987 try:
988 logging.error("Error respond from server : "+str(childcopy.before,"utf-8"))
989 except:
990 logging.error("Error respond from server. "+str(expindex))
991 else:
992 logging.warning("ssh key copied on the server.")
993 childcopy.close(force=True)
994 if (childcopy.exitstatus == 0):
995 NOT_CONNECTED=False
996 else:
997 try:
998 logging.error("Error with copy id %d" % (expindex))
999 logging.error("Spawn output : |"+str(childcopy.before,"utf-8")+"|")
1000 if (expindex == 3):
1001 logging.warning("after TIMEOUT ")
1002 else:
1003 logging.warning("after "+str(childcopy.after,"utf-8"))
1004 logging.warning("existstatus : ",childcopy.exitstatus, " signalestatus : ",childcopy.signalstatus)
1005 except:
1006 logging.warning("ssh key copied on the server.")
1007
1008 try:
1009 logging.error("load interact prompt to test by hand :")
1010 code.interact(banner="Try connection :",local=dict(globals(), **locals()))
1011 except SystemExit:
1012 pass
1013 childcopy.close(force=True)
1014 if (childcopy.exitstatus == 0):
1015 NOT_CONNECTED=False
1016
1017 if (auth_type == "rebound"):
1018 del lPassword
1019
1020 # Get free local PORT for ssh to Frontend TileServer
1021 import socket;
1022 s=socket.socket();
1023 s.bind(("", 0));
1024 sshPORT=str(int(s.getsockname()[1]));
1025 s.close()
1026 # Save/restore here ?
1027 TunnelFrontend = "ssh -o ForwardX11=no -4 -i "+sshKeyPath+" -T -N -nf"+\
1028 " -L "+str(sock.PORTServer)+":"+Frontend+":"+str(sock.PORTServer)+\
1029 " -L "+sshPORT+":localhost:22 "+UserFront+"@"+Frontend
1030
1031 logging.debug(TunnelFrontend)
1032 os.system(TunnelFrontend)
1033 logging.info("ssh tunneling OK.")
1034
1035 lshome="ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost 'ls $HOME/.tiledviz'"
1036 logging.debug(lshome)
1037 os.system(lshome)
1038
1039 mkdirhome="ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost 'mkdir $HOME/.tiledviz'"
1040 logging.debug(mkdirhome)
1041 os.system(mkdirhome)
1042
1043 chmodhome="ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost 'chmod og-rx $HOME/.tiledviz'"
1044 logging.debug(chmodhome)
1045 os.system(chmodhome)
1046
1047 cmdhome="ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost 'echo $HOME'"
1048 logging.debug(cmdhome)
1049 childhome=pexpect.spawn(cmdhome)
1050 expindex=childhome.expect([pexpect.EOF, pexpect.TIMEOUT])
1051 if ( expindex == 0 ):
1052 HomeFront = childhome.before.decode("utf-8").replace("\n","").replace("\r","")
1053 logging.warning(HomeFront)
1054 else:
1055 logging.warning("Error with requiring remote 'home' dir.")
1056 HomeFront = os.path.join("/home",UserFront)
1057 childhome.close(force=True)
1058
1059 TiledVizConfPath=os.path.join(HomeFront,'.tiledviz')
1060
1061 # import Swarm
1062 # if (TVconnection.scheduler_file != ""):
1063 # logging.warning("From DB connection scheduler_file : "+str(TVconnection.scheduler_file))
1064 # logging.warning("Bye !")
1065 #time.sleep(10)
1066
1067 JOBPath=os.path.join(TiledVizConfPath,TileSet+'_'+DATE)
1068
1069 if (auth_type == "ssh"):
1070 WorkdirFrontend = "ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost mkdir "+JOBPath
1071 logging.debug(WorkdirFrontend)
1072 os.system(WorkdirFrontend)
1073
1074 # prepare connect dir :
1075 CONNECTdir=TiledVizPath+"/TVConnections/connect"
1076 CONNECTpath=os.path.join(JOBPath,"connect")
1077
1078 ConnectdirFrontend = 'rsync -va -e "ssh -o ForwardX11=no -T -i '+sshKeyPath+' -p '+sshPORT+' " '+CONNECTdir+' '+UserFront+"@localhost"+":"+JOBPath
1079 logging.debug(ConnectdirFrontend)
1080 os.system(ConnectdirFrontend)
1081
1082 # Send or test TileServer run on server ??
1083 def launch_server(ServerFront):
1084 if ( ServerFront == "" ):
1085 TileServerFrontend = 'scp -o ForwardX11=no -i '+sshKeyPath+' -P '+sshPORT+' '+TiledVizPath+'/TVConnections/TileServer.py '+UserFront+"@localhost"+":"+TiledVizConfPath
1086 logging.debug(TileServerFrontend)
1087 os.system(TileServerFrontend)
1088 cmdTileServer="ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost 'sh -c \"cd "+TiledVizConfPath+"; cp -rp "+os.path.join(JOBPath,"connect")+" .; HOSTNAME=\""+Frontend+"\" python3 TileServer.py > TileServer_"+DATE+".log 2>&1 & \"'"
1089 logging.debug(cmdTileServer)
1090 childTileServer=pexpect.spawn(cmdTileServer)
1091 expindex=childTileServer.expect([pexpect.EOF, pexpect.TIMEOUT])
1092 if ( expindex == 0 ):
1093 logging.warning("TileServer launched on frontend "+Frontend+" !")
1094 time.sleep(2)
1095 else:
1096 logging.warning("Error on TileServer launched on frontend "+Frontend+".")
1097 childTileServer.close(force=True)
1098
1099 def test_TileServer():
1100 cmdServer="ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost 'sh -c \"ps -Aef |grep TileServer |grep -v grep |grep "+UserFront+"\"'"
1101 logging.debug(cmdServer)
1102 childServer=pexpect.spawn(cmdServer)
1103 expindex=childServer.expect([pexpect.EOF, pexpect.TIMEOUT])
1104 if ( expindex == 0 ):
1105 ServerFront = childServer.before.decode("utf-8").replace("\n","").replace("\r","")
1106 logging.debug(ServerFront)
1107 launch_server(ServerFront)
1108 childServer.close(force=True)
1109
1110 test_TileServer()
1111
1112 # Get Job file
1113 filename=TileSetDB.launch_file
1114 #eval(import filename, dict(globals()), dict(locals()))
1115
1116 # ConnectionForm.scheduler = RadioField(label='Type of scheduler on HPC machine',
1117 # description='How to launch containers job on the machine :',
1118 # choices=[("none","No schedule at all : you will have to give the list of machines."),
1119 # ("slurm","Slurm scheduler."),
1120 # ("loadleveler","Loadleveler scheduler.")
1121 # ],
1122 # default=scheduler,
1123 # validators=[Optional()])
1124
1125 # Empty function to let TVSecure get new nodes.json from connectiondock.
1126 def get_new_nodes():
1127 return
1128
1129 # Launch nodes.json file
1130 def launch_nodes_json():
1131 if (os.path.exists("nodes.json")):
1132 os.system('bash -c "mv nodes.json nodes.json_$(date +%F_%H-%M-%S)"')
1133 out_get=get_file_client(client,TileSet,JOBPath,"nodes.json",".")
1134 logging.warning("out of get_file nodes.json size : "+str(out_get))
1135 iter=0
1136 while( out_get <= 0):
1137 time.sleep(2)
1138 out_get=get_file_client(client,TileSet,JOBPath,"nodes.json",".")
1139 logging.warning("out of get_file "+str(iter)+" nodes.json : "+str(out_get))
1140 iter=iter+1
1141 if (iter > 10):
1142 logging.error("Something go wrong with nodes.json. We quit.")
1143 kill_all_containers()
1144 break
1145 #os.system('rm -f ./nodes.json')
1146 return True
1147
1148 # if (args.debug):
1149 # try:
1150 # code.interact(banner="Before client (use raise SystemExit to close prompt)",local=dict(globals(), **locals()))
1151 # except SystemExit:
1152 # pass
1153 # except :
1154 # traceback.print_exc(file=sys.stderr)
1155 # pass
1156
1157 # build connection with TileServer on Frontend
1158 try:
1159 client=sock.client()
1160 except:
1161 logging.warning("Connection is not working with TileServer on Frontend, but the process exists. We ")
1162 cmdServer="ssh -o ForwardX11=no -i "+sshKeyPath+" -p "+sshPORT+" "+UserFront+"@localhost 'sh -c \"pgrep TileServer |xargs kill \"'"
1163 os.system(cmdServer)
1164 logging.debug(cmdServer)
1165
1166 test_TileServer()
1167 try:
1168 client=sock.client()
1169 except:
1170 logging.warning("Second test. Can not connect with TileServer on Frontend. We may stop.")
1171 try:
1172 sys.ps1="$$$ "
1173 code.interact(banner="Wrong socket connection client (use raise Exception to close prompt without exiting).",local=dict(globals(), **locals()))
1174 sys.ps1=">>> "
1175 except SystemExit:
1176 exit(0)
1177 except :
1178 traceback.print_exc(file=sys.stderr)
1179
1180 isActions=False
1181 # Launch Action connection
1182 def launch_actions():
1183 global isActions
1184 try:
1185 time.sleep(2)
1186 logging.warning("Launch actions thread.")
1187 sys.stdout.flush()
1188
1189 GetActions=ServerAction(connectionId,globals=dict(globals()),locals=dict(**locals()))
1190 outHandler.flush()
1191 except:
1192 traceback.print_exc(file=sys.stdout)
1193 code.interact(banner="Error ServerAction :",local=dict(globals(), **locals()))
1194
1195 logging.warning(f"Actions \n {tiles_actions}")
1196 sys.stdout.flush()
1197 isActions=True
1198
1199 # Launch Server for commands from FlaskDock
1200 def launch_actions_and_interact():
1201 global isActions
1202 if (not isActions):
1203 launch_actions()
1204
1205 if (args.debug):
1206 # if (not args.debug):
1207 # try:
1208 # code.interact(banner="Interactive console to use actions directly :",local=dict(globals(), **locals()))
1209 # except SystemExit:
1210 # pass
1211 # except:
1212 # pass
1213
1214 # else:
1215 # input("Debug mode : Wait for you hit return to close connection.\n")
1216 c = get_config()
1217 #c.InteractiveShellEmbed.colors="NoColor"
1218 c.InteractiveShellEmbed.banner1 = "Please type exit() to terminate launch script ."
1219 c.InteractiveShellEmbed.confirm_exit = False
1220 #c.InteractiveShellEmbed.color_info=False
1221 IPython.embed(config=c)
1222 else:
1223 time.sleep(MaxSessionDuration)
1224
1225 # Execute launch file
1226 try:
1227 COMMANDStop="echo 'error script "+filename+"'"
1228 exec(compile(open(filename, "rb").read(), filename, 'exec'), globals(), locals())
1229 #filename.job(globals(), locals())
1230 time.sleep(MaxSessionDuration)
1231 except :
1232 traceback.print_exc(file=sys.stderr)
1233 #myglobals=globals()
1234 #code.interact(local=locals())
1235
1236 pass
1237
1238 # If any, stop containers and remove TileSet and ssh chain
1239 kill_all_containers()
1240
1241 # close connection with server.
1242 client.close()
1243
1244 # Kill ssh tunneling for VNC :
1245 #os.system("ps -Aef | grep 'connect.*@172.17.*' |grep -v grep | sed -e 's%'+user+'\\s*\\‍([0-9]*\\‍).*%\\1%' |xargs kill")
1246 os.system('killall -9 ssh')
1247
1248 if (args.debug):
1249 try:
1250 code.interact(banner="Stop Connections :",local=dict(globals(), **locals()))
1251 except SystemExit:
1252 pass
1253 except :
1254 traceback.print_exc(file=sys.stderr)
1255
run(self, connectionId, globals, locals)
execute(self, globals, locals)