]> SALOME platform Git repositories - modules/kernel.git/blob - src/ResourcesManager/SALOME_ResourcesManager.cxx
Salome HOME
PR: merge from branch BR_UT_V310a2 tag BR_UT_V310a2_20051115
[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)
361 {
362   string command;
363
364   if ( ! _isAppliSalomeDefined )
365     command = BuildTempFileToLaunchRemoteContainer(machine, params);
366
367   else
368     {
369       const ParserResourcesType& resInfo = _resourcesList[machine];
370
371       if (params.isMPI)
372         {
373           int nbproc;
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       command += " SALOME_Container ";
422       command += _NS->ContainerName(params);
423       command += "&";
424
425       MESSAGE("command =" << command);
426     }
427
428   return command;
429 }
430
431
432 //=============================================================================
433 /*!
434  *  builds the command to be launched.
435  */ 
436 //=============================================================================
437
438 string
439 SALOME_ResourcesManager::BuildCommandToLaunchLocalContainer
440 (const Engines::MachineParameters& params)
441 {
442   _TmpFileName = "";
443   string command;
444   int nbproc = 0;
445
446   if (params.isMPI)
447     {
448       command = "mpirun -np ";
449
450       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
451         nbproc = 1;
452       else if ( params.nb_node == 0 )
453         nbproc = params.nb_proc_per_node;
454       else if ( params.nb_proc_per_node == 0 )
455         nbproc = params.nb_node;
456       else
457         nbproc = params.nb_node * params.nb_proc_per_node;
458
459       std::ostringstream o;
460
461       o << nbproc << " ";
462
463       command += o.str();
464       command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
465
466       if (isPythonContainer(params.container_name))
467         command += "pyMPI SALOME_ContainerPy.py ";
468       else
469         command += "SALOME_MPIContainer ";
470     }
471
472   else
473     {
474       if (isPythonContainer(params.container_name))
475         command = "SALOME_ContainerPy.py ";
476       else
477         command = "SALOME_Container ";
478     }
479
480   command += _NS->ContainerName(params);
481   command += " -";
482   AddOmninamesParams(command);
483   command += " > /tmp/";
484   command += _NS->ContainerName(params);
485   command += "_";
486   command += GetHostname();
487   command += "_";
488   command += getenv( "USER" ) ;
489   command += ".log 2>&1 &" ;
490   MESSAGE("Command is ... " << command);
491   return command;
492 }
493
494
495 //=============================================================================
496 /*!
497  *  removes the generated temporary file in case of a remote launch.
498  */ 
499 //=============================================================================
500
501 void SALOME_ResourcesManager::RmTmpFile()
502 {
503   if (_TmpFileName != "")
504     {
505       string command = "rm ";
506       command += _TmpFileName;
507       char *temp = strdup(command.c_str());
508       int lgthTemp = strlen(temp);
509       temp[lgthTemp - 3] = '*';
510       temp[lgthTemp - 2] = '\0';
511       system(temp);
512       free(temp);
513     }
514 }
515
516
517 //=============================================================================
518 /*!
519  *  builds the script to be launched
520  */ 
521 //=============================================================================
522
523 string
524 SALOME_ResourcesManager::BuildCommand
525 (const string& machine,
526  const char *containerName)
527 {
528   // rsh -n ikkyo /export/home/rahuel/SALOME_ROOT/bin/runSession SALOME_Container -ORBInitRef NameService=corbaname::dm2s0017:1515 &
529   const ParserResourcesType& resInfo = _resourcesList[machine];
530   bool pyCont = isPythonContainer(containerName);
531
532   string command;
533
534   if (resInfo.Protocol == rsh)
535     command = "rsh -n " ;
536   else if (resInfo.Protocol == ssh)
537     command = "ssh -f -n ";
538   else
539     throw SALOME_Exception("Not implemented yet...");
540
541   command += machine;
542   command += " ";
543   string path = (*(resInfo.ModulesPath.find("KERNEL"))).second;
544   command += path;
545   command += "/bin/salome/";
546
547   if ( pyCont )
548     command += "SALOME_ContainerPy.py ";
549   else
550     command += "SALOME_Container ";
551
552   command += containerName;
553   command += " -";
554   AddOmninamesParams(command);
555   command += " > /tmp/";
556   command += containerName;
557   command += "_";
558   command += machine;
559   command += ".log 2>&1 &" ;
560
561   SCRUTE( command );
562   return command;
563 }
564
565 //=============================================================================
566 /*!
567  *  Gives a sublist of machines with matching OS.
568  *  If parameter OS is empty, gives the complete list of machines
569  */ 
570 //=============================================================================
571
572 // Warning need an updated parsed list : _resourcesList
573 void
574 SALOME_ResourcesManager::SelectOnlyResourcesWithOS
575 ( vector<string>& hosts,
576   const char *OS) const
577 throw(SALOME_Exception)
578 {
579   string base(OS);
580
581   for (map<string, ParserResourcesType>::const_iterator iter =
582          _resourcesList.begin();
583        iter != _resourcesList.end();
584        iter++)
585     {
586       if ( (*iter).second.OS == base || base.size() == 0)
587         hosts.push_back((*iter).first);
588     }
589 }
590
591
592 //=============================================================================
593 /*!
594  *  Gives a sublist of machines on which the module is known.
595  */ 
596 //=============================================================================
597
598 //Warning need an updated parsed list : _resourcesList
599 void
600 SALOME_ResourcesManager::KeepOnlyResourcesWithModule
601 ( vector<string>& hosts,
602   const char *moduleName) const
603 throw(SALOME_Exception)
604 {
605   for (vector<string>::iterator iter = hosts.begin(); iter != hosts.end();)
606     {
607       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
608       const map<string, string>& mapOfModulesOfCurrentHost =
609         (((*it).second).ModulesPath);
610
611       if (mapOfModulesOfCurrentHost.find(moduleName) ==
612           mapOfModulesOfCurrentHost.end())
613         hosts.erase(iter);
614       else
615         iter++;
616     }
617 }
618
619
620 //=============================================================================
621 /*!
622  *   add to command all options relative to naming service.
623  */ 
624 //=============================================================================
625
626 void SALOME_ResourcesManager::AddOmninamesParams(string& command) const
627   {
628     // If env variable OMNIORB_CONFIG is not defined or the file is more complex than one line
629     // does not work
630     // Even if we use it we have to check if env variable exists
631     //string omniORBcfg( getenv( "OMNIORB_CONFIG" ) ) ;
632     //ifstream omniORBfile( omniORBcfg.c_str() ) ;
633     //char ORBInitRef[11] ;
634     //char egal[3] ;
635     //char nameservice[132] ;
636     //omniORBfile >> ORBInitRef ;
637     //command += "ORBInitRef " ;
638     //omniORBfile >> egal ;
639     //omniORBfile >> nameservice ;
640     //omniORBfile.close() ;
641     //char * bsn = strchr( nameservice , '\n' ) ;
642     //if ( bsn ) {
643     //bsn[ 0 ] = '\0' ;
644     //}
645     //command += nameservice ;
646
647     char *iorstr = _NS->getIORaddr();
648     command += "ORBInitRef NameService=";
649     command += iorstr;
650   }
651
652
653 //=============================================================================
654 /*!
655  *  add to command all options relative to naming service.
656  */ 
657 //=============================================================================
658
659 void SALOME_ResourcesManager::AddOmninamesParams(ofstream& fileStream) const
660   {
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     fileStream << "ORBInitRef ";
668     omniORBfile >> egal ;
669     omniORBfile >> nameservice ;
670     omniORBfile.close() ;
671     char * bsn = strchr( nameservice , '\n' ) ;
672
673     if ( bsn )
674       {
675         bsn[ 0 ] = '\0' ;
676       }
677
678     fileStream << nameservice;
679   }
680
681
682 //=============================================================================
683 /*!
684  *  generate a file name in /tmp directory
685  */ 
686 //=============================================================================
687
688 string SALOME_ResourcesManager::BuildTemporaryFileName() const
689   {
690     //build more complex file name to support multiple salome session
691     char *temp = new char[19];
692     strcpy(temp, "/tmp/command");
693     strcat(temp, "XXXXXX");
694 #ifndef WNT
695
696     mkstemp(temp);
697 #else
698
699     char aPID[80];
700     itoa(getpid(), aPID, 10);
701     strcat(temp, aPID);
702 #endif
703
704     string command(temp);
705     delete [] temp;
706     command += ".sh";
707     return command;
708   }
709
710
711 //=============================================================================
712 /*!
713  *  Builds in a temporary file the script to be launched.
714  *  
715  *  Used if SALOME Application ($APPLI) is not defined.
716  *  The command is build with data from CatalogResources, in which every path
717  *  used on remote computer must be defined.
718  */ 
719 //=============================================================================
720
721 string
722 SALOME_ResourcesManager::BuildTempFileToLaunchRemoteContainer
723 (const string& machine,
724  const Engines::MachineParameters& params)
725 {
726   _TmpFileName = BuildTemporaryFileName();
727   ofstream tempOutputFile;
728   tempOutputFile.open(_TmpFileName.c_str(), ofstream::out );
729   const ParserResourcesType& resInfo = _resourcesList[machine];
730   tempOutputFile << "#! /bin/sh" << endl;
731
732   // --- set env vars
733
734   for (map<string, string>::const_iterator iter = resInfo.ModulesPath.begin();
735        iter != resInfo.ModulesPath.end();
736        iter++)
737     {
738       string curModulePath((*iter).second);
739       tempOutputFile << (*iter).first << "_ROOT_DIR=" << curModulePath << endl;
740       tempOutputFile << "export " << (*iter).first << "_ROOT_DIR" << endl;
741       tempOutputFile << "LD_LIBRARY_PATH=" << curModulePath
742                      << "/lib/salome" << ":${LD_LIBRARY_PATH}" << endl;
743       tempOutputFile << "PYTHONPATH=" << curModulePath << "/bin/salome:"
744                      << curModulePath << "/lib/salome:" << curModulePath
745                      << "/lib/python2.2/site-packages/salome:";
746       tempOutputFile << curModulePath
747       << "/lib/python2.2/site-packages/salome/shared_modules:${PYTHONPATH}"
748       << endl;
749     }
750
751   tempOutputFile << "export LD_LIBRARY_PATH" << endl;
752   tempOutputFile << "export PYTHONPATH" << endl;
753   tempOutputFile << "source " << resInfo.PreReqFilePath << endl;
754
755   // ! env vars
756
757   if (params.isMPI)
758     {
759       tempOutputFile << "mpirun -np ";
760       int nbproc;
761
762       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
763         nbproc = 1;
764       else if ( params.nb_node == 0 )
765         nbproc = params.nb_proc_per_node;
766       else if ( params.nb_proc_per_node == 0 )
767         nbproc = params.nb_node;
768       else
769         nbproc = params.nb_node * params.nb_proc_per_node;
770
771       std::ostringstream o;
772
773       tempOutputFile << nbproc << " ";
774     }
775
776   tempOutputFile << (*(resInfo.ModulesPath.find("KERNEL"))).second
777                  << "/bin/salome/";
778
779   if (params.isMPI)
780     {
781       if (isPythonContainer(params.container_name))
782         tempOutputFile << "pyMPI SALOME_ContainerPy.py ";
783       else
784         tempOutputFile << "SALOME_MPIContainer ";
785     }
786
787   else
788     {
789       if (isPythonContainer(params.container_name))
790         tempOutputFile << "SALOME_ContainerPy.py ";
791       else
792         tempOutputFile << "SALOME_Container ";
793     }
794
795   tempOutputFile << _NS->ContainerName(params) << " -";
796   AddOmninamesParams(tempOutputFile);
797   tempOutputFile << " &" << endl;
798   tempOutputFile.flush();
799   tempOutputFile.close();
800   chmod(_TmpFileName.c_str(), 0x1ED);
801
802   // --- Build command
803
804   string command;
805
806   if (resInfo.Protocol == rsh)
807     {
808       command = "rsh ";
809       string commandRcp = "rcp ";
810       commandRcp += _TmpFileName;
811       commandRcp += " ";
812       commandRcp += machine;
813       commandRcp += ":";
814       commandRcp += _TmpFileName;
815       system(commandRcp.c_str());
816     }
817
818   else if (resInfo.Protocol == ssh)
819     command = "ssh ";
820   else
821     throw SALOME_Exception("Unknown protocol");
822
823   command += machine;
824   _CommandForRemAccess = command;
825   command += " ";
826   command += _TmpFileName;
827   command += " > ";
828   command += "/tmp/";
829   command += _NS->ContainerName(params);
830   command += "_";
831   command += machine;
832   command += ".log 2>&1 &";
833   SCRUTE(command);
834
835   return command;
836
837 }
838
839
840
841