--- /dev/null
+#!/usr/bin/env python\r
+#-*- coding:utf-8 -*-\r
+# Copyright (C) 2010-2013 CEA/DEN\r
+#\r
+# This library is free software; you can redistribute it and/or\r
+# modify it under the terms of the GNU Lesser General Public\r
+# License as published by the Free Software Foundation; either\r
+# version 2.1 of the License.\r
+#\r
+# This library is distributed in the hope that it will be useful,\r
+# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+# Lesser General Public License for more details.\r
+#\r
+# You should have received a copy of the GNU Lesser General Public\r
+# License along with this library; if not, write to the Free Software\r
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+import os\r
+import platform\r
+import shutil\r
+import getpass\r
+import subprocess\r
+import stat\r
+\r
+import src\r
+\r
+parser = src.options.Options()\r
+\r
+parser.add_option('n', 'name', 'string', 'name', _('The name of the launcher '\r
+ '(default is APPLICATION.profile.launcher_name)'))\r
+parser.add_option('c', 'catalog', 'string', 'catalog',\r
+ _('The resources catalog to use'))\r
+parser.add_option('', 'gencat', 'string', 'gencat',\r
+ _("Create a resources catalog for the specified machines "\r
+ "(separated with ',') \n\tNOTICE: this command will ssh to retrieve"\r
+ " information to each machine in the list"))\r
+\r
+def generate_launch_file(config,\r
+ logger,\r
+ env_info=None,\r
+ pathlauncher=None,\r
+ display=True,\r
+ additional_env={}):\r
+ '''Generates the launcher file.\r
+ \r
+ :param config Config: The global configuration\r
+ :param logger Logger: The logger instance to use for the display \r
+ and logging\r
+ :param env_info str: The list of products to add in the files.\r
+ :param pathlauncher str: The path to the launcher to generate\r
+ :param src_root str: The path to the directory where the sources are\r
+ :param display boolean: If False, do not print anything in the terminal\r
+ :param additional_env dict: The dict giving additional \r
+ environment variables\r
+ :return: The launcher file path.\r
+ :rtype: str\r
+ '''\r
+ # Get the application directory and the profile directory\r
+ out_dir = config.APPLICATION.workdir\r
+ profile = config.APPLICATION.profile\r
+ profile_install_dir = get_profile_dir(config)\r
+ \r
+ # Compute the default launcher path if it is not provided in pathlauncher\r
+ # parameter\r
+ if pathlauncher is None:\r
+ filepath = os.path.join( os.path.join( profile_install_dir,\r
+ 'bin',\r
+ 'salome' ),\r
+ profile['launcher_name'] )\r
+ else:\r
+ filepath = os.path.join(pathlauncher, profile['launcher_name'])\r
+\r
+ # Remove the file if it exists in order to replace it\r
+ if os.path.exists(filepath):\r
+ os.remove(filepath)\r
+\r
+ # Add the APPLI variable\r
+ additional_env['APPLI'] = filepath\r
+\r
+ # Get the launcher template\r
+ withProfile = src.fileEnviron.withProfile.replace( "PROFILE_INSTALL_DIR",\r
+ profile_install_dir )\r
+ before, after = withProfile.split(\r
+ "# here your local standalone environment\n")\r
+\r
+ # create an environment file writer\r
+ writer = src.environment.FileEnvWriter(config,\r
+ logger,\r
+ out_dir,\r
+ src_root=None,\r
+ env_info=env_info)\r
+\r
+ # Display some information\r
+ if display:\r
+ # Write the launcher file\r
+ logger.write(_("Generating launcher for %s :\n") % \r
+ src.printcolors.printcLabel(config.VARS.application), 1)\r
+ logger.write(" %s\n" %src.printcolors.printcLabel(filepath), 1)\r
+ \r
+ # open the file and write into it\r
+ launch_file = open(filepath, "w")\r
+ launch_file.write(before)\r
+ # Write\r
+ writer.write_cfgForPy_file(launch_file, additional_env=additional_env)\r
+ launch_file.write(after)\r
+ launch_file.close()\r
+ \r
+ # change the rights in order to make the file executable for everybody\r
+ os.chmod(filepath,\r
+ stat.S_IRUSR |\r
+ stat.S_IRGRP |\r
+ stat.S_IROTH |\r
+ stat.S_IWUSR |\r
+ stat.S_IXUSR |\r
+ stat.S_IXGRP |\r
+ stat.S_IXOTH)\r
+ return filepath\r
+\r
+def generate_launch_link(config,\r
+ logger,\r
+ launcherPath,\r
+ pathlauncher=None,\r
+ display=True,\r
+ packageLauncher=False):\r
+ '''Generates the launcher link that sources Python \r
+ and call the actual launcher.\r
+ \r
+ :param config Config: The global configuration\r
+ :param logger Logger: The logger instance to use for the display \r
+ and logging\r
+ :param launcherPath str: The path to the launcher to call\r
+ :param pathlauncher str: The path to the launcher (link) to generate\r
+ :param display boolean: If False, do not print anything in the terminal\r
+ :param packageLauncher boolean: if True, use a relative path (for package)\r
+ :return: The launcher link file path.\r
+ :rtype: str\r
+ '''\r
+ if pathlauncher is None:\r
+ # Make an executable file that sources python, then launch the launcher\r
+ # produced by generate_launch_file method\r
+ sourceLauncher = os.path.join(config.APPLICATION.workdir,\r
+ config.APPLICATION.profile.launcher_name)\r
+ else:\r
+ sourceLauncher = os.path.join(pathlauncher,\r
+ config.APPLICATION.profile.launcher_name)\r
+\r
+ # Change the extension for the windows case\r
+ if platform.system() == "Windows" :\r
+ sourceLauncher += '.bat'\r
+\r
+ # display some information\r
+ if display:\r
+ logger.write(_("\nGenerating the executable that sources"\r
+ " python and runs the launcher :\n") , 1)\r
+ logger.write(" %s\n" %src.printcolors.printcLabel(sourceLauncher), 1)\r
+\r
+ # open the file to write\r
+ f = open(sourceLauncher, "w")\r
+\r
+ # Write the set up of the environment\r
+ if platform.system() == "Windows" :\r
+ shell = 'bat'\r
+ else:\r
+ shell = 'bash'\r
+ \r
+ # Write the Python environment files\r
+ env = src.environment.SalomeEnviron( config, \r
+ src.fileEnviron.get_file_environ( f, shell, config ) )\r
+ env.set_a_product( "Python", logger)\r
+\r
+ # Write the call to the original launcher\r
+ f.write( "\n\n")\r
+ if packageLauncher:\r
+ cmd = os.path.join('${out_dir_Path}', launcherPath)\r
+ else:\r
+ cmd = launcherPath\r
+\r
+ if platform.system() == "Windows" :\r
+ cmd = 'python ' + cmd + ' %*'\r
+ else:\r
+ cmd = cmd + ' $*'\r
+ \r
+ f.write( cmd )\r
+ f.write( "\n\n")\r
+\r
+ # Write the cleaning of the environment\r
+ env.finish(True)\r
+\r
+ # Close new launcher\r
+ f.close()\r
+ os.chmod(sourceLauncher,\r
+ stat.S_IRUSR |\r
+ stat.S_IRGRP |\r
+ stat.S_IROTH |\r
+ stat.S_IWUSR |\r
+ stat.S_IWGRP |\r
+ stat.S_IWOTH |\r
+ stat.S_IXUSR |\r
+ stat.S_IXGRP |\r
+ stat.S_IXOTH)\r
+ return sourceLauncher\r
+\r
+def generate_catalog(machines, config, logger):\r
+ """Generates an xml catalog file from a list of machines.\r
+ \r
+ :param machines List: The list of machines to add in the catalog \r
+ :param config Config: The global configuration\r
+ :param logger Logger: The logger instance to use for the display \r
+ and logging\r
+ :return: The catalog file path.\r
+ :rtype: str\r
+ """\r
+ # remove empty machines\r
+ machines = map(lambda l: l.strip(), machines)\r
+ machines = filter(lambda l: len(l) > 0, machines)\r
+ \r
+ # log something\r
+ src.printcolors.print_value(logger, _("Generate Resources Catalog"),\r
+ ", ".join(machines), 4)\r
+ \r
+ # The command to execute on each machine in order to get some information\r
+ cmd = '"cat /proc/cpuinfo | grep MHz ; cat /proc/meminfo | grep MemTotal"'\r
+ user = getpass.getuser()\r
+\r
+ # Create the catalog path\r
+ catfile = src.get_tmp_filename(config, "CatalogResources.xml")\r
+ catalog = file(catfile, "w")\r
+ \r
+ # Write into it\r
+ catalog.write("<!DOCTYPE ResourcesCatalog>\n<resources>\n")\r
+ for k in machines:\r
+ logger.write(" ssh %s " % (k + " ").ljust(20, '.'), 4)\r
+ logger.flush()\r
+\r
+ # Verify that the machine is accessible\r
+ ssh_cmd = 'ssh -o "StrictHostKeyChecking no" %s %s' % (k, cmd)\r
+ p = subprocess.Popen(ssh_cmd, shell=True,\r
+ stdin=subprocess.PIPE,\r
+ stdout=subprocess.PIPE,\r
+ stderr=subprocess.PIPE)\r
+ p.wait()\r
+\r
+ if p.returncode != 0: # The machine is not accessible\r
+ logger.write(src.printcolors.printc(src.KO_STATUS) + "\n", 4)\r
+ logger.write(" " + \r
+ src.printcolors.printcWarning(p.stderr.read()), 2)\r
+ else:\r
+ # The machine is accessible, write the corresponding section on\r
+ # the xml file\r
+ logger.write(src.printcolors.printc(src.OK_STATUS) + "\n", 4)\r
+ lines = p.stdout.readlines()\r
+ freq = lines[0][:-1].split(':')[-1].split('.')[0].strip()\r
+ nb_proc = len(lines) -1\r
+ memory = lines[-1].split(':')[-1].split()[0].strip()\r
+ memory = int(memory) / 1000\r
+\r
+ catalog.write(" <machine\n")\r
+ catalog.write(" protocol=\"ssh\"\n")\r
+ catalog.write(" nbOfNodes=\"1\"\n")\r
+ catalog.write(" mode=\"interactif\"\n")\r
+ catalog.write(" OS=\"LINUX\"\n")\r
+ catalog.write(" CPUFreqMHz=\"%s\"\n" % freq)\r
+ catalog.write(" nbOfProcPerNode=\"%s\"\n" % nb_proc)\r
+ catalog.write(" memInMB=\"%s\"\n" % memory)\r
+ catalog.write(" userName=\"%s\"\n" % user)\r
+ catalog.write(" name=\"%s\"\n" % k)\r
+ catalog.write(" hostname=\"%s\"\n" % k)\r
+ catalog.write(" >\n")\r
+ catalog.write(" </machine>\n")\r
+\r
+ catalog.write("</resources>\n")\r
+ catalog.close()\r
+ return catfile\r
+\r
+def copy_catalog(config, catalog_path):\r
+ """Copy the xml catalog file into the right location\r
+ \r
+ :param config Config: The global configuration\r
+ :param catalog_path str: the catalog file path\r
+ :return: The environment dictionary corresponding to the file path.\r
+ :rtype: Dict\r
+ """\r
+ # Verify the existence of the file\r
+ if not os.path.exists(catalog_path):\r
+ raise IOError(_("Catalog not found: %s") % catalog_path)\r
+ # Compute the location where to copy the file\r
+ profile_dir = get_profile_dir(config)\r
+ new_catalog_path = os.path.join(profile_dir, "CatalogResources.xml")\r
+ # Do the copy\r
+ shutil.copy(catalog_path, new_catalog_path)\r
+ additional_environ = {'USER_CATALOG_RESOURCES_FILE' : new_catalog_path}\r
+ return additional_environ\r
+\r
+def get_profile_dir(config):\r
+ """Get the profile directory from the config\r
+ \r
+ :param config Config: The global configuration\r
+ :return: The profile install directory\r
+ :rtype: Str\r
+ """\r
+ profile_name = config.APPLICATION.profile.product\r
+ profile_info = src.product.get_product_config(config, profile_name)\r
+ return profile_info.install_dir\r
+\r
+def finish_profile_install(config, launcherPath):\r
+ """Add some symlinks required for SALOME\r
+ \r
+ :param config Config: The global configuration\r
+ :param launcherPath str: the launcher file path\r
+ """\r
+ # Create a USERS directory\r
+ profile_dir = get_profile_dir(config)\r
+ user_dir = os.path.join(profile_dir, 'USERS')\r
+ if not os.path.exists(user_dir):\r
+ os.makedirs(user_dir)\r
+ # change rights of USERS directory\r
+ os.chmod(user_dir,\r
+ stat.S_IRUSR |\r
+ stat.S_IRGRP |\r
+ stat.S_IROTH |\r
+ stat.S_IWUSR |\r
+ stat.S_IWGRP |\r
+ stat.S_IWOTH |\r
+ stat.S_IXUSR |\r
+ stat.S_IXGRP |\r
+ stat.S_IXOTH)\r
+\r
+ # create a link in root directory to the launcher\r
+ if platform.system() != "Windows" :
+ link_path = os.path.join(config.APPLICATION.workdir, 'salome')\r
+ if not os.path.exists(link_path):\r
+ try:\r
+ os.symlink(launcherPath, link_path)\r
+ except OSError:\r
+ os.remove(link_path)\r
+ os.symlink(launcherPath, link_path)\r
+\r
+ link_path = os.path.join(profile_dir, 'salome')\r
+ if not os.path.exists(link_path):\r
+ try:\r
+ os.symlink(launcherPath, link_path)\r
+ except OSError:\r
+ os.remove(link_path)\r
+ os.symlink(launcherPath, link_path)
+\r
+##################################################\r
+\r
+##\r
+# Describes the command\r
+def description():\r
+ return _("The launcher command generates a salome launcher.")\r
+\r
+##\r
+# Runs the command.\r
+def run(args, runner, logger):\r
+\r
+ # check for product\r
+ (options, args) = parser.parse_args(args)\r
+\r
+ # Verify that the command was called with an application\r
+ src.check_config_has_application( runner.cfg )\r
+ \r
+ # Verify that the APPLICATION section has a profile section\r
+ src.check_config_has_profile( runner.cfg )\r
+\r
+ # Change the name of the file to create \r
+ # if the corresponding option was called\r
+ if options.name:\r
+ runner.cfg.APPLICATION.profile['launcher_name'] = options.name\r
+\r
+ # Copy a catalog if the option is called\r
+ additional_environ = {}\r
+ if options.catalog:\r
+ additional_environ = copy_catalog(runner.cfg, options.catalog)\r
+\r
+ # Generate a catalog of resources if the corresponding option was called\r
+ if options.gencat:\r
+ catalog_path = generate_catalog(options.gencat.split(","),\r
+ runner.cfg,\r
+ logger)\r
+ additional_environ = copy_catalog(runner.cfg, catalog_path)\r
+\r
+ # Generate the launcher\r
+ launcherPath = generate_launch_file( runner.cfg,\r
+ logger,\r
+ additional_env = additional_environ )\r
+\r
+ # Create the link (bash file that sources python and then call \r
+ # the actual launcher) to the launcher\r
+ generate_launch_link( runner.cfg, logger, launcherPath)\r
+\r
+ # Add some links\r
+ finish_profile_install(runner.cfg, launcherPath)\r
+\r
+ return 0\r
:param lProducts list: List of products to potentially add
"""
- lProdHasGui = [p for p in lProducts if 'has_gui' in
+ lProdHasGui = [p for p in lProducts if 'type ' in
src.product.get_product_config(self.cfg, p) and
- src.product.get_product_config(self.cfg, p).has_gui=='yes']
+ src.product.get_product_config(self.cfg, p).type=='salome']
lProdName = []
for ProdName in lProdHasGui:
pi = src.product.get_product_config(self.cfg, ProdName)
# Loop on cfg_env values
for env_def in cfg_env:
val = cfg_env[env_def]
+
+ # if it is env_script, do not do anything (reserved keyword)
+ if env_def == "env_script":
+ continue
+
# if it is a dict, do not do anything
if isinstance(val, src.pyconf.Mapping):
continue
self.load_cfg_environment(pi.environ.build)
if not self.forBuild and "launch" in pi.environ:
self.load_cfg_environment(pi.environ.launch)
+ # if product_info defines a env_scripts, load it
+ if 'env_script' in pi.environ:
+ self.run_env_script(pi, logger)
# Set an additional environment for SALOME products
if src.product.product_is_salome(pi):
# set environment using definition of the product
self.set_salome_minimal_product_env(pi, logger)
self.set_salome_generic_product_env(product)
-
- # if product_info defines a env_scripts, load it
- if 'env_script' in pi:
- self.run_env_script(pi, logger)
def run_env_script(self, product_info, logger=None):
:param product_info Config: The product description
:param logger Logger: The logger instance to display messages
"""
- env_script = product_info.env_script
+ env_script = product_info.environ.env_script
# Check that the script exists
- if not os.path.exists(product_info.env_script):
+ if not os.path.exists(env_script):
raise src.SatException(_("Environment script not found: %s") %
env_script)
if not self.silent and logger is not None:
- logger.write(" ** load %s\n" % product_info.env_script, 4)
+ logger.write(" ** load %s\n" % env_script, 4)
# import the script and run the set_env function
try:
traceback.print_tb(exceptionTraceback)
traceback.print_exc()
+ def run_simple_env_script(self, script_path, logger=None):
+ """Runs an environment script. Same as run_env_script, but with a
+ script path as parameter.
+
+ :param script_path str: a path to an environment script
+ :param logger Logger: The logger instance to display messages
+ """
+ # Check that the script exists
+ if not os.path.exists(script_path):
+ raise src.SatException(_("Environment script not found: %s") %
+ script_path)
+
+ if not self.silent and logger is not None:
+ logger.write(" ** load %s\n" % script_path, 4)
+
+ script_basename = os.path.basename(script_path)
+ if script_basename.endswith(".py"):
+ script_basename = script_basename[:-len(".py")]
+
+ # import the script and run the set_env function
+ try:
+ import imp
+ pyproduct = imp.load_source(script_basename + "_env_script",
+ script_path)
+ pyproduct.load_env(self)
+ except:
+ __, exceptionValue, exceptionTraceback = sys.exc_info()
+ print(exceptionValue)
+ import traceback
+ traceback.print_tb(exceptionTraceback)
+ traceback.print_exc()
+
def set_products(self, logger, src_root=None):
"""Sets the environment for all the products.
# set product environ
self.set_application_env(logger)
- # set products
- install_root = os.path.join(self.cfg.APPLICATION.workdir, "INSTALL")
- source_root = os.path.join(self.cfg.APPLICATION.workdir, "SOURCES")
- self.set('INSTALL_ROOT', install_root)
- self.set('SRC_ROOT', source_root)
self.set_python_libdirs()
-
+
+ # set products
for product in env_info:
self.set_a_product(product, logger)
:param logger Logger: The logger instance to display messages
:param out_dir str: The directory path where t put the output files
:param src_root str: The application working directory
- :param env_info str:
+ :param env_info str: The list of products to add in the files.
'''
self.config = config
self.logger = logger
else:
# set env from PRODUCT
env.set_application_env(self.logger)
- # set the prerequisites
- env.set_prerequisites(self.logger)
+
# set the products
env.set_products(self.logger,
src_root=self.src_root)
else:
self.environ = os.environ
# Initialize some variables
- if not self.environ.has_key("PATH"):
+ if not "PATH" in self.environ.keys():
self.environ["PATH"]=""
- if not self.environ.has_key("LD_LIBRARY_PATH"):
+ if not "LD_LIBRARY_PATH" in self.environ.keys():
self.environ["LD_LIBRARY_PATH"]=""
- if not self.environ.has_key("PYTHONPATH"):
+ if not "PYTHONPATH" in self.environ.keys():
self.environ["PYTHONPATH"]=""
- if not self.environ.has_key("TCLLIBPATH"):
+ if not "TCLLIBPATH" in self.environ.keys():
self.environ["TCLLIBPATH"]=""
- if not self.environ.has_key("TKLIBPATH"):
+ if not "TKLIBPATH" in self.environ.keys():
self.environ["TKLIBPATH"]=""
# four whitespaces for first indentation in a python script
:param key str: the environment variable to check
'''
- return self.environ.has_key(key)
+ return key in self.environ.keys()
def get(self, key):
'''Get the value of the environment variable "key"
:param required bool: Do nothing if required is False
"""
- return
\ No newline at end of file
+ return
+
+# The SALOME launcher template
+withProfile = """#! /usr/bin/env python
+
+################################################################
+# WARNING: this file is automatically generated by SalomeTools #
+# WARNING: and so could be overwritten at any time. #
+################################################################
+
+import os
+import sys
+
+
+# Add the pwdPath to able to run the launcher after unpacking a package
+# Used only in case of a salomeTools package
+out_dir_Path=os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname((os.path.abspath(os.path.dirname(__file__)))))))
+prereq_install_Path=os.path.join(out_dir_Path , 'PREREQUISITES', 'INSTALL')
+prereq_build_Path=os.path.join(out_dir_Path , 'PREREQUISITES', 'BUILD')
+
+# Preliminary work to initialize path to SALOME Python modules
+def __initialize():
+
+ sys.path[:0] = [ os.path.join( 'PROFILE_INSTALL_DIR', 'bin', 'salome' ) ]
+ os.environ['ABSOLUTE_APPLI_PATH'] = 'PROFILE_INSTALL_DIR'
+
+ # define folder to store omniorb config (initially in virtual application folder)
+ try:
+ from salomeContextUtils import setOmniOrbUserPath
+ setOmniOrbUserPath()
+ except Exception, e:
+ print e
+ sys.exit(1)
+# End of preliminary work
+
+def main(args):
+ # Identify application path then locate configuration files
+ __initialize()
+
+ if args == ['--help']:
+ from salomeContext import usage
+ usage()
+ sys.exit(0)
+
+ #from salomeContextUtils import getConfigFileNames
+ #configFileNames, args, unexisting = getConfigFileNames( args, checkExistence=True )
+ #if len(unexisting) > 0:
+ # print "ERROR: unexisting configuration file(s): " + ', '.join(unexisting)
+ # sys.exit(1)
+
+ # Create a SalomeContext which parses configFileNames to initialize environment
+ try:
+ from salomeContext import SalomeContext, SalomeContextException
+ SalomeContext.addToSpecial=addToSpecial
+ context = SalomeContext(None)
+
+ # Here set specific variables, if needed
+ # context.addToPath('mypath')
+ # context.addToLdLibraryPath('myldlibrarypath')
+ # context.addToPythonPath('mypythonpath')
+ # context.setVariable('myvarname', 'value')
+
+ context.setVariable(r"PRODUCT_ROOT_DIR", out_dir_Path, overwrite=True)
+ # here your local standalone environment
+
+ # Start SALOME, parsing command line arguments
+ context.runSalome(args)
+ #print 'Thank you for using SALOME!'
+
+ except SalomeContextException, e:
+ import logging
+ logging.getLogger("salome").error(e)
+ sys.exit(1)
+#
+def addToSpecial(self, name, value, pathSep=None):
+ "add special dangerous cases: TCLLIBPATH PV_PLUGIN_PATH etc..."
+ #http://computer-programming-forum.com/57-tcl/1dfddc136afccb94.htm
+ #TCLLIBPATH: Tcl treats the contents of that variable as a list. Be happy, for you can now use drive letters on windows.
+ if value == '':
+ return
+
+ specialBlanksKeys=["TCLLIBPATH", "TKLIBPATH"]
+ specialSemicolonKeys=["PV_PLUGIN_PATH"]
+ res=os.pathsep
+ if name in specialBlanksKeys: res=" "
+ if name in specialSemicolonKeys: res=";"
+
+ if pathSep==None:
+ sep=res
+ else:
+ sep=pathSep
+ value = os.path.expandvars(value) # expand environment variables
+ self.getLogger().debug("Add to %s: %s", name, value)
+ env = os.getenv(name, None)
+ if env is None:
+ os.environ[name] = value
+ else:
+ os.environ[name] = value + sep + env #explicitely or not special path separator ?whitespace, semicolon?
+
+if __name__ == "__main__":
+ args = sys.argv[1:]
+ main(args)
+#
+"""
+
\ No newline at end of file