From 087058900744ecc1f375ee9a7b6f37de185fac3f Mon Sep 17 00:00:00 2001 From: Nicolas CROUZET - SFME/LGLS Date: Wed, 14 Sep 2016 16:51:38 +0200 Subject: [PATCH] implement a runRemote command to manage distant calculation with new launcher --- bin/CMakeLists.txt | 1 + bin/runRemote.py | 102 ++++++++++++ bin/salomeContext.py | 16 +- bin/salomeContextUtils.py.in | 10 +- .../cmake_files/SalomeSetupPlatform.cmake | 15 -- src/Container/SALOME_ContainerManager.cxx | 145 ++++++++---------- src/Container/SALOME_ContainerManager.hxx | 6 +- src/ResourcesManager/ResourcesManager.cxx | 24 +-- 8 files changed, 207 insertions(+), 112 deletions(-) create mode 100644 bin/runRemote.py diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index f97300c1f..a5564befa 100755 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -48,6 +48,7 @@ SET(SCRIPTS runSalome.py runSession.py runConsole.py + runRemote.py runTests.py salomeConsole.py ${CMAKE_CURRENT_BINARY_DIR}/salomeContextUtils.py diff --git a/bin/runRemote.py b/bin/runRemote.py new file mode 100644 index 000000000..6aa21f243 --- /dev/null +++ b/bin/runRemote.py @@ -0,0 +1,102 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +# +# Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +import os +from optparse import OptionParser +import subprocess +from salome_utils import getUserName +from salomeContextUtils import getShortAndExtraArgs + +# Use to display newlines (\n) in epilog +class MyParser(OptionParser): + def format_epilog(self, formatter): + return self.epilog +# +# +# --- set the OMNIORB_CONFIG file and environment relative to this run of SALOME +def _writeConfigFile(port, host): + path = os.environ['OMNIORB_USER_PATH'] + kwargs = {'with_username' : getUserName()} + + from ORBConfigFile import writeORBConfigFile + [ filename, msgSize ] = writeORBConfigFile(path, host, port, kwargs) + + os.environ['OMNIORB_CONFIG'] = filename +# + +def runRemote(args): + if args is None: + args = [] + usage = "Usage: salome runremote [options] -- command" + epilog = """\n +Execute command in SALOME environment from a remote call, ssh or rsh. +salome runremote is used notably to launch containers from a distant salome session. + +For example: + salome remote -m xxx.cea.fr -p 2810 ls /tmp >/dev/null 2>&1 + -> execute the command ls /tmp >/dev/null 2>&1 + + salome remote -m xxx.cea.fr -p 2810 SALOME_Container Cont_S + -ORBInitRef NameService=IOR:01... + -> starts a Salome container called Cont_S connected to port 2810 + of xxx.cea.fr +""" + parser = MyParser(usage=usage, epilog=epilog) + parser.add_option("-p", "--port", metavar="", default="2810", + action="store", type="string", dest="port", + help="The port to connect to." + ) + parser.add_option("-m", "--machine", metavar="", + action="store", type="string", dest="host", + default="localhost", + help="The machine where salome was launched." + ) + parser.add_option('-d', '--directory', dest="directory", + metavar="", default=None, + help="The directory where to execute the command." + ) + + # separate runRemote args from the command to run (given after --) + short_args, extra_args = getShortAndExtraArgs(args) + try: + (options, args) = parser.parse_args(short_args) + except Exception, e: + print e + print usage + print epilog + return + + port = options.port + host = options.host + directory = options.directory + command=extra_args[1:] + + _writeConfigFile(port, host) + os.environ['NSPORT'] = port + os.environ['NSHOST'] = host + print "[ Remote Command ] ", " ".join(command) + cmd = subprocess.Popen(command, cwd=directory) + cmd.wait() + return +# + diff --git a/bin/salomeContext.py b/bin/salomeContext.py index 7a89e9666..92be6066b 100644 --- a/bin/salomeContext.py +++ b/bin/salomeContext.py @@ -45,6 +45,7 @@ Commands: 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. + remote run command in SALOME environment from remote call, ssh or rsh. 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. @@ -216,6 +217,7 @@ class SalomeContext: 'start' : '_runAppli', 'context' : '_setContext', 'shell' : '_runSession', + 'remote' : '_runRemote', 'connect' : '_runConsole', 'kill' : '_kill', 'killall' : '_killAll', @@ -356,7 +358,7 @@ class SalomeContext: os.environ["SALOME_CONTEXT_SET"] = "yes" print "***" - print "*** SALOME context is now set." + print "*** SALOME context is set now." print "*** Enter 'exit' (only once!) to leave SALOME context." print "***" @@ -379,6 +381,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 = [] diff --git a/bin/salomeContextUtils.py.in b/bin/salomeContextUtils.py.in index 37fb3d7ed..cb0cad775 100644 --- a/bin/salomeContextUtils.py.in +++ b/bin/salomeContextUtils.py.in @@ -401,9 +401,9 @@ def formatScriptsAndArgs(scriptArgs=None): # If OMNIORB_USER_PATH is already set, only checks write access to associated directory ; # an exception is raised if check fails. It allows users for choosing a specific folder. # Else the function sets OMNIORB_USER_PATH this way: -# - If APPLI environment variable is set, OMNIORB_USER_PATH is set to ${APPLI}/USERS. -# The function does not check USERS folder existence or write access. This folder -# must exist ; this is the case if SALOME virtual application has been created using +# - If APPLI environment variable is set, and if ${APPLI}/USERS points at an existing +# folder with write access, then OMNIORB_USER_PATH is set to ${APPLI}/USERS. +# This is the case if SALOME virtual application has been created using # appli_gen.py script. # - Else OMNIORB_USER_PATH is set to user home directory. def setOmniOrbUserPath(): @@ -417,7 +417,9 @@ def setOmniOrbUserPath(): #defaultOmniorbUserPath = os.path.join(homePath, ".salomeConfig/USERS") defaultOmniorbUserPath = homePath if os.getenv("APPLI"): - defaultOmniorbUserPath = os.path.join(homePath, os.getenv("APPLI"), "USERS") + appli_users_path=os.path.join(homePath, os.getenv("APPLI"), "USERS") + if os.access(appli_users_path, os.W_OK): + defaultOmniorbUserPath = appli_users_path pass os.environ["OMNIORB_USER_PATH"] = defaultOmniorbUserPath # diff --git a/salome_adm/cmake_files/SalomeSetupPlatform.cmake b/salome_adm/cmake_files/SalomeSetupPlatform.cmake index aa6b80e11..a121fea03 100644 --- a/salome_adm/cmake_files/SalomeSetupPlatform.cmake +++ b/salome_adm/cmake_files/SalomeSetupPlatform.cmake @@ -166,18 +166,3 @@ IF(NOT WIN32) ENDIF() ENDIF() -IF(NOT NO_CXX11_SUPPORT) - # C++11 support - INCLUDE(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) - CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) - IF(COMPILER_SUPPORTS_CXX11) - MESSAGE(STATUS "Enable C++11 support") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - ELSEIF(COMPILER_SUPPORTS_CXX0X) - MESSAGE(STATUS "Enable C++0x support") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - ELSE() - MESSAGE(WARNING "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.") - ENDIF() -ENDIF() diff --git a/src/Container/SALOME_ContainerManager.cxx b/src/Container/SALOME_ContainerManager.cxx index 98f03802a..8afe7b503 100644 --- a/src/Container/SALOME_ContainerManager.cxx +++ b/src/Container/SALOME_ContainerManager.cxx @@ -516,26 +516,13 @@ SALOME_ContainerManager::LaunchContainer(const Engines::ContainerParameters& par // Only if an application directory is set if(hostname != Kernel_Utils::GetHostname() && _isAppliSalomeDefined) { - // Preparing remote command - std::string command = ""; + const ParserResourcesType resInfo(_resManager->GetResourceDefinition(resource_selected)); - command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, resInfo.UserName); - if (resInfo.AppliPath != "") - command += resInfo.AppliPath; - else - { - ASSERT(GetenvThreadSafe("APPLI")); - command += GetenvThreadSafeAsString("APPLI"); - } - command += "/runRemote.sh "; - ASSERT(GetenvThreadSafe("NSHOST")); - command += GetenvThreadSafeAsString("NSHOST"); // hostname of CORBA name server - command += " "; - ASSERT(GetenvThreadSafe("NSPORT")); - command += GetenvThreadSafeAsString("NSPORT"); // port of CORBA name server - command += " \"ls /tmp >/dev/null 2>&1\""; + std::string command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, + resInfo.UserName, resInfo.AppliPath); // Launch remote command + command += " \"ls /tmp >/dev/null 2>&1\""; int status = SystemThreadSafe(command.c_str()); if (status != 0) { @@ -756,38 +743,17 @@ SALOME_ContainerManager::BuildCommandToLaunchRemoteContainer(const std::string& else nbproc = params.nb_proc; } + std::string wdir = params.workingdir.in(); // "ssh -l user machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \ - // SALOME_Container containerName &" - command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, resInfo.UserName); - - if (resInfo.AppliPath != "") - command += resInfo.AppliPath; // path relative to user@machine $HOME - else - { - ASSERT(GetenvThreadSafe("APPLI")); - command += GetenvThreadSafeAsString("APPLI"); // path relative to user@machine $HOME - } + // SALOME_Container containerName -ORBInitRef NameService=IOR:01000..." + // or + // "ssh -l user machine distantLauncher remote -p hostNS -m portNS -d dir + // -- SALOME_Container contName -ORBInitRef NameService=IOR:01000..." + command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, + resInfo.UserName, resInfo.AppliPath, + wdir); - command += "/runRemote.sh "; - - ASSERT(GetenvThreadSafe("NSHOST")); - command += GetenvThreadSafeAsString("NSHOST"); // hostname of CORBA name server - - command += " "; - ASSERT(GetenvThreadSafe("NSPORT")); - command += GetenvThreadSafeAsString("NSPORT"); // port of CORBA name server - - std::string wdir = params.workingdir.in(); - if(wdir != "") - { - command += " WORKINGDIR "; - command += " '"; - if(wdir == "$TEMPDIR") - wdir="\\$TEMPDIR"; - command += wdir; // requested working directory - command += "'"; - } if(params.isMPI) { @@ -1207,41 +1173,8 @@ std::string SALOME_ContainerManager::GetMPIZeroNode(const std::string machine, c if (_isAppliSalomeDefined) { - if (resInfo.Protocol == rsh) - command = "rsh "; - else if (resInfo.Protocol == ssh) - command = "ssh "; - else if (resInfo.Protocol == srun) - command = "srun -n 1 -N 1 --share --nodelist="; - else - throw SALOME_Exception("Unknown protocol"); - - if (resInfo.UserName != "") - { - command += "-l "; - command += resInfo.UserName; - command += " "; - } - - command += resInfo.HostName; - command += " "; - - if (resInfo.AppliPath != "") - command += resInfo.AppliPath; // path relative to user@machine $HOME - else - { - ASSERT(GetenvThreadSafe("APPLI")); - command += GetenvThreadSafeAsString("APPLI"); // path relative to user@machine $HOME - } - - command += "/runRemote.sh "; - - ASSERT(GetenvThreadSafe("NSHOST")); - command += GetenvThreadSafeAsString("NSHOST"); // hostname of CORBA name server - - command += " "; - ASSERT(GetenvThreadSafe("NSPORT")); - command += GetenvThreadSafeAsString("NSPORT"); // port of CORBA name server + command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, + resInfo.UserName, resInfo.AppliPath); command += " mpirun -np 1 hostname -s > " + tmpFile; } @@ -1308,7 +1241,9 @@ std::set SALOME_ContainerManager::getpidofprogram(const std::string progr std::string SALOME_ContainerManager::getCommandToRunRemoteProcess(AccessProtocolType protocol, const std::string & hostname, - const std::string & username) + const std::string & username, + const std::string & applipath, + const std::string & workdir) { std::ostringstream command; switch (protocol) @@ -1344,6 +1279,52 @@ std::string SALOME_ContainerManager::getCommandToRunRemoteProcess(AccessProtocol throw SALOME_Exception("Unknown protocol"); } + std::string remoteapplipath; + if (applipath=="") + remoteapplipath = GetenvThreadSafeAsString("APPLI"); + else + remoteapplipath = applipath; + + ASSERT(GetenvThreadSafe("NSHOST")); + ASSERT(GetenvThreadSafe("NSPORT")); + + // $APPLI points either to an application directory, or to a salome launcher file + // we prepare the remote command according to the case + struct stat statbuf; + if (stat(GetenvThreadSafe("APPLI"), &statbuf) ==0 && S_ISREG(statbuf.st_mode)) + { + // if $APPLI is a regular file, we asume it's a salome Launcher + // generate a command with a salome launcher + command << remoteapplipath + << " remote" + << " -m " + << GetenvThreadSafeAsString("NSHOST") // hostname of CORBA name server + << " -p " + << GetenvThreadSafeAsString("NSPORT"); // port of CORBA name server + if (workdir != "") + command << "-d " << workdir; + command << " -- " ; + } + else // we assume it's a salome application directory + { + // generate a command with runRemote.sh + command << remoteapplipath; + command << "/runRemote.sh "; + command << GetenvThreadSafeAsString("NSHOST"); // hostname of CORBA name server + command << " "; + command << GetenvThreadSafeAsString("NSPORT"); // port of CORBA name server + if(workdir != "") + { + command << " WORKINGDIR "; + command << " '"; + if(workdir == "$TEMPDIR") + command << "\\$TEMPDIR"; + else + command << workdir; // requested working directory + command << "'"; + } + } + return command.str(); } diff --git a/src/Container/SALOME_ContainerManager.hxx b/src/Container/SALOME_ContainerManager.hxx index 8a49e05ba..41c39631d 100644 --- a/src/Container/SALOME_ContainerManager.hxx +++ b/src/Container/SALOME_ContainerManager.hxx @@ -91,7 +91,11 @@ protected: std::set getpidofprogram(const std::string program); - static std::string getCommandToRunRemoteProcess(AccessProtocolType protocol, const std::string & hostname, const std::string & username); + static std::string getCommandToRunRemoteProcess(AccessProtocolType protocol, + const std::string & hostname, + const std::string & username, + const std::string & applipath, + const std::string & workdir=""); Engines::Container_ptr LaunchContainer(const Engines::ContainerParameters& params, diff --git a/src/ResourcesManager/ResourcesManager.cxx b/src/ResourcesManager/ResourcesManager.cxx index ba27107b4..4a48e8349 100644 --- a/src/ResourcesManager/ResourcesManager.cxx +++ b/src/ResourcesManager/ResourcesManager.cxx @@ -148,17 +148,23 @@ ResourcesManager_cpp::ResourcesManager_cpp() throw(ResourcesException) default_file += "/"; default_file += getenv("APPLI"); default_file += "/CatalogResources.xml"; - _path_resources.push_back(default_file); - } - else - { - if(!getenv("KERNEL_ROOT_DIR")) - throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml"); - default_file = getenv("KERNEL_ROOT_DIR"); - default_file += "/share/salome/resources/kernel/CatalogResources.xml"; - _path_resources.push_back(default_file); + std::ifstream ifile(default_file.c_str(), std::ifstream::in ); + if (ifile) { + // The file exists, and is open for input + _path_resources.push_back(default_file); + default_catalog_resource=false; + } } } + if (default_catalog_resource) + { + std::string default_file(""); + if(!getenv("KERNEL_ROOT_DIR")) + throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml"); + default_file = getenv("KERNEL_ROOT_DIR"); + default_file += "/share/salome/resources/kernel/CatalogResources.xml"; + _path_resources.push_back(default_file); + } _lasttime=0; -- 2.39.2