]> SALOME platform Git repositories - modules/kernel.git/blob - bin/runSalome.py
Salome HOME
First integration of Salome On Demand
[modules/kernel.git] / bin / runSalome.py
1 #!/usr/bin/env python3
2 #  -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2022  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21
22 ## @package runSalome
23 # \brief Module that provides services to launch SALOME
24 #
25
26 import sys, os, string, glob, time, pickle, re
27 import setenv
28 from server import process_id, Server
29 import json
30 import subprocess
31 from salomeContextUtils import ScriptAndArgsObjectEncoder
32 import runSalomeNoServer
33 import runSalomeCommon
34 import platform
35 import runSalomeOnDemand
36 from launchConfigureParser import verbosity_nam, on_demand_nam
37 import logging
38 logger = logging.getLogger()
39
40 # -----------------------------------------------------------------------------
41
42 from killSalome import killAllPorts
43
44 def kill_salome(args):
45     """
46     Kill servers from previous SALOME executions, if needed;
47     depending on args 'killall' or 'portkill', kill all executions,
48     or only execution on the same CORBA port
49     """
50
51     if args['killall']:
52         killAllPorts()
53 #
54 # -----------------------------------------------------------------------------
55
56 def startGUI(clt):
57     """Salome Session Graphic User Interface activation"""
58     import Engines
59     import SALOME
60     import SALOMEDS
61     import SALOME_ModuleCatalog
62     import SALOME_Session_idl
63     session=clt.waitNS("/Kernel/Session",SALOME.Session)
64     session.GetInterface()
65
66 # -----------------------------------------------------------------------------
67
68 def startSalome(args, modules_list, modules_root_dir):
69     """Launch all SALOME servers requested by args"""
70     init_time = os.times()
71
72     logger.debug("startSalome : {} ".format(args))
73
74     ior_fakens_filename = None
75
76     # Launch  Session Server (to show splash ASAP)
77     #
78
79     if args["gui"] and not args['launcher_only']:
80         mySessionServ = runSalomeNoServer.NoSessionServer(args,args['modules'],modules_root_dir)
81         mySessionServ.setpath(modules_list,modules_root_dir)
82         mySessionServ.run()
83         ior_fakens_filename = mySessionServ.iorfakens
84         logger.debug("Rendez-vous file for to retrieve IOR of session is \"{}\"".format(ior_fakens_filename))
85
86     end_time = os.times()
87
88     #
89     # Wait until Session Server is registered in naming service
90     #
91     logger.debug("Start SALOME, elapsed time : %5.1f seconds"% (end_time[4] - init_time[4]))
92
93     #
94     # additional external python interpreters
95     #
96     nbaddi=0
97
98     try:
99         if 'interp' in args:
100             nbaddi = args['interp']
101     except Exception:
102         import traceback
103         traceback.print_exc()
104         logger.error("-------------------------------------------------------------")
105         logger.error("-- to get an external python interpreter:runSalome --interp=1")
106         logger.error("-------------------------------------------------------------")
107
108     logger.debug("additional external python interpreters: {}".format(nbaddi))
109     if nbaddi:
110         for i in range(nbaddi):
111             anInterp=runSalomeCommon.InterpServer(args)
112             anInterp.run()
113
114     # set PYTHONINSPECT variable (python interpreter in interactive mode)
115     if args['pinter']:
116         os.environ["PYTHONINSPECT"]="1"
117         try:
118             import readline
119         except ImportError:
120             pass
121
122     return ior_fakens_filename
123
124 # -----------------------------------------------------------------------------
125
126 def useSalome(args, modules_list, modules_root_dir):
127     """
128     Launch all SALOME servers requested by args,
129     save list of process, give info to user,
130     show registered objects in Naming Service.
131     """
132     global process_id
133     ior_fakens_filename = None
134     try:
135         ior_fakens_filename = startSalome(args, modules_list, modules_root_dir)
136     except Exception:
137         import traceback
138         traceback.print_exc()
139         logger.error("--- Error during Salome launch ---")
140
141     # print(process_id)
142
143     from addToKillList import addToKillList
144     from killSalomeWithPort import getPiDict
145
146     filedict = getPiDict(args['port'])
147     for pid, cmd in list(process_id.items()):
148         addToKillList(pid, cmd, args['port'])
149         pass
150
151     logger.debug("""
152     Saving of the dictionary of Salome processes in %s
153     To kill SALOME processes from a console (kill all sessions from all ports):
154       python killSalome.py
155     To kill SALOME from the present interpreter, if it is not closed :
156       killLocalPort()      --> kill this session
157                                (use CORBA port from args of runSalome)
158       givenPortKill(port)  --> kill a specific session with given CORBA port
159       killAllPorts()       --> kill all sessions
160
161     runSalome, with --killall option, starts with killing
162     the processes resulting from the previous execution.
163     """%filedict)
164
165     return ior_fakens_filename
166
167 def execScript(script_path):
168     print('executing', script_path)
169     sys.path.insert(0, os.path.realpath(os.path.dirname(script_path)))
170     exec(compile(open(script_path).read(), script_path, 'exec'),globals())
171     del sys.path[0]
172
173 # -----------------------------------------------------------------------------
174
175 def main(exeName=None):
176     """Salome launch as a main application"""
177     keep_env = not os.getenv('SALOME_PLEASE_SETUP_ENVIRONMENT_AS_BEFORE')
178     args, modules_list, modules_root_dir = setenv.get_config(exeName=exeName, keepEnvironment=keep_env)
179     runSalomeCommon.setVerbose(args[verbosity_nam])
180
181     kill_salome(args)
182     # --
183
184     # Setup extension's env in salome on demand case
185     if args[on_demand_nam]:
186         runSalomeOnDemand.set_ext_env()
187         # Reset up module_list and modules_root_dir, if we dont want to define SalomeAppConfig on salome.py.
188         # We must remove the "else" on "if os.sys.platform == 'win32':" in launcheConfigureParser.py too.
189         args, _, __ = setenv.get_config(exeName=exeName, keepEnvironment=keep_env)
190
191     setenv.set_env(args, modules_list, modules_root_dir, keepEnvironment=keep_env)
192     ior_fakens_filename = useSalome(args, modules_list, modules_root_dir)
193     # Management of -t <script.py>
194     toimport = []
195     env = os.environ
196     if 'gui' in args and 'session_gui' in args:
197         if not args['gui'] or not args['session_gui']:
198             if 'study_hdf' in args:
199                 toopen = args['study_hdf']
200                 if toopen:
201                     os.environ["PATH_TO_STUDY_FILE_TO_INITIATE"] = toopen
202                     logger.debug("An input Study has been specified {} -> pass it with PATH_TO_STUDY_FILE_TO_INITIATE env var".format(toopen))
203             if 'pyscript' in args:
204                 toimport = args['pyscript']
205     from salomeContextUtils import formatScriptsAndArgs
206     from addToKillList import addToKillList
207     command = formatScriptsAndArgs(toimport, escapeSpaces=True)
208     if command:
209         logger.debug("Launching following shell command : {}".format(str(command)))
210         proc = subprocess.Popen(command, shell=True, env = env)
211         addToKillList(proc.pid, command)
212         res = proc.wait()
213         if res: sys.exit(1)
214     return args, ior_fakens_filename
215
216 # -----------------------------------------------------------------------------
217
218 def foreGround(args, ior_fakens_filename):
219     # --
220     import os
221     gui_detected = False
222     dt = 0.1
223     nbtot = 200
224     nb = 0
225     if ior_fakens_filename is None:
226         logger.warn("No file set to host IOR of the fake naming server")
227         return
228     if not os.path.exists(ior_fakens_filename):
229         logger.warn("No file {} set to host IOR of the fake naming server does not exit !")
230         return
231     import CORBA
232     #import Engines
233     #import SALOME
234     from time import sleep
235     orb = CORBA.ORB_init([''], CORBA.ORB_ID)
236     ior_fakens = None
237     session = None
238     while True:
239         try:
240             ior_fakens = orb.string_to_object(open(ior_fakens_filename).read())
241             session = orb.string_to_object(ior_fakens.Resolve("/Kernel/Session").decode())
242         except Exception:
243             pass
244         if ( session is not None ) and (not CORBA.is_nil(session)):
245             try:
246                 os.remove(ior_fakens_filename)
247                 logger.debug("File {} has been removed".format(ior_fakens_filename))
248             except:
249                 pass
250             logger.debug("Session in child process has been found ! yeah ! {}".format(str(session)))
251             break
252         sleep(dt)
253         nb += 1
254         logger.debug("Unfortunately Session not found into {} : Sleep and retry. {}/{}".format(ior_fakens_filename,nb,nbtot))
255         if nb == nbtot:
256             break
257     nb = 0
258     # --
259     # Wait until gui is arrived
260     # tmax = nbtot * dt
261     # --
262     session_pid = None
263     while 1:
264         try:
265             status = session.GetStatSession()
266             gui_detected = status.activeGUI
267             session_pid = session.getPID()
268             logger.debug("Process of the session under monitoring {}".format(session_pid))
269         except Exception:
270             pass
271         if gui_detected:
272             break
273         sleep(dt)
274         nb += 1
275         if nb == nbtot:
276             break
277         pass
278     # --
279     if not gui_detected:
280         return
281     # --
282     from salome_utils import getPortNumber
283     port = getPortNumber()
284     # --
285     dt = 1.0
286     try:
287         while 1:
288             try:
289                 status = session.GetStatSession()
290                 assert status.activeGUI
291             except Exception:
292                 logger.debug("Process of the session under monitoring {} has vanished !".format(session_pid))
293                 break
294             from time import sleep
295             sleep(dt)
296             pass
297         pass
298     except KeyboardInterrupt:
299         logger.debug("Keyboard requested : killing all process attached to port {}".format(port))
300     finally:
301         from killSalomeWithPort import killProcessSSL
302         killProcessSSL(port,[session_pid])
303     return
304 #
305
306 def runSalome():
307     args, ior_fakens_filename = main()
308     # --
309     test = args['gui'] and args['session_gui']
310     test = test and not args[on_demand_nam]
311     test = test or args['wake_up_session']
312     # --
313     # The next test covers the --pinter option or if var PYTHONINSPECT is set
314     # --
315     test = test and not os.environ.get('PYTHONINSPECT')
316     # --
317     # The next test covers the python -i $KERNEL_ROOT_DIR/bin/salome/runSalome.py case
318     # --
319     try:
320         from ctypes import POINTER, c_int, cast, pythonapi
321         iflag_ptr = cast(pythonapi.Py_InteractiveFlag, POINTER(c_int))
322         test = test and not iflag_ptr.contents.value
323     except Exception:
324         pass
325     # --
326 #    test = test and os.getenv("SALOME_TEST_MODE", "0") != "1"
327     test = test and args['foreground']
328     # --
329     if test:
330         from time import sleep
331         sleep(3.0)
332         foreGround(args, ior_fakens_filename)
333         pass
334     pass
335 #
336
337 # -----------------------------------------------------------------------------
338
339 if __name__ == "__main__":
340     runSalome()
341 #