Salome HOME
PR: merge from tag mergeto_trunk_16Jan05
[modules/yacs.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
257 class CatalogServer(Server):
258     def __init__(self,args):
259         self.args=args
260         self.initArgs()
261         self.SCMD1=['SALOME_ModuleCatalog_Server','-common']
262         self.SCMD2=['-personal',
263                     '${HOME}/Salome/resources/CatalogModulePersonnel.xml'] 
264
265     def setpath(self,modules_list,modules_root_dir):
266         cata_path=[]
267         list_modules = modules_list[:]
268         list_modules.reverse()
269         for module in ["KERNEL"] + list_modules:
270             module_root_dir=modules_root_dir[module]
271             module_cata=module+"Catalog.xml"
272             print "   ", module_cata
273             cata_path.extend(
274                 glob.glob(os.path.join(module_root_dir,
275                                        "share",self.args['appname'],
276                                        "resources",module_cata)))
277         self.CMD=self.SCMD1 + [string.join(cata_path,':')] + self.SCMD2
278
279 # ---
280
281 class SalomeDSServer(Server):
282     def __init__(self,args):
283         self.args=args
284         self.initArgs()
285         self.CMD=['SALOMEDS_Server']
286
287 # ---
288
289 class RegistryServer(Server):
290     def __init__(self,args):
291         self.args=args
292         self.initArgs()
293         self.CMD=['SALOME_Registry_Server', '--salome_session','theSession']
294
295 # ---
296
297 class ContainerCPPServer(Server):
298     def __init__(self,args):
299         self.args=args
300         self.initArgs()
301         self.CMD=['SALOME_Container','FactoryServer']
302
303 # ---
304
305 class ContainerPYServer(Server):
306     def __init__(self,args):
307         self.args=args
308         self.initArgs()
309         self.CMD=['SALOME_ContainerPy.py','FactoryServerPy']
310
311 # ---
312
313 class ContainerSUPERVServer(Server):
314     def __init__(self,args):
315         self.args=args
316         self.initArgs()
317         self.CMD=['SALOME_Container','SuperVisionContainer']
318
319 # ---
320
321 class LoggerServer(Server):
322     def __init__(self,args):
323         self.args=args
324         self.initArgs()
325         self.CMD=['SALOME_Logger_Server', 'logger.log']
326
327 # ---
328
329 class SessionLoader(Server):
330     def __init__(self,args):
331         self.args=args
332         self.initArgs()
333         self.CMD=['SALOME_Session_Loader']
334         if "cppContainer" in self.args['standalone'] \
335         or "cppContainer" in self.args['embedded']:
336             self.CMD=self.CMD+['CPP']
337         if "pyContainer" in self.args['standalone'] \
338         or "pyContainer" in self.args['embedded']:
339             self.CMD=self.CMD+['PY']
340         if "supervContainer" in self.args['containers'] \
341         or "supervContainer" in self.args['standalone']:
342             self.CMD=self.CMD+['SUPERV']
343         if self.args['gui']:
344             self.CMD=self.CMD+['GUI']
345         print self.CMD
346
347 # ---
348
349 class SessionServer(Server):
350     def __init__(self,args):
351         self.args=args
352         self.initArgs()
353         self.SCMD1=['SALOME_Session_Server']
354         self.SCMD2=[]
355         if 'registry' in self.args['embedded']:
356             self.SCMD1+=['--with','Registry',
357                          '(','--salome_session','theSession',')']
358         if 'moduleCatalog' in self.args['embedded']:
359             self.SCMD1+=['--with','ModuleCatalog','(','-common']
360             self.SCMD2+=['-personal',
361                      '${HOME}/Salome/resources/CatalogModulePersonnel.xml',')']
362         if 'study' in self.args['embedded']:
363             self.SCMD2+=['--with','SALOMEDS','(',')']
364         if 'cppContainer' in self.args['embedded']:
365             self.SCMD2+=['--with','Container','(','FactoryServer',')']
366
367     def setpath(self,modules_list,modules_root_dir):
368         cata_path=[]
369         list_modules = modules_list[:]
370         list_modules.reverse()
371         for module in ["KERNEL"] + list_modules:
372             module_root_dir=modules_root_dir[module]
373             module_cata=module+"Catalog.xml"
374             print "   ", module_cata
375             cata_path.extend(
376                 glob.glob(os.path.join(module_root_dir,"share",
377                                        self.args['appname'],"resources",
378                                        module_cata)))
379         if 'moduleCatalog' in self.args['embedded']:
380             self.CMD=self.SCMD1 + [string.join(cata_path,':')] + self.SCMD2
381         else:
382             self.CMD=self.SCMD1 + self.SCMD2
383
384 ##      # arguments SALOME_Session_Server pour ddd
385 ##      comm_ddd=""
386 ##      for mot in self.CMD:
387 ##          if mot == "(":
388 ##              comm_ddd+='"(" '
389 ##          elif mot == ")":
390 ##              comm_ddd+='")" '
391 ##          else:
392 ##              comm_ddd+=mot+" "
393 ##      print comm_ddd
394       
395 # ---
396
397 class NotifyServer(Server):
398     def __init__(self,args,modules_root_dir):
399         self.args=args
400         self.initArgs()
401         self.modules_root_dir=modules_root_dir
402         myLogName = os.environ["LOGNAME"]
403         self.CMD=['notifd','-c',
404                   self.modules_root_dir["KERNEL"]
405                   +'/share/salome/resources/channel.cfg',
406                   '-DFactoryIORFileName=/tmp/'+myLogName+'_rdifact.ior',
407                   '-DChannelIORFileName=/tmp/'+myLogName+'_rdichan.ior']
408
409 #
410 # -----------------------------------------------------------------------------
411
412 def startGUI():
413     """Salome Session Graphic User Interface activation"""
414     import SALOME
415     session=clt.waitNS("/Kernel/Session",SALOME.Session)
416     session.GetInterface()
417   
418 # -----------------------------------------------------------------------------
419
420 def startSalome(args, modules_list, modules_root_dir):
421     """Launch all SALOME servers requested by args"""
422     init_time = os.times()
423
424     #
425     # Lancement Session Loader
426     #
427
428     print "startSalome ", args
429     
430     if args['gui']:
431         myServer=SessionLoader(args)
432         myServer.run()
433
434     #
435     # Initialisation ORB et Naming Service
436     #
437    
438     clt=orbmodule.client()
439
440     # (non obligatoire) Lancement Logger Server
441     # et attente de sa disponibilite dans le naming service
442     #
443
444     if args['logger']:
445         myServer=LoggerServer(args)
446         myServer.run()
447         clt.waitLogger("Logger")
448
449     # Notify Server launch
450     #
451
452     myServer=NotifyServer(args,modules_root_dir)
453     myServer.run()
454
455     #
456     # Lancement Registry Server,
457     # attente de la disponibilité du Registry dans le Naming Service
458     #
459
460     if 'registry' not in args['embedded']:
461         myServer=RegistryServer(args)
462         myServer.run()
463         clt.waitNS("/Registry")
464
465     #
466     # Lancement Catalog Server,
467     # attente de la disponibilité du Catalog Server dans le Naming Service
468     #
469
470     if 'moduleCatalog' not in args['embedded']:
471         cataServer=CatalogServer(args)
472         cataServer.setpath(modules_list,modules_root_dir)
473         cataServer.run()
474         import SALOME_ModuleCatalog
475         clt.waitNS("/Kernel/ModulCatalog",SALOME_ModuleCatalog.ModuleCatalog)
476
477     #
478     # Lancement SalomeDS Server,
479     # attente de la disponibilité du SalomeDS dans le Naming Service
480     #
481
482     os.environ["CSF_PluginDefaults"] \
483     = os.path.join(modules_root_dir["KERNEL"],"share",
484                    args['appname'],"resources")
485     os.environ["CSF_SALOMEDS_ResourcesDefaults"] \
486     = os.path.join(modules_root_dir["KERNEL"],"share",
487                    args['appname'],"resources")
488
489     if "GEOM" in modules_list:
490         print "GEOM OCAF Resources"
491         os.environ["CSF_GEOMDS_ResourcesDefaults"] \
492         = os.path.join(modules_root_dir["GEOM"],"share",
493                        args['appname'],"resources")
494         print "GEOM Shape Healing Resources"
495         os.environ["CSF_ShHealingDefaults"] \
496         = os.path.join(modules_root_dir["GEOM"],"share",
497                        args['appname'],"resources")
498
499     if 'study' not in args['embedded']:
500         myServer=SalomeDSServer(args)
501         myServer.run()
502         clt.waitNS("/myStudyManager")
503
504     #
505     # Lancement Session Server
506     #
507
508     mySessionServ = SessionServer(args)
509     mySessionServ.setpath(modules_list,modules_root_dir)
510     mySessionServ.run()
511
512     #macomm2=['ddd']
513     #pid = os.spawnvp(os.P_NOWAIT, macomm2[0], macomm2)
514     #
515     # Attente de la disponibilité du Session Server dans le Naming Service
516     #
517
518     import SALOME
519     session=clt.waitNS("/Kernel/Session",SALOME.Session)
520
521     from Utils_Identity import getShortHostName
522     
523     if os.getenv("HOSTNAME") == None:
524         if os.getenv("HOST") == None:
525             os.environ["HOSTNAME"]=getShortHostName()
526         else:
527             os.environ["HOSTNAME"]=os.getenv("HOST")
528
529     theComputer = getShortHostName()
530   
531     #
532     # Lancement Container C++ local,
533     # attente de la disponibilité du Container C++ local dans le Naming Service
534     #
535
536     if 'cppContainer' in args['standalone']:
537         myServer=ContainerCPPServer(args)
538         myServer.run()
539         clt.waitNS("/Containers/" + theComputer + "/FactoryServer")
540
541     #
542     # Lancement Container Python local,
543     # attente de la disponibilité du Container Python local
544     # dans le Naming Service
545     #
546
547     if 'pyContainer' in args['standalone']:
548         myServer=ContainerPYServer(args)
549         myServer.run()
550         clt.waitNS("/Containers/" + theComputer + "/FactoryServerPy")
551
552     #
553     # Lancement Container Supervision local,
554     # attente de la disponibilité du Container Supervision local
555     # dans le Naming Service
556     #
557
558     if 'supervContainer' in args['standalone']:
559         myServer=ContainerSUPERVServer(args)
560         myServer.run()
561         clt.waitNS("/Containers/" + theComputer + "/SuperVisionContainer")
562
563     end_time = os.times()
564     print
565     print "Start SALOME, elapsed time : %5.1f seconds"% (end_time[4]
566                                                          - init_time[4])
567
568     return clt
569
570 # -----------------------------------------------------------------------------
571
572 def useSalome(args, modules_list, modules_root_dir):
573     """
574     Launch all SALOME servers requested by args,
575     save list of process, give info to user,
576     show registered objects in Naming Service.
577     """
578     
579     clt=None
580     try:
581         clt = startSalome(args, modules_list, modules_root_dir)
582     except:
583         print
584         print
585         print "--- erreur au lancement Salome ---"
586         
587     #print process_id
588     
589     filedict = '/tmp/' + os.getenv('USER') + "_" + str(args['port']) \
590              + '_' + args['appname'].upper() + '_pidict'
591    
592     process_ids = []
593     try:
594         fpid=open(filedict, 'r')
595         process_ids=pickle.load(fpid)
596         fpid.close()
597     except:
598         pass
599     
600     fpid=open(filedict, 'w')
601     process_ids.append(process_id)
602     pickle.dump(process_ids,fpid)
603     fpid.close()
604     
605     print """
606     Saving of the dictionary of Salome processes in %s
607     To kill SALOME processes from a console (kill all sessions from all ports):
608       python killSalome.py 
609     To kill SALOME from the present interpreter, if it is not closed :
610       killLocalPort()      --> kill this session
611                                (use CORBA port from args of runSalome)
612       givenPortKill(port)  --> kill a specific session with given CORBA port 
613       killAllPorts()       --> kill all sessions
614     
615     runSalome, with --killall option, starts with killing
616     the processes resulting from the previous execution.
617     """%filedict
618     
619     #
620     #  Impression arborescence Naming Service
621     #
622     
623     if clt != None:
624         print
625         print " --- registered objects tree in Naming Service ---"
626         clt.showNS()
627
628     return clt
629
630 # -----------------------------------------------------------------------------
631
632 def registerEnv(args, modules_list, modules_root_dir):
633     """
634     Register args, modules_list, modules_root_dir in a file
635     for further use, when SALOME is launched embedded in an other application.
636     """
637     fileEnv = '/tmp/' + os.getenv('USER') + "_" + str(args['port']) \
638             + '_' + args['appname'].upper() + '_env'
639     fenv=open(fileEnv,'w')
640     pickle.dump((args, modules_list, modules_root_dir),fenv)
641     fenv.close()
642     os.environ["SALOME_LAUNCH_CONFIG"] = fileEnv
643
644 # -----------------------------------------------------------------------------
645
646 def no_main():
647     """Salome Launch, when embedded in other application"""
648     fileEnv = os.environ["SALOME_LAUNCH_CONFIG"]
649     fenv=open(fileEnv,'r')
650     args, modules_list, modules_root_dir = pickle.load(fenv)
651     fenv.close()
652     kill_salome(args)
653     clt = useSalome(args, modules_list, modules_root_dir)
654     return clt
655
656 # -----------------------------------------------------------------------------
657
658 def main():
659     """Salome launch as a main application"""
660     args, modules_list, modules_root_dir = get_config()
661     kill_salome(args)
662     set_env(args, modules_list, modules_root_dir)
663     clt = useSalome(args, modules_list, modules_root_dir)
664     return clt,args
665
666 # -----------------------------------------------------------------------------
667
668 if __name__ == "__main__":
669    clt,args = main()