]> SALOME platform Git repositories - modules/kernel.git/blob - src/Container/SALOME_ContainerManager.cxx
Salome HOME
debug MPI Containers
[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   MESSAGE("constructor end");
85 }
86
87 //=============================================================================
88 /*! 
89  * destructor
90  */
91 //=============================================================================
92
93 SALOME_ContainerManager::~SALOME_ContainerManager()
94 {
95   MESSAGE("destructor");
96 }
97
98 //=============================================================================
99 //! shutdown all the containers, then the ContainerManager servant
100 /*! CORBA method:
101  */
102 //=============================================================================
103
104 void SALOME_ContainerManager::Shutdown()
105 {
106   MESSAGE("Shutdown");
107   ShutdownContainers();
108   _NS->Destroy_Name(_ContainerManagerNameInNS);
109   PortableServer::ObjectId_var oid = _poa->servant_to_id(this);
110   _poa->deactivate_object(oid);
111 }
112
113 //=============================================================================
114 //! Loop on all the containers listed in naming service, ask shutdown on each
115 /*! CORBA Method:
116  */
117 //=============================================================================
118
119 void SALOME_ContainerManager::ShutdownContainers()
120 {
121   MESSAGE("ShutdownContainers");
122   bool isOK;
123   isOK = _NS->Change_Directory("/Containers");
124   if( isOK ){
125     vector<string> vec = _NS->list_directory_recurs();
126     list<string> lstCont;
127     for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++)
128       {
129         SCRUTE((*iter));
130         CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
131         try
132           {
133             Engines::Container_var cont=Engines::Container::_narrow(obj);
134             if(!CORBA::is_nil(cont))
135               lstCont.push_back((*iter));
136           }
137         catch(const CORBA::Exception& e)
138           {
139             // ignore this entry and continue
140           }
141       }
142     MESSAGE("Container list: ");
143     for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++){
144       SCRUTE((*iter));
145     }
146     for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++)
147     {
148       try
149       {
150         SCRUTE((*iter));
151         CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
152         Engines::Container_var cont=Engines::Container::_narrow(obj);
153         if(!CORBA::is_nil(cont))
154         {
155           MESSAGE("ShutdownContainers: " << (*iter));
156           cont->Shutdown();
157         }
158         else 
159           MESSAGE("ShutdownContainers: no container ref for " << (*iter));
160       }
161       catch(CORBA::SystemException& e)
162       {
163         INFOS("CORBA::SystemException ignored : " << e);
164       }
165       catch(CORBA::Exception&)
166       {
167         INFOS("CORBA::Exception ignored.");
168       }
169       catch(...)
170       {
171         INFOS("Unknown exception ignored.");
172       }
173     }
174   }
175 }
176
177 //=============================================================================
178 //! Give a suitable Container given constraints
179 /*! CORBA Method:
180  *  \param params            Machine Parameters required for the container
181  *  \return the container or nil
182  */
183 //=============================================================================
184
185 Engines::Container_ptr
186 SALOME_ContainerManager::GiveContainer(const Engines::MachineParameters& params)
187 {
188   char *valenv=getenv("SALOME_BATCH");
189   if(valenv)
190     if (strcmp(valenv,"1")==0)
191       {
192         if(_batchLaunchedContainers.empty())
193           fillBatchLaunchedContainers();
194
195         if (_batchLaunchedContainersIter == _batchLaunchedContainers.end())
196           _batchLaunchedContainersIter = _batchLaunchedContainers.begin();
197
198         Engines::Container_ptr rtn = Engines::Container::_duplicate(*_batchLaunchedContainersIter);
199         _batchLaunchedContainersIter++;
200         return rtn;
201       }
202   return StartContainer(params);
203 }
204
205 //=============================================================================
206 //! Start a suitable Container in a list of machines with constraints 
207 /*! C++ Method:
208  * Constraints are given by a machine parameters struct
209  *  \param params            Machine Parameters required for the container
210  *  \param possibleComputers list of machines usable for start
211  *  \param container_exe specific container executable (default=SALOME_Container)
212  */
213 //=============================================================================
214
215 Engines::Container_ptr
216 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params,
217                const Engines::MachineList& possibleComputers,
218                const std::string& container_exe)
219 {
220 #ifdef WITH_PACO_PARALLEL
221   std::string parallelLib(params.parallelLib);
222   if (parallelLib != "")
223   {
224     Engines::MachineParameters myparams(params);
225     myparams.computerList=possibleComputers;
226     return StartParallelContainer(myparams);
227   }
228 #endif
229   string containerNameInNS;
230   Engines::Container_ptr ret = Engines::Container::_nil();
231
232   MESSAGE("SALOME_ContainerManager::StartContainer " << possibleComputers.length());
233
234   vector<string> lm;
235 // if mode is "get" keep only machines with existing containers 
236   if(std::string(params.mode.in())=="get")
237     {
238       for(unsigned int i=0;i<possibleComputers.length();i++)
239         {
240           Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
241           try
242             {
243               if(!cont->_non_existent())
244                 lm.push_back(string(possibleComputers[i]));
245             }
246           catch(CORBA::Exception&)
247             {
248               // CORBA::Exception ignored.
249             }
250         }
251     }
252   else
253     {
254       for(unsigned int i=0;i<possibleComputers.length();i++)
255         lm.push_back(string(possibleComputers[i]));
256     }
257
258   string theMachine;
259   try
260     {
261       theMachine=_ResManager->GetImpl()->Find(params.policy.in(),lm);
262     }
263   catch( const SALOME_Exception &ex )
264     {
265       MESSAGE(ex.what());
266       return Engines::Container::_nil();
267     }
268
269   //If the machine name is localhost use the real name
270   if(theMachine == "localhost")
271     theMachine=Kernel_Utils::GetHostname();
272
273   //check if an entry exists in Naming service
274   //if params.mode == "start" or "" shutdown the existing container before launching a new one with that name
275   //if params.mode == "getorstart" or "get" use the existing container
276   if(params.isMPI)
277     // A parallel container register on zero node in NS
278     containerNameInNS = _NS->BuildContainerNameForNS(params,GetMPIZeroNode(theMachine).c_str());
279   else
280     containerNameInNS = _NS->BuildContainerNameForNS(params,theMachine.c_str());
281
282   SCRUTE(containerNameInNS);
283   CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
284   if ( !CORBA::is_nil(obj) )
285     {
286       try
287         {
288           Engines::Container_var cont=Engines::Container::_narrow(obj);
289           if(!cont->_non_existent())
290             {
291               if(std::string(params.mode.in())=="getorstart"||std::string(params.mode.in())=="get")
292                 return cont._retn(); /* the container exists and params.mode is getorstart or get use it*/
293               else
294                 {
295                   INFOS("A container is already registered with the name: " << containerNameInNS << ", shutdown the existing container");
296                   cont->Shutdown(); // shutdown the registered container if it exists
297                 }
298             }
299         }
300       catch(CORBA::Exception&)
301         {
302           INFOS("CORBA::Exception ignored.");
303         }
304     }
305
306   //try to launch a new container
307   MESSAGE("try to launch it on " << theMachine);
308
309   string command;
310   if(theMachine==""){
311     MESSAGE("SALOME_ContainerManager::StartContainer : no possible computer");
312     return Engines::Container::_nil();
313   }
314   else if(theMachine==Kernel_Utils::GetHostname())
315     command = BuildCommandToLaunchLocalContainer(params,container_exe);
316   else
317     command = BuildCommandToLaunchRemoteContainer(theMachine,params,container_exe);
318
319   //redirect stdout and stderr in a file
320   string logFilename="/tmp/"+_NS->ContainerName(params)+"_"+ theMachine +"_"+getenv( "USER" )+".log" ;
321   command += " > " + logFilename + " 2>&1 &";
322
323   // launch container with a system call
324   int status=system(command.c_str());
325
326   if (status == -1){
327     MESSAGE("SALOME_ContainerManager::StartContainer rsh failed (system command status -1)");
328     RmTmpFile(_TmpFileName); // command file can be removed here
329     return Engines::Container::_nil();
330   }
331   else if (status == 217){
332     MESSAGE("SALOME_ContainerManager::StartContainer rsh failed (system command status 217)");
333     RmTmpFile(_TmpFileName); // command file can be removed here
334     return Engines::Container::_nil();
335   }
336   else{
337     int count=TIME_OUT_TO_LAUNCH_CONT;
338     MESSAGE("count = "<<count);
339     while ( CORBA::is_nil(ret) && count ){
340 #ifndef WIN32
341       sleep( 1 ) ;
342 #else
343       Sleep(1000);
344 #endif
345       count-- ;
346       if ( count != 10 )
347         MESSAGE( count << ". Waiting for container on " << theMachine);
348
349       CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
350       ret=Engines::Container::_narrow(obj);
351     }
352     
353     if ( CORBA::is_nil(ret) )
354       {
355         MESSAGE("SALOME_ContainerManager::StartContainer rsh failed");
356       }
357     else
358       {
359         logFilename=":"+logFilename;
360         logFilename="@"+Kernel_Utils::GetHostname()+logFilename;
361         logFilename=getenv( "USER" )+logFilename;
362         ret->logfilename(logFilename.c_str());
363       }
364
365     RmTmpFile(_TmpFileName); // command file can be removed here
366     return ret;
367   }
368 }
369
370 //=============================================================================
371 //! Start a suitable Container given constraints 
372 /*! CORBA Method:
373  *  \param params            Machine Parameters required for the container
374  */
375 //=============================================================================
376
377 Engines::Container_ptr
378 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params)
379 {
380   Engines::MachineList_var possibleComputers = _ResManager->GetFittingResources(params);
381
382   // Look into ModulCatalog if a specific container must be launched
383   CORBA::String_var container_exe;
384   int found=0;
385   try
386     {
387       CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
388       SALOME_ModuleCatalog::ModuleCatalog_var Catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
389       if (CORBA::is_nil (Catalog))
390         return Engines::Container::_nil();
391       // Loop through component list
392       for(unsigned int i=0;i<params.componentList.length();i++)
393         {
394           const char* compoi = params.componentList[i];
395           SALOME_ModuleCatalog::Acomponent_var compoInfo = Catalog->GetComponent(compoi);
396           if (CORBA::is_nil (compoInfo))
397             {
398               continue;
399             }
400           SALOME_ModuleCatalog::ImplType impl=compoInfo->implementation_type();
401           container_exe=compoInfo->implementation_name();
402           if(impl==SALOME_ModuleCatalog::CEXE)
403             {
404               if(found)
405                 {
406                   INFOS("ContainerManager Error: you can't have 2 CEXE component in the same container" );
407                   return Engines::Container::_nil();
408                 }
409               found=1;
410             }
411         }
412     }
413   catch (ServiceUnreachable&)
414     {
415       INFOS("Caught exception: Naming Service Unreachable");
416       return Engines::Container::_nil();
417     }
418   catch (...)
419     {
420       INFOS("Caught unknown exception.");
421       return Engines::Container::_nil();
422     }
423
424   if(found)
425     return StartContainer(params,possibleComputers,container_exe.in());
426   else
427     return StartContainer(params,possibleComputers);
428 }
429
430 //=============================================================================
431 //!  Find or start a suitable Container given some constraints
432 /*! CORBA Method:
433  *  \param params            Machine Parameters required for the container
434  *  \return the container or nil
435  */
436 //=============================================================================
437
438 Engines::Container_ptr
439 SALOME_ContainerManager::FindOrStartContainer(const Engines::MachineParameters& params)
440 {
441   Engines::Container_ptr ret = FindContainer(params,params.computerList);
442   if(!CORBA::is_nil(ret))
443     return ret;
444   MESSAGE("Container doesn't exist try to launch it ...");
445
446   return StartContainer(params);
447 }
448
449 //=============================================================================
450 //! Find a container given constraints (params) on a list of machines (possibleComputers)
451 /*!
452  *
453  */
454 //=============================================================================
455
456 Engines::Container_ptr
457 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
458                                        const Engines::MachineList& possibleComputers)
459 {
460   MESSAGE("FindContainer "<<possibleComputers.length());
461   for(unsigned int i=0;i<possibleComputers.length();i++)
462     {
463       MESSAGE("FindContainer possible " << possibleComputers[i]);
464       Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
465       if( !CORBA::is_nil(cont) )
466         return cont;
467     }
468   MESSAGE("FindContainer: not found");
469   return Engines::Container::_nil();
470 }
471
472 //=============================================================================
473 //! Find a container given constraints (params) on a machine (theMachine)
474 /*!
475  *
476  */
477 //=============================================================================
478
479 Engines::Container_ptr
480 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
481                                        const char *theMachine)
482 {
483   string containerNameInNS(_NS->BuildContainerNameForNS(params,theMachine));
484   CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
485   try
486     {
487       if(obj->_non_existent())
488         return Engines::Container::_nil();
489       else
490         return Engines::Container::_narrow(obj);
491     }
492   catch(const CORBA::Exception& e)
493     {
494       return Engines::Container::_nil();
495     }
496 }
497
498 #ifdef WITH_PACO_PARALLEL
499 //=============================================================================
500 /*! CORBA Method:
501  *  Find or Start a suitable PaCO++ Parallel Container in a list of machines.
502  *  \param params            Machine Parameters required for the container
503  *  \return CORBA container reference.
504  */
505 //=============================================================================
506 Engines::Container_ptr
507 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params_const)
508 {
509   CORBA::Object_var obj;
510   PaCO::InterfaceManager_var container_proxy;
511   Engines::Container_ptr ret = Engines::Container::_nil();
512   Engines::MachineParameters params(params_const);
513
514   // Step 1 : Try to find a suitable container
515   // Currently not as good as could be since
516   // we have to verified the number of nodes of the container
517   // if a user tell that.
518   ret = FindContainer(params, params.computerList);
519   if(CORBA::is_nil(ret)) {
520     // Step 2 : Starting a new parallel container !
521     INFOS("[StartParallelContainer] Starting a PaCO++ parallel container");
522
523     // Step 3 : Choose a computer
524     std::string theMachine = _ResManager->FindFirst(params.computerList);
525     //If the machine name is localhost use the real name
526     if(theMachine == "localhost")
527       theMachine=Kernel_Utils::GetHostname();
528
529     if(theMachine == "") {
530       INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
531       INFOS("[StartParallelContainer] No possible computer found");
532       INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
533       return ret;
534     }
535     INFOS("[StartParallelContainer] on machine : " << theMachine);
536     params.hostname = CORBA::string_dup(theMachine.c_str());
537
538     // Step 4 : starting parallel container proxy
539     Engines::MachineParameters params_proxy(params);
540     std::string command_proxy;
541     SALOME_ContainerManager::actual_launch_machine_t proxy_machine;
542     try 
543     {
544       command_proxy = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerProxy", params_proxy, proxy_machine);
545     }
546     catch(const SALOME_Exception & ex)
547     {
548       INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
549       INFOS(ex.what());
550       return ret;
551     }
552     params_proxy.nb_component_nodes = 0; // LaunchParallelContainer uses this value to know if it launches the proxy or the nodes
553     obj = LaunchParallelContainer(command_proxy, params_proxy, _NS->ContainerName(params_proxy), proxy_machine);
554     if (CORBA::is_nil(obj))
555     {
556       INFOS("[StartParallelContainer] LaunchParallelContainer for proxy returns NIL !");
557       return ret;
558     }
559     try 
560     {
561       container_proxy = PaCO::InterfaceManager::_narrow(obj);
562     }
563     catch(CORBA::SystemException& e)
564     {
565       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
566       INFOS("CORBA::SystemException : " << e);
567       return ret;
568     }
569     catch(CORBA::Exception& e)
570     {
571       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
572       INFOS("CORBA::Exception" << e);
573       return ret;
574     }
575     catch(...)
576     {
577       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
578       INFOS("Unknown exception !");
579       return ret;
580     }
581     if (CORBA::is_nil(container_proxy))
582     {
583       INFOS("[StartParallelContainer] PaCO::InterfaceManager::_narrow returns NIL !");
584       return ret;
585     }
586
587     // Step 5 : starting parallel container nodes
588     std::string command_nodes;
589     Engines::MachineParameters params_nodes(params);
590     SALOME_ContainerManager::actual_launch_machine_t nodes_machines;
591     try 
592     {
593       command_nodes = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerNode", params_nodes, nodes_machines, proxy_machine[0]);
594     }
595     catch(const SALOME_Exception & ex)
596     {
597       INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
598       INFOS(ex.what());
599       return ret;
600     }
601     std::string container_generic_node_name = _NS->ContainerName(params) + "Node";
602     obj = LaunchParallelContainer(command_nodes, params_nodes, container_generic_node_name, nodes_machines);
603     if (CORBA::is_nil(obj))
604     {
605       INFOS("[StartParallelContainer] LaunchParallelContainer for nodes returns NIL !");
606       // Il faut tuer le proxy
607       try 
608       {
609         Engines::Container_var proxy = Engines::Container::_narrow(container_proxy);
610         proxy->Shutdown();
611       }
612       catch (...)
613       {
614         INFOS("[StartParallelContainer] Exception catched from proxy Shutdown...");
615       }
616       return ret;
617     }
618
619     // Step 6 : connecting nodes and the proxy to actually create a parallel container
620     for (int i = 0; i < params.nb_component_nodes; i++) 
621     {
622       std::ostringstream tmp;
623       tmp << i;
624       std::string proc_number = tmp.str();
625       std::string container_node_name = container_generic_node_name + proc_number;
626
627       std::string theNodeMachine(nodes_machines[i]);
628       std::string containerNameInNS = _NS->BuildContainerNameForNS(container_node_name.c_str(), theNodeMachine.c_str());
629       obj = _NS->Resolve(containerNameInNS.c_str());
630       if (CORBA::is_nil(obj)) 
631       {
632         INFOS("[StartParallelContainer] CONNECTION FAILED From Naming Service !");
633         INFOS("[StartParallelContainer] Container name is " << containerNameInNS);
634         return ret;
635       }
636       try
637       {
638         MESSAGE("[StartParallelContainer] Deploying node : " << container_node_name);
639         PaCO::InterfaceParallel_var node = PaCO::InterfaceParallel::_narrow(obj);
640         node->deploy();
641         MESSAGE("[StartParallelContainer] node " << container_node_name << " is deployed");
642       }
643       catch(CORBA::SystemException& e)
644       {
645         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
646         INFOS("CORBA::SystemException : " << e);
647         return ret;
648       }
649       catch(CORBA::Exception& e)
650       {
651         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
652         INFOS("CORBA::Exception" << e);
653         return ret;
654       }
655       catch(...)
656       {
657         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
658         INFOS("Unknown exception !");
659         return ret;
660       }
661     }
662
663     // Step 7 : starting parallel container
664     try 
665     {
666       MESSAGE ("[StartParallelContainer] Starting parallel object");
667       container_proxy->start();
668       MESSAGE ("[StartParallelContainer] Parallel object is started");
669       ret = Engines::Container::_narrow(container_proxy);
670     }
671     catch(CORBA::SystemException& e)
672     {
673       INFOS("Caught CORBA::SystemException. : " << e);
674     }
675     catch(PortableServer::POA::ServantAlreadyActive&)
676     {
677       INFOS("Caught CORBA::ServantAlreadyActiveException");
678     }
679     catch(CORBA::Exception&)
680     {
681       INFOS("Caught CORBA::Exception.");
682     }
683     catch(std::exception& exc)
684     {
685       INFOS("Caught std::exception - "<<exc.what()); 
686     }
687     catch(...)
688     {
689       INFOS("Caught unknown exception.");
690     }
691   }
692   return ret;
693 }
694 #else
695 //=============================================================================
696 /*! CORBA Method:
697  *  Find or Start a suitable PaCO++ Parallel Container in a list of machines.
698  *  \param params            Machine Parameters required for the container
699  *  \return CORBA container reference.
700  */
701 //=============================================================================
702 Engines::Container_ptr
703 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params)
704 {
705   Engines::Container_ptr ret = Engines::Container::_nil();
706   INFOS("[StartParallelContainer] is disabled !");
707   INFOS("[StartParallelContainer] recompile SALOME Kernel to enable parallel extension");
708   return ret;
709 }
710 #endif
711
712 //=============================================================================
713 /*! This method launches the parallel container.
714  *  It will may be placed on the ressources manager.
715  *
716  * \param command to launch
717  * \param container's parameters
718  * \param name of the container
719  *
720  * \return CORBA container reference
721  */
722 //=============================================================================
723 CORBA::Object_ptr 
724 SALOME_ContainerManager::LaunchParallelContainer(const std::string& command, 
725                                                  const Engines::MachineParameters& params,
726                                                  const std::string& name,
727                                                  SALOME_ContainerManager::actual_launch_machine_t & vect_machine)
728 {
729   CORBA::Object_ptr obj = CORBA::Object::_nil();
730   std::string containerNameInNS;
731   int count = TIME_OUT_TO_LAUNCH_CONT;
732
733   INFOS("[LaunchParallelContainer] Begin");
734   int status = system(command.c_str());
735   if (status == -1) {
736     INFOS("[LaunchParallelContainer] failed : system command status -1");
737     return obj;
738   }
739   else if (status == 217) {
740     INFOS("[LaunchParallelContainer] failed : system command status 217");
741     return obj;
742   }
743
744   if (params.nb_component_nodes == 0) 
745   {
746     std::string theMachine(vect_machine[0]);
747     // Proxy We have launch a proxy
748     containerNameInNS = _NS->BuildContainerNameForNS((char*) name.c_str(), theMachine.c_str());
749     INFOS("[LaunchParallelContainer]  Waiting for Parallel Container proxy " << containerNameInNS << " on " << theMachine);
750     while (CORBA::is_nil(obj) && count) 
751     {
752 #ifndef WIN32
753       sleep(1) ;
754 #else
755       Sleep(1000);
756 #endif
757       count-- ;
758       obj = _NS->Resolve(containerNameInNS.c_str());
759     }
760   }
761   else 
762   {
763     INFOS("[LaunchParallelContainer] launching the nodes of the parallel container");
764     // We are waiting all the nodes
765     for (int i = 0; i < params.nb_component_nodes; i++) 
766     {
767       obj = CORBA::Object::_nil();
768       std::string theMachine(vect_machine[i]);
769       // Name of the node
770       std::ostringstream tmp;
771       tmp << i;
772       std::string proc_number = tmp.str();
773       std::string container_node_name = name + proc_number;
774       containerNameInNS = _NS->BuildContainerNameForNS((char*) container_node_name.c_str(), theMachine.c_str());
775       INFOS("[LaunchParallelContainer]  Waiting for Parallel Container node " << containerNameInNS << " on " << theMachine);
776       while (CORBA::is_nil(obj) && count) {
777 #ifndef WIN32
778         sleep(1) ;
779 #else
780         Sleep(1000);
781 #endif
782         count-- ;
783         obj = _NS->Resolve(containerNameInNS.c_str());
784       }
785       if (CORBA::is_nil(obj))
786       {
787         INFOS("[LaunchParallelContainer] Launch of node failed (or not found) !");
788         return obj;
789       }
790     }
791   }
792   if (CORBA::is_nil(obj)) 
793     INFOS("[LaunchParallelContainer] failed");
794   
795   return obj;
796 }
797
798 void SALOME_ContainerManager::fillBatchLaunchedContainers()
799 {
800   _batchLaunchedContainers.clear();
801   _NS->Change_Directory("/Containers");
802   vector<string> vec = _NS->list_directory_recurs();
803   for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++){
804     CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
805     Engines::Container_ptr cont=Engines::Container::_narrow(obj);
806     if(!CORBA::is_nil(cont)){
807       _batchLaunchedContainers.push_back(cont);
808     }
809   }
810   _batchLaunchedContainersIter=_batchLaunchedContainers.begin();
811 }
812
813 //=============================================================================
814 /*!
815  *  This is no longer valid (C++ container are also python containers)
816  */ 
817 //=============================================================================
818
819 bool isPythonContainer(const char* ContainerName)
820 {
821   bool ret = false;
822   int len = strlen(ContainerName);
823
824   if (len >= 2)
825     if (strcmp(ContainerName + len - 2, "Py") == 0)
826       ret = true;
827
828   return ret;
829 }
830
831 //=============================================================================
832 /*!
833  *  Builds the script to be launched
834  *
835  *  If SALOME Application not defined ($APPLI),
836  *  see BuildTempFileToLaunchRemoteContainer()
837  *
838  *  Else rely on distant configuration. Command is under the form (example):
839  *  ssh user@machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \
840  *                   SALOME_Container containerName &"
841
842  *  - where user is ommited if not specified in CatalogResources,
843  *  - where distant path is always relative to user@machine $HOME, and
844  *    equal to $APPLI if not specified in CatalogResources,
845  *  - where hostNS is the hostname of CORBA naming server (set by scripts to
846  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
847  *  - where portNS is the port used by CORBA naming server (set by scripts to
848  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
849  *  - where workingdir is the requested working directory for the container.
850  *    If WORKINGDIR (and workingdir) is not present the working dir will be $HOME
851  */ 
852 //=============================================================================
853
854 string
855 SALOME_ContainerManager::BuildCommandToLaunchRemoteContainer
856 (const string& machine,
857  const Engines::MachineParameters& params, const std::string& container_exe)
858 {
859   string command;
860   int nbproc;
861           
862   if ( ! _isAppliSalomeDefined )
863     command = BuildTempFileToLaunchRemoteContainer(machine, params);
864
865   else
866     {
867       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine);
868
869       if (params.isMPI)
870         {
871           if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
872             nbproc = 1;
873           else if ( params.nb_node == 0 )
874             nbproc = params.nb_proc_per_node;
875           else if ( params.nb_proc_per_node == 0 )
876             nbproc = params.nb_node;
877           else
878             nbproc = params.nb_node * params.nb_proc_per_node;
879         }
880
881       // "ssh user@machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \
882         //  SALOME_Container containerName &"
883
884       if (resInfo.Protocol == rsh)
885         command = "rsh ";
886       else if (resInfo.Protocol == ssh)
887         command = "ssh ";
888       else
889         throw SALOME_Exception("Unknown protocol");
890
891       if (resInfo.UserName != "")
892         {
893           command += resInfo.UserName;
894           command += "@";
895         }
896
897       command += machine;
898       command += " ";
899
900       if (resInfo.AppliPath != "")
901         command += resInfo.AppliPath; // path relative to user@machine $HOME
902       else
903         {
904           ASSERT(getenv("APPLI"));
905           command += getenv("APPLI"); // path relative to user@machine $HOME
906         }
907
908       command += "/runRemote.sh ";
909
910       ASSERT(getenv("NSHOST")); 
911       command += getenv("NSHOST"); // hostname of CORBA name server
912
913       command += " ";
914       ASSERT(getenv("NSPORT"));
915       command += getenv("NSPORT"); // port of CORBA name server
916
917       std::string wdir=params.workingdir.in();
918       if(wdir != "")
919         {
920           command += " WORKINGDIR ";
921           command += " '";
922           if(wdir == "$TEMPDIR")
923             wdir="\\$TEMPDIR";
924           command += wdir; // requested working directory
925           command += "'"; 
926         }
927
928       if(params.isMPI)
929         {
930           command += " mpirun -np ";
931           std::ostringstream o;
932           o << nbproc << " ";
933           command += o.str();
934 #ifdef WITHLAM
935           command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
936 #elif defined(WITHOPENMPI)
937           if( getenv("OMPI_URI_FILE") == NULL )
938             command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
939           else{
940             command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
941             command += getenv("OMPI_URI_FILE");
942           }
943 #endif  
944           command += " SALOME_MPIContainer ";
945         }
946       else
947         command += " " +container_exe+ " ";
948
949       command += _NS->ContainerName(params);
950       command += " -";
951       AddOmninamesParams(command);
952
953       MESSAGE("command =" << command);
954     }
955
956   return command;
957 }
958
959 //=============================================================================
960 /*!
961  *  builds the command to be launched.
962  */ 
963 //=============================================================================
964
965 string
966 SALOME_ContainerManager::BuildCommandToLaunchLocalContainer
967 (const Engines::MachineParameters& params, const std::string& container_exe)
968 {
969   _TmpFileName = BuildTemporaryFileName();
970   string command;
971   int nbproc = 0;
972
973   ofstream command_file( _TmpFileName.c_str() );
974
975   if (params.isMPI)
976     {
977       //command = "mpirun -np ";
978       command_file << "mpirun -np ";
979
980       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
981         nbproc = 1;
982       else if ( params.nb_node == 0 )
983         nbproc = params.nb_proc_per_node;
984       else if ( params.nb_proc_per_node == 0 )
985         nbproc = params.nb_node;
986       else
987         nbproc = params.nb_node * params.nb_proc_per_node;
988
989       //std::ostringstream o;
990
991       //o << nbproc << " ";
992       command_file << nbproc << " ";
993
994       //command += o.str();
995 #ifdef WITHLAM
996       //command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
997       command_file << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
998 #elif defined(WITHOPENMPI)
999       //command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace ";
1000       if( getenv("OMPI_URI_FILE") == NULL )
1001         command_file << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
1002       else
1003         {
1004           command_file << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
1005           command_file << getenv("OMPI_URI_FILE");
1006         }
1007 #endif
1008
1009       if (isPythonContainer(params.container_name))
1010         //command += "pyMPI SALOME_ContainerPy.py ";
1011         command_file << " pyMPI SALOME_ContainerPy.py ";
1012       else
1013         //command += "SALOME_MPIContainer ";
1014         command_file << " SALOME_MPIContainer ";
1015     }
1016
1017   else
1018     {
1019       //command="";
1020       std::string wdir=params.workingdir.in();
1021       if(wdir != "")
1022         {
1023           // a working directory is requested
1024           if(wdir == "$TEMPDIR")
1025             {
1026               // a new temporary directory is requested
1027               string dir = Kernel_Utils::GetTmpDir();
1028 #ifdef WIN32
1029               //command += "cd /d "+ dir +";";
1030               command_file << "cd /d " << dir << endl;
1031 #else
1032               //command = "cd "+ dir +";";
1033               command_file << "cd " << dir << ";";
1034 #endif
1035
1036             }
1037           else
1038             {
1039               // a permanent directory is requested use it or create it
1040 #ifdef WIN32
1041               //command="mkdir " + wdir;
1042               command_file << "mkdir " + wdir << endl;
1043               command_file << "cd /D " + wdir << endl;
1044 #else
1045               //command="mkdir -p " + wdir + " && cd " + wdir + ";";
1046               command_file << "mkdir -p " << wdir << " && cd " << wdir + ";";
1047 #endif
1048             }
1049         }
1050       if (isPythonContainer(params.container_name))
1051         //command += "SALOME_ContainerPy.py ";
1052         command_file << "SALOME_ContainerPy.py ";
1053       else
1054         //command += container_exe + " ";
1055         command_file << container_exe + " ";
1056
1057     }
1058
1059   command_file << _NS->ContainerName(params);
1060   command_file << " -";
1061   AddOmninamesParams(command_file);
1062   command_file.close();
1063
1064 #ifndef WIN32
1065   chmod(_TmpFileName.c_str(), 0x1ED);
1066 #endif
1067   command = _TmpFileName;
1068
1069   MESSAGE("Command is file ... " << command);
1070   return command;
1071 }
1072
1073
1074 //=============================================================================
1075 /*!
1076  *  removes the generated temporary file in case of a remote launch.
1077  */ 
1078 //=============================================================================
1079
1080 void SALOME_ContainerManager::RmTmpFile(std::string& tmpFileName)
1081 {
1082   int lenght = tmpFileName.size();
1083   if ( lenght  > 0)
1084     {
1085 #ifdef WIN32
1086       string command = "del /F ";
1087 #else
1088       string command = "rm ";      
1089 #endif
1090       if ( lenght > 4 )
1091         command += tmpFileName.substr(0, lenght - 3 );
1092       else
1093         command += tmpFileName;
1094       command += '*';
1095       system(command.c_str());
1096       //if dir is empty - remove it
1097       string tmp_dir = Kernel_Utils::GetDirByPath( tmpFileName );
1098       if ( Kernel_Utils::IsEmptyDir( tmp_dir ) )
1099         {
1100 #ifdef WIN32
1101           command = "del /F " + tmp_dir;
1102 #else
1103           command = "rmdir " + tmp_dir;
1104 #endif
1105           system(command.c_str());
1106         }
1107     }
1108 }
1109
1110 //=============================================================================
1111 /*!
1112  *   add to command all options relative to naming service.
1113  */ 
1114 //=============================================================================
1115
1116 void SALOME_ContainerManager::AddOmninamesParams(string& command) const
1117 {
1118   CORBA::String_var iorstr = _NS->getIORaddr();
1119   command += "ORBInitRef NameService=";
1120   command += iorstr;
1121 }
1122
1123
1124 //=============================================================================
1125 /*!
1126  *  add to command all options relative to naming service.
1127  */ 
1128 //=============================================================================
1129
1130 void SALOME_ContainerManager::AddOmninamesParams(ofstream& fileStream) const
1131 {
1132   CORBA::String_var iorstr = _NS->getIORaddr();
1133   fileStream << "ORBInitRef NameService=";
1134   fileStream << iorstr;
1135 }
1136
1137 //=============================================================================
1138 /*!
1139  *  generate a file name in /tmp directory
1140  */ 
1141 //=============================================================================
1142
1143 string SALOME_ContainerManager::BuildTemporaryFileName() const
1144 {
1145   //build more complex file name to support multiple salome session
1146   string aFileName = Kernel_Utils::GetTmpFileName();
1147 #ifndef WIN32
1148   aFileName += ".sh";
1149 #else
1150   aFileName += ".bat";
1151 #endif
1152   return aFileName;
1153 }
1154
1155
1156 //=============================================================================
1157 /*!
1158  *  Builds in a temporary file the script to be launched.
1159  *  
1160  *  Used if SALOME Application ($APPLI) is not defined.
1161  *  The command is build with data from CatalogResources, in which every path
1162  *  used on remote computer must be defined.
1163  */ 
1164 //=============================================================================
1165
1166 string
1167 SALOME_ContainerManager::BuildTempFileToLaunchRemoteContainer
1168 (const string& machine,
1169  const Engines::MachineParameters& params) throw(SALOME_Exception)
1170 {
1171   int status;
1172
1173   _TmpFileName = BuildTemporaryFileName();
1174   ofstream tempOutputFile;
1175   tempOutputFile.open(_TmpFileName.c_str(), ofstream::out );
1176   const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine);
1177   tempOutputFile << "#! /bin/sh" << endl;
1178
1179   // --- set env vars
1180
1181   tempOutputFile << "export SALOME_trace=local" << endl; // mkr : 27.11.2006 : PAL13967 - Distributed supervision graphs - Problem with "SALOME_trace"
1182   //tempOutputFile << "source " << resInfo.PreReqFilePath << endl;
1183
1184   // ! env vars
1185
1186   if (params.isMPI)
1187     {
1188       tempOutputFile << "mpirun -np ";
1189       int nbproc;
1190
1191       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
1192         nbproc = 1;
1193       else if ( params.nb_node == 0 )
1194         nbproc = params.nb_proc_per_node;
1195       else if ( params.nb_proc_per_node == 0 )
1196         nbproc = params.nb_node;
1197       else
1198         nbproc = params.nb_node * params.nb_proc_per_node;
1199
1200       std::ostringstream o;
1201
1202       tempOutputFile << nbproc << " ";
1203 #ifdef WITHLAM
1204       tempOutputFile << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
1205 #elif defined(WITHOPENMPI)
1206       if( getenv("OMPI_URI_FILE") == NULL )
1207         tempOutputFile << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
1208       else{
1209         tempOutputFile << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
1210         tempOutputFile << getenv("OMPI_URI_FILE");
1211       }
1212 #endif
1213     }
1214
1215   tempOutputFile << getenv("KERNEL_ROOT_DIR") << "/bin/salome/";
1216
1217   if (params.isMPI)
1218     {
1219       if (isPythonContainer(params.container_name))
1220         tempOutputFile << " pyMPI SALOME_ContainerPy.py ";
1221       else
1222         tempOutputFile << " SALOME_MPIContainer ";
1223     }
1224
1225   else
1226     {
1227       if (isPythonContainer(params.container_name))
1228         tempOutputFile << "SALOME_ContainerPy.py ";
1229       else
1230         tempOutputFile << "SALOME_Container ";
1231     }
1232
1233   tempOutputFile << _NS->ContainerName(params) << " -";
1234   AddOmninamesParams(tempOutputFile);
1235   tempOutputFile << " &" << endl;
1236   tempOutputFile.flush();
1237   tempOutputFile.close();
1238 #ifndef WIN32
1239   chmod(_TmpFileName.c_str(), 0x1ED);
1240 #endif
1241
1242   // --- Build command
1243
1244   string command;
1245
1246   if (resInfo.Protocol == rsh)
1247     {
1248       command = "rsh ";
1249       string commandRcp = "rcp ";
1250       commandRcp += _TmpFileName;
1251       commandRcp += " ";
1252       commandRcp += machine;
1253       commandRcp += ":";
1254       commandRcp += _TmpFileName;
1255       status = system(commandRcp.c_str());
1256     }
1257
1258   else if (resInfo.Protocol == ssh)
1259     {
1260       command = "ssh ";
1261       string commandRcp = "scp ";
1262       commandRcp += _TmpFileName;
1263       commandRcp += " ";
1264       commandRcp += machine;
1265       commandRcp += ":";
1266       commandRcp += _TmpFileName;
1267       status = system(commandRcp.c_str());
1268     }
1269   else
1270     throw SALOME_Exception("Unknown protocol");
1271
1272   if(status)
1273     throw SALOME_Exception("Error of connection on remote host");    
1274
1275   command += machine;
1276   _CommandForRemAccess = command;
1277   command += " ";
1278   command += _TmpFileName;
1279
1280   SCRUTE(command);
1281
1282   return command;
1283
1284 }
1285
1286 //=============================================================================
1287 /*! Creates a command line that the container manager uses to launch
1288  * a parallel container.
1289  */ 
1290 //=============================================================================
1291 string 
1292 SALOME_ContainerManager::BuildCommandToLaunchParallelContainer(const std::string& exe_name,
1293                                                                const Engines::MachineParameters& params,
1294                                                                SALOME_ContainerManager::actual_launch_machine_t & vect_machine,
1295                                                                const std::string proxy_hostname)
1296 {
1297   // This method knows the differences between the proxy and the nodes.
1298   // nb_component_nodes is not used in the same way if it is a proxy or 
1299   // a node.
1300   
1301   //command = "gdb --args ";
1302   //command = "valgrind --tool=memcheck --log-file=val_log ";
1303   //command += real_exe_name;
1304
1305   // Step 0 : init some variables...
1306   std::string parallelLib(CORBA::string_dup(params.parallelLib));
1307   std::string real_exe_name  = exe_name + parallelLib;
1308   std::string machine_file_name("");
1309   bool remote = false;
1310   bool is_a_proxy = false; 
1311   std::string hostname(CORBA::string_dup(params.hostname));
1312
1313   std::ostringstream tmp_string;
1314   CORBA::Long nb_nodes = params.nb_component_nodes;
1315   tmp_string << nb_nodes;
1316   std::string nbproc = tmp_string.str();
1317
1318   Engines::MachineParameters_var rtn = new Engines::MachineParameters();
1319   rtn->container_name = params.container_name;
1320   rtn->hostname = params.hostname;
1321   rtn->OS = params.OS;
1322   rtn->mem_mb = params.mem_mb;
1323   rtn->cpu_clock = params.cpu_clock;
1324   rtn->nb_proc_per_node = params.nb_proc_per_node;
1325   rtn->nb_node = params.nb_node;
1326   rtn->isMPI = params.isMPI;
1327
1328   // Step 1 : local or remote launch ?
1329   if (hostname != std::string(Kernel_Utils::GetHostname()) )
1330   {
1331     MESSAGE("[BuildCommandToLaunchParallelContainer] remote machine case detected !");
1332     remote = true;
1333   }
1334
1335   // Step 2 : proxy or nodes launch ?
1336   std::string::size_type loc_proxy = exe_name.find("Proxy");
1337   if( loc_proxy != string::npos ) {
1338     is_a_proxy = true;
1339   } 
1340
1341   // Step 3 : Depending of the parallelLib, getting the machine file
1342   // ParallelLib Dummy has is own machine for this method
1343   if (remote)
1344   {
1345     if (is_a_proxy)
1346     {
1347       machine_file_name = _ResManager->getMachineFile(hostname,
1348                                                       1,
1349                                                       parallelLib);
1350     }
1351     else
1352     {
1353       machine_file_name = _ResManager->getMachineFile(hostname, 
1354                                                       params.nb_component_nodes,
1355                                                       parallelLib);
1356     }
1357     if (machine_file_name == "")
1358     {
1359       INFOS("[BuildCommandToLaunchParallelContainer] Error machine_file was not generated for machine " << hostname);
1360       throw SALOME_Exception("Error machine_file was not generated");
1361     }
1362     MESSAGE("[BuildCommandToLaunchParallelContainer] machine_file_name is : " << machine_file_name);
1363   }
1364
1365   // Step 4 : Log type choosen by the user
1366   std::string log_env("");
1367   char * get_val = getenv("PARALLEL_LOG");
1368   if (get_val)
1369     log_env = get_val;
1370   std::string command_begin("");
1371   std::string command_end("");
1372   if(log_env == "xterm")
1373   {
1374     command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1375     command_end   = "\"&";
1376   }
1377   else if(log_env == "xterm_debug")
1378   {
1379     command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1380     command_end   = "; cat \" &";
1381   }
1382   else
1383   {
1384     // default into a file...
1385     std::string logFilename = "/tmp/" + _NS->ContainerName(params) + "_" + hostname;
1386     if (is_a_proxy)
1387       logFilename += "_Proxy_";
1388     else
1389       logFilename += "_Node_";
1390     logFilename += std::string(getenv("USER")) + ".log";
1391     command_end = " > " + logFilename + " 2>&1 & ";
1392   }
1393
1394   // Step 5 : Building the command
1395   std::string command("");
1396   if (parallelLib == "Dummy")
1397   {
1398     if (is_a_proxy)
1399     {
1400       std::string command_remote("");
1401       if (remote)
1402       {
1403         std::string machine_name;
1404         std::ifstream machine_file(machine_file_name.c_str());
1405         std::getline(machine_file, machine_name);
1406         MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << machine_name)
1407
1408         // We want to launch a command like : 
1409         // ssh user@machine distantPath/runRemote.sh hostNS portNS
1410         const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine_name);
1411         if (resInfo.Protocol == rsh)
1412           command_remote = "rsh ";
1413         else 
1414           command_remote = "ssh ";
1415         command_remote += resInfo.UserName;
1416         command_remote += "@";
1417         command_remote += machine_name;
1418         command_remote += " ";
1419         command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1420         command_remote += "/runRemote.sh ";
1421         ASSERT(getenv("NSHOST")); 
1422         command_remote += getenv("NSHOST"); // hostname of CORBA name server
1423         command_remote += " ";
1424         ASSERT(getenv("NSPORT"));
1425         command_remote += getenv("NSPORT"); // port of CORBA name server
1426         command_remote += " ";
1427
1428         hostname = machine_name;
1429       }
1430
1431       command =  real_exe_name;
1432       command += " " + _NS->ContainerName(rtn);
1433       command += " " + parallelLib;
1434       command += " " + hostname;
1435       command += " " + nbproc;
1436       command += " -";
1437       AddOmninamesParams(command);
1438
1439       command = command_begin + command_remote + command + command_end;
1440       vect_machine.push_back(hostname);
1441     }
1442     else
1443     {
1444       std::ifstream * machine_file = NULL;
1445       if (remote)
1446         machine_file = new std::ifstream(machine_file_name.c_str());
1447       for (int i= 0; i < nb_nodes; i++)
1448       {
1449         std::string command_remote("");
1450         if (remote)
1451         {
1452           std::string machine_name;
1453           std::getline(*machine_file, machine_name);
1454           MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << machine_name)
1455
1456             // We want to launch a command like : 
1457             // ssh user@machine distantPath/runRemote.sh hostNS portNS
1458             const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine_name);
1459           if (resInfo.Protocol == rsh)
1460             command_remote = "rsh ";
1461           else 
1462             command_remote = "ssh ";
1463           command_remote += resInfo.UserName;
1464           command_remote += "@";
1465           command_remote += machine_name;
1466           command_remote += " ";
1467           command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1468           command_remote += "/runRemote.sh ";
1469           ASSERT(getenv("NSHOST")); 
1470           command_remote += getenv("NSHOST"); // hostname of CORBA name server
1471           command_remote += " ";
1472           ASSERT(getenv("NSPORT"));
1473           command_remote += getenv("NSPORT"); // port of CORBA name server
1474           command_remote += " ";
1475
1476           hostname = machine_name;
1477         }
1478
1479         std::ostringstream tmp;
1480         tmp << i;
1481         std::string proc_number = tmp.str();
1482
1483         std::string command_tmp("");
1484         command_tmp += real_exe_name;
1485         command_tmp += " " + _NS->ContainerName(rtn);
1486         command_tmp += " " + parallelLib;
1487         command_tmp += " " + proxy_hostname;
1488         command_tmp += " " + proc_number;
1489         command_tmp += " -";
1490         AddOmninamesParams(command_tmp);
1491
1492         // On change _Node_ par _Nodex_ pour avoir chaque noeud
1493         // sur un fichier
1494         std::string command_end_tmp = command_end;
1495         std::string::size_type loc_node = command_end_tmp.find("_Node_");
1496         if (loc_node != std::string::npos)
1497           command_end_tmp.insert(loc_node+5, proc_number);
1498         command += command_begin + command_remote + command_tmp + command_end_tmp;
1499         vect_machine.push_back(hostname);
1500       }
1501       if (machine_file)
1502         delete machine_file;
1503     }
1504   }
1505   else if (parallelLib == "Mpi")
1506   {
1507     // Step 0: if remote we have to copy the file
1508     // to the first machine of the file
1509     std::string remote_machine("");
1510     if (remote)
1511     {
1512       std::ifstream * machine_file = NULL;
1513       machine_file = new std::ifstream(machine_file_name.c_str());
1514       // Get first word of the line
1515       // For MPI implementation the first word is the 
1516       // machine name
1517       std::getline(*machine_file, remote_machine, ' ');
1518       machine_file->close();
1519       MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << remote_machine)
1520
1521       // We want to launch a command like : 
1522       // scp mpi_machine_file user@machine:Path
1523       std::string command_remote("");
1524       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1525       if (resInfo.Protocol == rsh)
1526         command_remote = "rcp ";
1527       else 
1528         command_remote = "scp ";
1529
1530       command_remote += machine_file_name;
1531       command_remote += " ";
1532       command_remote += resInfo.UserName;
1533       command_remote += "@";
1534       command_remote += remote_machine;
1535       command_remote += ":";
1536       command_remote += machine_file_name;
1537
1538       int status = system(command_remote.c_str());
1539       if (status == -1)
1540       {
1541         INFOS("copy of the mpi machine file failed !");
1542         return "";
1543       }
1544     }
1545
1546     if (is_a_proxy)
1547     {
1548       std::string command_remote("");
1549       if (remote)
1550       {
1551         // We want to launch a command like : 
1552         // ssh user@machine distantPath/runRemote.sh hostNS portNS
1553         const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1554         if (resInfo.Protocol == rsh)
1555           command_remote = "rsh ";
1556         else 
1557           command_remote = "ssh ";
1558         command_remote += resInfo.UserName;
1559         command_remote += "@";
1560         command_remote += remote_machine;
1561         command_remote += " ";
1562         command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1563         command_remote += "/runRemote.sh ";
1564         ASSERT(getenv("NSHOST")); 
1565         command_remote += getenv("NSHOST"); // hostname of CORBA name server
1566         command_remote += " ";
1567         ASSERT(getenv("NSPORT"));
1568         command_remote += getenv("NSPORT"); // port of CORBA name server
1569         command_remote += " ";
1570
1571         hostname = remote_machine;
1572       }
1573
1574       // We use Dummy proxy for MPI parallel containers
1575       real_exe_name  = exe_name + "Dummy";
1576       command =  real_exe_name;
1577       command += " " + _NS->ContainerName(rtn);
1578       command += " Dummy";
1579       command += " " + hostname;
1580       command += " " + nbproc;
1581       command += " -";
1582       AddOmninamesParams(command);
1583
1584       command = command_begin + command_remote + command + command_end;
1585       vect_machine.push_back(hostname);
1586     }
1587     else                                          
1588     {
1589       std::string command_remote("");
1590       if (remote)
1591       {
1592         const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1593         if (resInfo.Protocol == rsh)
1594           command_remote = "rsh ";
1595         else 
1596           command_remote = "ssh ";
1597         command_remote += resInfo.UserName;
1598         command_remote += "@";
1599         command_remote += remote_machine;
1600         command_remote += " ";
1601
1602         std::string new_real_exe_name("");
1603         new_real_exe_name += resInfo.AppliPath; // path relative to user@machine $HOME
1604         new_real_exe_name += "/runRemote.sh ";
1605         ASSERT(getenv("NSHOST")); 
1606         new_real_exe_name += getenv("NSHOST"); // hostname of CORBA name server
1607         new_real_exe_name += " ";
1608         ASSERT(getenv("NSPORT"));
1609         new_real_exe_name += getenv("NSPORT"); // port of CORBA name server
1610         new_real_exe_name += " ";
1611
1612         real_exe_name = new_real_exe_name + real_exe_name;
1613         hostname = remote_machine;
1614       }
1615
1616       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(hostname);
1617       if (resInfo.mpi == lam)
1618       {
1619         command = "mpiexec -ssi boot ";
1620         if (resInfo.Protocol == rsh)
1621           command += "rsh ";
1622         else 
1623           command += "ssh ";
1624         command += "-machinefile " + machine_file_name + " "; 
1625         command += "-n " + nbproc + " ";
1626         command += real_exe_name;
1627         command += " " + _NS->ContainerName(rtn);
1628         command += " " + parallelLib;
1629         command += " " + proxy_hostname;
1630         command += " -";
1631         AddOmninamesParams(command);
1632       }
1633       else
1634       {
1635         command = "mpirun -np " + nbproc + " ";
1636         command += real_exe_name;
1637         command += " " + _NS->ContainerName(rtn);
1638         command += " " + parallelLib;
1639         command += " " + proxy_hostname;
1640         command += " -";
1641         AddOmninamesParams(command);
1642       }
1643
1644       command = command_begin + command_remote + command + command_end;
1645       for (int i= 0; i < nb_nodes; i++)
1646         vect_machine.push_back(proxy_hostname);
1647     }
1648   }
1649   else
1650   {
1651     std::string message("Unknown parallelLib : " + parallelLib);
1652     throw SALOME_Exception(message.c_str());
1653   }
1654
1655   MESSAGE("Parallel launch is: " << command);
1656   return command;
1657 }
1658
1659 string SALOME_ContainerManager::GetMPIZeroNode(string machine)
1660 {
1661   int status;
1662   string zeronode;
1663   string cmd;
1664   string tmpFile = BuildTemporaryFileName();
1665
1666   cmd = "ssh " + machine + " mpirun -np 1 hostname > " + tmpFile;
1667
1668   status = system(cmd.c_str());
1669   if( status == 0 ){
1670     ifstream fp(tmpFile.c_str(),ios::in);
1671     fp >> zeronode;
1672   }
1673
1674   RmTmpFile(tmpFile);
1675
1676   return zeronode;
1677 }