X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=bin%2FsalomeContext.py;h=41bbb9d0bdf89ba21a6fd443a8ebc1607cdc6933;hb=8306d70519d0426fca4862042219799dfcfe4f38;hp=8a78e1442f586de5bd0e0ed0e15f9dc88043e757;hpb=ee1423ae556e68ac97fb6fa6c99978ff555c0ea8;p=modules%2Fkernel.git diff --git a/bin/salomeContext.py b/bin/salomeContext.py old mode 100644 new mode 100755 index 8a78e1442..41bbb9d0b --- a/bin/salomeContext.py +++ b/bin/salomeContext.py @@ -1,4 +1,5 @@ -# Copyright (C) 2013-2017 CEA/DEN, EDF R&D, OPEN CASCADE +#! /usr/bin/env python3 +# Copyright (C) 2013-2022 CEA/DEN, EDF R&D, OPEN CASCADE # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -27,6 +28,7 @@ from parseConfigFile import parseConfigFile import tempfile import pickle import subprocess +import sys import platform from salomeContextUtils import SalomeContextException @@ -37,22 +39,25 @@ Usage: salome [command] [options] [--config=] Commands: ========= - start Start a new SALOME instance. + start Start a new SALOME instance. Start a single SALOME_Session_Server_No_Server + process with environment relevant to the application and hosting all servants in it. context Initialize SALOME context. Current environment is extended. shell Initialize SALOME context, attached to the last created SALOME instance if any, and executes scripts passed as command arguments. User works in a Shell terminal. SALOME environment is set but application is not started. - connect Connect a Python console to the active SALOME instance. - kill Terminate SALOME instances running on given ports for current user. - Port numbers must be separated by blank characters. - killall Terminate *all* SALOME running instances for current user. - Do not start a new one. test Run SALOME tests. info Display some information about SALOME. doc Show online module documentation (if available). Module names must be separated by blank characters. help Show this message. + remote run command in SALOME environment from remote call, ssh or rsh. + withsession Start a new SWS SALOME instance with multiple servers hosting all servants. + connect In SWS context, Connect a Python console to the active SALOME instance. + kill In SWS context, Terminate SALOME instances running on given ports for current user. + Port numbers must be separated by blank characters. + killall Terminate *all* SALOME running SWS instances for current user. + Do not start a new one. If no command is given, default is start. @@ -64,7 +69,7 @@ Command options: --config= ========================== Initialize SALOME context from a list of context files and/or a list - of folders containing context files. The list is comma-separated, whithout + of folders containing context files. The list is comma-separated, without any blank characters. ''' @@ -84,7 +89,7 @@ class SalomeContext: """ def __init__(self, configFileNames=0): self.getLogger().setLevel(logging.INFO) - #it could be None explicitely (if user use multiples setVariable...for standalone) + #it could be None explicitly (if user use multiples setVariable...for standalone) if configFileNames is None: return configFileNames = configFileNames or [] @@ -100,14 +105,16 @@ class SalomeContext: self.getLogger().error("Unrecognized extension for configuration file: %s", filename) # - def __loadMPI(self, module_name): - print("Trying to load MPI module: %s..."%module_name) + def __loadEnvModules(self, env_modules): + modulecmd = os.getenv('LMOD_CMD') + if not modulecmd: + raise SalomeContextException("Module environment not present") + return try: - out, err = subprocess.Popen(["modulecmd", "python", "load", module_name], stdout=subprocess.PIPE).communicate() - exec(out) # define specific environment variables - print(" OK") - except: - print(" ** Failed **") + out, err = subprocess.Popen([modulecmd, "python", "try-load"] + env_modules, stdout=subprocess.PIPE).communicate() + exec(out) # define specific environment variables + except Exception: + raise SalomeContextException("Failed to load env modules: %s ..." % ' '.join(env_modules)) pass # @@ -115,22 +122,22 @@ class SalomeContext: import os # Run this module as a script, in order to use appropriate Python interpreter # according to current path (initialized from context files). - mpi_module_option = "--with-mpi-module=" - mpi_module = [x for x in args if x.startswith(mpi_module_option)] - if mpi_module: - mpi_module = mpi_module[0][len(mpi_module_option):] - self.__loadMPI(mpi_module) - args = [x for x in args if not x.startswith(mpi_module_option)] + env_modules_option = "--with-env-modules=" + env_modules_l = [x for x in args if x.startswith(env_modules_option)] + if env_modules_l: + env_modules = env_modules_l[-1][len(env_modules_option):].split(',') + self.__loadEnvModules(env_modules) + args = [x for x in args if not x.startswith(env_modules_option)] else: - mpi_module = os.getenv("SALOME_MPI_MODULE_NAME", None) - if mpi_module: - self.__loadMPI(mpi_module) + env_modules = os.getenv("SALOME_ENV_MODULES", None) + if env_modules: + self.__loadEnvModules(env_modules.split(',')) absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','') env_copy = os.environ.copy() - selfBytes= pickle.dumps(self,protocol=0) - argsBytes= pickle.dumps(args,protocol=0) - proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), selfBytes.decode(), argsBytes.decode()], shell=False, close_fds=True, env=env_copy) + selfBytes= pickle.dumps(self, protocol=0) + argsBytes= pickle.dumps(args, protocol=0) + proc = subprocess.Popen(['python3', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), selfBytes.decode('latin1'), argsBytes.decode('latin1')], shell=False, close_fds=True, env=env_copy) out, err = proc.communicate() return out, err, proc.returncode # @@ -142,9 +149,9 @@ class SalomeContext: """Append value to LD_LIBRARY_PATH environment variable""" def addToLdLibraryPath(self, value): - if platform.system() == 'Windows': + if sys.platform == 'win32': self.addToVariable('PATH', value) - elif platform.system() == 'Darwin': + elif sys.platform == 'darwin': if "LAPACK" in value: self.addToVariable('DYLD_FALLBACK_LIBRARY_PATH', value) else: @@ -178,13 +185,21 @@ class SalomeContext: os.environ[name] = value # + def setDefaultValue(self, name, value): + """ Set environment variable only if it is undefined.""" + env = os.getenv(name, '') + if not env: + value = os.path.expandvars(value) # expand environment variables + self.getLogger().debug("Set environment variable: %s=%s", name, value) + os.environ[name] = value + """Unset environment variable""" def unsetVariable(self, name): - if os.environ.has_key(name): + if name in os.environ: del os.environ[name] # - """Append value to environment variable""" + """Prepend value to environment variable""" def addToVariable(self, name, value, separator=os.pathsep): if value == '': return @@ -198,6 +213,19 @@ class SalomeContext: os.environ[name] = value + separator + env # + """Append a variable""" + def appendVariable(self, name, value, separator=os.pathsep): + if value == '': + return + + value = os.path.expandvars(value) # expand environment variables + env = os.getenv(name, None) + if env is None: + os.environ[name] = value + else: + os.environ[name] = env + separator + value + return + ################################### # This begins the private section # ################################### @@ -210,9 +238,11 @@ class SalomeContext: options = args[1:] availableCommands = { - 'start' : '_runAppli', + 'start' : '_sessionless', + 'withsession' : '_runAppli', 'context' : '_setContext', 'shell' : '_runSession', + 'remote' : '_runRemote', 'connect' : '_runConsole', 'kill' : '_kill', 'killall' : '_killAll', @@ -233,7 +263,7 @@ class SalomeContext: """ Run SALOME! - Args consist in a mandatory command followed by optionnal parameters. + Args consist in a mandatory command followed by optional parameters. See usage for details on commands. """ def _startSalome(self, args): @@ -247,7 +277,7 @@ class SalomeContext: path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome", "appliskel")) add_path(path, "PYTHONPATH") - except: + except Exception: pass command, options = self.__parseArguments(args) @@ -258,30 +288,35 @@ class SalomeContext: usage() return 0 # try to default to "start" command - command = "_runAppli" + command = "_sessionless" try: res = getattr(self, command)(options) # run appropriate method return res or 0 - except SystemExit as returncode: - if returncode != 0: - self.getLogger().error("SystemExit %s in method %s.", returncode, command) - return returncode + except SystemExit as ex: + if ex.code != 0: + self.getLogger().error("SystemExit %s in method %s.", ex.code, command) + return ex.code + except SalomeContextException as e: + self.getLogger().error(e) + return 1 except Exception: self.getLogger().error("Unexpected error:") import traceback traceback.print_exc() return 1 - except SalomeContextException as e: - self.getLogger().error(e) - return 1 # def __setContextFromConfigFile(self, filename, reserved=None): + mesa_root_dir = "MESA_ROOT_DIR" if reserved is None: reserved = [] try: - unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved) + configInfo = parseConfigFile(filename, reserved) + unsetVars = configInfo.unsetVariables + configVars = configInfo.outputVariables + reservedDict = configInfo.reservedValues + defaultValues = configInfo.defaultValues except SalomeContextException as e: msg = "%s"%e self.getLogger().error(msg) @@ -291,6 +326,16 @@ class SalomeContext: for var in unsetVars: self.unsetVariable(var) + # mesa stuff + if "MESA_GL_VERSION_OVERRIDE" in os.environ: + configVarsDict = {k:v for (k,v) in configVars} + if mesa_root_dir in configVarsDict: + path_to_mesa_lib = os.path.join(configVarsDict[mesa_root_dir],"lib") + if os.name == "posix": + self.addToVariable("LD_LIBRARY_PATH",path_to_mesa_lib) + else: + self.addToVariable("PATH",path_to_mesa_lib) + # set context for reserved in reservedDict: a = [_f for _f in reservedDict[reserved] if _f] # remove empty elements @@ -302,10 +347,15 @@ class SalomeContext: self.addToVariable(reserved, reformattedVals) pass + for key,val in configVars: self.setVariable(key, val, overwrite=True) pass + for key,val in defaultValues: + self.setDefaultValue(key, val) + pass + pythonpath = os.getenv('PYTHONPATH','').split(os.pathsep) pythonpath = [ os.path.realpath(x) for x in pythonpath ] sys.path[:0] = pythonpath @@ -315,12 +365,25 @@ class SalomeContext: if args is None: args = [] # Initialize SALOME environment + sys.argv = ['runSalomeOld'] + args + import setenv + setenv.main(True, exeName="salome withsession") + + import runSalomeOld + runSalomeOld.runSalome() + return 0 + # + + def _sessionless(self, args=None): + if args is None: + args = [] sys.argv = ['runSalome'] + args import setenv - setenv.main(True, exeName="salome start") + setenv.main(True, exeName="salome withsession") import runSalome runSalome.runSalome() + return 0 # def _setContext(self, args=None): @@ -330,7 +393,7 @@ class SalomeContext: print("*** SALOME context has already been set.") print("*** Enter 'exit' (only once!) to leave SALOME context.") print("***") - return + return 0 os.environ["SALOME_CONTEXT_SET"] = "yes" print("***") @@ -338,9 +401,13 @@ class SalomeContext: print("*** Enter 'exit' (only once!) to leave SALOME context.") print("***") - cmd = ["/bin/bash"] + if sys.platform == 'win32': + cmd = ['cmd.exe'] + else: + cmd = ["/bin/bash"] proc = subprocess.Popen(cmd, shell=False, close_fds=True) - return proc.communicate() + proc.communicate() + return proc.returncode # def _runSession(self, args=None): @@ -357,6 +424,18 @@ class SalomeContext: return runSession.runSession(params, args) # + def _runRemote(self, args=None): + if args is None: + args = [] +# complete salome environment + sys.argv = ['runRemote'] + import setenv + setenv.main(True) + + import runRemote + return runRemote.runRemote(args) + # + def _runConsole(self, args=None): if args is None: args = [] @@ -375,38 +454,49 @@ class SalomeContext: ports = args if not ports: print("Port number(s) not provided to command: salome kill ") - return + return 1 - from multiprocessing import Process - from killSalomeWithPort import killMyPort - import tempfile + import subprocess + sys.argv = ['kill'] + import setenv + setenv.main(True) + if os.getenv("NSHOST") == "no_host": + os.unsetenv("NSHOST") for port in ports: - with tempfile.NamedTemporaryFile(): - p = Process(target = killMyPort, args=(port,)) - p.start() - p.join() - pass + if sys.platform == "win32": + proc = subprocess.Popen([os.getenv("PYTHONBIN"), "-m", "killSalomeWithPort", str(port)]) + else: + proc = subprocess.Popen(["killSalomeWithPort.py", str(port)]) + proc.communicate() + return 0 # def _killAll(self, unused=None): + sys.argv = ['killAll'] + import setenv + setenv.main(True) + if os.getenv("NSHOST") == "no_host": + os.unsetenv("NSHOST") try: import PortManager # mandatory - from multiprocessing import Process - from killSalomeWithPort import killMyPort + import subprocess ports = PortManager.getBusyPorts()['this'] if ports: - import tempfile for port in ports: - with tempfile.NamedTemporaryFile(): - p = Process(target = killMyPort, args=(port,)) - p.start() - p.join() + if sys.platform == "win32": + proc = subprocess.Popen([os.getenv("PYTHONBIN"), "-m", "killSalomeWithPort", str(port)]) + else: + proc = subprocess.Popen(["killSalomeWithPort.py", str(port)]) + proc.communicate() except ImportError: # :TODO: should be declared obsolete from killSalome import killAllPorts killAllPorts() pass + from addToKillList import killList + killList() + return 0 # def _runTests(self, args=None): @@ -433,18 +523,18 @@ class SalomeContext: versions[software.upper()] = version if len(software) > max_len: max_len = len(software) - except: + except Exception: pass pass pass if softwares: for soft in softwares: - if versions.has_key(soft.upper()): + if soft.upper() in versions: print(soft.upper().rjust(max_len), versions[soft.upper()]) else: import collections od = collections.OrderedDict(sorted(versions.items())) - for name, version in od.iteritems(): + for name, version in od.items(): print(name.rjust(max_len), versions[name]) pass @@ -468,7 +558,7 @@ Available options are: if "-h" in args or "--help" in args: print(usage + epilog) - return + return 0 if "-p" in args or "--ports" in args: import PortManager @@ -500,7 +590,9 @@ Available options are: if "-v" in args or "--version" in args: print("Running with python", platform.python_version()) - self._runAppli(["--version"]) + return self._sessionless(["--version"]) + + return 0 # def _showDoc(self, args=None): @@ -510,7 +602,7 @@ Available options are: modules = args if not modules: print("Module(s) not provided to command: salome doc ") - return + return 1 appliPath = os.getenv("ABSOLUTE_APPLI_PATH") if not appliPath: @@ -615,8 +707,8 @@ Available options are: if __name__ == "__main__": if len(sys.argv) == 3: - context = pickle.loads(sys.argv[1].encode()) - args = pickle.loads(sys.argv[2].encode()) + context = pickle.loads(sys.argv[1].encode('latin1')) + args = pickle.loads(sys.argv[2].encode('latin1')) status = context._startSalome(args) sys.exit(status)