Salome HOME
launch ompi-server with salome, and kill it at the end of Salome
[modules/kernel.git] / src / Container / SALOME_ContainerManager.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
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>
28 #include <sys/stat.h>
29 #ifndef WIN32
30 #include <unistd.h>
31 #endif
32 #include <vector>
33 #include "Utils_CorbaException.hxx"
34 #include "Batch_Date.hxx"
35 #include <sstream>
36
37 #ifdef WITH_PACO_PARALLEL
38 #include "PaCOPP.hxx"
39 #endif
40
41 #define TIME_OUT_TO_LAUNCH_CONT 61
42
43 using namespace std;
44
45 vector<Engines::Container_ptr> SALOME_ContainerManager::_batchLaunchedContainers;
46
47 vector<Engines::Container_ptr>::iterator SALOME_ContainerManager::_batchLaunchedContainersIter;
48
49 const char *SALOME_ContainerManager::_ContainerManagerNameInNS = 
50   "/ContainerManager";
51
52 //=============================================================================
53 /*! 
54  *  Constructor
55  *  \param orb
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
58  */
59 //=============================================================================
60
61 SALOME_ContainerManager::SALOME_ContainerManager(CORBA::ORB_ptr orb, PortableServer::POA_var poa, SALOME_ResourcesManager *rm, SALOME_NamingService *ns)
62 {
63   MESSAGE("constructor");
64   _NS = ns;
65   _ResManager = rm;
66
67   PortableServer::POAManager_var pman = poa->the_POAManager();
68   _orb = CORBA::ORB::_duplicate(orb) ;
69   CORBA::PolicyList policies;
70   policies.length(1);
71   PortableServer::ThreadPolicy_var threadPol = 
72     poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
73   policies[0] = PortableServer::ThreadPolicy::_duplicate(threadPol);
74
75   _poa = poa->create_POA("SThreadPOA",pman,policies);
76   threadPol->destroy();
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);
81
82   _NS->Register(refContMan,_ContainerManagerNameInNS);
83   _isAppliSalomeDefined = (getenv("APPLI") != 0);
84
85 #ifdef HAVE_MPI2
86   if( getenv("OMPI_URI_FILE") != NULL ){
87     system("killall ompi-server");
88     string command;
89     command = "ompi-server -r ";
90     command += getenv("OMPI_URI_FILE");
91     int status=system(command.c_str());
92     if(status!=0)
93       throw SALOME_Exception("Error when launching ompi-server");
94   }
95 #endif
96
97   MESSAGE("constructor end");
98 }
99
100 //=============================================================================
101 /*! 
102  * destructor
103  */
104 //=============================================================================
105
106 SALOME_ContainerManager::~SALOME_ContainerManager()
107 {
108   MESSAGE("destructor");
109 #ifdef HAVE_MPI2
110   if( getenv("OMPI_URI_FILE") != NULL )
111     system("killall ompi-server");
112 #endif
113 }
114
115 //=============================================================================
116 //! shutdown all the containers, then the ContainerManager servant
117 /*! CORBA method:
118  */
119 //=============================================================================
120
121 void SALOME_ContainerManager::Shutdown()
122 {
123   MESSAGE("Shutdown");
124   ShutdownContainers();
125   _NS->Destroy_Name(_ContainerManagerNameInNS);
126   PortableServer::ObjectId_var oid = _poa->servant_to_id(this);
127   _poa->deactivate_object(oid);
128 }
129
130 //=============================================================================
131 //! Loop on all the containers listed in naming service, ask shutdown on each
132 /*! CORBA Method:
133  */
134 //=============================================================================
135
136 void SALOME_ContainerManager::ShutdownContainers()
137 {
138   MESSAGE("ShutdownContainers");
139   bool isOK;
140   isOK = _NS->Change_Directory("/Containers");
141   if( isOK ){
142     vector<string> vec = _NS->list_directory_recurs();
143     list<string> lstCont;
144     for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++)
145       {
146         SCRUTE((*iter));
147         CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
148         try
149           {
150             Engines::Container_var cont=Engines::Container::_narrow(obj);
151             if(!CORBA::is_nil(cont))
152               lstCont.push_back((*iter));
153           }
154         catch(const CORBA::Exception& e)
155           {
156             // ignore this entry and continue
157           }
158       }
159     MESSAGE("Container list: ");
160     for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++){
161       SCRUTE((*iter));
162     }
163     for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++)
164     {
165       try
166       {
167         SCRUTE((*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))
171         {
172           MESSAGE("ShutdownContainers: " << (*iter));
173           cont->Shutdown();
174         }
175         else 
176           MESSAGE("ShutdownContainers: no container ref for " << (*iter));
177       }
178       catch(CORBA::SystemException& e)
179       {
180         INFOS("CORBA::SystemException ignored : " << e);
181       }
182       catch(CORBA::Exception&)
183       {
184         INFOS("CORBA::Exception ignored.");
185       }
186       catch(...)
187       {
188         INFOS("Unknown exception ignored.");
189       }
190     }
191   }
192 }
193
194 //=============================================================================
195 //! Give a suitable Container given constraints
196 /*! CORBA Method:
197  *  \param params            Machine Parameters required for the container
198  *  \return the container or nil
199  */
200 //=============================================================================
201
202 Engines::Container_ptr
203 SALOME_ContainerManager::GiveContainer(const Engines::MachineParameters& params)
204 {
205   char *valenv=getenv("SALOME_BATCH");
206   if(valenv)
207     if (strcmp(valenv,"1")==0)
208       {
209         if(_batchLaunchedContainers.empty())
210           fillBatchLaunchedContainers();
211
212         if (_batchLaunchedContainersIter == _batchLaunchedContainers.end())
213           _batchLaunchedContainersIter = _batchLaunchedContainers.begin();
214
215         Engines::Container_ptr rtn = Engines::Container::_duplicate(*_batchLaunchedContainersIter);
216         _batchLaunchedContainersIter++;
217         return rtn;
218       }
219   return StartContainer(params);
220 }
221
222 //=============================================================================
223 //! Start a suitable Container in a list of machines with constraints 
224 /*! C++ Method:
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)
229  */
230 //=============================================================================
231
232 Engines::Container_ptr
233 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params,
234                const Engines::MachineList& possibleComputers,
235                const std::string& container_exe)
236 {
237 #ifdef WITH_PACO_PARALLEL
238   std::string parallelLib(params.parallelLib);
239   if (parallelLib != "")
240   {
241     Engines::MachineParameters myparams(params);
242     myparams.computerList=possibleComputers;
243     return StartParallelContainer(myparams);
244   }
245 #endif
246   string containerNameInNS;
247   Engines::Container_ptr ret = Engines::Container::_nil();
248
249   MESSAGE("SALOME_ContainerManager::StartContainer " << possibleComputers.length());
250
251   vector<string> lm;
252 // if mode is "get" keep only machines with existing containers 
253   if(std::string(params.mode.in())=="get")
254     {
255       for(unsigned int i=0;i<possibleComputers.length();i++)
256         {
257           Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
258           try
259             {
260               if(!cont->_non_existent())
261                 lm.push_back(string(possibleComputers[i]));
262             }
263           catch(CORBA::Exception&)
264             {
265               // CORBA::Exception ignored.
266             }
267         }
268     }
269   else
270     {
271       for(unsigned int i=0;i<possibleComputers.length();i++)
272         lm.push_back(string(possibleComputers[i]));
273     }
274
275   string theMachine;
276   try
277     {
278       theMachine=_ResManager->GetImpl()->Find(params.policy.in(),lm);
279     }
280   catch( const SALOME_Exception &ex )
281     {
282       MESSAGE(ex.what());
283       return Engines::Container::_nil();
284     }
285
286   //If the machine name is localhost use the real name
287   if(theMachine == "localhost")
288     theMachine=Kernel_Utils::GetHostname();
289
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
293   if(params.isMPI)
294     // A parallel container register on zero node in NS
295     containerNameInNS = _NS->BuildContainerNameForNS(params,GetMPIZeroNode(theMachine).c_str());
296   else
297     containerNameInNS = _NS->BuildContainerNameForNS(params,theMachine.c_str());
298
299   SCRUTE(containerNameInNS);
300   CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
301   if ( !CORBA::is_nil(obj) )
302     {
303       try
304         {
305           Engines::Container_var cont=Engines::Container::_narrow(obj);
306           if(!cont->_non_existent())
307             {
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*/
310               else
311                 {
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
314                 }
315             }
316         }
317       catch(CORBA::Exception&)
318         {
319           INFOS("CORBA::Exception ignored.");
320         }
321     }
322
323   //try to launch a new container
324   MESSAGE("try to launch it on " << theMachine);
325
326   string command;
327   if(theMachine==""){
328     MESSAGE("SALOME_ContainerManager::StartContainer : no possible computer");
329     return Engines::Container::_nil();
330   }
331   else if(theMachine==Kernel_Utils::GetHostname())
332     command = BuildCommandToLaunchLocalContainer(params,container_exe);
333   else
334     command = BuildCommandToLaunchRemoteContainer(theMachine,params,container_exe);
335
336   //redirect stdout and stderr in a file
337 #ifdef WNT
338   string logFilename=getenv("TEMP");
339   logFilename += "\\";
340 #else
341   string logFilename="/tmp";
342   char* val = getenv("SALOME_TMP_DIR");
343   if(val)
344     {
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;
350     }
351   logFilename += "/";
352 #endif
353   logFilename += _NS->ContainerName(params)+"_"+ theMachine +"_"+getenv( "USER" )+".log" ;
354   command += " > " + logFilename + " 2>&1";
355 #ifdef WNT
356   command = "%PYTHONBIN% -c \"import win32pm ; win32pm.spawnpid(r'" + command + "', '')\"";
357 #else
358   command += " &";
359 #endif
360
361   // launch container with a system call
362   int status=system(command.c_str());
363
364   if (status == -1){
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();
368   }
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();
373   }
374   else{
375     int count=TIME_OUT_TO_LAUNCH_CONT;
376     MESSAGE("count = "<<count);
377     while ( CORBA::is_nil(ret) && count ){
378 #ifndef WIN32
379       sleep( 1 ) ;
380 #else
381       Sleep(1000);
382 #endif
383       count-- ;
384       if ( count != 10 )
385         MESSAGE( count << ". Waiting for container on " << theMachine);
386
387       CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
388       ret=Engines::Container::_narrow(obj);
389     }
390     
391     if ( CORBA::is_nil(ret) )
392       {
393         MESSAGE("SALOME_ContainerManager::StartContainer rsh failed");
394       }
395     else
396       {
397         logFilename=":"+logFilename;
398         logFilename="@"+Kernel_Utils::GetHostname()+logFilename;
399         logFilename=getenv( "USER" )+logFilename;
400         ret->logfilename(logFilename.c_str());
401       }
402
403     RmTmpFile(_TmpFileName); // command file can be removed here
404     return ret;
405   }
406 }
407
408 //=============================================================================
409 //! Start a suitable Container given constraints 
410 /*! CORBA Method:
411  *  \param params            Machine Parameters required for the container
412  */
413 //=============================================================================
414
415 Engines::Container_ptr
416 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params)
417 {
418   Engines::MachineList_var possibleComputers = _ResManager->GetFittingResources(params);
419
420   // Look into ModulCatalog if a specific container must be launched
421   CORBA::String_var container_exe;
422   int found=0;
423   try
424     {
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++)
431         {
432           const char* compoi = params.componentList[i];
433           SALOME_ModuleCatalog::Acomponent_var compoInfo = Catalog->GetComponent(compoi);
434           if (CORBA::is_nil (compoInfo))
435             {
436               continue;
437             }
438           SALOME_ModuleCatalog::ImplType impl=compoInfo->implementation_type();
439           container_exe=compoInfo->implementation_name();
440           if(impl==SALOME_ModuleCatalog::CEXE)
441             {
442               if(found)
443                 {
444                   INFOS("ContainerManager Error: you can't have 2 CEXE component in the same container" );
445                   return Engines::Container::_nil();
446                 }
447               found=1;
448             }
449         }
450     }
451   catch (ServiceUnreachable&)
452     {
453       INFOS("Caught exception: Naming Service Unreachable");
454       return Engines::Container::_nil();
455     }
456   catch (...)
457     {
458       INFOS("Caught unknown exception.");
459       return Engines::Container::_nil();
460     }
461
462   if(found)
463     return StartContainer(params,possibleComputers,container_exe.in());
464   else
465     return StartContainer(params,possibleComputers);
466 }
467
468 //=============================================================================
469 //!  Find or start a suitable Container given some constraints
470 /*! CORBA Method:
471  *  \param params            Machine Parameters required for the container
472  *  \return the container or nil
473  */
474 //=============================================================================
475
476 Engines::Container_ptr
477 SALOME_ContainerManager::FindOrStartContainer(const Engines::MachineParameters& params)
478 {
479   Engines::Container_ptr ret = FindContainer(params,params.computerList);
480   if(!CORBA::is_nil(ret))
481     return ret;
482   MESSAGE("Container doesn't exist try to launch it ...");
483
484   return StartContainer(params);
485 }
486
487 //=============================================================================
488 //! Find a container given constraints (params) on a list of machines (possibleComputers)
489 /*!
490  *
491  */
492 //=============================================================================
493
494 Engines::Container_ptr
495 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
496                                        const Engines::MachineList& possibleComputers)
497 {
498   MESSAGE("FindContainer "<<possibleComputers.length());
499   for(unsigned int i=0;i<possibleComputers.length();i++)
500     {
501       MESSAGE("FindContainer possible " << possibleComputers[i]);
502       Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
503       if( !CORBA::is_nil(cont) )
504         return cont;
505     }
506   MESSAGE("FindContainer: not found");
507   return Engines::Container::_nil();
508 }
509
510 //=============================================================================
511 //! Find a container given constraints (params) on a machine (theMachine)
512 /*!
513  *
514  */
515 //=============================================================================
516
517 Engines::Container_ptr
518 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
519                                        const char *theMachine)
520 {
521   string containerNameInNS(_NS->BuildContainerNameForNS(params,theMachine));
522   CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
523   try
524     {
525       if(obj->_non_existent())
526         return Engines::Container::_nil();
527       else
528         return Engines::Container::_narrow(obj);
529     }
530   catch(const CORBA::Exception& e)
531     {
532       return Engines::Container::_nil();
533     }
534 }
535
536 #ifdef WITH_PACO_PARALLEL
537 //=============================================================================
538 /*! CORBA Method:
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.
542  */
543 //=============================================================================
544 Engines::Container_ptr
545 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params_const)
546 {
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);
551
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");
560
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();
566
567     if(theMachine == "") {
568       INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
569       INFOS("[StartParallelContainer] No possible computer found");
570       INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
571       return ret;
572     }
573     INFOS("[StartParallelContainer] on machine : " << theMachine);
574     params.hostname = CORBA::string_dup(theMachine.c_str());
575
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;
580     try 
581     {
582       command_proxy = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerProxy", params_proxy, proxy_machine);
583     }
584     catch(const SALOME_Exception & ex)
585     {
586       INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
587       INFOS(ex.what());
588       return ret;
589     }
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))
593     {
594       INFOS("[StartParallelContainer] LaunchParallelContainer for proxy returns NIL !");
595       return ret;
596     }
597     try 
598     {
599       container_proxy = PaCO::InterfaceManager::_narrow(obj);
600     }
601     catch(CORBA::SystemException& e)
602     {
603       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
604       INFOS("CORBA::SystemException : " << e);
605       return ret;
606     }
607     catch(CORBA::Exception& e)
608     {
609       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
610       INFOS("CORBA::Exception" << e);
611       return ret;
612     }
613     catch(...)
614     {
615       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
616       INFOS("Unknown exception !");
617       return ret;
618     }
619     if (CORBA::is_nil(container_proxy))
620     {
621       INFOS("[StartParallelContainer] PaCO::InterfaceManager::_narrow returns NIL !");
622       return ret;
623     }
624
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;
629     try 
630     {
631       command_nodes = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerNode", params_nodes, nodes_machines, proxy_machine[0]);
632     }
633     catch(const SALOME_Exception & ex)
634     {
635       INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
636       INFOS(ex.what());
637       return ret;
638     }
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))
642     {
643       INFOS("[StartParallelContainer] LaunchParallelContainer for nodes returns NIL !");
644       // Il faut tuer le proxy
645       try 
646       {
647         Engines::Container_var proxy = Engines::Container::_narrow(container_proxy);
648         proxy->Shutdown();
649       }
650       catch (...)
651       {
652         INFOS("[StartParallelContainer] Exception catched from proxy Shutdown...");
653       }
654       return ret;
655     }
656
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++) 
659     {
660       std::ostringstream tmp;
661       tmp << i;
662       std::string proc_number = tmp.str();
663       std::string container_node_name = container_generic_node_name + proc_number;
664
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)) 
669       {
670         INFOS("[StartParallelContainer] CONNECTION FAILED From Naming Service !");
671         INFOS("[StartParallelContainer] Container name is " << containerNameInNS);
672         return ret;
673       }
674       try
675       {
676         MESSAGE("[StartParallelContainer] Deploying node : " << container_node_name);
677         PaCO::InterfaceParallel_var node = PaCO::InterfaceParallel::_narrow(obj);
678         node->deploy();
679         MESSAGE("[StartParallelContainer] node " << container_node_name << " is deployed");
680       }
681       catch(CORBA::SystemException& e)
682       {
683         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
684         INFOS("CORBA::SystemException : " << e);
685         return ret;
686       }
687       catch(CORBA::Exception& e)
688       {
689         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
690         INFOS("CORBA::Exception" << e);
691         return ret;
692       }
693       catch(...)
694       {
695         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
696         INFOS("Unknown exception !");
697         return ret;
698       }
699     }
700
701     // Step 7 : starting parallel container
702     try 
703     {
704       MESSAGE ("[StartParallelContainer] Starting parallel object");
705       container_proxy->start();
706       MESSAGE ("[StartParallelContainer] Parallel object is started");
707       ret = Engines::Container::_narrow(container_proxy);
708     }
709     catch(CORBA::SystemException& e)
710     {
711       INFOS("Caught CORBA::SystemException. : " << e);
712     }
713     catch(PortableServer::POA::ServantAlreadyActive&)
714     {
715       INFOS("Caught CORBA::ServantAlreadyActiveException");
716     }
717     catch(CORBA::Exception&)
718     {
719       INFOS("Caught CORBA::Exception.");
720     }
721     catch(std::exception& exc)
722     {
723       INFOS("Caught std::exception - "<<exc.what()); 
724     }
725     catch(...)
726     {
727       INFOS("Caught unknown exception.");
728     }
729   }
730   return ret;
731 }
732 #else
733 //=============================================================================
734 /*! CORBA Method:
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.
738  */
739 //=============================================================================
740 Engines::Container_ptr
741 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params)
742 {
743   Engines::Container_ptr ret = Engines::Container::_nil();
744   INFOS("[StartParallelContainer] is disabled !");
745   INFOS("[StartParallelContainer] recompile SALOME Kernel to enable parallel extension");
746   return ret;
747 }
748 #endif
749
750 //=============================================================================
751 /*! This method launches the parallel container.
752  *  It will may be placed on the ressources manager.
753  *
754  * \param command to launch
755  * \param container's parameters
756  * \param name of the container
757  *
758  * \return CORBA container reference
759  */
760 //=============================================================================
761 CORBA::Object_ptr 
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)
766 {
767   CORBA::Object_ptr obj = CORBA::Object::_nil();
768   std::string containerNameInNS;
769   int count = TIME_OUT_TO_LAUNCH_CONT;
770
771   INFOS("[LaunchParallelContainer] Begin");
772   int status = system(command.c_str());
773   if (status == -1) {
774     INFOS("[LaunchParallelContainer] failed : system command status -1");
775     return obj;
776   }
777   else if (status == 217) {
778     INFOS("[LaunchParallelContainer] failed : system command status 217");
779     return obj;
780   }
781
782   if (params.nb_component_nodes == 0) 
783   {
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) 
789     {
790 #ifndef WIN32
791       sleep(1) ;
792 #else
793       Sleep(1000);
794 #endif
795       count-- ;
796       obj = _NS->Resolve(containerNameInNS.c_str());
797     }
798   }
799   else 
800   {
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++) 
804     {
805       obj = CORBA::Object::_nil();
806       std::string theMachine(vect_machine[i]);
807       // Name of the node
808       std::ostringstream tmp;
809       tmp << i;
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) {
815 #ifndef WIN32
816         sleep(1) ;
817 #else
818         Sleep(1000);
819 #endif
820         count-- ;
821         obj = _NS->Resolve(containerNameInNS.c_str());
822       }
823       if (CORBA::is_nil(obj))
824       {
825         INFOS("[LaunchParallelContainer] Launch of node failed (or not found) !");
826         return obj;
827       }
828     }
829   }
830   if (CORBA::is_nil(obj)) 
831     INFOS("[LaunchParallelContainer] failed");
832   
833   return obj;
834 }
835
836 void SALOME_ContainerManager::fillBatchLaunchedContainers()
837 {
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);
846     }
847   }
848   _batchLaunchedContainersIter=_batchLaunchedContainers.begin();
849 }
850
851 //=============================================================================
852 /*!
853  *  This is no longer valid (C++ container are also python containers)
854  */ 
855 //=============================================================================
856
857 bool isPythonContainer(const char* ContainerName)
858 {
859   bool ret = false;
860   int len = strlen(ContainerName);
861
862   if (len >= 2)
863     if (strcmp(ContainerName + len - 2, "Py") == 0)
864       ret = true;
865
866   return ret;
867 }
868
869 //=============================================================================
870 /*!
871  *  Builds the script to be launched
872  *
873  *  If SALOME Application not defined ($APPLI),
874  *  see BuildTempFileToLaunchRemoteContainer()
875  *
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 &"
879
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
889  */ 
890 //=============================================================================
891
892 string
893 SALOME_ContainerManager::BuildCommandToLaunchRemoteContainer
894 (const string& machine,
895  const Engines::MachineParameters& params, const std::string& container_exe)
896 {
897   string command;
898   int nbproc;
899           
900   if ( ! _isAppliSalomeDefined )
901     command = BuildTempFileToLaunchRemoteContainer(machine, params);
902
903   else
904     {
905       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine);
906
907       if (params.isMPI)
908         {
909           if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
910             nbproc = 1;
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;
915           else
916             nbproc = params.nb_node * params.nb_proc_per_node;
917         }
918
919       // "ssh user@machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \
920         //  SALOME_Container containerName &"
921
922       if (resInfo.Protocol == rsh)
923         command = "rsh ";
924       else if (resInfo.Protocol == ssh)
925         command = "ssh ";
926       else
927         throw SALOME_Exception("Unknown protocol");
928
929       if (resInfo.UserName != "")
930         {
931           command += resInfo.UserName;
932           command += "@";
933         }
934
935       command += machine;
936       command += " ";
937
938       if (resInfo.AppliPath != "")
939         command += resInfo.AppliPath; // path relative to user@machine $HOME
940       else
941         {
942           ASSERT(getenv("APPLI"));
943           command += getenv("APPLI"); // path relative to user@machine $HOME
944         }
945
946       command += "/runRemote.sh ";
947
948       ASSERT(getenv("NSHOST")); 
949       command += getenv("NSHOST"); // hostname of CORBA name server
950
951       command += " ";
952       ASSERT(getenv("NSPORT"));
953       command += getenv("NSPORT"); // port of CORBA name server
954
955       std::string wdir=params.workingdir.in();
956       if(wdir != "")
957         {
958           command += " WORKINGDIR ";
959           command += " '";
960           if(wdir == "$TEMPDIR")
961             wdir="\\$TEMPDIR";
962           command += wdir; // requested working directory
963           command += "'"; 
964         }
965
966       if(params.isMPI)
967         {
968           command += " mpirun -np ";
969           std::ostringstream o;
970           o << nbproc << " ";
971           command += o.str();
972 #ifdef WITHLAM
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";
977           else{
978             command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
979             command += getenv("OMPI_URI_FILE");
980           }
981 #endif  
982           command += " SALOME_MPIContainer ";
983         }
984       else
985         command += " " +container_exe+ " ";
986
987       command += _NS->ContainerName(params);
988       command += " -";
989       AddOmninamesParams(command);
990
991       MESSAGE("command =" << command);
992     }
993
994   return command;
995 }
996
997 //=============================================================================
998 /*!
999  *  builds the command to be launched.
1000  */ 
1001 //=============================================================================
1002
1003 string
1004 SALOME_ContainerManager::BuildCommandToLaunchLocalContainer
1005 (const Engines::MachineParameters& params, const std::string& container_exe)
1006 {
1007   _TmpFileName = BuildTemporaryFileName();
1008   string command;
1009   int nbproc = 0;
1010
1011   ofstream command_file( _TmpFileName.c_str() );
1012
1013   if (params.isMPI)
1014     {
1015       //command = "mpirun -np ";
1016       command_file << "mpirun -np ";
1017
1018       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
1019         nbproc = 1;
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;
1024       else
1025         nbproc = params.nb_node * params.nb_proc_per_node;
1026
1027       //std::ostringstream o;
1028
1029       //o << nbproc << " ";
1030       command_file << nbproc << " ";
1031
1032       //command += o.str();
1033 #ifdef WITHLAM
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";
1040       else
1041         {
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");
1044         }
1045 #endif
1046
1047       if (isPythonContainer(params.container_name))
1048         //command += "pyMPI SALOME_ContainerPy.py ";
1049         command_file << " pyMPI SALOME_ContainerPy.py ";
1050       else
1051         //command += "SALOME_MPIContainer ";
1052         command_file << " SALOME_MPIContainer ";
1053     }
1054
1055   else
1056     {
1057       //command="";
1058       std::string wdir=params.workingdir.in();
1059       if(wdir != "")
1060         {
1061           // a working directory is requested
1062           if(wdir == "$TEMPDIR")
1063             {
1064               // a new temporary directory is requested
1065               string dir = Kernel_Utils::GetTmpDir();
1066 #ifdef WIN32
1067               //command += "cd /d "+ dir +";";
1068               command_file << "cd /d " << dir << endl;
1069 #else
1070               //command = "cd "+ dir +";";
1071               command_file << "cd " << dir << ";";
1072 #endif
1073
1074             }
1075           else
1076             {
1077               // a permanent directory is requested use it or create it
1078 #ifdef WIN32
1079               //command="mkdir " + wdir;
1080               command_file << "mkdir " + wdir << endl;
1081               command_file << "cd /D " + wdir << endl;
1082 #else
1083               //command="mkdir -p " + wdir + " && cd " + wdir + ";";
1084               command_file << "mkdir -p " << wdir << " && cd " << wdir + ";";
1085 #endif
1086             }
1087         }
1088       if (isPythonContainer(params.container_name))
1089         //command += "SALOME_ContainerPy.py ";
1090         command_file << "SALOME_ContainerPy.py ";
1091       else
1092         //command += container_exe + " ";
1093         command_file << container_exe + " ";
1094
1095     }
1096
1097   command_file << _NS->ContainerName(params);
1098   command_file << " -";
1099   AddOmninamesParams(command_file);
1100   command_file.close();
1101
1102 #ifndef WIN32
1103   chmod(_TmpFileName.c_str(), 0x1ED);
1104 #endif
1105   command = _TmpFileName;
1106
1107   MESSAGE("Command is file ... " << command);
1108   return command;
1109 }
1110
1111
1112 //=============================================================================
1113 /*!
1114  *  removes the generated temporary file in case of a remote launch.
1115  */ 
1116 //=============================================================================
1117
1118 void SALOME_ContainerManager::RmTmpFile(std::string& tmpFileName)
1119 {
1120   int lenght = tmpFileName.size();
1121   if ( lenght  > 0)
1122     {
1123 #ifdef WIN32
1124       string command = "del /F ";
1125 #else
1126       string command = "rm ";      
1127 #endif
1128       if ( lenght > 4 )
1129         command += tmpFileName.substr(0, lenght - 3 );
1130       else
1131         command += tmpFileName;
1132       command += '*';
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 ) )
1137         {
1138 #ifdef WIN32
1139           command = "del /F " + tmp_dir;
1140 #else
1141           command = "rmdir " + tmp_dir;
1142 #endif
1143           system(command.c_str());
1144         }
1145     }
1146 }
1147
1148 //=============================================================================
1149 /*!
1150  *   add to command all options relative to naming service.
1151  */ 
1152 //=============================================================================
1153
1154 void SALOME_ContainerManager::AddOmninamesParams(string& command) const
1155 {
1156   CORBA::String_var iorstr = _NS->getIORaddr();
1157   command += "ORBInitRef NameService=";
1158   command += iorstr;
1159 }
1160
1161
1162 //=============================================================================
1163 /*!
1164  *  add to command all options relative to naming service.
1165  */ 
1166 //=============================================================================
1167
1168 void SALOME_ContainerManager::AddOmninamesParams(ofstream& fileStream) const
1169 {
1170   CORBA::String_var iorstr = _NS->getIORaddr();
1171   fileStream << "ORBInitRef NameService=";
1172   fileStream << iorstr;
1173 }
1174
1175 //=============================================================================
1176 /*!
1177  *  generate a file name in /tmp directory
1178  */ 
1179 //=============================================================================
1180
1181 string SALOME_ContainerManager::BuildTemporaryFileName() const
1182 {
1183   //build more complex file name to support multiple salome session
1184   string aFileName = Kernel_Utils::GetTmpFileName();
1185 #ifndef WIN32
1186   aFileName += ".sh";
1187 #else
1188   aFileName += ".bat";
1189 #endif
1190   return aFileName;
1191 }
1192
1193
1194 //=============================================================================
1195 /*!
1196  *  Builds in a temporary file the script to be launched.
1197  *  
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.
1201  */ 
1202 //=============================================================================
1203
1204 string
1205 SALOME_ContainerManager::BuildTempFileToLaunchRemoteContainer
1206 (const string& machine,
1207  const Engines::MachineParameters& params) throw(SALOME_Exception)
1208 {
1209   int status;
1210
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;
1216
1217   // --- set env vars
1218
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;
1221
1222   // ! env vars
1223
1224   if (params.isMPI)
1225     {
1226       tempOutputFile << "mpirun -np ";
1227       int nbproc;
1228
1229       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
1230         nbproc = 1;
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;
1235       else
1236         nbproc = params.nb_node * params.nb_proc_per_node;
1237
1238       std::ostringstream o;
1239
1240       tempOutputFile << nbproc << " ";
1241 #ifdef WITHLAM
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";
1246       else{
1247         tempOutputFile << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
1248         tempOutputFile << getenv("OMPI_URI_FILE");
1249       }
1250 #endif
1251     }
1252
1253   tempOutputFile << getenv("KERNEL_ROOT_DIR") << "/bin/salome/";
1254
1255   if (params.isMPI)
1256     {
1257       if (isPythonContainer(params.container_name))
1258         tempOutputFile << " pyMPI SALOME_ContainerPy.py ";
1259       else
1260         tempOutputFile << " SALOME_MPIContainer ";
1261     }
1262
1263   else
1264     {
1265       if (isPythonContainer(params.container_name))
1266         tempOutputFile << "SALOME_ContainerPy.py ";
1267       else
1268         tempOutputFile << "SALOME_Container ";
1269     }
1270
1271   tempOutputFile << _NS->ContainerName(params) << " -";
1272   AddOmninamesParams(tempOutputFile);
1273   tempOutputFile << " &" << endl;
1274   tempOutputFile.flush();
1275   tempOutputFile.close();
1276 #ifndef WIN32
1277   chmod(_TmpFileName.c_str(), 0x1ED);
1278 #endif
1279
1280   // --- Build command
1281
1282   string command;
1283
1284   if (resInfo.Protocol == rsh)
1285     {
1286       command = "rsh ";
1287       string commandRcp = "rcp ";
1288       commandRcp += _TmpFileName;
1289       commandRcp += " ";
1290       commandRcp += machine;
1291       commandRcp += ":";
1292       commandRcp += _TmpFileName;
1293       status = system(commandRcp.c_str());
1294     }
1295
1296   else if (resInfo.Protocol == ssh)
1297     {
1298       command = "ssh ";
1299       string commandRcp = "scp ";
1300       commandRcp += _TmpFileName;
1301       commandRcp += " ";
1302       commandRcp += machine;
1303       commandRcp += ":";
1304       commandRcp += _TmpFileName;
1305       status = system(commandRcp.c_str());
1306     }
1307   else
1308     throw SALOME_Exception("Unknown protocol");
1309
1310   if(status)
1311     throw SALOME_Exception("Error of connection on remote host");    
1312
1313   command += machine;
1314   _CommandForRemAccess = command;
1315   command += " ";
1316   command += _TmpFileName;
1317
1318   SCRUTE(command);
1319
1320   return command;
1321
1322 }
1323
1324 //=============================================================================
1325 /*! Creates a command line that the container manager uses to launch
1326  * a parallel container.
1327  */ 
1328 //=============================================================================
1329 string 
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)
1334 {
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 
1337   // a node.
1338   
1339   //command = "gdb --args ";
1340   //command = "valgrind --tool=memcheck --log-file=val_log ";
1341   //command += real_exe_name;
1342
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));
1350
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();
1355
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;
1365
1366   // Step 1 : local or remote launch ?
1367   if (hostname != std::string(Kernel_Utils::GetHostname()) )
1368   {
1369     MESSAGE("[BuildCommandToLaunchParallelContainer] remote machine case detected !");
1370     remote = true;
1371   }
1372
1373   // Step 2 : proxy or nodes launch ?
1374   std::string::size_type loc_proxy = exe_name.find("Proxy");
1375   if( loc_proxy != string::npos ) {
1376     is_a_proxy = true;
1377   } 
1378
1379   // Step 3 : Depending of the parallelLib, getting the machine file
1380   // ParallelLib Dummy has is own machine for this method
1381   if (remote)
1382   {
1383     if (is_a_proxy)
1384     {
1385       machine_file_name = _ResManager->getMachineFile(hostname,
1386                                                       1,
1387                                                       parallelLib);
1388     }
1389     else
1390     {
1391       machine_file_name = _ResManager->getMachineFile(hostname, 
1392                                                       params.nb_component_nodes,
1393                                                       parallelLib);
1394     }
1395     if (machine_file_name == "")
1396     {
1397       INFOS("[BuildCommandToLaunchParallelContainer] Error machine_file was not generated for machine " << hostname);
1398       throw SALOME_Exception("Error machine_file was not generated");
1399     }
1400     MESSAGE("[BuildCommandToLaunchParallelContainer] machine_file_name is : " << machine_file_name);
1401   }
1402
1403   // Step 4 : Log type choosen by the user
1404   std::string log_env("");
1405   char * get_val = getenv("PARALLEL_LOG");
1406   if (get_val)
1407     log_env = get_val;
1408   std::string command_begin("");
1409   std::string command_end("");
1410   if(log_env == "xterm")
1411   {
1412     command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1413     command_end   = "\"&";
1414   }
1415   else if(log_env == "xterm_debug")
1416   {
1417     command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1418     command_end   = "; cat \" &";
1419   }
1420   else
1421   {
1422     // default into a file...
1423     std::string logFilename = "/tmp/" + _NS->ContainerName(params) + "_" + hostname;
1424     if (is_a_proxy)
1425       logFilename += "_Proxy_";
1426     else
1427       logFilename += "_Node_";
1428     logFilename += std::string(getenv("USER")) + ".log";
1429     command_end = " > " + logFilename + " 2>&1 & ";
1430   }
1431
1432   // Step 5 : Building the command
1433   std::string command("");
1434   if (parallelLib == "Dummy")
1435   {
1436     if (is_a_proxy)
1437     {
1438       std::string command_remote("");
1439       if (remote)
1440       {
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)
1445
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 ";
1451         else 
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 += " ";
1465
1466         hostname = machine_name;
1467       }
1468
1469       command =  real_exe_name;
1470       command += " " + _NS->ContainerName(rtn);
1471       command += " " + parallelLib;
1472       command += " " + hostname;
1473       command += " " + nbproc;
1474       command += " -";
1475       AddOmninamesParams(command);
1476
1477       command = command_begin + command_remote + command + command_end;
1478       vect_machine.push_back(hostname);
1479     }
1480     else
1481     {
1482       std::ifstream * machine_file = NULL;
1483       if (remote)
1484         machine_file = new std::ifstream(machine_file_name.c_str());
1485       for (int i= 0; i < nb_nodes; i++)
1486       {
1487         std::string command_remote("");
1488         if (remote)
1489         {
1490           std::string machine_name;
1491           std::getline(*machine_file, machine_name);
1492           MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << machine_name)
1493
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 ";
1499           else 
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 += " ";
1513
1514           hostname = machine_name;
1515         }
1516
1517         std::ostringstream tmp;
1518         tmp << i;
1519         std::string proc_number = tmp.str();
1520
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);
1529
1530         // On change _Node_ par _Nodex_ pour avoir chaque noeud
1531         // sur un fichier
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);
1538       }
1539       if (machine_file)
1540         delete machine_file;
1541     }
1542   }
1543   else if (parallelLib == "Mpi")
1544   {
1545     // Step 0: if remote we have to copy the file
1546     // to the first machine of the file
1547     std::string remote_machine("");
1548     if (remote)
1549     {
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 
1554       // machine name
1555       std::getline(*machine_file, remote_machine, ' ');
1556       machine_file->close();
1557       MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << remote_machine)
1558
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 ";
1565       else 
1566         command_remote = "scp ";
1567
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;
1575
1576       int status = system(command_remote.c_str());
1577       if (status == -1)
1578       {
1579         INFOS("copy of the mpi machine file failed !");
1580         return "";
1581       }
1582     }
1583
1584     if (is_a_proxy)
1585     {
1586       std::string command_remote("");
1587       if (remote)
1588       {
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 ";
1594         else 
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 += " ";
1608
1609         hostname = remote_machine;
1610       }
1611
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;
1619       command += " -";
1620       AddOmninamesParams(command);
1621
1622       command = command_begin + command_remote + command + command_end;
1623       vect_machine.push_back(hostname);
1624     }
1625     else                                          
1626     {
1627       std::string command_remote("");
1628       if (remote)
1629       {
1630         const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1631         if (resInfo.Protocol == rsh)
1632           command_remote = "rsh ";
1633         else 
1634           command_remote = "ssh ";
1635         command_remote += resInfo.UserName;
1636         command_remote += "@";
1637         command_remote += remote_machine;
1638         command_remote += " ";
1639
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 += " ";
1649
1650         real_exe_name = new_real_exe_name + real_exe_name;
1651         hostname = remote_machine;
1652       }
1653
1654       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(hostname);
1655       if (resInfo.mpi == lam)
1656       {
1657         command = "mpiexec -ssi boot ";
1658         if (resInfo.Protocol == rsh)
1659           command += "rsh ";
1660         else 
1661           command += "ssh ";
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;
1668         command += " -";
1669         AddOmninamesParams(command);
1670       }
1671       else
1672       {
1673         command = "mpirun -np " + nbproc + " ";
1674         command += real_exe_name;
1675         command += " " + _NS->ContainerName(rtn);
1676         command += " " + parallelLib;
1677         command += " " + proxy_hostname;
1678         command += " -";
1679         AddOmninamesParams(command);
1680       }
1681
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);
1685     }
1686   }
1687   else
1688   {
1689     std::string message("Unknown parallelLib : " + parallelLib);
1690     throw SALOME_Exception(message.c_str());
1691   }
1692
1693   MESSAGE("Parallel launch is: " << command);
1694   return command;
1695 }
1696
1697 string SALOME_ContainerManager::GetMPIZeroNode(string machine)
1698 {
1699   int status;
1700   string zeronode;
1701   string cmd;
1702   string tmpFile = BuildTemporaryFileName();
1703
1704   cmd = "ssh " + machine + " mpirun -np 1 hostname > " + tmpFile;
1705
1706   status = system(cmd.c_str());
1707   if( status == 0 ){
1708     ifstream fp(tmpFile.c_str(),ios::in);
1709     fp >> zeronode;
1710   }
1711
1712   RmTmpFile(tmpFile);
1713
1714   return zeronode;
1715 }