IceStarter.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore::core
19  * @author Nicola Miskowiec
20  * @date 2016
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 
26 #include "IceStarter.h"
30 #include <algorithm>
31 
32 using namespace ScenarioManager;
33 using namespace Exec;
34 using namespace Generator;
35 using namespace Data_Structure;
36 
37 IceStarter::IceStarter(const IceGrid::AdminPrx admin) : admin(admin), statusReader(admin) //IceAdmin interrupts calls if they take longer than 3 minutes
38 {
39 }
40 
41 void IceStarter::startApplication(ApplicationInstancePtr application, StatusManager statusManager, const std::string& commandLineParameters, bool printOnly)
42 {
44  {
45  application->setStatusWriteBlock(false);
46  };
47  if (!application->getEnabled())
48  {
49  return;
50  }
51 
52  // IceGridXmlGenerator generator;
53 
54  // IceGrid::ServerInstanceDescriptor serverInstanceDescriptor = generator.generateComponentNode(application);
55  // std::vector<std::string> appNames = admin->getAllApplicationNames();
56 
57  try
58  {
59  auto appId = IceStatusReader::GetApplicationId(application);
60  // IceGrid::ServerInfo serverInfo = admin->getServerInfo(appId);
61  if (!admin->isServerEnabled(appId))
62  {
63  admin->enableServer(appId, true);
64  }
65  if (admin->getServerState(appId) != IceGrid::Active)
66  {
67  admin->startServer(appId);
68  }
69  try
70  {
71  application->setPid(admin->getServerPid(appId));
72 
73  }
74  catch (...)
75  {
76  ARMARX_INFO << deactivateSpam(10, application->getName()) << "Could not get PID for " << appId;
77  application->setPid(-1);
78  }
79  }
80  catch (IceGrid::ServerNotExistException& ex)
81  {
82  ARMARX_ERROR_S << "There is no Server for " << application->getName() << " - please make sure the Scenario is correctly deployed";
83 
84  }
85  catch (IceGrid::ServerStartException& ex)
86  {
87  ARMARX_ERROR_S << "Could not start Server " << application->getName() << " Reason: " << ex.reason;
88 
89  }
90  catch (IceGrid::NodeUnreachableException& ex)
91  {
92  ARMARX_ERROR_S << "Could not connect to the Node of " << application->getName() << " - please make sure the Scenario is correctly deployed";
93 
94  }
95  catch (IceGrid::DeploymentException& ex)
96  {
97  ARMARX_ERROR_S << "Could not connect deploy " << application->getName() << " - please make sure the Scenario is correctly deployed";
98 
99  }
100 
101 }
102 
103 void IceStarter::deployApplication(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager, const std::string& commandLineParameters, bool printOnly)
104 {
106  {
107  application->setStatusWriteBlock(false);
108  };
109  if (!application->getEnabled())
110  {
111  return;
112  }
113 
114  IceGridXmlGenerator generator;
115 
116  IceGrid::ServerInstanceDescriptor serverInstanceDescriptor = generator.generateComponentNode(application);
117  std::vector<std::string> appNames = admin->getAllApplicationNames();
118  //There already is an IceApplication so just register this app and update
119  if (std::find(appNames.begin(), appNames.end(), application->getScenario()->getName()) != appNames.end())
120  {
121  IceGrid::ApplicationInfo appInfo = admin->getApplicationInfo(application->getScenario()->getName());
122  IceGrid::ApplicationDescriptor appDescriptor = appInfo.descriptor;
123 
124  //since we only want to update this app clear the server instance list
125  appDescriptor.nodes[application->getEffectiveNodeName()].serverInstances.clear();
126  appDescriptor.nodes[application->getEffectiveNodeName()].serverInstances.push_back(serverInstanceDescriptor);
127  IceGrid::ApplicationUpdateDescriptor appUpdate = generator.generateUpdateDescriptor(appDescriptor);
128  admin->updateApplication(appUpdate);
129  }
130  else //in this case we need to create the IceApplication with just this app
131  {
132  ARMARX_INFO << application->getName() << " on node " << application->getEffectiveNodeName();
133 
134  IceGrid::ApplicationDescriptor appDescriptor;
135  if (application->getScenario()->getScenarioDeploymentType() == ScenarioDeploymentType::Local)
136  {
137  appDescriptor = generator.generateEmptyLocalApplicationDescriptor(application->getScenario(), admin);
138  }
139  else
140  {
141  appDescriptor = generator.generateEmptyRemoteApplicationDescriptor(application->getScenario(), admin);
142  }
143  appDescriptor.nodes[application->getEffectiveNodeName()].serverInstances.push_back(serverInstanceDescriptor);
144  admin->addApplication(appDescriptor);
145  statusManager.setIceScenario(application->getScenario(), true);
146  }
147 
148  try
149  {
150  application->setPid(admin->getServerPid(application->getName()));
151  }
152  catch (...)
153  {
154  ARMARX_INFO << deactivateSpam(10, application->getName()) << "Could not get PID for " << application->getName();
155  application->setPid(-1);
156  }
157 
158 }
159 
160 void IceStarter::deployScenario(Data_Structure::ScenarioPtr scenario, StatusManager statusManager, const std::string& commandLineParameters, bool printOnly)
161 {
163  {
164  scenario->setStatusWriteBlock(false);
165  };
166  IceGridXmlGenerator generator;
167 
168  IceGrid::ApplicationDescriptor appDescriptor;
169  if (scenario->getScenarioDeploymentType() == ScenarioDeploymentType::Local)
170  {
171  appDescriptor = generator.generateLocalApplicationDescriptor(scenario, admin);
172  }
173  else
174  {
175  appDescriptor = generator.generateRemoteApplicationDescriptor(scenario, admin);
176  }
177 
178  try
179  {
180  std::vector<std::string> appNames = admin->getAllApplicationNames();
181  std::vector<std::string> nodeNames = admin->getAllNodeNames();
182  for (auto nodeName : scenario->getAllDeploymendNodeNames())
183  {
184  if (std::find(nodeNames.begin(), nodeNames.end(), nodeName) == nodeNames.end())
185  {
186  ARMARX_ERROR_S << "You are launching an Scenario with applications on an unlaunched Node. Either start the node or change the launch Nodes of the curresponding applications. Nodename is: " + nodeName;
187 
188  throw IceGrid::DeploymentException("You are launching an Scenario with applications on an unlaunched Node. Either start the node or change the launch Nodes of the curresponding applications. Nodename is: " + nodeName);
189  }
190  }
191 
192  if (std::find(appNames.begin(), appNames.end(), scenario->getName()) != appNames.end())
193  {
194  admin->updateApplication(generator.generateUpdateDescriptor(appDescriptor));
195  }
196  else
197  {
198  admin->addApplication(appDescriptor);
199  }
200  for (auto& node : appDescriptor.nodes)
201  {
202  for (IceGrid::ServerInstanceDescriptor& server : node.second.serverInstances)
203  {
204  auto name = server.parameterValues["componentId"];
205  admin->enableServer(name, false);
206  }
207  }
208  }
209  catch (IceGrid::AccessDeniedException& ex)
210  {
211  ARMARX_ERROR_S << "Error while deploying Scenario " << scenario->getName() << " another application has the accesss rights to the IceGridAdmin. (Please try again)";
212 
213  }
214  catch (IceGrid::DeploymentException& ex)
215  {
216 
217  throw ex;
218  }
219 
220  statusManager.setIceScenario(scenario, true);
221 
222 }
223 
224 
225 void IceStarter::startScenario(Data_Structure::ScenarioPtr scenario, StatusManager statusManager, const std::string& commandLineParameters, bool printOnly)
226 {
227  std::vector<std::string> appNames = admin->getAllApplicationNames();
228  //std::vector<Ice::AsyncResultPtr> futures;
229  auto admin = this->admin;
230  std::thread
231  {
232  [admin, scenario, statusManager, commandLineParameters, printOnly, appNames]
233  {
235  {
236  scenario->setStatusWriteBlock(false);
237  };
238  std::map<Data_Structure::ApplicationInstancePtr, ::Ice::AsyncResultPtr> asyncResultMap;
239  //Check if there is an deployed application
240  if (std::find(appNames.begin(), appNames.end(), scenario->getName()) != appNames.end())
241  {
242  for (auto app : *scenario->getApplications())
243  {
244  auto appId = IceStatusReader::GetApplicationId(app);
245  try
246  {
247  if (admin->getServerState(appId) == IceGrid::ServerState::Inactive)
248  {
249  ARMARX_DEBUG << "Enabling server";
250  admin->enableServer(appId, true);
251  ARMARX_DEBUG << "Starting server";
252  asyncResultMap[app] = admin->begin_startServer(appId);
253  }
254  }
255  catch (IceGrid::ServerNotExistException& ex)
256  {
257  ARMARX_INFO_S << "Could not start Server " << appId << " because it is not existent";
258  }
259  catch (IceGrid::ServerStartException& ex)
260  {
261  ARMARX_INFO_S << "Could not start Server " << appId << " because it had an starting error. \nReason :" << ex.reason;
262  if (scenario->getScenarioDeploymentType() == ScenarioDeploymentType::Remote)
263  {
264  IceGridXmlGenerator generator;
265  ARMARX_INFO_S << "Often this is related to an unknown launching path. The ScenarioManager thinks to find the binary on the host of " << app->getEffectiveNodeName() << " at: " << generator.getDefaultSyncFile() << "/bin";
266  }
267  throw ex;
268  }
269  catch (IceGrid::NodeUnreachableException& ex)
270  {
271  ARMARX_INFO_S << "Could not start Server " << appId << " because the node is unreachable";
272  }
273  catch (IceGrid::DeploymentException& ex)
274  {
275  ARMARX_INFO_S << "Could not start Server " << appId << " because there was an deployment error";
276  }
277  }
278  for (auto pair : asyncResultMap)
279  {
280  auto app = pair.first;
281  auto appId = IceStatusReader::GetApplicationId(app);
282  try
283  {
284  admin->end_startServer(pair.second);
285  ARMARX_DEBUG << "Server " << appId << " started";
286 
287  }
288  catch (IceGrid::ServerNotExistException& ex)
289  {
290  ARMARX_INFO_S << "Could not start Server " << appId << " because it is not existent";
291  }
292  catch (IceGrid::ServerStartException& ex)
293  {
294  ARMARX_INFO_S << "Could not start Server " << appId << " because it had an starting error. \nReason :" << ex.reason;
295  if (scenario->getScenarioDeploymentType() == ScenarioDeploymentType::Remote)
296  {
297  IceGridXmlGenerator generator;
298  ARMARX_INFO_S << "Often this is related to an unknown launching path. The ScenarioManager thinks to find the binary on the host of " << app->getEffectiveNodeName() << " at: " << generator.getDefaultSyncFile() << "/bin";
299  }
300  throw ex;
301  }
302  catch (IceGrid::NodeUnreachableException& ex)
303  {
304  ARMARX_INFO_S << "Could not start Server " << appId << " because the node is unreachable";
305  }
306  catch (IceGrid::DeploymentException& ex)
307  {
308  ARMARX_INFO_S << "Could not start Server " << appId << " because there was an deployment error";
309  }
310  }
311  }
312  else //in this case we need to deploy the IceApplication
313  {
314  ARMARX_ERROR_S << "There is no deployed IceApplication for scenario " << scenario->getName() << " - please deploy it before starting";
315  }
316 
317  // for (auto future : futures)
318  // {
319  // future->waitForCompleted();
320  // }
321  for (auto app : *scenario->getApplications())
322  {
323  try
324  {
325  app->setPid(admin->getServerPid(IceStatusReader::GetApplicationId(app)));
326  ARMARX_INFO << " PID of " << app->getName() << " is " << app->getPid();
327  }
328  catch (...)
329  {
330  ARMARX_INFO << deactivateSpam(10, app->getName()) << "Could not get PID for " << IceStatusReader::GetApplicationId(app) + "Server";
331  app->setPid(-1);
332  }
333  }
334  }
335  }
336  .detach();
337 
338 }
339 
340 
341 std::string IceStarter::getStatus(ApplicationInstancePtr application, StatusManager statusManager)
342 {
343  ARMARX_CHECK_EXPRESSION(application);
344  // this async thread is completetly useless?!
345  // //Launch the fetching of the Status in a different Thread
346  // std::cout << "launching status reading in thread " << application->getName() << std::endl;
347  // std::packaged_task<void()> task(std::bind(&IceStatusReader::fetch, &statusReader, application));
348  // std::cout << "fetching future" << std::endl;
349  // std::future<void> result = task.get_future();
350  // std::cout << "got future" << std::endl;
351 
352  // std::thread t(std::move(task));
353  // t.detach();
354  // std::cout << "thread detached" << std::endl;
355 
356  //Return the fetched Status
357  return statusReader.getStatus(application);
358 
359 }
360 
361 
363 {
364  std::vector<std::string> appNames = admin->getAllApplicationNames();
365  //Check if there is an deployed application
366  if (std::find(appNames.begin(), appNames.end(), application->getScenario()->getName()) != appNames.end())
367  {
368  IceGrid::ApplicationInfo info = admin->getApplicationInfo(application->getScenario()->getName());
369  IceGrid::ServerInstanceDescriptorSeq serverInstances = info.descriptor.nodes[application->getEffectiveNodeName()].serverInstances;
370  if (std::find_if(serverInstances.begin(), serverInstances.end(), [application](const IceGrid::ServerInstanceDescriptor & d)
371  {
372  return d.parameterValues.at("component") == application->getName()
373  && d.parameterValues.at("componentId") == application->getInstanceName();
374  }) != serverInstances.end())
375  {
376  return true;
377  }
378  else
379  {
380  return false;
381  }
382  }
383  else
384  {
385  return false;
386  }
387 }
388 
390 {
391  std::vector<std::string> appNames = admin->getAllApplicationNames();
392  //Check if there is an deployed application
393  if (std::find(appNames.begin(), appNames.end(), scenario->getName()) != appNames.end())
394  {
395  return true;
396  }
397  else
398  {
399  return false;
400  }
401 }
402 
ScenarioManager::Data_Structure::ApplicationInstancePtr
std::shared_ptr< ApplicationInstance > ApplicationInstancePtr
Definition: ApplicationInstance.h:33
ScenarioManager::Data_Structure::ScenarioPtr
std::shared_ptr< Scenario > ScenarioPtr
Definition: Scenario.h:36
OnScopeExit.h
ScenarioManager::Exec::IceStatusReader::getStatus
virtual std::string getStatus(Data_Structure::ApplicationInstancePtr application)
Definition: IceStatusReader.cpp:14
ScenarioManager::Exec::IceStarter::IceStarter
IceStarter(const IceGrid::AdminPrx admin)
Definition: IceStarter.cpp:37
IceStarter.h
ScenarioManager::Exec::ApplicationStarter::commandLineParameters
std::string commandLineParameters
Definition: ApplicationStarter.h:67
ARMARX_ON_SCOPE_EXIT
#define ARMARX_ON_SCOPE_EXIT
Executes given code when the enclosing scope is left.
Definition: OnScopeExit.h:112
ApplicationInstancePtr
std::shared_ptr< ScenarioManager::Data_Structure::ApplicationInstance > ApplicationInstancePtr
Definition: StopStrategy.h:7
ScenarioManager::Exec::IceStarter::startScenario
virtual void startScenario(Data_Structure::ScenarioPtr scenario, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false) override
Definition: IceStarter.cpp:225
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:209
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
ScenarioManager::StatusManager
Definition: StatusManager.h:7
ScenarioManager::Data_Structure::Local
@ Local
Definition: Scenario.h:53
IceGridXmlGenerator.h
ScenarioManager::Exec::IceStarter::isScenarioDeployed
virtual bool isScenarioDeployed(Data_Structure::ScenarioPtr scenario) override
Definition: IceStarter.cpp:389
ExpressionException.h
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
ScenarioManager
Definition: Application.cpp:166
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
ScenarioManager::Data_Structure::Remote
@ Remote
Definition: Scenario.h:54
ScenarioManager::Exec::IceStarter::deployScenario
virtual void deployScenario(Data_Structure::ScenarioPtr scenario, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false) override
Definition: IceStarter.cpp:160
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:195
ScenarioManager::StatusManager::setIceScenario
void setIceScenario(Data_Structure::ScenarioPtr scenario, bool state)
Definition: StatusManager.cpp:97
ScenarioManager::Exec::IceStarter::deployApplication
virtual void deployApplication(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false) override
Definition: IceStarter.cpp:103
ScenarioManager::Exec::IceStatusReader::GetApplicationId
static std::string GetApplicationId(const ApplicationInstancePtr &application)
Definition: IceStatusReader.cpp:89
ScenarioManager::Exec::IceStarter::isApplicationDeployed
virtual bool isApplicationDeployed(Data_Structure::ApplicationInstancePtr application) override
Definition: IceStarter.cpp:362
ScenarioManager::Exec::IceStarter::startApplication
virtual void startApplication(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false) override
Starts an application.
Definition: IceStarter.cpp:41
ScenarioManager::Exec::IceStarter::getStatus
virtual std::string getStatus(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager) override
Returns the status of an application.
Definition: IceStarter.cpp:341