Salome HOME
Porting to Mandrake 10.1 and new products:
[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 #include <unistd.h>
10 #include <fstream>
11 #include <iostream>
12 #include <string.h>
13 #include <map>
14 #include <list>
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18
19 #define MAX_SIZE_FOR_HOSTNAME 256;
20
21 using namespace std;
22
23 //just for test
24 SALOME_ResourcesManager::SALOME_ResourcesManager(const char *xmlFilePath):_path_resources(xmlFilePath)
25 {
26 }
27
28 SALOME_ResourcesManager::SALOME_ResourcesManager()
29 {
30   _path_resources=getenv("KERNEL_ROOT_DIR");
31   _path_resources+="/share/salome/resources/CatalogResources.xml";
32   ParseXmlFile();
33 }
34
35 SALOME_ResourcesManager::~SALOME_ResourcesManager()
36 {
37 }
38
39 vector<string> SALOME_ResourcesManager::GetFittingResources(const Engines::MachineParameters& params,const char *moduleName) throw(SALOME_Exception)
40 {
41   vector <std::string> ret;
42   //To be sure that we search in a correct list.
43   ParseXmlFile();
44   const char *hostname=(const char *)params.hostname;
45   if(hostname[0]!='\0')
46     {
47       if(_resourcesList.find(hostname)!=_resourcesList.end())
48         // params.hostame is in the list of resources so return it.
49         ret.push_back(hostname);
50       else
51         //user specified an unknown hostame so notify to him.
52         throw SALOME_Exception("unknown host");
53     }
54   else
55     // Search for available resources sorted by priority
56     {
57       SelectOnlyResourcesWithOS(ret,params.OS);
58       KeepOnlyResourcesWithModule(ret,moduleName);
59       //set wanted parameters
60       ResourceDataToSort::_nbOfNodesWanted=params.nb_node;
61       ResourceDataToSort::_nbOfProcPerNodeWanted=params.nb_proc_per_node;
62       ResourceDataToSort::_CPUFreqMHzWanted=params.cpu_clock;
63       ResourceDataToSort::_memInMBWanted=params.mem_mb;
64       //end of set
65       list<ResourceDataToSort> li;
66       for(vector<string>::iterator iter=ret.begin();iter!=ret.end();iter++)
67         li.push_back(_resourcesList[(*iter)].DataForSort);
68       li.sort();
69       unsigned int i=0;
70       for(list<ResourceDataToSort>::iterator iter2=li.begin();iter2!=li.end();iter2++)
71         ret[i++]=(*iter2)._hostName;
72     }
73   return ret;
74 }
75
76 int SALOME_ResourcesManager::AddResourceInCatalog(const Engines::MachineParameters& paramsOfNewResources, const map<string,string>& modulesOnNewResources,
77                                                   const char *environPathOfPrerequired,
78                                                   const char *alias, const char *userName, AccessModeType mode, AccessProtocolType prot) throw(SALOME_Exception)
79 {
80   map<string,string>::const_iterator iter=modulesOnNewResources.find("KERNEL");
81   if(iter!=modulesOnNewResources.end())
82     {
83       ParserResourcesType newElt;
84       newElt.DataForSort._hostName=paramsOfNewResources.hostname;
85       newElt.Alias=alias;
86       newElt.Protocol=prot;
87       newElt.Mode=mode;
88       newElt.UserName=userName;
89       newElt.ModulesPath=modulesOnNewResources;
90       newElt.PreReqFilePath=environPathOfPrerequired;
91       newElt.OS=paramsOfNewResources.OS;
92       newElt.DataForSort._memInMB=paramsOfNewResources.mem_mb;
93       newElt.DataForSort._CPUFreqMHz=paramsOfNewResources.cpu_clock;
94       newElt.DataForSort._nbOfNodes=paramsOfNewResources.nb_node;
95       newElt.DataForSort._nbOfProcPerNode=paramsOfNewResources.nb_proc_per_node;
96       _resourcesList[newElt.DataForSort._hostName]=newElt;
97       return 0;
98     }
99   else
100     throw SALOME_Exception("KERNEL is not present in this resource");
101 }
102
103 void SALOME_ResourcesManager::DeleteResourceInCatalog(const char *hostname)
104 {
105   _resourcesList.erase(hostname);
106 }
107
108 void SALOME_ResourcesManager::WriteInXmlFile()
109 {
110   QDomDocument doc("ResourcesCatalog");
111   SALOME_ResourcesCatalog_Handler* handler = new SALOME_ResourcesCatalog_Handler(_resourcesList);
112   handler->PrepareDocToXmlFile(doc);
113   delete handler;
114   QFile file( _path_resources );
115   if( !file.open( IO_WriteOnly ) )
116     cout << "WRITING ERROR !!!" << endl;
117
118   QTextStream ts( &file );
119   ts << doc.toString();
120
121   file.close();
122   cout << "WRITING DONE!!!" << endl;
123 }
124
125 const MapOfParserResourcesType& SALOME_ResourcesManager::ParseXmlFile() 
126 {
127   SALOME_ResourcesCatalog_Handler* handler = new SALOME_ResourcesCatalog_Handler(_resourcesList);
128   QFile xmlFile(_path_resources);
129
130   QXmlInputSource source(xmlFile);
131
132   QXmlSimpleReader reader;
133   reader.setContentHandler( handler );
134   reader.setErrorHandler( handler );
135   reader.parse( source );
136   xmlFile.close();
137   delete handler;
138   return _resourcesList;
139 }
140
141 bool SALOME_ResourcesManager::_verify_resources(MapOfParserResourcesType resourceslist)
142 {
143 //     bool _return_value = true;
144 //     bool _bool = false ;
145 //     vector<string> _machine_list;
146 //     _machine_list.resize(0);
147
148 //   // Fill a list of all computers indicated in the resources list
149 //   for (unsigned int ind = 0; ind < resourceslist.size(); ind++)
150 //           _machine_list.push_back(resourceslist[ind].HostName);   
151
152 //   // Parse if a computer name is twice in the list of computers
153 //   for (unsigned int ind = 0; ind < _machine_list.size(); ind++)
154 //     {
155 //      for (unsigned int ind1 = ind+1 ; ind1 < _machine_list.size(); ind1++)
156 //        {
157 //          if(_machine_list[ind].compare(_machine_list[ind1]) == 0)
158 //            {
159 //              MESSAGE("The computer " << _machine_list[ind] << " is indicated more than once in the resources list")
160 //              _return_value = false;
161 //           }
162 //        }
163 //     }
164
165 //    return _return_value;
166   return true;
167 }
168
169 const MapOfParserResourcesType& SALOME_ResourcesManager::GetList() const
170 {
171   return _resourcesList;
172 }
173
174 string SALOME_ResourcesManager::FindBest(const Engines::MachineList& listOfMachines)
175 {
176   return _dynamicResourcesSelecter.FindBest(listOfMachines);
177 }
178
179 string SALOME_ResourcesManager::BuildTempFileToLaunchRemoteContainer(const string& machine,const char *containerName)
180 {
181   _TmpFileName=BuildTemporaryFileName();
182   ofstream tempOutputFile;
183   tempOutputFile.open(_TmpFileName.c_str(),ofstream::out );
184   const ParserResourcesType& resInfo=_resourcesList[machine];
185   tempOutputFile << "#! /bin/sh" << endl;
186   //set env vars
187   for(map<string,string>::const_iterator iter=resInfo.ModulesPath.begin();iter!=resInfo.ModulesPath.end();iter++)
188     {
189       string curModulePath((*iter).second);
190       tempOutputFile << (*iter).first << "_ROOT_DIR="<< curModulePath << endl;
191       tempOutputFile << "export " << (*iter).first << "_ROOT_DIR" << endl;
192       tempOutputFile << "LD_LIBRARY_PATH=" << curModulePath << "/lib/salome" << ":${LD_LIBRARY_PATH}" << endl;
193       tempOutputFile << "PYTHONPATH=" << curModulePath << "/bin/salome:" << curModulePath << "/lib/salome:" << curModulePath << "/lib/python2.2/site-packages/salome:";
194       tempOutputFile << curModulePath << "/lib/python2.2/site-packages/salome/shared_modules:${PYTHONPATH}" << endl;
195     }
196   tempOutputFile << "export LD_LIBRARY_PATH" << endl;
197   tempOutputFile << "export PYTHONPATH" << endl;
198   tempOutputFile << "source " << resInfo.PreReqFilePath << endl;
199   // ! env vars
200   tempOutputFile << (*(resInfo.ModulesPath.find("KERNEL"))).second << "/bin/salome/";
201   if(Engines_Container_i::isPythonContainer(containerName))
202     tempOutputFile << "SALOME_ContainerPy.py ";
203   else
204     tempOutputFile << "SALOME_Container ";
205   tempOutputFile << containerName << " -";
206   AddOmninamesParams(tempOutputFile);
207   tempOutputFile << " &" << endl;
208   tempOutputFile.flush();
209   tempOutputFile.close();
210   chmod(_TmpFileName.c_str(),0x1ED);
211   //Build command
212   string command;
213   if(resInfo.Protocol==rsh)
214     {
215       command = "rsh ";
216       string commandRcp="rcp ";
217       commandRcp+=_TmpFileName;
218       commandRcp+=" ";
219       commandRcp+=machine;
220       commandRcp+=":";
221       commandRcp+=_TmpFileName;
222       system(commandRcp.c_str());
223     }
224   else if(resInfo.Protocol==ssh)
225     command = "ssh ";
226   else
227     throw SALOME_Exception("Unknown protocol");
228   command+=machine;
229   _CommandForRemAccess=command;
230   command+=" ";
231   command+=_TmpFileName;
232   command += " > ";
233   command += "/tmp/";
234   command += containerName;
235   command += "_";
236   command += machine;
237   command += ".log &";
238   cout << "Command is ... " << command << endl;
239   return command;
240 }
241
242 string SALOME_ResourcesManager::BuildCommandToLaunchLocalContainer(const char *containerName)
243 {
244   _TmpFileName="";
245   string command;
246   if(Engines_Container_i::isPythonContainer(containerName))
247     command="SALOME_ContainerPy.py ";
248   else
249     command="SALOME_Container ";
250   command+=containerName;
251   command+=" -";
252   AddOmninamesParams(command);
253   command+=" > /tmp/";
254   command+=containerName;
255   command += "_";
256   command += GetHostname();
257   command += ".log 2>&1 &" ;
258   cout << "Command is ... " << command << endl << flush;
259   return command;
260 }
261
262 void SALOME_ResourcesManager::RmTmpFile()
263 {
264   if(_TmpFileName!="")
265     {
266       string command="rm ";
267       command+=_TmpFileName;
268       char *temp=strdup(command.c_str());
269       int lgthTemp=strlen(temp);
270       temp[lgthTemp-3]='*';
271       temp[lgthTemp-2]='\0';
272       system(temp);
273       free(temp);
274     }
275 }
276
277 string SALOME_ResourcesManager::BuildCommand(const string& machine,const char *containerName)
278 {
279 // rsh -n ikkyo /export/home/rahuel/SALOME_ROOT/bin/runSession SALOME_Container -ORBInitRef NameService=corbaname::dm2s0017:1515 &
280   const ParserResourcesType& resInfo=_resourcesList[machine];
281   bool pyCont=Engines_Container_i::isPythonContainer(containerName);
282   string command;
283   if(resInfo.Protocol==rsh)
284     command = "rsh -n " ;
285   else if(resInfo.Protocol==ssh)
286     command = "ssh -f -n ";
287   else
288     throw SALOME_Exception("Not implemented yet...");
289       command += machine;
290   command += " ";
291   string path = (*(resInfo.ModulesPath.find("KERNEL"))).second;
292   command +=path;
293   command += "/bin/salome/";
294   if ( pyCont )
295     command += "SALOME_ContainerPy.py ";
296   else
297     command += "SALOME_Container ";
298   command += containerName;
299   command += " -";
300   AddOmninamesParams(command);
301   command += " > /tmp/";
302   command += containerName;
303   command += "_";
304   command += machine;
305   command += ".log 2>&1 &" ;
306   SCRUTE( command );
307   return command;
308 }
309
310 // Warning need an updated parsed list : _resourcesList
311 void SALOME_ResourcesManager::SelectOnlyResourcesWithOS(vector<string>& hosts,const char *OS) const throw(SALOME_Exception)
312 {
313   string base(OS);
314   for(map<string, ParserResourcesType>::const_iterator iter=_resourcesList.begin();iter!=_resourcesList.end();iter++)
315     if((*iter).second.OS==base)
316       hosts.push_back((*iter).first);
317 }
318
319 //Warning need an updated parsed list : _resourcesList
320 void SALOME_ResourcesManager::KeepOnlyResourcesWithModule(vector<string>& hosts,const char *moduleName) const throw(SALOME_Exception)
321 {
322    for(vector<string>::iterator iter=hosts.begin();iter!=hosts.end();)
323      {
324        MapOfParserResourcesType::const_iterator it=_resourcesList.find(*iter);
325        const map<string,string>& mapOfModulesOfCurrentHost=(((*it).second).ModulesPath);
326        if(mapOfModulesOfCurrentHost.find(moduleName)==mapOfModulesOfCurrentHost.end())
327          hosts.erase(iter);
328        else
329          iter++;
330      }
331 }
332
333 void SALOME_ResourcesManager::AddOmninamesParams(string& command) const
334 {
335   string omniORBcfg( getenv( "OMNIORB_CONFIG" ) ) ;
336   ifstream omniORBfile( omniORBcfg.c_str() ) ;
337   char ORBInitRef[12] ;
338   char nameservice[132] ;
339   omniORBfile >> ORBInitRef ;
340   command += ORBInitRef ;
341   command += " " ;
342   omniORBfile >> nameservice ;
343   omniORBfile.close() ;
344   char * bsn = strchr( nameservice , '\n' ) ;
345   if ( bsn ) {
346     bsn[ 0 ] = '\0' ;
347   }
348   command += nameservice ;
349 }
350
351 void SALOME_ResourcesManager::AddOmninamesParams(ofstream& fileStream) const
352 {
353   string omniORBcfg( getenv( "OMNIORB_CONFIG" ) ) ;
354   ifstream omniORBfile( omniORBcfg.c_str() ) ;
355   char ORBInitRef[12] ;
356   char nameservice[132] ;
357   omniORBfile >> ORBInitRef ;
358   fileStream << ORBInitRef;
359   fileStream << " ";
360   omniORBfile >> nameservice ;
361   omniORBfile.close() ;
362   char * bsn = strchr( nameservice , '\n' ) ;
363   if ( bsn ) {
364     bsn[ 0 ] = '\0' ;
365   }
366   fileStream << nameservice;
367 }
368
369 string SALOME_ResourcesManager::BuildTemporaryFileName() const
370 {
371   //build more complex file name to support multiple salome session
372   char *temp=new char[19];
373   strcpy(temp,"/tmp/command");
374   strcat(temp,"XXXXXX");
375   mkstemp(temp);
376   string command(temp);
377   delete [] temp;
378   command += ".sh";
379   return command;
380 }
381
382