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