1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "SALOME_ContainerManager.hxx"
23 #include "SALOME_NamingService.hxx"
24 #include "SALOME_ModuleCatalog.hh"
25 #include "Basics_Utils.hxx"
26 #include "Basics_DirUtils.hxx"
27 #include <sys/types.h>
33 #include "Utils_CorbaException.hxx"
34 #include "Batch_Date.hxx"
37 #ifdef WITH_PACO_PARALLEL
41 #define TIME_OUT_TO_LAUNCH_CONT 61
45 vector<Engines::Container_ptr> SALOME_ContainerManager::_batchLaunchedContainers;
47 vector<Engines::Container_ptr>::iterator SALOME_ContainerManager::_batchLaunchedContainersIter;
49 const char *SALOME_ContainerManager::_ContainerManagerNameInNS =
52 //=============================================================================
56 * Define a CORBA single thread policy for the server, which avoid to deal
57 * with non thread-safe usage like Change_Directory in SALOME naming service
59 //=============================================================================
61 SALOME_ContainerManager::SALOME_ContainerManager(CORBA::ORB_ptr orb, PortableServer::POA_var poa, SALOME_ResourcesManager *rm, SALOME_NamingService *ns)
63 MESSAGE("constructor");
67 PortableServer::POAManager_var pman = poa->the_POAManager();
68 _orb = CORBA::ORB::_duplicate(orb) ;
69 CORBA::PolicyList policies;
71 PortableServer::ThreadPolicy_var threadPol =
72 poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
73 policies[0] = PortableServer::ThreadPolicy::_duplicate(threadPol);
75 _poa = poa->create_POA("SThreadPOA",pman,policies);
77 PortableServer::ObjectId_var id = _poa->activate_object(this);
78 CORBA::Object_var obj = _poa->id_to_reference(id);
79 Engines::ContainerManager_var refContMan =
80 Engines::ContainerManager::_narrow(obj);
82 _NS->Register(refContMan,_ContainerManagerNameInNS);
83 _isAppliSalomeDefined = (getenv("APPLI") != 0);
86 if( getenv("OMPI_URI_FILE") != NULL ){
87 system("killall ompi-server");
89 command = "ompi-server -r ";
90 command += getenv("OMPI_URI_FILE");
91 int status=system(command.c_str());
93 throw SALOME_Exception("Error when launching ompi-server");
97 MESSAGE("constructor end");
100 //=============================================================================
104 //=============================================================================
106 SALOME_ContainerManager::~SALOME_ContainerManager()
108 MESSAGE("destructor");
110 if( getenv("OMPI_URI_FILE") != NULL )
111 system("killall ompi-server");
115 //=============================================================================
116 //! shutdown all the containers, then the ContainerManager servant
119 //=============================================================================
121 void SALOME_ContainerManager::Shutdown()
124 ShutdownContainers();
125 _NS->Destroy_Name(_ContainerManagerNameInNS);
126 PortableServer::ObjectId_var oid = _poa->servant_to_id(this);
127 _poa->deactivate_object(oid);
130 //=============================================================================
131 //! Loop on all the containers listed in naming service, ask shutdown on each
134 //=============================================================================
136 void SALOME_ContainerManager::ShutdownContainers()
138 MESSAGE("ShutdownContainers");
140 isOK = _NS->Change_Directory("/Containers");
142 vector<string> vec = _NS->list_directory_recurs();
143 list<string> lstCont;
144 for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++)
147 CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
150 Engines::Container_var cont=Engines::Container::_narrow(obj);
151 if(!CORBA::is_nil(cont))
152 lstCont.push_back((*iter));
154 catch(const CORBA::Exception& e)
156 // ignore this entry and continue
159 MESSAGE("Container list: ");
160 for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++){
163 for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++)
168 CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
169 Engines::Container_var cont=Engines::Container::_narrow(obj);
170 if(!CORBA::is_nil(cont))
172 MESSAGE("ShutdownContainers: " << (*iter));
176 MESSAGE("ShutdownContainers: no container ref for " << (*iter));
178 catch(CORBA::SystemException& e)
180 INFOS("CORBA::SystemException ignored : " << e);
182 catch(CORBA::Exception&)
184 INFOS("CORBA::Exception ignored.");
188 INFOS("Unknown exception ignored.");
194 //=============================================================================
195 //! Give a suitable Container given constraints
197 * \param params Machine Parameters required for the container
198 * \return the container or nil
200 //=============================================================================
202 Engines::Container_ptr
203 SALOME_ContainerManager::GiveContainer(const Engines::MachineParameters& params)
205 char *valenv=getenv("SALOME_BATCH");
207 if (strcmp(valenv,"1")==0)
209 if(_batchLaunchedContainers.empty())
210 fillBatchLaunchedContainers();
212 if (_batchLaunchedContainersIter == _batchLaunchedContainers.end())
213 _batchLaunchedContainersIter = _batchLaunchedContainers.begin();
215 Engines::Container_ptr rtn = Engines::Container::_duplicate(*_batchLaunchedContainersIter);
216 _batchLaunchedContainersIter++;
219 return StartContainer(params);
222 //=============================================================================
223 //! Start a suitable Container in a list of machines with constraints
225 * Constraints are given by a machine parameters struct
226 * \param params Machine Parameters required for the container
227 * \param possibleComputers list of machines usable for start
228 * \param container_exe specific container executable (default=SALOME_Container)
230 //=============================================================================
232 Engines::Container_ptr
233 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params,
234 const Engines::MachineList& possibleComputers,
235 const std::string& container_exe)
237 #ifdef WITH_PACO_PARALLEL
238 std::string parallelLib(params.parallelLib);
239 if (parallelLib != "")
241 Engines::MachineParameters myparams(params);
242 myparams.computerList=possibleComputers;
243 return StartParallelContainer(myparams);
246 string containerNameInNS;
247 Engines::Container_ptr ret = Engines::Container::_nil();
249 MESSAGE("SALOME_ContainerManager::StartContainer " << possibleComputers.length());
252 // if mode is "get" keep only machines with existing containers
253 if(std::string(params.mode.in())=="get")
255 for(unsigned int i=0;i<possibleComputers.length();i++)
257 Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
260 if(!cont->_non_existent())
261 lm.push_back(string(possibleComputers[i]));
263 catch(CORBA::Exception&)
265 // CORBA::Exception ignored.
271 for(unsigned int i=0;i<possibleComputers.length();i++)
272 lm.push_back(string(possibleComputers[i]));
278 theMachine=_ResManager->GetImpl()->Find(params.policy.in(),lm);
280 catch( const SALOME_Exception &ex )
283 return Engines::Container::_nil();
286 //If the machine name is localhost use the real name
287 if(theMachine == "localhost")
288 theMachine=Kernel_Utils::GetHostname();
290 //check if an entry exists in Naming service
291 //if params.mode == "start" or "" shutdown the existing container before launching a new one with that name
292 //if params.mode == "getorstart" or "get" use the existing container
294 // A parallel container register on zero node in NS
295 containerNameInNS = _NS->BuildContainerNameForNS(params,GetMPIZeroNode(theMachine).c_str());
297 containerNameInNS = _NS->BuildContainerNameForNS(params,theMachine.c_str());
299 SCRUTE(containerNameInNS);
300 CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
301 if ( !CORBA::is_nil(obj) )
305 Engines::Container_var cont=Engines::Container::_narrow(obj);
306 if(!cont->_non_existent())
308 if(std::string(params.mode.in())=="getorstart"||std::string(params.mode.in())=="get")
309 return cont._retn(); /* the container exists and params.mode is getorstart or get use it*/
312 INFOS("A container is already registered with the name: " << containerNameInNS << ", shutdown the existing container");
313 cont->Shutdown(); // shutdown the registered container if it exists
317 catch(CORBA::Exception&)
319 INFOS("CORBA::Exception ignored.");
323 //try to launch a new container
324 MESSAGE("try to launch it on " << theMachine);
328 MESSAGE("SALOME_ContainerManager::StartContainer : no possible computer");
329 return Engines::Container::_nil();
331 else if(theMachine==Kernel_Utils::GetHostname())
332 command = BuildCommandToLaunchLocalContainer(params,container_exe);
334 command = BuildCommandToLaunchRemoteContainer(theMachine,params,container_exe);
336 //redirect stdout and stderr in a file
338 string logFilename=getenv("TEMP");
341 string logFilename="/tmp";
342 char* val = getenv("SALOME_TMP_DIR");
345 struct stat file_info;
346 stat(val, &file_info);
347 bool is_dir = S_ISDIR(file_info.st_mode);
348 if (is_dir)logFilename=val;
349 else std::cerr << "SALOME_TMP_DIR environment variable is not a directory use /tmp instead" << std::endl;
353 logFilename += _NS->ContainerName(params)+"_"+ theMachine +"_"+getenv( "USER" )+".log" ;
354 command += " > " + logFilename + " 2>&1";
356 command = "%PYTHONBIN% -c \"import win32pm ; win32pm.spawnpid(r'" + command + "', '')\"";
361 // launch container with a system call
362 int status=system(command.c_str());
365 MESSAGE("SALOME_ContainerManager::StartContainer rsh failed (system command status -1)");
366 RmTmpFile(_TmpFileName); // command file can be removed here
367 return Engines::Container::_nil();
369 else if (status == 217){
370 MESSAGE("SALOME_ContainerManager::StartContainer rsh failed (system command status 217)");
371 RmTmpFile(_TmpFileName); // command file can be removed here
372 return Engines::Container::_nil();
375 int count=TIME_OUT_TO_LAUNCH_CONT;
376 MESSAGE("count = "<<count);
377 while ( CORBA::is_nil(ret) && count ){
385 MESSAGE( count << ". Waiting for container on " << theMachine);
387 CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
388 ret=Engines::Container::_narrow(obj);
391 if ( CORBA::is_nil(ret) )
393 MESSAGE("SALOME_ContainerManager::StartContainer rsh failed");
397 logFilename=":"+logFilename;
398 logFilename="@"+Kernel_Utils::GetHostname()+logFilename;
399 logFilename=getenv( "USER" )+logFilename;
400 ret->logfilename(logFilename.c_str());
403 RmTmpFile(_TmpFileName); // command file can be removed here
408 //=============================================================================
409 //! Start a suitable Container given constraints
411 * \param params Machine Parameters required for the container
413 //=============================================================================
415 Engines::Container_ptr
416 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params)
418 Engines::MachineList_var possibleComputers = _ResManager->GetFittingResources(params);
420 // Look into ModulCatalog if a specific container must be launched
421 CORBA::String_var container_exe;
425 CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
426 SALOME_ModuleCatalog::ModuleCatalog_var Catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
427 if (CORBA::is_nil (Catalog))
428 return Engines::Container::_nil();
429 // Loop through component list
430 for(unsigned int i=0;i<params.componentList.length();i++)
432 const char* compoi = params.componentList[i];
433 SALOME_ModuleCatalog::Acomponent_var compoInfo = Catalog->GetComponent(compoi);
434 if (CORBA::is_nil (compoInfo))
438 SALOME_ModuleCatalog::ImplType impl=compoInfo->implementation_type();
439 container_exe=compoInfo->implementation_name();
440 if(impl==SALOME_ModuleCatalog::CEXE)
444 INFOS("ContainerManager Error: you can't have 2 CEXE component in the same container" );
445 return Engines::Container::_nil();
451 catch (ServiceUnreachable&)
453 INFOS("Caught exception: Naming Service Unreachable");
454 return Engines::Container::_nil();
458 INFOS("Caught unknown exception.");
459 return Engines::Container::_nil();
463 return StartContainer(params,possibleComputers,container_exe.in());
465 return StartContainer(params,possibleComputers);
468 //=============================================================================
469 //! Find or start a suitable Container given some constraints
471 * \param params Machine Parameters required for the container
472 * \return the container or nil
474 //=============================================================================
476 Engines::Container_ptr
477 SALOME_ContainerManager::FindOrStartContainer(const Engines::MachineParameters& params)
479 Engines::Container_ptr ret = FindContainer(params,params.computerList);
480 if(!CORBA::is_nil(ret))
482 MESSAGE("Container doesn't exist try to launch it ...");
484 return StartContainer(params);
487 //=============================================================================
488 //! Find a container given constraints (params) on a list of machines (possibleComputers)
492 //=============================================================================
494 Engines::Container_ptr
495 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
496 const Engines::MachineList& possibleComputers)
498 MESSAGE("FindContainer "<<possibleComputers.length());
499 for(unsigned int i=0;i<possibleComputers.length();i++)
501 MESSAGE("FindContainer possible " << possibleComputers[i]);
502 Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
503 if( !CORBA::is_nil(cont) )
506 MESSAGE("FindContainer: not found");
507 return Engines::Container::_nil();
510 //=============================================================================
511 //! Find a container given constraints (params) on a machine (theMachine)
515 //=============================================================================
517 Engines::Container_ptr
518 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
519 const char *theMachine)
521 string containerNameInNS(_NS->BuildContainerNameForNS(params,theMachine));
522 CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
525 if(obj->_non_existent())
526 return Engines::Container::_nil();
528 return Engines::Container::_narrow(obj);
530 catch(const CORBA::Exception& e)
532 return Engines::Container::_nil();
536 #ifdef WITH_PACO_PARALLEL
537 //=============================================================================
539 * Find or Start a suitable PaCO++ Parallel Container in a list of machines.
540 * \param params Machine Parameters required for the container
541 * \return CORBA container reference.
543 //=============================================================================
544 Engines::Container_ptr
545 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params_const)
547 CORBA::Object_var obj;
548 PaCO::InterfaceManager_var container_proxy;
549 Engines::Container_ptr ret = Engines::Container::_nil();
550 Engines::MachineParameters params(params_const);
552 // Step 1 : Try to find a suitable container
553 // Currently not as good as could be since
554 // we have to verified the number of nodes of the container
555 // if a user tell that.
556 ret = FindContainer(params, params.computerList);
557 if(CORBA::is_nil(ret)) {
558 // Step 2 : Starting a new parallel container !
559 INFOS("[StartParallelContainer] Starting a PaCO++ parallel container");
561 // Step 3 : Choose a computer
562 std::string theMachine = _ResManager->FindFirst(params.computerList);
563 //If the machine name is localhost use the real name
564 if(theMachine == "localhost")
565 theMachine=Kernel_Utils::GetHostname();
567 if(theMachine == "") {
568 INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
569 INFOS("[StartParallelContainer] No possible computer found");
570 INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
573 INFOS("[StartParallelContainer] on machine : " << theMachine);
574 params.hostname = CORBA::string_dup(theMachine.c_str());
576 // Step 4 : starting parallel container proxy
577 Engines::MachineParameters params_proxy(params);
578 std::string command_proxy;
579 SALOME_ContainerManager::actual_launch_machine_t proxy_machine;
582 command_proxy = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerProxy", params_proxy, proxy_machine);
584 catch(const SALOME_Exception & ex)
586 INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
590 params_proxy.nb_component_nodes = 0; // LaunchParallelContainer uses this value to know if it launches the proxy or the nodes
591 obj = LaunchParallelContainer(command_proxy, params_proxy, _NS->ContainerName(params_proxy), proxy_machine);
592 if (CORBA::is_nil(obj))
594 INFOS("[StartParallelContainer] LaunchParallelContainer for proxy returns NIL !");
599 container_proxy = PaCO::InterfaceManager::_narrow(obj);
601 catch(CORBA::SystemException& e)
603 INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
604 INFOS("CORBA::SystemException : " << e);
607 catch(CORBA::Exception& e)
609 INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
610 INFOS("CORBA::Exception" << e);
615 INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
616 INFOS("Unknown exception !");
619 if (CORBA::is_nil(container_proxy))
621 INFOS("[StartParallelContainer] PaCO::InterfaceManager::_narrow returns NIL !");
625 // Step 5 : starting parallel container nodes
626 std::string command_nodes;
627 Engines::MachineParameters params_nodes(params);
628 SALOME_ContainerManager::actual_launch_machine_t nodes_machines;
631 command_nodes = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerNode", params_nodes, nodes_machines, proxy_machine[0]);
633 catch(const SALOME_Exception & ex)
635 INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
639 std::string container_generic_node_name = _NS->ContainerName(params) + "Node";
640 obj = LaunchParallelContainer(command_nodes, params_nodes, container_generic_node_name, nodes_machines);
641 if (CORBA::is_nil(obj))
643 INFOS("[StartParallelContainer] LaunchParallelContainer for nodes returns NIL !");
644 // Il faut tuer le proxy
647 Engines::Container_var proxy = Engines::Container::_narrow(container_proxy);
652 INFOS("[StartParallelContainer] Exception catched from proxy Shutdown...");
657 // Step 6 : connecting nodes and the proxy to actually create a parallel container
658 for (int i = 0; i < params.nb_component_nodes; i++)
660 std::ostringstream tmp;
662 std::string proc_number = tmp.str();
663 std::string container_node_name = container_generic_node_name + proc_number;
665 std::string theNodeMachine(nodes_machines[i]);
666 std::string containerNameInNS = _NS->BuildContainerNameForNS(container_node_name.c_str(), theNodeMachine.c_str());
667 obj = _NS->Resolve(containerNameInNS.c_str());
668 if (CORBA::is_nil(obj))
670 INFOS("[StartParallelContainer] CONNECTION FAILED From Naming Service !");
671 INFOS("[StartParallelContainer] Container name is " << containerNameInNS);
676 MESSAGE("[StartParallelContainer] Deploying node : " << container_node_name);
677 PaCO::InterfaceParallel_var node = PaCO::InterfaceParallel::_narrow(obj);
679 MESSAGE("[StartParallelContainer] node " << container_node_name << " is deployed");
681 catch(CORBA::SystemException& e)
683 INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
684 INFOS("CORBA::SystemException : " << e);
687 catch(CORBA::Exception& e)
689 INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
690 INFOS("CORBA::Exception" << e);
695 INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
696 INFOS("Unknown exception !");
701 // Step 7 : starting parallel container
704 MESSAGE ("[StartParallelContainer] Starting parallel object");
705 container_proxy->start();
706 MESSAGE ("[StartParallelContainer] Parallel object is started");
707 ret = Engines::Container::_narrow(container_proxy);
709 catch(CORBA::SystemException& e)
711 INFOS("Caught CORBA::SystemException. : " << e);
713 catch(PortableServer::POA::ServantAlreadyActive&)
715 INFOS("Caught CORBA::ServantAlreadyActiveException");
717 catch(CORBA::Exception&)
719 INFOS("Caught CORBA::Exception.");
721 catch(std::exception& exc)
723 INFOS("Caught std::exception - "<<exc.what());
727 INFOS("Caught unknown exception.");
733 //=============================================================================
735 * Find or Start a suitable PaCO++ Parallel Container in a list of machines.
736 * \param params Machine Parameters required for the container
737 * \return CORBA container reference.
739 //=============================================================================
740 Engines::Container_ptr
741 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params)
743 Engines::Container_ptr ret = Engines::Container::_nil();
744 INFOS("[StartParallelContainer] is disabled !");
745 INFOS("[StartParallelContainer] recompile SALOME Kernel to enable parallel extension");
750 //=============================================================================
751 /*! This method launches the parallel container.
752 * It will may be placed on the ressources manager.
754 * \param command to launch
755 * \param container's parameters
756 * \param name of the container
758 * \return CORBA container reference
760 //=============================================================================
762 SALOME_ContainerManager::LaunchParallelContainer(const std::string& command,
763 const Engines::MachineParameters& params,
764 const std::string& name,
765 SALOME_ContainerManager::actual_launch_machine_t & vect_machine)
767 CORBA::Object_ptr obj = CORBA::Object::_nil();
768 std::string containerNameInNS;
769 int count = TIME_OUT_TO_LAUNCH_CONT;
771 INFOS("[LaunchParallelContainer] Begin");
772 int status = system(command.c_str());
774 INFOS("[LaunchParallelContainer] failed : system command status -1");
777 else if (status == 217) {
778 INFOS("[LaunchParallelContainer] failed : system command status 217");
782 if (params.nb_component_nodes == 0)
784 std::string theMachine(vect_machine[0]);
785 // Proxy We have launch a proxy
786 containerNameInNS = _NS->BuildContainerNameForNS((char*) name.c_str(), theMachine.c_str());
787 INFOS("[LaunchParallelContainer] Waiting for Parallel Container proxy " << containerNameInNS << " on " << theMachine);
788 while (CORBA::is_nil(obj) && count)
796 obj = _NS->Resolve(containerNameInNS.c_str());
801 INFOS("[LaunchParallelContainer] launching the nodes of the parallel container");
802 // We are waiting all the nodes
803 for (int i = 0; i < params.nb_component_nodes; i++)
805 obj = CORBA::Object::_nil();
806 std::string theMachine(vect_machine[i]);
808 std::ostringstream tmp;
810 std::string proc_number = tmp.str();
811 std::string container_node_name = name + proc_number;
812 containerNameInNS = _NS->BuildContainerNameForNS((char*) container_node_name.c_str(), theMachine.c_str());
813 INFOS("[LaunchParallelContainer] Waiting for Parallel Container node " << containerNameInNS << " on " << theMachine);
814 while (CORBA::is_nil(obj) && count) {
821 obj = _NS->Resolve(containerNameInNS.c_str());
823 if (CORBA::is_nil(obj))
825 INFOS("[LaunchParallelContainer] Launch of node failed (or not found) !");
830 if (CORBA::is_nil(obj))
831 INFOS("[LaunchParallelContainer] failed");
836 void SALOME_ContainerManager::fillBatchLaunchedContainers()
838 _batchLaunchedContainers.clear();
839 _NS->Change_Directory("/Containers");
840 vector<string> vec = _NS->list_directory_recurs();
841 for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++){
842 CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
843 Engines::Container_ptr cont=Engines::Container::_narrow(obj);
844 if(!CORBA::is_nil(cont)){
845 _batchLaunchedContainers.push_back(cont);
848 _batchLaunchedContainersIter=_batchLaunchedContainers.begin();
851 //=============================================================================
853 * This is no longer valid (C++ container are also python containers)
855 //=============================================================================
857 bool isPythonContainer(const char* ContainerName)
860 int len = strlen(ContainerName);
863 if (strcmp(ContainerName + len - 2, "Py") == 0)
869 //=============================================================================
871 * Builds the script to be launched
873 * If SALOME Application not defined ($APPLI),
874 * see BuildTempFileToLaunchRemoteContainer()
876 * Else rely on distant configuration. Command is under the form (example):
877 * ssh user@machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \
878 * SALOME_Container containerName &"
880 * - where user is ommited if not specified in CatalogResources,
881 * - where distant path is always relative to user@machine $HOME, and
882 * equal to $APPLI if not specified in CatalogResources,
883 * - where hostNS is the hostname of CORBA naming server (set by scripts to
884 * use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
885 * - where portNS is the port used by CORBA naming server (set by scripts to
886 * use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
887 * - where workingdir is the requested working directory for the container.
888 * If WORKINGDIR (and workingdir) is not present the working dir will be $HOME
890 //=============================================================================
893 SALOME_ContainerManager::BuildCommandToLaunchRemoteContainer
894 (const string& machine,
895 const Engines::MachineParameters& params, const std::string& container_exe)
900 if ( ! _isAppliSalomeDefined )
901 command = BuildTempFileToLaunchRemoteContainer(machine, params);
905 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine);
909 if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
911 else if ( params.nb_node == 0 )
912 nbproc = params.nb_proc_per_node;
913 else if ( params.nb_proc_per_node == 0 )
914 nbproc = params.nb_node;
916 nbproc = params.nb_node * params.nb_proc_per_node;
919 // "ssh user@machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \
920 // SALOME_Container containerName &"
922 if (resInfo.Protocol == rsh)
924 else if (resInfo.Protocol == ssh)
927 throw SALOME_Exception("Unknown protocol");
929 if (resInfo.UserName != "")
931 command += resInfo.UserName;
938 if (resInfo.AppliPath != "")
939 command += resInfo.AppliPath; // path relative to user@machine $HOME
942 ASSERT(getenv("APPLI"));
943 command += getenv("APPLI"); // path relative to user@machine $HOME
946 command += "/runRemote.sh ";
948 ASSERT(getenv("NSHOST"));
949 command += getenv("NSHOST"); // hostname of CORBA name server
952 ASSERT(getenv("NSPORT"));
953 command += getenv("NSPORT"); // port of CORBA name server
955 std::string wdir=params.workingdir.in();
958 command += " WORKINGDIR ";
960 if(wdir == "$TEMPDIR")
962 command += wdir; // requested working directory
968 command += " mpirun -np ";
969 std::ostringstream o;
973 command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
974 #elif defined(WITHOPENMPI)
975 if( getenv("OMPI_URI_FILE") == NULL )
976 command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
978 command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
979 command += getenv("OMPI_URI_FILE");
982 command += " SALOME_MPIContainer ";
985 command += " " +container_exe+ " ";
987 command += _NS->ContainerName(params);
989 AddOmninamesParams(command);
991 MESSAGE("command =" << command);
997 //=============================================================================
999 * builds the command to be launched.
1001 //=============================================================================
1004 SALOME_ContainerManager::BuildCommandToLaunchLocalContainer
1005 (const Engines::MachineParameters& params, const std::string& container_exe)
1007 _TmpFileName = BuildTemporaryFileName();
1011 ofstream command_file( _TmpFileName.c_str() );
1015 //command = "mpirun -np ";
1016 command_file << "mpirun -np ";
1018 if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
1020 else if ( params.nb_node == 0 )
1021 nbproc = params.nb_proc_per_node;
1022 else if ( params.nb_proc_per_node == 0 )
1023 nbproc = params.nb_node;
1025 nbproc = params.nb_node * params.nb_proc_per_node;
1027 //std::ostringstream o;
1029 //o << nbproc << " ";
1030 command_file << nbproc << " ";
1032 //command += o.str();
1034 //command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
1035 command_file << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
1036 #elif defined(WITHOPENMPI)
1037 //command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace ";
1038 if( getenv("OMPI_URI_FILE") == NULL )
1039 command_file << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
1042 command_file << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
1043 command_file << getenv("OMPI_URI_FILE");
1047 if (isPythonContainer(params.container_name))
1048 //command += "pyMPI SALOME_ContainerPy.py ";
1049 command_file << " pyMPI SALOME_ContainerPy.py ";
1051 //command += "SALOME_MPIContainer ";
1052 command_file << " SALOME_MPIContainer ";
1058 std::string wdir=params.workingdir.in();
1061 // a working directory is requested
1062 if(wdir == "$TEMPDIR")
1064 // a new temporary directory is requested
1065 string dir = Kernel_Utils::GetTmpDir();
1067 //command += "cd /d "+ dir +";";
1068 command_file << "cd /d " << dir << endl;
1070 //command = "cd "+ dir +";";
1071 command_file << "cd " << dir << ";";
1077 // a permanent directory is requested use it or create it
1079 //command="mkdir " + wdir;
1080 command_file << "mkdir " + wdir << endl;
1081 command_file << "cd /D " + wdir << endl;
1083 //command="mkdir -p " + wdir + " && cd " + wdir + ";";
1084 command_file << "mkdir -p " << wdir << " && cd " << wdir + ";";
1088 if (isPythonContainer(params.container_name))
1089 //command += "SALOME_ContainerPy.py ";
1090 command_file << "SALOME_ContainerPy.py ";
1092 //command += container_exe + " ";
1093 command_file << container_exe + " ";
1097 command_file << _NS->ContainerName(params);
1098 command_file << " -";
1099 AddOmninamesParams(command_file);
1100 command_file.close();
1103 chmod(_TmpFileName.c_str(), 0x1ED);
1105 command = _TmpFileName;
1107 MESSAGE("Command is file ... " << command);
1112 //=============================================================================
1114 * removes the generated temporary file in case of a remote launch.
1116 //=============================================================================
1118 void SALOME_ContainerManager::RmTmpFile(std::string& tmpFileName)
1120 int lenght = tmpFileName.size();
1124 string command = "del /F ";
1126 string command = "rm ";
1129 command += tmpFileName.substr(0, lenght - 3 );
1131 command += tmpFileName;
1133 system(command.c_str());
1134 //if dir is empty - remove it
1135 string tmp_dir = Kernel_Utils::GetDirByPath( tmpFileName );
1136 if ( Kernel_Utils::IsEmptyDir( tmp_dir ) )
1139 command = "del /F " + tmp_dir;
1141 command = "rmdir " + tmp_dir;
1143 system(command.c_str());
1148 //=============================================================================
1150 * add to command all options relative to naming service.
1152 //=============================================================================
1154 void SALOME_ContainerManager::AddOmninamesParams(string& command) const
1156 CORBA::String_var iorstr = _NS->getIORaddr();
1157 command += "ORBInitRef NameService=";
1162 //=============================================================================
1164 * add to command all options relative to naming service.
1166 //=============================================================================
1168 void SALOME_ContainerManager::AddOmninamesParams(ofstream& fileStream) const
1170 CORBA::String_var iorstr = _NS->getIORaddr();
1171 fileStream << "ORBInitRef NameService=";
1172 fileStream << iorstr;
1175 //=============================================================================
1177 * generate a file name in /tmp directory
1179 //=============================================================================
1181 string SALOME_ContainerManager::BuildTemporaryFileName() const
1183 //build more complex file name to support multiple salome session
1184 string aFileName = Kernel_Utils::GetTmpFileName();
1188 aFileName += ".bat";
1194 //=============================================================================
1196 * Builds in a temporary file the script to be launched.
1198 * Used if SALOME Application ($APPLI) is not defined.
1199 * The command is build with data from CatalogResources, in which every path
1200 * used on remote computer must be defined.
1202 //=============================================================================
1205 SALOME_ContainerManager::BuildTempFileToLaunchRemoteContainer
1206 (const string& machine,
1207 const Engines::MachineParameters& params) throw(SALOME_Exception)
1211 _TmpFileName = BuildTemporaryFileName();
1212 ofstream tempOutputFile;
1213 tempOutputFile.open(_TmpFileName.c_str(), ofstream::out );
1214 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine);
1215 tempOutputFile << "#! /bin/sh" << endl;
1219 tempOutputFile << "export SALOME_trace=local" << endl; // mkr : 27.11.2006 : PAL13967 - Distributed supervision graphs - Problem with "SALOME_trace"
1220 //tempOutputFile << "source " << resInfo.PreReqFilePath << endl;
1226 tempOutputFile << "mpirun -np ";
1229 if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
1231 else if ( params.nb_node == 0 )
1232 nbproc = params.nb_proc_per_node;
1233 else if ( params.nb_proc_per_node == 0 )
1234 nbproc = params.nb_node;
1236 nbproc = params.nb_node * params.nb_proc_per_node;
1238 std::ostringstream o;
1240 tempOutputFile << nbproc << " ";
1242 tempOutputFile << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
1243 #elif defined(WITHOPENMPI)
1244 if( getenv("OMPI_URI_FILE") == NULL )
1245 tempOutputFile << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
1247 tempOutputFile << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
1248 tempOutputFile << getenv("OMPI_URI_FILE");
1253 tempOutputFile << getenv("KERNEL_ROOT_DIR") << "/bin/salome/";
1257 if (isPythonContainer(params.container_name))
1258 tempOutputFile << " pyMPI SALOME_ContainerPy.py ";
1260 tempOutputFile << " SALOME_MPIContainer ";
1265 if (isPythonContainer(params.container_name))
1266 tempOutputFile << "SALOME_ContainerPy.py ";
1268 tempOutputFile << "SALOME_Container ";
1271 tempOutputFile << _NS->ContainerName(params) << " -";
1272 AddOmninamesParams(tempOutputFile);
1273 tempOutputFile << " &" << endl;
1274 tempOutputFile.flush();
1275 tempOutputFile.close();
1277 chmod(_TmpFileName.c_str(), 0x1ED);
1280 // --- Build command
1284 if (resInfo.Protocol == rsh)
1287 string commandRcp = "rcp ";
1288 commandRcp += _TmpFileName;
1290 commandRcp += machine;
1292 commandRcp += _TmpFileName;
1293 status = system(commandRcp.c_str());
1296 else if (resInfo.Protocol == ssh)
1299 string commandRcp = "scp ";
1300 commandRcp += _TmpFileName;
1302 commandRcp += machine;
1304 commandRcp += _TmpFileName;
1305 status = system(commandRcp.c_str());
1308 throw SALOME_Exception("Unknown protocol");
1311 throw SALOME_Exception("Error of connection on remote host");
1314 _CommandForRemAccess = command;
1316 command += _TmpFileName;
1324 //=============================================================================
1325 /*! Creates a command line that the container manager uses to launch
1326 * a parallel container.
1328 //=============================================================================
1330 SALOME_ContainerManager::BuildCommandToLaunchParallelContainer(const std::string& exe_name,
1331 const Engines::MachineParameters& params,
1332 SALOME_ContainerManager::actual_launch_machine_t & vect_machine,
1333 const std::string proxy_hostname)
1335 // This method knows the differences between the proxy and the nodes.
1336 // nb_component_nodes is not used in the same way if it is a proxy or
1339 //command = "gdb --args ";
1340 //command = "valgrind --tool=memcheck --log-file=val_log ";
1341 //command += real_exe_name;
1343 // Step 0 : init some variables...
1344 std::string parallelLib(CORBA::string_dup(params.parallelLib));
1345 std::string real_exe_name = exe_name + parallelLib;
1346 std::string machine_file_name("");
1347 bool remote = false;
1348 bool is_a_proxy = false;
1349 std::string hostname(CORBA::string_dup(params.hostname));
1351 std::ostringstream tmp_string;
1352 CORBA::Long nb_nodes = params.nb_component_nodes;
1353 tmp_string << nb_nodes;
1354 std::string nbproc = tmp_string.str();
1356 Engines::MachineParameters_var rtn = new Engines::MachineParameters();
1357 rtn->container_name = params.container_name;
1358 rtn->hostname = params.hostname;
1359 rtn->OS = params.OS;
1360 rtn->mem_mb = params.mem_mb;
1361 rtn->cpu_clock = params.cpu_clock;
1362 rtn->nb_proc_per_node = params.nb_proc_per_node;
1363 rtn->nb_node = params.nb_node;
1364 rtn->isMPI = params.isMPI;
1366 // Step 1 : local or remote launch ?
1367 if (hostname != std::string(Kernel_Utils::GetHostname()) )
1369 MESSAGE("[BuildCommandToLaunchParallelContainer] remote machine case detected !");
1373 // Step 2 : proxy or nodes launch ?
1374 std::string::size_type loc_proxy = exe_name.find("Proxy");
1375 if( loc_proxy != string::npos ) {
1379 // Step 3 : Depending of the parallelLib, getting the machine file
1380 // ParallelLib Dummy has is own machine for this method
1385 machine_file_name = _ResManager->getMachineFile(hostname,
1391 machine_file_name = _ResManager->getMachineFile(hostname,
1392 params.nb_component_nodes,
1395 if (machine_file_name == "")
1397 INFOS("[BuildCommandToLaunchParallelContainer] Error machine_file was not generated for machine " << hostname);
1398 throw SALOME_Exception("Error machine_file was not generated");
1400 MESSAGE("[BuildCommandToLaunchParallelContainer] machine_file_name is : " << machine_file_name);
1403 // Step 4 : Log type choosen by the user
1404 std::string log_env("");
1405 char * get_val = getenv("PARALLEL_LOG");
1408 std::string command_begin("");
1409 std::string command_end("");
1410 if(log_env == "xterm")
1412 command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1413 command_end = "\"&";
1415 else if(log_env == "xterm_debug")
1417 command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1418 command_end = "; cat \" &";
1422 // default into a file...
1423 std::string logFilename = "/tmp/" + _NS->ContainerName(params) + "_" + hostname;
1425 logFilename += "_Proxy_";
1427 logFilename += "_Node_";
1428 logFilename += std::string(getenv("USER")) + ".log";
1429 command_end = " > " + logFilename + " 2>&1 & ";
1432 // Step 5 : Building the command
1433 std::string command("");
1434 if (parallelLib == "Dummy")
1438 std::string command_remote("");
1441 std::string machine_name;
1442 std::ifstream machine_file(machine_file_name.c_str());
1443 std::getline(machine_file, machine_name);
1444 MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << machine_name)
1446 // We want to launch a command like :
1447 // ssh user@machine distantPath/runRemote.sh hostNS portNS
1448 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine_name);
1449 if (resInfo.Protocol == rsh)
1450 command_remote = "rsh ";
1452 command_remote = "ssh ";
1453 command_remote += resInfo.UserName;
1454 command_remote += "@";
1455 command_remote += machine_name;
1456 command_remote += " ";
1457 command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1458 command_remote += "/runRemote.sh ";
1459 ASSERT(getenv("NSHOST"));
1460 command_remote += getenv("NSHOST"); // hostname of CORBA name server
1461 command_remote += " ";
1462 ASSERT(getenv("NSPORT"));
1463 command_remote += getenv("NSPORT"); // port of CORBA name server
1464 command_remote += " ";
1466 hostname = machine_name;
1469 command = real_exe_name;
1470 command += " " + _NS->ContainerName(rtn);
1471 command += " " + parallelLib;
1472 command += " " + hostname;
1473 command += " " + nbproc;
1475 AddOmninamesParams(command);
1477 command = command_begin + command_remote + command + command_end;
1478 vect_machine.push_back(hostname);
1482 std::ifstream * machine_file = NULL;
1484 machine_file = new std::ifstream(machine_file_name.c_str());
1485 for (int i= 0; i < nb_nodes; i++)
1487 std::string command_remote("");
1490 std::string machine_name;
1491 std::getline(*machine_file, machine_name);
1492 MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << machine_name)
1494 // We want to launch a command like :
1495 // ssh user@machine distantPath/runRemote.sh hostNS portNS
1496 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine_name);
1497 if (resInfo.Protocol == rsh)
1498 command_remote = "rsh ";
1500 command_remote = "ssh ";
1501 command_remote += resInfo.UserName;
1502 command_remote += "@";
1503 command_remote += machine_name;
1504 command_remote += " ";
1505 command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1506 command_remote += "/runRemote.sh ";
1507 ASSERT(getenv("NSHOST"));
1508 command_remote += getenv("NSHOST"); // hostname of CORBA name server
1509 command_remote += " ";
1510 ASSERT(getenv("NSPORT"));
1511 command_remote += getenv("NSPORT"); // port of CORBA name server
1512 command_remote += " ";
1514 hostname = machine_name;
1517 std::ostringstream tmp;
1519 std::string proc_number = tmp.str();
1521 std::string command_tmp("");
1522 command_tmp += real_exe_name;
1523 command_tmp += " " + _NS->ContainerName(rtn);
1524 command_tmp += " " + parallelLib;
1525 command_tmp += " " + proxy_hostname;
1526 command_tmp += " " + proc_number;
1527 command_tmp += " -";
1528 AddOmninamesParams(command_tmp);
1530 // On change _Node_ par _Nodex_ pour avoir chaque noeud
1532 std::string command_end_tmp = command_end;
1533 std::string::size_type loc_node = command_end_tmp.find("_Node_");
1534 if (loc_node != std::string::npos)
1535 command_end_tmp.insert(loc_node+5, proc_number);
1536 command += command_begin + command_remote + command_tmp + command_end_tmp;
1537 vect_machine.push_back(hostname);
1540 delete machine_file;
1543 else if (parallelLib == "Mpi")
1545 // Step 0: if remote we have to copy the file
1546 // to the first machine of the file
1547 std::string remote_machine("");
1550 std::ifstream * machine_file = NULL;
1551 machine_file = new std::ifstream(machine_file_name.c_str());
1552 // Get first word of the line
1553 // For MPI implementation the first word is the
1555 std::getline(*machine_file, remote_machine, ' ');
1556 machine_file->close();
1557 MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << remote_machine)
1559 // We want to launch a command like :
1560 // scp mpi_machine_file user@machine:Path
1561 std::string command_remote("");
1562 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1563 if (resInfo.Protocol == rsh)
1564 command_remote = "rcp ";
1566 command_remote = "scp ";
1568 command_remote += machine_file_name;
1569 command_remote += " ";
1570 command_remote += resInfo.UserName;
1571 command_remote += "@";
1572 command_remote += remote_machine;
1573 command_remote += ":";
1574 command_remote += machine_file_name;
1576 int status = system(command_remote.c_str());
1579 INFOS("copy of the mpi machine file failed !");
1586 std::string command_remote("");
1589 // We want to launch a command like :
1590 // ssh user@machine distantPath/runRemote.sh hostNS portNS
1591 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1592 if (resInfo.Protocol == rsh)
1593 command_remote = "rsh ";
1595 command_remote = "ssh ";
1596 command_remote += resInfo.UserName;
1597 command_remote += "@";
1598 command_remote += remote_machine;
1599 command_remote += " ";
1600 command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1601 command_remote += "/runRemote.sh ";
1602 ASSERT(getenv("NSHOST"));
1603 command_remote += getenv("NSHOST"); // hostname of CORBA name server
1604 command_remote += " ";
1605 ASSERT(getenv("NSPORT"));
1606 command_remote += getenv("NSPORT"); // port of CORBA name server
1607 command_remote += " ";
1609 hostname = remote_machine;
1612 // We use Dummy proxy for MPI parallel containers
1613 real_exe_name = exe_name + "Dummy";
1614 command = real_exe_name;
1615 command += " " + _NS->ContainerName(rtn);
1616 command += " Dummy";
1617 command += " " + hostname;
1618 command += " " + nbproc;
1620 AddOmninamesParams(command);
1622 command = command_begin + command_remote + command + command_end;
1623 vect_machine.push_back(hostname);
1627 std::string command_remote("");
1630 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1631 if (resInfo.Protocol == rsh)
1632 command_remote = "rsh ";
1634 command_remote = "ssh ";
1635 command_remote += resInfo.UserName;
1636 command_remote += "@";
1637 command_remote += remote_machine;
1638 command_remote += " ";
1640 std::string new_real_exe_name("");
1641 new_real_exe_name += resInfo.AppliPath; // path relative to user@machine $HOME
1642 new_real_exe_name += "/runRemote.sh ";
1643 ASSERT(getenv("NSHOST"));
1644 new_real_exe_name += getenv("NSHOST"); // hostname of CORBA name server
1645 new_real_exe_name += " ";
1646 ASSERT(getenv("NSPORT"));
1647 new_real_exe_name += getenv("NSPORT"); // port of CORBA name server
1648 new_real_exe_name += " ";
1650 real_exe_name = new_real_exe_name + real_exe_name;
1651 hostname = remote_machine;
1654 const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(hostname);
1655 if (resInfo.mpi == lam)
1657 command = "mpiexec -ssi boot ";
1658 if (resInfo.Protocol == rsh)
1662 command += "-machinefile " + machine_file_name + " ";
1663 command += "-n " + nbproc + " ";
1664 command += real_exe_name;
1665 command += " " + _NS->ContainerName(rtn);
1666 command += " " + parallelLib;
1667 command += " " + proxy_hostname;
1669 AddOmninamesParams(command);
1673 command = "mpirun -np " + nbproc + " ";
1674 command += real_exe_name;
1675 command += " " + _NS->ContainerName(rtn);
1676 command += " " + parallelLib;
1677 command += " " + proxy_hostname;
1679 AddOmninamesParams(command);
1682 command = command_begin + command_remote + command + command_end;
1683 for (int i= 0; i < nb_nodes; i++)
1684 vect_machine.push_back(proxy_hostname);
1689 std::string message("Unknown parallelLib : " + parallelLib);
1690 throw SALOME_Exception(message.c_str());
1693 MESSAGE("Parallel launch is: " << command);
1697 string SALOME_ContainerManager::GetMPIZeroNode(string machine)
1702 string tmpFile = BuildTemporaryFileName();
1704 cmd = "ssh " + machine + " mpirun -np 1 hostname > " + tmpFile;
1706 status = system(cmd.c_str());
1708 ifstream fp(tmpFile.c_str(),ios::in);