From: Konstantin Leontev Date: Mon, 19 Jun 2023 16:48:54 +0000 (+0100) Subject: [bos #35138][EDF] (2023-T1) Specialization of resources in KERNEL. X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=85a59f708626d55f739b6822c571785171d980b4;p=modules%2Fkernel.git [bos #35138][EDF] (2023-T1) Specialization of resources in KERNEL. --- diff --git a/idl/CMakeLists.txt b/idl/CMakeLists.txt index 43cd37e9a..a7f704257 100644 --- a/idl/CMakeLists.txt +++ b/idl/CMakeLists.txt @@ -30,6 +30,9 @@ SET(SalomeIDLKernel_IDLSOURCES SALOME_Exception.idl SALOME_Comm.idl SALOME_ModuleCatalog.idl + SALOME_Resource.idl + SALOME_ResourceJob.idl + SALOME_ResourceContainer.idl SALOME_ResourcesManager.idl SALOME_Launcher.idl SALOMEDS.idl diff --git a/idl/SALOME_ContainerManager.idl b/idl/SALOME_ContainerManager.idl index ecba48ad9..fc9a4c592 100644 --- a/idl/SALOME_ContainerManager.idl +++ b/idl/SALOME_ContainerManager.idl @@ -64,7 +64,7 @@ struct ContainerParameters string parallelLib; //! Parameters to choose a resource - ResourceParameters resource_params; + ResourceParametersContainer resource_params; }; /*! \brief Interface of the %containerManager diff --git a/idl/SALOME_Launcher.idl b/idl/SALOME_Launcher.idl index 474781e6e..5193d29b7 100644 --- a/idl/SALOME_Launcher.idl +++ b/idl/SALOME_Launcher.idl @@ -137,7 +137,7 @@ struct JobParameters - mem_mb -> Memory expressed in megabytes. - nb_proc -> Number of Processors. */ - ResourceParameters resource_required; + ResourceParametersContainer resource_required; //! Name of the batch queue chosen - optional string queue; @@ -298,7 +298,7 @@ interface SalomeLauncher // Useful methods long createJobWithFile(in string xmlJobFile, in string clusterName) raises (SALOME::SALOME_Exception); - boolean testBatch (in ResourceParameters params) raises (SALOME::SALOME_Exception); + boolean testBatch (in ResourceParametersJob params) raises (SALOME::SALOME_Exception); // SALOME kernel service methods //! Shutdow SalomeLauncher server. diff --git a/idl/SALOME_Resource.idl b/idl/SALOME_Resource.idl new file mode 100644 index 000000000..24f2ea221 --- /dev/null +++ b/idl/SALOME_Resource.idl @@ -0,0 +1,35 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef _SALOME_RESOURCE_IDL_ +#define _SALOME_RESOURCE_IDL_ + + +/*! \file SALOME_Resource.idl \brief common definintions for %SALOME Resources +*/ + +module Engines +{ + +//! Type to transmit list of resources. +typedef sequence ResourceList; + +}; + +#endif diff --git a/idl/SALOME_ResourceContainer.idl b/idl/SALOME_ResourceContainer.idl new file mode 100644 index 000000000..f71e66d8f --- /dev/null +++ b/idl/SALOME_ResourceContainer.idl @@ -0,0 +1,169 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef _SALOME_RESOURCECONTAINER_IDL_ +#define _SALOME_RESOURCECONTAINER_IDL_ + +#include "SALOME_Resource.idl" + +/*! \file SALOME_ResourceContainer.idl \brief interfaces for %SALOME Resource container parameters and definition +*/ + +module Engines +{ + +//! components list +typedef sequence CompoList; + +//! Type to describe required properties of a resource +struct ResourceParametersContainer +{ + // Common for all resources structs + //======================================================================================== + + //! resource name - manual selection + /*! If a name is provided, the resource will be imposed. + If the name is an empty string, the resource will be chosen to match + the other parameters. + */ + string name; + + //! host name + string hostname; + + // Common for all resources parameters + //======================================================================================== + + // Permits to configure SALOME resource management + //! resource management policy : first, cycl, altcycl or best (can be extended) + string policy; + + //! restricted list of resources to search in + ResourceList resList; + + // Specific for container resources parameters + //======================================================================================== + + //! if given required operating system + string OS; + + //! if given, list of components that could be loaded on a container. + /*! Ignored if no resources are found with this constraint.*/ + CompoList componentList; + + // Permits to order resources + //! required number of processors + /*! This parameter must be specified explicitly, because it is not provided + by the resource definition. + */ + long nb_proc; + + //! required memory size + /*! This parameter must be specified explicitly, because it is not provided + by the resource definition. + + The parameter specifies the maximum memory value that could be allocated + for executing the job. This takes into account not only the data that + could be loaded by the batch process but also the linked dynamic library. + A possible problem, for example in the case where you use the ssh + emulation of a batch system, is to get an error message as below + when libBatch tries to run the ssh command: +\verbatim +/usr/bin/ssh: error while loading shared libraries: libcrypto.so.0.9.8: failed +to map segment from shared object: Cannot allocate memory +\endverbatim + In this example, the mem_mb was set to 1MB, value that is not + sufficient to load the dynamic libraries linked to the ssh + executable (libcrypto.so in the error message). + So, even in the case of a simple test shell script, you should + set this value at least to a standard threshold as 500MB. + */ + long mem_mb; + + //! required frequency + long cpu_clock; + + //! required number of nodes. Can be used when submitting slurm jobs. + long nb_node; + + //! required number of proc per node + long nb_proc_per_node; +}; + +//! Type to describe a container resource +struct ResourceDefinitionContainer +{ + // Common for all resources structs + //======================================================================================== + + //! resource name - manual selection + /*! If a name is provided, the resource will be imposed. + If the name is an empty string, the resource will be chosen to match + the other parameters. + */ + string name; + + //! host name + string hostname; + + // Common for all resources definitions + //======================================================================================== + + //! protocol to connect to the resource and to start a remote container + //! Possible values: + //! "rsh" : uses rsh and rcp + //! "ssh" : uses ssh and scp + //! "rsync" : uses ssh and rsync + string protocol; + + //! login name to use to start a remote container + string username; + + //! salome application to use to start a remote container + string applipath; + + //! batch system + string batch; + + // Specific for container resources definitions + //======================================================================================== + + //! list of available components. + //! An empty list means every component is available. + CompoList componentList; + + //! operating system + string OS; + + //! memory size per node + long mem_mb; + + //! frequency + long cpu_clock; + + //! number of node + long nb_node; + + //! number of proc per node + long nb_proc_per_node; +}; + +}; + +#endif diff --git a/idl/SALOME_ResourceJob.idl b/idl/SALOME_ResourceJob.idl new file mode 100644 index 000000000..09b13d131 --- /dev/null +++ b/idl/SALOME_ResourceJob.idl @@ -0,0 +1,112 @@ +// Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef _SALOME_RESOURCEJOB_IDL_ +#define _SALOME_RESOURCEJOB_IDL_ + +#include "SALOME_Resource.idl" + +/*! \file SALOME_ResourceJob.idl \brief interfaces for %SALOME Resource job parameters and definition +*/ + +module Engines +{ + +//! Type to describe required properties of a job resource +struct ResourceParametersJob +{ + // Common for all resources structs + //======================================================================================== + + //! resource name - manual selection + /*! If a name is provided, the resource will be imposed. + If the name is an empty string, the resource will be chosen to match + the other parameters. + */ + string name; + + //! host name + string hostname; + + // Common for all resources parameters + //======================================================================================== + + // Permits to configure SALOME resource management + //! resource management policy : first, cycl, altcycl or best (can be extended) + string policy; + + //! restricted list of resources to search in + ResourceList resList; +}; + +//! Type to describe a job resource +struct ResourceDefinitionJob +{ + // Common for all resources structs + //======================================================================================== + + //! resource name - manual selection + /*! If a name is provided, the resource will be imposed. + If the name is an empty string, the resource will be chosen to match + the other parameters. + */ + string name; + + //! host name + string hostname; + + // Common for all resources definitions + //======================================================================================== + + //! protocol to connect to the resource and to start a remote container + //! Possible values: + //! "rsh" : uses rsh and rcp + //! "ssh" : uses ssh and scp + //! "rsync" : uses ssh and rsync + string protocol; + + //! login name to use to start a remote container + string username; + + //! salome application to use to start a remote container + string applipath; + + //! batch system + string batch; + + // Specific for job resources definitions + //======================================================================================== + + //! MPI implementation + string mpiImpl; + + //! if the resource is a cluster: + //! internal protocol to use to start a remote container (ssh or rsh) on the cluster + string iprotocol; + + //! Predefined working directory on the resource + string working_directory; +}; + +}; + +#endif diff --git a/idl/SALOME_ResourcesManager.idl b/idl/SALOME_ResourcesManager.idl index 375f3273e..b2ca42c16 100644 --- a/idl/SALOME_ResourcesManager.idl +++ b/idl/SALOME_ResourcesManager.idl @@ -17,12 +17,14 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #ifndef _SALOME_RESOURCESMANAGER_IDL_ #define _SALOME_RESOURCESMANAGER_IDL_ +#include "SALOME_ResourceJob.idl" +#include "SALOME_ResourceContainer.idl" #include "SALOME_Exception.idl" /*! \file SALOME_ResourcesManager.idl \brief interfaces for %SALOME Resources Manager service @@ -31,125 +33,9 @@ module Engines { -//! Type to transmit list of resources. -typedef sequence ResourceList; -//! components list -typedef sequence CompoList; +//! type to keep procs of machines list typedef sequence IntegerList; - -//! Type to describe required properties of a resource -struct ResourceParameters -{ - //! resource name - manual selection - /*! If a name is provided, the resource will be imposed. - If the name is an empty string, the resource will be chosen to match - the other parameters. - */ - string name; - - //! host name - string hostname; - //! if true select only resources that can launch batch jobs - boolean can_launch_batch_jobs; - //! if true select only resources that can run containers - boolean can_run_containers; - //! if given required operating system - string OS; - //! if given, list of components that could be loaded on a container. - /*! Ignored if no resources are found with this constraint.*/ - CompoList componentList; - - // Permits to order resources - //! required number of processors - /*! This parameter must be specified explicitly, because it is not provided - by the resource definition. - */ - long nb_proc; - - //! required memory size - /*! This parameter must be specified explicitly, because it is not provided - by the resource definition. - - The parameter specifies the maximum memory value that could be allocated - for executing the job. This takes into account not only the data that - could be loaded by the batch process but also the linked dynamic library. - A possible problem, for example in the case where you use the ssh - emulation of a batch system, is to get an error message as below - when libBatch tries to run the ssh command: -\verbatim -/usr/bin/ssh: error while loading shared libraries: libcrypto.so.0.9.8: failed -to map segment from shared object: Cannot allocate memory -\endverbatim - In this example, the mem_mb was set to 1MB, value that is not - sufficient to load the dynamic libraries linked to the ssh - executable (libcrypto.so in the error message). - So, even in the case of a simple test shell script, you should - set this value at least to a standard threshold as 500MB. - */ - long mem_mb; - //! required frequency - long cpu_clock; - //! required number of nodes. Can be used when submitting slurm jobs. - long nb_node; - //! required number of proc per node - long nb_proc_per_node; - - // Permits to configure SALOME resource management - //! resource management policy : first, cycl, altcycl or best (can be extended) - string policy; - //! restricted list of resources to search in - ResourceList resList; -}; -//! Type to describe a resource -struct ResourceDefinition -{ - //! name - string name; - //! hostname - string hostname; - //! Type of the resource ("cluster" or "single_machine") - string type; - //! protocol to connect to the resource and to start a remote container - //! Possible values: - //! "rsh" : uses rsh and rcp - //! "ssh" : uses ssh and scp - //! "rsync" : uses ssh and rsync - string protocol; - //! login name to use to start a remote container - string username; - //! salome application to use to start a remote container - string applipath; - //! list of available components. - //! An empty list means every component is available. - CompoList componentList; - - //! operating system - string OS; - //! memory size per node - long mem_mb; - //! frequency - long cpu_clock; - //! number of node - long nb_node; - //! number of proc per node - long nb_proc_per_node; - //! batch system - string batch; - //! MPI implementation - string mpiImpl; - //! if the resource is a cluster: - //! internal protocol to use to start a remote container (ssh or rsh) on the cluster - string iprotocol; - - //! Specify if the resource can launch batch jobs - boolean can_launch_batch_jobs; - //! Specify if the resource can run containers - boolean can_run_containers; - - //! Predefined working directory on the resource - string working_directory; -}; /*! \brief Interface of the %resourcesManager This interface is used for interaction with the unique instance @@ -158,46 +44,91 @@ struct ResourceDefinition interface ResourcesManager { //! Find first available resource in a resources list - string FindFirst(in ResourceList possibleResources); + string FindFirst(in ResourceList possibleContainerResources); //! Find best available computer according to policy in a computers list - string Find(in string policy, in ResourceList possibleResources); + string Find(in string policy, in ResourceList possibleContainerResources); + + //======================================================================================== + + //! Get a list of resources that are best suited to launch a job given constraints + /*! + The constraints are resource constraints (params) and components constraints (componentList) + */ + ResourceList GetFittingResourcesJob(in ResourceParametersJob params) raises (SALOME::SALOME_Exception); //! Get a list of resources that are best suited to launch a container given constraints /*! The constraints are resource constraints (params) and components constraints (componentList) */ - ResourceList GetFittingResources(in ResourceParameters params) raises (SALOME::SALOME_Exception); + ResourceList GetFittingResourcesContainer(in ResourceParametersContainer params) raises (SALOME::SALOME_Exception); + + //======================================================================================== - //! Get definition of a resource - ResourceDefinition GetResourceDefinition(in string name) raises (SALOME::SALOME_Exception); + //! Get definition of a job resource + ResourceDefinitionJob GetResourceDefinitionJob(in string name) raises (SALOME::SALOME_Exception); - //! Add a new resource to the resource_manager + //! Get definition of a container resource + ResourceDefinitionContainer GetResourceDefinitionContainer(in string name) raises (SALOME::SALOME_Exception); + + //======================================================================================== + + //! Add a new job resource to the resource_manager /*! write -> true, resource manager will add it into a xml_file xml_file -> could be empty, in this case if write is true, resource manager will write the resource in its first ResourceCatalog file */ - void AddResource(in ResourceDefinition new_resource, in boolean write, in string xml_file) + void AddResourceJob(in ResourceDefinitionJob new_resource, in boolean write, in string xml_file) raises (SALOME::SALOME_Exception); - //! Remove a new resource to the resource_manager + //! Add a new container resource to the resource_manager + /*! + write -> true, resource manager will add it into a xml_file + xml_file -> could be empty, in this case if write is true, resource manager will write + the resource in its first ResourceCatalog file + */ + void AddResourceContainer(in ResourceDefinitionContainer new_resource, in boolean write, in string xml_file) + raises (SALOME::SALOME_Exception); + + //======================================================================================== + + //! Remove a job resource from the resource_manager /*! write -> true, resource manager will write a new xml_file xml_file -> could be empty, in this case if write is true, resource manager will write the resource in its first ResourceCatalog file */ - void RemoveResource(in string resource_name, in boolean write, in string xml_file) + void RemoveResourceJob(in string resource_name, in boolean write, in string xml_file) raises (SALOME::SALOME_Exception); + //! Remove a container resource from the resource_manager + /*! + write -> true, resource manager will write a new xml_file + xml_file -> could be empty, in this case if write is true, resource manager will write + the resource in its first ResourceCatalog file + */ + void RemoveResourceContainer(in string resource_name, in boolean write, in string xml_file) + raises (SALOME::SALOME_Exception); + + //======================================================================================== + //! Create a machine file for PaCO container string getMachineFile(in string resource_name, in long nb_procs, in string parallelLib) raises (SALOME::SALOME_Exception); + + //======================================================================================== + + //! Return list of container resources available (regarding content of CatalogResources.xml). And for each resource the number of proc available of it. + void ListAllAvailableResourcesContainer(out ResourceList machines, out IntegerList nbProcsOfMachines) raises (SALOME::SALOME_Exception); + + //======================================================================================== - //! Return list of resources available (regarding content of CatalogResources.xml). And for each resource the number of proc available of it. - void ListAllAvailableResources(out ResourceList machines, out IntegerList nbProcsOfMachines) raises (SALOME::SALOME_Exception); + //! Return list of job resources in catalog + ResourceList ListAllResourcesInCatalogJob() raises (SALOME::SALOME_Exception); - ResourceList ListAllResourcesInCatalog() raises (SALOME::SALOME_Exception); + //! Return list of container resources in catalog + ResourceList ListAllResourcesInCatalogContainer() raises (SALOME::SALOME_Exception); }; }; diff --git a/src/Container/Container_i.cxx b/src/Container/Container_i.cxx index a0215f45e..b4e8bc413 100644 --- a/src/Container/Container_i.cxx +++ b/src/Container/Container_i.cxx @@ -2261,9 +2261,9 @@ Engines_Container_SSL_i *KERNEL::getContainerSA() CORBA::PolicyList policies; policies.length(0); // - char *argv[4] = {"Container","FactoryServer","toto",nullptr}; + char *argv[4] = { (char*)"Container", (char*)"FactoryServer", (char*)"toto",nullptr}; SALOME_Fake_NamingService ns; - _container_singleton_ssl = new Engines_Container_SSL_i(orb,poa,"FactoryServer",2,argv,&ns,false); + _container_singleton_ssl = new Engines_Container_SSL_i(orb,poa,(char*)"FactoryServer",2,argv,&ns,false); PortableServer::ObjectId * cont_id = _container_singleton_ssl->getCORBAId(); // CORBA::Object_var zeRef = poa->id_to_reference(*cont_id); diff --git a/src/Container/SALOME_ContainerManager.cxx b/src/Container/SALOME_ContainerManager.cxx index e9b7e23a1..7f2a86c4f 100644 --- a/src/Container/SALOME_ContainerManager.cxx +++ b/src/Container/SALOME_ContainerManager.cxx @@ -320,9 +320,8 @@ Engines::Container_ptr SALOME_ContainerManager::GiveContainer(const Engines::Con // Step 2: Get all possibleResources from the parameters // Consider only resources that can run containers - resourceParams resource_params = resourceParameters_CORBAtoCPP(local_params.resource_params); - resource_params.can_run_containers = true; - std::vector possibleResources = _resManager->GetFittingResources(resource_params); + resourceParamsContainer resource_params = resourceParametersContainer_CORBAtoCPP(local_params.resource_params); + std::vector possibleResources = _resManager->GetFittingResourcesContainer(resource_params); MESSAGE("[GiveContainer] - length of possible resources " << possibleResources.size()); std::vector local_resources; @@ -380,8 +379,8 @@ Engines::Container_ptr SALOME_ContainerManager::GiveContainer(const Engines::Con MESSAGE("[GiveContainer] Resource selected is: " << resource_selected); // Step 5: Create container name - ParserResourcesType resource_definition = _resManager->GetResourceDefinition(resource_selected); - std::string hostname(resource_definition.HostName); + ParserResourcesTypeContainer resource_definition = _resManager->GetResourceDefinitionContainer(resource_selected); + std::string hostname(resource_definition.hostname); std::string containerNameInNS; if(params.isMPI){ int nbproc = params.nb_proc <= 0 ? 1 : params.nb_proc; @@ -537,9 +536,9 @@ SALOME_ContainerManager::LaunchContainer(const Engines::ContainerParameters& par if(hostname != Kernel_Utils::GetHostname() && _isAppliSalomeDefined) { - const ParserResourcesType resInfo(_resManager->GetResourceDefinition(resource_selected)); - std::string command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, - resInfo.UserName, resInfo.AppliPath); + const ParserResourcesTypeContainer resInfo(_resManager->GetResourceDefinitionContainer(resource_selected)); + std::string command = getCommandToRunRemoteProcess(resInfo.protocol, resInfo.hostname, + resInfo.username, resInfo.applipath); // Launch remote command command += " \"ls /tmp >/dev/null 2>&1\""; @@ -684,8 +683,8 @@ Engines::Container_ptr SALOME_ContainerManager::FindContainer(const Engines::Con Engines::Container_ptr SALOME_ContainerManager::FindContainer(const Engines::ContainerParameters& params, const std::string& resource) { - ParserResourcesType resource_definition = _resManager->GetResourceDefinition(resource); - std::string hostname(resource_definition.HostName); + ParserResourcesTypeContainer resource_definition = _resManager->GetResourceDefinitionContainer(resource); + std::string hostname(resource_definition.hostname); std::string containerNameInNS(_NS->BuildContainerNameForNS(params, hostname.c_str())); MESSAGE("[FindContainer] Try to find a container " << containerNameInNS << " on resource " << resource); CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str()); @@ -750,12 +749,12 @@ std::string SALOME_ContainerManager::BuildCommandToLaunchRemoteContainer(const std::string& resource_name, const Engines::ContainerParameters& params, const std::string& container_exe) const { std::string command,tmpFileName; - const ParserResourcesType resInfo(_resManager->GetResourceDefinition(resource_name)); + const ParserResourcesTypeContainer resInfo(_resManager->GetResourceDefinitionContainer(resource_name)); std::string wdir = params.workingdir.in(); if (!_isAppliSalomeDefined) { - command = getCommandToRunRemoteProcessNoAppli(resInfo.Protocol, resInfo.HostName, - resInfo.UserName, resInfo.AppliPath, + command = getCommandToRunRemoteProcessNoAppli(resInfo.protocol, resInfo.hostname, + resInfo.username, resInfo.applipath, wdir); } else @@ -765,8 +764,8 @@ SALOME_ContainerManager::BuildCommandToLaunchRemoteContainer(const std::string& // or // "ssh -l user machine distantLauncher remote -p hostNS -m portNS -d dir // -- SALOME_Container contName -ORBInitRef NameService=IOR:01000..." - command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, - resInfo.UserName, resInfo.AppliPath, + command = getCommandToRunRemoteProcess(resInfo.protocol, resInfo.hostname, + resInfo.username, resInfo.applipath, wdir); } if(params.isMPI) @@ -1173,7 +1172,7 @@ std::string SALOME_ContainerManager::BuildTempFileToLaunchRemoteContainer (const tmpFileName = BuildTemporaryFileName(); std::ofstream tempOutputFile; tempOutputFile.open(tmpFileName.c_str(), std::ofstream::out ); - const ParserResourcesType resInfo(_resManager->GetResourceDefinition(resource_name)); + const ParserResourcesTypeContainer resInfo(_resManager->GetResourceDefinitionContainer(resource_name)); tempOutputFile << "#! /bin/sh" << std::endl; // --- set env vars @@ -1235,37 +1234,37 @@ std::string SALOME_ContainerManager::BuildTempFileToLaunchRemoteContainer (const std::string command; - if (resInfo.Protocol == rsh) + if (resInfo.protocol == rsh) { command = "rsh "; std::string commandRcp = "rcp "; commandRcp += tmpFileName; commandRcp += " "; - commandRcp += resInfo.HostName; + commandRcp += resInfo.hostname; commandRcp += ":"; commandRcp += tmpFileName; status = SystemThreadSafe(commandRcp.c_str()); } - else if (resInfo.Protocol == ssh) + else if (resInfo.protocol == ssh) { command = "ssh "; std::string commandRcp = "scp "; commandRcp += tmpFileName; commandRcp += " "; - commandRcp += resInfo.HostName; + commandRcp += resInfo.hostname; commandRcp += ":"; commandRcp += tmpFileName; status = SystemThreadSafe(commandRcp.c_str()); } - else if (resInfo.Protocol == srun) + else if (resInfo.protocol == srun) { command = "srun -n 1 -N 1 -s --mem-per-cpu=0 --cpu-bind=none --nodelist="; std::string commandRcp = "rcp "; commandRcp += tmpFileName; commandRcp += " "; - commandRcp += resInfo.HostName; + commandRcp += resInfo.hostname; commandRcp += ":"; commandRcp += tmpFileName; status = SystemThreadSafe(commandRcp.c_str()); @@ -1276,7 +1275,7 @@ std::string SALOME_ContainerManager::BuildTempFileToLaunchRemoteContainer (const if(status) throw SALOME_Exception("Error of connection on remote host"); - command += resInfo.HostName; + command += resInfo.hostname; command += " "; command += tmpFileName; @@ -1292,19 +1291,19 @@ std::string SALOME_ContainerManager::GetMPIZeroNode(const std::string machine, c std::string zeronode; std::string command; std::string tmpFile = BuildTemporaryFileName(); - const ParserResourcesType resInfo(_resManager->GetResourceDefinition(machine)); + const ParserResourcesTypeContainer resInfo(_resManager->GetResourceDefinitionContainer(machine)); - if(resInfo.Protocol == sh) + if(resInfo.protocol == sh) { - return resInfo.HostName; + return resInfo.hostname; } if( GetenvThreadSafe("LIBBATCH_NODEFILE") == NULL ) { if (_isAppliSalomeDefined) { - command = getCommandToRunRemoteProcess(resInfo.Protocol, resInfo.HostName, - resInfo.UserName, resInfo.AppliPath); + command = getCommandToRunRemoteProcess(resInfo.protocol, resInfo.hostname, + resInfo.username, resInfo.applipath); command += " mpirun -np 1 hostname -s > " + tmpFile; } else @@ -1479,17 +1478,17 @@ SALOME_ContainerManager::checkPaCOParameters(Engines::ContainerParameters & para } // Step 2 : check resource_selected - const ParserResourcesType resource_definition = _resManager->GetResourceDefinition(resource_selected); + const ParserResourcesTypeContainer resource_definition = _resManager->GetResourceDefinitionContainer(resource_selected); //std::string protocol = resource_definition->protocol.in(); - std::string username = resource_definition.UserName; - std::string applipath = resource_definition.AppliPath; + std::string username = resource_definition.username; + std::string applipath = resource_definition.applipath; //if (protocol == "" || username == "" || applipath == "") if (username == "" || applipath == "") { INFOS("[checkPaCOParameters] resource selected is not well defined"); - INFOS("[checkPaCOParameters] resource name: " << resource_definition.Name); - INFOS("[checkPaCOParameters] resource hostname: " << resource_definition.HostName); + INFOS("[checkPaCOParameters] resource name: " << resource_definition.name); + INFOS("[checkPaCOParameters] resource hostname: " << resource_definition.hostname); INFOS("[checkPaCOParameters] resource protocol: " << resource_definition.getAccessProtocolTypeStr()); INFOS("[checkPaCOParameters] resource username: " << username); INFOS("[checkPaCOParameters] resource applipath: " << applipath); @@ -1744,8 +1743,8 @@ SALOME_ContainerManager::BuildCommandToLaunchPaCOProxyContainer(const Engines::C std::string nb_proc_str = tmp_string.str(); // Get resource definition - ParserResourcesType resource_definition = - _resManager->GetResourceDefinition(params.resource_params.name.in()); + ParserResourcesTypeContainer resource_definition = + _resManager->GetResourceDefinitionContainer(params.resource_params.name.in()); // Choose hostname std::string hostname; @@ -1789,9 +1788,9 @@ SALOME_ContainerManager::BuildCommandToLaunchPaCOProxyContainer(const Engines::C command << resource_definition.getAccessProtocolTypeStr(); command << " -l "; - command << resource_definition.UserName; + command << resource_definition.username; command << " " << hostname; - command << " " << resource_definition.AppliPath; + command << " " << resource_definition.applipath; command << "/runRemote.sh "; command << GetenvThreadSafeAsString("NSHOST") << " "; // hostname of CORBA name server command << GetenvThreadSafeAsString("NSPORT") << " "; // port of CORBA name server @@ -1828,8 +1827,8 @@ SALOME_ContainerManager::BuildCommandToLaunchPaCONodeContainer(const Engines::Co nb_proc_stream << params.nb_proc; // Get resource definition - ParserResourcesType resource_definition = - _resManager->GetResourceDefinition(params.resource_params.name.in()); + ParserResourcesTypeContainer resource_definition = + _resManager->GetResourceDefinitionContainer(params.resource_params.name.in()); // Log environment std::string log_type(""); @@ -1877,9 +1876,9 @@ SALOME_ContainerManager::BuildCommandToLaunchPaCONodeContainer(const Engines::Co command_node_stream << resource_definition.getAccessProtocolTypeStr(); command_node_stream << " -l "; - command_node_stream << resource_definition.UserName; + command_node_stream << resource_definition.username; command_node_stream << " " << hostname; - command_node_stream << " " << resource_definition.AppliPath; + command_node_stream << " " << resource_definition.applipath; command_node_stream << "/runRemote.sh "; command_node_stream << GetenvThreadSafeAsString("NSHOST") << " "; // hostname of CORBA name server command_node_stream << GetenvThreadSafeAsString("NSPORT") << " "; // port of CORBA name server @@ -1920,13 +1919,13 @@ SALOME_ContainerManager::BuildCommandToLaunchPaCONodeContainer(const Engines::Co if (last == std::string::npos) last = -1; - if (resource_definition.Protocol == rsh) + if (resource_definition.protocol == rsh) command_remote_stream << "rcp "; else command_remote_stream << "scp "; command_remote_stream << machine_file_name << " "; - command_remote_stream << resource_definition.UserName << "@"; - command_remote_stream << hostname << ":" << resource_definition.AppliPath; + command_remote_stream << resource_definition.username << "@"; + command_remote_stream << hostname << ":" << resource_definition.applipath; command_remote_stream << "/" << machine_file_name.substr(last+1); int status = SystemThreadSafe(command_remote_stream.str().c_str()); @@ -1953,9 +1952,9 @@ SALOME_ContainerManager::BuildCommandToLaunchPaCONodeContainer(const Engines::Co command_nodes << resource_definition.getAccessProtocolTypeStr(); command_nodes << " -l "; - command_nodes << resource_definition.UserName; + command_nodes << resource_definition.username; command_nodes << " " << hostname; - command_nodes << " " << resource_definition.AppliPath; + command_nodes << " " << resource_definition.applipath; command_nodes << "/runRemote.sh "; command_nodes << GetenvThreadSafeAsString("NSHOST") << " "; // hostname of CORBA name server command_nodes << GetenvThreadSafeAsString("NSPORT") << " "; // port of CORBA name server diff --git a/src/Container/SALOME_ContainerManager.hxx b/src/Container/SALOME_ContainerManager.hxx index 9c75c71d2..8f420a030 100644 --- a/src/Container/SALOME_ContainerManager.hxx +++ b/src/Container/SALOME_ContainerManager.hxx @@ -28,7 +28,7 @@ #include #include CORBA_CLIENT_HEADER(SALOME_Component) #include CORBA_CLIENT_HEADER(SALOME_ContainerManager) -#include "SALOME_ResourcesCatalog_Parser.hxx" +#include "SALOME_ParserResourcesTypeContainer.hxx" #include "Utils_Mutex.hxx" diff --git a/src/Container/Test/testcontainer.py b/src/Container/Test/testcontainer.py index d0b677960..ebef8f452 100644 --- a/src/Container/Test/testcontainer.py +++ b/src/Container/Test/testcontainer.py @@ -20,7 +20,7 @@ import unittest from os import getcwd -from Engines import ContainerParameters, ResourceParameters +from Engines import ContainerParameters, ResourceParametersContainer import SALOME import salome @@ -28,10 +28,9 @@ from time import sleep class TestResourceManager(unittest.TestCase): def getContainer(self, name): - rp = ResourceParameters(name="localhost", + rp = ResourceParametersContainer( + name="localhost", hostname="localhost", - can_launch_batch_jobs=False, - can_run_containers=True, OS="Linux", componentList=[], nb_proc=1, diff --git a/src/Launcher/BatchTest.cxx b/src/Launcher/BatchTest.cxx index ff6b16914..8a66d28eb 100644 --- a/src/Launcher/BatchTest.cxx +++ b/src/Launcher/BatchTest.cxx @@ -37,7 +37,7 @@ #ifdef WIN32 # include #endif -BatchTest::BatchTest(const Engines::ResourceDefinition& batch_descr) +BatchTest::BatchTest(const Engines::ResourceDefinitionJob& batch_descr) { #ifdef WITH_LIBBATCH _batch_descr = batch_descr; diff --git a/src/Launcher/BatchTest.hxx b/src/Launcher/BatchTest.hxx index 449fdee87..e38feed70 100644 --- a/src/Launcher/BatchTest.hxx +++ b/src/Launcher/BatchTest.hxx @@ -33,7 +33,7 @@ class SALOMELAUNCHER_EXPORT BatchTest { public: - BatchTest(const Engines::ResourceDefinition& batch_descr); + BatchTest(const Engines::ResourceDefinitionJob& batch_descr); virtual ~BatchTest(); bool test(); @@ -49,7 +49,7 @@ class SALOMELAUNCHER_EXPORT BatchTest std::string get_home(std::string * home); private: - Engines::ResourceDefinition _batch_descr; + Engines::ResourceDefinitionJob _batch_descr; std::string _test_filename; std::string _base_filename; std::string _date; diff --git a/src/Launcher/Launcher.cxx b/src/Launcher/Launcher.cxx index 0a0958d24..63ea28b1c 100644 --- a/src/Launcher/Launcher.cxx +++ b/src/Launcher/Launcher.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -293,7 +294,7 @@ Launcher_cpp::getJobResults(int job_id, std::string directory) LAUNCHER_MESSAGE("Get Job results"); Launcher::Job * job = findJob(job_id); - std::string resource_name = job->getResourceDefinition().Name; + std::string resource_name = job->getResourceDefinition().name; try { if (directory != "") @@ -344,7 +345,7 @@ Launcher_cpp::getJobDumpState(int job_id, std::string directory) LAUNCHER_MESSAGE("Get Job dump state"); Launcher::Job * job = findJob(job_id); - std::string resource_name = job->getResourceDefinition().Name; + std::string resource_name = job->getResourceDefinition().name; try { if (directory != "") @@ -375,7 +376,7 @@ Launcher_cpp::getJobWorkFile(int job_id, LAUNCHER_MESSAGE("Get working file " << work_file); Launcher::Job * job = findJob(job_id); - std::string resource_name = job->getResourceDefinition().Name; + std::string resource_name = job->getResourceDefinition().name; try { if (directory != "") @@ -492,7 +493,7 @@ Launcher_cpp::getJobParameters(int job_id) job_parameters.wckey = job->getWCKey(); job_parameters.extra_params = job->getExtraParams(); - resourceParams resource_params = job->getResourceRequiredParams(); + resourceParamsContainer resource_params = job->getResourceRequiredParams(); job_parameters.resource_required.name = resource_params.name; job_parameters.resource_required.hostname = resource_params.hostname; job_parameters.resource_required.OS = resource_params.OS; @@ -547,7 +548,7 @@ Launcher_cpp::createJobWithFile(const std::string xmlExecuteFile, for(size_t i=0; i < job_params.OutputFile.size();i++) new_job->add_out_file(job_params.OutputFile[i]); - resourceParams p; + resourceParamsContainer p; p.hostname = clusterName; p.name = ""; p.OS = ""; @@ -568,15 +569,15 @@ Launcher_cpp::createJobWithFile(const std::string xmlExecuteFile, */ //============================================================================= Batch::BatchManager * -Launcher_cpp::FactoryBatchManager(ParserResourcesType& params) +Launcher_cpp::FactoryBatchManager(ParserResourcesTypeJob& params) { std::string mpi; Batch::CommunicationProtocolType protocol; Batch::FactBatchManager * fact; - std::string hostname = params.HostName; + std::string hostname = params.hostname; - switch(params.Protocol) + switch(params.protocol) { case sh: protocol = Batch::SH; @@ -595,7 +596,7 @@ Launcher_cpp::FactoryBatchManager(ParserResourcesType& params) break; } - switch(params.mpi) + switch(params.mpiImpl) { case lam: mpi = "lam"; @@ -623,7 +624,7 @@ Launcher_cpp::FactoryBatchManager(ParserResourcesType& params) } const char * bmType; - switch( params.Batch ) + switch( params.batch ) { case pbs: bmType = "PBS"; @@ -656,7 +657,7 @@ Launcher_cpp::FactoryBatchManager(ParserResourcesType& params) bmType = "COORM"; break; default: - LAUNCHER_MESSAGE("Bad batch description of the resource: Batch = " << params.Batch); + LAUNCHER_MESSAGE("Bad batch description of the resource: Batch = " << params.batch); throw LauncherException("No batchmanager for that cluster - Bad batch description of the resource"); } Batch::BatchManagerCatalog & cata = Batch::BatchManagerCatalog::getInstance(); @@ -666,7 +667,7 @@ Launcher_cpp::FactoryBatchManager(ParserResourcesType& params) throw LauncherException("Cannot find batch manager factory"); } LAUNCHER_MESSAGE("Instantiation of batch manager of type: " << bmType); - Batch::BatchManager * batch_client = (*fact)(hostname.c_str(), params.UserName.c_str(), + Batch::BatchManager * batch_client = (*fact)(hostname.c_str(), params.username.c_str(), protocol, mpi.c_str()); return batch_client; } @@ -861,12 +862,12 @@ Launcher_cpp::getBatchManager(Launcher::Job * job) // Select a resource for the job std::vector ResourceList; - resourceParams params = job->getResourceRequiredParams(); + resourceParamsContainer params = job->getResourceRequiredParams(); // Consider only resources that can launch batch jobs - params.can_launch_batch_jobs = true; + try { - ResourceList = _ResManager->GetFittingResources(params); + ResourceList = _ResManager->GetFittingResourcesContainer(params); } catch(const ResourcesException &ex) { @@ -880,7 +881,7 @@ Launcher_cpp::getBatchManager(Launcher::Job * job) } // Configure the job with the resource selected - the first of the list - ParserResourcesType resource_definition = _ResManager->GetResourcesDescr(ResourceList[0]); + ParserResourcesTypeJob resource_definition = _ResManager->GetResourceDefinitionJob(ResourceList[0]); // Set resource definition to the job // The job will check if the definitions needed diff --git a/src/Launcher/Launcher.hxx b/src/Launcher/Launcher.hxx index a0fe219cb..5f767194f 100644 --- a/src/Launcher/Launcher.hxx +++ b/src/Launcher/Launcher.hxx @@ -27,13 +27,8 @@ #include "Launcher_Job.hxx" #include "ResourcesManager.hxx" -#include - #include "SALOME_Launcher_Parser.hxx" -#include -#include -#include #include class MpiImpl; @@ -56,7 +51,7 @@ struct LAUNCHER_EXPORT JobParameters_cpp std::string local_directory; std::string result_directory; std::string maximum_duration; - resourceParams resource_required; + resourceParamsContainer resource_required; std::string queue; std::string partition; bool exclusive; @@ -118,7 +113,7 @@ protected: // Methods used by user interface methods #ifdef WITH_LIBBATCH - Batch::BatchManager *FactoryBatchManager(ParserResourcesType& params); + Batch::BatchManager *FactoryBatchManager(ParserResourcesTypeJob& params); std::map _batchmap; Batch::BatchManager* getBatchManager(Launcher::Job * job); #endif diff --git a/src/Launcher/Launcher_Job.cxx b/src/Launcher/Launcher_Job.cxx index 327784a95..20d1b92dd 100644 --- a/src/Launcher/Launcher_Job.cxx +++ b/src/Launcher/Launcher_Job.cxx @@ -185,11 +185,11 @@ Launcher::Job::getNumber() } void -Launcher::Job::setResourceDefinition(const ParserResourcesType & resource_definition) +Launcher::Job::setResourceDefinition(const ParserResourcesTypeJob& resource_definition) { // Check machine_definition std::string user_name = ""; - if (resource_definition.UserName == "") + if (resource_definition.username == "") { #ifndef WIN32 struct passwd *pwd = getpwuid(getuid()); @@ -210,13 +210,13 @@ Launcher::Job::setResourceDefinition(const ParserResourcesType & resource_defini } } else - user_name = resource_definition.UserName; + user_name = resource_definition.username; _resource_definition = resource_definition; - _resource_definition.UserName = user_name; + _resource_definition.username = user_name; } -ParserResourcesType +ParserResourcesTypeJob Launcher::Job::getResourceDefinition() const { return _resource_definition; @@ -315,7 +315,7 @@ Launcher::Job::setLauncherArgs(const std::string & launcher_args) } void -Launcher::Job::setResourceRequiredParams(const resourceParams & resource_required_params) +Launcher::Job::setResourceRequiredParams(const resourceParamsContainer& resource_required_params) { checkResourceRequiredParams(resource_required_params); _resource_required_params = resource_required_params; @@ -422,7 +422,7 @@ Launcher::Job::getLauncherArgs() const return _launcher_args; } -resourceParams +resourceParamsContainer Launcher::Job::getResourceRequiredParams() const { return _resource_required_params; @@ -527,14 +527,15 @@ Launcher::Job::checkMaximumDuration(const std::string & maximum_duration) } void -Launcher::Job::checkResourceRequiredParams(const resourceParams & resource_required_params) +Launcher::Job::checkResourceRequiredParams(const resourceParamsContainer& resource_required_params) { + // TODO: check if we need this check for a job: // nb_proc has be to > 0 - if (resource_required_params.nb_proc <= 0) - { - std::string message("[Launcher::Job::checkResourceRequiredParams] proc number is not > 0 ! "); - throw LauncherException(message); - } + // if (resource_required_params.nb_proc <= 0) + // { + // std::string message("[Launcher::Job::checkResourceRequiredParams] proc number is not > 0 ! "); + // throw LauncherException(message); + // } } long @@ -614,22 +615,23 @@ Launcher::Job::common_job_params() Batch::Parametre params; params[Batch::NAME] = getJobName(); - params[Batch::NBPROC] = _resource_required_params.nb_proc; - if(_resource_required_params.nb_proc_per_node > 0) - params[Batch::NBPROCPERNODE] = _resource_required_params.nb_proc_per_node; - - if(_resource_required_params.nb_node > 0) - params[Batch::NBNODE] = _resource_required_params.nb_node; - - // Memory in megabytes - if (_resource_required_params.mem_mb > 0) - { - params[Batch::MAXRAMSIZE] = _resource_required_params.mem_mb; - } - else if (_mem_per_cpu > 0) - { - params[Batch::MEMPERCPU] = (long)_mem_per_cpu; - } + // TODO: check if we use this params for jobs: + // params[Batch::NBPROC] = _resource_required_params.nb_proc; + // if(_resource_required_params.nb_proc_per_node > 0) + // params[Batch::NBPROCPERNODE] = _resource_required_params.nb_proc_per_node; + + // if(_resource_required_params.nb_node > 0) + // params[Batch::NBNODE] = _resource_required_params.nb_node; + + // // Memory in megabytes + // if (_resource_required_params.mem_mb > 0) + // { + // params[Batch::MAXRAMSIZE] = _resource_required_params.mem_mb; + // } + // else if (_mem_per_cpu > 0) + // { + // params[Batch::MEMPERCPU] = (long)_mem_per_cpu; + // } // We define a default directory if (_work_directory == "") diff --git a/src/Launcher/Launcher_Job.hxx b/src/Launcher/Launcher_Job.hxx index 800f96508..134f18e1c 100644 --- a/src/Launcher/Launcher_Job.hxx +++ b/src/Launcher/Launcher_Job.hxx @@ -29,9 +29,6 @@ #include #include -#include -#include -#include #include #include #include @@ -61,8 +58,8 @@ namespace Launcher void setNumber(const int & number); int getNumber(); - virtual void setResourceDefinition(const ParserResourcesType & resource_definition); - ParserResourcesType getResourceDefinition() const; + virtual void setResourceDefinition(const ParserResourcesTypeJob& resource_definition); + ParserResourcesTypeJob getResourceDefinition() const; // Common parameters void setJobName(const std::string & job_name); @@ -74,7 +71,7 @@ namespace Launcher void add_in_file(const std::string & file); void add_out_file(const std::string & file); void setMaximumDuration(const std::string & maximum_duration); - void setResourceRequiredParams(const resourceParams & resource_required_params); + void setResourceRequiredParams(const resourceParamsContainer & resource_required_params); void setQueue(const std::string & queue); void setPartition(const std::string & partition); void setEnvFile(const std::string & env_file); @@ -97,7 +94,7 @@ namespace Launcher const std::list & get_in_files() const; const std::list & get_out_files() const; std::string getMaximumDuration() const; - resourceParams getResourceRequiredParams() const; + resourceParamsContainer getResourceRequiredParams() const; std::string getQueue() const; std::string getPartition() const; std::string getEnvFile() const; @@ -122,7 +119,7 @@ namespace Launcher // Checks void checkMaximumDuration(const std::string & maximum_duration); - void checkResourceRequiredParams(const resourceParams & resource_required_params); + void checkResourceRequiredParams(const resourceParamsContainer & resource_required_params); // Helps long convertMaximumDuration(const std::string & maximum_duration); @@ -144,7 +141,7 @@ namespace Launcher std::string _launch_date; std::string _env_file; - ParserResourcesType _resource_definition; + ParserResourcesTypeJob _resource_definition; std::string _job_name; std::string _job_file; @@ -160,7 +157,7 @@ namespace Launcher std::map _specific_parameters; std::string _maximum_duration; long _maximum_duration_in_second; - resourceParams _resource_required_params; + resourceParamsContainer _resource_required_params; std::string _queue; std::string _partition; bool _exclusive; diff --git a/src/Launcher/Launcher_Job_Command.cxx b/src/Launcher/Launcher_Job_Command.cxx index 455d636c1..6e014a1e0 100644 --- a/src/Launcher/Launcher_Job_Command.cxx +++ b/src/Launcher/Launcher_Job_Command.cxx @@ -33,6 +33,7 @@ #endif #include +#include const char Launcher::Job_Command::TYPE_NAME[] = "command"; diff --git a/src/Launcher/Launcher_Job_CommandSALOME.cxx b/src/Launcher/Launcher_Job_CommandSALOME.cxx index 6686ff97f..a53eba32a 100644 --- a/src/Launcher/Launcher_Job_CommandSALOME.cxx +++ b/src/Launcher/Launcher_Job_CommandSALOME.cxx @@ -46,12 +46,12 @@ std::string Launcher::Job_CommandSALOME::runCommandString() struct stat statbuf; if(stat(getenv("APPLI"), &statbuf) ==0 && S_ISREG(statbuf.st_mode)) // case of a salome launcher file - result << _resource_definition.AppliPath + result << _resource_definition.applipath << " shell ./" << _job_file_name_complete; else // case of a salome appli dir - result << _resource_definition.AppliPath + result << _resource_definition.applipath << "/salome shell ./" << _job_file_name_complete; return result.str(); diff --git a/src/Launcher/Launcher_Job_PythonSALOME.cxx b/src/Launcher/Launcher_Job_PythonSALOME.cxx index c9eeab7aa..5854d0756 100644 --- a/src/Launcher/Launcher_Job_PythonSALOME.cxx +++ b/src/Launcher/Launcher_Job_PythonSALOME.cxx @@ -21,6 +21,7 @@ // #include "Launcher_Job_PythonSALOME.hxx" #include +#include const char Launcher::Job_PythonSALOME::TYPE_NAME[] = "python_salome"; @@ -38,12 +39,12 @@ Launcher::Job_PythonSALOME::setJobFile(const std::string & job_file) } void -Launcher::Job_PythonSALOME::addJobTypeSpecificScript(std::ofstream & launch_script_stream) +Launcher::Job_PythonSALOME::addJobTypeSpecificScript(std::ofstream& launch_script_stream) { struct stat statbuf; if(stat(getenv("APPLI"), &statbuf) ==0 && S_ISREG(statbuf.st_mode)) - // case where AppliPath hold a salome launcher file - launch_script_stream << _resource_definition.AppliPath << " shell -- python " << _job_file_name_complete << " > logs/python_" << _launch_date << ".log 2>&1" << std::endl; + // case where applipath hold a salome launcher file + launch_script_stream << _resource_definition.applipath << " shell -- python " << _job_file_name_complete << " > logs/python_" << _launch_date << ".log 2>&1" << std::endl; else - launch_script_stream << _resource_definition.AppliPath << "/salome shell -- python " << _job_file_name_complete << " > logs/python_" << _launch_date << ".log 2>&1" << std::endl; + launch_script_stream << _resource_definition.applipath << "/salome shell -- python " << _job_file_name_complete << " > logs/python_" << _launch_date << ".log 2>&1" << std::endl; } diff --git a/src/Launcher/Launcher_Job_SALOME.cxx b/src/Launcher/Launcher_Job_SALOME.cxx index 9efe9ab3a..846a16872 100644 --- a/src/Launcher/Launcher_Job_SALOME.cxx +++ b/src/Launcher/Launcher_Job_SALOME.cxx @@ -34,6 +34,7 @@ #include #include +#include Launcher::Job_SALOME::Job_SALOME(bool activateSession) : _activateSession(activateSession){} @@ -41,12 +42,12 @@ Launcher::Job_SALOME::Job_SALOME(bool activateSession) Launcher::Job_SALOME::~Job_SALOME() {} void -Launcher::Job_SALOME::setResourceDefinition(const ParserResourcesType & resource_definition) +Launcher::Job_SALOME::setResourceDefinition(const ParserResourcesTypeJob& resource_definition) { // Check resource_definition - if (resource_definition.AppliPath == "") + if (resource_definition.applipath == "") { - std::string mess = "Resource definition must define an application path !, resource name is: " + resource_definition.Name; + std::string mess = "Resource definition must define an application path !, resource name is: " + resource_definition.name; throw LauncherException(mess); } Launcher::Job::setResourceDefinition(resource_definition); @@ -121,8 +122,8 @@ Launcher::Job_SALOME::buildSalomeScript(Batch::Parametre params) launch_script_stream << "echo ' hostname='\\\"\"$host_basename\"\\\"" << std::endl; launch_script_stream << "echo ' type=\"single_machine\"'" << std::endl; launch_script_stream << "echo ' protocol=\"" << resource_protocol << "\"'" << std::endl; - launch_script_stream << "echo ' userName=\"" << _resource_definition.UserName << "\"'" << std::endl; - launch_script_stream << "echo ' appliPath=\"" << _resource_definition.AppliPath << "\"'" << std::endl; + launch_script_stream << "echo ' userName=\"" << _resource_definition.username << "\"'" << std::endl; + launch_script_stream << "echo ' appliPath=\"" << _resource_definition.applipath << "\"'" << std::endl; launch_script_stream << "echo ' mpi=\"" << _resource_definition.getMpiImplTypeStr() << "\"'" << std::endl; launch_script_stream << "echo ' nbOfNodes='\\\"\"$nbproc\"\\\"" << std::endl; launch_script_stream << "echo ' nbOfProcPerNode=\"1\"'" << std::endl; diff --git a/src/Launcher/Launcher_Job_SALOME.hxx b/src/Launcher/Launcher_Job_SALOME.hxx index 091f60807..d01240fd3 100644 --- a/src/Launcher/Launcher_Job_SALOME.hxx +++ b/src/Launcher/Launcher_Job_SALOME.hxx @@ -38,7 +38,7 @@ namespace Launcher Job_SALOME(bool activateSession=true); virtual ~Job_SALOME(); - virtual void setResourceDefinition(const ParserResourcesType & resource_definition); + virtual void setResourceDefinition(const ParserResourcesTypeJob& resource_definition); virtual void update_job(); #ifdef WITH_LIBBATCH diff --git a/src/Launcher/Launcher_Job_YACSFile.cxx b/src/Launcher/Launcher_Job_YACSFile.cxx index f608082f5..9c6ce1577 100644 --- a/src/Launcher/Launcher_Job_YACSFile.cxx +++ b/src/Launcher/Launcher_Job_YACSFile.cxx @@ -21,6 +21,7 @@ // #include "Launcher_Job_YACSFile.hxx" #include +#include #include const char Launcher::Job_YACSFile::TYPE_NAME[] = "yacs_file"; @@ -47,9 +48,9 @@ Launcher::Job_YACSFile::addJobTypeSpecificScript(std::ofstream & launch_script_s struct stat statbuf; if(stat(getenv("APPLI"), &statbuf) ==0 && S_ISREG(statbuf.st_mode)) // case of a salome launcher file - launch_script_stream << _resource_definition.AppliPath << " shell -- driver " << _job_file_name_complete; + launch_script_stream << _resource_definition.applipath << " shell -- driver " << _job_file_name_complete; else - launch_script_stream << _resource_definition.AppliPath << "/salome shell -- driver " << _job_file_name_complete; + launch_script_stream << _resource_definition.applipath << "/salome shell -- driver " << _job_file_name_complete; if (_dumpState > 0) launch_script_stream << " --dump=" << _dumpState; if(! _yacsDriverOptions.empty()) diff --git a/src/Launcher/Launcher_XML_Persistence.cxx b/src/Launcher/Launcher_XML_Persistence.cxx index 786525a73..a76a776af 100644 --- a/src/Launcher/Launcher_XML_Persistence.cxx +++ b/src/Launcher/Launcher_XML_Persistence.cxx @@ -175,23 +175,24 @@ XML_Persistence::addJobToXmlDocument(xmlNodePtr root_node, const Job & job) } // Resource part - resourceParams resource_params = job.getResourceRequiredParams(); + resourceParamsContainer resource_params = job.getResourceRequiredParams(); xmlNodePtr res_node = addNode(node, "resource_params", ""); addNode(res_node, "name", resource_params.name); if (!resource_params.hostname.empty()) addNode(res_node, "hostname", resource_params.hostname); - if (!resource_params.OS.empty()) - addNode(res_node, "OS", resource_params.OS); - if (resource_params.nb_proc > 0) - addNumericalNode(res_node, "nb_proc", resource_params.nb_proc); - if (resource_params.nb_node > 0) - addNumericalNode(res_node, "nb_node", resource_params.nb_node); - if (resource_params.nb_proc_per_node > 0) - addNumericalNode(res_node, "nb_proc_per_node", resource_params.nb_proc_per_node); - if (resource_params.cpu_clock > 0) - addNumericalNode(res_node, "cpu_clock", resource_params.cpu_clock); - if (resource_params.mem_mb > 0) - addNumericalNode(res_node, "mem_mb", resource_params.mem_mb); + // TODO: check if we don't need these params for a job: + // if (!resource_params.OS.empty()) + // addNode(res_node, "OS", resource_params.OS); + // if (resource_params.nb_proc > 0) + // addNumericalNode(res_node, "nb_proc", resource_params.nb_proc); + // if (resource_params.nb_node > 0) + // addNumericalNode(res_node, "nb_node", resource_params.nb_node); + // if (resource_params.nb_proc_per_node > 0) + // addNumericalNode(res_node, "nb_proc_per_node", resource_params.nb_proc_per_node); + // if (resource_params.cpu_clock > 0) + // addNumericalNode(res_node, "cpu_clock", resource_params.cpu_clock); + // if (resource_params.mem_mb > 0) + // addNumericalNode(res_node, "mem_mb", resource_params.mem_mb); if (!job.getMaximumDuration().empty()) addNode(node, "maximum_duration", job.getMaximumDuration()); @@ -393,7 +394,7 @@ XML_Persistence::parseUserNode(Job * new_job, xmlNodePtr user_node) void XML_Persistence::parseResourceNode(Job * new_job, xmlNodePtr res_node) { - resourceParams p; + resourceParamsContainer p; xmlNodePtr current_node = xmlFirstElementChild(res_node); while (current_node != NULL) { diff --git a/src/Launcher/SALOME_Launcher.cxx b/src/Launcher/SALOME_Launcher.cxx index 5f19212fe..6b876147f 100644 --- a/src/Launcher/SALOME_Launcher.cxx +++ b/src/Launcher/SALOME_Launcher.cxx @@ -347,22 +347,21 @@ SALOME_Launcher::createJobWithFile(const char * xmlExecuteFile, */ //============================================================================= CORBA::Boolean -SALOME_Launcher::testBatch(const Engines::ResourceParameters& params) +SALOME_Launcher::testBatch(const Engines::ResourceParametersJob& params) { MESSAGE("BEGIN OF SALOME_Launcher::testBatch"); CORBA::Boolean rtn = false; try { // Consider only resources that can run batch jobs - Engines::ResourceParameters new_params(params); - new_params.can_launch_batch_jobs = true; + Engines::ResourceParametersJob new_params(params); // find a resource matching the required parameters - Engines::ResourceList *aMachineList = _ResManager->GetFittingResources(new_params); + Engines::ResourceList *aMachineList = _ResManager->GetFittingResourcesJob(new_params); if (aMachineList->length() == 0) throw SALOME_Exception("No resources have been found with your parameters"); - const Engines::ResourceDefinition* p = _ResManager->GetResourceDefinition((*aMachineList)[0]); + const Engines::ResourceDefinitionJob* p = _ResManager->GetResourceDefinitionJob((*aMachineList)[0]); std::string resource_name(p->name); INFOS("Choose resource for test: " << resource_name); @@ -629,7 +628,7 @@ SALOME_Launcher::JobParameters_CORBA2CPP( result.result_directory = job_parameters.result_directory.in(); result.maximum_duration = job_parameters.maximum_duration.in(); - result.resource_required = resourceParameters_CORBAtoCPP(job_parameters.resource_required); + result.resource_required = resourceParametersContainer_CORBAtoCPP(job_parameters.resource_required); result.queue = job_parameters.queue.in(); result.partition = job_parameters.partition.in(); @@ -678,7 +677,7 @@ SALOME_Launcher::JobParameters_CPP2CORBA(const JobParameters_cpp& job_parameters result->result_directory = CORBA::string_dup(job_parameters.result_directory.c_str()); result->maximum_duration = CORBA::string_dup(job_parameters.maximum_duration.c_str()); - result->resource_required = resourceParameters_CPPtoCORBA(job_parameters.resource_required); + result->resource_required = resourceParametersContainer_CPPtoCORBA(job_parameters.resource_required); result->queue = CORBA::string_dup(job_parameters.queue.c_str()); result->partition = CORBA::string_dup(job_parameters.partition.c_str()); diff --git a/src/Launcher/SALOME_Launcher.hxx b/src/Launcher/SALOME_Launcher.hxx index bcb084953..6e48ed45b 100644 --- a/src/Launcher/SALOME_Launcher.hxx +++ b/src/Launcher/SALOME_Launcher.hxx @@ -62,7 +62,7 @@ public: // Useful methods CORBA::Long createJobWithFile(const char * xmlExecuteFile, const char * clusterName); - CORBA::Boolean testBatch (const Engines::ResourceParameters& params); + CORBA::Boolean testBatch (const Engines::ResourceParametersJob& params); // SALOME Kernel service methods void Shutdown(); diff --git a/src/Launcher/Test/TestSSLAttached.py b/src/Launcher/Test/TestSSLAttached.py index 0153e8d32..40ad28973 100644 --- a/src/Launcher/Test/TestSSLAttached.py +++ b/src/Launcher/Test/TestSSLAttached.py @@ -25,10 +25,9 @@ import salome import Engines salome.salome_init_without_session() -rp=Engines.ResourceParameters(name="localhost", +rp=Engines.ResourceParametersContainer( + name="localhost", hostname="localhost", - can_launch_batch_jobs=False, - can_run_containers=True, OS="Linux", componentList=[], nb_proc=1, diff --git a/src/Launcher/Test/launcher_use_case.py b/src/Launcher/Test/launcher_use_case.py index ebc9b83bb..f18316739 100644 --- a/src/Launcher/Test/launcher_use_case.py +++ b/src/Launcher/Test/launcher_use_case.py @@ -31,7 +31,7 @@ if __name__ == '__main__': salome.salome_init() launcher = salome.naming_service.Resolve('/SalomeLauncher') job_params = salome.JobParameters() - job_params.resource_required = salome.ResourceParameters() + job_params.resource_required = salome.ResourceParametersContainer() job_params.resource_required.name = "localhost" job_params.resource_required.nb_proc = 1 # slurm: --ntasks diff --git a/src/Launcher/Test/test_launcher.py b/src/Launcher/Test/test_launcher.py index 06a66915a..5ed629dca 100755 --- a/src/Launcher/Test/test_launcher.py +++ b/src/Launcher/Test/test_launcher.py @@ -65,10 +65,10 @@ class TestCompo(unittest.TestCase): # salome_runtime.addCatalog(session_catalog) # Get the list of possible ressources - ressource_param = salome.ResourceParameters() - ressource_param.can_launch_batch_jobs = True + ressource_param = salome.ResourceParametersContainer() + rm = salome.lcc.getResourcesManager() - cls.ressources = rm.GetFittingResources(ressource_param) + cls.ressources = rm.GetFittingResourcesContainer(ressource_param) def verifyFile(self, path, content): try: @@ -82,7 +82,7 @@ class TestCompo(unittest.TestCase): def create_JobParameters(self): job_params = salome.JobParameters() job_params.wckey="P11N0:SALOME" #needed by edf clusters - job_params.resource_required = salome.ResourceParameters() + job_params.resource_required = salome.ResourceParametersContainer() job_params.resource_required.nb_proc = 1 return job_params @@ -237,7 +237,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "CommandJob" + self.suffix) job_params.work_directory = wd @@ -340,7 +340,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "YacsJob" + self.suffix) job_params.work_directory = wd @@ -451,7 +451,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "YacsJobOpt" + self.suffix) job_params.work_directory = wd @@ -531,7 +531,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "CommandPreJob" + self.suffix) job_params.work_directory = wd @@ -625,7 +625,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "CommandSalomeJob" + self.suffix) job_params.work_directory = wd diff --git a/src/Launcher_SWIG/Launcher.i b/src/Launcher_SWIG/Launcher.i index 72913846d..e1c39af05 100644 --- a/src/Launcher_SWIG/Launcher.i +++ b/src/Launcher_SWIG/Launcher.i @@ -25,24 +25,28 @@ struct ResourceDefinition_cpp { -public: std::string name; std::string hostname; - std::string type; std::string protocol; std::string username; std::string applipath; + std::string batch; +}; + +struct ResourceDefinitionJob_cpp : ResourceDefinition_cpp +{ + std::string mpiImpl; + std::string iprotocol; + std::string working_directory; +}; + +struct ResourceDefinitionContainer_cpp : ResourceDefinition_cpp +{ std::string OS; int mem_mb; int cpu_clock; int nb_node; int nb_proc_per_node; - std::string batch; - std::string mpiImpl; - std::string iprotocol; - bool can_launch_batch_jobs; - bool can_run_containers; - std::string working_directory; }; %} @@ -64,20 +68,29 @@ namespace std { %naturalvar JobParameters_cpp::resourceList; struct resourceParams { - resourceParams(); + //resourceParams(); std::string name; std::string hostname; - bool can_launch_batch_jobs; - bool can_run_containers; + + std::vector resourceList; +}; + +struct resourceParamsJob : resourceParams +{ +}; + +struct resourceParamsContainer : resourceParams +{ std::string OS; + long nb_proc; long nb_node; long nb_proc_per_node; long cpu_clock; long mem_mb; + std::vector componentList; - std::vector resourceList; }; // see JobParameters from SALOME_Launcher.idl @@ -99,7 +112,7 @@ public: std::string local_directory; std::string result_directory; std::string maximum_duration; - resourceParams resource_required; + resourceParamsContainer resource_required; std::string queue; std::string partition; bool exclusive; @@ -115,24 +128,28 @@ public: // no other c++ equivalent. Convertion from ParserResourcesType struct ResourceDefinition_cpp { -public: std::string name; std::string hostname; - std::string type; std::string protocol; std::string username; std::string applipath; + std::string batch; +}; + +struct ResourceDefinitionJob_cpp : ResourceDefinition_cpp +{ + std::string mpiImpl; + std::string iprotocol; + std::string working_directory; +}; + +struct ResourceDefinitionContainer_cpp : ResourceDefinition_cpp +{ std::string OS; int mem_mb; int cpu_clock; int nb_node; int nb_proc_per_node; - std::string batch; - std::string mpiImpl; - std::string iprotocol; - bool can_launch_batch_jobs; - bool can_run_containers; - std::string working_directory; }; %exception @@ -158,34 +175,54 @@ class ResourcesManager_cpp { public: ResourcesManager_cpp(const char *xmlFilePath); - std::vector GetFittingResources(const resourceParams& params); + std::vector GetFittingResourcesJob(const resourceParamsJob& params); + std::vector GetFittingResourcesContainer(const resourceParamsContainer& params); + %extend { - ResourceDefinition_cpp GetResourceDefinition(const std::string& name) + ResourceDefinitionJob_cpp GetResourceDefinitionJob(const std::string& name) { - ResourceDefinition_cpp swig_result; - ParserResourcesType cpp_result = $self->GetResourcesDescr(name); + ResourceDefinitionJob_cpp swig_result; + ParserResourcesTypeJob cpp_result = $self->GetResourceDefinitionJob(name); - swig_result.name = cpp_result.Name; - swig_result.hostname = cpp_result.HostName; - swig_result.type = cpp_result.getResourceTypeStr(); + // Common params + swig_result.name = cpp_result.name; + swig_result.hostname = cpp_result.hostname; swig_result.protocol = cpp_result.getAccessProtocolTypeStr(); - swig_result.username = cpp_result.UserName; - swig_result.applipath = cpp_result.AppliPath; - swig_result.OS = cpp_result.OS; - swig_result.mem_mb = cpp_result.DataForSort._memInMB; - swig_result.cpu_clock = cpp_result.DataForSort._CPUFreqMHz; - swig_result.nb_node = cpp_result.DataForSort._nbOfNodes; - swig_result.nb_proc_per_node = cpp_result.DataForSort._nbOfProcPerNode; + swig_result.username = cpp_result.username; + swig_result.applipath = cpp_result.applipath; swig_result.batch = cpp_result.getBatchTypeStr(); + + // Job specific params swig_result.mpiImpl = cpp_result.getMpiImplTypeStr(); swig_result.iprotocol = cpp_result.getClusterInternalProtocolStr(); - swig_result.can_launch_batch_jobs = cpp_result.can_launch_batch_jobs; - swig_result.can_run_containers = cpp_result.can_run_containers; swig_result.working_directory = cpp_result.working_directory; return swig_result; } + + ResourceDefinitionContainer_cpp GetResourceDefinitionContainer(const std::string& name) + { + ResourceDefinitionContainer_cpp swig_result; + ParserResourcesTypeContainer cpp_result = $self->GetResourceDefinitionContainer(name); + + // Common params + swig_result.name = cpp_result.name; + swig_result.hostname = cpp_result.hostname; + swig_result.protocol = cpp_result.getAccessProtocolTypeStr(); + swig_result.username = cpp_result.username; + swig_result.applipath = cpp_result.applipath; + swig_result.batch = cpp_result.getBatchTypeStr(); + + // Container specific params + swig_result.OS = cpp_result.OS; + swig_result.mem_mb = cpp_result.dataForSort.mem_mb; + swig_result.cpu_clock = cpp_result.dataForSort.cpu_clock; + swig_result.nb_node = cpp_result.dataForSort.nb_node; + swig_result.nb_proc_per_node = cpp_result.dataForSort.nb_proc_per_node; + + return swig_result; + } } }; diff --git a/src/Launcher_SWIG/Test/test_swig_launcher.py b/src/Launcher_SWIG/Test/test_swig_launcher.py index 9cb0a974f..9f54d5b48 100755 --- a/src/Launcher_SWIG/Test/test_swig_launcher.py +++ b/src/Launcher_SWIG/Test/test_swig_launcher.py @@ -52,7 +52,7 @@ def createJobParameters(): return jp def createResourceParameters(): - return pylauncher.resourceParams() + return pylauncher.resourceParamsContainer() # Test of SalomeLauncher. # This test should be run in the salome environment, using "salome shell". @@ -76,9 +76,8 @@ class TestCompo(unittest.TestCase): # Get the list of possible ressources ressource_param = createResourceParameters() - ressource_param.can_launch_batch_jobs = True rm = createResourcesManager() - cls.ressources = rm.GetFittingResources(ressource_param) + cls.ressources = rm.GetFittingResourcesContainer(ressource_param) def verifyFile(self, path, content): try: @@ -245,7 +244,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "CommandJob" + self.suffix) job_params.work_directory = wd @@ -349,7 +348,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "YacsJob" + self.suffix) job_params.work_directory = wd @@ -464,7 +463,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "YacsJobOpt" + self.suffix) job_params.work_directory = wd @@ -544,7 +543,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "CommandPreJob" + self.suffix) job_params.work_directory = wd @@ -638,7 +637,7 @@ f.close() job_params.resource_required.name = resource # use the working directory of the resource - resParams = resManager.GetResourceDefinition(resource) + resParams = resManager.GetResourceDefinitionJob(resource) wd = os.path.join(resParams.working_directory, "CommandSalomeJob" + self.suffix) job_params.work_directory = wd diff --git a/src/Launcher_SWIG/test.py b/src/Launcher_SWIG/test.py index f95cbdd12..64f5ac8d6 100644 --- a/src/Launcher_SWIG/test.py +++ b/src/Launcher_SWIG/test.py @@ -24,7 +24,7 @@ jp.job_type = "command" jp.job_file = "/home/I35256/salome/scripts/job_sh/script.sh" jp.work_directory = "/tmp/wd" jp.result_directory = "/tmp/rd" -rp = pylauncher.resourceParams() +rp = pylauncher.resourceParamsContainer() rp.name="localhost" rp.hostname="localhost" rp.nb_proc = 1 diff --git a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx index 0890e8c66..2e5069c32 100644 --- a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx +++ b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx @@ -146,11 +146,11 @@ SALOME_LifeCycleCORBA::FindComponent(const Engines::ContainerParameters& params, Engines::ContainerParameters new_params(params); new_params.resource_params.componentList.length(1); new_params.resource_params.componentList[0] = componentName; - new_params.resource_params.can_run_containers = true; + Engines::ResourceList_var listOfResources; try { - listOfResources = _ResManager->GetFittingResources(new_params.resource_params); + listOfResources = _ResManager->GetFittingResourcesContainer(new_params.resource_params); } catch( const SALOME::SALOME_Exception& /*ex*/ ) //!< TODO: unused variable { @@ -185,12 +185,11 @@ SALOME_LifeCycleCORBA::LoadComponent(const Engines::ContainerParameters& params, Engines::ContainerParameters new_params(params); new_params.resource_params.componentList.length(1); new_params.resource_params.componentList[0] = componentName; - new_params.resource_params.can_run_containers = true; Engines::ResourceList_var listOfResources; try { - listOfResources = _ResManager->GetFittingResources(new_params.resource_params); + listOfResources = _ResManager->GetFittingResourcesContainer(new_params.resource_params); } catch( const SALOME::SALOME_Exception& /*ex*/ ) //!< TODO: unused variable { @@ -227,12 +226,11 @@ FindOrLoad_Component(const Engines::ContainerParameters& params, Engines::ContainerParameters new_params(params); new_params.resource_params.componentList.length(1); new_params.resource_params.componentList[0] = componentName; - new_params.resource_params.can_run_containers = true; Engines::ResourceList_var listOfResources; try { - listOfResources = _ResManager->GetFittingResources(new_params.resource_params); + listOfResources = _ResManager->GetFittingResourcesContainer(new_params.resource_params); } catch( const SALOME::SALOME_Exception& /*ex*/ ) //!< TODO: unused variable { @@ -342,7 +340,7 @@ bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName) //============================================================================= void -SALOME_LifeCycleCORBA::preSet(Engines::ResourceParameters& params) +SALOME_LifeCycleCORBA::preSet(Engines::ResourceParametersContainer& params) { params.name = ""; params.hostname = ""; @@ -353,8 +351,6 @@ SALOME_LifeCycleCORBA::preSet(Engines::ResourceParameters& params) params.nb_node = 0; params.nb_proc_per_node = 0; params.policy = ""; - params.can_launch_batch_jobs = false; - params.can_run_containers = false; } //============================================================================= @@ -667,8 +663,8 @@ _FindComponent(const Engines::ContainerParameters& params, for(unsigned int i=0; i < listOfResources.length(); i++) { const char * currentResource = listOfResources[i]; - Engines::ResourceDefinition_var resource_definition = - _ResManager->GetResourceDefinition(currentResource); + Engines::ResourceDefinitionContainer_var resource_definition = + _ResManager->GetResourceDefinitionContainer(currentResource); CORBA::Object_var obj = _NS->ResolveComponent(resource_definition->hostname.in(), containerName, componentName, @@ -682,8 +678,8 @@ _FindComponent(const Engines::ContainerParameters& params, { resourcesOK->length(lghtOfresourcesOK); CORBA::String_var bestResource = _ResManager->FindFirst(resourcesOK); - Engines::ResourceDefinition_var resource_definition = - _ResManager->GetResourceDefinition(bestResource); + Engines::ResourceDefinitionContainer_var resource_definition = + _ResManager->GetResourceDefinitionContainer(bestResource); CORBA::Object_var obj = _NS->ResolveComponent(resource_definition->hostname.in(), containerName, componentName, diff --git a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx index 13a9c52df..ceba58442 100644 --- a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx +++ b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx @@ -90,7 +90,7 @@ public: int NbProc(const Engines::ContainerParameters& params); - static void preSet(Engines::ResourceParameters& outparams); + static void preSet(Engines::ResourceParametersContainer& outparams); static void preSet(Engines::ContainerParameters& outparams); Engines::ContainerManager_ptr getContainerManager(); diff --git a/src/LifeCycleCORBA/Test/LifeCycleCORBATest.cxx b/src/LifeCycleCORBA/Test/LifeCycleCORBATest.cxx index a76d7c583..ec37077ac 100644 --- a/src/LifeCycleCORBA/Test/LifeCycleCORBATest.cxx +++ b/src/LifeCycleCORBA/Test/LifeCycleCORBATest.cxx @@ -696,9 +696,8 @@ std::string LifeCycleCORBATest::GetRemoteHost() _LCC.preSet(params); // empty params to get all the machines params.resource_params.componentList.length(1); params.resource_params.componentList[0]="SalomeTestComponent"; - params.resource_params.can_run_containers = true; - Engines::ResourceList_var hostList = resourcesManager->GetFittingResources(params.resource_params); + Engines::ResourceList_var hostList = resourcesManager->GetFittingResourcesContainer(params.resource_params); CPPUNIT_ASSERT(hostList->length() > 1); std::string localHost = Kernel_Utils::GetHostname(); @@ -706,7 +705,7 @@ std::string LifeCycleCORBATest::GetRemoteHost() for (unsigned int i=0; i < hostList->length(); i++) { const char* aMachine = hostList[i]; - Engines::ResourceDefinition_var resource_definition = resourcesManager->GetResourceDefinition(aMachine); + Engines::ResourceDefinitionContainer_var resource_definition = resourcesManager->GetResourceDefinitionContainer(aMachine); std::string machine(resource_definition->hostname.in()); if (machine != localHost) { diff --git a/src/LifeCycleCORBA/TestContainerManager.cxx b/src/LifeCycleCORBA/TestContainerManager.cxx index a2d160055..481968934 100644 --- a/src/LifeCycleCORBA/TestContainerManager.cxx +++ b/src/LifeCycleCORBA/TestContainerManager.cxx @@ -140,7 +140,7 @@ int main (int argc, char * argv[]) int nbpmax=1; for(std::map::iterator iter=cycle.begin();iter!=cycle.end();iter++){ if(strcmp((*iter).first.c_str(),"localhost")!=0){ - Engines::ResourceDefinition *p = _ResManager->GetResourceDefinition((*iter).first.c_str()); + Engines::ResourceDefinitionContainer *p = _ResManager->GetResourceDefinitionContainer((*iter).first.c_str()); int nbproc = p->nb_node * p->nb_proc_per_node; if(cycle[(*iter).first]/nbproccmax) cmax=cycle[(*iter).first]/nbproc; diff --git a/src/LifeCycleCORBA_SWIG/LifeCycleCORBA.py b/src/LifeCycleCORBA_SWIG/LifeCycleCORBA.py index 0302900af..2a59505ae 100644 --- a/src/LifeCycleCORBA_SWIG/LifeCycleCORBA.py +++ b/src/LifeCycleCORBA_SWIG/LifeCycleCORBA.py @@ -44,22 +44,22 @@ class LifeCycleCORBASSL(SALOME_LifeCycleCORBASSL): def FindOrLoadComponent(self, containerName, componentName): return SALOME_LifeCycleCORBA.FindOrLoad_Component(self,containerName,componentName) -class ContainerParameters (Engines.ContainerParameters): +class ContainerParameters(Engines.ContainerParameters): def __init__(self, container_name='', mode='start', workingdir='', nb_proc=0, isMPI=False, parallelLib='',resource_params=None): - if resource_params is None:resource_params=ResourceParameters() + if resource_params is None:resource_params=ResourceParametersContainer() Engines.ContainerParameters.__init__(self,container_name, mode, workingdir, nb_proc, isMPI, parallelLib,resource_params) -class ResourceParameters (Engines.ResourceParameters): - def __init__(self, name="", hostname="", OS="", componentList=None, - nb_proc=0, mem_mb=0, cpu_clock=0, nb_node=0, nb_proc_per_node=0, - policy="", resList=None, can_launch_batch_jobs = False, can_run_containers = False): +class ResourceParametersContainer(Engines.ResourceParametersContainer): + def __init__(self, name="", hostname="", + policy="", resList = None, + OS = "", componentList = None, nb_proc = 0, mem_mb = 0, cpu_clock = 0, nb_node = 0, nb_proc_per_node = 0): if componentList is None: componentList = [] if resList is None: resList = [] - Engines.ResourceParameters.__init__(self, name, hostname, can_launch_batch_jobs, can_run_containers, - OS, componentList, nb_proc, mem_mb, cpu_clock, nb_node, - nb_proc_per_node, policy, resList) + Engines.ResourceParametersContainer.__init__(self, name, hostname, + policy, resList, + OS, componentList, nb_proc, mem_mb, cpu_clock, nb_node, nb_proc_per_node) class JobParameters (Engines.JobParameters): def __init__(self, job_name="", job_type="", job_file="", pre_command="", env_file="", in_files=None, out_files=None, @@ -73,20 +73,20 @@ class JobParameters (Engines.JobParameters): out_files = [] if specific_parameters is None: specific_parameters = [] + if resource_required is None: + resource_required = ResourceParametersContainer() Engines.JobParameters.__init__(self, job_name, job_type, job_file, pre_command, env_file, in_files, out_files, work_directory, local_directory, result_directory, maximum_duration, resource_required, queue, partition, exclusive, mem_per_cpu, wckey, extra_params, specific_parameters, launcher_file, launcher_args) -class ResourceDefinition(Engines.ResourceDefinition): +class ResourceDefinitionContainer(Engines.ResourceDefinitionContainer): def __init__(self, name="", hostname="", protocol="rsh", username="", applipath="", componentList=None, mode="interactive", OS="", mem_mb=1, cpu_clock=1, nb_node=1, nb_proc_per_node=1, - batch="", mpiImpl="", iprotocol="rsh", type = "single_machine", - can_launch_batch_jobs = False, can_run_containers = False, working_directory = ""): + batch=""): if componentList is None: componentList = [] - Engines.ResourceDefinition.__init__(self, name, hostname, type, protocol, username, applipath, + Engines.ResourceDefinitionContainer.__init__(self, name, hostname, type, protocol, username, applipath, componentList, OS, mem_mb, cpu_clock, nb_node, nb_proc_per_node, - batch, mpiImpl, iprotocol, can_launch_batch_jobs, - can_run_containers, working_directory) + batch) diff --git a/src/LifeCycleCORBA_SWIG/Test/CatalogResources_resource.xml b/src/LifeCycleCORBA_SWIG/Test/CatalogResources_resource.xml index 38be2c067..f11b2a27e 100644 --- a/src/LifeCycleCORBA_SWIG/Test/CatalogResources_resource.xml +++ b/src/LifeCycleCORBA_SWIG/Test/CatalogResources_resource.xml @@ -1,15 +1,17 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/LifeCycleCORBA_SWIG/Test/testcontainermanager.py b/src/LifeCycleCORBA_SWIG/Test/testcontainermanager.py index 704a88a13..6b64bce4f 100644 --- a/src/LifeCycleCORBA_SWIG/Test/testcontainermanager.py +++ b/src/LifeCycleCORBA_SWIG/Test/testcontainermanager.py @@ -44,7 +44,7 @@ Test with catalog : def test0(self): """""" - rp=LifeCycleCORBA.ResourceParameters(policy="best",componentList=["PYHELLO"]) + rp=LifeCycleCORBA.ResourceParametersContainer(policy="best",componentList=["PYHELLO"]) p=LifeCycleCORBA.ContainerParameters(container_name=self.container_name,mode="start",resource_params=rp) co=cm.GiveContainer( p ) host1=co.getHostName() @@ -57,7 +57,7 @@ Test with catalog : def test1(self): """""" - rp=LifeCycleCORBA.ResourceParameters(policy="best",componentList=["PYHELLO"]) + rp=LifeCycleCORBA.ResourceParametersContainer(policy="best",componentList=["PYHELLO"]) p=LifeCycleCORBA.ContainerParameters(container_name=self.container_name,mode="get",resource_params=rp) co=cm.GiveContainer( p ) host1=co.getHostName() @@ -70,7 +70,7 @@ Test with catalog : def test2(self): """""" - rp=LifeCycleCORBA.ResourceParameters(policy="best",componentList=["PYHELLO"]) + rp=LifeCycleCORBA.ResourceParametersContainer(policy="best",componentList=["PYHELLO"]) p=LifeCycleCORBA.ContainerParameters(container_name=self.container_name,mode="getorstart",resource_params=rp) co=cm.GiveContainer( p ) host1=co.getHostName() diff --git a/src/LifeCycleCORBA_SWIG/Test/testresourcemanager.py b/src/LifeCycleCORBA_SWIG/Test/testresourcemanager.py index 25b3d2c53..6616b7f7e 100644 --- a/src/LifeCycleCORBA_SWIG/Test/testresourcemanager.py +++ b/src/LifeCycleCORBA_SWIG/Test/testresourcemanager.py @@ -31,18 +31,20 @@ class TestResourceManager(unittest.TestCase): Test with CatalogResources.xml: - - - - - - - - - - - - + + + + + + + + + + + + + + """ def setUp(self): @@ -50,63 +52,63 @@ Test with CatalogResources.xml: def test0(self): """host required""" - params=LifeCycleCORBA.ResourceParameters(hostname="m3") - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(hostname="m3") + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(machineList, ["m3"]) def test1(self): """OS required""" - params=LifeCycleCORBA.ResourceParameters(OS="Linux") - self.assertRaises(SALOME.SALOME_Exception,rm.GetFittingResources,params) + params=LifeCycleCORBA.ResourceParametersContainer(OS="Linux") + self.assertRaises(SALOME.SALOME_Exception,rm.GetFittingResourcesContainer,params) def test2(self): """component add required. If a resource doesn't have any module or component defined in the catalog, it means that it has every module and component and it fits for any request. """ - params=LifeCycleCORBA.ResourceParameters(componentList=["add"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["add"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(machineList, ['claui2c6', 'localhost', 'm1', 'm2']) def test3(self): """component tutu required""" - params=LifeCycleCORBA.ResourceParameters(componentList=["tutu"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["tutu"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(machineList, ['localhost', 'm1', 'm2', 'm3']) def test4(self): """component tata required""" - params=LifeCycleCORBA.ResourceParameters(componentList=["tata"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["tata"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(machineList, ['localhost', 'm1', 'm2']) def test5(self): """component titi required""" - params=LifeCycleCORBA.ResourceParameters(componentList=["titi"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["titi"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(machineList, ['localhost', 'm1', 'm2']) def test6(self): """component toto required""" - params=LifeCycleCORBA.ResourceParameters(componentList=["toto"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["toto"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(machineList, ['claui2c6', 'localhost', 'm1', 'm2']) def test7(self): """components add and toto required""" - params=LifeCycleCORBA.ResourceParameters(componentList=["add","toto"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["add","toto"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(machineList, ['claui2c6', 'localhost', 'm1', 'm2']) def test8(self): """components add and toto required""" - machineDef=rm.GetResourceDefinition('claui2c6') + machineDef=rm.GetResourceDefinitionContainer('claui2c6') self.assertEqual(machineDef.componentList, ['toto', 'add']) def test10(self): """policy altcycl""" - params=LifeCycleCORBA.ResourceParameters(componentList=["add","toto"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["add","toto"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(rm.Find('altcycl',machineList), "claui2c6") self.assertEqual(rm.Find('altcycl',machineList), "localhost") self.assertEqual(rm.Find('altcycl',machineList), "m1") @@ -118,8 +120,8 @@ Test with CatalogResources.xml: def test11(self): """policy cycl""" - params=LifeCycleCORBA.ResourceParameters(componentList=["add","toto"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["add","toto"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(rm.Find('cycl',machineList), "claui2c6") self.assertEqual(rm.Find('cycl',machineList), "localhost") self.assertEqual(rm.Find('cycl',machineList), "m1") @@ -131,15 +133,15 @@ Test with CatalogResources.xml: def test12(self): """policy first""" - params=LifeCycleCORBA.ResourceParameters(componentList=["add","toto"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["add","toto"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(rm.Find('first',machineList), "claui2c6") self.assertEqual(rm.Find('first',machineList), "claui2c6") def test13(self): """policy best""" - params=LifeCycleCORBA.ResourceParameters(componentList=["add","toto"]) - machineList=rm.GetFittingResources(params) + params=LifeCycleCORBA.ResourceParametersContainer(componentList=["add","toto"]) + machineList=rm.GetFittingResourcesContainer(params) self.assertEqual(rm.Find('best',machineList), "claui2c6") self.assertEqual(rm.Find('best',machineList), "localhost") self.assertEqual(rm.Find('best',machineList), "m1") diff --git a/src/ResourcesManager/CMakeLists.txt b/src/ResourcesManager/CMakeLists.txt index ffca1252f..fc7a9ce6e 100644 --- a/src/ResourcesManager/CMakeLists.txt +++ b/src/ResourcesManager/CMakeLists.txt @@ -40,7 +40,10 @@ SET(COMMON_LIBS ) SET(ResourcesManager_SOURCES - SALOME_ResourcesCatalog_Parser.cxx + SALOME_ParserResourceDataToSort.cxx + SALOME_ParserResourcesType.cxx + SALOME_ParserResourcesTypeContainer.cxx + SALOME_ParserResourcesTypeJob.cxx SALOME_ResourcesCatalog_Handler.cxx SALOME_LoadRateManager.cxx ResourcesManager.cxx @@ -67,7 +70,11 @@ SET(COMMON_HEADERS_HXX ResourcesManager.hxx ResourcesManager_Defs.hxx SALOME_LoadRateManager.hxx - SALOME_ResourcesCatalog_Parser.hxx + SALOME_ParserResourceDataToSort.hxx + SALOME_ParserResourcesType.hxx + SALOME_ParserResourcesTypeCommon.hxx + SALOME_ParserResourcesTypeContainer.hxx + SALOME_ParserResourcesTypeJob.hxx SALOME_ResourcesManager.hxx SALOME_ResourcesManager_Client.hxx SALOME_ResourcesManager_Common.hxx diff --git a/src/ResourcesManager/ResourcesManager.cxx b/src/ResourcesManager/ResourcesManager.cxx index 6e8535a7e..d9b9b7512 100644 --- a/src/ResourcesManager/ResourcesManager.cxx +++ b/src/ResourcesManager/ResourcesManager.cxx @@ -25,42 +25,139 @@ #include "SALOME_ResourcesCatalog_Handler.hxx" #include #include +#include "utilities.h" #include -#include -#include -#include -#include -#include #include #include #ifdef WIN32 #else #include #endif -#include #include +#include -#define MAX_SIZE_FOR_HOSTNAME 256; +namespace +{ + const std::string DEFAULT_RESOURCE_NAME = "localhost"; + const char* ENV_APPLI = "APPLI"; + + static LoadRateManagerFirst first; + static LoadRateManagerCycl cycl; + static LoadRateManagerAltCycl altcycl; + + template bool IsDefaultResource(const T& resource/*, const T& default_resource*/) + { + if ((resource.name == DEFAULT_RESOURCE_NAME || resource.name.empty()) && + (resource.hostname == DEFAULT_RESOURCE_NAME || resource.hostname == Kernel_Utils::GetHostname())) + { + return true; + } -using namespace std; + return false; + + // Some of the properties of the default resource shouldn't be modified + // TODO: check if it's a right set of properties to check + // std::string check; + // if (default_resource.hostname != resource.hostname) + // check += "The Hostname property of the default resource can not be modified.\n"; + // if (default_resource.applipath != resource.applipath) + // check += "The Applipath property of the default resource can not be modified.\n"; + // if (default_resource.protocol != resource.protocol) + // check += "The Protocol property of the default resource can not be modified.\n"; + // if (!check.empty()) + // throw ResourcesException(check); + } -const string ResourcesManager_cpp::DEFAULT_RESOURCE_NAME = "localhost"; + template void AddDefaultResourceInCatalogCommon(T& resource) + { + resource.name = DEFAULT_RESOURCE_NAME; + // We can't use "localhost" for parameter hostname because the containers are registered in the + // naming service with the real hostname, not "localhost" + resource.hostname = Kernel_Utils::GetHostname(); + resource.protocol = sh; + resource.batch = none; -static LoadRateManagerFirst first; -static LoadRateManagerCycl cycl; -static LoadRateManagerAltCycl altcycl; + const char* appliStr = getenv(ENV_APPLI); -resourceParams::resourceParams() -: can_launch_batch_jobs(false), - can_run_containers(false), - nb_proc(-1), - nb_node(0), - nb_proc_per_node(-1), - cpu_clock(-1), - mem_mb(-1) -{ +#ifndef WIN32 + struct stat statbuf; + std::string aHomePath = Kernel_Utils::HomePath(); + + if (aHomePath.length() && appliStr) + { + if (stat(appliStr, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) + { + // if $APPLI is a regular file, we asume it's a salome Launcher file + resource.applipath = std::string(appliStr); + } + else + { + resource.applipath = aHomePath + "/" + appliStr; + } + } +#else + const char* userprofileStr = getenv("USERPROFILE"); + if (userprofileStr && appliStr) + { + resource.applipath = std::string(userprofileStr) + "\\" + appliStr; + } +#endif + } + + template T GetResourceDefinition(const std::string& name, const U& resourceList) + { + const auto it = resourceList.find(name); + if (it != resourceList.end()) + return (*it).second; + + throw ResourcesException("Resource with a given name does not exist: " + name); + } + + template void RemoveResourceCommon(const char* name, T& resourceList) + { + const auto it = resourceList.find(name); + if (it == resourceList.end()) + { + MESSAGE("You try to delete a resource that does not exist... : " << name); + return; + } + + if (IsDefaultResource((*it).second)) + { + MESSAGE("Warning! You try to delete a default local resource: " << name); + return; + } + + resourceList.erase(name); + + // This is a previouse error handling. Leave here for reference: + // if (DEFAULT_RESOURCE_NAME == name){ + // std::string error("Cannot delete default local resource \"" + DEFAULT_RESOURCE_NAME + "\""); + // throw ResourcesException(error); + // } + } + + template ResourceList GetResourcesByHostname(const std::string& hostnameIn, const T& resourceList) + { + if (hostnameIn.empty()) + { + return {}; + } + + const std::string hostname = + hostnameIn == DEFAULT_RESOURCE_NAME ? Kernel_Utils::GetHostname() : hostnameIn; + + ResourceList result; + for (const auto& res : resourceList) + { + if (res.second.hostname == hostname) + result.push_back(res.first); + } + + return result; + } } //============================================================================= @@ -69,8 +166,7 @@ resourceParams::resourceParams() */ //============================================================================= -ResourcesManager_cpp:: -ResourcesManager_cpp(const char *xmlFilePath) +ResourcesManager_cpp::ResourcesManager_cpp(const char* xmlFilePath) { _path_resources.push_back(xmlFilePath); #if defined(_DEBUG_) || defined(_DEBUG) @@ -99,7 +195,7 @@ ResourcesManager_cpp(const char *xmlFilePath) ResourcesManager_cpp::ResourcesManager_cpp() { - RES_MESSAGE("ResourcesManager_cpp constructor"); + MESSAGE("ResourcesManager_cpp constructor"); _resourceManagerMap["first"]=&first; _resourceManagerMap["cycl"]=&cycl; @@ -110,26 +206,29 @@ ResourcesManager_cpp::ResourcesManager_cpp() AddDefaultResourceInCatalog(); bool default_catalog_resource = true; - if (getenv("USER_CATALOG_RESOURCES_FILE") != 0) + const char* userFileStr = getenv("USER_CATALOG_RESOURCES_FILE"); + if (userFileStr) { default_catalog_resource = false; - std::string user_file(""); - user_file = getenv("USER_CATALOG_RESOURCES_FILE"); + const std::string user_file(userFileStr); + std::ifstream ifile(user_file.c_str(), std::ifstream::in ); - if (ifile) { + if (ifile) + { // The file exists, and is open for input _path_resources.push_back(user_file); } - else { + else + { default_catalog_resource = false; - RES_INFOS("Warning: USER_CATALOG_RESOURCES_FILE is set and file cannot be found.") - RES_INFOS("Warning: That's why we try to create a new one.") + MESSAGE("Warning: USER_CATALOG_RESOURCES_FILE is set and file cannot be found.") + MESSAGE("Warning: That's why we try to create a new one.") std::ofstream user_catalog_file; user_catalog_file.open(user_file.c_str()); if (user_catalog_file.fail()) { - RES_INFOS("Error: cannot write in the user catalog resources files"); - RES_INFOS("Error: using default CatalogResources.xml file"); + MESSAGE("Error: cannot write in the user catalog resources files"); + MESSAGE("Error: using default CatalogResources.xml file"); default_catalog_resource = true; } else @@ -143,35 +242,39 @@ ResourcesManager_cpp::ResourcesManager_cpp() } } } + if (default_catalog_resource) { - std::string default_file(""); - if (getenv("APPLI") != 0) + const char* appliStr = getenv("APPLI"); + if (appliStr) { - default_file += Kernel_Utils::HomePath(); + std::string default_file = Kernel_Utils::HomePath(); default_file += "/"; - default_file += getenv("APPLI"); + default_file += appliStr; default_file += "/CatalogResources.xml"; - std::ifstream ifile(default_file.c_str(), std::ifstream::in ); - if (ifile) { + std::ifstream ifile(default_file.c_str(), std::ifstream::in); + if (ifile) + { // The file exists, and is open for input _path_resources.push_back(default_file); - default_catalog_resource=false; + default_catalog_resource = false; } } } + if (default_catalog_resource) { - std::string default_file(""); - if(!getenv("KERNEL_ROOT_DIR")) + const char* kernelRootStr = getenv("KERNEL_ROOT_DIR"); + if(!kernelRootStr) throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml"); - default_file = getenv("KERNEL_ROOT_DIR"); + + std::string default_file(kernelRootStr); default_file += "/share/salome/resources/kernel/CatalogResources.xml"; _path_resources.push_back(default_file); } ParseXmlFiles(); - RES_MESSAGE("ResourcesManager_cpp constructor end"); + MESSAGE("ResourcesManager_cpp constructor end"); } //============================================================================= @@ -182,266 +285,372 @@ ResourcesManager_cpp::ResourcesManager_cpp() ResourcesManager_cpp::~ResourcesManager_cpp() { - RES_MESSAGE("ResourcesManager_cpp destructor"); + MESSAGE("ResourcesManager_cpp destructor"); } +//! threadsafe //============================================================================= -//! get the list of resource names fitting constraints given by params +/*! + * Finds a container resource + */ +//============================================================================= +std::string ResourcesManager_cpp::Find(const std::string& policy, const ResourceList& possibleContainerResources) const +{ + auto it = _resourceManagerMap.find(policy); + if(it==_resourceManagerMap.end()) + { + it = _resourceManagerMap.find(""); + return ((*it).second)->Find(possibleContainerResources, _resourcesListContainer); + } + + return ((*it).second)->Find(possibleContainerResources, _resourcesListContainer); +} + +//============================================================================= +//! Get the list of job resource names fitting constraints given by params /*! * Steps: * 1: Restrict list with resourceList if defined * 2: If name is defined -> check resource list * 3: If not 2:, if hostname is defined -> check resource list - * 4: If not 3:, sort resource with nb_proc, etc... - * 5: In all cases remove resource that does not correspond with OS - * 6: And remove resource with componentList - if list is empty ignored it... */ //============================================================================= - -std::vector -ResourcesManager_cpp::GetFittingResources(const resourceParams& params) +ResourceList ResourcesManager_cpp::GetFittingResourcesJob(const resourceParamsJob& params) { - RES_MESSAGE("[GetFittingResources] on computer " << Kernel_Utils::GetHostname().c_str()); - RES_MESSAGE("[GetFittingResources] with resource name: " << params.name); - RES_MESSAGE("[GetFittingResources] with hostname: "<< params.hostname); + MESSAGE("GetFittingResourcesJob on computer: " << Kernel_Utils::GetHostname()); - // Result - std::vector vec; - - // Parse Again CalatogResource File ParseXmlFiles(); // Steps: // 1: If name is defined -> check resource list // 2: Restrict list with resourceList if defined // 3: If not 2:, if hostname is defined -> check resource list - // 4: If not 3:, sort resource with nb_proc, etc... - // 5: In all cases remove resource that does not correspond with OS - // 6: And remove resource with componentList - if list is empty ignored it... // Step 1 - if (params.name != "") - { - RES_MESSAGE("[GetFittingResources] name parameter found !"); - if (_resourcesList.find(params.name) != _resourcesList.end()) + if (!params.name.empty()) + { + if (_resourcesListJob.find(params.name) != _resourcesListJob.end()) { - vec.push_back(params.name); - return vec; + MESSAGE("Complete. Found a resource with a given name: " << params.name); + return { params.name }; } - else - RES_MESSAGE("[GetFittingResources] resource name was not found on resource list ! name requested was " << params.name); - std::string error("[GetFittingResources] resource name was not found on resource list ! name requested was " + params.name); - throw ResourcesException(error); + + throw ResourcesException("Resource name was not found in resource list! Requested name: " + params.name); } - MapOfParserResourcesType local_resourcesList = _resourcesList; - // Step 2 - if (params.resourceList.size() > 0) + // Step 3 + ResourceList result = GetResourcesByHostname(params.hostname, _resourcesListJob); + + // End + // Send an exception if return list is empty... + if (!result.size()) { - RES_MESSAGE("[GetFittingResources] Restricted resource list found !"); - local_resourcesList.clear(); - std::vector::size_type sz = params.resourceList.size(); + throw ResourcesException("ResourcesManager doesn't find any resource that fits to your parameters"); + } + + return result; +} + +//============================================================================= +//! Get the list of container resource names fitting constraints given by params +/*! + * Steps: + * 1: Restrict list with resourceList if defined + * 2: If name is defined -> check resource list + * 3: If not 2:, if hostname is defined -> check resource list + * 4: If not 3:, sort resource with nb_proc, etc... + * 5: In all cases remove resource that does not correspond with OS + * 6: And remove resource with componentList - if list is empty ignored it... + */ +//============================================================================= +ResourceList ResourcesManager_cpp::GetFittingResourcesContainer(const resourceParamsContainer& params) +{ + MESSAGE("GetFittingResourcesContainer on computer: " << Kernel_Utils::GetHostname()); + + // Parse Again CalatogResource File + ParseXmlFiles(); - for (unsigned int i=0; i < sz; i++) + // Step 1 + if (!params.name.empty()) + { + if (_resourcesListContainer.find(params.name) != _resourcesListContainer.end()) { - if (_resourcesList.find(params.resourceList[i]) != _resourcesList.end()) - local_resourcesList[params.resourceList[i]] = _resourcesList[params.resourceList[i]]; + MESSAGE("Complete. Found a resource with a given name: " << params.name); + return { params.name }; } + + throw ResourcesException("Resource name was not found in resource list! Requested name: " + params.name); } // Step 3 - if (params.hostname != "") + ResourceList result = GetResourcesByHostname(params.hostname, _resourcesListContainer); + + if (params.hostname.empty()) + { + // Step 2 + SortResourcesTypeContainerByData(params, result); + } + + // Step 5 + SelectOnlyResourcesWithOS(params.OS, result); + + // Step 6 + ResourceList vec_save(result); + KeepOnlyResourcesWithComponent(params.componentList, result); + if (!result.size()) + result = vec_save; + + // End + // Send an exception if return list is empty... + if (!result.size()) { - RES_MESSAGE("[GetFittingResources] Entering in hostname case !"); + throw ResourcesException("ResourcesManager doesn't find any resource that fits to your parameters"); + } - std::string hostname = params.hostname; - if (hostname == "localhost") - hostname = Kernel_Utils::GetHostname().c_str(); + return result; +} - std::map::const_iterator iter = _resourcesList.begin(); - for (; iter != _resourcesList.end(); iter++) +//! thread safe +//============================================================================= +/*! + * Get a job resource by given name + */ +//============================================================================= +ParserResourcesTypeJob ResourcesManager_cpp::GetResourceDefinitionJob(const std::string& name) const +{ + return GetResourceDefinition(name, _resourcesListJob); +} + +//============================================================================= +/*! + * Get a container resource by given name + */ +//============================================================================= +ParserResourcesTypeContainer ResourcesManager_cpp::GetResourceDefinitionContainer(const std::string& name) const +{ + return GetResourceDefinition(name, _resourcesListContainer); +} + +//============================================================================= +/*! + * Add a default job resource into catalog + */ +//============================================================================= +void ResourcesManager_cpp::AddDefaultResourceInCatalogJob() +{ + ParserResourcesTypeJob resource; + AddDefaultResourceInCatalogCommon(resource); + +#ifndef WIN32 + std::string tmpdir = "/tmp"; + const char* tmpdirStr = getenv("TMPDIR"); + if (tmpdirStr) + tmpdir = std::string(tmpdirStr); + + resource.working_directory = tmpdir + "/salome_localres_workdir"; + const char* userStr = getenv("USER"); + if (userStr) + resource.working_directory += std::string("_") + userStr; +#else + std::string tmpdir = "C:\\tmp"; + const char* tmpdirStr = getenv("TEMP"); + if (tmpdirStr) + tmpdir = std::string(tmpdirStr); + + resource.working_directory = tmpdir + "\\salome_localres_workdir"; + const char* usernameStr = getenv("USERNAME"); + if (usernameStr) + resource.working_directory += std::string("_") + usernameStr; +#endif + + _resourcesListJob[resource.name] = resource; +} + +//============================================================================= +/*! + * Add a default container resource into catalog + */ +//============================================================================= +void ResourcesManager_cpp::AddDefaultResourceInCatalogContainer() +{ + ParserResourcesTypeContainer resource; + AddDefaultResourceInCatalogCommon(resource); + + resource.dataForSort.name = DEFAULT_RESOURCE_NAME; + + _resourcesListContainer[resource.name] = resource; +} + +//============================================================================= +/*! + * Add all types of default resources into catalog + */ +//============================================================================= +void ResourcesManager_cpp::AddDefaultResourceInCatalog() +{ + AddDefaultResourceInCatalogJob(); + AddDefaultResourceInCatalogContainer(); +} + +//============================================================================= +/*! + * Add a job entry in the resources catalog + */ +//============================================================================= + +void ResourcesManager_cpp::AddResourceJob(const ParserResourcesTypeJob& resource) +{ + if (IsDefaultResource(resource)) + { + const auto it = _resourcesListJob.find(DEFAULT_RESOURCE_NAME); + if (it == _resourcesListJob.end()) { - if ((*iter).second.HostName == hostname) - vec.push_back((*iter).first); + _resourcesListJob[DEFAULT_RESOURCE_NAME] = resource; } + + return; } - // Step 4 - else - { - // --- Search for available resources sorted by priority - MapOfParserResourcesType_it i = local_resourcesList.begin(); - for (; i != local_resourcesList.end(); ++i) - vec.push_back(i->first); - - // --- set wanted parameters - ResourceDataToSort::_nbOfProcWanted = params.nb_proc; - ResourceDataToSort::_nbOfNodesWanted = params.nb_node; - ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node; - ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock; - ResourceDataToSort::_memInMBWanted = params.mem_mb; - // --- end of set - - // Sort - std::list li; - std::vector::iterator iter = vec.begin(); - for (; iter != vec.end(); iter++) - li.push_back(local_resourcesList[(*iter)].DataForSort); - li.sort(); - - vec.clear(); - for (std::list::iterator iter2 = li.begin(); iter2 != li.end(); iter2++) - vec.push_back((*iter2)._Name); + + if (!resource.name.empty()) + { + MESSAGE("Added a job resource: " << resource.name); + _resourcesListJob[resource.name] = resource; + + return; } - // Step 5 - SelectOnlyResourcesWithOS(vec, params.OS.c_str()); + MESSAGE("Warning! An attempt to add job resource with empty name. Using hostname as a key: " << resource.hostname); + _resourcesListJob[resource.hostname] = resource; +} - // Step 6 - std::vector vec_save(vec); - KeepOnlyResourcesWithComponent(vec, params.componentList); - if (vec.size() == 0) - vec = vec_save; +//============================================================================= +/*! + * Add a container entry in the resources catalog + */ +//============================================================================= - // Step 7 : Filter on possible usage - vector prev_list(vec); - vec.clear(); - for (vector::iterator iter = prev_list.begin() ; iter != prev_list.end() ; iter++) +void ResourcesManager_cpp::AddResourceContainer(const ParserResourcesTypeContainer& resource) +{ + if (IsDefaultResource(resource)) { - MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter); - if (it != _resourcesList.end() && - (!params.can_launch_batch_jobs || it->second.can_launch_batch_jobs) && - (!params.can_run_containers || it->second.can_run_containers)) - vec.push_back(*iter); + const auto it = _resourcesListContainer.find(DEFAULT_RESOURCE_NAME); + if (it != _resourcesListContainer.end()) + { + MESSAGE("An attempt to add default container resource. Using an old default object with overwritten DataForSort."); + + ParserResourcesTypeContainer& defaultContainer((*it).second); + defaultContainer.dataForSort.nb_node = resource.dataForSort.nb_node; + defaultContainer.dataForSort.nb_proc_per_node = resource.dataForSort.nb_proc_per_node; + defaultContainer.dataForSort.cpu_clock = resource.dataForSort.cpu_clock; + defaultContainer.dataForSort.mem_mb = resource.dataForSort.mem_mb; + } + else + { + MESSAGE("Warning! Added new default container resource: " << DEFAULT_RESOURCE_NAME); + _resourcesListContainer[DEFAULT_RESOURCE_NAME] = resource; + } + + return; } - // End - // Send an exception if return list is empty... - if (vec.size() == 0) + if (!resource.name.empty()) { - std::string error("[GetFittingResources] ResourcesManager doesn't find any resource that fits to your parameters"); - throw ResourcesException(error); + MESSAGE("Added a container resource: " << resource.name); + _resourcesListContainer[resource.name] = resource; + + return; } - return vec; + MESSAGE("Warning! An attempt to add container resource with empty name. Using hostname as a key: " << resource.hostname); + _resourcesListContainer[resource.hostname] = resource; } //============================================================================= /*! - * add an entry in the resources catalog xml file. + * Deletes a job resource from the catalog */ //============================================================================= - -void -ResourcesManager_cpp::AddResourceInCatalog(const ParserResourcesType & new_resource) +void ResourcesManager_cpp::RemoveResourceJob(const char* name) { - if (new_resource.Name == DEFAULT_RESOURCE_NAME){ - ParserResourcesType default_resource = _resourcesList[DEFAULT_RESOURCE_NAME]; - // some of the properties of the default resource shouldn't be modified - std::string check; - if( default_resource.HostName != new_resource.HostName) - check += "The Hostname property of the default resource can not be modified.\n"; - if( default_resource.AppliPath != new_resource.AppliPath) - check += "The Applipath property of the default resource can not be modified.\n"; - if( !new_resource.can_run_containers) - check += "The default resource should be able to run containers.\n"; - if( !new_resource.can_launch_batch_jobs) - check += "The default resource should be able to launch batch jobs.\n"; - if( default_resource.Protocol != new_resource.Protocol) - check += "The Protocol property of the default resource can not be modified.\n"; - if(!check.empty()) - throw ResourcesException(check); - } - // TODO - Add minimal check - _resourcesList[new_resource.Name] = new_resource; + RemoveResourceCommon(name, _resourcesListJob); } //============================================================================= /*! - * Deletes a resource from the catalog + * Deletes a container resource from the catalog */ //============================================================================= - -void ResourcesManager_cpp::DeleteResourceInCatalog(const char * name) +void ResourcesManager_cpp::RemoveResourceContainer(const char* name) { - if (DEFAULT_RESOURCE_NAME == name){ - std::string error("Cannot delete default local resource \"" + DEFAULT_RESOURCE_NAME + "\""); - throw ResourcesException(error); - } - MapOfParserResourcesType_it it = _resourcesList.find(name); - if (it != _resourcesList.end()) - _resourcesList.erase(name); - else - RES_INFOS("You try to delete a resource that does not exist... : " << name); + RemoveResourceCommon(name, _resourcesListContainer); } //============================================================================= /*! - * write the current data in memory in file. + * Write the current data in memory in file. */ //============================================================================= void ResourcesManager_cpp::WriteInXmlFile(std::string xml_file) { - RES_MESSAGE("WriteInXmlFile : start"); + MESSAGE("Start writing resource to XML file..."); - MapOfParserResourcesType resourceListToSave(_resourcesList); - if (resourceListToSave.empty()) + //MapOfParserResourcesType resourceListToSave(_resourcesList); + if (_resourcesListJob.empty() || _resourcesListContainer.empty()) { - RES_MESSAGE("WriteInXmlFile: nothing to do, no resource to save!"); + MESSAGE("Nothing to do, no resource to save!"); return; } - if (xml_file == "") + if (xml_file.empty()) { - _path_resources_it = _path_resources.begin(); - xml_file = *_path_resources_it; + if (_path_resources.empty()) + { + MESSAGE("Warning! Empty path to resource file. Return."); + return; + } + + xml_file = _path_resources.front(); } const char* aFilePath = xml_file.c_str(); FILE* aFile = fopen(aFilePath, "w"); - if (aFile == NULL) { - std::cerr << "Error opening file in WriteInXmlFile : " << xml_file << std::endl; + MESSAGE("Error opening file: " << xml_file); return; } xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0"); xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog"); - SALOME_ResourcesCatalog_Handler* handler = - new SALOME_ResourcesCatalog_Handler(resourceListToSave); - handler->PrepareDocToXmlFile(aDoc); - delete handler; + const std::unique_ptr handler( + new SALOME_ResourcesCatalog_Handler(_resourcesListJob, _resourcesListContainer)); + handler->writeXmlDoc(aDoc); - int isOk = xmlSaveFormatFile(aFilePath, aDoc, 1); - if (!isOk) - std::cerr << "Error while XML file saving : " << xml_file << std::endl; + if (xmlSaveFormatFile(aFilePath, aDoc, 1) == -1) + { + MESSAGE("Error saving file: " << xml_file); + } // Free the document xmlFreeDoc(aDoc); fclose(aFile); - RES_MESSAGE("WriteInXmlFile : WRITING DONE!"); -} -//============================================================================= -/*! - * parse the data type catalog - */ -//============================================================================= + MESSAGE("Complete! Resources has written in XML file: " << xml_file); +} -const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles() +bool ResourcesManager_cpp::IsNeedToParse() { // Parse file only if its modification time is greater than lasttime (last registered modification time) bool to_parse = false; - for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it) + for(const auto& path :_path_resources) { struct stat statinfo; - int result = stat((*_path_resources_it).c_str(), &statinfo); - if (result < 0) + if (stat(path.c_str(), &statinfo) < 0) { - RES_MESSAGE("Resource file " << *_path_resources_it << " does not exist"); - return _resourcesList; + MESSAGE("Resource file " << path << " does not exist"); + return false; } if(_lasttime == 0 || statinfo.st_mtime > _lasttime) @@ -451,214 +660,221 @@ const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles() } } - if (to_parse) + return to_parse; +} + +void ResourcesManager_cpp::ClearResourcesCatalog() +{ + _resourcesListJob.clear(); + _resourcesListContainer.clear(); +} + +//============================================================================= +/*! + * Parse the data type catalog + */ +//============================================================================= + +void ResourcesManager_cpp::ParseXmlFiles() +{ + if (!IsNeedToParse()) { - _resourcesList.clear(); - AddDefaultResourceInCatalog(); - // On parse tous les fichiers - for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it) - { - MapOfParserResourcesType _resourcesList_tmp; - MapOfParserResourcesType _resourcesBatchList_tmp; - SALOME_ResourcesCatalog_Handler *handler( new SALOME_ResourcesCatalog_Handler(_resourcesList_tmp) ); - const char *aFilePath( (*_path_resources_it).c_str() ); - FILE* aFile = fopen(aFilePath, "r"); + return; + } - if (aFile != NULL) - { - xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0); - if (aDoc != NULL) - { - handler->ProcessXmlDocument(aDoc); - - // adding new resources to the file - for (MapOfParserResourcesType_it i = _resourcesList_tmp.begin(); i != _resourcesList_tmp.end(); ++i) - { - MapOfParserResourcesType_it j = _resourcesList.find(i->first); - if (i->second.HostName == DEFAULT_RESOURCE_NAME || i->second.HostName == Kernel_Utils::GetHostname()) - { - MapOfParserResourcesType_it it0(_resourcesList.find(DEFAULT_RESOURCE_NAME)); - if(it0!=_resourcesList.end()) - { - ParserResourcesType& localhostElt((*it0).second); - localhostElt.DataForSort._nbOfNodes=(*i).second.DataForSort._nbOfNodes; - localhostElt.DataForSort._nbOfProcPerNode=(*i).second.DataForSort._nbOfProcPerNode; - localhostElt.DataForSort._CPUFreqMHz=(*i).second.DataForSort._CPUFreqMHz; - localhostElt.DataForSort._memInMB=(*i).second.DataForSort._memInMB; - } - RES_MESSAGE("Resource " << i->first << " is not added because it is the same " - "machine as default local resource \"" << DEFAULT_RESOURCE_NAME << "\""); - } - else if (j != _resourcesList.end()) - { - cerr << "ParseXmlFiles Warning, two resources with the same name were found, " - "taking the first declaration : " << i->first << endl; - } - else - { - _resourcesList[i->first] = i->second; - } - } - } - else - std::cerr << "ResourcesManager_cpp: could not parse file " << aFilePath << std::endl; - // Free the document - xmlFreeDoc(aDoc); - fclose(aFile); - } - else - std::cerr << "ResourcesManager_cpp: file " << aFilePath << " is not readable." << std::endl; + ClearResourcesCatalog(); + AddDefaultResourceInCatalog(); - delete handler; - } + // Iterate all resource files + for(const auto& path :_path_resources) + { + ParseResourceFile(path); } - return _resourcesList; } //============================================================================= /*! - * consult the content of the list + * Read all resources from a given XML file */ //============================================================================= -const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const +void ResourcesManager_cpp::ParseResourceFile(const std::string& resFile) { - return _resourcesList; -} + MESSAGE("Path to resource file to parse: " << resFile); -//! threadsafe -std::string ResourcesManager_cpp::Find(const std::string& policy, const std::vector& listOfResources) const -{ - std::map::const_iterator it(_resourceManagerMap.find(policy)); - if(it==_resourceManagerMap.end()) - { - it=_resourceManagerMap.find(""); - return ((*it).second)->Find(listOfResources, _resourcesList); - } - return ((*it).second)->Find(listOfResources, _resourcesList); + ParserResourcesTypeJob::TypeMap _resourcesListJobTemp; + ParserResourcesTypeContainer::TypeMap _resourcesListContainerTemp; + std::unique_ptr handler( + new SALOME_ResourcesCatalog_Handler(_resourcesListJobTemp, _resourcesListContainerTemp)); + + const char* aFilePath((resFile).c_str()); + FILE* aFile = fopen(aFilePath, "r"); + if (!aFile) + { + std::cerr << "ResourcesManager_cpp: file " << aFilePath << " is not readable." << std::endl; + return; + } + + xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, XML_PARSE_NOBLANKS); + if (!aDoc) + { + std::cerr << "ResourcesManager_cpp: could not parse file " << aFilePath << std::endl; + return; + } + + handler->readXmlDoc(aDoc); + + // Adding new resources to the catalog + for (const auto& res : _resourcesListJobTemp) + { + AddResourceJob(res.second); + } + + for (const auto& res : _resourcesListContainerTemp) + { + AddResourceContainer(res.second); + } + + // Free the document + xmlFreeDoc(aDoc); + fclose(aFile); } //============================================================================= /*! - * Gives a sublist of resources with matching OS. - * If parameter OS is empty, gives the complete list of resources + * Sort container resources. It's a helper method for GetFittingResourcesContainer() */ //============================================================================= -void -ResourcesManager_cpp::SelectOnlyResourcesWithOS(std::vector& resources, std::string OS) + +void ResourcesManager_cpp::SortResourcesTypeContainerByData( + const resourceParamsContainer& params, ResourceList& resourcesOut) { - if (OS != "") + ParserResourcesTypeContainer::TypeMap local_resourcesList = _resourcesListContainer; + if (params.resourceList.size()) { - // a computer list is given : take only resources with OS on those computers - std::vector vec_tmp = resources; - resources.clear(); - std::vector::iterator iter = vec_tmp.begin(); - for (; iter != vec_tmp.end(); iter++) + MESSAGE("Restricted resource list found!"); + local_resourcesList.clear(); + + for (const auto& res : params.resourceList) { - MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter); - if(it != _resourcesList.end()) - if ( (*it).second.OS == OS) - resources.push_back(*iter); + if (_resourcesListContainer.find(res) != _resourcesListContainer.end()) + local_resourcesList[res] = _resourcesListContainer[res]; } } -} + // Search for available resources sorted by priority + for (const auto& res : local_resourcesList) + { + resourcesOut.push_back(res.first); + } + + // Set wanted parameters + ResourceDataToSort::nb_proc_wanted = params.nb_proc; + ResourceDataToSort::nb_node_wanted = params.nb_node; + ResourceDataToSort::nb_proc_per_node_wanted = params.nb_proc_per_node; + ResourceDataToSort::cpu_clock_wanted = params.cpu_clock; + ResourceDataToSort::mem_mb_wanted = params.mem_mb; + // --- end of set + + // Sort + std::list li; + for (const auto& res : resourcesOut) + { + li.push_back(local_resourcesList[res].dataForSort); + } + li.sort(); + + resourcesOut.clear(); + for (const auto& data : li) + { + resourcesOut.push_back(data.name); + } +} //============================================================================= /*! - * Gives a sublist of machines on which the component is known. + * Consult the content of the job list */ //============================================================================= -void -ResourcesManager_cpp::KeepOnlyResourcesWithComponent(std::vector& resources, - const std::vector& componentList) +const ParserResourcesTypeJob::TypeMap& ResourcesManager_cpp::ListAllResourcesInCatalogJob() const { - std::vector kept_resources; - - std::vector::iterator iter = resources.begin(); - for (; iter != resources.end(); iter++) - { - const std::vector& mapOfComponentsOfCurrentHost = _resourcesList[*iter].ComponentsList; + return _resourcesListJob; +} - bool erasedHost = false; - if( mapOfComponentsOfCurrentHost.size() > 0 ) - { - for(unsigned int i=0; i::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(), - mapOfComponentsOfCurrentHost.end(), - componentList[i]); - if (itt == mapOfComponentsOfCurrentHost.end()) - { - erasedHost = true; - break; - } - } - } - if(!erasedHost) - kept_resources.push_back(*iter); - } - resources=kept_resources; +//============================================================================= +/*! + * Consult the content of the container list + */ +//============================================================================= +const ParserResourcesTypeContainer::TypeMap& ResourcesManager_cpp::ListAllResourcesInCatalogContainer() const +{ + return _resourcesListContainer; } -//! thread safe -ParserResourcesType ResourcesManager_cpp::GetResourcesDescr(const std::string & name) const +//============================================================================= +/*! + * Gives a sublist of resources with matching OS. + * If parameter OS is empty, gives the complete list of resources + */ +//============================================================================= +void ResourcesManager_cpp::SelectOnlyResourcesWithOS(const std::string& OS, ResourceList& resourcesOut) const { - MapOfParserResourcesType::const_iterator it(_resourcesList.find(name)); - if (it != _resourcesList.end()) - return (*it).second; - else + // A computer list is given : take only resources with OS on those computers + if (OS.empty()) { - std::string error("[GetResourcesDescr] Resource does not exist: "); - error += name; - throw ResourcesException(error); + return; } + + // This predicate returns true if an element should be removed + auto doesntHaveOs = [&] (const std::string& resName) -> bool + { + const auto it = _resourcesListContainer.find(resName); + return it == _resourcesListContainer.end() || (*it).second.OS != OS; + }; + + // Erase elements without OS in place + resourcesOut.erase(std::remove_if(resourcesOut.begin(), resourcesOut.end(), doesntHaveOs), resourcesOut.end()); } -void ResourcesManager_cpp::AddDefaultResourceInCatalog() + +//============================================================================= +/*! + * Gives a sublist of machines on which the component is known. + */ +//============================================================================= +void ResourcesManager_cpp::KeepOnlyResourcesWithComponent(const ResourceList& componentList, ResourceList& resourcesOut) const { - ParserResourcesType resource; - resource.Name = DEFAULT_RESOURCE_NAME; - // We can't use "localhost" for parameter hostname because the containers are registered in the - // naming service with the real hostname, not "localhost" - resource.HostName = Kernel_Utils::GetHostname(); - resource.DataForSort._Name = DEFAULT_RESOURCE_NAME; - resource.Protocol = sh; - resource.Batch = none; -#ifndef WIN32 - struct stat statbuf; - std::string aHomePath = Kernel_Utils::HomePath(); - if (aHomePath != "" && getenv("APPLI") != NULL) + // This predicate returns true if an element should be removed + auto hasMismatchComponent = [&] (const std::string& resName) -> bool { - if (stat(getenv("APPLI"), &statbuf) ==0 && S_ISREG(statbuf.st_mode)) + const auto& curComponentList = _resourcesListContainer.at(resName).componentList; + + // If a resource doesn't have any module or component defined in the catalog, + // it means that it has every module and component and it fits for any request. + if (!componentList.size() || !curComponentList.size()) { - // if $APPLI is a regular file, we asume it's a salome Launcher file - resource.AppliPath = string(getenv("APPLI")); + return false; } - else + + // We expect the names in list to be unique, so the number of elements in a given list + // must be less or equal than in list from current resource. + if (componentList.size() > curComponentList.size()) { - resource.AppliPath = aHomePath + "/" + getenv("APPLI"); + return true; } - } - string tmpdir = "/tmp"; - if (getenv("TMPDIR") != NULL) - tmpdir = getenv("TMPDIR"); - resource.working_directory = tmpdir + "/salome_localres_workdir"; - if (getenv("USER") != NULL) - resource.working_directory += string("_") + getenv("USER"); -#else - if (getenv("USERPROFILE") != NULL && getenv("APPLI") != NULL) - { - resource.AppliPath = string(getenv("USERPROFILE")) + "\\" + getenv("APPLI"); - } - string tmpdir = "C:\\tmp"; - if (getenv("TEMP") != NULL) - tmpdir = getenv("TEMP"); - resource.working_directory = tmpdir + "\\salome_localres_workdir"; - if (getenv("USERNAME") != NULL) - resource.working_directory += string("_") + getenv("USERNAME"); -#endif - resource.can_launch_batch_jobs = true; - resource.can_run_containers = true; - _resourcesList[resource.Name] = resource; + + for (const auto& component : componentList) + { + const auto it = std::find(curComponentList.begin(), curComponentList.end(), component); + if (it == curComponentList.end()) + { + return true; + } + } + + return false; + }; + + // Erase elements without given components in place + resourcesOut.erase(std::remove_if(resourcesOut.begin(), resourcesOut.end(), hasMismatchComponent), resourcesOut.end()); } diff --git a/src/ResourcesManager/ResourcesManager.hxx b/src/ResourcesManager/ResourcesManager.hxx index d72308f25..e97d66f1a 100644 --- a/src/ResourcesManager/ResourcesManager.hxx +++ b/src/ResourcesManager/ResourcesManager.hxx @@ -24,13 +24,11 @@ #define __RESOURCESMANAGER_HXX__ #include "ResourcesManager_Defs.hxx" +#include "SALOME_ParserResourcesTypeJob.hxx" +#include "SALOME_ParserResourcesTypeContainer.hxx" +#include "SALOME_LoadRateManager.hxx" -#include -#include -#include #include -#include "SALOME_ResourcesCatalog_Parser.hxx" -#include "SALOME_LoadRateManager.hxx" #include #include #ifdef WIN32 @@ -43,6 +41,8 @@ //#pragma warning(disable:4290) // Warning Exception ... #endif +using ResourceList = std::vector; + // --- WARNING --- // The call of BuildTempFileToLaunchRemoteContainer and RmTmpFile must be done // in a critical section to be sure to be clean. @@ -50,77 +50,85 @@ // session. struct RESOURCESMANAGER_EXPORT resourceParams { - resourceParams(); - std::string name; std::string hostname; - bool can_launch_batch_jobs; - bool can_run_containers; - std::string OS; - long nb_proc; - long nb_node; - long nb_proc_per_node; - long cpu_clock; - long mem_mb; - std::vector componentList; - std::vector resourceList; -}; -class RESOURCESMANAGER_EXPORT ResourcesManager_cpp - { + ResourceList resourceList; +}; - public: +struct RESOURCESMANAGER_EXPORT resourceParamsJob : resourceParams +{ +}; - ResourcesManager_cpp(const char *xmlFilePath); - ResourcesManager_cpp(); +struct RESOURCESMANAGER_EXPORT resourceParamsContainer : resourceParams +{ + std::string OS; - ~ResourcesManager_cpp(); + long nb_proc = -1; + long nb_node = 0; + long nb_proc_per_node = -1; + long cpu_clock = -1; + long mem_mb = -1; - std::vector - GetFittingResources(const resourceParams& params); + ResourceList componentList; +}; - std::string Find(const std::string& policy, const std::vector& listOfResources) const; +class RESOURCESMANAGER_EXPORT ResourcesManager_cpp +{ +public: + ResourcesManager_cpp(const char* xmlFilePath); + ResourcesManager_cpp(); - void AddResourceInCatalog (const ParserResourcesType & new_resource); + virtual ~ResourcesManager_cpp(); - void DeleteResourceInCatalog(const char * name); + std::string Find(const std::string& policy, const ResourceList& possibleContainerResources) const; - void WriteInXmlFile(std::string xml_file); + ResourceList GetFittingResourcesJob(const resourceParamsJob& params); + ResourceList GetFittingResourcesContainer(const resourceParamsContainer& params); - const MapOfParserResourcesType& ParseXmlFiles(); + ParserResourcesTypeJob GetResourceDefinitionJob(const std::string& name) const; + ParserResourcesTypeContainer GetResourceDefinitionContainer(const std::string& name) const; - const MapOfParserResourcesType& GetList() const; + void AddResourceJob(const ParserResourcesTypeJob& resource); + void AddResourceContainer(const ParserResourcesTypeContainer& resource); - //! thread safe - ParserResourcesType GetResourcesDescr(const std::string & name) const; + void RemoveResourceJob(const char* name); + void RemoveResourceContainer(const char* name); - protected: - - void SelectOnlyResourcesWithOS(std::vector& resources, std::string OS); + const ParserResourcesTypeJob::TypeMap& ListAllResourcesInCatalogJob() const; + const ParserResourcesTypeContainer::TypeMap& ListAllResourcesInCatalogContainer() const; + + void WriteInXmlFile(std::string xml_file); + void ParseXmlFiles(); - void KeepOnlyResourcesWithComponent(std::vector& resources, - const std::vector& componentList); +protected: + bool IsNeedToParse(); + void ClearResourcesCatalog(); + void ParseResourceFile(const std::string& resFile); + void SortResourcesTypeContainerByData(const resourceParamsContainer& params, ResourceList& resourcesOut); - /** - * Add the default local resource in the catalog - */ - void AddDefaultResourceInCatalog(); + void SelectOnlyResourcesWithOS(const std::string& OS, ResourceList& resourcesOut) const; + void KeepOnlyResourcesWithComponent(const ResourceList& componentList, ResourceList& resourcesOut) const; - //! will contain the path to the resources catalog - std::list _path_resources; - std::list::iterator _path_resources_it; + /** + * Add the default local resource in the catalog + */ + void AddDefaultResourceInCatalogJob(); + void AddDefaultResourceInCatalogContainer(); + void AddDefaultResourceInCatalog(); - //! will contain the information on the data type catalog(after parsing) - MapOfParserResourcesType _resourcesList; + //! will contain the path to the resources catalog + ResourceList _path_resources; - //! a map that contains all the available load rate managers (the key is the name) - std::map _resourceManagerMap; + //! will contain the information on the data type catalog(after parsing) + ParserResourcesTypeJob::TypeMap _resourcesListJob; + ParserResourcesTypeContainer::TypeMap _resourcesListContainer; - //! contain the time where resourcesList was created - time_t _lasttime = 0; + //! a map that contains all the available load rate managers (the key is the name) + std::map _resourceManagerMap; - //! the name of the default local resource - static const std::string DEFAULT_RESOURCE_NAME; - }; + //! contain the time where resourcesList was created + time_t _lasttime = 0; +}; #endif // __RESOURCESMANAGER_HXX__ diff --git a/src/ResourcesManager/SALOME_LoadRateManager.cxx b/src/ResourcesManager/SALOME_LoadRateManager.cxx index fa30f2d9f..776c1f62c 100644 --- a/src/ResourcesManager/SALOME_LoadRateManager.cxx +++ b/src/ResourcesManager/SALOME_LoadRateManager.cxx @@ -17,15 +17,14 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "SALOME_LoadRateManager.hxx" -#include -#include + std::string LoadRateManagerFirst::Find(const std::vector& hosts, - const MapOfParserResourcesType& /*resList*/) + const ParserResourcesTypeContainer::TypeMap& /*resList*/) { if (hosts.size() == 0) return std::string(""); @@ -34,7 +33,7 @@ std::string LoadRateManagerFirst::Find(const std::vector& hosts, } std::string LoadRateManagerCycl::Find(const std::vector& hosts, - const MapOfParserResourcesType& resList) + const ParserResourcesTypeContainer::TypeMap& resList) { static int imachine = 0; static int iproc = 0; @@ -42,29 +41,32 @@ std::string LoadRateManagerCycl::Find(const std::vector& hosts, // if empty list return empty string if (hosts.size() == 0) return std::string(""); - else{ - MapOfParserResourcesType::const_iterator it(resList.find(hosts[imachine])); - ParserResourcesType resource; - if(it!=resList.end()) - resource = (*it).second; - int nbproc = resource.DataForSort._nbOfProcPerNode * resource.DataForSort._nbOfNodes; - if( nbproc <= 0) nbproc = 1; - if( iproc < nbproc ){ - iproc++; - return std::string(hosts[imachine]); - } - else{ - iproc = 1; - imachine++; - if(imachine >= (int)hosts.size()) - imachine = 0; - return std::string(hosts[imachine]); - } + + const auto it = resList.find(hosts[imachine]); + ParserResourcesTypeContainer resource; + if (it != resList.end()) + resource = (*it).second; + + int nbproc = resource.dataForSort.nb_proc_per_node * resource.dataForSort.nb_node; + if( nbproc <= 0) + nbproc = 1; + + if( iproc < nbproc ) + { + iproc++; + return hosts[imachine]; } + + iproc = 1; + imachine++; + if(imachine >= (int)hosts.size()) + imachine = 0; + + return hosts[imachine]; } std::string LoadRateManagerAltCycl::Find(const std::vector& hosts, - const MapOfParserResourcesType& /*resList*/) + const ParserResourcesTypeContainer::TypeMap& /*resList*/) { if (hosts.size() == 0) return std::string(""); @@ -77,16 +79,16 @@ std::string LoadRateManagerAltCycl::Find(const std::vector& hosts, uses=0; for (std::vector::const_iterator iter = hosts.begin(); iter != hosts.end(); iter++) - { - std::string machine=*iter; - if(_numberOfUses.count(machine) == 0) - _numberOfUses[machine]=0; - if(_numberOfUses[machine] < uses) - { - selected=machine; - uses=_numberOfUses[machine]; - } - } + { + std::string machine=*iter; + if(_numberOfUses.count(machine) == 0) + _numberOfUses[machine]=0; + if(_numberOfUses[machine] < uses) + { + selected=machine; + uses=_numberOfUses[machine]; + } + } _numberOfUses[selected]=_numberOfUses[selected]+1; //std::cerr << "selected: " << selected << " " << _numberOfUses[selected] << std::endl; diff --git a/src/ResourcesManager/SALOME_LoadRateManager.hxx b/src/ResourcesManager/SALOME_LoadRateManager.hxx index ae8560553..e5ecccafa 100644 --- a/src/ResourcesManager/SALOME_LoadRateManager.hxx +++ b/src/ResourcesManager/SALOME_LoadRateManager.hxx @@ -17,42 +17,40 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #ifndef __SALOME_LOADRATEMANAGER_HXX__ #define __SALOME_LOADRATEMANAGER_HXX__ #include "ResourcesManager_Defs.hxx" -#include -#include -#include "SALOME_ResourcesCatalog_Parser.hxx" +#include "SALOME_ParserResourcesTypeContainer.hxx" class RESOURCESMANAGER_EXPORT LoadRateManager { public: - virtual std::string Find(const std::vector& /*hosts*/, const MapOfParserResourcesType& /*resList*/) { return ""; } + virtual std::string Find(const std::vector& /*hosts*/, const ParserResourcesTypeContainer::TypeMap& /*resList*/) { return ""; } }; class RESOURCESMANAGER_EXPORT LoadRateManagerFirst : public LoadRateManager { public: virtual std::string Find(const std::vector& hosts, - const MapOfParserResourcesType& resList); + const ParserResourcesTypeContainer::TypeMap& resList); }; class RESOURCESMANAGER_EXPORT LoadRateManagerCycl : public LoadRateManager { public: virtual std::string Find(const std::vector& hosts, - const MapOfParserResourcesType& resList); + const ParserResourcesTypeContainer::TypeMap& resList); }; class RESOURCESMANAGER_EXPORT LoadRateManagerAltCycl : public LoadRateManager { public: virtual std::string Find(const std::vector& hosts, - const MapOfParserResourcesType& resList); + const ParserResourcesTypeContainer::TypeMap& resList); protected: std::map _numberOfUses; }; diff --git a/src/ResourcesManager/SALOME_ParserResourceDataToSort.cxx b/src/ResourcesManager/SALOME_ParserResourceDataToSort.cxx new file mode 100644 index 000000000..cba3272f7 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourceDataToSort.cxx @@ -0,0 +1,129 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "SALOME_ParserResourceDataToSort.hxx" + +#include + +#define NULL_VALUE 0 + +unsigned int ResourceDataToSort::mem_mb_wanted = NULL_VALUE; +unsigned int ResourceDataToSort::cpu_clock_wanted = NULL_VALUE; +unsigned int ResourceDataToSort::nb_node_wanted = NULL_VALUE; +unsigned int ResourceDataToSort::nb_proc_per_node_wanted = NULL_VALUE; + +unsigned int ResourceDataToSort::nb_proc_wanted = NULL_VALUE; + + +ResourceDataToSort::ResourceDataToSort() +{} + +ResourceDataToSort::ResourceDataToSort(const std::string& name, + unsigned int nb_node, + unsigned int nb_proc_per_node, + unsigned int cpu_clock, + unsigned int mem_mb): + name(name), + nb_node(nb_node), + nb_proc_per_node(nb_proc_per_node), + cpu_clock(cpu_clock), + mem_mb(mem_mb) +{} + +//! Method used by list::sort to sort the resources used in SALOME_ResourcesManager::GetResourcesFitting +bool ResourceDataToSort::operator< (const ResourceDataToSort& other) const +{ + unsigned int nbPts = GetNumberOfPoints(); + return nbPts < other.GetNumberOfPoints(); +} + +unsigned int ResourceDataToSort::GetNumberOfPoints() const +{ + unsigned int ret = 0; + + //priority 0 : Nb of proc + if (nb_proc_wanted != NULL_VALUE) + { + unsigned int nb_proc = nb_node * nb_proc_per_node; + if (nb_proc == nb_proc_wanted) + ret += 30000; + else if (nb_proc > nb_proc_wanted) + ret += 20000; + else + ret += 10000; + } + + //priority 1 : Nb of nodes + if (nb_node_wanted != NULL_VALUE) + { + if (nb_node == nb_node_wanted) + ret += 3000; + else if (nb_node > nb_node_wanted) + ret += 2000; + else + ret += 1000; + } + + //priority 2 : Nb of proc by node + if (nb_proc_per_node_wanted != NULL_VALUE) + { + if (nb_proc_per_node == nb_proc_per_node_wanted) + ret += 300; + else if (nb_proc_per_node > nb_proc_per_node_wanted) + ret += 200; + else + ret += 100; + } + + //priority 3 : Cpu freq + if (cpu_clock_wanted != NULL_VALUE) + { + if (cpu_clock == cpu_clock_wanted) + ret += 30; + else if (cpu_clock > cpu_clock_wanted) + ret += 20; + else + ret += 10; + } + + //priority 4 : memory + if (mem_mb_wanted != NULL_VALUE) + { + if (mem_mb == mem_mb_wanted) + ret += 3; + else if (mem_mb > mem_mb_wanted) + ret += 2; + else + ret += 1; + } + + //RES_MESSAGE("[GetNumberOfPoints] points number for resource: " << name << " " << ret); + return ret; +} + +//! Method used for debug +void ResourceDataToSort::Print() const +{ + std::cout << "\nResourceDataToSort:\n" << + "name: " << name << '\n' << + "mem_mb: " << mem_mb << '\n' << + "cpu_clock: " << cpu_clock << '\n' << + "nb_node: " << nb_node << '\n' << + "nb_proc_per_node: " << nb_proc_per_node << '\n'; +} diff --git a/src/ResourcesManager/SALOME_ParserResourceDataToSort.hxx b/src/ResourcesManager/SALOME_ParserResourceDataToSort.hxx new file mode 100644 index 000000000..e52f9c7b7 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourceDataToSort.hxx @@ -0,0 +1,70 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SALOME ResourcesCatalog : implementation of catalog resources parsing (SALOME_ModuleCatalog.idl) +// File : SALOME_ParserResourceDataToSort.hxx +// Author : Konstantin Leontev +// Module : KERNEL +//$Header$ +// +#ifndef SALOME_PARSER_RESOURCES_DATA_SORT +#define SALOME_PARSER_RESOURCES_DATA_SORT + +#include "ResourcesManager_Defs.hxx" + +#include + +#ifdef WIN32 +#pragma warning(disable:4251) // Warning DLL Interface ... +#endif + +class RESOURCESMANAGER_EXPORT ResourceDataToSort +{ +public: + std::string name; + + // Same as in resource definintion in idl/SALOME_ResourceContainer.idl file + unsigned int mem_mb = 0; + unsigned int cpu_clock = 0; + unsigned int nb_node = 1; + unsigned int nb_proc_per_node = 1; + + static unsigned int mem_mb_wanted; + static unsigned int cpu_clock_wanted; + static unsigned int nb_node_wanted; + static unsigned int nb_proc_per_node_wanted; + + // An additional memeber to those above + static unsigned int nb_proc_wanted; + +public: + ResourceDataToSort(); + ResourceDataToSort(const std::string& name, + unsigned int nb_node, + unsigned int nb_proc_per_node, + unsigned int cpu_clock, + unsigned int mem_mb); + bool operator< (const ResourceDataToSort& other) const; + void Print() const; + +private: + unsigned int GetNumberOfPoints() const; +}; + +#endif //SALOME_PARSER_RESOURCES_DATA_SORT diff --git a/src/ResourcesManager/SALOME_ParserResourcesType.cxx b/src/ResourcesManager/SALOME_ParserResourcesType.cxx new file mode 100644 index 000000000..875e27ae6 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourcesType.cxx @@ -0,0 +1,151 @@ +// Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "SALOME_ParserResourcesType.hxx" + +#include + +namespace +{ + const std::map batchTypeMap + { + { none, "none" }, + { pbs, "pbs" }, + { lsf, "lsf" }, + { sge, "sge" }, + { ccc, "ccc" }, + { slurm, "slurm" }, + { ll, "ll" }, + { vishnu, "vishnu" }, + { oar, "oar" }, + { coorm, "coorm" }, + { ssh_batch, "ssh_batch" }, + }; + + const std::map protocolTypeMap + { + { sh, "sh" }, + { rsh, "rsh" }, + { ssh, "ssh" }, + { srun, "srun" }, + { pbsdsh, "pbsdsh" }, + { blaunch, "blaunch" }, + { rsync, "rsync" } + }; +} + +ParserResourcesType::ParserResourcesType() : + protocol(ssh), + batch(none) +{ +} + +ParserResourcesType::~ParserResourcesType() +{ +} + +std::string ParserResourcesType::getAccessProtocolTypeStr() const +{ + return protocolToString(protocol); +} + +void ParserResourcesType::setAccessProtocolTypeStr(const std::string& protocolStr) +{ + protocol = stringToProtocol(protocolStr); +} + +std::string ParserResourcesType::getBatchTypeStr() const +{ + const auto it = batchTypeMap.find(batch); + if (it == batchTypeMap.end()) + { + throw ResourcesException("Unknown batch type: " + std::to_string(batch)); + } + + return it->second; +} + +void ParserResourcesType::setBatchTypeStr(const std::string& batchTypeStr) +{ + if (batchTypeStr.empty()) + { + batch = none; + return; + } + + for (const auto& batchType : batchTypeMap) + { + if (batchType.second == batchTypeStr) + { + batch = batchType.first; + return; + } + } + + throw ResourcesException("Unknown batch type " + batchTypeStr); +} + +std::string ParserResourcesType::protocolToString(AccessProtocolType protocolType) +{ + const auto it = protocolTypeMap.find(protocolType); + if (it == protocolTypeMap.end()) + { + throw ResourcesException("Unknown protocol type: " + std::to_string(protocolType)); + } + + return it->second; +} + +AccessProtocolType ParserResourcesType::stringToProtocol(const std::string& protocolStr) +{ + // Use sh protocol by default + if (protocolStr.empty()) + { + return sh; + } + + for (const auto& protocolType : protocolTypeMap) + { + if (protocolType.second == protocolStr) + { + return protocolType.first; + } + } + + throw ResourcesException("Unknown protocol " + protocolStr); +} + +void ParserResourcesType::print(std::ostream& os) const +{ + os << "name: " << name << '\n' << + "hostname: " << hostname << '\n' << + "Protocol: " << getAccessProtocolTypeStr() << '\n' << + "batch: " << getBatchTypeStr() << '\n' << + "username: " << username << '\n' << + "applipath: " << applipath << '\n' << + + // TODO: all the stuff below wasn't declared in idl/SALOME_Resource.idl file + // TODO: decide if we need these members in the base class + "batchQueue: " << batchQueue << '\n' << + "userCommands: " << userCommands << '\n' << + "use: " << use << '\n'; +} diff --git a/src/ResourcesManager/SALOME_ParserResourcesType.hxx b/src/ResourcesManager/SALOME_ParserResourcesType.hxx new file mode 100644 index 000000000..1383cc046 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourcesType.hxx @@ -0,0 +1,77 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SALOME ResourcesCatalog : implementation of catalog resources parsing (SALOME_ModuleCatalog.idl) +// File : SALOME_ParserResourcesType.hxx +// Author : Konstantin Leontev +// Module : KERNEL +//$Header$ +// +#ifndef SALOME_PARSER_RESOURCES_TYPE +#define SALOME_PARSER_RESOURCES_TYPE + +#include "SALOME_ParserResourcesTypeCommon.hxx" + +#include +#include +#include + +#ifdef WIN32 +#pragma warning(disable:4251) // Warning DLL Interface ... +#endif + +class RESOURCESMANAGER_EXPORT ParserResourcesType +{ +public: + ParserResourcesType(); + virtual ~ParserResourcesType(); + + // Implementation must return true for ParserResourcesTypeJob + virtual bool isCanLaunchBatchJob() const = 0; + // Implementation must return true for ParserResourcesTypeContainer + virtual bool isCanRunContainers() const = 0; + + std::string getAccessProtocolTypeStr() const; + void setAccessProtocolTypeStr(const std::string& protocolTypeStr); + + std::string getBatchTypeStr() const; + void setBatchTypeStr(const std::string& batchTypeStr); + + // Same as in resource definintion in idl/SALOME_Resource.idl file + std::string name; + std::string hostname; + AccessProtocolType protocol; + std::string username; + std::string applipath; + BatchType batch; + + // TODO: all the members below wasn't declared in idl/SALOME_Resource.idl file + // TODO: decide if we need these members in the base class + std::string batchQueue; + std::string userCommands; + std::string use; + +protected: + static std::string protocolToString(AccessProtocolType protocol); + static AccessProtocolType stringToProtocol(const std::string& protocolStr); + + virtual void print(std::ostream& os) const; +}; + +#endif //SALOME_PARSER_RESOURCES_TYPE diff --git a/src/ResourcesManager/SALOME_ParserResourcesTypeCommon.hxx b/src/ResourcesManager/SALOME_ParserResourcesTypeCommon.hxx new file mode 100644 index 000000000..5b8f298b8 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourcesTypeCommon.hxx @@ -0,0 +1,51 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SALOME ResourcesCatalog : implementation of catalog resources parsing (SALOME_ModuleCatalog.idl) +// File : SALOME_ParserResourcesTypeCommon.hxx +// Author : Konstantin Leontev +// Module : KERNEL +//$Header$ +// +#ifndef SALOME_PARSER_RESOURCES_TYPE_COMMON +#define SALOME_PARSER_RESOURCES_TYPE_COMMON + +#include "ResourcesManager_Defs.hxx" + +#include + +#ifdef WIN32 +#pragma warning(disable:4251) // Warning DLL Interface ... +#endif + +enum AccessProtocolType { sh, rsh, ssh, srun, pbsdsh, blaunch, rsync }; + +enum BatchType { none, pbs, lsf, sge, ccc, ll, slurm, vishnu, oar, coorm, ssh_batch }; + +enum MpiImplType { nompi, lam, mpich1, mpich2, openmpi, ompi, slurmmpi, prun }; + +class RESOURCESMANAGER_EXPORT ResourcesException +{ +public: + const std::string msg; + + ResourcesException(const std::string m) : msg(m) {} +}; + +#endif //SALOME_PARSER_RESOURCES_TYPE_COMMON diff --git a/src/ResourcesManager/SALOME_ParserResourcesTypeContainer.cxx b/src/ResourcesManager/SALOME_ParserResourcesTypeContainer.cxx new file mode 100644 index 000000000..9a98bc621 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourcesTypeContainer.cxx @@ -0,0 +1,61 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "SALOME_ParserResourcesTypeContainer.hxx" + +ParserResourcesTypeContainer::ParserResourcesTypeContainer() +: ParserResourcesType() +{ +} + +ParserResourcesTypeContainer::~ParserResourcesTypeContainer() +{ +} + +void ParserResourcesTypeContainer::print(std::ostream& os) const +{ + ParserResourcesType::print(os); + + os << "nb_node: " << dataForSort.nb_node << '\n' << + "nb_proc_per_node: " << dataForSort.nb_proc_per_node << '\n' << + "cpu_clock: " << dataForSort.cpu_clock << '\n' << + "mem_mb: " << dataForSort.mem_mb << '\n' << + "OS: " << OS << '\n'; + + for(unsigned int i = 0 ; i < componentList.size(); i++) + os << "Component " << i + 1 << " called: " << componentList[i] << '\n'; + + // TODO: all the stuff below wasn't declared in idl/SALOME_Resource.idl file + std::list::const_iterator it; + for(it = ClusterMembersList.begin() ; it != ClusterMembersList.end() ; it++) + { + os << "Cluster member called: " << (*it).hostname << '\n'; + } + + os << "NbOfProc: " << nbOfProc << '\n'; + + // TODO: do we need to ptint the ModulesList? +} + +std::ostream& operator<<(std::ostream& os, const ParserResourcesTypeContainer& prt) +{ + prt.print(os); + + return os; +} diff --git a/src/ResourcesManager/SALOME_ParserResourcesTypeContainer.hxx b/src/ResourcesManager/SALOME_ParserResourcesTypeContainer.hxx new file mode 100644 index 000000000..8025a79f8 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourcesTypeContainer.hxx @@ -0,0 +1,74 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SALOME ResourcesCatalog : implementation of catalog resources parsing (SALOME_ModuleCatalog.idl) +// File : SALOME_ParserResourcesTypeContainer.hxx +// Author : Konstantin Leontev +// Module : KERNEL +//$Header$ +// +#ifndef SALOME_PARSER_RESOURCES_TYPE_CONTAINER +#define SALOME_PARSER_RESOURCES_TYPE_CONTAINER + +#include "SALOME_ParserResourcesType.hxx" +#include "SALOME_ParserResourceDataToSort.hxx" + +#include +#include + +#ifdef WIN32 +#pragma warning(disable:4251) // Warning DLL Interface ... +#endif + +class RESOURCESMANAGER_EXPORT ParserResourcesTypeContainer : public ParserResourcesType +{ +public: + using TypeMap = std::map; + using TypeMapIt = std::map::iterator; + + ParserResourcesTypeContainer(); + virtual ~ParserResourcesTypeContainer(); + + virtual bool isCanLaunchBatchJob() const override { return false; } + virtual bool isCanRunContainers() const override { return true; } + + // Same as in resource definintion in idl/SALOME_ResourceContainer.idl file + std::vector componentList; + std::string OS; + + // Keeps other members of container resource definition: + // mem_mb + // cpu_clock + // nb_node + // nb_proc_per_node + ResourceDataToSort dataForSort; + + unsigned int nbOfProc = 1; + std::list ClusterMembersList; + std::vector ModulesList; // module == component + +protected: + virtual void print(std::ostream& os) const override; + + RESOURCESMANAGER_EXPORT friend std::ostream & operator<<(std::ostream& os, + const ParserResourcesTypeContainer& rt); + +}; + +#endif //SALOME_PARSER_RESOURCES_TYPE_CONTAINER diff --git a/src/ResourcesManager/SALOME_ParserResourcesTypeJob.cxx b/src/ResourcesManager/SALOME_ParserResourcesTypeJob.cxx new file mode 100644 index 000000000..17f6ae254 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourcesTypeJob.cxx @@ -0,0 +1,105 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "SALOME_ParserResourcesTypeJob.hxx" + +namespace +{ + const std::map mpiImplTypeMap + { + { nompi, "no mpiImpl" }, + { lam, "lam" }, + { mpich1, "mpich1" }, + { mpich2, "mpich2" }, + { openmpi, "openmpi" }, + { ompi, "ompi" }, + { slurmmpi, "slurmmpi" }, + { prun, "prun" } + }; +} + +ParserResourcesTypeJob::ParserResourcesTypeJob() +: ParserResourcesType(), + iprotocol(ssh), + mpiImpl(nompi) +{ +} + +ParserResourcesTypeJob::~ParserResourcesTypeJob() +{ +} + +std::string ParserResourcesTypeJob::getMpiImplTypeStr() const +{ + const auto it = mpiImplTypeMap.find(mpiImpl); + if (it == mpiImplTypeMap.end()) + { + throw ResourcesException("Unknown MPI implementation type"); + } + + return it->second; +} + +void ParserResourcesTypeJob::setMpiImplTypeStr(const std::string& mpiImplTypeStr) +{ + // Consider an empty string as nompi type + if (mpiImplTypeStr.empty()) + { + mpiImpl = nompi; + return; + } + + for (const auto& mpi : mpiImplTypeMap) + { + if (mpi.second == mpiImplTypeStr) + { + mpiImpl = mpi.first; + return; + } + } + + throw ResourcesException("Unknown MPI implementation type " + mpiImplTypeStr); +} + +std::string ParserResourcesTypeJob::getClusterInternalProtocolStr() const +{ + return protocolToString(iprotocol); +} + + +void ParserResourcesTypeJob::setClusterInternalProtocolStr(const std::string& internalProtocolTypeStr) +{ + iprotocol = stringToProtocol(internalProtocolTypeStr); +} + +void ParserResourcesTypeJob::print(std::ostream& os) const +{ + ParserResourcesType::print(os); + + os << "iprotocol: " << getClusterInternalProtocolStr() << '\n' << + "mpiImpl: " << getMpiImplTypeStr() << '\n' << + "working_directory: " << working_directory << '\n'; +} + +std::ostream& operator<<(std::ostream& os, const ParserResourcesTypeJob& prt) +{ + prt.print(os); + + return os; +} diff --git a/src/ResourcesManager/SALOME_ParserResourcesTypeJob.hxx b/src/ResourcesManager/SALOME_ParserResourcesTypeJob.hxx new file mode 100644 index 000000000..772e25ff2 --- /dev/null +++ b/src/ResourcesManager/SALOME_ParserResourcesTypeJob.hxx @@ -0,0 +1,67 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SALOME ResourcesCatalog : implementation of catalog resources parsing (SALOME_ModuleCatalog.idl) +// File : SALOME_ParserResourcesTypeJob.hxx +// Author : Konstantin Leontev +// Module : KERNEL +//$Header$ +// +#ifndef SALOME_PARSER_RESOURCES_TYPE_JOB +#define SALOME_PARSER_RESOURCES_TYPE_JOB + +#include "SALOME_ParserResourcesType.hxx" + +#include + +#ifdef WIN32 +#pragma warning(disable:4251) // Warning DLL Interface ... +#endif + +class RESOURCESMANAGER_EXPORT ParserResourcesTypeJob : public ParserResourcesType +{ +public: + using TypeMap = std::map; + using TypeMapIt = std::map::iterator; + + ParserResourcesTypeJob(); + virtual ~ParserResourcesTypeJob(); + + virtual bool isCanLaunchBatchJob() const override { return true; } + virtual bool isCanRunContainers() const override { return false; } + + std::string getMpiImplTypeStr() const; + void setMpiImplTypeStr(const std::string& mpiImplTypeStr); + + std::string getClusterInternalProtocolStr() const; + void setClusterInternalProtocolStr(const std::string& internalProtocolTypeStr); + + // Same as in resource definintion in idl/SALOME_ResourceJob.idl file + MpiImplType mpiImpl; + AccessProtocolType iprotocol; + std::string working_directory; + +protected: + virtual void print(std::ostream& os) const override; + + RESOURCESMANAGER_EXPORT friend std::ostream& operator<<(std::ostream& os, + const ParserResourcesTypeJob& rt); +}; + +#endif //SALOME_PARSER_RESOURCES_TYPE_JOB diff --git a/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.cxx b/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.cxx index 1173574d9..d79b2ee5d 100644 --- a/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.cxx +++ b/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.cxx @@ -22,60 +22,175 @@ // SALOME ResourcesCatalog : implementation of catalog resources parsing (SALOME_ModuleCatalog.idl) // File : SALOME_ResourcesCatalog_Handler.cxx -// Author : Estelle Deville +// Author : Estelle Deville, Konstantin Leontev // Module : SALOME //$Header$ // #include "SALOME_ResourcesCatalog_Handler.hxx" + #include "Basics_Utils.hxx" #include "utilities.h" -#include -#include -#include -using namespace std; +namespace +{ + // XML tags + // ---------------------------------------------------- + + // Doc's root + const xmlChar* tag_root = BAD_CAST "resources"; + + // Resources types roots + const xmlChar* tag_resources_job = BAD_CAST "resources_job"; + const xmlChar* tag_resources_container = BAD_CAST "resources_container"; + + // Tags for each resource + const xmlChar* tag_machine = BAD_CAST "machine"; + const xmlChar* tag_cluster = BAD_CAST "cluster"; + const xmlChar* tag_members = BAD_CAST "members"; + + // Tags for container resources + const xmlChar* tag_component = BAD_CAST "component"; + const xmlChar* tag_modules = BAD_CAST "modules"; // module == component + + // Attributes + // ---------------------------------------------------- + + // Common attributes for each type of resource + const xmlChar* attr_name = BAD_CAST "name"; + const xmlChar* attr_hostname = BAD_CAST "hostname"; + const xmlChar* attr_protocol = BAD_CAST "protocol"; + const xmlChar* attr_username = BAD_CAST "username"; + const xmlChar* attr_applipath = BAD_CAST "applipath"; + const xmlChar* attr_batch = BAD_CAST "batch"; + + // Job's attributes + const xmlChar* attr_mpiImpl = BAD_CAST "mpi"; + const xmlChar* attr_iprotocol = BAD_CAST "iprotocol"; + const xmlChar* attr_working_directory = BAD_CAST "workingDirectory"; + + // Container's attributes + const xmlChar* attr_component_name = BAD_CAST "name"; + const xmlChar* attr_os = BAD_CAST "OS"; + const xmlChar* attr_mem_mb = BAD_CAST "memInMB"; + const xmlChar* attr_cpu_clock = BAD_CAST "CPUFreqMHz"; + const xmlChar* attr_nb_node = BAD_CAST "nbOfNodes"; + const xmlChar* attr_nb_proc_per_node = BAD_CAST "nbOfProcPerNode"; + const xmlChar* attr_nb_of_proc = BAD_CAST "nbOfProc"; + const xmlChar* attr_module_name = BAD_CAST "moduleName"; + + // for compatibility + const xmlChar* tag_batch_queue = BAD_CAST "batchQueue"; + const xmlChar* tag_user_commands = BAD_CAST "userCommands"; + const xmlChar* tag_use = BAD_CAST "use"; + + + // Generic functions for common processing of all resources' types + // ---------------------------------------------------- + + // Reads common attributes from machine tag + template bool readMachineCommon(xmlNodePtr node, T& resource) + { + MESSAGE("Read machine..."); + + // This alias is only to use short name for readAttr() method + auto readAttr = &SALOME_ResourcesCatalog_Handler::readAttr; + + resource.name = readAttr(node, attr_name); + + resource.hostname = readAttr(node, attr_hostname); + if (resource.hostname.empty()) + { + MESSAGE("Warning! Hostname is empty. This machine will not be added."); + return false; + } + + // Use the hostname as a name if the name wasn't provided + if (resource.name.empty()) + { + MESSAGE("Resourece name is empty. Using hostname as a name: " << resource.hostname); + resource.name = resource.hostname; + } + + resource.username = readAttr(node, attr_username); + resource.applipath = readAttr(node, attr_applipath); + + try + { + resource.setAccessProtocolTypeStr(readAttr(node, attr_protocol)); + } + catch(const ResourcesException& e) + { + MESSAGE("Warning! " << e.msg << " Using default value."); + } + + try + { + resource.setBatchTypeStr(readAttr(node, attr_batch)); + } + catch(const ResourcesException& e) + { + MESSAGE("Warning! " << e.msg << " Using default value."); + } + + // Check if those below are from a common part + resource.batchQueue = readAttr(node, tag_batch_queue); + resource.userCommands = readAttr(node, tag_user_commands); + resource.use = readAttr(node, tag_use); + + return true; + } + + // Add resource to a given map. + template void addResourceToMap(T& resource, U& resourceMap) + { + if(resource.hostname == "localhost") + { + resource.hostname = Kernel_Utils::GetHostname(); + } + + const auto iter = resourceMap.find(resource.name); + if (iter != resourceMap.end()) + { + MESSAGE("Warning! Resource " << resource.name << " already added, keep last resource found!"); + } + + resourceMap[resource.name] = resource; + MESSAGE("Added resource: " << resource.name); + } + + // Writes common attributes to machine tag + template void writeMachineCommon(xmlNodePtr node, const T& resource) + { + MESSAGE("Write machine..."); + + xmlNewProp(node, attr_name, BAD_CAST resource.name.c_str()); + xmlNewProp(node, attr_hostname, BAD_CAST resource.hostname.c_str()); + xmlNewProp(node, attr_protocol, BAD_CAST resource.getAccessProtocolTypeStr().c_str()); + xmlNewProp(node, attr_username, BAD_CAST resource.username.c_str()); + xmlNewProp(node, attr_applipath, BAD_CAST resource.applipath.c_str()); + xmlNewProp(node, attr_batch, BAD_CAST resource.getBatchTypeStr().c_str()); + + // Check if those below are from a common part + xmlNewProp(node, tag_batch_queue, BAD_CAST resource.batchQueue.c_str()); + xmlNewProp(node, tag_user_commands, BAD_CAST resource.userCommands.c_str()); + xmlNewProp(node, tag_use, BAD_CAST resource.use.c_str()); + } +} //============================================================================= /*! * Constructor - * \param listOfResources: map of ParserResourcesType to fill when parsing + * \param resourcesJob: map of ParserResourcesTypeJob to fill when parsing + * \param resourcesContainer: map of ParserResourcesTypeContainer to fill when parsing */ //============================================================================= -SALOME_ResourcesCatalog_Handler:: -SALOME_ResourcesCatalog_Handler(MapOfParserResourcesType& resources_list): _resources_list(resources_list) +SALOME_ResourcesCatalog_Handler::SALOME_ResourcesCatalog_Handler( + ParserResourcesTypeJob::TypeMap& resourcesJob, + ParserResourcesTypeContainer::TypeMap& resourcesContainer) : + resourcesJob(resourcesJob), + resourcesContainer(resourcesContainer) { - //XML tags initialisation - test_machine = "machine"; - test_cluster = "cluster"; - test_name = "name"; - test_hostname = "hostname"; - test_type = "type"; - test_protocol = "protocol"; - test_cluster_internal_protocol = "iprotocol"; - test_mode = "mode"; - test_batch = "batch"; - test_mpi = "mpi"; - test_user_name = "userName"; - test_appli_path = "appliPath"; - test_modules = "modules"; - test_module_name = "moduleName"; - test_components = "component"; - test_component_name = "name"; - test_os = "OS"; - test_mem_in_mb = "memInMB"; - test_cpu_freq_mhz = "CPUFreqMHz"; - test_nb_of_nodes = "nbOfNodes"; - test_nb_of_proc = "nbOfProc"; - test_nb_of_proc_per_node = "nbOfProcPerNode"; - test_batch_queue = "batchQueue"; - test_user_commands = "userCommands"; - test_use = "use"; - test_members = "members"; - test_is_cluster_head = "isClusterHead"; - test_working_directory = "workingDirectory"; - test_can_launch_batch_jobs = "canLaunchBatchJobs"; - test_can_run_containers = "canRunContainers"; } //============================================================================= @@ -91,662 +206,706 @@ SALOME_ResourcesCatalog_Handler::~SALOME_ResourcesCatalog_Handler() //============================================================================= /*! - * Retrieves DS after the file parse. + * Retrieves job resources map after the file parse. */ //============================================================================= -const MapOfParserResourcesType& -SALOME_ResourcesCatalog_Handler::GetResourcesAfterParsing() const +const ParserResourcesTypeJob::TypeMap& +SALOME_ResourcesCatalog_Handler::getResourcesJob() const { - return _resources_list; + return resourcesJob; +} + +//============================================================================= +/*! + * Retrieves container resources map after the file parse. + */ +//============================================================================= + +const ParserResourcesTypeContainer::TypeMap& +SALOME_ResourcesCatalog_Handler::getResourcesContainer() const +{ + return resourcesContainer; } //============================================================================= /*! * Processes XML document and fills the list of resources + * \param theDoc: a pointer to XML doc to read from */ //============================================================================= -void SALOME_ResourcesCatalog_Handler::ProcessXmlDocument(xmlDocPtr theDoc) +void SALOME_ResourcesCatalog_Handler::readXmlDoc(xmlDocPtr theDoc) { // Empty private elements - _resources_list.clear(); + resourcesJob.clear(); + resourcesContainer.clear(); // Get the document root node - xmlNodePtr aCurNode = xmlDocGetRootElement(theDoc); + xmlNodePtr node = xmlDocGetRootElement(theDoc); + if (!node) + { + MESSAGE("Warning! Couldn't find a root element in XML doc. Reading of resources was stopped."); + return; + } - aCurNode = aCurNode->xmlChildrenNode; + if (xmlStrcmp(node->name, tag_root)) + { + MESSAGE("Warning! Wrong name of the root element in XML doc. Expected: " << tag_root << ", but given: " << node->name); + } + + node = node->xmlChildrenNode; // Processing the document nodes - while(aCurNode != NULL) + while(node) { - // Declaration of a single machine or a frontal node for a cluster managed by a batch manager - if (!xmlStrcmp(aCurNode->name,(const xmlChar*)test_machine)) + // Check if we have different type of resources here + if (!xmlStrcmp(node->name, tag_resources_job)) { - ParserResourcesType resource; - bool Ok = ProcessMachine(aCurNode, resource); - if (Ok) - { - // Adding a resource - if(resource.HostName == "localhost") - { - resource.HostName = Kernel_Utils::GetHostname(); - } - std::map::const_iterator iter = _resources_list.find(resource.Name); - if (iter != _resources_list.end()) - RES_INFOS("Warning resource " << resource.Name << " already added, keep last resource found !"); - _resources_list[resource.Name] = resource; - } + readNodeResourcesJob(node); } - // Declaration of a cluster - // Here, a cluster is NOT the frontal node of a cluster managed by a batch manager (classical - // usage of a cluster). It is a group of machines intended to be used for a parallel container. - // The methods ProcessCluster and ProcessMember are only used in the context of parallel - // containers. They are not used in classical Salome usage scenarios. - if (!xmlStrcmp(aCurNode->name,(const xmlChar*)test_cluster)) + else if(!xmlStrcmp(node->name, tag_resources_container)) { - ParserResourcesType resource; - if(ProcessCluster(aCurNode, resource)) - { - std::map::const_iterator iter = _resources_list.find(resource.Name); - if (iter != _resources_list.end()) - RES_INFOS("Warning resource " << resource.Name << " already added, keep last resource found !"); - _resources_list[resource.Name] = resource; - } + readNodeResourcesContainer(node); + } + // else if(!xmlStrcmp(node->name, tag_cluster)) + // { + // readNodeCluster(node); + // } + else + { + // We don't expect other types of elements on this level + MESSAGE("Warning! Unexpected name of the element under root level. Skip element: " << node->name); } - aCurNode = aCurNode->next; - } -#ifdef _DEBUG_ - for (std::map::const_iterator iter = _resources_list.begin(); - iter != _resources_list.end(); - iter++) - { - MESSAGE( "************************************************" ); - MESSAGE( "Resource " << (*iter).first << " found:" ); - MESSAGE( (*iter).second ); - MESSAGE( "************************************************" ); - } -#endif + node = node->next; + } + +// Commented code below leaved temprarly for previouse implementation reference. + +// // Declaration of a single machine or a frontal node for a cluster managed by a batch manager +// if (!xmlStrcmp(node->name, tag_machine)) +// { +// ParserResourcesType resource; +// bool Ok = ProcessMachine(aCurNode, resource); +// if (Ok) +// { +// // Adding a resource +// if(resource.HostName == "localhost") +// { +// resource.HostName = Kernel_Utils::GetHostname(); +// } +// std::map::const_iterator iter = _resources_list.find(resource.Name); +// if (iter != _resources_list.end()) +// MESSAGE("Warning! Resource " << resource.Name << " already added, keep last resource found!"); +// _resources_list[resource.Name] = resource; +// } +// } +// // Declaration of a cluster +// // Here, a cluster is NOT the frontal node of a cluster managed by a batch manager (classical +// // usage of a cluster). It is a group of machines intended to be used for a parallel container. +// // The methods ProcessCluster and ProcessMember are only used in the context of parallel +// // containers. They are not used in classical Salome usage scenarios. +// if (!xmlStrcmp(aCurNode->name, tag_cluster)) +// { +// ParserResourcesType resource; +// if(ProcessCluster(aCurNode, resource)) +// { +// std::map::const_iterator iter = _resources_list.find(resource.Name); +// if (iter != _resources_list.end()) +// MESSAGE("Warning! Resource " << resource.Name << " already added, keep last resource found!"); +// _resources_list[resource.Name] = resource; +// } +// } +// aCurNode = aCurNode->next; +// } + +// #ifdef _DEBUG_ +// for (std::map::const_iterator iter = _resources_list.begin(); +// iter != _resources_list.end(); +// iter++) +// { +// MESSAGE("************************************************"); +// MESSAGE("Resource " << (*iter).first << " found:"); +// MESSAGE( (*iter).second ); +// MESSAGE("************************************************"); +// } +// #endif } -bool -SALOME_ResourcesCatalog_Handler::ProcessCluster(xmlNodePtr cluster_descr, ParserResourcesType & resource) -{ - // Ajout d'un cluster - // hostname, use et nbOfProc sont obligatoires - if (xmlHasProp(cluster_descr, (const xmlChar*)test_hostname)) - { - xmlChar* hostname = xmlGetProp(cluster_descr, (const xmlChar*)test_hostname); - resource.HostName = (const char*)hostname; - xmlFree(hostname); - } - else - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! found a cluster without a hostname" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! this cluster will not be added" ); - return false; - } - - if (xmlHasProp(cluster_descr, (const xmlChar*)test_name)) - { - xmlChar* name = xmlGetProp(cluster_descr, (const xmlChar*)test_name); - resource.Name = (const char*)name; - resource.DataForSort._Name = (const char*)name; - xmlFree(name); - } - else - { - resource.Name = resource.HostName; - resource.DataForSort._Name = resource.HostName; - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! No Name found use Hostname for resource: " << resource.Name ); - } +//============================================================================= +/*! + * Fill the document tree in xml file, used to write in an xml file. + * \param theDoc document to fill. + */ +//============================================================================= - if (xmlHasProp(cluster_descr, (const xmlChar*)test_use)) - { - xmlChar* use = xmlGetProp(cluster_descr, (const xmlChar*)test_use); - resource.use = (const char*)use; - xmlFree(use); - } - else - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! found a cluster without a use" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! this cluster will not be added" ); - return false; - } +void SALOME_ResourcesCatalog_Handler::writeXmlDoc(xmlDocPtr theDoc) const +{ + // Set root + xmlNodePtr root_node = xmlNewNode(NULL, tag_root); + xmlDocSetRootElement(theDoc, root_node); - if (xmlHasProp(cluster_descr, (const xmlChar*)test_nb_of_proc)) - { - xmlChar* nb_of_proc = xmlGetProp(cluster_descr, (const xmlChar*)test_nb_of_proc); - resource.nbOfProc = atoi((const char*)nb_of_proc); - xmlFree(nb_of_proc); - } - else - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! found a cluster without a nbOfProc" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! this cluster will not be added" ); - return false; - } + // Write resources + writeNodeResourcesJob(root_node); + writeNodeResourcesContainer(root_node); +} - if (xmlHasProp(cluster_descr, (const xmlChar*)test_mpi)) - { - xmlChar* mpi = xmlGetProp(cluster_descr, (const xmlChar*)test_mpi); - std::string anMpi = (const char*)mpi; - xmlFree(mpi); - resource.setMpiImplTypeStr(anMpi); - } +//============================================================================= +/*! + * Reads all machines inside job resources tag. + * \param node: a pointer to node to read from + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::readNodeResourcesJob(xmlNodePtr node) +{ + MESSAGE("Read job resources..."); - // Parsing des membres du cluster - xmlNodePtr aCurSubNode = cluster_descr->xmlChildrenNode; - while(aCurSubNode != NULL) + node = node->xmlChildrenNode; + while(node) { - if (!xmlStrcmp(aCurSubNode->name, (const xmlChar*)test_members)) + if (!xmlStrcmp(node->name, tag_machine)) { - xmlNodePtr members = aCurSubNode->xmlChildrenNode; - while (members != NULL) - { - // Process members - if (!xmlStrcmp(members->name, (const xmlChar*)test_machine)) - { - ParserResourcesType new_member; - if (ProcessMember(members, new_member)) - resource.ClusterMembersList.push_back(new_member); - } - members = members->next; - } + ParserResourcesTypeJob resource; + if (readMachineJob(node, resource)) + { + addResourceToMap(resource, resourcesJob); + } + } + else + { + MESSAGE("Warning! Unexpected name of the child element: " << node->name); } - aCurSubNode = aCurSubNode->next; - } - // Test: Il faut au moins un membre pour que le cluster soit correct ! - if (resource.ClusterMembersList.empty()) - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! found a cluster without a member" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessCluster : !!! Warning !!! this cluster will not be added" ); - return false; + node = node->next; } - return true; } -bool -SALOME_ResourcesCatalog_Handler::ProcessMember(xmlNodePtr member_descr, ParserResourcesType & resource) +//============================================================================= +/*! + * Reads all machines inside container resources tag. + * \param node: a pointer to node to read from + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::readNodeResourcesContainer(xmlNodePtr node) { - if (xmlHasProp(member_descr, (const xmlChar*)test_hostname)) - { - xmlChar* hostname = xmlGetProp(member_descr, (const xmlChar*)test_hostname); - resource.HostName = (const char*)hostname; - xmlFree(hostname); - } - else - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine without a hostname" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; - } + MESSAGE("Read container resources..."); - if (xmlHasProp(member_descr, (const xmlChar*)test_protocol)) + node = node->xmlChildrenNode; + while(node) { - xmlChar* protocol= xmlGetProp(member_descr, (const xmlChar*)test_protocol); - try + if (!xmlStrcmp(node->name, tag_machine)) { - resource.setAccessProtocolTypeStr((const char *)protocol); + ParserResourcesTypeContainer resource; + if (readMachineContainer(node, resource)) + { + addResourceToMap(resource, resourcesContainer); + } } - catch (const ResourcesException & ) + else { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine with a bad protocol" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; + MESSAGE("Warning! Unexpected name of the child element: " << node->name); } - xmlFree(protocol); - } - else - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine without a protocol" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; - } - if (xmlHasProp(member_descr, (const xmlChar*)test_cluster_internal_protocol)) - { - xmlChar* iprotocol= xmlGetProp(member_descr, (const xmlChar*)test_cluster_internal_protocol); - try - { - resource.setClusterInternalProtocolStr((const char *)iprotocol); - } - catch (const ResourcesException &) - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine with a bad protocol" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; - } - xmlFree(iprotocol); - } - else - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine without a protocol" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; + node = node->next; } +} - if (xmlHasProp(member_descr, (const xmlChar*)test_user_name)) - { - xmlChar* user_name= xmlGetProp(member_descr, (const xmlChar*)test_user_name); - resource.UserName = (const char*)user_name; - xmlFree(user_name); - } - else +//============================================================================= +/*! + * Reads all attributes of job resource machine. + * \param node: a pointer to node to read modules from + * \param resource: a reference to job resource type object + */ +//============================================================================= +bool SALOME_ResourcesCatalog_Handler::readMachineJob(xmlNodePtr node, ParserResourcesTypeJob& resource) const +{ + // Read common attributes + if (!readMachineCommon(node, resource)) { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine without a user name" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); return false; } - if (xmlHasProp(member_descr, (const xmlChar*)test_nb_of_nodes)) + // Read specific job attributes + try { - xmlChar* nb_of_nodes = xmlGetProp(member_descr, (const xmlChar*)test_nb_of_nodes); - resource.DataForSort._nbOfNodes = atoi((const char*)nb_of_nodes); - xmlFree(nb_of_nodes); + resource.setMpiImplTypeStr(readAttr(node, attr_mpiImpl)); } - else + catch (const ResourcesException& e) { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine without a nbOfNodes" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; + MESSAGE(e.msg << " Using default value."); } - if (xmlHasProp(member_descr, (const xmlChar*)test_nb_of_proc_per_node)) + try { - xmlChar* nb_of_proc_per_node = xmlGetProp(member_descr, (const xmlChar*)test_nb_of_proc_per_node); - resource.DataForSort._nbOfProcPerNode = atoi((const char*)nb_of_proc_per_node); - xmlFree(nb_of_proc_per_node); + resource.setClusterInternalProtocolStr(readAttr(node, attr_iprotocol)); } - else + catch (const ResourcesException& e) { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine without a nbOfProcPerNode" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; + MESSAGE(e.msg << " Using default value."); } - if (xmlHasProp(member_descr, (const xmlChar*)test_appli_path)) - { - xmlChar* appli_path = xmlGetProp(member_descr, (const xmlChar*)test_appli_path); - resource.AppliPath = (const char*)appli_path; - xmlFree(appli_path); - } - else - { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning found a machine without a AppliPath" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMember : Warning this machine will not be added" ); - return false; - } + + resource.working_directory = readAttr(node, attr_working_directory); + return true; } -bool -SALOME_ResourcesCatalog_Handler::ProcessMachine(xmlNodePtr machine_descr, ParserResourcesType & resource) +//============================================================================= +/*! + * Reads all attributes of container resource machine. + * It's a single machine or a frontal node for a cluster managed by a batch manager + * \param node: a pointer to node to read modules from + * \param resource: a reference to container resource type object + */ +//============================================================================= +bool SALOME_ResourcesCatalog_Handler::readMachineContainer(xmlNodePtr node, ParserResourcesTypeContainer& resource) const { - if (xmlHasProp(machine_descr, (const xmlChar*)test_hostname)) - { - xmlChar* hostname = xmlGetProp(machine_descr, (const xmlChar*)test_hostname); - resource.HostName = (const char*)hostname; - xmlFree(hostname); - } - else + // Read common attributes + if (!readMachineCommon(node, resource)) { - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMachine : Warning found a machine without a hostname" ); - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMachine : Warning this machine will not be added" ); return false; } - if (xmlHasProp(machine_descr, (const xmlChar*)test_name)) - { - xmlChar* name = xmlGetProp(machine_descr, (const xmlChar*)test_name); - resource.Name = (const char*)name; - resource.DataForSort._Name = (const char*)name; - xmlFree(name); - } - else - { - resource.Name = resource.HostName; - resource.DataForSort._Name = resource.HostName; - MESSAGE( "SALOME_ResourcesCatalog_Handler::ProcessMachine : !!! Warning !!! No Name found use Hostname for resource: " << resource.Name ); - } + // Read specific job attributes + // TODO: decide if we accept empty values here + resource.OS = readAttr(node, attr_os); - // This block is for compatibility with files created in Salome 6. - // It can safely be removed in Salome 8. - if (xmlHasProp(machine_descr, (const xmlChar*)test_mode)) + // Overrides a given default value only if we can get a valid conversion to int + auto readAttrInt = [&](const xmlChar* attrStr, unsigned int& attrValueOut) -> void { - MESSAGE( "Warning: parameter \"" << test_mode << "\" defined for resource \"" << - resource.Name << "\" is deprecated. It will be replaced when your resource " << - "file is saved." ); - xmlChar* mode=xmlGetProp(machine_descr, (const xmlChar*)test_mode); - switch ( mode[0] ) + const std::string attrValueStr = readAttr(node, attrStr); + if (attrValueStr.empty()) { - case 'i': - resource.can_run_containers = true; - break; - case 'b': - resource.can_launch_batch_jobs = true; - break; - default: - break; + return; } - xmlFree(mode); - } - if (xmlHasProp(machine_descr, (const xmlChar*)test_is_cluster_head)) - { - MESSAGE( "Warning: parameter \"" << test_is_cluster_head << "\" defined for resource \"" << - resource.Name << "\" is deprecated. It will be replaced when your resource " << - "file is saved." ); - xmlChar* is_cluster_head = xmlGetProp(machine_descr, (const xmlChar*)test_is_cluster_head); - std::string str_ich = (const char*)is_cluster_head; - if (str_ich == "true") - { - resource.type = cluster; - resource.can_launch_batch_jobs = true; - resource.can_run_containers = false; - } - else - { - resource.type = single_machine; - resource.can_run_containers = true; - } - xmlFree(is_cluster_head); - } - // End of compatibility block - - if (xmlHasProp(machine_descr, (const xmlChar*)test_type)) - { - xmlChar* type = xmlGetProp(machine_descr, (const xmlChar*)test_type); try { - resource.setResourceTypeStr((const char*)type); + attrValueOut = std::stoi(attrValueStr); } - catch (const ResourcesException &) + catch(const std::exception& e) { - MESSAGE( "Warning, invalid type \"" << (const char*)type << "\" for resource \"" << - resource.Name << "\", using default value \"" << resource.getResourceTypeStr() << - "\"" ) ; + MESSAGE(e.what()); } - xmlFree(type); - } - else - { - MESSAGE( "Warning, no type found for resource \"" << resource.Name << - "\", using default value \"" << resource.getResourceTypeStr() << "\""); - } + }; - if (xmlHasProp(machine_descr, (const xmlChar*)test_batch_queue)) - { - xmlChar* batch_queue = xmlGetProp(machine_descr, (const xmlChar*)test_batch_queue); - resource.batchQueue = (const char*)batch_queue; - xmlFree(batch_queue); - } + resource.dataForSort.name = resource.name; + readAttrInt(attr_mem_mb, resource.dataForSort.mem_mb); + readAttrInt(attr_cpu_clock, resource.dataForSort.cpu_clock); + readAttrInt(attr_nb_node, resource.dataForSort.nb_node); + readAttrInt(attr_nb_proc_per_node, resource.dataForSort.nb_proc_per_node); + readAttrInt(attr_nb_of_proc, resource.nbOfProc); - if (xmlHasProp(machine_descr, (const xmlChar*)test_user_commands)) + // Read child nodes to get components and modules if we have any + node = node->xmlChildrenNode; + while(node) { - xmlChar* user_commands= xmlGetProp(machine_descr, (const xmlChar*)test_user_commands); - resource.userCommands = (const char*)user_commands; - xmlFree(user_commands); - } + readComponent(node, resource); + readModule(node, resource); - if (xmlHasProp(machine_descr, (const xmlChar*)test_protocol)) - { - xmlChar* protocol= xmlGetProp(machine_descr, (const xmlChar*)test_protocol); - try - { - resource.setAccessProtocolTypeStr((const char *)protocol); - } - catch (const ResourcesException &) - { - MESSAGE( "Warning, invalid protocol \"" << (const char*)protocol << "\" for resource \"" << - resource.Name << "\", using default value \"" << - resource.getAccessProtocolTypeStr() << "\"" ); - } - xmlFree(protocol); + node = node->next; } - if (xmlHasProp(machine_descr, (const xmlChar*)test_cluster_internal_protocol)) - { - xmlChar* iprotocol= xmlGetProp(machine_descr, (const xmlChar*)test_cluster_internal_protocol); - try - { - resource.setClusterInternalProtocolStr((const char *)iprotocol); - } - catch (const ResourcesException &) - { - MESSAGE( "Warning, invalid internal protocol \"" << (const char*)iprotocol << - "\" for resource \"" << resource.Name << "\", using default value \"" << - resource.getClusterInternalProtocolStr() << "\"" ); - } - xmlFree(iprotocol); - } - else - resource.ClusterInternalProtocol = resource.Protocol; + return true; +} - if (xmlHasProp(machine_descr, (const xmlChar*)test_batch)) +//============================================================================= +/*! + * Reads all components of container resource machine. + * \param node: a pointer to node to read modules from + * \param resource: a reference to container resource type object + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::readComponent(xmlNodePtr node, ParserResourcesTypeContainer& resource) const +{ + if (!xmlStrcmp(node->name, tag_component)) { - xmlChar* batch = xmlGetProp(machine_descr, (const xmlChar*)test_batch); - try + // If a component is given, it is in a module with the same name + // except if the module name is given + const std::string componentName = readAttr(node, attr_component_name); + if (!componentName.empty()) { - resource.setBatchTypeStr((const char *)batch); - } - catch (const ResourcesException &) - { - MESSAGE( "Warning, invalid batch manager \"" << (const char*)batch << - "\" for resource \"" << resource.Name << "\", using default value \"" << - resource.getBatchTypeStr() << "\"" ); + resource.componentList.push_back(componentName); + + const std::string moduleName = readAttr(node, attr_module_name); + if (!moduleName.empty()) + { + resource.ModulesList.push_back(moduleName); + } + else + { + resource.ModulesList.push_back(componentName); + } } - xmlFree(batch); } +} - if (xmlHasProp(machine_descr, (const xmlChar*)test_mpi)) +//============================================================================= +/*! + * Reads all modules of container resource machine. + * \param node: a pointer to node to read modules from + * \param resource: a reference to container resource type object + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::readModule(xmlNodePtr node, ParserResourcesTypeContainer& resource) const +{ + if ( !xmlStrcmp(node->name, tag_modules) ) { - xmlChar* mpi = xmlGetProp(machine_descr, (const xmlChar*)test_mpi); - try - { - resource.setMpiImplTypeStr((const char *)mpi); - } - catch (const ResourcesException &) + // If a module is given, we create an entry in componentsList and modulesList + // with the same name (module == component) + const std::string moduleName = readAttr(node, attr_module_name); + + if (!moduleName.empty()) { - MESSAGE( "Warning, invalid MPI implementation \"" << (const char*)mpi << - "\" for resource \"" << resource.Name << "\", using default value \"" << - resource.getMpiImplTypeStr() << "\"" ); + resource.componentList.push_back(moduleName); + resource.ModulesList.push_back(moduleName); } - xmlFree(mpi); } +} - if (xmlHasProp(machine_descr, (const xmlChar*)test_user_name)) - { - xmlChar* user_name= xmlGetProp(machine_descr, (const xmlChar*)test_user_name); - resource.UserName = (const char*)user_name; - xmlFree(user_name); - } +// //============================================================================= +// /*! +// * Here, a cluster is NOT the frontal node of a cluster managed by a batch manager (classical +// * usage of a cluster). It is a group of machines intended to be used for a parallel container. +// * The methods readNodeClaster and readNodeClasterMember are only used in the context of parallel +// * containers. They are not used in classical Salome usage scenarios. +// * \param node: a pointer to node to read from +// */ +// //============================================================================= +// void SALOME_ResourcesCatalog_Handler::readNodeCluster(xmlNodePtr node) +// { +// // TODO: change implementation after we know if we need to process clusters as job or containers or both +// } + +// //============================================================================= +// /*! +// * Reads a member of a cluster +// * \param node: a pointer to node to read from +// * \param resource: a reference to container resource type object +// */ +// //============================================================================= +// bool SALOME_ResourcesCatalog_Handler::readNodeClusterMember(xmlNodePtr node, ParserResourcesTypeContainer& resource) +// { +// // TODO: add implementation +// return true; +// } - if (xmlHasProp(machine_descr, (const xmlChar*)test_appli_path)) +//============================================================================= +/*! + * Reads an attribute from XML node. Rases a warning if there's not any. + * It's on the caller side to decide if an attribute is mandatory or not. + * \param node: a pointer to node to read attribute from + * \param attr: an attribute's name + */ +//============================================================================= +std::string SALOME_ResourcesCatalog_Handler::readAttr(xmlNodePtr node, const xmlChar* attr) +{ + if (xmlHasProp(node, attr)) { - xmlChar* appli_path = xmlGetProp(machine_descr, (const xmlChar*)test_appli_path); - resource.AppliPath = (const char*)appli_path; - xmlFree(appli_path); - } + xmlChar* attrValue = xmlGetProp(node, attr); + const std::string attrValueStr((const char*)attrValue); + xmlFree(attrValue); - if (xmlHasProp(machine_descr, (const xmlChar*)test_os)) - { - xmlChar* os = xmlGetProp(machine_descr, (const xmlChar*)test_os); - resource.OS = (const char*)os; - xmlFree(os); + return attrValueStr; } - if (xmlHasProp(machine_descr, (const xmlChar*)test_mem_in_mb)) - { - xmlChar* mem_in_mb = xmlGetProp(machine_descr, (const xmlChar*)test_mem_in_mb); - resource.DataForSort._memInMB = atoi((const char*)mem_in_mb); - xmlFree(mem_in_mb); - } + MESSAGE("Couldn't find an attribute: " << attr); + return {}; +} - if (xmlHasProp(machine_descr, (const xmlChar*)test_cpu_freq_mhz)) +//============================================================================= +/*! + * Write job resources as a child of a given node. + * \param node: a pointer to the parent node + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::writeNodeResourcesJob(xmlNodePtr node) const +{ + node = xmlNewChild(node, NULL, tag_resources_job, NULL); + for (const auto& res : resourcesJob) { - xmlChar* cpu_freq_mhz = xmlGetProp(machine_descr, (const xmlChar*)test_cpu_freq_mhz); - resource.DataForSort._CPUFreqMHz = atoi((const char*)cpu_freq_mhz); - xmlFree(cpu_freq_mhz); + writeMachineJob(node, res.second); } +} - if (xmlHasProp(machine_descr, (const xmlChar*)test_nb_of_nodes)) +//============================================================================= +/*! + * Write container resources as a child of a given node. + * \param node: a pointer to the parent node + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::writeNodeResourcesContainer(xmlNodePtr node) const +{ + node = xmlNewChild(node, NULL, tag_resources_container, NULL); + for (const auto& res : resourcesContainer) { - xmlChar* nb_of_nodes = xmlGetProp(machine_descr, (const xmlChar*)test_nb_of_nodes); - resource.DataForSort._nbOfNodes = atoi((const char*)nb_of_nodes); - xmlFree(nb_of_nodes); - } + writeMachineContainer(node, res.second); + } +} - if (xmlHasProp(machine_descr, (const xmlChar*)test_nb_of_proc_per_node)) - { - xmlChar* nb_of_proc_per_node = xmlGetProp(machine_descr, (const xmlChar*)test_nb_of_proc_per_node); - resource.DataForSort._nbOfProcPerNode = atoi((const char*)nb_of_proc_per_node); - xmlFree(nb_of_proc_per_node); - } +//============================================================================= +/*! + * Write a given job resource as a child of a given node. + * \param node: a pointer to the parent node + * \param resource: a reference to the job resource type object + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::writeMachineJob(xmlNodePtr node, const ParserResourcesTypeJob& resource) const +{ + // Common part + MESSAGE("Add resource name = " << resource.name); - if (xmlHasProp(machine_descr, (const xmlChar*)test_can_launch_batch_jobs)) - { - xmlChar* can_launch_batch_jobs = xmlGetProp(machine_descr, (const xmlChar*)test_can_launch_batch_jobs); - try - { - resource.setCanLaunchBatchJobsStr((const char *)can_launch_batch_jobs); - } - catch (const ResourcesException &) - { - MESSAGE( "Warning, invalid can_launch_batch_jobs parameter value \"" << - (const char*)can_launch_batch_jobs << "\" for resource \"" << resource.Name << - "\", using default value \"" << resource.getCanLaunchBatchJobsStr() << "\"" ); - } - xmlFree(can_launch_batch_jobs); - } + node = xmlNewChild(node, NULL, tag_machine, NULL); + writeMachineCommon(node, resource); - if (xmlHasProp(machine_descr, (const xmlChar*)test_can_run_containers)) - { - xmlChar* can_run_containers = xmlGetProp(machine_descr, (const xmlChar*)test_can_run_containers); - try - { - resource.setCanRunContainersStr((const char *)can_run_containers); - } - catch (const ResourcesException &) - { - MESSAGE( "Warning, invalid can_run_containers parameter value \"" << - (const char*)can_run_containers << "\" for resource \"" << resource.Name << - "\", using default value \"" << resource.getCanRunContainersStr() << "\"" ); - } - xmlFree(can_run_containers); - } + // Specific job's attributes + xmlNewProp(node, attr_mpiImpl, BAD_CAST resource.getMpiImplTypeStr().c_str()); + xmlNewProp(node, attr_iprotocol, BAD_CAST resource.getClusterInternalProtocolStr().c_str()); + xmlNewProp(node, attr_working_directory, BAD_CAST resource.working_directory.c_str()); +} - if (xmlHasProp(machine_descr, (const xmlChar*)test_working_directory)) - { - xmlChar* working_directory = xmlGetProp(machine_descr, (const xmlChar*)test_working_directory); - resource.working_directory = (const char*)working_directory; - xmlFree(working_directory); - } +//============================================================================= +/*! + * Write a given container resource as a child of a given node. + * \param node: a pointer to the parent node + * \param resource: a reference to the container resource type object + */ +//============================================================================= +void SALOME_ResourcesCatalog_Handler::writeMachineContainer(xmlNodePtr node, const ParserResourcesTypeContainer& resource) const +{ + // Common part + MESSAGE("Add resource name = " << resource.name); - // Process children nodes - xmlNodePtr aCurSubNode = machine_descr->xmlChildrenNode; - while(aCurSubNode != NULL) - { - // Process components - if ( !xmlStrcmp(aCurSubNode->name, (const xmlChar*)test_components) ) - { - //If a component is given, it is in a module with the same name - //except if the module name is given - if (xmlHasProp(aCurSubNode, (const xmlChar*)test_component_name)) - { - xmlChar* component_name = xmlGetProp(aCurSubNode, (const xmlChar*)test_component_name); - std::string aComponentName = (const char*)component_name; - resource.ComponentsList.push_back(aComponentName); - if (xmlHasProp(aCurSubNode, (const xmlChar*)test_module_name)) - { - xmlChar* module_name = xmlGetProp(aCurSubNode, (const xmlChar*)test_module_name); - std::string aModuleName = (const char*)module_name; - resource.ModulesList.push_back(aModuleName); - xmlFree(module_name); - } - else - resource.ModulesList.push_back(aComponentName); - xmlFree(component_name); - } - } - // Process modules - else if ( !xmlStrcmp(aCurSubNode->name, (const xmlChar*)test_modules) ) - { - // If a module is given, we create an entry in componentsList and modulesList - // with the same name (module == component) - if (xmlHasProp(aCurSubNode, (const xmlChar*)test_module_name)) - { - xmlChar* component_name = xmlGetProp(aCurSubNode, (const xmlChar*)test_module_name); - std::string aComponentName = (const char*)component_name; - resource.ComponentsList.push_back(aComponentName); - resource.ModulesList.push_back(aComponentName); - xmlFree(component_name); - } - } - aCurSubNode = aCurSubNode->next; - } - return true; + node = xmlNewChild(node, NULL, tag_machine, NULL); + writeMachineCommon(node, resource); + + // Specific container's attributes + xmlNewProp(node, attr_os, BAD_CAST resource.OS.c_str()); + xmlNewProp(node, attr_mem_mb, BAD_CAST std::to_string(resource.dataForSort.mem_mb).c_str()); + xmlNewProp(node, attr_cpu_clock, BAD_CAST std::to_string(resource.dataForSort.cpu_clock).c_str()); + xmlNewProp(node, attr_nb_node, BAD_CAST std::to_string(resource.dataForSort.nb_node).c_str()); + xmlNewProp(node, attr_nb_proc_per_node, BAD_CAST std::to_string(resource.dataForSort.nb_proc_per_node).c_str()); + xmlNewProp(node, attr_nb_of_proc, BAD_CAST std::to_string(resource.nbOfProc).c_str()); + + writeComponents(node, resource); } //============================================================================= /*! - * Fill the document tree in xml file, used to write in an xml file. - * \param theDoc document to fill. + * Write all the components of a given container resource as children of a given node. + * \param node: a pointer to the parent node + * \param resource: a reference to the container resource type object */ //============================================================================= - -void SALOME_ResourcesCatalog_Handler::PrepareDocToXmlFile(xmlDocPtr theDoc) +void SALOME_ResourcesCatalog_Handler::writeComponents(xmlNodePtr node, const ParserResourcesTypeContainer& resource) const { - // Node pointers - xmlNodePtr root_node = NULL, node = NULL, node1 = NULL; - - root_node = xmlNewNode(NULL, BAD_CAST "resources"); - xmlDocSetRootElement(theDoc, root_node); - - std::map::iterator iter = _resources_list.begin(); - for (; iter != _resources_list.end(); iter++) + for (const auto& component : resource.componentList) { - node = xmlNewChild(root_node, NULL, BAD_CAST test_machine, NULL); - RES_MESSAGE("Add resource name = " << (*iter).second.Name.c_str()); - xmlNewProp(node, BAD_CAST test_name, BAD_CAST (*iter).second.Name.c_str()); - xmlNewProp(node, BAD_CAST test_hostname, BAD_CAST (*iter).second.HostName.c_str()); - xmlNewProp(node, BAD_CAST test_type, BAD_CAST (*iter).second.getResourceTypeStr().c_str()); - xmlNewProp(node, BAD_CAST test_appli_path, BAD_CAST (*iter).second.AppliPath.c_str()); - xmlNewProp(node, BAD_CAST test_batch_queue, BAD_CAST (*iter).second.batchQueue.c_str()); - xmlNewProp(node, BAD_CAST test_user_commands, BAD_CAST (*iter).second.userCommands.c_str()); - xmlNewProp(node, BAD_CAST test_protocol, BAD_CAST (*iter).second.getAccessProtocolTypeStr().c_str()); - xmlNewProp(node, BAD_CAST test_cluster_internal_protocol, - BAD_CAST (*iter).second.getClusterInternalProtocolStr().c_str()); - xmlNewProp(node, BAD_CAST test_working_directory, BAD_CAST (*iter).second.working_directory.c_str()); - xmlNewProp(node, BAD_CAST test_can_launch_batch_jobs, - BAD_CAST (*iter).second.getCanLaunchBatchJobsStr().c_str()); - xmlNewProp(node, BAD_CAST test_can_run_containers, - BAD_CAST (*iter).second.getCanRunContainersStr().c_str()); - xmlNewProp(node, BAD_CAST test_batch, BAD_CAST (*iter).second.getBatchTypeStr().c_str()); - xmlNewProp(node, BAD_CAST test_mpi, BAD_CAST (*iter).second.getMpiImplTypeStr().c_str()); - xmlNewProp(node, BAD_CAST test_user_name, BAD_CAST (*iter).second.UserName.c_str()); - - std::vector::const_iterator iter2 = (*iter).second.ComponentsList.begin(); - for(;iter2 != (*iter).second.ComponentsList.end(); iter2++) - { - node1 = xmlNewChild(node, NULL, BAD_CAST test_components, NULL); - xmlNewProp(node1, BAD_CAST test_component_name, BAD_CAST (*iter2).c_str()); - } - - xmlNewProp(node, BAD_CAST test_os, BAD_CAST (*iter).second.OS.c_str()); - std::ostringstream mem_stream; - mem_stream << (*iter).second.DataForSort._memInMB; - xmlNewProp(node, BAD_CAST test_mem_in_mb, BAD_CAST mem_stream.str().c_str()); - std::ostringstream cpu_stream; - cpu_stream << (*iter).second.DataForSort._CPUFreqMHz; - xmlNewProp(node, BAD_CAST test_cpu_freq_mhz, BAD_CAST cpu_stream.str().c_str()); - std::ostringstream nb_nodes_stream; - nb_nodes_stream << (*iter).second.DataForSort._nbOfNodes; - xmlNewProp(node, BAD_CAST test_nb_of_nodes, BAD_CAST nb_nodes_stream.str().c_str()); - std::ostringstream nb_proc_per_nodes_stream; - nb_proc_per_nodes_stream << (*iter).second.DataForSort._nbOfProcPerNode; - xmlNewProp(node, BAD_CAST test_nb_of_proc_per_node, BAD_CAST nb_proc_per_nodes_stream.str().c_str()); + xmlNodePtr nodeComp = xmlNewChild(node, NULL, tag_component, NULL); + xmlNewProp(nodeComp, attr_component_name, BAD_CAST component.c_str()); } } + + +// All the commented code below should be deleted after decision on cluster reading. +// Leaved here for implementation reference. + +// bool +// SALOME_ResourcesCatalog_Handler::ProcessCluster(xmlNodePtr cluster_descr, ParserResourcesType & resource) +// { +// // Ajout d'un cluster +// // hostname, use et nbOfProc sont obligatoires +// if (xmlHasProp(cluster_descr, attr_hostname)) +// { +// xmlChar* hostname = xmlGetProp(cluster_descr, attr_hostname); +// resource.HostName = (const char*)hostname; +// xmlFree(hostname); +// } +// else +// { +// MESSAGE("Warning! Found a cluster without a hostname. This cluster will not be added."); +// return false; +// } + +// if (xmlHasProp(cluster_descr, attr_name)) +// { +// xmlChar* name = xmlGetProp(cluster_descr, attr_name); +// resource.Name = (const char*)name; +// resource.DataForSort._Name = (const char*)name; +// xmlFree(name); +// } +// else +// { +// resource.Name = resource.HostName; +// resource.DataForSort._Name = resource.HostName; +// MESSAGE("Warning! No Name found use Hostname for resource: " << resource.Name ); +// } + +// if (xmlHasProp(cluster_descr, tag_use)) +// { +// xmlChar* use = xmlGetProp(cluster_descr, tag_use); +// resource.use = (const char*)use; +// xmlFree(use); +// } +// else +// { +// MESSAGE("Warning! Found a cluster without a use. This cluster will not be added."); +// return false; +// } + +// if (xmlHasProp(cluster_descr, attr_nb_of_proc)) +// { +// xmlChar* nb_of_proc = xmlGetProp(cluster_descr, attr_nb_of_proc); +// resource.nbOfProc = atoi((const char*)nb_of_proc); +// xmlFree(nb_of_proc); +// } +// else +// { +// MESSAGE("Warning! Found a cluster without a nbOfProc. This cluster will not be added."); +// return false; +// } + +// if (xmlHasProp(cluster_descr, attr_mpiImpl)) +// { +// xmlChar* mpi = xmlGetProp(cluster_descr, attr_mpiImpl); +// std::string anMpi = (const char*)mpi; +// xmlFree(mpi); +// resource.setMpiImplTypeStr(anMpi); +// } + +// // Parsing des membres du cluster +// xmlNodePtr aCurSubNode = cluster_descr->xmlChildrenNode; +// while(aCurSubNode != NULL) +// { +// if (!xmlStrcmp(aCurSubNode->name, tag_members)) +// { +// xmlNodePtr members = aCurSubNode->xmlChildrenNode; +// while (members != NULL) +// { +// // Process members +// if (!xmlStrcmp(members->name, tag_machine)) +// { +// ParserResourcesType new_member; +// if (ProcessMember(members, new_member)) +// resource.ClusterMembersList.push_back(new_member); +// } +// members = members->next; +// } +// } +// aCurSubNode = aCurSubNode->next; +// } + +// // Test: Il faut au moins un membre pour que le cluster soit correct ! +// if (resource.ClusterMembersList.empty()) +// { +// MESSAGE("Warning! Found a cluster without a member. This cluster will not be added."); +// return false; +// } +// return true; +// } + +// bool +// SALOME_ResourcesCatalog_Handler::ProcessMember(xmlNodePtr member_descr, ParserResourcesType & resource) +// { +// if (xmlHasProp(member_descr, attr_hostname)) +// { +// xmlChar* hostname = xmlGetProp(member_descr, attr_hostname); +// resource.HostName = (const char*)hostname; +// xmlFree(hostname); +// } +// else +// { +// MESSAGE("Warning! Found a machine without a hostname. This machine will not be added."); +// return false; +// } + +// if (xmlHasProp(member_descr, attr_protocol)) +// { +// xmlChar* protocol= xmlGetProp(member_descr, attr_protocol); +// try +// { +// resource.setAccessProtocolTypeStr((const char *)protocol); +// } +// catch (const ResourcesException & ) +// { +// MESSAGE("Warning! Found a machine with a bad protocol. This machine will not be added."); +// return false; +// } +// xmlFree(protocol); +// } +// else +// { +// MESSAGE("Warning! Found a machine without a protocol. This machine will not be added."); +// return false; +// } + +// if (xmlHasProp(member_descr, attr_iprotocol)) +// { +// xmlChar* iprotocol= xmlGetProp(member_descr, attr_iprotocol); +// try +// { +// resource.setClusterInternalProtocolStr((const char *)iprotocol); +// } +// catch (const ResourcesException &) +// { +// MESSAGE("Warning! Found a machine with a bad protocol. This machine will not be added."); +// return false; +// } +// xmlFree(iprotocol); +// } +// else +// { +// MESSAGE("Warning! Found a machine without a protocol. This machine will not be added."); +// return false; +// } + +// if (xmlHasProp(member_descr, attr_username)) +// { +// xmlChar* user_name= xmlGetProp(member_descr, attr_username); +// resource.UserName = (const char*)user_name; +// xmlFree(user_name); +// } +// else +// { +// MESSAGE("Warning! Found a machine without a user name. This machine will not be added."); +// return false; +// } + +// if (xmlHasProp(member_descr, attr_nb_node)) +// { +// xmlChar* nb_of_nodes = xmlGetProp(member_descr, attr_nb_node); +// resource.DataForSort._nbOfNodes = atoi((const char*)nb_of_nodes); +// xmlFree(nb_of_nodes); +// } +// else +// { +// MESSAGE("Warning! Found a machine without a nbOfNodes. This machine will not be added."); +// return false; +// } + +// if (xmlHasProp(member_descr, attr_nb_proc_per_node)) +// { +// xmlChar* nb_of_proc_per_node = xmlGetProp(member_descr, attr_nb_proc_per_node); +// resource.DataForSort._nbOfProcPerNode = atoi((const char*)nb_of_proc_per_node); +// xmlFree(nb_of_proc_per_node); +// } +// else +// { +// MESSAGE("Warning! Found a machine without a nbOfProcPerNode. This machine will not be added."); +// return false; +// } + +// if (xmlHasProp(member_descr, attr_applipath)) +// { +// xmlChar* appli_path = xmlGetProp(member_descr, attr_applipath); +// resource.AppliPath = (const char*)appli_path; +// xmlFree(appli_path); +// } +// else +// { +// MESSAGE("Warning! Found a machine without a AppliPath. This machine will not be added."); +// return false; +// } +// return true; +// } diff --git a/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.hxx b/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.hxx index 60a049f33..33df40f0e 100644 --- a/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.hxx +++ b/src/ResourcesManager/SALOME_ResourcesCatalog_Handler.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE +// Copyright (C) 2007-2023 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -29,72 +29,61 @@ #ifndef SALOME_RESOURCES_CATALOG_HANDLER #define SALOME_RESOURCES_CATALOG_HANDLER - #include "ResourcesManager_Defs.hxx" -#include "SALOME_ResourcesCatalog_Parser.hxx" - -#include -#include +#include "SALOME_ParserResourcesTypeJob.hxx" +#include "SALOME_ParserResourcesTypeContainer.hxx" #include class RESOURCESMANAGER_EXPORT SALOME_ResourcesCatalog_Handler { - - public : - SALOME_ResourcesCatalog_Handler(MapOfParserResourcesType& resources_list); - - const MapOfParserResourcesType& GetResourcesAfterParsing() const; - - virtual ~SALOME_ResourcesCatalog_Handler(); - - void ProcessXmlDocument(xmlDocPtr theDoc); - - bool ProcessMachine(xmlNodePtr machine_descr, ParserResourcesType & resource); - bool ProcessCluster(xmlNodePtr cluster_descr, ParserResourcesType & resource); - bool ProcessMember(xmlNodePtr member_descr, ParserResourcesType & resource); - - void PrepareDocToXmlFile(xmlDocPtr theDoc); - - private : - std::string previous_component_name; - - MapOfParserResourcesType& _resources_list; - - const char *test_machine; - const char *test_cluster; - const char *test_name; - const char *test_hostname; - const char *test_type; - const char *test_protocol; - const char *test_cluster_internal_protocol; - const char *test_batch; - const char *test_mpi; - const char *test_user_name; - const char *test_appli_path; - const char *test_can_launch_batch_jobs; - const char *test_can_run_containers; - // for compatibility - const char *test_modules; - const char *test_module_name; - const char *test_components; - const char *test_component_name; - const char *test_os; - const char *test_mem_in_mb; - const char *test_cpu_freq_mhz; - const char *test_nb_of_nodes; - const char *test_nb_of_proc; - const char *test_nb_of_proc_per_node; - const char *test_batch_queue; - const char *test_user_commands; - const char *test_use; - const char *test_members; - const char *test_working_directory; - - const char *test_mode; // To be removed in SALOME 8 - const char *test_is_cluster_head; // To be removed in SALOME 8 - - }; +public : + SALOME_ResourcesCatalog_Handler() = delete; + SALOME_ResourcesCatalog_Handler( + ParserResourcesTypeJob::TypeMap& resourcesJob, + ParserResourcesTypeContainer::TypeMap& resourcesContainer + ); + + virtual ~SALOME_ResourcesCatalog_Handler(); + + const ParserResourcesTypeJob::TypeMap& getResourcesJob() const; + const ParserResourcesTypeContainer::TypeMap& getResourcesContainer() const; + + void readXmlDoc(xmlDocPtr theDoc); + void writeXmlDoc(xmlDocPtr theDoc) const; + +protected: + void readNodeResourcesJob(xmlNodePtr node); + void readNodeResourcesContainer(xmlNodePtr node); + + bool readMachineJob(xmlNodePtr node, ParserResourcesTypeJob& resource) const; + bool readMachineContainer(xmlNodePtr node, ParserResourcesTypeContainer& resource) const; + + void readComponent(xmlNodePtr node, ParserResourcesTypeContainer& resource) const; + void readModule(xmlNodePtr node, ParserResourcesTypeContainer& resource) const; + + // void readNodeCluster(xmlNodePtr node); + // bool readNodeClusterMember(xmlNodePtr node, ParserResourcesTypeContainer& resource); + + static std::string readAttr(xmlNodePtr node, const xmlChar* attr); + + void writeNodeResourcesJob(xmlNodePtr node) const; + void writeNodeResourcesContainer(xmlNodePtr node) const; + + void writeMachineJob(xmlNodePtr node, const ParserResourcesTypeJob& resource) const; + void writeMachineContainer(xmlNodePtr node, const ParserResourcesTypeContainer& resource) const; + + void writeComponents(xmlNodePtr node, const ParserResourcesTypeContainer& resource) const; + + // bool ProcessCluster(xmlNodePtr cluster_descr, ParserResourcesType& resource); + // bool ProcessMember(xmlNodePtr member_descr, ParserResourcesType& resource); + +private : + std::string previous_component_name; + + ParserResourcesTypeJob::TypeMap& resourcesJob; + ParserResourcesTypeContainer::TypeMap& resourcesContainer; +}; #endif // SALOME_RESOURCES_CATALOG_HANDLER diff --git a/src/ResourcesManager/SALOME_ResourcesCatalog_Parser.cxx b/src/ResourcesManager/SALOME_ResourcesCatalog_Parser.cxx deleted file mode 100644 index 037297f17..000000000 --- a/src/ResourcesManager/SALOME_ResourcesCatalog_Parser.cxx +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -#include "SALOME_ResourcesCatalog_Parser.hxx" -#include -#include - -using namespace std; - -#define NULL_VALUE 0 - -unsigned int ResourceDataToSort::_nbOfProcWanted = NULL_VALUE; -unsigned int ResourceDataToSort::_nbOfNodesWanted = NULL_VALUE; -unsigned int ResourceDataToSort::_nbOfProcPerNodeWanted = NULL_VALUE; -unsigned int ResourceDataToSort::_CPUFreqMHzWanted = NULL_VALUE; -unsigned int ResourceDataToSort::_memInMBWanted = NULL_VALUE; - -ResourceDataToSort::ResourceDataToSort() -{} - -ResourceDataToSort::ResourceDataToSort(const std::string& name, - unsigned int nbOfNodes, - unsigned int nbOfProcPerNode, - unsigned int CPUFreqMHz, - unsigned int memInMB): - _Name(name), - _nbOfNodes(nbOfNodes), - _nbOfProcPerNode(nbOfProcPerNode), - _CPUFreqMHz(CPUFreqMHz), - _memInMB(memInMB) -{} - -//! Method used by list::sort to sort the resources used in SALOME_ResourcesManager::GetResourcesFitting -bool ResourceDataToSort::operator< (const ResourceDataToSort& other) const - { - unsigned int nbPts = GetNumberOfPoints(); - return nbPts < other.GetNumberOfPoints(); - } - -unsigned int ResourceDataToSort::GetNumberOfPoints() const - { - unsigned int ret = 0; - //priority 0 : Nb of proc - - if (_nbOfProcWanted != NULL_VALUE) - { - unsigned int nb_proc = _nbOfNodes * _nbOfProcPerNode; - if (nb_proc == _nbOfProcWanted) - ret += 30000; - else if (nb_proc > _nbOfProcWanted) - ret += 20000; - else - ret += 10000; - } - - //priority 1 : Nb of nodes - - if (_nbOfNodesWanted != NULL_VALUE) - { - if (_nbOfNodes == _nbOfNodesWanted) - ret += 3000; - else if (_nbOfNodes > _nbOfNodesWanted) - ret += 2000; - else - ret += 1000; - } - - //priority 2 : Nb of proc by node - if (_nbOfProcPerNodeWanted != NULL_VALUE) - { - if (_nbOfProcPerNode == _nbOfProcPerNodeWanted) - ret += 300; - else if (_nbOfProcPerNode > _nbOfProcPerNodeWanted) - ret += 200; - else - ret += 100; - } - - //priority 3 : Cpu freq - if (_CPUFreqMHzWanted != NULL_VALUE) - { - if (_CPUFreqMHz == _CPUFreqMHzWanted) - ret += 30; - else if (_CPUFreqMHz > _CPUFreqMHzWanted) - ret += 20; - else - ret += 10; - } - - //priority 4 : memory - if (_memInMBWanted != NULL_VALUE) - { - if (_memInMB == _memInMBWanted) - ret += 3; - else if (_memInMB > _memInMBWanted) - ret += 2; - else - ret += 1; - } - - //RES_MESSAGE("[GetNumberOfPoints] points number for resource: " << _Name << " " << ret); - return ret; - } - -//! Method used for debug -void ResourceDataToSort::Print() const - { - std::cout << _nbOfNodes << std::endl; - std::cout << _nbOfProcPerNode << std::endl; - std::cout << _CPUFreqMHz << std::endl; - std::cout << _memInMB << std::endl; - } - - -ParserResourcesType::ParserResourcesType() -: Protocol(ssh), - ClusterInternalProtocol(ssh), - type(single_machine), - Batch(none), - mpi(nompi), - nbOfProc(1), - can_launch_batch_jobs(false), - can_run_containers(false) -{ - DataForSort._Name = ""; - DataForSort._nbOfNodes = 1; - DataForSort._nbOfProcPerNode = 1; - DataForSort._CPUFreqMHz = 0; - DataForSort._memInMB = 0; -} - -ParserResourcesType::~ParserResourcesType() -{ -} - -std::string ParserResourcesType::protocolToString(AccessProtocolType protocol) -{ - switch (protocol) - { - case sh: - return "sh"; - case rsh: - return "rsh"; - case ssh: - return "ssh"; - case srun: - return "srun"; - case pbsdsh: - return "pbsdsh"; - case blaunch: - return "blaunch"; - case rsync: - return "rsync"; - default: - throw ResourcesException("Unknown protocol"); - } -} - -AccessProtocolType ParserResourcesType::stringToProtocol(const std::string & protocolStr) -{ - if (protocolStr == "sh") - return sh; - else if (protocolStr == "rsh") - return rsh; - else if (protocolStr == "ssh") - return ssh; - else if (protocolStr == "srun") - return srun; - else if (protocolStr == "pbsdsh") - return pbsdsh; - else if (protocolStr == "blaunch") - return blaunch; - else if (protocolStr == "rsync") - return rsync; - else - throw ResourcesException((string("Unknown protocol ") + protocolStr).c_str()); -} - -ostream & operator<<(ostream &os, const ParserResourcesType &prt) -{ - os << "Name: " << prt.Name << endl << - "HostName: " << prt.HostName << endl << - "Type: " << prt.getResourceTypeStr() << endl << - "NbOfNodes: " << prt.DataForSort._nbOfNodes << endl << - "NbOfProcPerNode: " << prt.DataForSort._nbOfProcPerNode << endl << - "CPUFreqMHz: " << prt.DataForSort._CPUFreqMHz << endl << - "MemInMB: " << prt.DataForSort._memInMB << endl << - "Protocol: " << prt.getAccessProtocolTypeStr() << endl << - "ClusterInternalProtocol: " << prt.getClusterInternalProtocolStr() << endl << - "Batch: " << prt.getBatchTypeStr() << endl << - "mpi: " << prt.getMpiImplTypeStr() << endl << - "UserName: " << prt.UserName << endl << - "AppliPath: " << prt.AppliPath << endl << - "OS: " << prt.OS << endl << - "batchQueue: " << prt.batchQueue << endl << - "userCommands: " << prt.userCommands << endl << - "use: " << prt.use << endl << - "NbOfProc: " << prt.nbOfProc << endl << - "Can Launch Batch Jobs: " << prt.can_launch_batch_jobs << endl << - "Can Run Containers: " << prt.can_run_containers << endl << - "Working Directory: " << prt.working_directory << endl; - - for(unsigned int i=0 ; i::const_iterator it; - for(it = prt.ClusterMembersList.begin() ; it != prt.ClusterMembersList.end() ; it++) - { - os << "Cluster member called: " << (*it).HostName << endl; - } - return os; -} - -std::string -ParserResourcesType::getAccessProtocolTypeStr() const -{ - return protocolToString(Protocol); -} - -std::string -ParserResourcesType::getClusterInternalProtocolStr() const -{ - return protocolToString(ClusterInternalProtocol); -} - -std::string -ParserResourcesType::getResourceTypeStr() const -{ - switch (type) - { - case cluster: - return "cluster"; - case single_machine: - return "single_machine"; - default: - throw ResourcesException("Unknown resource type"); - } -} - -std::string -ParserResourcesType::getBatchTypeStr() const -{ - switch (Batch) - { - case none: - return "none"; - case pbs: - return "pbs"; - case lsf: - return "lsf"; - case sge: - return "sge"; - case ccc: - return "ccc"; - case slurm: - return "slurm"; - case ll: - return "ll"; - case vishnu: - return "vishnu"; - case oar: - return "oar"; - case coorm: - return "coorm"; - default: - throw ResourcesException("Unknown batch type"); - } -} - -std::string -ParserResourcesType::getMpiImplTypeStr() const -{ - switch (mpi) - { - case nompi: - return "no mpi"; - case lam: - return "lam"; - case mpich1: - return "mpich1"; - case mpich2: - return "mpich2"; - case openmpi: - return "openmpi"; - case ompi: - return "ompi"; - case slurmmpi: - return "slurmmpi"; - case prun: - return "prun"; - default: - throw ResourcesException("Unknown MPI implementation type"); - } -} - -string ParserResourcesType::getCanLaunchBatchJobsStr() const -{ - return can_launch_batch_jobs ? "true" : "false"; -} - -string ParserResourcesType::getCanRunContainersStr() const -{ - return can_run_containers ? "true" : "false"; -} - -void ParserResourcesType::setAccessProtocolTypeStr(const string & protocolTypeStr) -{ - Protocol = stringToProtocol(protocolTypeStr); -} - -void ParserResourcesType::setResourceTypeStr(const string & resourceTypeStr) -{ - if (resourceTypeStr == "cluster") - type = cluster; - else if (resourceTypeStr == "single_machine") - type = single_machine; - else - throw ResourcesException((string("Unknown resource type ") + resourceTypeStr).c_str()); -} - -void ParserResourcesType::setBatchTypeStr(const string & batchTypeStr) -{ - if (batchTypeStr == "pbs") - Batch = pbs; - else if (batchTypeStr == "lsf") - Batch = lsf; - else if (batchTypeStr == "sge") - Batch = sge; - else if (batchTypeStr == "slurm") - Batch = slurm; - else if (batchTypeStr == "ccc") - Batch = ccc; - else if (batchTypeStr == "ll") - Batch = ll; - else if (batchTypeStr == "vishnu") - Batch = vishnu; - else if (batchTypeStr == "oar") - Batch = oar; - else if (batchTypeStr == "coorm") - Batch = coorm; - else if (batchTypeStr == "" || batchTypeStr == "none" || batchTypeStr == "ssh_batch") - Batch = none; - else - throw ResourcesException((string("Unknown batch type ") + batchTypeStr).c_str()); -} - -void ParserResourcesType::setMpiImplTypeStr(const string & mpiImplTypeStr) -{ - if (mpiImplTypeStr == "lam") - mpi = lam; - else if (mpiImplTypeStr == "mpich1") - mpi = mpich1; - else if (mpiImplTypeStr == "mpich2") - mpi = mpich2; - else if (mpiImplTypeStr == "openmpi") - mpi = openmpi; - else if (mpiImplTypeStr == "ompi") - mpi = ompi; - else if (mpiImplTypeStr == "slurmmpi") - mpi = slurmmpi; - else if (mpiImplTypeStr == "prun") - mpi = prun; - else if (mpiImplTypeStr == "" || mpiImplTypeStr == "no mpi") - mpi = nompi; - else - throw ResourcesException((string("Unknown MPI implementation type ") + mpiImplTypeStr).c_str()); -} - -void ParserResourcesType::setClusterInternalProtocolStr(const string & internalProtocolTypeStr) -{ - ClusterInternalProtocol = stringToProtocol(internalProtocolTypeStr); -} - -void ParserResourcesType::setCanLaunchBatchJobsStr(const string & canLaunchBatchJobsStr) -{ - if (canLaunchBatchJobsStr == "true") - can_launch_batch_jobs = true; - else if (canLaunchBatchJobsStr == "false") - can_launch_batch_jobs = false; - else - throw ResourcesException((string("Invalid boolean value for can_launch_batch_jobs: ") + - canLaunchBatchJobsStr).c_str()); -} - -void ParserResourcesType::setCanRunContainersStr(const string & canRunContainersStr) -{ - if (canRunContainersStr == "true") - can_run_containers = true; - else if (canRunContainersStr == "false") - can_run_containers = false; - else - throw ResourcesException((string("Invalid boolean value for can_run_containers: ") + - canRunContainersStr).c_str()); -} diff --git a/src/ResourcesManager/SALOME_ResourcesCatalog_Parser.hxx b/src/ResourcesManager/SALOME_ResourcesCatalog_Parser.hxx deleted file mode 100644 index 1c3780758..000000000 --- a/src/ResourcesManager/SALOME_ResourcesCatalog_Parser.hxx +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// SALOME ResourcesCatalog : implementation of catalog resources parsing (SALOME_ModuleCatalog.idl) -// File : SALOME_ResourcesCatalog_Parser.hxx -// Author : Estelle Deville -// Module : SALOME -//$Header$ -// -#ifndef SALOME_RESOURCES_CATALOG_PARSER -#define SALOME_RESOURCES_CATALOG_PARSER - -#include "ResourcesManager_Defs.hxx" - -#include -#include -#include -#include -#include - -#ifdef WIN32 -#pragma warning(disable:4251) // Warning DLL Interface ... -#endif - -enum AccessProtocolType {sh, rsh, ssh, srun, pbsdsh, blaunch, rsync}; - -enum ResourceType {cluster, single_machine}; - -enum BatchType {none, pbs, lsf, sge, ccc, ll, slurm, vishnu, oar, coorm}; - -enum MpiImplType {nompi, lam, mpich1, mpich2, openmpi, ompi, slurmmpi, prun}; - -class RESOURCESMANAGER_EXPORT ResourcesException -{ -public: - const std::string msg; - - ResourcesException(const std::string m) : msg(m) {} -}; - -class RESOURCESMANAGER_EXPORT ResourceDataToSort - { - - public: - std::string _Name; - unsigned int _nbOfNodes; - unsigned int _nbOfProcPerNode; - unsigned int _CPUFreqMHz; - unsigned int _memInMB; - static unsigned int _nbOfProcWanted; - static unsigned int _nbOfNodesWanted; - static unsigned int _nbOfProcPerNodeWanted; - static unsigned int _CPUFreqMHzWanted; - static unsigned int _memInMBWanted; - - public: - ResourceDataToSort(); - ResourceDataToSort(const std::string& name, - unsigned int nbOfNodes, - unsigned int nbOfProcPerNode, - unsigned int CPUFreqMHz, - unsigned int memInMB); - bool operator< (const ResourceDataToSort& other) const; - void Print() const; - - private: - unsigned int GetNumberOfPoints() const; - }; - -class RESOURCESMANAGER_EXPORT ParserResourcesType -{ -public: - ParserResourcesType(); - virtual ~ParserResourcesType(); - - std::string getAccessProtocolTypeStr() const; - std::string getResourceTypeStr() const; - std::string getBatchTypeStr() const; - std::string getMpiImplTypeStr() const; - std::string getClusterInternalProtocolStr() const; - std::string getCanLaunchBatchJobsStr() const; - std::string getCanRunContainersStr() const; - - void setAccessProtocolTypeStr(const std::string & protocolTypeStr); - void setResourceTypeStr(const std::string & resourceTypeStr); - void setBatchTypeStr(const std::string & batchTypeStr); - void setMpiImplTypeStr(const std::string & mpiImplTypeStr); - void setClusterInternalProtocolStr(const std::string & internalProtocolTypeStr); - void setCanLaunchBatchJobsStr(const std::string & canLaunchBatchJobsStr); - void setCanRunContainersStr(const std::string & canRunContainersStr); - - ResourceDataToSort DataForSort; - std::string Name; - std::string HostName; - AccessProtocolType Protocol; - AccessProtocolType ClusterInternalProtocol; - ResourceType type; - BatchType Batch; - MpiImplType mpi; - std::string UserName; - std::string AppliPath; - std::vector ComponentsList; - std::vector ModulesList; - std::string OS; - std::string batchQueue; - std::string userCommands; - std::string use; - std::list ClusterMembersList; - unsigned int nbOfProc; - bool can_launch_batch_jobs; - bool can_run_containers; - std::string working_directory; - -protected: - - static std::string protocolToString(AccessProtocolType protocol); - static AccessProtocolType stringToProtocol(const std::string & protocolStr); - - RESOURCESMANAGER_EXPORT friend std::ostream & operator<<(std::ostream &os, - const ParserResourcesType &rt); - -}; - -typedef std::map MapOfParserResourcesType; -typedef std::map::iterator MapOfParserResourcesType_it; - -#endif //SALOME_RESOURCES_CATALOG_PARSER diff --git a/src/ResourcesManager/SALOME_ResourcesManager.cxx b/src/ResourcesManager/SALOME_ResourcesManager.cxx index 632a326b6..051612109 100644 --- a/src/ResourcesManager/SALOME_ResourcesManager.cxx +++ b/src/ResourcesManager/SALOME_ResourcesManager.cxx @@ -33,23 +33,31 @@ #include #include #endif -#include -#include -#include -#include -#include -#include #include #include #include "utilities.h" -#define MAX_SIZE_FOR_HOSTNAME 256; - -using namespace std; - const char *SALOME_ResourcesManager::_ResourcesManagerNameInNS = "/ResourcesManager"; +namespace +{ + template + Engines::ResourceList* ListAllResourcesInCatalog(const T& zeList) + { + Engines::ResourceList* ret(new Engines::ResourceList); + ret->length(zeList.size()); + CORBA::ULong i(0); + for(const auto it : zeList) + { + // TODO: it was a hostname here, but we use a name to keep and search resources. + // So, changed to name to have the same approach. Need to check though. + (*ret)[i++] = CORBA::string_dup(it.second.name.c_str() ); + } + return ret; + } +} + //============================================================================= /*! * just for test @@ -128,107 +136,56 @@ SALOME_ResourcesManager::~SALOME_ResourcesManager() MESSAGE("SALOME_ResourcesManager destructor"); } - //============================================================================= -/*! CORBA method: - * shutdown all the containers, then the ContainerManager servant - */ +/*! + * dynamically obtains the first machines + */ //============================================================================= -void SALOME_ResourcesManager::Shutdown() +char * +SALOME_ResourcesManager::FindFirst(const Engines::ResourceList& possibleContainerResources) { - MESSAGE("Shutdown"); - if(!_NS) - return ; - _NS->Destroy_Name(_ResourcesManagerNameInNS); - PortableServer::ObjectId_var oid = _poa->servant_to_id(this); - _poa->deactivate_object(oid); -} + // CORBA -> C++ + const auto rl = resourceList_CORBAtoCPP(possibleContainerResources); -/*! - * Return list of resources available (regarding content of CatalogResources.xml) but select only those with canRunContainers attribute set to true. - * And for each resource the number of proc available of it. - * - * \sa SALOME_ResourcesManager::ListAllResourcesInCatalog - */ -void SALOME_ResourcesManager::ListAllAvailableResources(Engines::ResourceList_out machines, Engines::IntegerList_out nbProcsOfMachines) -{ - const MapOfParserResourcesType& zeList(_rm->GetList()); - std::vector ret0; - std::vector ret1; - for(MapOfParserResourcesType::const_iterator it=zeList.begin();it!=zeList.end();it++) - { - const ParserResourcesType& elt((*it).second); - if(elt.can_run_containers) - { - ret0.push_back(elt.HostName); - ret1.push_back(elt.DataForSort._nbOfNodes*elt.DataForSort._nbOfProcPerNode); - } - } - machines=new Engines::ResourceList; - nbProcsOfMachines=new Engines::IntegerList; - std::size_t sz(ret0.size()); - machines->length((CORBA::ULong)sz); nbProcsOfMachines->length((CORBA::ULong)sz); - for(std::size_t j=0;jFind("first", rl).c_str()); } -/*! - * Return list of resources available (regarding content of CatalogResources.xml) whatever canRunContainers attribute value. - * - * \sa SALOME_ResourcesManager::ListAllAvailableResources - */ -Engines::ResourceList *SALOME_ResourcesManager::ListAllResourcesInCatalog() +char * +SALOME_ResourcesManager::Find(const char* policy, const Engines::ResourceList& possibleContainerResources) { - const MapOfParserResourcesType& zeList(_rm->GetList()); - auto sz = zeList.size(); - Engines::ResourceList *ret(new Engines::ResourceList); - ret->length( sz ); - CORBA::ULong i(0); - for(auto it : zeList) - { - (*ret)[i++] = CORBA::string_dup( it.second.HostName.c_str() ); - } - return ret; + // CORBA -> C++ + const auto rl = resourceList_CORBAtoCPP(possibleContainerResources); + + return CORBA::string_dup(_rm->Find(policy, rl).c_str()); } //============================================================================= -//! get the name of resources fitting the specified constraints (params) +//! get the name of job resources fitting the specified constraints (params) /*! - * If hostname specified, check it is local or known in resources catalog. - * - * Else - * - select first machines with corresponding OS (all machines if - * parameter OS empty), - * - then select the sublist of machines on which the component is known - * (if the result is empty, that probably means that the inventory of - * components is probably not done, so give complete list from previous step) + * Look at ResourcesManager_cpp class for implementation */ //============================================================================= Engines::ResourceList * -SALOME_ResourcesManager::GetFittingResources(const Engines::ResourceParameters& params) +SALOME_ResourcesManager::GetFittingResourcesJob(const Engines::ResourceParametersJob& params) { - //MESSAGE("ResourcesManager::GetFittingResources"); Engines::ResourceList_var ret; // CORBA -> C++ - resourceParams p = resourceParameters_CORBAtoCPP(params); + const resourceParamsJob p = resourceParametersJob_CORBAtoCPP(params); try { // Call C++ ResourceManager - std::vector vec = _rm->GetFittingResources(p); + const auto vec = _rm->GetFittingResourcesJob(p); // C++ -> CORBA ret = resourceList_CPPtoCORBA(vec); } catch(const ResourcesException &ex) { - INFOS("Caught exception in GetFittingResources C++: " << ex.msg); + INFOS("Caught exception in GetFittingResourcesJob C++: " << ex.msg); THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM); } @@ -236,53 +193,82 @@ SALOME_ResourcesManager::GetFittingResources(const Engines::ResourceParameters& } //============================================================================= +//! get the name of container resources fitting the specified constraints (params) /*! - * dynamically obtains the first machines + * Look at ResourcesManager_cpp class for implementation */ //============================================================================= -char * -SALOME_ResourcesManager::FindFirst(const Engines::ResourceList& listOfResources) +Engines::ResourceList * +SALOME_ResourcesManager::GetFittingResourcesContainer(const Engines::ResourceParametersContainer& params) { + Engines::ResourceList_var ret; + // CORBA -> C++ - std::vector rl = resourceList_CORBAtoCPP(listOfResources); + const resourceParamsContainer p = resourceParametersContainer_CORBAtoCPP(params); - return CORBA::string_dup(_rm->Find("first", rl).c_str()); + try + { + // Call C++ ResourceManager + const auto vec = _rm->GetFittingResourcesContainer(p); + + // C++ -> CORBA + ret = resourceList_CPPtoCORBA(vec); + } + catch(const ResourcesException& ex) + { + INFOS("Caught exception in GetFittingResourcesContainer C++: " << ex.msg); + THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM); + } + + return ret._retn(); } -char * -SALOME_ResourcesManager::Find(const char* policy, const Engines::ResourceList& listOfResources) +Engines::ResourceDefinitionJob* +SALOME_ResourcesManager::GetResourceDefinitionJob(const char* name) { - // CORBA -> C++ - std::vector rl = resourceList_CORBAtoCPP(listOfResources); + Engines::ResourceDefinitionJob_var resDef; + try + { + const auto resource = _rm->GetResourceDefinitionJob(name); + resDef = resourceDefinitionJob_CPPtoCORBA(resource); + } + catch (const ResourcesException& ex) + { + INFOS("Caught exception in GetResourceDefinitionJob: " << ex.msg); + THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(), SALOME::BAD_PARAM); + } - return CORBA::string_dup(_rm->Find(policy, rl).c_str()); + return resDef._retn(); } -Engines::ResourceDefinition* -SALOME_ResourcesManager::GetResourceDefinition(const char * name) +Engines::ResourceDefinitionContainer* +SALOME_ResourcesManager::GetResourceDefinitionContainer(const char* name) { - Engines::ResourceDefinition_var resDef; - try { - ParserResourcesType resource = _rm->GetResourcesDescr(name); - resDef = resourceDefinition_CPPtoCORBA(resource); - } catch (const exception & ex) { - INFOS("Caught exception in GetResourceDefinition: " << ex.what()); - THROW_SALOME_CORBA_EXCEPTION(ex.what(), SALOME::BAD_PARAM); + Engines::ResourceDefinitionContainer_var resDef; + try + { + const auto resource = _rm->GetResourceDefinitionContainer(name); + resDef = resourceDefinitionContainer_CPPtoCORBA(resource); + } + catch (const ResourcesException& ex) + { + INFOS("Caught exception in GetResourceDefinitionContainer: " << ex.msg); + THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(), SALOME::BAD_PARAM); } return resDef._retn(); } -void -SALOME_ResourcesManager::AddResource(const Engines::ResourceDefinition& new_resource, - CORBA::Boolean write, - const char * xml_file) +void SALOME_ResourcesManager::AddResourceJob( + const Engines::ResourceDefinitionJob& new_resource, + CORBA::Boolean write, + const char* xml_file) { try { - ParserResourcesType resource = resourceDefinition_CORBAtoCPP(new_resource); - _rm->AddResourceInCatalog(resource); + const auto resource = resourceDefinitionJob_CORBAtoCPP(new_resource); + _rm->AddResourceJob(resource); if (write) { @@ -290,30 +276,80 @@ SALOME_ResourcesManager::AddResource(const Engines::ResourceDefinition& new_reso _rm->ParseXmlFiles(); } } - catch (const SALOME_Exception & e) + catch (const SALOME_Exception& e) { - INFOS("Error in AddResourceInCatalog: " << e); + INFOS("Error in AddResourceJob: " << e); THROW_SALOME_CORBA_EXCEPTION(e.what(), SALOME::BAD_PARAM); } - catch (const ResourcesException & e) + catch (const ResourcesException& e) { - INFOS("Error in AddResourceInCatalog: " << e.msg); + INFOS("Error in AddResourceJob: " << e.msg); THROW_SALOME_CORBA_EXCEPTION(e.msg.c_str(), SALOME::BAD_PARAM); } } -void -SALOME_ResourcesManager::RemoveResource(const char * resource_name, - CORBA::Boolean write, - const char * xml_file) +void SALOME_ResourcesManager::AddResourceContainer( + const Engines::ResourceDefinitionContainer& new_resource, + CORBA::Boolean write, + const char* xml_file) { try { - _rm->DeleteResourceInCatalog(resource_name); + const auto resource = resourceDefinitionContainer_CORBAtoCPP(new_resource); + _rm->AddResourceContainer(resource); + + if (write) + { + _rm->WriteInXmlFile(std::string(xml_file)); + _rm->ParseXmlFiles(); + } } - catch (const SALOME_Exception & e) + catch (const SALOME_Exception& e) { - INFOS("Error in DeleteResourceInCatalog: " << e); + INFOS("Error in AddResourceContainer: " << e); + THROW_SALOME_CORBA_EXCEPTION(e.what(), SALOME::BAD_PARAM); + } + catch (const ResourcesException& e) + { + INFOS("Error in AddResourceContainer: " << e.msg); + THROW_SALOME_CORBA_EXCEPTION(e.msg.c_str(), SALOME::BAD_PARAM); + } +} + +void SALOME_ResourcesManager::RemoveResourceJob( + const char* resource_name, + CORBA::Boolean write, + const char* xml_file) +{ + try + { + _rm->RemoveResourceJob(resource_name); + } + catch (const SALOME_Exception& e) + { + INFOS("Error in RemoveResourceJob: " << e); + THROW_SALOME_CORBA_EXCEPTION(e.what(), SALOME::BAD_PARAM); + } + + if (write) + { + _rm->WriteInXmlFile(std::string(xml_file)); + _rm->ParseXmlFiles(); + } +} + +void SALOME_ResourcesManager::RemoveResourceContainer( + const char* resource_name, + CORBA::Boolean write, + const char* xml_file) +{ + try + { + _rm->RemoveResourceContainer(resource_name); + } + catch (const SALOME_Exception& e) + { + INFOS("Error in RemoveResourceContainer: " << e); THROW_SALOME_CORBA_EXCEPTION(e.what(), SALOME::BAD_PARAM); } @@ -325,46 +361,46 @@ SALOME_ResourcesManager::RemoveResource(const char * resource_name, } char * -SALOME_ResourcesManager::getMachineFile(const char * resource_name, +SALOME_ResourcesManager::getMachineFile(const char* resource_name, CORBA::Long nb_procs, - const char * parallelLib) + const char* parallelLib) { - std::string machine_file_name(""); + std::string machine_file_name; if (std::string(parallelLib) == "Dummy") { MESSAGE("[getMachineFile] parallelLib is Dummy"); - MapOfParserResourcesType resourcesList = _rm->GetList(); + const auto& resourcesList = _rm->ListAllResourcesInCatalogContainer(); + if (resourcesList.find(std::string(resource_name)) != resourcesList.end()) { - ParserResourcesType resource = resourcesList[std::string(resource_name)]; + ParserResourcesTypeContainer resource = resourcesList.at(std::string(resource_name)); // Check if resource is cluster or not if (resource.ClusterMembersList.empty()) { //It is not a cluster so we create a cluster with one machine - ParserResourcesType fake_node; - fake_node.HostName = resource.HostName; - fake_node.Protocol = resource.Protocol; - fake_node.ClusterInternalProtocol = resource.ClusterInternalProtocol; - fake_node.UserName = resource.UserName; - fake_node.AppliPath = resource.AppliPath; - fake_node.DataForSort = resource.DataForSort; + ParserResourcesTypeContainer fake_node; + fake_node.hostname = resource.hostname; + fake_node.protocol = resource.protocol; + //fake_node.ClusterInternalProtocol = resource.ClusterInternalProtocol; + fake_node.username = resource.username; + fake_node.applipath = resource.applipath; + fake_node.dataForSort = resource.dataForSort; resource.ClusterMembersList.push_front(fake_node); } // Creating list of machines for creating the machine file std::list list_of_machines; - std::list::iterator cluster_it = - resource.ClusterMembersList.begin(); + std::list::iterator cluster_it = resource.ClusterMembersList.begin(); while (cluster_it != resource.ClusterMembersList.end()) { // For each member of the cluster we add a nbOfNodes * nbOfProcPerNode in the list - unsigned int number_of_proc = (*cluster_it).DataForSort._nbOfNodes * - (*cluster_it).DataForSort._nbOfProcPerNode; + unsigned int number_of_proc = (*cluster_it).dataForSort.nb_node * + (*cluster_it).dataForSort.nb_proc_per_node; for (unsigned int i = 0; i < number_of_proc; i++) - list_of_machines.push_back((*cluster_it).HostName); + list_of_machines.push_back((*cluster_it).hostname); cluster_it++; } @@ -389,76 +425,147 @@ SALOME_ResourcesManager::getMachineFile(const char * resource_name, else INFOS("[getMachineFile] Error resource_name not found in resourcesList -> " << resource_name); } - else if (std::string(parallelLib) == "Mpi") + // TODO: check if we need to rewrite commented code below: + // else if (std::string(parallelLib) == "Mpi") + // { + // MESSAGE("[getMachineFile] parallelLib is Mpi"); + // const auto& resourcesList = _rm->ListAllResourcesInCatalogContainer(); + + // if (resourcesList.find(std::string(resource_name)) != resourcesList.end()) + // { + // ParserResourcesTypeContainer resource = resourcesList.at(std::string(resource_name)); + // // Check if resource is cluster or not + // if (resource.ClusterMembersList.empty()) + // { + // //It is not a cluster so we create a cluster with one machine + // ParserResourcesTypeContainer fake_node; + // fake_node.hostname = resource.hostname; + // fake_node.protocol = resource.protocol; + // //fake_node.ClusterInternalProtocol = resource.ClusterInternalProtocol; + // fake_node.username = resource.username; + // fake_node.applipath = resource.applipath; + // fake_node.dataForSort = resource.dataForSort; + + // resource.ClusterMembersList.push_front(fake_node); + // } + + // // Choose mpi implementation -> each MPI implementation has is own machinefile... + // if (resource.mpi == lam) + // { + // // Creating machine file + // machine_file_name = tmpnam(NULL); + // std::ofstream machine_file(machine_file_name.c_str(), std::ios_base::out); + + // // We add all cluster machines to the file + // std::list::iterator cluster_it = resource.ClusterMembersList.begin(); + // while (cluster_it != resource.ClusterMembersList.end()) + // { + // unsigned int number_of_proc = (*cluster_it).dataForSort.nb_node * + // (*cluster_it).dataForSort.nb_proc_per_node; + // machine_file << (*cluster_it).hostname << " cpu=" << number_of_proc << std::endl; + // cluster_it++; + // } + // } + // else if ((resource.mpi == openmpi) || (resource.mpi == ompi)) + // { + // // Creating machine file + // machine_file_name = tmpnam(NULL); + // std::ofstream machine_file(machine_file_name.c_str(), std::ios_base::out); + + // // We add all cluster machines to the file + // std::list::iterator cluster_it = resource.ClusterMembersList.begin(); + // while (cluster_it != resource.ClusterMembersList.end()) + // { + // unsigned int number_of_proc = (*cluster_it).dataForSort.nb_node * + // (*cluster_it).dataForSort.nb_proc_per_node; + // machine_file << (*cluster_it).hostname << " slots=" << number_of_proc << std::endl; + // cluster_it++; + // } + // } + // else if (resource.mpi == nompi) + // { + // INFOS("[getMachineFile] Error resource_name MPI implementation was defined for " << resource_name); + // } + // else + // INFOS("[getMachineFile] Error resource_name MPI implementation not currently handled for " << resource_name); + // } + // else + // INFOS("[getMachineFile] Error resource_name not found in resourcesList -> " << resource_name); + // } + else + INFOS("[getMachineFile] Error parallelLib is not handled -> " << parallelLib); + + return CORBA::string_dup(machine_file_name.c_str()); +} + +/*! + * Return list of container resources available (regarding content of CatalogResources.xml). + * And for each resource the number of proc available of it. + * + * \sa SALOME_ResourcesManager::ListAllResourcesInCatalogContainer + */ +void SALOME_ResourcesManager::ListAllAvailableResourcesContainer(Engines::ResourceList_out machines, Engines::IntegerList_out nbProcsOfMachines) +{ + const auto& zeList = _rm->ListAllResourcesInCatalogContainer(); + std::vector ret0; + std::vector ret1; + + for(const auto& resource : zeList) { - MESSAGE("[getMachineFile] parallelLib is Mpi"); + const auto& elt = resource.second; - MapOfParserResourcesType resourcesList = _rm->GetList(); - if (resourcesList.find(std::string(resource_name)) != resourcesList.end()) - { - ParserResourcesType resource = resourcesList[std::string(resource_name)]; - // Check if resource is cluster or not - if (resource.ClusterMembersList.empty()) - { - //It is not a cluster so we create a cluster with one machine - ParserResourcesType fake_node; - fake_node.HostName = resource.HostName; - fake_node.Protocol = resource.Protocol; - fake_node.ClusterInternalProtocol = resource.ClusterInternalProtocol; - fake_node.UserName = resource.UserName; - fake_node.AppliPath = resource.AppliPath; - fake_node.DataForSort = resource.DataForSort; + ret0.push_back(elt.hostname); + ret1.push_back(elt.dataForSort.nb_node * elt.dataForSort.nb_proc_per_node); + } - resource.ClusterMembersList.push_front(fake_node); - } + machines = new Engines::ResourceList; + nbProcsOfMachines = new Engines::IntegerList; + std::size_t sz(ret0.size()); + machines->length((CORBA::ULong)sz); + nbProcsOfMachines->length((CORBA::ULong)sz); - // Choose mpi implementation -> each MPI implementation has is own machinefile... - if (resource.mpi == lam) - { - // Creating machine file - machine_file_name = tmpnam(NULL); - std::ofstream machine_file(machine_file_name.c_str(), std::ios_base::out); - - // We add all cluster machines to the file - std::list::iterator cluster_it = - resource.ClusterMembersList.begin(); - while (cluster_it != resource.ClusterMembersList.end()) - { - unsigned int number_of_proc = (*cluster_it).DataForSort._nbOfNodes * - (*cluster_it).DataForSort._nbOfProcPerNode; - machine_file << (*cluster_it).HostName << " cpu=" << number_of_proc << std::endl; - cluster_it++; - } - } - else if ((resource.mpi == openmpi) || (resource.mpi == ompi)) - { - // Creating machine file - machine_file_name = tmpnam(NULL); - std::ofstream machine_file(machine_file_name.c_str(), std::ios_base::out); - - // We add all cluster machines to the file - std::list::iterator cluster_it = - resource.ClusterMembersList.begin(); - while (cluster_it != resource.ClusterMembersList.end()) - { - unsigned int number_of_proc = (*cluster_it).DataForSort._nbOfNodes * - (*cluster_it).DataForSort._nbOfProcPerNode; - machine_file << (*cluster_it).HostName << " slots=" << number_of_proc << std::endl; - cluster_it++; - } - } - else if (resource.mpi == nompi) - { - INFOS("[getMachineFile] Error resource_name MPI implementation was defined for " << resource_name); - } - else - INFOS("[getMachineFile] Error resource_name MPI implementation not currently handled for " << resource_name); - } - else - INFOS("[getMachineFile] Error resource_name not found in resourcesList -> " << resource_name); + for(std::size_t j = 0; j < sz; j++) + { + (*machines)[(CORBA::ULong)j] = CORBA::string_dup(ret0[j].c_str()); + (*nbProcsOfMachines)[(CORBA::ULong)j] = ret1[j]; } - else - INFOS("[getMachineFile] Error parallelLib is not handled -> " << parallelLib); +} - return CORBA::string_dup(machine_file_name.c_str()); +/*! + * Return list of job resources available (regarding content of CatalogResources.xml). + * + * \sa SALOME_ResourcesManager::ListAllAvailableResources + */ +Engines::ResourceList *SALOME_ResourcesManager::ListAllResourcesInCatalogJob() +{ + const auto& zeList = _rm->ListAllResourcesInCatalogJob(); + return ListAllResourcesInCatalog(zeList); +} + +/*! + * Return list of container resources available (regarding content of CatalogResources.xml). + * + * \sa SALOME_ResourcesManager::ListAllAvailableResources + */ +Engines::ResourceList *SALOME_ResourcesManager::ListAllResourcesInCatalogContainer() +{ + const auto& zeList = _rm->ListAllResourcesInCatalogContainer(); + return ListAllResourcesInCatalog(zeList); +} + + +//============================================================================= +/*! CORBA method: + * shutdown all the containers, then the ContainerManager servant + */ +//============================================================================= + +void SALOME_ResourcesManager::Shutdown() +{ + MESSAGE("Shutdown"); + if(!_NS) + return ; + _NS->Destroy_Name(_ResourcesManagerNameInNS); + PortableServer::ObjectId_var oid = _poa->servant_to_id(this); + _poa->deactivate_object(oid); } diff --git a/src/ResourcesManager/SALOME_ResourcesManager.hxx b/src/ResourcesManager/SALOME_ResourcesManager.hxx index 1d2d5d0ff..0c5dc7267 100644 --- a/src/ResourcesManager/SALOME_ResourcesManager.hxx +++ b/src/ResourcesManager/SALOME_ResourcesManager.hxx @@ -28,9 +28,7 @@ #include #include "SALOME_NamingService_Abstract.hxx" #include CORBA_CLIENT_HEADER(SALOME_ContainerManager) -#include #include -#include #include #include "ResourcesManager.hxx" @@ -59,31 +57,40 @@ class SALOMERESOURCESMANAGER_EXPORT SALOME_ResourcesManager: ~SALOME_ResourcesManager(); // CORBA Methods - Engines::ResourceList * GetFittingResources(const Engines::ResourceParameters& params); - char* FindFirst(const Engines::ResourceList& listOfResources); - char* Find(const char *policy, const Engines::ResourceList& listOfResources); - Engines::ResourceDefinition * GetResourceDefinition(const char * name); - void AddResource(const Engines::ResourceDefinition& new_resource, - CORBA::Boolean write, - const char * xml_file); - - void RemoveResource(const char * resource_name, - CORBA::Boolean write, - const char * xml_file); - char* getMachineFile(const char * resource_name, - CORBA::Long nb_procs, - const char * parallelLib); - void ListAllAvailableResources(Engines::ResourceList_out machines, Engines::IntegerList_out nbProcsOfMachines); + // ====================================================================================== + + char* FindFirst(const Engines::ResourceList& possibleContainerResources); + char* Find(const char *policy, const Engines::ResourceList& possibleContainerResources); + + Engines::ResourceList* GetFittingResourcesJob(const Engines::ResourceParametersJob& params); + Engines::ResourceList* GetFittingResourcesContainer(const Engines::ResourceParametersContainer& params); + + Engines::ResourceDefinitionJob* GetResourceDefinitionJob(const char* name); + Engines::ResourceDefinitionContainer* GetResourceDefinitionContainer(const char* name); + + void AddResourceJob(const Engines::ResourceDefinitionJob& new_resource, CORBA::Boolean write, const char* xml_file); + void AddResourceContainer(const Engines::ResourceDefinitionContainer& new_resource, CORBA::Boolean write, const char* xml_file); + + void RemoveResourceJob(const char* resource_name, CORBA::Boolean write, const char* xml_file); + void RemoveResourceContainer(const char* resource_name, CORBA::Boolean write, const char* xml_file); + + char* getMachineFile(const char* resource_name, CORBA::Long nb_procs, const char* parallelLib); + + void ListAllAvailableResourcesContainer(Engines::ResourceList_out machines, Engines::IntegerList_out nbProcsOfMachines); - Engines::ResourceList *ListAllResourcesInCatalog(); + Engines::ResourceList* ListAllResourcesInCatalogJob(); + Engines::ResourceList* ListAllResourcesInCatalogContainer(); + // Cpp Methods + // ====================================================================================== + void Shutdown(); std::shared_ptr& GetImpl() { return _rm; } - + public: static const char *_ResourcesManagerNameInNS; - protected: + protected: SALOME_NamingService_Abstract *_NS; CORBA::ORB_var _orb; PortableServer::POA_var _poa; diff --git a/src/ResourcesManager/SALOME_ResourcesManager_Client.cxx b/src/ResourcesManager/SALOME_ResourcesManager_Client.cxx index 90d7dfa56..e6187b76c 100644 --- a/src/ResourcesManager/SALOME_ResourcesManager_Client.cxx +++ b/src/ResourcesManager/SALOME_ResourcesManager_Client.cxx @@ -17,14 +17,13 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "SALOME_ResourcesManager_Client.hxx" #include "SALOME_ResourcesManager.hxx" #include "SALOME_NamingService_Abstract.hxx" -using namespace std; SALOME_ResourcesManager_Client::SALOME_ResourcesManager_Client(SALOME_NamingService_Abstract *ns) : _rm(Engines::ResourcesManager::_nil()) @@ -41,36 +40,48 @@ SALOME_ResourcesManager_Client::~SALOME_ResourcesManager_Client() } -vector SALOME_ResourcesManager_Client::GetFittingResources(const resourceParams& params) +std::string SALOME_ResourcesManager_Client::Find(const std::string& policy, const ResourceList& possibleContainerResources) const { - Engines::ResourceParameters_var corba_params = resourceParameters_CPPtoCORBA(params); - Engines::ResourceList_var corba_rl = _rm->GetFittingResources(corba_params); - vector res = resourceList_CORBAtoCPP(corba_rl); - return res; + Engines::ResourceList_var corba_rl = resourceList_CPPtoCORBA(possibleContainerResources); + CORBA::String_var corba_res = _rm->Find(policy.c_str(), corba_rl); + + return corba_res.in(); } -string SALOME_ResourcesManager_Client::Find(const string & policy, const vector & listOfResources) +ResourceList SALOME_ResourcesManager_Client::GetFittingResourcesJob(const resourceParamsJob& params) const { - Engines::ResourceList_var corba_rl = resourceList_CPPtoCORBA(listOfResources); - CORBA::String_var corba_res = _rm->Find(policy.c_str(), corba_rl); - string res = corba_res.in(); - return res; + Engines::ResourceParametersJob_var corba_params = resourceParametersJob_CPPtoCORBA(params); + Engines::ResourceList_var corba_rl = _rm->GetFittingResourcesJob(corba_params); + + return resourceList_CORBAtoCPP(corba_rl); +} + +ResourceList SALOME_ResourcesManager_Client::GetFittingResourcesContainer(const resourceParamsContainer& params) const +{ + Engines::ResourceParametersContainer_var corba_params = resourceParametersContainer_CPPtoCORBA(params); + Engines::ResourceList_var corba_rl = _rm->GetFittingResourcesContainer(corba_params); + + return resourceList_CORBAtoCPP(corba_rl); +} + +ParserResourcesTypeJob SALOME_ResourcesManager_Client::GetResourceDefinitionJob(const std::string& name) const +{ + const auto corba_res = _rm->GetResourceDefinitionJob(name.c_str()); + return resourceDefinitionJob_CORBAtoCPP(*corba_res); } -ParserResourcesType SALOME_ResourcesManager_Client::GetResourceDefinition(const std::string & name) +ParserResourcesTypeContainer SALOME_ResourcesManager_Client::GetResourceDefinitionContainer(const std::string & name) const { - Engines::ResourceDefinition_var corba_res = _rm->GetResourceDefinition(name.c_str()); - ParserResourcesType res = resourceDefinition_CORBAtoCPP(corba_res); - return res; + const auto corba_res = _rm->GetResourceDefinitionContainer(name.c_str()); + return resourceDefinitionContainer_CORBAtoCPP(*corba_res); } -string SALOME_ResourcesManager_Client::getMachineFile(const string & resource_name, +std::string SALOME_ResourcesManager_Client::getMachineFile(const std::string& resource_name, long nb_procs, - const string & parallelLib) + const std::string& parallelLib) { CORBA::String_var corba_res = _rm->getMachineFile(resource_name.c_str(), nb_procs, parallelLib.c_str()); - string res = corba_res.in(); - return res; + return corba_res.in(); } diff --git a/src/ResourcesManager/SALOME_ResourcesManager_Client.hxx b/src/ResourcesManager/SALOME_ResourcesManager_Client.hxx index 0ca372149..2dec4402b 100644 --- a/src/ResourcesManager/SALOME_ResourcesManager_Client.hxx +++ b/src/ResourcesManager/SALOME_ResourcesManager_Client.hxx @@ -17,7 +17,7 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #ifndef __SALOME_RESOURCESMANAGER_CLIENT_HXX__ @@ -36,12 +36,14 @@ public: SALOME_ResourcesManager_Client(SALOME_NamingService_Abstract *ns); ~SALOME_ResourcesManager_Client(); - std::vector GetFittingResources(const resourceParams& params); - //std::string FindFirst(const std::vector& listOfResources) const; - std::string Find(const std::string & policy, const std::vector & listOfResources); - ParserResourcesType GetResourceDefinition(const std::string & name); - //void AddResource(const ParserResourcesType & new_resource, bool write, const std::string & xml_file); - //void RemoveResource(const std::string & name, bool write, const std::string & xml_file); + std::string Find(const std::string& policy, const ResourceList& possibleContainerResources) const; + + ResourceList GetFittingResourcesJob(const resourceParamsJob& params) const; + ResourceList GetFittingResourcesContainer(const resourceParamsContainer& params) const; + + ParserResourcesTypeJob GetResourceDefinitionJob(const std::string& name) const; + ParserResourcesTypeContainer GetResourceDefinitionContainer(const std::string& name) const; + std::string getMachineFile(const std::string & resource_name, long nb_procs, const std::string & parallelLib); diff --git a/src/ResourcesManager/SALOME_ResourcesManager_Common.cxx b/src/ResourcesManager/SALOME_ResourcesManager_Common.cxx index e958f403a..749f1b416 100644 --- a/src/ResourcesManager/SALOME_ResourcesManager_Common.cxx +++ b/src/ResourcesManager/SALOME_ResourcesManager_Common.cxx @@ -17,39 +17,62 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "SALOME_ResourcesManager_Common.hxx" -using namespace std; - template -vector strvec_CORBAtoCPP(const T & strvecCorba) +ResourceList strvec_CORBAtoCPP(const T& strvecCorba) { - vector strvecCpp; - for(unsigned int i=0; i -typename T::_var_type strvec_CPPtoCORBA(const vector & strvecCpp) +typename T::_var_type strvec_CPPtoCORBA(const ResourceList& strvecCpp) { typename T::_var_type strvecCorba = new T; + strvecCorba->length((CORBA::ULong)strvecCpp.size()); - for(unsigned int i=0;i +U resourceParameters_CORBAtoCPP(const T& params) { - resourceParams p; + U p; + p.name = params.name; p.hostname = params.hostname; - p.can_launch_batch_jobs = params.can_launch_batch_jobs; - p.can_run_containers = params.can_run_containers; + p.resourceList = resourceList_CORBAtoCPP(params.resList); + + return p; + + // return + // {{ // resourceParams base class members: + // params.name, + // params.hostname, + // resourceList_CORBAtoCPP(params.resList) + // }}; +} + +resourceParamsJob resourceParametersJob_CORBAtoCPP(const Engines::ResourceParametersJob& params) +{ + return resourceParameters_CORBAtoCPP(params); +} + +resourceParamsContainer resourceParametersContainer_CORBAtoCPP(const Engines::ResourceParametersContainer& params) +{ + resourceParamsContainer p = resourceParameters_CORBAtoCPP(params); + + // Specific containers' params p.OS = params.OS; p.nb_proc = params.nb_proc; p.nb_node = params.nb_node; @@ -57,17 +80,35 @@ resourceParams resourceParameters_CORBAtoCPP(const Engines::ResourceParameters & p.cpu_clock = params.cpu_clock; p.mem_mb = params.mem_mb; p.componentList = strvec_CORBAtoCPP(params.componentList); - p.resourceList = resourceList_CORBAtoCPP(params.resList); + return p; } -Engines::ResourceParameters_var resourceParameters_CPPtoCORBA(const resourceParams & params) +template +void resourceParameters_CPPtoCORBA(const T& params, U& p) { - Engines::ResourceParameters_var p = new Engines::ResourceParameters; p->name = params.name.c_str(); p->hostname = params.hostname.c_str(); - p->can_launch_batch_jobs = params.can_launch_batch_jobs; - p->can_run_containers = params.can_run_containers; + p->resList = resourceList_CPPtoCORBA(params.resourceList); +} + +Engines::ResourceParametersJob_var resourceParametersJob_CPPtoCORBA(const resourceParamsJob& params) +{ + Engines::ResourceParametersJob_var p = new Engines::ResourceParametersJob; + + resourceParameters_CPPtoCORBA(params, p); + + return p; +} + +Engines::ResourceParametersContainer_var resourceParametersContainer_CPPtoCORBA(const resourceParamsContainer& params) +{ + Engines::ResourceParametersContainer_var p = new Engines::ResourceParametersContainer; + + // Common params + resourceParameters_CPPtoCORBA(params, p); + + // Specific containers' params p->OS = params.OS.c_str(); p->nb_proc = params.nb_proc; p->nb_node = params.nb_node; @@ -75,65 +116,106 @@ Engines::ResourceParameters_var resourceParameters_CPPtoCORBA(const resourcePara p->cpu_clock = params.cpu_clock; p->mem_mb = params.mem_mb; p->componentList = strvec_CPPtoCORBA(params.componentList); - p->resList = resourceList_CPPtoCORBA(params.resourceList); + return p; } -vector resourceList_CORBAtoCPP(const Engines::ResourceList & resList) +ResourceList resourceList_CORBAtoCPP(const Engines::ResourceList& resList) { return strvec_CORBAtoCPP(resList); } -Engines::ResourceList_var resourceList_CPPtoCORBA(const vector & resList) +Engines::ResourceList_var resourceList_CPPtoCORBA(const ResourceList& resList) { return strvec_CPPtoCORBA(resList); } -ParserResourcesType resourceDefinition_CORBAtoCPP(const Engines::ResourceDefinition & resDef) +template +U resourceDefinition_CORBAtoCPP(const T& resDef) { - ParserResourcesType resource; - resource.Name = resDef.name; - resource.HostName = resDef.hostname; - resource.setResourceTypeStr(resDef.type.in()); - resource.OS = resDef.OS; - resource.AppliPath = resDef.applipath; - resource.DataForSort._Name = resDef.name; - resource.DataForSort._memInMB = resDef.mem_mb; - resource.DataForSort._CPUFreqMHz = resDef.cpu_clock; - resource.DataForSort._nbOfNodes = resDef.nb_node; - resource.DataForSort._nbOfProcPerNode = resDef.nb_proc_per_node; - resource.UserName = resDef.username; - resource.can_launch_batch_jobs = resDef.can_launch_batch_jobs; - resource.can_run_containers = resDef.can_run_containers; - resource.working_directory = resDef.working_directory; + U resource; + + resource.name = resDef.name; + resource.hostname = resDef.hostname; + resource.setAccessProtocolTypeStr(resDef.protocol.in()); + resource.username = resDef.username; + resource.applipath = resDef.applipath; resource.setBatchTypeStr(resDef.batch.in()); + + return resource; +} + +ParserResourcesTypeJob resourceDefinitionJob_CORBAtoCPP(const Engines::ResourceDefinitionJob& resDef) +{ + ParserResourcesTypeJob resource = + resourceDefinition_CORBAtoCPP(resDef); + + // Specific job's params resource.setMpiImplTypeStr(resDef.mpiImpl.in()); - resource.setAccessProtocolTypeStr(resDef.protocol.in()); resource.setClusterInternalProtocolStr(resDef.iprotocol.in()); - resource.ComponentsList = strvec_CORBAtoCPP(resDef.componentList); + resource.working_directory = resDef.working_directory; + return resource; } -Engines::ResourceDefinition_var resourceDefinition_CPPtoCORBA(const ParserResourcesType & resource) +ParserResourcesTypeContainer resourceDefinitionContainer_CORBAtoCPP(const Engines::ResourceDefinitionContainer& resDef) { - Engines::ResourceDefinition_var resCorba = new Engines::ResourceDefinition; - resCorba->name = resource.Name.c_str(); - resCorba->hostname = resource.HostName.c_str(); - resCorba->type = resource.getResourceTypeStr().c_str(); + ParserResourcesTypeContainer resource = + resourceDefinition_CORBAtoCPP(resDef); + + // Specific container's params + resource.OS = resDef.OS; + resource.dataForSort.name = resDef.name; + resource.dataForSort.mem_mb = resDef.mem_mb; + resource.dataForSort.cpu_clock = resDef.cpu_clock; + resource.dataForSort.nb_node = resDef.nb_node; + resource.dataForSort.nb_proc_per_node = resDef.nb_proc_per_node; + resource.componentList = strvec_CORBAtoCPP(resDef.componentList); + + return resource; +} + +template +void resourceDefinition_CPPtoCORBA(const T& resource, U& resCorba) +{ + // Common params + resCorba->name = resource.name.c_str(); + resCorba->hostname = resource.hostname.c_str(); resCorba->protocol = resource.getAccessProtocolTypeStr().c_str(); + resCorba->username = resource.username.c_str(); + resCorba->applipath = resource.applipath.c_str(); + resCorba->batch = resource.getBatchTypeStr().c_str(); +} + +Engines::ResourceDefinitionJob_var resourceDefinitionJob_CPPtoCORBA(const ParserResourcesTypeJob& resource) +{ + Engines::ResourceDefinitionJob_var resCorba = new Engines::ResourceDefinitionJob; + + // Common params + resourceDefinition_CPPtoCORBA(resource, resCorba); + + // Specific job's params + resCorba->mpiImpl = resource.getMpiImplTypeStr().c_str(); resCorba->iprotocol = resource.getClusterInternalProtocolStr().c_str(); - resCorba->username = resource.UserName.c_str(); - resCorba->applipath = resource.AppliPath.c_str(); - resCorba->componentList = strvec_CPPtoCORBA(resource.ComponentsList); - resCorba->OS = resource.OS.c_str(); - resCorba->mem_mb = resource.DataForSort._memInMB; - resCorba->cpu_clock = resource.DataForSort._CPUFreqMHz; - resCorba->nb_proc_per_node = resource.DataForSort._nbOfProcPerNode; - resCorba->nb_node = resource.DataForSort._nbOfNodes; - resCorba->can_launch_batch_jobs = resource.can_launch_batch_jobs; - resCorba->can_run_containers = resource.can_run_containers; resCorba->working_directory = resource.working_directory.c_str(); - resCorba->mpiImpl = resource.getMpiImplTypeStr().c_str(); - resCorba->batch = resource.getBatchTypeStr().c_str(); + + return resCorba; +} + +Engines::ResourceDefinitionContainer_var resourceDefinitionContainer_CPPtoCORBA(const ParserResourcesTypeContainer& resource) +{ + Engines::ResourceDefinitionContainer_var resCorba = new Engines::ResourceDefinitionContainer; + + // Common params + resourceDefinition_CPPtoCORBA(resource, resCorba); + + // Specific container's params + resCorba->componentList = strvec_CPPtoCORBA(resource.componentList); + resCorba->OS = resource.OS.c_str(); + resCorba->mem_mb = resource.dataForSort.mem_mb; + resCorba->cpu_clock = resource.dataForSort.cpu_clock; + resCorba->nb_proc_per_node = resource.dataForSort.nb_proc_per_node; + resCorba->nb_node = resource.dataForSort.nb_node; + return resCorba; } diff --git a/src/ResourcesManager/SALOME_ResourcesManager_Common.hxx b/src/ResourcesManager/SALOME_ResourcesManager_Common.hxx index 61fa66368..c00476daa 100644 --- a/src/ResourcesManager/SALOME_ResourcesManager_Common.hxx +++ b/src/ResourcesManager/SALOME_ResourcesManager_Common.hxx @@ -34,18 +34,25 @@ #endif #include +// #include CORBA_CLIENT_HEADER(SALOME_Resource) +// #include CORBA_CLIENT_HEADER(SALOME_ResourceJob) +// #include CORBA_CLIENT_HEADER(SALOME_ResourceContainer) #include CORBA_CLIENT_HEADER(SALOME_ResourcesManager) #include "ResourcesManager.hxx" // Functions for CPP <-> CORBA conversions // All those functions are thread-safe -SALOMERESOURCESMANAGER_EXPORT resourceParams resourceParameters_CORBAtoCPP(const Engines::ResourceParameters & params); -SALOMERESOURCESMANAGER_EXPORT Engines::ResourceParameters_var resourceParameters_CPPtoCORBA(const resourceParams & params); +SALOMERESOURCESMANAGER_EXPORT resourceParamsJob resourceParametersJob_CORBAtoCPP(const Engines::ResourceParametersJob& params); +SALOMERESOURCESMANAGER_EXPORT resourceParamsContainer resourceParametersContainer_CORBAtoCPP(const Engines::ResourceParametersContainer& params); +SALOMERESOURCESMANAGER_EXPORT Engines::ResourceParametersJob_var resourceParametersJob_CPPtoCORBA(const resourceParamsJob& params); +SALOMERESOURCESMANAGER_EXPORT Engines::ResourceParametersContainer_var resourceParametersContainer_CPPtoCORBA(const resourceParamsContainer& params); -SALOMERESOURCESMANAGER_EXPORT std::vector resourceList_CORBAtoCPP(const Engines::ResourceList & resList); -SALOMERESOURCESMANAGER_EXPORT Engines::ResourceList_var resourceList_CPPtoCORBA(const std::vector & resList); +SALOMERESOURCESMANAGER_EXPORT ResourceList resourceList_CORBAtoCPP(const Engines::ResourceList& resList); +SALOMERESOURCESMANAGER_EXPORT Engines::ResourceList_var resourceList_CPPtoCORBA(const ResourceList& resList); -SALOMERESOURCESMANAGER_EXPORT ParserResourcesType resourceDefinition_CORBAtoCPP(const Engines::ResourceDefinition & resDef); -SALOMERESOURCESMANAGER_EXPORT Engines::ResourceDefinition_var resourceDefinition_CPPtoCORBA(const ParserResourcesType & resource); +SALOMERESOURCESMANAGER_EXPORT ParserResourcesTypeJob resourceDefinitionJob_CORBAtoCPP(const Engines::ResourceDefinitionJob& resDef); +SALOMERESOURCESMANAGER_EXPORT ParserResourcesTypeContainer resourceDefinitionContainer_CORBAtoCPP(const Engines::ResourceDefinitionContainer& resDef); +SALOMERESOURCESMANAGER_EXPORT Engines::ResourceDefinitionJob_var resourceDefinitionJob_CPPtoCORBA(const ParserResourcesTypeJob& resource); +SALOMERESOURCESMANAGER_EXPORT Engines::ResourceDefinitionContainer_var resourceDefinitionContainer_CPPtoCORBA(const ParserResourcesTypeContainer& resource); #endif