Salome HOME
22156a57b05ae2bdebf21a418c8970bde76d2d4f
[modules/kernel.git] / src / ResourcesManager / ResourcesManager.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "ResourcesManager.hxx" 
24
25 #include "SALOME_ResourcesCatalog_Handler.hxx"
26 #include <Basics_Utils.hxx>
27 #include <Basics_DirUtils.hxx>
28 #include "utilities.h"
29
30 #include <fstream>
31 #include <iostream>
32 #include <sstream>
33 #include <string.h>
34 #include <map>
35 #include <list>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #ifdef WIN32
39 #else
40 #include <unistd.h>
41 #endif
42 #include <libxml/parser.h>
43
44 #include <algorithm>
45
46 #define MAX_SIZE_FOR_HOSTNAME 256;
47
48 using namespace std;
49
50 const string ResourcesManager_cpp::DEFAULT_RESOURCE_NAME = "localhost";
51
52 static LoadRateManagerFirst first;
53 static LoadRateManagerCycl cycl;
54 static LoadRateManagerAltCycl altcycl;
55
56 resourceParams::resourceParams()
57 : can_launch_batch_jobs(false),
58   can_run_containers(false),
59   nb_proc(-1),
60   nb_node(0),
61   nb_proc_per_node(-1),
62   cpu_clock(-1),
63   mem_mb(-1)
64 {
65 }
66
67 //=============================================================================
68 /*!
69  * just for test
70  */ 
71 //=============================================================================
72
73 ResourcesManager_cpp::
74 ResourcesManager_cpp(const char *xmlFilePath)
75 {
76   _path_resources.push_back(xmlFilePath);
77 #if defined(_DEBUG_) || defined(_DEBUG)
78   std::cerr << "ResourcesManager_cpp constructor" << std::endl;
79 #endif
80   _resourceManagerMap["first"]=&first;
81   _resourceManagerMap["cycl"]=&cycl;
82   _resourceManagerMap["altcycl"]=&altcycl;
83   _resourceManagerMap["best"]=&altcycl;
84   _resourceManagerMap[""]=&altcycl;
85
86   AddDefaultResourceInCatalog();
87   ParseXmlFiles();
88 }
89
90 //=============================================================================
91 /*!
92  *  Standard constructor, parse resource file.
93  *  - if ${APPLI} exists in environment,
94  *    look for ${HOME}/${APPLI}/CatalogResources.xml
95  *  - else look for default:
96  *    ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
97  *  - parse XML resource file.
98  */ 
99 //=============================================================================
100
101 ResourcesManager_cpp::ResourcesManager_cpp()
102 {
103   RES_MESSAGE("ResourcesManager_cpp constructor");
104
105   _resourceManagerMap["first"]=&first;
106   _resourceManagerMap["cycl"]=&cycl;
107   _resourceManagerMap["altcycl"]=&altcycl;
108   _resourceManagerMap["best"]=&altcycl;
109   _resourceManagerMap[""]=&altcycl;
110
111   AddDefaultResourceInCatalog();
112
113   bool default_catalog_resource = true;
114   if (getenv("USER_CATALOG_RESOURCES_FILE") != 0)
115   {
116     default_catalog_resource = false;
117     std::string user_file("");
118     user_file = getenv("USER_CATALOG_RESOURCES_FILE");
119     std::ifstream ifile(user_file.c_str(), std::ifstream::in );
120     if (ifile) {
121       // The file exists, and is open for input
122       DEBUG_MESSAGE("USER_CATALOG_RESOURCES_FILE positioned -> add it into resourcefiles list");
123       _path_resources.push_back(user_file);
124     }
125     else {
126       default_catalog_resource = false;
127       WARNING_MESSAGE("Warning: USER_CATALOG_RESOURCES_FILE is set and file cannot be found.")
128       WARNING_MESSAGE("Warning: That's why we try to create a new one.")
129       std::ofstream user_catalog_file;
130       user_catalog_file.open(user_file.c_str());
131       if (user_catalog_file.fail())
132       {
133         WARNING_MESSAGE("Error: cannot write in the user catalog resources files");
134         WARNING_MESSAGE("Error: using default CatalogResources.xml file");
135         default_catalog_resource = true;
136       }
137       else
138       {
139         user_catalog_file << "<!-- File created by SALOME -->" << std::endl;
140         user_catalog_file << "<!DOCTYPE ResourcesCatalog>" << std::endl;
141         user_catalog_file << "<resources>" << std::endl;
142         user_catalog_file << "   <machine name=\"localhost\" hostname=\"localhost\" />" << std::endl;
143         user_catalog_file << "</resources>" << std::endl;
144         user_catalog_file.close();
145       }
146     }
147   }
148   if (default_catalog_resource)
149   {
150     std::string default_file("");
151     if (getenv("APPLI") != 0)
152     {
153       default_file += Kernel_Utils::HomePath();
154       default_file += "/";
155       default_file += getenv("APPLI");
156       default_file += "/CatalogResources.xml";
157       std::ifstream ifile(default_file.c_str(), std::ifstream::in );
158       if (ifile) {
159         // The file exists, and is open for input
160         DEBUG_MESSAGE("${APPLI}/CatalogResources.xml exists -> add it into resourcefiles list");
161         _path_resources.push_back(default_file);
162         default_catalog_resource=false;
163       }
164     }
165   }
166   if (default_catalog_resource)
167   {
168     std::string default_file("");
169     if(!getenv("KERNEL_ROOT_DIR"))
170       throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml");
171     default_file = getenv("KERNEL_ROOT_DIR");
172     default_file += "/share/salome/resources/kernel/CatalogResources.xml";
173     DEBUG_MESSAGE("${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml -> add it into resourcefiles list");
174     _path_resources.push_back(default_file);
175   }
176
177   ParseXmlFiles();
178   RES_MESSAGE("ResourcesManager_cpp constructor end");
179 }
180
181 //=============================================================================
182 /*!
183  *  Standard Destructor
184  */ 
185 //=============================================================================
186
187 ResourcesManager_cpp::~ResourcesManager_cpp()
188 {
189   RES_MESSAGE("ResourcesManager_cpp destructor");
190 }
191
192 //=============================================================================
193 //! get the list of resource names fitting constraints given by params
194 /*!
195  * Steps:
196  * 1: Restrict list with resourceList if defined
197  * 2: If name is defined -> check resource list
198  * 3: If not 2:, if hostname is defined -> check resource list
199  * 4: If not 3:, sort resource with nb_proc, etc...
200  * 5: In all cases remove resource that does not correspond with OS
201  * 6: And remove resource with componentList - if list is empty ignored it...
202  */ 
203 //=============================================================================
204
205 std::vector<std::string> 
206 ResourcesManager_cpp::GetFittingResources(const resourceParams& params) 
207 {
208   RES_MESSAGE("[GetFittingResources] on computer " << Kernel_Utils::GetHostname().c_str());
209   RES_MESSAGE("[GetFittingResources] with resource name: " << params.name);
210   RES_MESSAGE("[GetFittingResources] with hostname: "<< params.hostname);
211
212   // Result
213   std::vector<std::string> vec;
214
215   // Parse Again CalatogResource File
216   ParseXmlFiles();
217
218   // Steps:
219   // 1: If name is defined -> check resource list
220   // 2: Restrict list with resourceList if defined
221   // 3: If not 2:, if hostname is defined -> check resource list
222   // 4: If not 3:, sort resource with nb_proc, etc...
223   // 5: In all cases remove resource that does not correspond with OS
224   // 6: And remove resource with componentList - if list is empty ignored it...
225
226   // Step 1
227   if (params.name != "")
228   {
229     RES_MESSAGE("[GetFittingResources] name parameter found !");
230     if (_resourcesList.find(params.name) != _resourcesList.end())
231     {
232       vec.push_back(params.name);
233       return vec;
234     }
235     else
236       RES_MESSAGE("[GetFittingResources] resource name was not found on resource list ! name requested was " << params.name);
237       std::string error("[GetFittingResources] resource name was not found on resource list ! name requested was " + params.name);
238       throw ResourcesException(error);
239   }
240
241   MapOfParserResourcesType local_resourcesList = _resourcesList;
242   // Step 2
243   if (params.resourceList.size() > 0)
244   {
245     RES_MESSAGE("[GetFittingResources] Restricted resource list found !");
246     local_resourcesList.clear();
247     std::vector<std::string>::size_type sz = params.resourceList.size();
248
249     for (unsigned int i=0; i < sz; i++)
250     {
251       if (_resourcesList.find(params.resourceList[i]) != _resourcesList.end())
252         local_resourcesList[params.resourceList[i]] = _resourcesList[params.resourceList[i]];
253     }
254   }
255
256   // Step 3
257   if (params.hostname != "")
258   {
259     RES_MESSAGE("[GetFittingResources] Entering in hostname case !");
260
261     std::string hostname = params.hostname;
262     if (hostname ==  "localhost")
263       hostname = Kernel_Utils::GetHostname().c_str();
264
265     std::map<std::string, ParserResourcesType>::const_iterator iter = _resourcesList.begin();
266     for (; iter != _resourcesList.end(); iter++)
267     {
268       if ((*iter).second.HostName == hostname)
269         vec.push_back((*iter).first);
270     }
271   }
272   // Step 4
273   else
274   {
275     // --- Search for available resources sorted by priority
276     MapOfParserResourcesType_it i = local_resourcesList.begin();
277     for (; i != local_resourcesList.end(); ++i)
278       vec.push_back(i->first);
279
280     // --- set wanted parameters
281     ResourceDataToSort::_nbOfProcWanted = params.nb_proc;
282     ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
283     ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
284     ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
285     ResourceDataToSort::_memInMBWanted = params.mem_mb;
286     // --- end of set
287         
288     // Sort
289     std::list<ResourceDataToSort> li;
290     std::vector<std::string>::iterator iter = vec.begin();
291     for (; iter != vec.end(); iter++)
292       li.push_back(local_resourcesList[(*iter)].DataForSort);
293     li.sort();
294
295     vec.clear();
296     for (std::list<ResourceDataToSort>::iterator iter2 = li.begin(); iter2 != li.end(); iter2++)
297       vec.push_back((*iter2)._Name);
298   }
299
300   // Step 5
301   SelectOnlyResourcesWithOS(vec, params.OS.c_str());
302
303   // Step 6
304   std::vector<std::string> vec_save(vec);
305   KeepOnlyResourcesWithComponent(vec, params.componentList);
306   if (vec.size() == 0)
307     vec = vec_save;
308
309   // Step 7 : Filter on possible usage
310   vector<string> prev_list(vec);
311   vec.clear();
312   for (vector<string>::iterator iter = prev_list.begin() ; iter != prev_list.end() ; iter++)
313   {
314     MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
315     if (it != _resourcesList.end() &&
316         (!params.can_launch_batch_jobs || it->second.can_launch_batch_jobs) &&
317         (!params.can_run_containers || it->second.can_run_containers))
318       vec.push_back(*iter);
319   }
320
321   // End
322   // Send an exception if return list is empty...
323   if (vec.size() == 0)
324   {
325     std::string error("[GetFittingResources] ResourcesManager doesn't find any resource that fits to your parameters");
326     throw ResourcesException(error);
327   }
328
329   return vec;
330 }
331
332 //=============================================================================
333 /*!
334  *  add an entry in the resources catalog xml file.
335  */ 
336 //=============================================================================
337
338 void
339 ResourcesManager_cpp::AddResourceInCatalog(const ParserResourcesType & new_resource)
340 {
341   if (new_resource.Name == DEFAULT_RESOURCE_NAME){
342     ParserResourcesType default_resource = _resourcesList[DEFAULT_RESOURCE_NAME];
343     // some of the properties of the default resource shouldn't be modified
344     std::string check;
345     if( default_resource.HostName != new_resource.HostName)
346       check += "The Hostname property of the default resource can not be modified.\n";
347     if( default_resource.AppliPath != new_resource.AppliPath)
348       check += "The Applipath property of the default resource can not be modified.\n";
349     if( !new_resource.can_run_containers)
350       check += "The default resource should be able to run containers.\n";
351     if( !new_resource.can_launch_batch_jobs)
352       check += "The default resource should be able to launch batch jobs.\n";
353     if( default_resource.Protocol != new_resource.Protocol)
354       check += "The Protocol property of the default resource can not be modified.\n";
355     if(!check.empty())
356       throw ResourcesException(check);
357   }
358   // TODO - Add minimal check
359   _resourcesList[new_resource.Name] = new_resource;
360 }
361
362 void ResourcesManager_cpp::DeleteAllResourcesInCatalog()
363 {
364   _resourcesList.clear();
365 }
366
367 //=============================================================================
368 /*!
369  *  Deletes a resource from the catalog
370  */ 
371 //=============================================================================
372
373 void ResourcesManager_cpp::DeleteResourceInCatalog(const char * name)
374 {
375   if (DEFAULT_RESOURCE_NAME == name){
376     std::string error("Cannot delete default local resource \"" + DEFAULT_RESOURCE_NAME + "\"");
377     throw ResourcesException(error);
378   }
379   MapOfParserResourcesType_it it = _resourcesList.find(name);
380   if (it != _resourcesList.end())
381     _resourcesList.erase(name);
382   else
383     RES_INFOS("You try to delete a resource that does not exist... : " << name);
384 }
385
386 //=============================================================================
387 /*!
388  *  write the current data in memory in file.
389  */ 
390 //=============================================================================
391
392 void ResourcesManager_cpp::WriteInXmlFile(std::string xml_file)
393 {
394   RES_MESSAGE("WriteInXmlFile : start");
395
396   MapOfParserResourcesType resourceListToSave(_resourcesList);
397   if (resourceListToSave.empty())
398   {
399     RES_MESSAGE("WriteInXmlFile: nothing to do, no resource to save!");
400     return;
401   }
402
403   if (xml_file == "")
404   {
405     _path_resources_it = _path_resources.begin();
406     xml_file = *_path_resources_it;
407   }
408
409   const char* aFilePath = xml_file.c_str();
410   FILE* aFile = fopen(aFilePath, "w");
411
412   if (aFile == NULL)
413   {
414     std::cerr << "Error opening file in WriteInXmlFile : " << xml_file << std::endl;
415     return;
416   }
417   
418   xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
419   xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
420
421   SALOME_ResourcesCatalog_Handler* handler =
422     new SALOME_ResourcesCatalog_Handler(resourceListToSave);
423   handler->PrepareDocToXmlFile(aDoc);
424   delete handler;
425
426   int isOk = xmlSaveFormatFile(aFilePath, aDoc, 1);
427   if (!isOk) 
428      std::cerr << "Error while XML file saving : " << xml_file << std::endl;
429   
430   // Free the document
431   xmlFreeDoc(aDoc);
432   fclose(aFile);
433   RES_MESSAGE("WriteInXmlFile : WRITING DONE!");
434 }
435
436 //=============================================================================
437 /*!
438  *  parse the data type catalog
439  */ 
440 //=============================================================================
441
442 const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles()
443 {
444   // Parse file only if its modification time is greater than lasttime (last registered modification time)
445   bool to_parse = false;
446   for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
447   {
448     struct stat statinfo;
449     int result = stat((*_path_resources_it).c_str(), &statinfo);
450     if (result < 0)
451     {
452       WARNING_MESSAGE("Resource file " << *_path_resources_it << " does not exist -> no parsing");
453       return _resourcesList;
454     }
455
456     if(_lasttime == 0 || statinfo.st_mtime > _lasttime)
457     {
458       DEBUG_MESSAGE("Resource file " << *_path_resources_it << " has been detected to be present and newer than Resources in memory");
459       to_parse = true;
460       _lasttime = statinfo.st_mtime;
461     }
462   }
463
464   if (to_parse)
465   {
466     DEBUG_MESSAGE("After analyze of resoure files time meta data, a load of resources from scratch from files is necessary.");
467     _resourcesList.clear();
468     AddDefaultResourceInCatalog();
469     // On parse tous les fichiers
470     for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
471     {
472       MapOfParserResourcesType _resourcesList_tmp;
473       MapOfParserResourcesType _resourcesBatchList_tmp;
474       std::unique_ptr<SALOME_ResourcesCatalog_Handler> handler( new SALOME_ResourcesCatalog_Handler(_resourcesList_tmp) );
475       const char *aFilePath( (*_path_resources_it).c_str() );
476       FILE* aFile = fopen(aFilePath, "r");
477       if (aFile != NULL)
478       {
479         xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
480         if (aDoc != NULL)
481         {
482           DEBUG_MESSAGE("XML parsing of Resource file \"" << aFilePath << "\"");
483           handler->ProcessXmlDocument(aDoc);
484
485           // adding new resources to the file
486           for (MapOfParserResourcesType_it i = _resourcesList_tmp.begin(); i != _resourcesList_tmp.end(); ++i)
487           {
488             MapOfParserResourcesType_it j = _resourcesList.find(i->first);
489             if (i->second.HostName == DEFAULT_RESOURCE_NAME || i->second.HostName == Kernel_Utils::GetHostname())
490             {
491               DEBUG_MESSAGE("Resource \"" << i->first << "\" in file \"" << aFilePath << "\" is detected as localhost");
492               MapOfParserResourcesType_it it0(_resourcesList.find(DEFAULT_RESOURCE_NAME));
493               if(it0!=_resourcesList.end())
494                 {
495                   DEBUG_MESSAGE("Resource \"" << i->first << "\" in file \"" << aFilePath << "\" detected as localhost is already in memory -> update resource with content in file ( for attributes : nbOfNodes, nbOfProcPerNode, CPUFreqMHz and memInMB)");
496                   ParserResourcesType& localhostElt((*it0).second);
497                   localhostElt.DataForSort._nbOfNodes=(*i).second.DataForSort._nbOfNodes;
498                   localhostElt.DataForSort._nbOfProcPerNode=(*i).second.DataForSort._nbOfProcPerNode;
499                   localhostElt.DataForSort._CPUFreqMHz=(*i).second.DataForSort._CPUFreqMHz;
500                   localhostElt.DataForSort._memInMB=(*i).second.DataForSort._memInMB;
501                 }
502               DEBUG_MESSAGE("Resource \"" << i->first << "\" is not added because it is the same machine as default local resource \"" << DEFAULT_RESOURCE_NAME << "\"");
503             }
504             else if (j != _resourcesList.end())
505             {
506               WARNING_MESSAGE("ParseXmlFiles Warning, two resources with the same name were found, taking the first declaration : " << i->first );
507             }
508             else
509             {
510               DEBUG_MESSAGE("Resource \"" << i->first << "\" added");
511               _resourcesList[i->first] = i->second;
512             }
513           }
514         }
515         else
516           ERROR_MESSAGE( "ResourcesManager_cpp: could not parse file " << aFilePath );
517         // Free the document
518         xmlFreeDoc(aDoc);
519         fclose(aFile);
520       }
521       else
522         ERROR_MESSAGE( "ResourcesManager_cpp: file " << aFilePath << " is not readable." );
523     }
524   }
525   return _resourcesList;
526 }
527
528 //=============================================================================
529 /*!
530  *   consult the content of the list
531  */ 
532 //=============================================================================
533
534 const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const
535 {
536   return _resourcesList;
537 }
538
539 //! threadsafe
540 std::string ResourcesManager_cpp::Find(const std::string& policy, const std::vector<std::string>& listOfResources) const
541 {
542   std::map<std::string , LoadRateManager*>::const_iterator it(_resourceManagerMap.find(policy));
543   if(it==_resourceManagerMap.end())
544         {
545           it=_resourceManagerMap.find("");
546           return ((*it).second)->Find(listOfResources, _resourcesList);
547         }
548   return ((*it).second)->Find(listOfResources, _resourcesList);
549 }
550
551 //=============================================================================
552 /*!
553  *  Gives a sublist of resources with matching OS.
554  *  If parameter OS is empty, gives the complete list of resources
555  */ 
556 //=============================================================================
557 void 
558 ResourcesManager_cpp::SelectOnlyResourcesWithOS(std::vector<std::string>& resources, std::string OS)
559 {
560   if (OS != "")
561   {
562     // a computer list is given : take only resources with OS on those computers
563     std::vector<std::string> vec_tmp = resources;
564     resources.clear();
565     std::vector<std::string>::iterator iter = vec_tmp.begin();
566     for (; iter != vec_tmp.end(); iter++)
567     {
568       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
569       if(it != _resourcesList.end())
570         if ( (*it).second.OS == OS)
571           resources.push_back(*iter);
572     }
573   }
574 }
575
576
577 //=============================================================================
578 /*!
579  *  Gives a sublist of machines on which the component is known.
580  */ 
581 //=============================================================================
582 void 
583 ResourcesManager_cpp::KeepOnlyResourcesWithComponent(std::vector<std::string>& resources, 
584                                                      const std::vector<std::string>& componentList)
585 {
586   std::vector<std::string> kept_resources;
587
588   std::vector<std::string>::iterator iter = resources.begin();
589   for (; iter != resources.end(); iter++)
590   {
591     const std::vector<std::string>& mapOfComponentsOfCurrentHost = _resourcesList[*iter].ComponentsList;
592
593     bool erasedHost = false;
594     if( mapOfComponentsOfCurrentHost.size() > 0 )
595     {
596       for(unsigned int i=0; i<componentList.size(); i++)
597       {
598         std::vector<std::string>::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(),
599                                                             mapOfComponentsOfCurrentHost.end(),
600                                                             componentList[i]);
601         if (itt == mapOfComponentsOfCurrentHost.end())
602         {
603           erasedHost = true;
604           break;
605         }
606       }
607     }
608     if(!erasedHost)
609       kept_resources.push_back(*iter);
610   }
611   resources=kept_resources;
612 }
613
614 //! thread safe
615 ParserResourcesType ResourcesManager_cpp::GetResourcesDescr(const std::string & name) const
616 {
617   MapOfParserResourcesType::const_iterator it(_resourcesList.find(name));
618   if (it != _resourcesList.end())
619     return (*it).second;
620   else
621   {
622     std::string error("[GetResourcesDescr] Resource does not exist: ");
623     error += name;
624     throw ResourcesException(error);
625   }
626 }
627
628 void ResourcesManager_cpp::AddDefaultResourceInCatalog()
629 {
630   ParserResourcesType resource;
631   resource.Name = DEFAULT_RESOURCE_NAME;
632   // We can't use "localhost" for parameter hostname because the containers are registered in the
633   // naming service with the real hostname, not "localhost"
634   resource.HostName = Kernel_Utils::GetHostname();
635   resource.DataForSort._Name = DEFAULT_RESOURCE_NAME;
636   resource.Protocol = sh;
637   resource.Batch = none;
638 #ifndef WIN32
639   struct stat statbuf;
640   std::string aHomePath = Kernel_Utils::HomePath();
641   if (aHomePath != "" && getenv("APPLI") != NULL)
642   {
643     if (stat(getenv("APPLI"), &statbuf) ==0 &&  S_ISREG(statbuf.st_mode))
644     {
645         // if $APPLI is a regular file, we asume it's a salome Launcher file
646         resource.AppliPath = string(getenv("APPLI"));
647     }
648     else
649     {
650         resource.AppliPath = aHomePath + "/" + getenv("APPLI");
651     }
652   }
653   string tmpdir = "/tmp";
654   if (getenv("TMPDIR") != NULL)
655     tmpdir = getenv("TMPDIR");
656   resource.working_directory = tmpdir + "/salome_localres_workdir";
657   if (getenv("USER") != NULL)
658     resource.working_directory += string("_") + getenv("USER");
659 #else
660   if (getenv("USERPROFILE") != NULL && getenv("APPLI") != NULL)
661   {
662     resource.AppliPath = string(getenv("USERPROFILE")) + "\\" + getenv("APPLI");
663   }
664   string tmpdir = "C:\\tmp";
665   if (getenv("TEMP") != NULL)
666     tmpdir = getenv("TEMP");
667   resource.working_directory = tmpdir + "\\salome_localres_workdir";
668   if (getenv("USERNAME") != NULL)
669     resource.working_directory += string("_") + getenv("USERNAME");
670 #endif
671   resource.can_launch_batch_jobs = true;
672   resource.can_run_containers = true;
673   _resourcesList[resource.Name] = resource;
674   DEBUG_MESSAGE("Put Ressource \"" << resource.Name << "\" in dictionary of resources. This resource will be present even if resource files define it later.");
675 }