Salome HOME
Issue 0020194: EDF 977 ALL: Get rid of warnings PACKAGE_VERSION already defined
[modules/kernel.git] / src / ResourcesManager / SALOME_ResourcesManager.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "SALOME_ResourcesManager.hxx" 
23 #include "Utils_ExceptHandlers.hxx"
24 #include "Utils_CorbaException.hxx"
25 #include "OpUtil.hxx"
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #ifndef WIN32
30 #include <unistd.h>
31 #else
32 #include <io.h>
33 #include <process.h>
34 #endif
35 #include <fstream>
36 #include <iostream>
37 #include <sstream>
38 #include <string.h>
39 #include <map>
40 #include <list>
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include "utilities.h"
45
46 #define MAX_SIZE_FOR_HOSTNAME 256;
47
48 using namespace std;
49
50 const char *SALOME_ResourcesManager::_ResourcesManagerNameInNS = "/ResourcesManager";
51
52 //=============================================================================
53 /*!
54  * just for test
55  */ 
56 //=============================================================================
57
58 SALOME_ResourcesManager::
59 SALOME_ResourcesManager(CORBA::ORB_ptr orb, 
60                         PortableServer::POA_var poa, 
61                         SALOME_NamingService *ns,
62                         const char *xmlFilePath) : _rm(xmlFilePath)
63 {
64   MESSAGE("SALOME_ResourcesManager constructor");
65   _NS = ns;
66   _orb = CORBA::ORB::_duplicate(orb) ;
67   _poa = PortableServer::POA::_duplicate(poa) ;
68   PortableServer::ObjectId_var id = _poa->activate_object(this);
69   CORBA::Object_var obj = _poa->id_to_reference(id);
70   Engines::ResourcesManager_var refContMan = Engines::ResourcesManager::_narrow(obj);
71   _NS->Register(refContMan,_ResourcesManagerNameInNS);
72   MESSAGE("SALOME_ResourcesManager constructor end");
73 }
74
75 //=============================================================================
76 /*!
77  *  Standard constructor, parse resource file.
78  *  - if ${APPLI} exists in environment,
79  *    look for ${HOME}/${APPLI}/CatalogResources.xml
80  *  - else look for default:
81  *    ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
82  *  - parse XML resource file.
83  */ 
84 //=============================================================================
85
86 SALOME_ResourcesManager::SALOME_ResourcesManager(CORBA::ORB_ptr orb, 
87                                                  PortableServer::POA_var poa, 
88                                                  SALOME_NamingService *ns) : _rm()
89 {
90   MESSAGE("SALOME_ResourcesManager constructor");
91   _NS = ns;
92   _orb = CORBA::ORB::_duplicate(orb) ;
93   _poa = PortableServer::POA::_duplicate(poa) ;
94   PortableServer::ObjectId_var id = _poa->activate_object(this);
95   CORBA::Object_var obj = _poa->id_to_reference(id);
96   Engines::ResourcesManager_var refContMan = Engines::ResourcesManager::_narrow(obj);
97   _NS->Register(refContMan,_ResourcesManagerNameInNS);
98
99   MESSAGE("SALOME_ResourcesManager constructor end");
100 }
101
102 //=============================================================================
103 /*!
104  *  Standard Destructor
105  */ 
106 //=============================================================================
107
108 SALOME_ResourcesManager::~SALOME_ResourcesManager()
109 {
110   MESSAGE("SALOME_ResourcesManager destructor");
111 }
112
113
114 //=============================================================================
115 /*! CORBA method:
116  *  shutdown all the containers, then the ContainerManager servant
117  */
118 //=============================================================================
119
120 void SALOME_ResourcesManager::Shutdown()
121 {
122   MESSAGE("Shutdown");
123   _NS->Destroy_Name(_ResourcesManagerNameInNS);
124   PortableServer::ObjectId_var oid = _poa->servant_to_id(this);
125   _poa->deactivate_object(oid);
126 }
127
128 //=============================================================================
129 //! get the name of resources fitting the specified constraints (params)
130 /*!
131  *  If hostname specified, check it is local or known in resources catalog.
132  *
133  *  Else
134  *  - select first machines with corresponding OS (all machines if
135  *    parameter OS empty),
136  *  - then select the sublist of machines on which the component is known
137  *    (if the result is empty, that probably means that the inventory of
138  *    components is probably not done, so give complete list from previous step)
139  */ 
140 //=============================================================================
141
142 Engines::MachineList *
143 SALOME_ResourcesManager::GetFittingResources(const Engines::MachineParameters& params)
144 {
145 //   MESSAGE("ResourcesManager::GetFittingResources");
146   machineParams p;
147   p.hostname = params.hostname;
148   p.OS = params.OS;
149   p.nb_node = params.nb_node;
150   p.nb_proc_per_node = params.nb_proc_per_node;
151   p.cpu_clock = params.cpu_clock;
152   p.mem_mb = params.mem_mb;
153   p.parallelLib = params.parallelLib;
154   p.nb_component_nodes = params.nb_component_nodes;
155
156   for(unsigned int i=0;i<params.componentList.length();i++)
157     p.componentList.push_back(string(params.componentList[i]));
158
159   for(unsigned int i=0;i<params.computerList.length();i++)
160     p.computerList.push_back(string(params.computerList[i]));
161   
162   Engines::MachineList *ret=new Engines::MachineList;
163   try{
164       vector <std::string> vec = _rm.GetFittingResources(p);
165       ret->length(vec.size());
166       for(unsigned int i=0;i<vec.size();i++)
167         (*ret)[i] = (vec[i]).c_str();
168   }
169   catch(const ResourcesException &ex){
170     INFOS("Caught exception.");
171     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
172   }  
173
174   return ret;
175 }
176
177 //=============================================================================
178 /*!
179  *  dynamically obtains the first machines
180  */ 
181 //=============================================================================
182
183 char *
184 SALOME_ResourcesManager::FindFirst(const Engines::MachineList& listOfMachines)
185 {
186   vector<string> ml;
187   for(unsigned int i=0;i<listOfMachines.length();i++)
188     ml.push_back(string(listOfMachines[i]));
189
190   return CORBA::string_dup(_rm.Find("first",ml).c_str());
191 }
192
193 char *
194 SALOME_ResourcesManager::Find(const char* policy, const Engines::MachineList& listOfMachines)
195 {
196   vector<string> ml;
197   for(unsigned int i=0;i<listOfMachines.length();i++)
198     ml.push_back(string(listOfMachines[i]));
199   return CORBA::string_dup(_rm.Find(policy,ml).c_str());
200 }
201
202 Engines::MachineDefinition* SALOME_ResourcesManager::GetMachineParameters(const char *hostname)
203 {
204   ParserResourcesType resource = _rm.GetResourcesList(string(hostname));
205   Engines::MachineDefinition *p_ptr = new Engines::MachineDefinition;
206   p_ptr->hostname = CORBA::string_dup(resource.HostName.c_str());
207   p_ptr->alias = CORBA::string_dup(resource.Alias.c_str());
208   if( resource.Protocol == rsh )
209     p_ptr->protocol = "rsh";
210   else if( resource.Protocol == ssh )
211     p_ptr->protocol = "ssh";
212   p_ptr->username = CORBA::string_dup(resource.UserName.c_str());
213   p_ptr->applipath = CORBA::string_dup(resource.AppliPath.c_str());
214   p_ptr->componentList.length(resource.ComponentsList.size());
215   for(unsigned int i=0;i<resource.ComponentsList.size();i++)
216     p_ptr->componentList[i] = CORBA::string_dup(resource.ComponentsList[i].c_str());
217   p_ptr->OS = CORBA::string_dup(resource.OS.c_str());
218   p_ptr->mem_mb = resource.DataForSort._memInMB;
219   p_ptr->cpu_clock = resource.DataForSort._CPUFreqMHz;
220   p_ptr->nb_proc_per_node = resource.DataForSort._nbOfProcPerNode;
221   p_ptr->nb_node = resource.DataForSort._nbOfNodes;
222
223   if( resource.mpi == lam )
224     p_ptr->mpiImpl = "lam";
225   else if( resource.mpi == mpich1 )
226     p_ptr->mpiImpl = "mpich1";
227   else if( resource.mpi == mpich2 )
228     p_ptr->mpiImpl = "mpich2";
229   else if( resource.mpi == openmpi )
230     p_ptr->mpiImpl = "openmpi";
231   else if( resource.mpi == slurm )
232     p_ptr->mpiImpl = "slurm";
233   else if( resource.mpi == prun )
234     p_ptr->mpiImpl = "prun";
235
236   if( resource.Batch == pbs )
237     p_ptr->batch = "pbs";
238   else if( resource.Batch == lsf )
239     p_ptr->batch = "lsf";
240   else if( resource.Batch == sge )
241     p_ptr->batch = "sge";
242
243   p_ptr->nb_component_nodes=1;
244
245   return p_ptr;
246 }
247
248 std::string 
249 SALOME_ResourcesManager::getMachineFile(std::string hostname, CORBA::Long nb_procs, 
250                                         std::string parallelLib)
251 {
252   std::string machine_file_name("");
253
254   if (parallelLib == "Dummy")
255   {
256     MESSAGE("[getMachineFile] parallelLib is Dummy");
257     MapOfParserResourcesType resourcesList = _rm.GetList();
258     if (resourcesList.find(hostname) != resourcesList.end())
259     {
260       ParserResourcesType resource = resourcesList[hostname];
261
262       // Check if resource is cluster or not
263       if (resource.ClusterMembersList.empty())
264       {
265         //It is not a cluster so we create a cluster with one machine
266         ParserResourcesClusterMembersType fake_node;
267         fake_node.HostName = resource.HostName;
268         fake_node.Protocol = resource.Protocol;
269         fake_node.UserName = resource.UserName;
270         fake_node.AppliPath = resource.AppliPath;
271         fake_node.DataForSort = resource.DataForSort;
272
273         resource.ClusterMembersList.push_front(fake_node);
274       }
275
276       // Creating list of machines for creating the machine file
277       std::list<std::string> list_of_machines;
278       std::list<ParserResourcesClusterMembersType>::iterator cluster_it = 
279         resource.ClusterMembersList.begin();
280       while (cluster_it != resource.ClusterMembersList.end())
281       {
282         // For each member of the cluster we add a nbOfNodes * nbOfProcPerNode in the list
283         unsigned int number_of_proc = (*cluster_it).DataForSort._nbOfNodes * 
284                                       (*cluster_it).DataForSort._nbOfProcPerNode;
285         for (unsigned int i = 0; i < number_of_proc; i++)
286           list_of_machines.push_back((*cluster_it).HostName);
287         cluster_it++;
288       }
289
290       // Creating machine file
291       machine_file_name = tmpnam(NULL);
292       std::ofstream machine_file(machine_file_name.c_str(), ios_base::out);
293
294       CORBA::Long machine_number = 0;
295       std::list<std::string>::iterator it = list_of_machines.begin();
296       while (machine_number != nb_procs)
297       {
298         // Adding a new node to the machine file
299         machine_file << *it << endl;
300
301         // counting...
302         it++;
303         if (it == list_of_machines.end())
304           it = list_of_machines.begin();
305         machine_number++;
306       }
307     }
308     else
309       INFOS("[getMachineFile] Error hostname not found in resourcesList -> " << hostname);
310   }
311   else if (parallelLib == "Mpi")
312   {
313     MESSAGE("[getMachineFile] parallelLib is Mpi");
314
315     MapOfParserResourcesType resourcesList = _rm.GetList();
316     if (resourcesList.find(hostname) != resourcesList.end())
317     {
318       ParserResourcesType resource = resourcesList[hostname];
319       // Check if resource is cluster or not
320       if (resource.ClusterMembersList.empty())
321       {
322         //It is not a cluster so we create a cluster with one machine
323         ParserResourcesClusterMembersType fake_node;
324         fake_node.HostName = resource.HostName;
325         fake_node.Protocol = resource.Protocol;
326         fake_node.UserName = resource.UserName;
327         fake_node.AppliPath = resource.AppliPath;
328         fake_node.DataForSort = resource.DataForSort;
329
330         resource.ClusterMembersList.push_front(fake_node);
331       }
332
333       // Choose mpi implementation -> each MPI implementation has is own machinefile...
334       if (resource.mpi == lam)
335       {
336         // Creating machine file
337         machine_file_name = tmpnam(NULL);
338         std::ofstream machine_file(machine_file_name.c_str(), ios_base::out);
339
340         // We add all cluster machines to the file
341         std::list<ParserResourcesClusterMembersType>::iterator cluster_it = 
342           resource.ClusterMembersList.begin();
343         while (cluster_it != resource.ClusterMembersList.end())
344         {
345           unsigned int number_of_proc = (*cluster_it).DataForSort._nbOfNodes * 
346             (*cluster_it).DataForSort._nbOfProcPerNode;
347           machine_file << (*cluster_it).HostName << " cpu=" << number_of_proc << endl;
348           cluster_it++;
349         }
350       }
351       else if (resource.mpi == nompi)
352       {
353         INFOS("[getMachineFile] Error hostname MPI implementation was defined for " << hostname);
354       }
355       else
356         INFOS("[getMachineFile] Error hostname MPI implementation not currenly handled for " << hostname);
357     }
358     else
359       INFOS("[getMachineFile] Error hostname not found in resourcesList -> " << hostname);
360   }
361   else
362     INFOS("[getMachineFile] Error parallelLib is not handled -> " << parallelLib);
363
364   return machine_file_name;
365 }