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