]> SALOME platform Git repositories - modules/yacs.git/blob - src/runtime/SalomeContainerTools.cxx
Salome HOME
Debug + makes the remote python nodes //
[modules/yacs.git] / src / runtime / SalomeContainerTools.cxx
1 // Copyright (C) 2006-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SalomeContainerTools.hxx"
21 #include "SALOME_LifeCycleCORBA.hxx"
22 #include "SALOME_NamingService.hxx"
23 #include "SALOME_ResourcesManager.hxx"
24 #include "SALOME_ContainerManager.hxx"
25 #include "Container.hxx"
26 #include "AutoLocker.hxx"
27
28 #include "YacsTrace.hxx"
29 #include "Proc.hxx"
30 #include "ServiceNode.hxx"
31 #include "ComponentInstance.hxx"
32 #include "SalomeContainerHelper.hxx"
33 #include "RuntimeSALOME.hxx"
34 #include "Exception.hxx"
35
36 #include <sstream>
37
38 using namespace YACS::ENGINE;
39
40 SalomeContainerTools::SalomeContainerTools()
41 {
42   /* Init ContainerParameters */
43   SALOME_LifeCycleCORBA::preSet(_params);
44 }
45
46 SalomeContainerTools::SalomeContainerTools(const SalomeContainerTools& other):_params(other._params),_propertyMap(other._propertyMap)
47 {
48 }
49
50 void SalomeContainerTools::clearProperties()
51 {
52   _propertyMap.clear();
53   _params=Engines::ContainerParameters();
54 }
55
56 std::string SalomeContainerTools::getProperty(const std::string& name) const
57 {
58   std::map<std::string,std::string>::const_iterator it(_propertyMap.find(name));
59   if(it!=_propertyMap.end())
60     return (*it).second;
61   else
62     return std::string();
63 }
64
65 void SalomeContainerTools::setProperty(const std::string& name, const std::string& value)
66 {
67   //DEBTRACE("SalomeContainer::setProperty : " << name << " ; " << value);
68   // Container Part
69   if (name == "container_name")
70     _params.container_name = CORBA::string_dup(value.c_str());
71   else if (name == "workingdir")
72     _params.workingdir = CORBA::string_dup(value.c_str());
73   else if (name == "nb_parallel_procs")
74   {
75     std::istringstream iss(value);
76     if (!(iss >> _params.nb_proc))
77       throw Exception("salomecontainer::setproperty : params.nb_proc value not correct : " + value);
78   }
79   else if (name == "isMPI")
80   {
81     if (value == "true")
82       _params.isMPI = true;
83     else if (value == "false")
84       _params.isMPI = false;
85     else 
86       throw Exception("SalomeContainer::setProperty : params.isMPI value not correct : " + value);
87   }
88   else if (name == "parallelLib")
89     _params.parallelLib = CORBA::string_dup(value.c_str());
90
91   // Resource part
92   else if (name == "name")
93     _params.resource_params.name = CORBA::string_dup(value.c_str());
94   else if (name == "hostname")
95     _params.resource_params.hostname = CORBA::string_dup(value.c_str());
96   else if (name == "OS")
97     _params.resource_params.OS = CORBA::string_dup(value.c_str());
98   else if (name == "nb_resource_procs")
99   {
100     std::istringstream iss(value);
101     if (!(iss >> _params.resource_params.nb_proc))
102       throw Exception("salomecontainer::setproperty : params.resource_params.nb_proc value not correct : " + value);
103   }
104   else if (name == "mem_mb")
105   {
106     std::istringstream iss(value);
107     if (!(iss >> _params.resource_params.mem_mb))
108       throw Exception("salomecontainer::setproperty : params.resource_params.mem_mb value not correct : " + value);
109   }
110   else if (name == "cpu_clock")
111   {
112     std::istringstream iss(value);
113     if (!(iss >> _params.resource_params.cpu_clock))
114       throw Exception("salomecontainer::setproperty : params.resource_params.cpu_clock value not correct : " + value);
115   }
116   else if (name == "nb_node")
117   {
118     std::istringstream iss(value);
119     if (!(iss >> _params.resource_params.nb_node))
120       throw Exception("salomecontainer::setproperty : params.nb_node value not correct : " + value);
121   }
122   else if (name == "nb_proc_per_node")
123   {
124     std::istringstream iss(value);
125     if (!(iss >> _params.resource_params.nb_proc_per_node))
126       throw Exception("salomecontainer::setproperty : params.nb_proc_per_node value not correct : " + value);
127   }
128   else if (name == "policy")
129     _params.resource_params.policy = CORBA::string_dup(value.c_str());
130   else if (name == "component_list")
131   {
132     std::string clean_value(value);
133
134     // Step 1: remove blanks
135     while(clean_value.find(" ") != std::string::npos)
136       clean_value = clean_value.erase(clean_value.find(" "), 1);
137
138     // Step 2: get values
139     while(!clean_value.empty())
140     {
141       std::string result("");
142       std::string::size_type loc = clean_value.find(",", 0);
143       if (loc != std::string::npos)
144       {
145         result = clean_value.substr(0, loc);
146         clean_value = clean_value.erase(0, loc+1);
147       }
148       else
149       {
150         result = clean_value;
151         clean_value.erase();
152       }
153       if (result != "," && result != "")
154       {
155         addToComponentList(result);
156       }
157     }
158
159   }
160   else if (name == "resource_list")
161   {
162     std::string clean_value(value);
163
164     // Step 1: remove blanks
165     while(clean_value.find(" ") != std::string::npos)
166       clean_value = clean_value.erase(clean_value.find(" "), 1);
167
168     // Step 2: get values
169     while(!clean_value.empty())
170     {
171       std::string result("");
172       std::string::size_type loc = clean_value.find(",", 0);
173       if (loc != std::string::npos)
174       {
175         result = clean_value.substr(0, loc);
176         clean_value = clean_value.erase(0, loc+1);
177       }
178       else
179       {
180         result = clean_value;
181         clean_value.erase();
182       }
183       if (result != "," && result != "")
184       {
185         addToResourceList(result);
186       }
187     }
188
189   }
190   _propertyMap[name]=value;
191 }
192
193 void SalomeContainerTools::addToComponentList(const std::string& name)
194 {
195   // Search if name is already in the list
196   for (CORBA::ULong i = 0; i < _params.resource_params.componentList.length(); i++)
197     {
198       std::string component_name = _params.resource_params.componentList[i].in();
199       if (component_name == name)
200         return;
201     }
202   // Add name to list
203   CORBA::ULong lgth = _params.resource_params.componentList.length();
204   _params.resource_params.componentList.length(lgth + 1);
205   _params.resource_params.componentList[lgth] = CORBA::string_dup(name.c_str());
206 }
207
208 void SalomeContainerTools::addToResourceList(const std::string& name)
209 {
210   // Search if name is already in the list
211   for (CORBA::ULong i = 0; i < _params.resource_params.resList.length(); i++)
212     {
213       std::string component_name = _params.resource_params.resList[i].in();
214       if (component_name == name)
215         return;
216     }
217   // Add name to list
218   CORBA::ULong lgth = _params.resource_params.resList.length();
219   _params.resource_params.resList.length(lgth + 1);
220   _params.resource_params.resList[lgth] = CORBA::string_dup(name.c_str());
221 }
222
223 std::string SalomeContainerTools::getContainerName() const
224 {
225   return std::string(_params.container_name);
226 }
227
228 void SalomeContainerTools::setContainerName(const std::string& name)
229 {
230   SetContainerNameOf(_params,name);
231 }
232
233 std::string SalomeContainerTools::getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const
234 {
235   isEmpty=true;
236   std::string name(_params.container_name);
237   if(!name.empty())
238     {
239       isEmpty=false;
240       return name;
241     }
242   else
243     {
244       //give a almost unique name to the container : Pid_Name_Addr
245       std::ostringstream stream;
246       stream << getpid();
247       stream << "_";
248       stream << contPtr->getName();
249       stream << "_";
250       stream << contPtr->getDiscreminantStrOfThis(askingNode);
251       return stream.str();
252     }
253 }
254
255 std::string SalomeContainerTools::getHostName() const
256 {
257   return std::string(_params.resource_params.hostname);
258 }
259
260 void SalomeContainerTools::SetContainerNameOf(Engines::ContainerParameters& params, const std::string& name)
261 {
262   params.container_name=CORBA::string_dup(name.c_str());
263 }
264
265 std::map<std::string,std::string> SalomeContainerTools::getResourceProperties(const std::string& name) const
266 {
267   std::map<std::string,std::string> properties;
268
269   YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
270   CORBA::ORB_ptr orb = runTime->getOrb();
271   if (!orb) return properties;
272   SALOME_NamingService namingService(orb);
273   SALOME_LifeCycleCORBA lcc(&namingService);
274   CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
275   if (CORBA::is_nil(obj))
276     return properties;
277   Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
278   if (CORBA::is_nil(resManager))
279     return properties;
280
281   std::ostringstream value;
282   Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
283   properties["hostname"]=resource_definition->hostname.in();
284   properties["OS"]=resource_definition->OS.in();
285   value.str(""); value << resource_definition->mem_mb;
286   properties["mem_mb"]=value.str();
287   value.str(""); value << resource_definition->cpu_clock;
288   properties["cpu_clock"]=value.str();
289   value.str(""); value << resource_definition->nb_node;
290   properties["nb_node"]=value.str();
291   value.str(""); value << resource_definition->nb_proc_per_node;
292   properties["nb_proc_per_node"]=value.str();
293   /*
294   properties["component_list"]="";
295   for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
296     {
297       if(i > 0)
298         properties["component_list"]=properties["component_list"]+",";
299       properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();
300     }
301     */
302   return properties;
303 }
304
305 /*!
306  * \param [in] compoNames
307  * \param [in,out] shutdownLevel
308  */
309 void SalomeContainerTools::Start(const std::vector<std::string>& compoNames, SalomeContainerHelper *schelp, SalomeContainerTools& sct, int& shutdownLevel, const Container *cont, const Task *askingNode)
310 {
311   CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb());
312   SALOME_NamingService ns;
313   try
314   {
315       ns.init_orb(orb);
316   }
317   catch(SALOME_Exception& e)
318   {
319       throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
320   }
321   CORBA::Object_var obj(ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS));
322   Engines::ContainerManager_var contManager(Engines::ContainerManager::_narrow(obj));
323
324   bool isEmptyName;
325   std::string str(sct.getNotNullContainerName(cont,askingNode,isEmptyName));
326   DEBTRACE("SalomeContainer::start " << str <<";"<< _sct.getHostName() <<";"<<_type);
327
328   // Finalize parameters with components found in the container
329
330   for(std::vector<std::string>::const_iterator iter=compoNames.begin();iter!=compoNames.end();iter++)
331     sct.addToComponentList(*iter);
332
333   Engines::ContainerParameters myparams(sct.getParameters());
334   {
335     std::string dftLauchMode(schelp->getDftLaunchMode());
336     myparams.mode=CORBA::string_dup(dftLauchMode.c_str());
337   }
338
339   //If a container_name is given try to find an already existing container in naming service
340   //If not found start a new container with the given parameters
341   if (dynamic_cast<SalomeContainerMonoHelper *>(schelp) && !isEmptyName)
342     {
343       myparams.mode=CORBA::string_dup("getorstart");
344     }
345
346   if (isEmptyName)
347     {
348       shutdownLevel=1;
349     }
350   //sct.setContainerName(str);
351   SetContainerNameOf(myparams,str);
352   Engines::Container_var trueCont(Engines::Container::_nil());
353   if(!isEmptyName && shutdownLevel==999)
354     {
355       //Make this only the first time start is called (_shutdownLevel==999)
356       //If the container is named, first try to get an existing container
357       //If there is an existing container use it and set the shutdown level to 3
358       //If there is no existing container, try to launch a new one and set the shutdown level to 2
359       myparams.mode="get";
360       try
361       {
362           trueCont=contManager->GiveContainer(myparams);
363       }
364       catch( const SALOME::SALOME_Exception& ex )
365       {
366           std::string msg="SalomeContainer::start : no existing container : ";
367           msg += '\n';
368           msg += ex.details.text.in();
369           DEBTRACE( msg );
370       }
371       catch(...)
372       {
373       }
374
375       if(!CORBA::is_nil(trueCont))
376         {
377           shutdownLevel=3;
378           DEBTRACE( "container found: " << str << " " << _shutdownLevel );
379         }
380       else
381         {
382           shutdownLevel=2;
383           myparams.mode="start";
384           DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
385         }
386     }
387
388   if(CORBA::is_nil(trueCont))
389     try
390   {
391         // --- GiveContainer is used in batch mode to retreive launched containers,
392         //     and is equivalent to StartContainer when not in batch.
393         trueCont=contManager->GiveContainer(myparams);
394   }
395   catch( const SALOME::SALOME_Exception& ex )
396   {
397       std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
398       msg += '\n';
399       msg += ex.details.text.in();
400       throw Exception(msg);
401   }
402   catch(CORBA::COMM_FAILURE&)
403   {
404       throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
405   }
406   catch(CORBA::Exception&)
407   {
408       throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
409   }
410
411   if(CORBA::is_nil(trueCont))
412     throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
413
414   schelp->setContainer(askingNode,trueCont);
415
416   CORBA::String_var containerName(trueCont->name()),hostName(trueCont->getHostName());
417   std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << trueCont->getPID() << std::endl;
418 }
419
420 CORBA::Object_ptr SalomeContainerTools::LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode)
421 {
422   DEBTRACE("SalomeContainer::loadComponent ");
423   const ComponentInstance *inst(askingNode?askingNode->getComponent():0);
424   {
425     YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
426     if(!cont->isAlreadyStarted(askingNode))
427       cont->start(askingNode);
428   }
429   if(!inst)
430     throw Exception("SalomeContainerTools::LoadComponent : no instance of component in the task requesting for a load of its component !");
431   CORBA::Object_ptr objComponent=CORBA::Object::_nil();
432   {
433     YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
434     std::string compoName(inst->getCompoName());
435     Engines::Container_var container(launchModeType->getContainer(askingNode));
436
437     char *reason;
438     bool isLoadable(container->load_component_Library(compoName.c_str(), reason));
439     if(isLoadable)
440       objComponent=CreateComponentInstance(cont,container,inst);
441   }
442   return objComponent;
443 }
444
445 CORBA::Object_ptr SalomeContainerTools::CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst)
446 {
447   if(!inst)
448     throw Exception("SalomeContainerTools::CreateComponentInstance : no instance of component in the task requesting for a load of its component !");
449   char *reason(0);
450   std::string compoName(inst->getCompoName());
451   CORBA::Object_ptr objComponent=CORBA::Object::_nil();
452   int studyid(1);
453   Proc* p(cont->getProc());
454   if(p)
455     {
456       std::string value(p->getProperty("DefaultStudyID"));
457       if(!value.empty())
458         studyid= atoi(value.c_str());
459     }
460   // prepare component instance properties
461   Engines::FieldsDict_var env(new Engines::FieldsDict);
462   std::map<std::string, std::string> properties(inst->getProperties());
463   if(p)
464     {
465       std::map<std::string,std::string> procMap=p->getProperties();
466       properties.insert(procMap.begin(),procMap.end());
467     }
468
469   std::map<std::string, std::string>::const_iterator itm;
470   env->length(properties.size());
471   int item=0;
472   for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
473     {
474       DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
475       env[item].key= CORBA::string_dup(itm->first.c_str());
476       env[item].value <<= itm->second.c_str();
477     }
478
479   objComponent=contPtr->create_component_instance_env(compoName.c_str(), studyid, env, reason);
480   if(CORBA::is_nil(objComponent))
481     {
482       std::string text="Error while trying to create a new component: component '"+ compoName;
483       text=text+"' is not installed or it's a wrong name";
484       text += '\n';
485       text += reason;
486       CORBA::string_free(reason);
487       throw Exception(text);
488     }
489   return objComponent;
490 }
491
492 std::string SalomeContainerTools::GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
493 {
494   if(cont->isAlreadyStarted(askingNode))
495     {
496       Engines::Container_var container(launchModeType->getContainer(askingNode));
497       const char *what="/";
498       CORBA::String_var corbaStr(container->name());
499       std::string ret(corbaStr);
500
501       //Salome FOREVER ...
502       std::string::size_type i=ret.find_first_of(what,0);
503       i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
504       if(i!=std::string::npos)
505         return ret.substr(i+1);
506       return ret;
507     }
508   else
509     return "Not placed yet !!!";
510 }
511
512 std::string SalomeContainerTools::GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
513 {
514   if(cont->isAlreadyStarted(askingNode))
515     {
516       Engines::Container_var container(launchModeType->getContainer(askingNode));
517       try
518       {
519           CORBA::String_var corbaStr(container->name());
520           std::string ret(corbaStr);
521           return ret;
522       }
523       catch(...)
524       {
525           return "Unknown_placement";
526       }
527     }
528   else
529     return "Not_placed_yet";
530 }