Salome HOME
Fix compilation pb.
[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   // Free the global variables that may have been allocated by the parser
362   xmlCleanupParser();
363   
364   fclose(aFile);
365   
366   MESSAGE("WRITING DONE!");
367 }
368
369 //=============================================================================
370 /*!
371  *  parse the data type catalog
372  */ 
373 //=============================================================================
374
375 const MapOfParserResourcesType& SALOME_ResourcesManager::ParseXmlFile()
376 {
377   SALOME_ResourcesCatalog_Handler* handler =
378     new SALOME_ResourcesCatalog_Handler(_resourcesList);
379
380   const char* aFilePath = _path_resources.c_str();
381   FILE* aFile = fopen(aFilePath, "r");
382   
383   if (aFile != NULL)
384     {
385       xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
386       
387       if (aDoc != NULL)
388         handler->ProcessXmlDocument(aDoc);
389       else
390         INFOS("ResourcesManager: could not parse file "<<aFilePath);
391       
392       // Free the document
393       xmlFreeDoc(aDoc);
394
395       // Free the global variables that may have been allocated by the parser
396       xmlCleanupParser();
397       fclose(aFile);
398     }
399   else
400     INFOS("ResourcesManager: file "<<aFilePath<<" is not readable.");
401   
402   delete handler;
403
404   return _resourcesList;
405 }
406
407 //=============================================================================
408 /*!
409  *   consult the content of the list
410  */ 
411 //=============================================================================
412
413 const MapOfParserResourcesType& SALOME_ResourcesManager::GetList() const
414   {
415     return _resourcesList;
416   }
417
418
419 //=============================================================================
420 /*!
421  *  dynamically obtains the first machines
422  */ 
423 //=============================================================================
424
425 char *
426 SALOME_ResourcesManager::FindFirst(const Engines::MachineList& listOfMachines)
427 {
428   return CORBA::string_dup(_dynamicResourcesSelecter.FindFirst(listOfMachines).c_str());
429 }
430
431 //=============================================================================
432 /*!
433  *  dynamically obtains the best machines
434  */ 
435 //=============================================================================
436
437 string
438 SALOME_ResourcesManager::FindNext(const Engines::MachineList& listOfMachines)
439 {
440   return _dynamicResourcesSelecter.FindNext(listOfMachines,_resourcesList,_NS);
441 }
442 //=============================================================================
443 /*!
444  *  dynamically obtains the best machines
445  */ 
446 //=============================================================================
447
448 string
449 SALOME_ResourcesManager::FindBest(const Engines::MachineList& listOfMachines)
450 {
451   return _dynamicResourcesSelecter.FindBest(listOfMachines);
452 }
453
454 //=============================================================================
455 /*!
456  *  This is no longer valid (C++ container are also python containers)
457  */ 
458 //=============================================================================
459
460 bool isPythonContainer(const char* ContainerName)
461 {
462   bool ret = false;
463   int len = strlen(ContainerName);
464
465   if (len >= 2)
466     if (strcmp(ContainerName + len - 2, "Py") == 0)
467       ret = true;
468
469   return ret;
470 }
471
472
473 //=============================================================================
474 /*!
475  *  Builds the script to be launched
476  *
477  *  If SALOME Application not defined ($APPLI),
478  *  see BuildTempFileToLaunchRemoteContainer()
479  *
480  *  Else rely on distant configuration. Command is under the form (example):
481  *  ssh user@machine distantPath/runRemote.sh hostNS portNS \
482  *                   SALOME_Container containerName &"
483
484  *  - where user is ommited if not specified in CatalogResources,
485  *  - where distant path is always relative to user@machine $HOME, and
486  *    equal to $APPLI if not specified in CatalogResources,
487  *  - where hostNS is the hostname of CORBA naming server (set by scripts to
488  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
489  *  - where portNS is the port used by CORBA naming server (set by scripts to
490  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
491  */ 
492 //=============================================================================
493
494 string
495 SALOME_ResourcesManager::BuildCommandToLaunchRemoteContainer
496 (const string& machine,
497  const Engines::MachineParameters& params, const long id)
498 {
499   string command;
500   int nbproc;
501   char idc[3*sizeof(long)];
502           
503   if ( ! _isAppliSalomeDefined )
504     command = BuildTempFileToLaunchRemoteContainer(machine, params);
505
506   else
507     {
508       const ParserResourcesType& resInfo = _resourcesList[machine];
509
510       if (params.isMPI)
511         {
512           if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
513             nbproc = 1;
514           else if ( params.nb_node == 0 )
515             nbproc = params.nb_proc_per_node;
516           else if ( params.nb_proc_per_node == 0 )
517             nbproc = params.nb_node;
518           else
519             nbproc = params.nb_node * params.nb_proc_per_node;
520         }
521
522       // "ssh user@machine distantPath/runRemote.sh hostNS portNS \
523       //  SALOME_Container containerName &"
524
525       if (resInfo.Protocol == rsh)
526         command = "rsh ";
527       else if (resInfo.Protocol == ssh)
528         command = "ssh ";
529       else
530         throw SALOME_Exception("Unknown protocol");
531
532       if (resInfo.UserName != "")
533         {
534           command += resInfo.UserName;
535           command += "@";
536         }
537
538       command += machine;
539       command += " ";
540
541       if (resInfo.AppliPath != "")
542         command += resInfo.AppliPath; // path relative to user@machine $HOME
543       else
544         {
545           ASSERT(getenv("APPLI"));
546           command += getenv("APPLI"); // path relative to user@machine $HOME
547         }
548
549       command += "/runRemote.sh ";
550
551       ASSERT(getenv("NSHOST")); 
552       command += getenv("NSHOST"); // hostname of CORBA name server
553
554       command += " ";
555       ASSERT(getenv("NSPORT"));
556       command += getenv("NSPORT"); // port of CORBA name server
557
558       if(params.isMPI)
559         {
560           command += " mpirun -np ";
561           std::ostringstream o;
562           o << nbproc << " ";
563           command += o.str();
564 #ifdef WITHLAM
565           command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
566 #endif  
567           command += " SALOME_MPIContainer ";
568         }
569       else
570         command += " SALOME_Container ";
571
572       command += _NS->ContainerName(params);
573       command += " -id ";
574       sprintf(idc,"%ld",id);
575       command += idc;
576       command += " -";
577       AddOmninamesParams(command);
578       command += " > /tmp/";
579       command += _NS->ContainerName(params);
580       command += "_";
581       command += GetHostname();
582       command += "_";
583       command += getenv( "USER" ) ;
584       command += ".log 2>&1 &" ;
585
586       MESSAGE("command =" << command);
587     }
588
589   return command;
590 }
591
592 //=============================================================================
593 /*!
594  *  builds the command to be launched.
595  */ 
596 //=============================================================================
597
598 string
599 SALOME_ResourcesManager::BuildCommandToLaunchLocalContainer
600 (const Engines::MachineParameters& params, const long id)
601 {
602   _TmpFileName = "";
603   string command;
604   int nbproc = 0;
605   char idc[3*sizeof(long)];
606
607   if (params.isMPI)
608     {
609       command = "mpirun -np ";
610
611       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
612         nbproc = 1;
613       else if ( params.nb_node == 0 )
614         nbproc = params.nb_proc_per_node;
615       else if ( params.nb_proc_per_node == 0 )
616         nbproc = params.nb_node;
617       else
618         nbproc = params.nb_node * params.nb_proc_per_node;
619
620       std::ostringstream o;
621
622       o << nbproc << " ";
623
624       command += o.str();
625 #ifdef WITHLAM
626       command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
627 #endif
628
629       if (isPythonContainer(params.container_name))
630         command += "pyMPI SALOME_ContainerPy.py ";
631       else
632         command += "SALOME_MPIContainer ";
633     }
634
635   else
636     {
637       if (isPythonContainer(params.container_name))
638         command = "SALOME_ContainerPy.py ";
639       else
640         command = "SALOME_Container ";
641     }
642
643   command += _NS->ContainerName(params);
644   command += " -id ";
645   sprintf(idc,"%ld",id);
646   command += idc;
647   command += " -";
648   AddOmninamesParams(command);
649   command += " > /tmp/";
650   command += _NS->ContainerName(params);
651   command += "_";
652   command += GetHostname();
653   command += "_";
654   command += getenv( "USER" ) ;
655   command += ".log 2>&1 &" ;
656   MESSAGE("Command is ... " << command);
657   return command;
658 }
659
660
661 //=============================================================================
662 /*!
663  *  removes the generated temporary file in case of a remote launch.
664  */ 
665 //=============================================================================
666
667 void SALOME_ResourcesManager::RmTmpFile()
668 {
669   if (_TmpFileName != "")
670     {
671 #ifndef WNT
672       string command = "rm ";
673 #else
674       string command = "del /F ";
675 #endif
676       command += _TmpFileName;
677       char *temp = strdup(command.c_str());
678       int lgthTemp = strlen(temp);
679       temp[lgthTemp - 3] = '*';
680       temp[lgthTemp - 2] = '\0';
681       system(temp);
682       free(temp);
683     }
684 }
685
686
687 //=============================================================================
688 /*!
689  *  builds the script to be launched
690  */ 
691 //=============================================================================
692
693 string
694 SALOME_ResourcesManager::BuildCommand
695 (const string& machine,
696  const char *containerName)
697 {
698   // rsh -n ikkyo /export/home/rahuel/SALOME_ROOT/bin/runSession SALOME_Container -ORBInitRef NameService=corbaname::dm2s0017:1515 &
699   const ParserResourcesType& resInfo = _resourcesList[machine];
700   bool pyCont = isPythonContainer(containerName);
701
702   string command;
703
704   if (resInfo.Protocol == rsh)
705     command = "rsh -n " ;
706   else if (resInfo.Protocol == ssh)
707     command = "ssh -f -n ";
708   else
709     throw SALOME_Exception("Not implemented yet...");
710
711   command += machine;
712   command += " ";
713   string path = getenv("KERNEL_ROOT_DIR");
714   command += path;
715   command += "/bin/salome/";
716
717   if ( pyCont )
718     command += "SALOME_ContainerPy.py ";
719   else
720     command += "SALOME_Container ";
721
722   command += containerName;
723   command += " -";
724   AddOmninamesParams(command);
725   command += " > /tmp/";
726   command += containerName;
727   command += "_";
728   command += machine;
729   command += "_";
730   command += getenv( "USER" ) ;
731   command += ".log 2>&1 &" ;
732
733   SCRUTE( command );
734   return command;
735 }
736
737 //=============================================================================
738 /*!
739  *  Gives a sublist of machines with matching OS.
740  *  If parameter OS is empty, gives the complete list of machines
741  */ 
742 //=============================================================================
743
744 // Warning need an updated parsed list : _resourcesList
745 void
746 SALOME_ResourcesManager::SelectOnlyResourcesWithOS
747 ( vector<string>& hosts,
748   const char *OS) const
749 throw(SALOME_Exception)
750 {
751   string base(OS);
752
753   for (map<string, ParserResourcesType>::const_iterator iter =
754          _resourcesList.begin();
755        iter != _resourcesList.end();
756        iter++)
757     {
758       if ( (*iter).second.OS == base || base.size() == 0)
759         hosts.push_back((*iter).first);
760     }
761 }
762
763
764 //=============================================================================
765 /*!
766  *  Gives a sublist of machines on which the module is known.
767  */ 
768 //=============================================================================
769
770 //Warning need an updated parsed list : _resourcesList
771 void
772 SALOME_ResourcesManager::KeepOnlyResourcesWithModule
773 ( vector<string>& hosts,
774   const Engines::CompoList& componentList) const
775 throw(SALOME_Exception)
776 {
777   for (vector<string>::iterator iter = hosts.begin(); iter != hosts.end();)
778     {
779       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
780       const vector<string>& mapOfModulesOfCurrentHost = (((*it).second).ModulesList);
781
782       bool erasedHost = false;
783       if( mapOfModulesOfCurrentHost.size() > 0 ){
784         for(int i=0;i<componentList.length();i++){
785           const char* compoi = componentList[i];
786           vector<string>::const_iterator itt = find(mapOfModulesOfCurrentHost.begin(),
787                                               mapOfModulesOfCurrentHost.end(),
788                                               compoi);
789 //                                            componentList[i]);
790           if (itt == mapOfModulesOfCurrentHost.end()){
791             erasedHost = true;
792             break;
793           }
794         }
795       }
796       if(erasedHost)
797         hosts.erase(iter);
798       else
799         iter++;
800     }
801 }
802
803
804 //=============================================================================
805 /*!
806  *   add to command all options relative to naming service.
807  */ 
808 //=============================================================================
809
810 void SALOME_ResourcesManager::AddOmninamesParams(string& command) const
811   {
812     // If env variable OMNIORB_CONFIG is not defined or the file is more complex than one line
813     // does not work
814     // Even if we use it we have to check if env variable exists
815     //string omniORBcfg( getenv( "OMNIORB_CONFIG" ) ) ;
816     //ifstream omniORBfile( omniORBcfg.c_str() ) ;
817     //char ORBInitRef[11] ;
818     //char egal[3] ;
819     //char nameservice[132] ;
820     //omniORBfile >> ORBInitRef ;
821     //command += "ORBInitRef " ;
822     //omniORBfile >> egal ;
823     //omniORBfile >> nameservice ;
824     //omniORBfile.close() ;
825     //char * bsn = strchr( nameservice , '\n' ) ;
826     //if ( bsn ) {
827     //bsn[ 0 ] = '\0' ;
828     //}
829     //command += nameservice ;
830
831     char *iorstr = _NS->getIORaddr();
832     command += "ORBInitRef NameService=";
833     command += iorstr;
834   }
835
836
837 //=============================================================================
838 /*!
839  *  add to command all options relative to naming service.
840  */ 
841 //=============================================================================
842
843 void SALOME_ResourcesManager::AddOmninamesParams(ofstream& fileStream) const
844   {
845     fileStream << "ORBInitRef NameService=";
846     fileStream << _NS->getIORaddr();
847   }
848
849
850 //=============================================================================
851 /*!
852  *  generate a file name in /tmp directory
853  */ 
854 //=============================================================================
855
856 string SALOME_ResourcesManager::BuildTemporaryFileName() const
857   {
858     //build more complex file name to support multiple salome session
859     char *temp = new char[19];
860     strcpy(temp, "/tmp/command");
861     strcat(temp, "XXXXXX");
862 #ifndef WNT
863
864     mkstemp(temp);
865 #else
866
867     char aPID[80];
868     itoa(getpid(), aPID, 10);
869     strcat(temp, aPID);
870 #endif
871
872     string command(temp);
873     delete [] temp;
874     command += ".sh";
875     return command;
876   }
877
878
879 //=============================================================================
880 /*!
881  *  Builds in a temporary file the script to be launched.
882  *  
883  *  Used if SALOME Application ($APPLI) is not defined.
884  *  The command is build with data from CatalogResources, in which every path
885  *  used on remote computer must be defined.
886  */ 
887 //=============================================================================
888
889 string
890 SALOME_ResourcesManager::BuildTempFileToLaunchRemoteContainer
891 (const string& machine,
892  const Engines::MachineParameters& params) throw(SALOME_Exception)
893 {
894   int status;
895
896   _TmpFileName = BuildTemporaryFileName();
897   ofstream tempOutputFile;
898   tempOutputFile.open(_TmpFileName.c_str(), ofstream::out );
899   const ParserResourcesType& resInfo = _resourcesList[machine];
900   tempOutputFile << "#! /bin/sh" << endl;
901
902   // --- set env vars
903
904   tempOutputFile << "export SALOME_trace=local" << endl; // mkr : 27.11.2006 : PAL13967 - Distributed supervision graphs - Problem with "SALOME_trace"
905   //tempOutputFile << "source " << resInfo.PreReqFilePath << endl;
906
907   // ! env vars
908
909   if (params.isMPI)
910     {
911       tempOutputFile << "mpirun -np ";
912       int nbproc;
913
914       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
915         nbproc = 1;
916       else if ( params.nb_node == 0 )
917         nbproc = params.nb_proc_per_node;
918       else if ( params.nb_proc_per_node == 0 )
919         nbproc = params.nb_node;
920       else
921         nbproc = params.nb_node * params.nb_proc_per_node;
922
923       std::ostringstream o;
924
925       tempOutputFile << nbproc << " ";
926 #ifdef WITHLAM
927       tempOutputFile << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
928 #endif
929     }
930
931   tempOutputFile << getenv("KERNEL_ROOT_DIR") << "/bin/salome/";
932
933   if (params.isMPI)
934     {
935       if (isPythonContainer(params.container_name))
936         tempOutputFile << "pyMPI SALOME_ContainerPy.py ";
937       else
938         tempOutputFile << "SALOME_MPIContainer ";
939     }
940
941   else
942     {
943       if (isPythonContainer(params.container_name))
944         tempOutputFile << "SALOME_ContainerPy.py ";
945       else
946         tempOutputFile << "SALOME_Container ";
947     }
948
949   tempOutputFile << _NS->ContainerName(params) << " -";
950   AddOmninamesParams(tempOutputFile);
951   tempOutputFile << " &" << endl;
952   tempOutputFile.flush();
953   tempOutputFile.close();
954   chmod(_TmpFileName.c_str(), 0x1ED);
955
956   // --- Build command
957
958   string command;
959
960   if (resInfo.Protocol == rsh)
961     {
962       command = "rsh ";
963       string commandRcp = "rcp ";
964       commandRcp += _TmpFileName;
965       commandRcp += " ";
966       commandRcp += machine;
967       commandRcp += ":";
968       commandRcp += _TmpFileName;
969       status = system(commandRcp.c_str());
970     }
971
972   else if (resInfo.Protocol == ssh)
973     {
974       command = "ssh ";
975       string commandRcp = "scp ";
976       commandRcp += _TmpFileName;
977       commandRcp += " ";
978       commandRcp += machine;
979       commandRcp += ":";
980       commandRcp += _TmpFileName;
981       status = system(commandRcp.c_str());
982     }
983   else
984     throw SALOME_Exception("Unknown protocol");
985
986   if(status)
987     throw SALOME_Exception("Error of connection on remote host");    
988
989   command += machine;
990   _CommandForRemAccess = command;
991   command += " ";
992   command += _TmpFileName;
993   command += " > ";
994   command += "/tmp/";
995   command += _NS->ContainerName(params);
996   command += "_";
997   command += machine;
998   command += "_";
999   command += getenv( "USER" ) ;
1000   command += ".log 2>&1 &";
1001   SCRUTE(command);
1002
1003   return command;
1004
1005 }
1006
1007 //=============================================================================
1008 /*! Creates a command line that the container manager uses to launch
1009  * a parallel container.
1010  */ 
1011 //=============================================================================
1012 string 
1013 SALOME_ResourcesManager::BuildCommandToLaunchLocalParallelContainer(const std::string& exe_name,
1014                                                                     const Engines::MachineParameters& params,
1015                                                                     const std::string& log)
1016 {
1017   // This method knows the differences between the proxy and the nodes.
1018   // nb_component_nodes is not used in the same way if it is a proxy or 
1019   // a node.
1020
1021   string command;
1022   string parallelLib(CORBA::string_dup(params.parallelLib));
1023   string hostname(CORBA::string_dup(params.hostname));
1024   int par = exe_name.find("Proxy");
1025   int nbproc = params.nb_component_nodes;
1026   char buffer [33];
1027   sprintf(buffer,"%d",nbproc);
1028
1029   Engines::MachineParameters_var rtn = new Engines::MachineParameters();
1030   rtn->container_name = params.container_name;
1031   rtn->hostname = params.hostname;
1032   rtn->OS = params.OS;
1033   rtn->mem_mb = params.mem_mb;
1034   rtn->cpu_clock = params.cpu_clock;
1035   rtn->nb_proc_per_node = params.nb_proc_per_node;
1036   rtn->nb_node = params.nb_node;
1037   rtn->isMPI = params.isMPI;
1038
1039   string real_exe_name  = exe_name + parallelLib;
1040
1041   if (parallelLib == "Dummy")
1042   {
1043     //command = "gdb --args ";
1044     //command = "valgrind --tool=memcheck --log-file=val_log ";
1045     //command += real_exe_name;
1046     
1047     command = real_exe_name;
1048     
1049     command += " " + _NS->ContainerName(rtn);
1050     command += " " + parallelLib;
1051     command += " " + hostname;
1052     command += " -";
1053     AddOmninamesParams(command);
1054   }
1055
1056   if (parallelLib == "Mpi")
1057   {
1058     // Step 1 : check if MPI is started
1059     if (_MpiStarted == false)
1060     {
1061       startMPI();
1062     }
1063
1064     if (par < 0)
1065     {
1066       // Nodes case
1067
1068       command = "mpiexec -np " + string(buffer) + " ";
1069 //      command += "gdb --args ";
1070       command += real_exe_name;
1071       command += " " + _NS->ContainerName(rtn);
1072       command += " " + parallelLib;
1073       command += " " + hostname;
1074       command += " -";
1075       AddOmninamesParams(command);
1076     }
1077     else                                          
1078     {
1079       // Proxy case
1080       command = "mpiexec -np 1 ";
1081       command += real_exe_name;
1082       command += " " + _NS->ContainerName(rtn);
1083       command += " " + string(buffer);
1084       command += " " + parallelLib;
1085       command += " " + hostname;
1086       command += " -";
1087       AddOmninamesParams(command);
1088     }
1089   }
1090
1091   // log choice
1092   if (log == "default")
1093   {
1094     command += " > /tmp/";
1095     command += _NS->ContainerName(rtn);
1096     command += "_";
1097     command += GetHostname();
1098     command += "_";
1099     command += getenv( "USER" ) ;
1100     command += ".log 2>&1 &" ;
1101   }
1102   if (log == "xterm")
1103   {
1104     command = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;  " 
1105               + command + " \" &";
1106 //            + command + "; echo $LD_LIBRARY_PATH; cat \" &";
1107   }
1108   return command;
1109
1110 /*  if (log == "xterm")
1111   {
1112     command = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH; echo $LD_LIBRARY_PATH; echo $PATH; " + command + "; cat \" &";
1113   }
1114 */
1115 /*  command = "cd ; rm " + fichier_commande + "; touch " + \
1116              fichier_commande + "; echo \" export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; " + \
1117              command + " >& /tmp/ribes_" + fichier_commande + " & \" > " + fichier_commande + ";";
1118   command += "ssh cn01 sh " + fichier_commande + " &";
1119   cerr << "La commande : " << command << endl;
1120 */
1121 }
1122
1123 void SALOME_ResourcesManager::startMPI()
1124 {
1125   cerr << "----------------------------------------------" << endl;
1126   cerr << "----------------------------------------------" << endl;
1127   cerr << "----------------------------------------------" << endl;
1128   cerr << "-Only Lam on Localhost is currently supported-" << endl;
1129   cerr << "----------------------------------------------" << endl;
1130   cerr << "----------------------------------------------" << endl;
1131   cerr << "----------------------------------------------" << endl;
1132
1133   int status = system("lamboot");
1134   if (status == -1)
1135   {
1136     INFOS("lamboot failed : system command status -1");
1137   }
1138   else if (status == 217)
1139   {
1140     INFOS("lamboot failed : system command status 217");
1141   }
1142   else
1143   {
1144     _MpiStarted = true;
1145   }
1146 }
1147
1148 Engines::MachineParameters* SALOME_ResourcesManager::GetMachineParameters(const char *hostname)
1149 {
1150   ParserResourcesType resource = _resourcesList[string(hostname)];
1151   Engines::MachineParameters *p_ptr = new Engines::MachineParameters;
1152   p_ptr->container_name = CORBA::string_dup("");
1153   p_ptr->hostname = CORBA::string_dup("hostname");
1154   p_ptr->alias = CORBA::string_dup(resource.Alias.c_str());
1155   if( resource.Protocol == rsh )
1156     p_ptr->protocol = "rsh";
1157   else if( resource.Protocol == ssh )
1158     p_ptr->protocol = "ssh";
1159   p_ptr->username = CORBA::string_dup(resource.UserName.c_str());
1160   p_ptr->applipath = CORBA::string_dup(resource.AppliPath.c_str());
1161   p_ptr->modList.length(resource.ModulesList.size());
1162   for(int i=0;i<resource.ModulesList.size();i++)
1163     p_ptr->modList[i] = CORBA::string_dup(resource.ModulesList[i].c_str());
1164   p_ptr->OS = CORBA::string_dup(resource.OS.c_str());
1165   p_ptr->mem_mb = resource.DataForSort._memInMB;
1166   p_ptr->cpu_clock = resource.DataForSort._CPUFreqMHz;
1167   p_ptr->nb_proc_per_node = resource.DataForSort._nbOfProcPerNode;
1168   p_ptr->nb_node = resource.DataForSort._nbOfNodes;
1169   if( resource.mpi == indif )
1170     p_ptr->mpiImpl = "indif";
1171   else if( resource.mpi == lam )
1172     p_ptr->mpiImpl = "lam";
1173   else if( resource.mpi == mpich1 )
1174     p_ptr->mpiImpl = "mpich1";
1175   else if( resource.mpi == mpich2 )
1176     p_ptr->mpiImpl = "mpich2";
1177   else if( resource.mpi == openmpi )
1178     p_ptr->mpiImpl = "openmpi";
1179   if( resource.Batch == pbs )
1180     p_ptr->batch = "pbs";
1181   else if( resource.Batch == lsf )
1182     p_ptr->batch = "lsf";
1183   else if( resource.Batch == slurm )
1184     p_ptr->batch = "slurm";
1185   return p_ptr;
1186 }