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