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