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