]> SALOME platform Git repositories - modules/kernel.git/blob - src/ResourcesManager/SALOME_ResourcesManager.cxx
Salome HOME
merge from BR_For40_DSC 28 jan 08
[modules/kernel.git] / src / ResourcesManager / SALOME_ResourcesManager.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 #include "SALOME_ResourcesManager.hxx" 
21 #include "Utils_ExceptHandlers.hxx"
22 #include "Utils_CorbaException.hxx"
23 #include "OpUtil.hxx"
24
25 #include <stdlib.h>
26 #ifndef WNT
27 #include <unistd.h>
28 #else
29 #include <io.h>
30 #include <process.h>
31 #endif
32 #include <fstream>
33 #include <iostream>
34 #include <sstream>
35 #include <string.h>
36 #include <map>
37 #include <list>
38
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include "utilities.h"
42
43 #define MAX_SIZE_FOR_HOSTNAME 256;
44
45 using namespace std;
46
47 const char *SALOME_ResourcesManager::_ResourcesManagerNameInNS = "/ResourcesManager";
48
49 //=============================================================================
50 /*!
51  * just for test
52  */ 
53 //=============================================================================
54
55 SALOME_ResourcesManager::
56 SALOME_ResourcesManager(CORBA::ORB_ptr orb, 
57                         PortableServer::POA_var poa, 
58                         SALOME_NamingService *ns,
59                         const char *xmlFilePath) :
60     _path_resources(xmlFilePath)
61 {
62   MESSAGE("constructor");
63   _NS = ns;
64   _orb = CORBA::ORB::_duplicate(orb) ;
65   _poa = PortableServer::POA::_duplicate(poa) ;
66   PortableServer::ObjectId_var id = _poa->activate_object(this);
67   CORBA::Object_var obj = _poa->id_to_reference(id);
68   Engines::SalomeLauncher_var refContMan =
69     Engines::SalomeLauncher::_narrow(obj);
70
71   _NS->Register(refContMan,_ResourcesManagerNameInNS);
72   _MpiStarted = false;
73   MESSAGE("constructor end");
74 }
75
76 //=============================================================================
77 /*!
78  *  Standard constructor, parse resource file.
79  *  - if ${APPLI} exists in environment,
80  *    look for ${HOME}/${APPLI}/CatalogResources.xml
81  *  - else look for default:
82  *    ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
83  *  - parse XML resource file.
84  */ 
85 //=============================================================================
86
87 SALOME_ResourcesManager::SALOME_ResourcesManager(CORBA::ORB_ptr orb, 
88                                                  PortableServer::POA_var poa, 
89                                                  SALOME_NamingService *ns)
90 {
91   MESSAGE("constructor");
92   _NS = ns;
93   _orb = CORBA::ORB::_duplicate(orb) ;
94   _poa = PortableServer::POA::_duplicate(poa) ;
95   PortableServer::ObjectId_var id = _poa->activate_object(this);
96   CORBA::Object_var obj = _poa->id_to_reference(id);
97   Engines::ResourcesManager_var refContMan = Engines::ResourcesManager::_narrow(obj);
98   _NS->Register(refContMan,_ResourcesManagerNameInNS);
99
100   _isAppliSalomeDefined = (getenv("APPLI") != 0);
101   _MpiStarted = false;
102
103   if (_isAppliSalomeDefined)
104     {
105       _path_resources = getenv("HOME");
106       _path_resources += "/";
107       _path_resources += getenv("APPLI");
108       _path_resources += "/CatalogResources.xml";
109     }
110
111   else
112     {
113       _path_resources = getenv("KERNEL_ROOT_DIR");
114       _path_resources += "/share/salome/resources/kernel/CatalogResources.xml";
115     }
116
117   ParseXmlFile();
118   MESSAGE("constructor end");
119 }
120
121 //=============================================================================
122 /*!
123  *  Standard Destructor
124  */ 
125 //=============================================================================
126
127 SALOME_ResourcesManager::~SALOME_ResourcesManager()
128 {
129   MESSAGE("destructor");
130 }
131
132
133 //=============================================================================
134 /*! CORBA method:
135  *  shutdown all the containers, then the ContainerManager servant
136  */
137 //=============================================================================
138
139 void SALOME_ResourcesManager::Shutdown()
140 {
141   MESSAGE("Shutdown");
142   _NS->Destroy_Name(_ResourcesManagerNameInNS);
143   PortableServer::ObjectId_var oid = _poa->servant_to_id(this);
144   _poa->deactivate_object(oid);
145   //_remove_ref();
146 }
147
148 //=============================================================================
149 /*!
150  *  get the list of name of ressources fitting for the specified module.
151  *  If hostname specified, check it is local or known in resources catalog.
152  *
153  *  Else
154  *  - select first machines with corresponding OS (all machines if
155  *    parameter OS empty),
156  *  - then select the sublist of machines on witch the module is known
157  *    (if the result is empty, that probably means that the inventory of
158  *    modules is probably not done, so give complete list from previous step)
159  */ 
160 //=============================================================================
161
162 Engines::MachineList *
163 SALOME_ResourcesManager::GetFittingResources(const Engines::MachineParameters& params,
164                                              const Engines::CompoList& componentList)
165 //throw(SALOME_Exception)
166 {
167 //   MESSAGE("ResourcesManager::GetFittingResources");
168   vector <std::string> vec;
169   Engines::MachineList *ret=new Engines::MachineList;
170
171   try{
172     // --- To be sure that we search in a correct list.
173     ParseXmlFile();
174
175     const char *hostname = (const char *)params.hostname;
176     MESSAGE("GetFittingResources " << hostname << " " << GetHostname().c_str());
177
178     if (hostname[0] != '\0')
179       {
180 //       MESSAGE("ResourcesManager::GetFittingResources : hostname specified" );
181
182         if ( strcmp(hostname, "localhost") == 0 ||
183              strcmp(hostname, GetHostname().c_str()) == 0 )
184           {
185             //           MESSAGE("ResourcesManager::GetFittingResources : localhost" );
186             vec.push_back(GetHostname().c_str());
187             //    MESSAGE("ResourcesManager::GetFittingResources : " << vec.size());
188           }
189         
190         else if (_resourcesList.find(hostname) != _resourcesList.end())
191           {
192             // --- params.hostname is in the list of resources so return it.
193             vec.push_back(hostname);
194           }
195         
196         else
197           {
198             // Cas d'un cluster: nombre de noeuds > 1
199             int cpt=0;
200             for (map<string, ParserResourcesType>::const_iterator iter = _resourcesList.begin(); iter != _resourcesList.end(); iter++){
201               if( (*iter).second.DataForSort._nbOfNodes > 1 ){
202                 if( strncmp(hostname,(*iter).first.c_str(),strlen(hostname)) == 0 ){
203                   vec.push_back((*iter).first.c_str());
204                   //cout << "SALOME_ResourcesManager::GetFittingResources vector["
205                   //     << cpt << "] = " << (*iter).first.c_str() << endl ;
206                   cpt++;
207                 }
208               }
209             }
210             if(cpt==0){
211               // --- user specified an unknown hostame so notify him.
212               MESSAGE("ResourcesManager::GetFittingResources : SALOME_Exception");
213               throw SALOME_Exception("unknown host");
214             }
215           }
216       }
217     
218     else
219       // --- Search for available resources sorted by priority
220       {
221         SelectOnlyResourcesWithOS(vec, params.OS);
222         
223         KeepOnlyResourcesWithModule(vec, componentList);
224         
225         if (vec.size() == 0)
226           SelectOnlyResourcesWithOS(vec, params.OS);
227         
228         // --- set wanted parameters
229         ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
230         
231         ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
232         
233         ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
234         
235         ResourceDataToSort::_memInMBWanted = params.mem_mb;
236         
237         // --- end of set
238         
239         list<ResourceDataToSort> li;
240         
241         for (vector<string>::iterator iter = vec.begin();
242            iter != vec.end();
243              iter++)
244           li.push_back(_resourcesList[(*iter)].DataForSort);
245         
246         li.sort();
247         
248         unsigned int i = 0;
249         
250         for (list<ResourceDataToSort>::iterator iter2 = li.begin();
251              iter2 != li.end();
252              iter2++)
253           vec[i++] = (*iter2)._hostName;
254       }
255     
256     //  MESSAGE("ResourcesManager::GetFittingResources : return" << ret.size());
257     ret->length(vec.size());
258     for(unsigned int i=0;i<vec.size();i++)
259       (*ret)[i]=(vec[i]).c_str();
260
261   }
262   catch(const SALOME_Exception &ex)
263     {
264       INFOS("Caught exception.");
265       THROW_SALOME_CORBA_EXCEPTION(ex.what(),SALOME::BAD_PARAM);
266       //return ret;
267     }  
268
269   return ret;
270 }
271
272 //=============================================================================
273 /*!
274  *  add an entry in the ressources catalog  xml file.
275  *  Return 0 if OK (KERNEL found in new resources modules) else throw exception
276  */ 
277 //=============================================================================
278
279 int
280 SALOME_ResourcesManager::
281 AddResourceInCatalog(const Engines::MachineParameters& paramsOfNewResources,
282                      const vector<string>& modulesOnNewResources,
283                      const char *alias,
284                      const char *userName,
285                      AccessModeType mode,
286                      AccessProtocolType prot)
287 throw(SALOME_Exception)
288 {
289   vector<string>::const_iterator iter = find(modulesOnNewResources.begin(),
290                                              modulesOnNewResources.end(),
291                                              "KERNEL");
292
293   if (iter != modulesOnNewResources.end())
294     {
295       ParserResourcesType newElt;
296       newElt.DataForSort._hostName = paramsOfNewResources.hostname;
297       newElt.Alias = alias;
298       newElt.Protocol = prot;
299       newElt.Mode = mode;
300       newElt.UserName = userName;
301       newElt.ModulesList = modulesOnNewResources;
302       newElt.OS = paramsOfNewResources.OS;
303       newElt.DataForSort._memInMB = paramsOfNewResources.mem_mb;
304       newElt.DataForSort._CPUFreqMHz = paramsOfNewResources.cpu_clock;
305       newElt.DataForSort._nbOfNodes = paramsOfNewResources.nb_node;
306       newElt.DataForSort._nbOfProcPerNode =
307         paramsOfNewResources.nb_proc_per_node;
308       _resourcesList[newElt.DataForSort._hostName] = newElt;
309       return 0;
310     }
311
312   else
313     throw SALOME_Exception("KERNEL is not present in this resource");
314 }
315
316 //=============================================================================
317 /*!
318  *  Deletes a resource from the catalog
319  */ 
320 //=============================================================================
321
322 void SALOME_ResourcesManager::DeleteResourceInCatalog(const char *hostname)
323 {
324   _resourcesList.erase(hostname);
325 }
326
327 //=============================================================================
328 /*!
329  *  write the current data in memory in file.
330  */ 
331 //=============================================================================
332
333 void SALOME_ResourcesManager::WriteInXmlFile()
334 {
335   const char* aFilePath = _path_resources.c_str();
336   
337   FILE* aFile = fopen(aFilePath, "w");
338
339   if (aFile == NULL)
340     {
341       INFOS("Error opening file !");
342       return;
343     }
344   
345   xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
346   xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
347
348   SALOME_ResourcesCatalog_Handler* handler =
349     new SALOME_ResourcesCatalog_Handler(_resourcesList);
350   handler->PrepareDocToXmlFile(aDoc);
351   delete handler;
352
353   int isOk = xmlSaveFile(aFilePath, aDoc);
354   
355   if (!isOk)
356     INFOS("Error while XML file saving.");
357   
358   // Free the document
359   xmlFreeDoc(aDoc);
360
361   fclose(aFile);
362   
363   MESSAGE("WRITING DONE!");
364 }
365
366 //=============================================================================
367 /*!
368  *  parse the data type catalog
369  */ 
370 //=============================================================================
371
372 const MapOfParserResourcesType& SALOME_ResourcesManager::ParseXmlFile()
373 {
374   SALOME_ResourcesCatalog_Handler* handler =
375     new SALOME_ResourcesCatalog_Handler(_resourcesList);
376
377   const char* aFilePath = _path_resources.c_str();
378   FILE* aFile = fopen(aFilePath, "r");
379   
380   if (aFile != NULL)
381     {
382       xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
383       
384       if (aDoc != NULL)
385         handler->ProcessXmlDocument(aDoc);
386       else
387         INFOS("ResourcesManager: could not parse file "<<aFilePath);
388       
389       // Free the document
390       xmlFreeDoc(aDoc);
391
392       fclose(aFile);
393     }
394   else
395     INFOS("ResourcesManager: file "<<aFilePath<<" is not readable.");
396   
397   delete handler;
398
399   return _resourcesList;
400 }
401
402 //=============================================================================
403 /*!
404  *   consult the content of the list
405  */ 
406 //=============================================================================
407
408 const MapOfParserResourcesType& SALOME_ResourcesManager::GetList() const
409   {
410     return _resourcesList;
411   }
412
413
414 //=============================================================================
415 /*!
416  *  dynamically obtains the first machines
417  */ 
418 //=============================================================================
419
420 char *
421 SALOME_ResourcesManager::FindFirst(const Engines::MachineList& listOfMachines)
422 {
423   return CORBA::string_dup(_dynamicResourcesSelecter.FindFirst(listOfMachines).c_str());
424 }
425
426 //=============================================================================
427 /*!
428  *  dynamically obtains the best machines
429  */ 
430 //=============================================================================
431
432 string
433 SALOME_ResourcesManager::FindNext(const Engines::MachineList& listOfMachines)
434 {
435   return _dynamicResourcesSelecter.FindNext(listOfMachines,_resourcesList,_NS);
436 }
437 //=============================================================================
438 /*!
439  *  dynamically obtains the best machines
440  */ 
441 //=============================================================================
442
443 string
444 SALOME_ResourcesManager::FindBest(const Engines::MachineList& listOfMachines)
445 {
446   return _dynamicResourcesSelecter.FindBest(listOfMachines);
447 }
448
449 //=============================================================================
450 /*!
451  *  This is no longer valid (C++ container are also python containers)
452  */ 
453 //=============================================================================
454
455 bool isPythonContainer(const char* ContainerName)
456 {
457   bool ret = false;
458   int len = strlen(ContainerName);
459
460   if (len >= 2)
461     if (strcmp(ContainerName + len - 2, "Py") == 0)
462       ret = true;
463
464   return ret;
465 }
466
467
468 //=============================================================================
469 /*!
470  *  Builds the script to be launched
471  *
472  *  If SALOME Application not defined ($APPLI),
473  *  see BuildTempFileToLaunchRemoteContainer()
474  *
475  *  Else rely on distant configuration. Command is under the form (example):
476  *  ssh user@machine distantPath/runRemote.sh hostNS portNS \
477  *                   SALOME_Container containerName &"
478
479  *  - where user is ommited if not specified in CatalogResources,
480  *  - where distant path is always relative to user@machine $HOME, and
481  *    equal to $APPLI if not specified in CatalogResources,
482  *  - where hostNS is the hostname of CORBA naming server (set by scripts to
483  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
484  *  - where portNS is the port used by CORBA naming server (set by scripts to
485  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
486  */ 
487 //=============================================================================
488
489 string
490 SALOME_ResourcesManager::BuildCommandToLaunchRemoteContainer
491 (const string& machine,
492  const Engines::MachineParameters& params, const long id)
493 {
494   string command;
495   int nbproc;
496   char idc[3*sizeof(long)];
497           
498   if ( ! _isAppliSalomeDefined )
499     command = BuildTempFileToLaunchRemoteContainer(machine, params);
500
501   else
502     {
503       const ParserResourcesType& resInfo = _resourcesList[machine];
504
505       if (params.isMPI)
506         {
507           if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
508             nbproc = 1;
509           else if ( params.nb_node == 0 )
510             nbproc = params.nb_proc_per_node;
511           else if ( params.nb_proc_per_node == 0 )
512             nbproc = params.nb_node;
513           else
514             nbproc = params.nb_node * params.nb_proc_per_node;
515         }
516
517       // "ssh user@machine distantPath/runRemote.sh hostNS portNS \
518       //  SALOME_Container containerName &"
519
520       if (resInfo.Protocol == rsh)
521         command = "rsh ";
522       else if (resInfo.Protocol == ssh)
523         command = "ssh ";
524       else
525         throw SALOME_Exception("Unknown protocol");
526
527       if (resInfo.UserName != "")
528         {
529           command += resInfo.UserName;
530           command += "@";
531         }
532
533       command += machine;
534       command += " ";
535
536       if (resInfo.AppliPath != "")
537         command += resInfo.AppliPath; // path relative to user@machine $HOME
538       else
539         {
540           ASSERT(getenv("APPLI"));
541           command += getenv("APPLI"); // path relative to user@machine $HOME
542         }
543
544       command += "/runRemote.sh ";
545
546       ASSERT(getenv("NSHOST")); 
547       command += getenv("NSHOST"); // hostname of CORBA name server
548
549       command += " ";
550       ASSERT(getenv("NSPORT"));
551       command += getenv("NSPORT"); // port of CORBA name server
552
553       if(params.isMPI)
554         {
555           command += " mpirun -np ";
556           std::ostringstream o;
557           o << nbproc << " ";
558           command += o.str();
559 #ifdef WITHLAM
560           command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
561 #endif  
562           command += " SALOME_MPIContainer ";
563         }
564       else
565         command += " SALOME_Container ";
566
567       command += _NS->ContainerName(params);
568       command += " -id ";
569       sprintf(idc,"%ld",id);
570       command += idc;
571       command += " -";
572       AddOmninamesParams(command);
573       command += " > /tmp/";
574       command += _NS->ContainerName(params);
575       command += "_";
576       command += GetHostname();
577       command += "_";
578       command += getenv( "USER" ) ;
579       command += ".log 2>&1 &" ;
580
581       MESSAGE("command =" << command);
582     }
583
584   return command;
585 }
586
587 //=============================================================================
588 /*!
589  *  builds the command to be launched.
590  */ 
591 //=============================================================================
592
593 string
594 SALOME_ResourcesManager::BuildCommandToLaunchLocalContainer
595 (const Engines::MachineParameters& params, const long id)
596 {
597   _TmpFileName = "";
598   string command;
599   int nbproc = 0;
600   char idc[3*sizeof(long)];
601
602   if (params.isMPI)
603     {
604       command = "mpirun -np ";
605
606       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
607         nbproc = 1;
608       else if ( params.nb_node == 0 )
609         nbproc = params.nb_proc_per_node;
610       else if ( params.nb_proc_per_node == 0 )
611         nbproc = params.nb_node;
612       else
613         nbproc = params.nb_node * params.nb_proc_per_node;
614
615       std::ostringstream o;
616
617       o << nbproc << " ";
618
619       command += o.str();
620 #ifdef WITHLAM
621       command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
622 #endif
623
624       if (isPythonContainer(params.container_name))
625         command += "pyMPI SALOME_ContainerPy.py ";
626       else
627         command += "SALOME_MPIContainer ";
628     }
629
630   else
631     {
632       if (isPythonContainer(params.container_name))
633         command = "SALOME_ContainerPy.py ";
634       else
635         command = "SALOME_Container ";
636     }
637
638   command += _NS->ContainerName(params);
639   command += " -id ";
640   sprintf(idc,"%ld",id);
641   command += idc;
642   command += " -";
643   AddOmninamesParams(command);
644   command += " > /tmp/";
645   command += _NS->ContainerName(params);
646   command += "_";
647   command += GetHostname();
648   command += "_";
649   command += getenv( "USER" ) ;
650   command += ".log 2>&1 &" ;
651   MESSAGE("Command is ... " << command);
652   return command;
653 }
654
655
656 //=============================================================================
657 /*!
658  *  removes the generated temporary file in case of a remote launch.
659  */ 
660 //=============================================================================
661
662 void SALOME_ResourcesManager::RmTmpFile()
663 {
664   if (_TmpFileName != "")
665     {
666 #ifndef WNT
667       string command = "rm ";
668 #else
669       string command = "del /F ";
670 #endif
671       command += _TmpFileName;
672       char *temp = strdup(command.c_str());
673       int lgthTemp = strlen(temp);
674       temp[lgthTemp - 3] = '*';
675       temp[lgthTemp - 2] = '\0';
676       system(temp);
677       free(temp);
678     }
679 }
680
681
682 //=============================================================================
683 /*!
684  *  builds the script to be launched
685  */ 
686 //=============================================================================
687
688 string
689 SALOME_ResourcesManager::BuildCommand
690 (const string& machine,
691  const char *containerName)
692 {
693   // rsh -n ikkyo /export/home/rahuel/SALOME_ROOT/bin/runSession SALOME_Container -ORBInitRef NameService=corbaname::dm2s0017:1515 &
694   const ParserResourcesType& resInfo = _resourcesList[machine];
695   bool pyCont = isPythonContainer(containerName);
696
697   string command;
698
699   if (resInfo.Protocol == rsh)
700     command = "rsh -n " ;
701   else if (resInfo.Protocol == ssh)
702     command = "ssh -f -n ";
703   else
704     throw SALOME_Exception("Not implemented yet...");
705
706   command += machine;
707   command += " ";
708   string path = getenv("KERNEL_ROOT_DIR");
709   command += path;
710   command += "/bin/salome/";
711
712   if ( pyCont )
713     command += "SALOME_ContainerPy.py ";
714   else
715     command += "SALOME_Container ";
716
717   command += containerName;
718   command += " -";
719   AddOmninamesParams(command);
720   command += " > /tmp/";
721   command += containerName;
722   command += "_";
723   command += machine;
724   command += "_";
725   command += getenv( "USER" ) ;
726   command += ".log 2>&1 &" ;
727
728   SCRUTE( command );
729   return command;
730 }
731
732 //=============================================================================
733 /*!
734  *  Gives a sublist of machines with matching OS.
735  *  If parameter OS is empty, gives the complete list of machines
736  */ 
737 //=============================================================================
738
739 // Warning need an updated parsed list : _resourcesList
740 void
741 SALOME_ResourcesManager::SelectOnlyResourcesWithOS
742 ( vector<string>& hosts,
743   const char *OS) const
744 throw(SALOME_Exception)
745 {
746   string base(OS);
747
748   for (map<string, ParserResourcesType>::const_iterator iter =
749          _resourcesList.begin();
750        iter != _resourcesList.end();
751        iter++)
752     {
753       if ( (*iter).second.OS == base || base.size() == 0)
754         hosts.push_back((*iter).first);
755     }
756 }
757
758
759 //=============================================================================
760 /*!
761  *  Gives a sublist of machines on which the module is known.
762  */ 
763 //=============================================================================
764
765 //Warning need an updated parsed list : _resourcesList
766 void
767 SALOME_ResourcesManager::KeepOnlyResourcesWithModule
768 ( vector<string>& hosts,
769   const Engines::CompoList& componentList) const
770 throw(SALOME_Exception)
771 {
772   for (vector<string>::iterator iter = hosts.begin(); iter != hosts.end();)
773     {
774       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
775       const vector<string>& mapOfModulesOfCurrentHost = (((*it).second).ModulesList);
776
777       bool erasedHost = false;
778       if( mapOfModulesOfCurrentHost.size() > 0 ){
779         for(int i=0;i<componentList.length();i++){
780           const char* compoi = componentList[i];
781           vector<string>::const_iterator itt = find(mapOfModulesOfCurrentHost.begin(),
782                                               mapOfModulesOfCurrentHost.end(),
783                                               compoi);
784 //                                            componentList[i]);
785           if (itt == mapOfModulesOfCurrentHost.end()){
786             erasedHost = true;
787             break;
788           }
789         }
790       }
791       if(erasedHost)
792         hosts.erase(iter);
793       else
794         iter++;
795     }
796 }
797
798
799 //=============================================================================
800 /*!
801  *   add to command all options relative to naming service.
802  */ 
803 //=============================================================================
804
805 void SALOME_ResourcesManager::AddOmninamesParams(string& command) const
806   {
807     // If env variable OMNIORB_CONFIG is not defined or the file is more complex than one line
808     // does not work
809     // Even if we use it we have to check if env variable exists
810     //string omniORBcfg( getenv( "OMNIORB_CONFIG" ) ) ;
811     //ifstream omniORBfile( omniORBcfg.c_str() ) ;
812     //char ORBInitRef[11] ;
813     //char egal[3] ;
814     //char nameservice[132] ;
815     //omniORBfile >> ORBInitRef ;
816     //command += "ORBInitRef " ;
817     //omniORBfile >> egal ;
818     //omniORBfile >> nameservice ;
819     //omniORBfile.close() ;
820     //char * bsn = strchr( nameservice , '\n' ) ;
821     //if ( bsn ) {
822     //bsn[ 0 ] = '\0' ;
823     //}
824     //command += nameservice ;
825
826     char *iorstr = _NS->getIORaddr();
827     command += "ORBInitRef NameService=";
828     command += iorstr;
829     //It's in fact a CORBA::String allocated with new [] !!!
830     delete [] iorstr;
831   }
832
833
834 //=============================================================================
835 /*!
836  *  add to command all options relative to naming service.
837  */ 
838 //=============================================================================
839
840 void SALOME_ResourcesManager::AddOmninamesParams(ofstream& fileStream) const
841   {
842     fileStream << "ORBInitRef NameService=";
843     fileStream << _NS->getIORaddr();
844   }
845
846
847 //=============================================================================
848 /*!
849  *  generate a file name in /tmp directory
850  */ 
851 //=============================================================================
852
853 string SALOME_ResourcesManager::BuildTemporaryFileName() const
854   {
855     //build more complex file name to support multiple salome session
856     char *temp = new char[19];
857     strcpy(temp, "/tmp/command");
858     strcat(temp, "XXXXXX");
859 #ifndef WNT
860
861     mkstemp(temp);
862 #else
863
864     char aPID[80];
865     itoa(getpid(), aPID, 10);
866     strcat(temp, aPID);
867 #endif
868
869     string command(temp);
870     delete [] temp;
871     command += ".sh";
872     return command;
873   }
874
875
876 //=============================================================================
877 /*!
878  *  Builds in a temporary file the script to be launched.
879  *  
880  *  Used if SALOME Application ($APPLI) is not defined.
881  *  The command is build with data from CatalogResources, in which every path
882  *  used on remote computer must be defined.
883  */ 
884 //=============================================================================
885
886 string
887 SALOME_ResourcesManager::BuildTempFileToLaunchRemoteContainer
888 (const string& machine,
889  const Engines::MachineParameters& params) throw(SALOME_Exception)
890 {
891   int status;
892
893   _TmpFileName = BuildTemporaryFileName();
894   ofstream tempOutputFile;
895   tempOutputFile.open(_TmpFileName.c_str(), ofstream::out );
896   const ParserResourcesType& resInfo = _resourcesList[machine];
897   tempOutputFile << "#! /bin/sh" << endl;
898
899   // --- set env vars
900
901   tempOutputFile << "export SALOME_trace=local" << endl; // mkr : 27.11.2006 : PAL13967 - Distributed supervision graphs - Problem with "SALOME_trace"
902   //tempOutputFile << "source " << resInfo.PreReqFilePath << endl;
903
904   // ! env vars
905
906   if (params.isMPI)
907     {
908       tempOutputFile << "mpirun -np ";
909       int nbproc;
910
911       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
912         nbproc = 1;
913       else if ( params.nb_node == 0 )
914         nbproc = params.nb_proc_per_node;
915       else if ( params.nb_proc_per_node == 0 )
916         nbproc = params.nb_node;
917       else
918         nbproc = params.nb_node * params.nb_proc_per_node;
919
920       std::ostringstream o;
921
922       tempOutputFile << nbproc << " ";
923 #ifdef WITHLAM
924       tempOutputFile << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
925 #endif
926     }
927
928   tempOutputFile << getenv("KERNEL_ROOT_DIR") << "/bin/salome/";
929
930   if (params.isMPI)
931     {
932       if (isPythonContainer(params.container_name))
933         tempOutputFile << "pyMPI SALOME_ContainerPy.py ";
934       else
935         tempOutputFile << "SALOME_MPIContainer ";
936     }
937
938   else
939     {
940       if (isPythonContainer(params.container_name))
941         tempOutputFile << "SALOME_ContainerPy.py ";
942       else
943         tempOutputFile << "SALOME_Container ";
944     }
945
946   tempOutputFile << _NS->ContainerName(params) << " -";
947   AddOmninamesParams(tempOutputFile);
948   tempOutputFile << " &" << endl;
949   tempOutputFile.flush();
950   tempOutputFile.close();
951   chmod(_TmpFileName.c_str(), 0x1ED);
952
953   // --- Build command
954
955   string command;
956
957   if (resInfo.Protocol == rsh)
958     {
959       command = "rsh ";
960       string commandRcp = "rcp ";
961       commandRcp += _TmpFileName;
962       commandRcp += " ";
963       commandRcp += machine;
964       commandRcp += ":";
965       commandRcp += _TmpFileName;
966       status = system(commandRcp.c_str());
967     }
968
969   else if (resInfo.Protocol == ssh)
970     {
971       command = "ssh ";
972       string commandRcp = "scp ";
973       commandRcp += _TmpFileName;
974       commandRcp += " ";
975       commandRcp += machine;
976       commandRcp += ":";
977       commandRcp += _TmpFileName;
978       status = system(commandRcp.c_str());
979     }
980   else
981     throw SALOME_Exception("Unknown protocol");
982
983   if(status)
984     throw SALOME_Exception("Error of connection on remote host");    
985
986   command += machine;
987   _CommandForRemAccess = command;
988   command += " ";
989   command += _TmpFileName;
990   command += " > ";
991   command += "/tmp/";
992   command += _NS->ContainerName(params);
993   command += "_";
994   command += machine;
995   command += "_";
996   command += getenv( "USER" ) ;
997   command += ".log 2>&1 &";
998   SCRUTE(command);
999
1000   return command;
1001
1002 }
1003
1004 //=============================================================================
1005 /*! Creates a command line that the container manager uses to launch
1006  * a parallel container.
1007  */ 
1008 //=============================================================================
1009 string 
1010 SALOME_ResourcesManager::BuildCommandToLaunchLocalParallelContainer(const std::string& exe_name,
1011                                                                     const Engines::MachineParameters& params,
1012                                                                     const std::string& log)
1013 {
1014   // This method knows the differences between the proxy and the nodes.
1015   // nb_component_nodes is not used in the same way if it is a proxy or 
1016   // a node.
1017
1018   string command;
1019   string parallelLib(CORBA::string_dup(params.parallelLib));
1020   string hostname(CORBA::string_dup(params.hostname));
1021   int par = exe_name.find("Proxy");
1022   int nbproc = params.nb_component_nodes;
1023   char buffer [33];
1024   sprintf(buffer,"%d",nbproc);
1025
1026   Engines::MachineParameters_var rtn = new Engines::MachineParameters();
1027   rtn->container_name = params.container_name;
1028   rtn->hostname = params.hostname;
1029   rtn->OS = params.OS;
1030   rtn->mem_mb = params.mem_mb;
1031   rtn->cpu_clock = params.cpu_clock;
1032   rtn->nb_proc_per_node = params.nb_proc_per_node;
1033   rtn->nb_node = params.nb_node;
1034   rtn->isMPI = params.isMPI;
1035
1036   string real_exe_name  = exe_name + parallelLib;
1037
1038   if (parallelLib == "Dummy")
1039   {
1040     //command = "gdb --args ";
1041     //command = "valgrind --tool=memcheck --log-file=val_log ";
1042     //command += real_exe_name;
1043
1044     command = real_exe_name;
1045
1046     command += " " + _NS->ContainerName(rtn);
1047     command += " " + parallelLib;
1048     command += " " + hostname;
1049     command += " -";
1050     AddOmninamesParams(command);
1051   }
1052
1053   else if (parallelLib == "Mpi")
1054   {
1055     // Step 1 : check if MPI is started
1056     if (_MpiStarted == false)
1057     {
1058       startMPI();
1059     }
1060
1061     if (par < 0)
1062     {
1063       // Nodes case
1064
1065       command = "mpiexec -np " + string(buffer) + " ";
1066 //      command += "gdb --args ";
1067       command += real_exe_name;
1068       command += " " + _NS->ContainerName(rtn);
1069       command += " " + parallelLib;
1070       command += " " + hostname;
1071       command += " -";
1072       AddOmninamesParams(command);
1073     }
1074     else                                          
1075     {
1076       // Proxy case
1077       command = "mpiexec -np 1 ";
1078       command += real_exe_name;
1079       command += " " + _NS->ContainerName(rtn);
1080       command += " " + string(buffer);
1081       command += " " + parallelLib;
1082       command += " " + hostname;
1083       command += " -";
1084       AddOmninamesParams(command);
1085     }
1086   }
1087   else
1088   {
1089     std::string message("Unknown parallelLib" + parallelLib);
1090     throw SALOME_Exception(message.c_str());
1091   }
1092
1093   // log choice
1094   if (log == "default")
1095   {
1096     command += " > /tmp/";
1097     command += _NS->ContainerName(rtn);
1098     command += "_";
1099     command += GetHostname();
1100     command += "_";
1101     command += getenv( "USER" ) ;
1102     command += ".log 2>&1 &" ;
1103   }
1104   if (log == "xterm")
1105   {
1106     command = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;  " 
1107               + command + " \" &";
1108 //            + command + "; echo $LD_LIBRARY_PATH; cat \" &";
1109   }
1110   return command;
1111
1112 /*  if (log == "xterm")
1113   {
1114     command = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH; echo $LD_LIBRARY_PATH; echo $PATH; " + command + "; cat \" &";
1115   }
1116 */
1117 /*  command = "cd ; rm " + fichier_commande + "; touch " + \
1118              fichier_commande + "; echo \" export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; " + \
1119              command + " >& /tmp/ribes_" + fichier_commande + " & \" > " + fichier_commande + ";";
1120   command += "ssh cn01 sh " + fichier_commande + " &";
1121   cerr << "La commande : " << command << endl;
1122 */
1123 }
1124
1125 void SALOME_ResourcesManager::startMPI()
1126 {
1127   cerr << "----------------------------------------------" << endl;
1128   cerr << "----------------------------------------------" << endl;
1129   cerr << "----------------------------------------------" << endl;
1130   cerr << "-Only Lam on Localhost is currently supported-" << endl;
1131   cerr << "----------------------------------------------" << endl;
1132   cerr << "----------------------------------------------" << endl;
1133   cerr << "----------------------------------------------" << endl;
1134
1135   int status = system("lamboot");
1136   if (status == -1)
1137   {
1138     INFOS("lamboot failed : system command status -1");
1139   }
1140   else if (status == 217)
1141   {
1142     INFOS("lamboot failed : system command status 217");
1143   }
1144   else
1145   {
1146     _MpiStarted = true;
1147   }
1148 }
1149
1150 Engines::MachineParameters* SALOME_ResourcesManager::GetMachineParameters(const char *hostname)
1151 {
1152   ParserResourcesType resource = _resourcesList[string(hostname)];
1153   Engines::MachineParameters *p_ptr = new Engines::MachineParameters;
1154   p_ptr->container_name = CORBA::string_dup("");
1155   p_ptr->hostname = CORBA::string_dup("hostname");
1156   p_ptr->alias = CORBA::string_dup(resource.Alias.c_str());
1157   if( resource.Protocol == rsh )
1158     p_ptr->protocol = "rsh";
1159   else if( resource.Protocol == ssh )
1160     p_ptr->protocol = "ssh";
1161   p_ptr->username = CORBA::string_dup(resource.UserName.c_str());
1162   p_ptr->applipath = CORBA::string_dup(resource.AppliPath.c_str());
1163   p_ptr->modList.length(resource.ModulesList.size());
1164   for(int i=0;i<resource.ModulesList.size();i++)
1165     p_ptr->modList[i] = CORBA::string_dup(resource.ModulesList[i].c_str());
1166   p_ptr->OS = CORBA::string_dup(resource.OS.c_str());
1167   p_ptr->mem_mb = resource.DataForSort._memInMB;
1168   p_ptr->cpu_clock = resource.DataForSort._CPUFreqMHz;
1169   p_ptr->nb_proc_per_node = resource.DataForSort._nbOfProcPerNode;
1170   p_ptr->nb_node = resource.DataForSort._nbOfNodes;
1171   if( resource.mpi == indif )
1172     p_ptr->mpiImpl = "indif";
1173   else if( resource.mpi == lam )
1174     p_ptr->mpiImpl = "lam";
1175   else if( resource.mpi == mpich1 )
1176     p_ptr->mpiImpl = "mpich1";
1177   else if( resource.mpi == mpich2 )
1178     p_ptr->mpiImpl = "mpich2";
1179   else if( resource.mpi == openmpi )
1180     p_ptr->mpiImpl = "openmpi";
1181   if( resource.Batch == pbs )
1182     p_ptr->batch = "pbs";
1183   else if( resource.Batch == lsf )
1184     p_ptr->batch = "lsf";
1185   else if( resource.Batch == slurm )
1186     p_ptr->batch = "slurm";
1187   return p_ptr;
1188 }