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