1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "ResourcesManager.hxx"
24 #include "SALOME_ResourcesCatalog_Handler.hxx"
25 #include <Basics_Utils.hxx>
32 #include <sys/types.h>
38 #include <libxml/parser.h>
42 #include "Utils_SALOME_Exception.hxx"
44 #define MAX_SIZE_FOR_HOSTNAME 256;
48 const string ResourcesManager_cpp::DEFAULT_RESOURCE_NAME = "localhost";
50 static LoadRateManagerFirst first;
51 static LoadRateManagerCycl cycl;
52 static LoadRateManagerAltCycl altcycl;
53 //=============================================================================
57 //=============================================================================
59 ResourcesManager_cpp::
60 ResourcesManager_cpp(const char *xmlFilePath)
62 _path_resources.push_back(xmlFilePath);
63 #if defined(_DEBUG_) || defined(_DEBUG)
64 std::cerr << "ResourcesManager_cpp constructor" << std::endl;
66 _resourceManagerMap["first"]=&first;
67 _resourceManagerMap["cycl"]=&cycl;
68 _resourceManagerMap["altcycl"]=&altcycl;
69 _resourceManagerMap["best"]=&altcycl;
70 _resourceManagerMap[""]=&altcycl;
72 AddDefaultResourceInCatalog();
75 //=============================================================================
77 * Standard constructor, parse resource file.
78 * - if ${APPLI} exists in environment,
79 * look for ${HOME}/${APPLI}/CatalogResources.xml
80 * - else look for default:
81 * ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
82 * - parse XML resource file.
84 //=============================================================================
86 ResourcesManager_cpp::ResourcesManager_cpp() throw(ResourcesException)
88 RES_MESSAGE("ResourcesManager_cpp constructor");
90 _resourceManagerMap["first"]=&first;
91 _resourceManagerMap["cycl"]=&cycl;
92 _resourceManagerMap["altcycl"]=&altcycl;
93 _resourceManagerMap["best"]=&altcycl;
94 _resourceManagerMap[""]=&altcycl;
96 AddDefaultResourceInCatalog();
98 bool default_catalog_resource = true;
99 if (getenv("USER_CATALOG_RESOURCES_FILE") != 0)
101 default_catalog_resource = false;
102 std::string user_file("");
103 user_file = getenv("USER_CATALOG_RESOURCES_FILE");
104 std::ifstream ifile(user_file.c_str(), std::ifstream::in );
106 // The file exists, and is open for input
107 _path_resources.push_back(user_file);
110 default_catalog_resource = false;
111 RES_INFOS("Warning: USER_CATALOG_RESOURCES_FILE is set and file cannot be found.")
112 RES_INFOS("Warning: That's why we try to create a new one.")
113 std::ofstream user_catalog_file;
114 user_catalog_file.open(user_file.c_str());
115 if (user_catalog_file.fail())
117 RES_INFOS("Error: cannot write in the user catalog resouces files");
118 RES_INFOS("Error: using default CatalogResources.xml file");
119 default_catalog_resource = true;
123 user_catalog_file << "<!-- File created by SALOME -->" << std::endl;
124 user_catalog_file << "<!DOCTYPE ResourcesCatalog>" << std::endl;
125 user_catalog_file << "<resources>" << std::endl;
126 user_catalog_file << " <machine name=\"localhost\" hostname=\"localhost\" />" << std::endl;
127 user_catalog_file << "</resources>" << std::endl;
128 user_catalog_file.close();
132 if (default_catalog_resource)
134 std::string default_file("");
135 if (getenv("APPLI") != 0)
137 default_file += getenv("HOME");
139 default_file += getenv("APPLI");
140 default_file += "/CatalogResources.xml";
141 _path_resources.push_back(default_file);
145 if(!getenv("KERNEL_ROOT_DIR"))
146 throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml");
147 default_file = getenv("KERNEL_ROOT_DIR");
148 default_file += "/share/salome/resources/kernel/CatalogResources.xml";
149 _path_resources.push_back(default_file);
156 RES_MESSAGE("ResourcesManager_cpp constructor end");
159 //=============================================================================
161 * Standard Destructor
163 //=============================================================================
165 ResourcesManager_cpp::~ResourcesManager_cpp()
167 RES_MESSAGE("ResourcesManager_cpp destructor");
170 //=============================================================================
171 //! get the list of resource names fitting constraints given by params
174 * 1: Restrict list with resourceList if defined
175 * 2: If name is defined -> check resource list
176 * 3: If not 2:, if hostname is defined -> check resource list
177 * 4: If not 3:, sort resource with nb_proc, etc...
178 * 5: In all cases remove resource that does not correspond with OS
179 * 6: And remove resource with componentList - if list is empty ignored it...
181 //=============================================================================
183 std::vector<std::string>
184 ResourcesManager_cpp::GetFittingResources(const resourceParams& params) throw(ResourcesException)
186 RES_MESSAGE("[GetFittingResources] on computer " << Kernel_Utils::GetHostname().c_str());
187 RES_MESSAGE("[GetFittingResources] with resource name: " << params.name);
188 RES_MESSAGE("[GetFittingResources] with hostname: "<< params.hostname);
191 std::vector<std::string> vec;
193 // Parse Again CalatogResource File
197 // 1: If name is defined -> check resource list
198 // 2: Restrict list with resourceList if defined
199 // 3: If not 2:, if hostname is defined -> check resource list
200 // 4: If not 3:, sort resource with nb_proc, etc...
201 // 5: In all cases remove resource that does not correspond with OS
202 // 6: And remove resource with componentList - if list is empty ignored it...
205 if (params.name != "")
207 RES_MESSAGE("[GetFittingResources] name parameter found !");
208 if (_resourcesList.find(params.name) != _resourcesList.end())
210 vec.push_back(params.name);
214 RES_MESSAGE("[GetFittingResources] resource name was not found on resource list ! name requested was " << params.name);
215 std::string error("[GetFittingResources] resource name was not found on resource list ! name requested was " + params.name);
216 throw ResourcesException(error);
219 MapOfParserResourcesType local_resourcesList = _resourcesList;
221 if (params.resourceList.size() > 0)
223 RES_MESSAGE("[GetFittingResources] Restricted resource list found !");
224 local_resourcesList.clear();
225 std::vector<std::string>::size_type sz = params.resourceList.size();
227 for (unsigned int i=0; i < sz; i++)
229 if (_resourcesList.find(params.resourceList[i]) != _resourcesList.end())
230 local_resourcesList[params.resourceList[i]] = _resourcesList[params.resourceList[i]];
235 if (params.hostname != "")
237 RES_MESSAGE("[GetFittingResources] Entering in hostname case !");
239 std::string hostname = params.hostname;
240 if (hostname == "localhost")
241 hostname = Kernel_Utils::GetHostname().c_str();
243 std::map<std::string, ParserResourcesType>::const_iterator iter = _resourcesList.begin();
244 for (; iter != _resourcesList.end(); iter++)
246 if ((*iter).second.HostName == hostname)
247 vec.push_back((*iter).first);
253 // --- Search for available resources sorted by priority
254 MapOfParserResourcesType_it i = local_resourcesList.begin();
255 for (; i != local_resourcesList.end(); ++i)
256 vec.push_back(i->first);
258 // --- set wanted parameters
259 ResourceDataToSort::_nbOfProcWanted = params.nb_proc;
260 ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
261 ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
262 ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
263 ResourceDataToSort::_memInMBWanted = params.mem_mb;
267 std::list<ResourceDataToSort> li;
268 std::vector<std::string>::iterator iter = vec.begin();
269 for (; iter != vec.end(); iter++)
270 li.push_back(local_resourcesList[(*iter)].DataForSort);
274 for (std::list<ResourceDataToSort>::iterator iter2 = li.begin(); iter2 != li.end(); iter2++)
275 vec.push_back((*iter2)._Name);
279 SelectOnlyResourcesWithOS(vec, params.OS.c_str());
282 std::vector<std::string> vec_save(vec);
283 KeepOnlyResourcesWithComponent(vec, params.componentList);
287 // Step 7 : Filter on possible usage
288 vector<string> prev_list(vec);
290 for (vector<string>::iterator iter = prev_list.begin() ; iter != prev_list.end() ; iter++)
292 MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
293 if (it != _resourcesList.end() &&
294 (!params.can_launch_batch_jobs || it->second.can_launch_batch_jobs) &&
295 (!params.can_run_containers || it->second.can_run_containers))
296 vec.push_back(*iter);
300 // Send an exception if return list is empty...
303 std::string error("[GetFittingResources] ResourcesManager doesn't find any resource that fits to your parameters");
304 throw ResourcesException(error);
310 //=============================================================================
312 * add an entry in the ressources catalog xml file.
314 //=============================================================================
317 ResourcesManager_cpp::AddResourceInCatalog(const ParserResourcesType & new_resource)
319 if (new_resource.Name == DEFAULT_RESOURCE_NAME)
320 throw SALOME_Exception((string("Cannot modify default local resource \"") +
321 DEFAULT_RESOURCE_NAME + "\"").c_str());
322 // TODO - Add minimal check
323 _resourcesList[new_resource.Name] = new_resource;
326 //=============================================================================
328 * Deletes a resource from the catalog
330 //=============================================================================
332 void ResourcesManager_cpp::DeleteResourceInCatalog(const char * name)
334 if (DEFAULT_RESOURCE_NAME == name)
335 throw SALOME_Exception((string("Cannot delete default local resource \"") +
336 DEFAULT_RESOURCE_NAME + "\"").c_str());
337 MapOfParserResourcesType_it it = _resourcesList.find(name);
338 if (it != _resourcesList.end())
339 _resourcesList.erase(name);
341 RES_INFOS("You try to delete a resource that does not exist... : " << name);
344 //=============================================================================
346 * write the current data in memory in file.
348 //=============================================================================
350 void ResourcesManager_cpp::WriteInXmlFile(std::string xml_file)
352 RES_MESSAGE("WriteInXmlFile : start");
354 MapOfParserResourcesType resourceListToSave(_resourcesList);
355 // We do not save default local resource because it is automatically created at startup
356 resourceListToSave.erase(DEFAULT_RESOURCE_NAME);
357 if (resourceListToSave.empty())
359 RES_MESSAGE("WriteInXmlFile: nothing to do, no resource except default \"" <<
360 DEFAULT_RESOURCE_NAME << "\"");
366 _path_resources_it = _path_resources.begin();
367 xml_file = *_path_resources_it;
370 const char* aFilePath = xml_file.c_str();
371 FILE* aFile = fopen(aFilePath, "w");
375 std::cerr << "Error opening file in WriteInXmlFile : " << xml_file << std::endl;
379 xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
380 xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
382 SALOME_ResourcesCatalog_Handler* handler =
383 new SALOME_ResourcesCatalog_Handler(resourceListToSave);
384 handler->PrepareDocToXmlFile(aDoc);
387 int isOk = xmlSaveFormatFile(aFilePath, aDoc, 1);
389 std::cerr << "Error while XML file saving : " << xml_file << std::endl;
394 RES_MESSAGE("WriteInXmlFile : WRITING DONE!");
397 //=============================================================================
399 * parse the data type catalog
401 //=============================================================================
403 const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles()
405 // Parse file only if its modification time is greater than lasttime (last registered modification time)
406 bool to_parse = false;
407 for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
409 struct stat statinfo;
410 int result = stat((*_path_resources_it).c_str(), &statinfo);
413 RES_MESSAGE("Resource file " << *_path_resources_it << " does not exist");
414 return _resourcesList;
417 if(statinfo.st_mtime > _lasttime)
420 _lasttime = statinfo.st_mtime;
426 _resourcesList.clear();
427 AddDefaultResourceInCatalog();
428 // On parse tous les fichiers
429 for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
431 MapOfParserResourcesType _resourcesList_tmp;
432 MapOfParserResourcesType _resourcesBatchList_tmp;
433 SALOME_ResourcesCatalog_Handler* handler =
434 new SALOME_ResourcesCatalog_Handler(_resourcesList_tmp);
435 const char* aFilePath = (*_path_resources_it).c_str();
436 FILE* aFile = fopen(aFilePath, "r");
440 xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
443 handler->ProcessXmlDocument(aDoc);
445 // adding new resources to the file
446 for (MapOfParserResourcesType_it i = _resourcesList_tmp.begin(); i != _resourcesList_tmp.end(); ++i)
448 MapOfParserResourcesType_it j = _resourcesList.find(i->first);
449 if (i->second.HostName == "localhost" || i->second.HostName == Kernel_Utils::GetHostname())
451 RES_MESSAGE("Resource " << i->first << " is not added because it is the same "
452 "machine as default local resource \"" << DEFAULT_RESOURCE_NAME << "\"");
454 else if (j != _resourcesList.end())
456 cerr << "ParseXmlFiles Warning, two resources with the same name were found, "
457 "taking the first declaration : " << i->first << endl;
461 _resourcesList[i->first] = i->second;
466 std::cerr << "ResourcesManager_cpp: could not parse file " << aFilePath << std::endl;
472 std::cerr << "ResourcesManager_cpp: file " << aFilePath << " is not readable." << std::endl;
477 return _resourcesList;
480 //=============================================================================
482 * consult the content of the list
484 //=============================================================================
486 const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const
488 return _resourcesList;
491 std::string ResourcesManager_cpp::Find(const std::string& policy, const std::vector<std::string>& listOfResources)
493 if(_resourceManagerMap.count(policy)==0)
494 return _resourceManagerMap[""]->Find(listOfResources, _resourcesList);
495 return _resourceManagerMap[policy]->Find(listOfResources, _resourcesList);
498 //=============================================================================
500 * Gives a sublist of resources with matching OS.
501 * If parameter OS is empty, gives the complete list of resources
503 //=============================================================================
505 ResourcesManager_cpp::SelectOnlyResourcesWithOS(std::vector<std::string>& resources, std::string OS)
509 // a computer list is given : take only resources with OS on those computers
510 std::vector<std::string> vec_tmp = resources;
512 std::vector<std::string>::iterator iter = vec_tmp.begin();
513 for (; iter != vec_tmp.end(); iter++)
515 MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
516 if(it != _resourcesList.end())
517 if ( (*it).second.OS == OS)
518 resources.push_back(*iter);
524 //=============================================================================
526 * Gives a sublist of machines on which the component is known.
528 //=============================================================================
530 ResourcesManager_cpp::KeepOnlyResourcesWithComponent(std::vector<std::string>& resources,
531 const std::vector<std::string>& componentList)
533 std::vector<std::string> kept_resources;
535 std::vector<std::string>::iterator iter = resources.begin();
536 for (; iter != resources.end(); iter++)
538 const std::vector<std::string>& mapOfComponentsOfCurrentHost = _resourcesList[*iter].ComponentsList;
540 bool erasedHost = false;
541 if( mapOfComponentsOfCurrentHost.size() > 0 )
543 for(unsigned int i=0; i<componentList.size(); i++)
545 std::vector<std::string>::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(),
546 mapOfComponentsOfCurrentHost.end(),
548 if (itt == mapOfComponentsOfCurrentHost.end())
556 kept_resources.push_back(*iter);
558 resources=kept_resources;
563 ResourcesManager_cpp::GetResourcesDescr(const std::string & name)
565 if (_resourcesList.find(name) != _resourcesList.end())
566 return _resourcesList[name];
569 std::string error("[GetResourcesDescr] Resource does not exist: ");
571 throw ResourcesException(error);
575 void ResourcesManager_cpp::AddDefaultResourceInCatalog()
577 ParserResourcesType resource;
578 resource.Name = DEFAULT_RESOURCE_NAME;
579 // We can't use "localhost" for parameter hostname because the containers are registered in the
580 // naming service with the real hostname, not "localhost"
581 resource.HostName = Kernel_Utils::GetHostname();
582 resource.DataForSort._Name = DEFAULT_RESOURCE_NAME;
583 resource.Protocol = sh;
584 resource.Batch = none;
585 if (getenv("HOME") != NULL && getenv("APPLI") != NULL)
587 resource.AppliPath = string(getenv("HOME")) + "/" + getenv("APPLI");
589 resource.working_directory = "/tmp/salome_localres_workdir";
590 resource.can_launch_batch_jobs = true;
591 resource.can_run_containers = true;
592 _resourcesList[resource.Name] = resource;