Salome HOME
e423d97bace04f6dc0413e9bb8f2f24260d70477
[modules/kernel.git] / bin / runSalome.py
1 #!/usr/bin/env python
2
3 import sys, os, string, glob, time, pickle
4 import orbmodule
5
6 process_id = {}
7
8 # -----------------------------------------------------------------------------
9
10 def add_path(directory, variable_name):
11     """Function helper to add environment variables"""
12     if not os.environ.has_key(variable_name):
13         os.environ[variable_name] = ""
14         pass
15     if os.path.exists(directory):
16         newpath=[]
17         for _dir in os.environ[variable_name].split(":"):
18             if os.path.exists(_dir):
19                 if not os.path.samefile(_dir, directory):
20                   newpath.append(_dir)
21             else:
22                 if os.path.abspath(_dir) != os.path.abspath(directory):
23                   newpath.append(_dir)
24             pass
25         import string
26         newpath[:0] = [ directory ]
27         newpath = string.join(newpath,":")
28         os.environ[variable_name] = newpath
29         if variable_name == "PYTHONPATH":
30             sys.path[:0] = [directory]
31
32 # -----------------------------------------------------------------------------
33
34 def get_config():
35     """
36     Get list of modules, paths.
37     
38     Read args from launch configure xml file and command line options.
39     Check variables <module>_ROOT_DIR and set list of used modules.
40     Return args, modules_list, modules_root_dir    
41     """
42     
43     # read args from launch configure xml file and command line options
44     
45     import launchConfigureParser
46     args = launchConfigureParser.args
47     
48     # Check variables <module>_ROOT_DIR
49     # and set list of used modules (without KERNEL)
50
51     modules_list = []
52     if args.has_key("modules"):
53         modules_list += args["modules"]
54     # KERNEL must be last in the list to locate it at the first place in PATH 
55     modules_list[:0] = ["KERNEL"]
56     modules_list.reverse()
57
58     modules_root_dir = {}
59
60     to_remove_list=[]
61     for module in modules_list :
62         module_variable=module.upper()+"_ROOT_DIR"
63         if not os.environ.has_key(module_variable):
64             print "*******************************************************"
65             print "*"
66             print "* Environment variable",module_variable,"must be set"
67             print "* Module", module, "will be not available"
68             print "*"
69             print "********************************************************"
70             to_remove_list.append(module)
71             continue
72             pass
73         module_root_dir = os.environ[module_variable]
74         modules_root_dir[module]=module_root_dir
75
76     for to_remove in to_remove_list:
77         modules_list.remove(to_remove)
78
79     while "KERNEL" in modules_list:
80         modules_list.remove("KERNEL")
81         pass
82
83     if "SUPERV" in modules_list and not 'superv' in args['standalone']:
84         args['standalone'].append("superv")
85         pass
86    
87     return args, modules_list, modules_root_dir
88
89 # -----------------------------------------------------------------------------
90
91 def set_env(args, modules_list, modules_root_dir):
92     """Add to the PATH-variables modules specific paths"""
93     
94     python_version="python%d.%d" % sys.version_info[0:2]
95     modules_root_dir_list = []
96     modules_list = modules_list[:] + ["KERNEL"] 
97     for module in modules_list :
98         module_root_dir = modules_root_dir[module]
99         modules_root_dir_list[:0] = [module_root_dir]
100         add_path(os.path.join(module_root_dir,"lib",args['appname']),
101                  "LD_LIBRARY_PATH")
102         add_path(os.path.join(module_root_dir,"bin",args['appname']),
103                  "PATH")
104         if os.path.exists(module_root_dir + "/examples") :
105             add_path(os.path.join(module_root_dir,"examples"),
106                      "PYTHONPATH")
107         add_path(os.path.join(module_root_dir,"bin",args['appname']),
108                  "PYTHONPATH")
109         add_path(os.path.join(module_root_dir,"lib",
110                               python_version,"site-packages",args['appname']),
111                  "PYTHONPATH")
112         add_path(os.path.join(module_root_dir,"lib",args['appname']),
113                  "PYTHONPATH")
114         add_path(os.path.join(module_root_dir,"lib",
115                               python_version,"site-packages",args['appname'],
116                               "shared_modules"),
117                  "PYTHONPATH")
118
119     os.environ["SALOMEPATH"]=":".join(modules_root_dir_list)
120     
121     # special path for logger lib if needeed
122     
123     os.environ["SALOME_trace"]="local"
124     if args['file']:
125         os.environ["SALOME_trace"]=args['file'][0]
126     if args['logger']:
127         os.environ["SALOME_trace"]="with_logger"
128         locdir=os.environ['PWD']
129         libtracedir=os.path.join(locdir,"libSalomeTrace")
130         libtrace = os.path.join(modules_root_dir["KERNEL"],"lib",
131                                 args['appname'],
132                                 "libSALOMELoggerClient.so.0.0.0")
133         libtraceln = os.path.join(libtracedir,"libSALOMELocalTrace.so")
134         aCommand = 'rm -rf ' + libtracedir + "; "
135         aCommand += 'mkdir ' + libtracedir + "; "
136         aCommand += 'ln -s ' + libtrace + " " + libtraceln + "; "
137         aCommand += 'ln -s ' + libtrace + " " + libtraceln + ".0; "
138         aCommand += 'ln -s ' + libtrace + " " + libtraceln + ".0.0.0; "
139         os.system(aCommand)
140         add_path(libtracedir, "LD_LIBRARY_PATH")
141
142     # set environment for SMESH plugins
143
144     if "SMESH" in modules_list:
145         os.environ["SMESH_MeshersList"]="StdMeshers"
146         if not os.environ.has_key("SALOME_StdMeshersResources"):
147             os.environ["SALOME_StdMeshersResources"] \
148             = modules_root_dir["SMESH"]+"/share/"+args["appname"]+"/resources"
149             pass
150         if args.has_key("SMESH_plugins"):
151             for plugin in args["SMESH_plugins"]:
152                 if os.environ.has_key(plugin.upper()+"_ROOT_DIR"):
153                     os.environ["SMESH_MeshersList"] \
154                     = os.environ["SMESH_MeshersList"]+":"+plugin
155                     plugin_root = os.environ[plugin.upper()+"_ROOT_DIR"]
156                     if not os.environ.has_key("SALOME_"+plugin+"Resources"):
157                         os.environ["SALOME_"+plugin+"Resources"] \
158                         = plugin_root+"/share/"+args["appname"]+"/resources"
159                     add_path(os.path.join(plugin_root,"lib",python_version,
160                                           "site-packages",args['appname']),
161                              "PYTHONPATH")
162                     add_path(os.path.join(plugin_root,"lib",args['appname']),
163                              "PYTHONPATH")
164                     add_path(os.path.join(plugin_root,"lib",args['appname']),
165                              "LD_LIBRARY_PATH")
166                     add_path(os.path.join(plugin_root,"bin",args['appname']),
167                              "PYTHONPATH")
168                     add_path(os.path.join(plugin_root,"bin",args['appname']),
169                              "PATH")
170             pass
171         pass
172
173     # set environment for SUPERV module
174     os.environ["ENABLE_MACRO_NODE"]="1"
175    
176
177 # -----------------------------------------------------------------------------
178
179 from killSalome import killAllPorts
180
181 def killLocalPort():
182     """
183     kill servers from a previous SALOME exection, if needed,
184     on the CORBA port given in args of runSalome
185     """
186     
187     from killSalomeWithPort import killMyPort
188     my_port=str(args['port'])
189     try:
190         killMyPort(my_port)
191     except:
192         print "problem in killLocalPort()"
193         pass
194     pass
195     
196 def givenPortKill(port):
197     """
198     kill servers from a previous SALOME exection, if needed,
199     on the same CORBA port
200     """
201     
202     from killSalomeWithPort import killMyPort
203     my_port=port
204     try:
205         killMyPort(my_port)
206     except:
207         print "problem in LocalPortKill(), killMyPort("<<port<<")"
208         pass
209     pass
210
211 def kill_salome(args):
212     """
213     Kill servers from previous SALOME executions, if needed;
214     depending on args 'killall' or 'portkill', kill all executions,
215     or only execution on the same CORBA port
216     """
217
218     if args['killall']:
219         killAllPorts()
220     elif args['portkill']:
221         givenPortKill(str(args['port']))
222         
223 # -----------------------------------------------------------------------------
224 #
225 # Définition des classes d'objets pour le lancement des Server CORBA
226 #
227
228 class Server:
229     """Generic class for CORBA server launch"""
230
231     def initArgs(self):
232         self.CMD=[]
233         self.ARGS=[]    
234         if self.args['xterm']:
235             self.ARGS=['xterm', '-iconic', '-sb', '-sl', '500', '-hold']
236
237     def __init__(self,args):
238         self.args=args
239         self.initArgs()
240
241
242     def run(self):
243         global process_id
244         myargs=self.ARGS
245         if self.args['xterm']:
246             # (Debian) send LD_LIBRARY_PATH to children shells (xterm)
247             env_ld_library_path=['env', 'LD_LIBRARY_PATH='
248                                  + os.getenv("LD_LIBRARY_PATH")]
249             myargs = myargs +['-T']+self.CMD[:1]+['-e'] + env_ld_library_path
250         command = myargs + self.CMD
251         # print "command = ", command
252         pid = os.spawnvp(os.P_NOWAIT, command[0], command)
253         process_id[pid]=self.CMD
254
255
256 class InterpServer(Server):
257     def __init__(self,args):
258         self.args=args
259         env_ld_library_path=['env', 'LD_LIBRARY_PATH=' + os.getenv("LD_LIBRARY_PATH")]
260         self.CMD=['xterm', '-e']+ env_ld_library_path + ['python']
261         #self.CMD=['xterm', '-e', 'python']
262        
263     def run(self):
264         global process_id
265         command = self.CMD
266         print "command = ", command
267         pid = os.spawnvp(os.P_NOWAIT, command[0], command)
268         process_id[pid]=self.CMD
269
270 # ---
271
272 class CatalogServer(Server):
273     def __init__(self,args):
274         self.args=args
275         self.initArgs()
276         self.SCMD1=['SALOME_ModuleCatalog_Server','-common']
277         self.SCMD2=['-personal',
278                     '${HOME}/Salome/resources/CatalogModulePersonnel.xml'] 
279
280     def setpath(self,modules_list,modules_root_dir):
281         cata_path=[]
282         list_modules = modules_list[:]
283         list_modules.reverse()
284         for module in ["KERNEL"] + list_modules:
285             module_root_dir=modules_root_dir[module]
286             module_cata=module+"Catalog.xml"
287             print "   ", module_cata
288             cata_path.extend(
289                 glob.glob(os.path.join(module_root_dir,
290                                        "share",self.args['appname'],
291                                        "resources",module_cata)))
292         self.CMD=self.SCMD1 + [string.join(cata_path,':')] + self.SCMD2
293
294 # ---
295
296 class SalomeDSServer(Server):
297     def __init__(self,args):
298         self.args=args
299         self.initArgs()
300         self.CMD=['SALOMEDS_Server']
301
302 # ---
303
304 class RegistryServer(Server):
305     def __init__(self,args):
306         self.args=args
307         self.initArgs()
308         self.CMD=['SALOME_Registry_Server', '--salome_session','theSession']
309
310 # ---
311
312 class ContainerCPPServer(Server):
313     def __init__(self,args):
314         self.args=args
315         self.initArgs()
316         self.CMD=['SALOME_Container','FactoryServer']
317
318 # ---
319
320 class ContainerPYServer(Server):
321     def __init__(self,args):
322         self.args=args
323         self.initArgs()
324         self.CMD=['SALOME_ContainerPy.py','FactoryServerPy']
325
326 # ---
327
328 class ContainerSUPERVServer(Server):
329     def __init__(self,args):
330         self.args=args
331         self.initArgs()
332         self.CMD=['SALOME_Container','SuperVisionContainer']
333
334 # ---
335
336 class LoggerServer(Server):
337     def __init__(self,args):
338         self.args=args
339         self.initArgs()
340         self.CMD=['SALOME_Logger_Server', 'logger.log']
341
342 # ---
343
344 class SessionLoader(Server):
345     def __init__(self,args):
346         self.args=args
347         self.initArgs()
348         self.CMD=['SALOME_Session_Loader']
349         if "cppContainer" in self.args['standalone'] \
350         or "cppContainer" in self.args['embedded']:
351             self.CMD=self.CMD+['CPP']
352         if "pyContainer" in self.args['standalone'] \
353         or "pyContainer" in self.args['embedded']:
354             self.CMD=self.CMD+['PY']
355         if "supervContainer" in self.args['containers'] \
356         or "supervContainer" in self.args['standalone']:
357             self.CMD=self.CMD+['SUPERV']
358         if self.args['gui']:
359             self.CMD=self.CMD+['GUI']
360         print self.CMD
361
362 # ---
363
364 class SessionServer(Server):
365     def __init__(self,args):
366         self.args=args
367         self.initArgs()
368         self.SCMD1=['SALOME_Session_Server']
369         self.SCMD2=[]
370         if 'registry' in self.args['embedded']:
371             self.SCMD1+=['--with','Registry',
372                          '(','--salome_session','theSession',')']
373         if 'moduleCatalog' in self.args['embedded']:
374             self.SCMD1+=['--with','ModuleCatalog','(','-common']
375             self.SCMD2+=['-personal',
376                      '${HOME}/Salome/resources/CatalogModulePersonnel.xml',')']
377         if 'study' in self.args['embedded']:
378             self.SCMD2+=['--with','SALOMEDS','(',')']
379         if 'cppContainer' in self.args['embedded']:
380             self.SCMD2+=['--with','Container','(','FactoryServer',')']
381
382     def setpath(self,modules_list,modules_root_dir):
383         cata_path=[]
384         list_modules = modules_list[:]
385         list_modules.reverse()
386         for module in ["KERNEL"] + list_modules:
387             module_root_dir=modules_root_dir[module]
388             module_cata=module+"Catalog.xml"
389             print "   ", module_cata
390             cata_path.extend(
391                 glob.glob(os.path.join(module_root_dir,"share",
392                                        self.args['appname'],"resources",
393                                        module_cata)))
394         if 'moduleCatalog' in self.args['embedded']:
395             self.CMD=self.SCMD1 + [string.join(cata_path,':')] + self.SCMD2
396         else:
397             self.CMD=self.SCMD1 + self.SCMD2
398
399 ##      # arguments SALOME_Session_Server pour ddd
400 ##      comm_ddd=""
401 ##      for mot in self.CMD:
402 ##          if mot == "(":
403 ##              comm_ddd+='"(" '
404 ##          elif mot == ")":
405 ##              comm_ddd+='")" '
406 ##          else:
407 ##              comm_ddd+=mot+" "
408 ##      print comm_ddd
409       
410 # ---
411
412 class NotifyServer(Server):
413     def __init__(self,args,modules_root_dir):
414         self.args=args
415         self.initArgs()
416         self.modules_root_dir=modules_root_dir
417         myLogName = os.environ["LOGNAME"]
418         self.CMD=['notifd','-c',
419                   self.modules_root_dir["KERNEL"] +'/share/salome/resources/channel.cfg',
420                   '-DFactoryIORFileName=/tmp/'+myLogName+'_rdifact.ior',
421                   '-DChannelIORFileName=/tmp/'+myLogName+'_rdichan.ior',
422                   '-DReportLogFile=/tmp/'+myLogName+'_notifd.report',
423                   '-DDebugLogFile=/tmp/'+myLogName+'_notifd.debug',
424                   ]
425
426 #
427 # -----------------------------------------------------------------------------
428
429 def startGUI():
430     """Salome Session Graphic User Interface activation"""
431     import SALOME
432     session=clt.waitNS("/Kernel/Session",SALOME.Session)
433     session.GetInterface()
434   
435 # -----------------------------------------------------------------------------
436
437 def startSalome(args, modules_list, modules_root_dir):
438     """Launch all SALOME servers requested by args"""
439     init_time = os.times()
440
441     #
442     # Lancement Session Loader
443     #
444
445     print "startSalome ", args
446     
447     if args['gui']:
448         myServer=SessionLoader(args)
449         myServer.run()
450
451     #
452     # Initialisation ORB et Naming Service
453     #
454    
455     clt=orbmodule.client()
456
457     # (non obligatoire) Lancement Logger Server
458     # et attente de sa disponibilite dans le naming service
459     #
460
461     if args['logger']:
462         myServer=LoggerServer(args)
463         myServer.run()
464         clt.waitLogger("Logger")
465
466     # Notify Server launch
467     #
468
469     print "Notify Server to launch"
470
471     myServer=NotifyServer(args,modules_root_dir)
472     myServer.run()
473
474     #
475     # Lancement Registry Server,
476     # attente de la disponibilité du Registry dans le Naming Service
477     #
478
479     if 'registry' not in args['embedded']:
480         myServer=RegistryServer(args)
481         myServer.run()
482         clt.waitNS("/Registry")
483
484     #
485     # Lancement Catalog Server,
486     # attente de la disponibilité du Catalog Server dans le Naming Service
487     #
488     
489
490     if 'moduleCatalog' not in args['embedded']:
491         cataServer=CatalogServer(args)
492         cataServer.setpath(modules_list,modules_root_dir)
493         cataServer.run()
494         import SALOME_ModuleCatalog
495         clt.waitNS("/Kernel/ModulCatalog",SALOME_ModuleCatalog.ModuleCatalog)
496
497     #
498     # Lancement SalomeDS Server,
499     # attente de la disponibilité du SalomeDS dans le Naming Service
500     #
501
502     os.environ["CSF_PluginDefaults"] \
503     = os.path.join(modules_root_dir["KERNEL"],"share",
504                    args['appname'],"resources")
505     os.environ["CSF_SALOMEDS_ResourcesDefaults"] \
506     = os.path.join(modules_root_dir["KERNEL"],"share",
507                    args['appname'],"resources")
508
509     if "GEOM" in modules_list:
510         print "GEOM OCAF Resources"
511         os.environ["CSF_GEOMDS_ResourcesDefaults"] \
512         = os.path.join(modules_root_dir["GEOM"],"share",
513                        args['appname'],"resources")
514         print "GEOM Shape Healing Resources"
515         os.environ["CSF_ShHealingDefaults"] \
516         = os.path.join(modules_root_dir["GEOM"],"share",
517                        args['appname'],"resources")
518
519     if 'study' not in args['embedded']:
520         myServer=SalomeDSServer(args)
521         myServer.run()
522         clt.waitNS("/myStudyManager")
523
524     #
525     # Lancement Session Server
526     #
527
528     mySessionServ = SessionServer(args)
529     mySessionServ.setpath(modules_list,modules_root_dir)
530     mySessionServ.run()
531
532     #macomm2=['ddd']
533     #pid = os.spawnvp(os.P_NOWAIT, macomm2[0], macomm2)
534     #
535     # Attente de la disponibilité du Session Server dans le Naming Service
536     #
537
538     import SALOME
539     session=clt.waitNS("/Kernel/Session",SALOME.Session)
540
541     from Utils_Identity import getShortHostName
542     
543     if os.getenv("HOSTNAME") == None:
544         if os.getenv("HOST") == None:
545             os.environ["HOSTNAME"]=getShortHostName()
546         else:
547             os.environ["HOSTNAME"]=os.getenv("HOST")
548
549     theComputer = getShortHostName()
550     
551     #
552     # Lancement Container C++ local,
553     # attente de la disponibilité du Container C++ local dans le Naming Service
554     #
555
556     if 'cppContainer' in args['standalone']:
557         myServer=ContainerCPPServer(args)
558         myServer.run()
559         clt.waitNS("/Containers/" + theComputer + "/FactoryServer")
560
561     #
562     # Lancement Container Python local,
563     # attente de la disponibilité du Container Python local
564     # dans le Naming Service
565     #
566
567     if 'pyContainer' in args['standalone']:
568         myServer=ContainerPYServer(args)
569         myServer.run()
570         clt.waitNS("/Containers/" + theComputer + "/FactoryServerPy")
571
572     #
573     # Lancement Container Supervision local,
574     # attente de la disponibilité du Container Supervision local
575     # dans le Naming Service
576     #
577
578     if 'supervContainer' in args['standalone']:
579         myServer=ContainerSUPERVServer(args)
580         myServer.run()
581         clt.waitNS("/Containers/" + theComputer + "/SuperVisionContainer")
582
583     end_time = os.times()
584     print
585     print "Start SALOME, elapsed time : %5.1f seconds"% (end_time[4]
586                                                          - init_time[4])
587
588     #
589     # additionnal external python interpreters
590     #
591     nbaddi=0
592     
593     try:
594         if 'interp' in args:
595             if args['interp']:
596                 nbaddi = int(args['interp'][0])
597     except:
598         import traceback
599         traceback.print_exc()
600         print "-------------------------------------------------------------"
601         print "-- to get an external python interpreter:runSalome --interp=1"
602         print "-------------------------------------------------------------"
603         
604     print "additional external python interpreters: ", nbaddi
605     if nbaddi:
606         for i in range(nbaddi):
607             print "i=",i
608             anInterp=InterpServer(args)
609             anInterp.run()
610     
611     return clt
612
613 # -----------------------------------------------------------------------------
614
615 def useSalome(args, modules_list, modules_root_dir):
616     """
617     Launch all SALOME servers requested by args,
618     save list of process, give info to user,
619     show registered objects in Naming Service.
620     """
621     
622     clt=None
623     try:
624         clt = startSalome(args, modules_list, modules_root_dir)
625     except:
626         import traceback
627         traceback.print_exc()
628         print
629         print
630         print "--- erreur au lancement Salome ---"
631         
632     #print process_id
633     
634     filedict = '/tmp/' + os.getenv('USER') + "_" + str(args['port']) \
635              + '_' + args['appname'].upper() + '_pidict'
636    
637     process_ids = []
638     try:
639         fpid=open(filedict, 'r')
640         process_ids=pickle.load(fpid)
641         fpid.close()
642     except:
643         pass
644     
645     fpid=open(filedict, 'w')
646     process_ids.append(process_id)
647     pickle.dump(process_ids,fpid)
648     fpid.close()
649     
650     print """
651     Saving of the dictionary of Salome processes in %s
652     To kill SALOME processes from a console (kill all sessions from all ports):
653       python killSalome.py 
654     To kill SALOME from the present interpreter, if it is not closed :
655       killLocalPort()      --> kill this session
656                                (use CORBA port from args of runSalome)
657       givenPortKill(port)  --> kill a specific session with given CORBA port 
658       killAllPorts()       --> kill all sessions
659     
660     runSalome, with --killall option, starts with killing
661     the processes resulting from the previous execution.
662     """%filedict
663     
664     #
665     #  Impression arborescence Naming Service
666     #
667     
668     if clt != None:
669         print
670         print " --- registered objects tree in Naming Service ---"
671         clt.showNS()
672
673     return clt
674
675 # -----------------------------------------------------------------------------
676
677 def registerEnv(args, modules_list, modules_root_dir):
678     """
679     Register args, modules_list, modules_root_dir in a file
680     for further use, when SALOME is launched embedded in an other application.
681     """
682     fileEnv = '/tmp/' + os.getenv('USER') + "_" + str(args['port']) \
683             + '_' + args['appname'].upper() + '_env'
684     fenv=open(fileEnv,'w')
685     pickle.dump((args, modules_list, modules_root_dir),fenv)
686     fenv.close()
687     os.environ["SALOME_LAUNCH_CONFIG"] = fileEnv
688
689 # -----------------------------------------------------------------------------
690
691 def no_main():
692     """Salome Launch, when embedded in other application"""
693     fileEnv = os.environ["SALOME_LAUNCH_CONFIG"]
694     fenv=open(fileEnv,'r')
695     args, modules_list, modules_root_dir = pickle.load(fenv)
696     fenv.close()
697     kill_salome(args)
698     clt = useSalome(args, modules_list, modules_root_dir)
699     return clt
700
701 # -----------------------------------------------------------------------------
702
703 def main():
704     """Salome launch as a main application"""
705     args, modules_list, modules_root_dir = get_config()
706     kill_salome(args)
707     set_env(args, modules_list, modules_root_dir)
708     clt = useSalome(args, modules_list, modules_root_dir)
709     return clt,args
710
711 # -----------------------------------------------------------------------------
712
713 if __name__ == "__main__":
714    import user
715    clt,args = main()