X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=bin%2FsalomeContext.py;h=c5eda0a516aae432bd351660860b6baa6970c852;hb=f2d7bee74f47cd695b4c4b9b0921424837140d0c;hp=98d2453571e990b9917cefa86b4a4c46cc25f563;hpb=e8ea5c566a690b3e3d24df9a3a4f9de8d52883a4;p=modules%2Fkernel.git diff --git a/bin/salomeContext.py b/bin/salomeContext.py index 98d245357..c5eda0a51 100644 --- a/bin/salomeContext.py +++ b/bin/salomeContext.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +# Copyright (C) 2013-2016 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 @@ -31,90 +31,120 @@ import subprocess import platform from salomeContextUtils import SalomeContextException -from salomeContextUtils import getScriptsAndArgs, formatScriptsAndArgs def usage(): - #exeName = os.path.splitext(os.path.basename(__file__))[0] - msg = '''\ -Usage: salome [command] [options] [--config=file1,...,filen] +Usage: salome [command] [options] [--config=] Commands: - start Launches SALOME virtual application [DEFAULT] - shell Executes a script under SALOME application environment - connect Connects a Python console to the active SALOME session - killall Kill all SALOME running sessions - info Display some information about SALOME - help Show this message - coffee Yes! SALOME can also make coffee!!" - -Use salome start --help or salome shell --help -to show help on start and shell commands. +========= + start Start a new SALOME instance. + 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. + help Show this message. + +If no command is given, default to start. + +Command options: +================ + Use salome --help to show help on command ; available for commands: + start, shell, connect, test, info. + +--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 + any blank characters. ''' print msg # """ -The SalomeContext class in an API to configure SALOME environment then +The SalomeContext class in an API to configure SALOME context then start SALOME using a single python command. """ class SalomeContext: """ - Initialize environment from a list of configuration files + Initialize context from a list of configuration files identified by their names. These files should be in appropriate (new .cfg) format. However you can give old .sh environment files; in this case, the SalomeContext class will try to automatically convert them - to .cfg format before setting the environment. + to .cfg format before setting the context. """ - def __init__(self, configFileNames=[]): + def __init__(self, configFileNames=0): + self.getLogger().setLevel(logging.INFO) #it could be None explicitely (if user use multiples setVariable...for standalone) - if configFileNames==None: + if configFileNames is None: return - + configFileNames = configFileNames or [] if len(configFileNames) == 0: raise SalomeContextException("No configuration files given") - reserved=['PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH'] + reserved=['PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH', 'INCLUDE', 'LIBPATH', 'SALOME_PLUGINS_PATH'] for filename in configFileNames: basename, extension = os.path.splitext(filename) if extension == ".cfg": - self.__setEnvironmentFromConfigFile(filename, reserved) + self.__setContextFromConfigFile(filename, reserved) elif extension == ".sh": #new convert procedures, temporary could be use not to be automatically deleted #temp = tempfile.NamedTemporaryFile(suffix='.cfg', delete=False) temp = tempfile.NamedTemporaryFile(suffix='.cfg') try: convertEnvFileToConfigFile(filename, temp.name, reserved) - self.__setEnvironmentFromConfigFile(temp.name, reserved) - except ConfigParser.ParsingError, e: - self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename)) - print e - print '\n' - finally: - # Automatically cleans up the file + self.__setContextFromConfigFile(temp.name, reserved) temp.close() + except (ConfigParser.ParsingError, ValueError) as e: + self.getLogger().error("Invalid token found when parsing file: %s\n"%(filename)) + temp.close() + sys.exit(1) else: self.getLogger().warning("Unrecognized extension for configuration file: %s", filename) # + def __loadMPI(self, module_name): + print "Trying to load MPI module: %s..."%module_name, + 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 **" + pass + # + def runSalome(self, args): + import os # Run this module as a script, in order to use appropriate Python interpreter - # according to current path (initialized from environment files). - kill = False - for e in args: - if "--shutdown-server" in e: - kill = True - args.remove(e) + # 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)] + else: + mpi_module = os.getenv("SALOME_MPI_MODULE_NAME", None) + if mpi_module: + self.__loadMPI(mpi_module) absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','') - proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True) - msg = proc.communicate() - if kill: - self._killAll(args) - return msg + env_copy = os.environ.copy() + proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True, env=env_copy) + out, err = proc.communicate() + return out, err, proc.returncode # """Append value to PATH environment variable""" @@ -124,7 +154,10 @@ class SalomeContext: """Append value to LD_LIBRARY_PATH environment variable""" def addToLdLibraryPath(self, value): - self.addToVariable('LD_LIBRARY_PATH', value) + if platform.system() == 'Windows': + self.addToVariable('PATH', value) + else: + self.addToVariable('LD_LIBRARY_PATH', value) # """Append value to DYLD_LIBRARY_PATH environment variable""" @@ -184,13 +217,17 @@ class SalomeContext: options = args[1:] availableCommands = { - 'start' : '_runAppli', - 'shell' : '_runSession', + 'start' : '_runAppli', + 'context' : '_setContext', + 'shell' : '_runSession', 'connect' : '_runConsole', - 'killall': '_killAll', - 'info': '_showInfo', - 'help': '_usage', - 'coffee' : '_makeCoffee' + 'kill' : '_kill', + 'killall' : '_killAll', + 'test' : '_runTests', + 'info' : '_showInfo', + 'help' : '_usage', + 'coffee' : '_makeCoffee', + 'car' : '_getCar', } if not command in availableCommands.keys(): @@ -206,6 +243,19 @@ class SalomeContext: See usage for details on commands. """ def _startSalome(self, args): + import os + import sys + try: + from setenv import add_path + absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH') + path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome")) + add_path(path, "PYTHONPATH") + path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome", "appliskel")) + add_path(path, "PYTHONPATH") + + except: + pass + command, options = self.__parseArguments(args) sys.argv = options @@ -219,12 +269,10 @@ class SalomeContext: try: res = getattr(self, command)(options) # run appropriate method return res or (None, None) - except SystemExit, exc: - if exc==0: - sys.exit(0) #catch sys.exit(0) happy end no warning - if exc==1: - self.getLogger().warning("SystemExit 1 in method %s.", command) - sys.exit(1) + except SystemExit, returncode: + if returncode != 0: + self.getLogger().warning("SystemExit %s in method %s.", returncode, command) + sys.exit(returncode) except StandardError: self.getLogger().error("Unexpected error:") import traceback @@ -235,84 +283,139 @@ class SalomeContext: sys.exit(1) # - def __setEnvironmentFromConfigFile(self, filename, reserved=[]): - unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved) + def __setContextFromConfigFile(self, filename, reserved=None): + if reserved is None: + reserved = [] + try: + unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved) + except SalomeContextException, e: + msg = "%s"%e + file_dir = os.path.dirname(filename) + file_base = os.path.basename(filename) + base_no_ext, ext = os.path.splitext(file_base) + sh_file = os.path.join(file_dir, base_no_ext+'.sh') + #if ext == ".cfg" and os.path.isfile(sh_file): + if False: + msg += "Found similar %s file; trying to parse this one instead..."%(base_no_ext+'.sh') + temp = tempfile.NamedTemporaryFile(suffix='.cfg') + try: + convertEnvFileToConfigFile(sh_file, temp.name, reserved) + self.__setContextFromConfigFile(temp.name, reserved) + msg += "OK\n" + self.getLogger().warning(msg) + temp.close() + return + except (ConfigParser.ParsingError, ValueError) as e: + msg += "Invalid token found when parsing file: %s\n"%(sh_file) + self.getLogger().error(msg) + temp.close() + sys.exit(1) + else: + self.getLogger().error(msg) + sys.exit(1) # unset variables for var in unsetVars: self.unsetVariable(var) - # set environment + # set context for reserved in reservedDict: a = filter(None, reservedDict[reserved]) # remove empty elements - reformattedVals = ':'.join(a) - self.addToVariable(reserved, reformattedVals) + a = [ os.path.realpath(x) for x in a ] + reformattedVals = os.pathsep.join(a) + if reserved in ["INCLUDE", "LIBPATH"]: + self.addToVariable(reserved, reformattedVals, separator=' ') + else: + self.addToVariable(reserved, reformattedVals) pass for key,val in configVars: self.setVariable(key, val, overwrite=True) pass - sys.path[:0] = os.getenv('PYTHONPATH','').split(':') + pythonpath = os.getenv('PYTHONPATH','').split(os.pathsep) + pythonpath = [ os.path.realpath(x) for x in pythonpath ] + sys.path[:0] = pythonpath # - def _runAppli(self, args=[]): + def _runAppli(self, args=None): + if args is None: + args = [] # Initialize SALOME environment sys.argv = ['runSalome'] + args import setenv - setenv.main(True) + setenv.main(True, exeName="salome start") import runSalome runSalome.runSalome() # - def _runSession(self, args=[]): + def _setContext(self, args=None): + salome_context_set = os.getenv("SALOME_CONTEXT_SET") + if salome_context_set: + print "***" + print "*** SALOME context has already been set." + print "*** Enter 'exit' (only once!) to leave SALOME context." + print "***" + return + + os.environ["SALOME_CONTEXT_SET"] = "yes" + print "***" + print "*** SALOME context is now set." + print "*** Enter 'exit' (only once!) to leave SALOME context." + print "***" + + cmd = ["/bin/bash"] + proc = subprocess.Popen(cmd, shell=False, close_fds=True) + return proc.communicate() + # + + def _runSession(self, args=None): + if args is None: + args = [] sys.argv = ['runSession'] + args import runSession - runSession.configureSession(args) + params, args = runSession.configureSession(args, exe="salome shell") + sys.argv = ['runSession'] + args import setenv setenv.main(True) - scriptArgs = getScriptsAndArgs(args) - command = formatScriptsAndArgs(scriptArgs) - if command: - sep = ";" - if sys.platform == "win32": - sep= "&" - command = command.split(sep) - outmsg = [] - errmsg = [] - for cmd in command: - cmd = cmd.strip().split(' ') - #proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - proc = subprocess.Popen(cmd) - (stdoutdata, stderrdata) = proc.communicate() - if stdoutdata or stderrdata: - outmsg.append(stdoutdata) - errmsg.append(stderrdata) - - return ("".join(outmsg), "".join(errmsg)) - else: - absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','') - cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ] - proc = subprocess.Popen(cmd, shell=False, close_fds=True) - return proc.communicate() + return runSession.runSession(params, args) # - def _runConsole(self, args=[]): + def _runConsole(self, args=None): + if args is None: + args = [] # Initialize SALOME environment - sys.argv = ['runConsole'] + args + sys.argv = ['runConsole'] import setenv setenv.main(True) - cmd = ["python", "-c", "import runConsole\nrunConsole.connect()" ] - proc = subprocess.Popen(cmd, shell=False, close_fds=True) - return proc.communicate() + import runConsole + return runConsole.connect(args) # - def _killAll(self, args=[]): - absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','') + def _kill(self, args=None): + if args is None: + args = [] + ports = args + if not ports: + print "Port number(s) not provided to command: salome kill " + return + + from multiprocessing import Process + from killSalomeWithPort import killMyPort + import tempfile + for port in ports: + with tempfile.NamedTemporaryFile(): + p = Process(target = killMyPort, args=(port,)) + p.start() + p.join() + pass + # + + def _killAll(self, unused=None): try: import PortManager # mandatory from multiprocessing import Process @@ -326,27 +429,82 @@ class SalomeContext: p = Process(target = killMyPort, args=(port,)) p.start() p.join() - - p = Process(target = killMyPort, args=(2809,)) - p.start() - p.join() except ImportError: + # :TODO: should be declared obsolete from killSalome import killAllPorts killAllPorts() pass + # + def _runTests(self, args=None): + if args is None: + args = [] + sys.argv = ['runTests'] + import setenv + setenv.main(True) + + import runTests + return runTests.runTests(args, exe="salome test") # - def _showInfo(self, args=[]): - print "Running with python", platform.python_version() - self._runAppli(["--version"]) + def _showSoftwareVersions(self): + config = ConfigParser.SafeConfigParser() + absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH') + filename = os.path.join(absoluteAppliPath, ".softwares_versions") + try: + config.read(filename) + sections = config.sections() + for section in sections: + entries = config.items(section, raw=True) # do not use interpolation + for key,val in entries: + version,text = [ x.strip() for x in val.split(',') ] + print "%s: %s"%(text, version) + except: + import traceback + traceback.print_exc() + return + pass + + def _showInfo(self, args=None): + if args is None: + args = [] + + usage = "Usage: salome info [options]" + epilog = """\n +Display some information about SALOME.\n +Available options are: + -p,--ports Show the list of busy ports (running SALOME instances). + -s,--softwares Show the list and versions of SALOME softwares. + -v,--version Show running SALOME version. + -h,--help Show this message. +""" + if not args: + args = ["--version"] + + if "-h" in args or "--help" in args: + print usage + epilog + return + + if "-p" in args or "--ports" in args: + import PortManager + ports = PortManager.getBusyPorts() + print "SALOME instances are running on ports:", ports + if ports: + print "Last started instance on port %s"%ports[-1] + + if "-s" in args or "--softwares" in args: + self._showSoftwareVersions() + + if "-v" in args or "--version" in args: + print "Running with python", platform.python_version() + self._runAppli(["--version"]) # - def _usage(self, unused=[]): + def _usage(self, unused=None): usage() # - def _makeCoffee(self, args=[]): + def _makeCoffee(self, unused=None): print " (" print " ) (" print " ___...(-------)-....___" @@ -357,9 +515,9 @@ class SalomeContext: print " | | | |" print " \\ \\ | |" print " `\\ `\\ | |" - print " `\\ `| |" - print " _/ /\\ /" - print " (__/ \\ /" + print " `\\ `| SALOME |" + print " _/ /\\ 4 EVER /" + print " (__/ \\ <3 /" print " _..---\"\"` \\ /`\"\"---.._" print " .-\' \\ / \'-." print " : `-.__ __.-\' :" @@ -369,6 +527,43 @@ class SalomeContext: print " \'._ \"\"\"----.....______.....----\"\"\" _.\'" print " `\"\"--..,,_____ _____,,..--\"\"`" print " `\"\"\"----\"\"\"`" + print "" + print " SALOME is working for you; what else?" + print "" + sys.exit(0) + # + + def _getCar(self, unused=None): + print " _____________" + print " ..---:::::::-----------. ::::;;." + print " .\'\"\"\"\"\"\" ;; \\ \":." + print " .\'\' ; \\ \"\\__." + print " .\' ;; ; \\\\\";" + print " .\' ; _____; \\\\/" + print " .\' :; ;\" \\ ___:\'." + print " .\'--........................... : = ____:\" \\ \\" + print " ..-\"\" \"\"\"\' o\"\"\" ; ; :" + print " .--\"\" .----- ..----... _.- --. ..-\" ; ; ; ;" + print " .\"\"_- \"--\"\"-----\'\"\" _-\" .-\"\" ; ; .-." + print " .\' .\' SALOME .\" .\" ; ; /. |" + print " /-./\' 4 EVER <3 .\" / _.. ; ; ;;;|" + print " : ;-.______ / _________==. /_ \\ ; ; ;;;;" + print " ; / | \"\"\"\"\"\"\"\"\"\"\".---.\"\"\"\"\"\"\" : /\" \". |; ; _; ;;;" + print " /\"-/ | / / / / ;|; ;-\" | ;\';" + print ":- : \"\"\"----______ / / ____. . .\"\'. ;; .-\"..T\" ." + print "\'. \" ___ \"\": \'\"\"\"\"\"\"\"\"\"\"\"\"\"\" . ; ; ;; ;.\" .\" \'--\"" + print " \", __ \"\"\" \"\"---... :- - - - - - - - - \' \' ; ; ; ;;\" .\"" + print " /. ; \"\"\"---___ ; ; ; ;|.\"\"" + print " : \": \"\"\"----. .-------. ; ; ; ;:" + print " \\ \'--__ \\ \\ \\ / | ; ;;" + print " \'-.. \"\"\"\"---___ : .______..\\ __/..-\"\"| ; ; ;" + print " \"\"--.. \"\"\"--\" m l s . \". . ;" + print " \"\"------... ..--\"\" \" :" + print " \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" \\ /" + print " \"------\"" + print "" + print " Drive your simulation properly with SALOME!" + print "" sys.exit(0) # @@ -388,16 +583,16 @@ class SalomeContext: if not hasattr(self, '_logger'): self._logger = logging.getLogger(__name__) #self._logger.setLevel(logging.DEBUG) + #self._logger.setLevel(logging.WARNING) self._logger.setLevel(logging.ERROR) return self._logger # -### -import pickle if __name__ == "__main__": if len(sys.argv) == 3: context = pickle.loads(sys.argv[1]) args = pickle.loads(sys.argv[2]) + (out, err) = context._startSalome(args) if out: sys.stdout.write(out)