ScenarioCli.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 Cedric Seehausen (usdnr at kit dot edu)
20  * @date 2016
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 
26 #include "ScenarioCli.h"
27 
28 #include "ScenarioCliOptions.h"
30 
41 #include <iostream>
42 #include <filesystem>
43 
44 namespace armarx
45 {
47  {
48 
49  }
50 
52  Ice::PropertiesPtr properties)
53  {
54  //this->registry = registry;
55  }
56 
57  int ScenarioCli::exec(const ArmarXManagerPtr& armarXManager)
58  {
59  if (options.applicationName.empty())
60  {
61  startScenario(options.command, localScen, options.print, armarXManager->getIceManager()->getIceGridSession()->getAdmin(), options.parameters);
62  }
63  else
64  {
65  ApplicationInstancePtr app = localScen->getApplicationByName(options.applicationName);
66  if (app.get() != nullptr)
67  {
68  startApplication(options.command, app, options.print, armarXManager->getIceManager()->getIceGridSession()->getAdmin(), options.parameters);
69  }
70  else
71  {
72  options.error = true;
73  optionsManager.showHelp(options, "Could not find application '" + options.applicationName + "' in scenario '" + localScen->getName() + "'");
74  return 0;
75  }
76  }
77 
78  if (!options.print)
79  {
80  std::cout << "Finished" << std::endl;
81  }
82 
83  if (!options.wait || options.print)
84  {
85  armarXManager->shutdown();
86  }
87 
88  armarXManager->waitForShutdown();
89  return 0;
90  }
91 
92  int ScenarioCli::run(int argc, char* argv[])
93  {
94  using namespace ScenarioManager;
95  using namespace Parser;
96  using namespace Data_Structure;
97  try
98  {
99  setIceProperties(IceProperties::create(ApplicationOptions::mergeProperties(communicator()->getProperties()->clone(), argc, argv)));
100  }
101  catch (...)
102  {
103  std::cout << "Failed to parse arguments. exiting";
104  return -1;
105  }
106  ScenarioManagerCliOptions cliOptionsManager;
107  options = cliOptionsManager.parseCmdOptions(argc, argv);
108 
109 
110  if (!options.parameters.empty())
111  {
112  std::cout << "Additional command line parameters are: " << options.parameters << std::endl;
113  }
114 
115  //Handle help | error of parsing
116  if (options.showHelp || options.error)
117  {
118  if (options.error)
119  {
120  cliOptionsManager.showHelp(options, "Could not parse input parameters");
121  return 0;
122  }
123  cliOptionsManager.showHelp(options);
124  return 0;
125  }
126 
127  //capture edge cases
128  if (options.print && options.command != "start")
129  {
130  cliOptionsManager.showHelp(options, "Print is only a valid option for the start command");
131  return 0;
132  }
133  else if (options.wait && (options.command == "list" || options.command == "status"))
134  {
135  cliOptionsManager.showHelp(options, "Wait is not valid for the list or status command");
136  return 0;
137  }
138 
139  PackageBuilder builder;
140 
141  //Handle list
142  if (options.command.compare("list") == 0)
143  {
144  std::cout << "Listing all Scenarios out of default Packages" << std::endl;
145  for (auto package : getArmarXPackageNames())
146  {
147  std::cout << "Scenarios in " << package << ":" << std::endl;
148  PackagePtr currentPackage = builder.parsePackage(package);
149  if (currentPackage.get() == nullptr)
150  {
151  std::cout << "Package " << package << " is listed in default packages, but could not be found" << std::endl << std::endl << std::endl;
152  continue;
153  }
154  for (auto scenario : * (currentPackage->getScenarios()))
155  {
156  std::cout << scenario->getName() << std::endl;
157  }
158  std::cout << std::endl << std::endl;
159  }
160  return 0;
161  }
162 
163  std::string packageName = options.packageName;
164  std::string scenarioName = ScenarioManagerCliOptions::GetScenarioNameByCommandLineInput(options);
165 
166  if (options.packageName.empty())
167  {
168  if (std::filesystem::is_regular_file(std::filesystem::path(options.scxPath))
169  || std::filesystem::is_directory(std::filesystem::path(options.scxPath)))
170  {
171  XMLScenarioParser parser;
172  std::string filePackageName;
173  if (std::filesystem::is_regular_file(std::filesystem::path(options.scxPath)))
174  {
175  filePackageName = parser.getPackageNameFromScx(options.scxPath);
176  }
177  else
178  {
179  filePackageName = parser.getPackageNameFromScx((std::filesystem::path(options.scxPath) / std::filesystem::path(scenarioName + ".scx")).string());
180  }
181 
182  if (filePackageName != "")
183  {
184  packageName = filePackageName;
185  }
186  else
187  {
188  packageName = packageChoosingDialog(scenarioName);
189  if (packageName.empty())
190  {
191  options.error = true;
192  cliOptionsManager.showHelp(options, "Could not find any package for " + options.scxPath + ". Please add a PackageName or Add the PackageName to your default config.");
193  return 0;
194  }
195  }
196  }
197  else
198  {
199  packageName = packageChoosingDialog(scenarioName);
200  if (packageName.empty())
201  {
202  options.error = true;
203  cliOptionsManager.showHelp(options, "Could not find any package for " + options.scxPath + ". Please add a PackageName or Add the PackageName to your default config.");
204  return 0;
205  }
206  }
207  }
208 
209 
210  if (scenarioName.empty())
211  {
212  options.error = true;
213  cliOptionsManager.showHelp(options, "Could not find Scenario " + options.scxPath + " in Package " + packageName);
214  return 0;
215  }
216 
217  PackagePtr package;
218  ScenarioPtr scenario;
219 
220  CMakePackageFinder finder(packageName);
221  if (!finder.packageFound())
222  {
223  options.error = true;
224  cliOptionsManager.showHelp(options, "CMakePackageFinder could not find package '" + packageName + "'");
225  return 0;
226  }
227 
228  XMLScenarioParser parser;
229  std::vector<std::string> scenarios = parser.getScenariosFromFolder(finder.getScenariosDir());
230 
231  for (auto scen : scenarios)
232  {
233  auto sFolderPos = scen.rfind("/");
234  if ((sFolderPos == std::string::npos && scen == scenarioName)
235  || (sFolderPos != std::string::npos && scen.substr(sFolderPos + 1) == scenarioName))
236  {
237  package = builder.parsePackage(packageName, StringList {scen + "::Package::" + packageName});
238  break;
239  }
240  }
241 
242  if (package.get() == nullptr)
243  {
244  cliOptionsManager.showHelp(options, "Failed to parse package " + packageName);
245  return 0;
246  }
247 
248  scenario = package->getScenarioByName(scenarioName);
249 
250  if (scenario.get() == nullptr)
251  {
252  options.error = true;
253  cliOptionsManager.showHelp(options, "Could not find Scenario " + scenarioName + " in Package " + package->getName());
254  return 0;
255  }
256 
257  if (options.command == "generate")
258  {
260  generator.generateLocalApplication(scenario);
261  generator.generateRemoteApplication(scenario);
262 
263  return 0;
264  }
265 
266  localScen = scenario;
267 
268  const char* n_argv[] = {argv[0], "--ArmarX.RedirectStdout=false"};
269  return armarx::Application::run(2, const_cast<char**>(n_argv));
270  }
271 
272  std::string ScenarioCli::packageChoosingDialog(std::string scenarioName)
273  {
274  using namespace ScenarioManager;
275  using namespace Parser;
276  using namespace Data_Structure;
277  using namespace Exec;
278  StringList packages = PackageBuilder::FilterPackagesForScenario(scenarioName);
279 
280  if (packages.size() == 0)
281  {
282  return "";
283  }
284  else if (packages.size() == 1)
285  {
286  return packages[0];
287  }
288  else if (packages.size() > 1)
289  {
290  size_t answer = -1;
291  while (answer > packages.size())
292  {
293  std::cout << "Found multiple possible packages for this Scenario path, please select: " << std::endl;
294  int number = 1;
295  for (auto package : packages)
296  {
297  std::cout << number << ") " << package << std::endl;
298  number++;
299  }
300  std::cout << "Please enter a number now: " << std::endl;
301 
302  std::string answerString;
303  std::cin >> answerString;
304  try
305  {
306  answer = boost::lexical_cast<size_t>(answerString);
307  }
308  catch (...)
309  {
310  std::cout << "ERROR: Could not convert input to a number - please type in a number between 1 and " << packages.size() << std::endl << std::endl;
311  continue;
312  }
313 
314  if (answer > packages.size() || answer == 0)
315  {
316  answer = -1;
317  continue;
318  }
319  answer -= 1;
320  }
321  return packages[answer];
322  }
323 
324  return "";
325  }
326 
327  void ScenarioCli::startScenario(std::string command, ScenarioManager::Data_Structure::ScenarioPtr scenario, bool printOnly, IceGrid::AdminPrx iceAdmin, const std::string& commandLineParameters)
328  {
329  using namespace ScenarioManager;
330  using namespace Exec;
331  StopStrategyFactory stopStrategyFactory;
332  Executor executor(stopStrategyFactory.getStopStrategy(StopperFactory::getFactory()->getPidStopper()), StarterFactory::getFactory()->getStarter());
333 
334  std::future<void> result;
335 
336  StatusManager manager;
337 
338  //look if the app is startet or not and look for pids
339  for (auto app : *scenario->getApplications())
340  {
341  app->setStatus(executor.getApplicationStatus(app));
342  }
343 
344 
345  if (command == "status")
346  {
347  std::cout << "Status of " << scenario->getName() << " is: ";
348 
350  {
352  }
353  else if (scenario->getStatus() == ScenarioManager::Data_Structure::ApplicationStatus::Inactive)
354  {
356  }
357  else if (scenario->getStatus() == ScenarioManager::Data_Structure::ApplicationStatus::Running)
358  {
360  }
361  else if (scenario->getStatus() == ScenarioManager::Data_Structure::ApplicationStatus::Mixed)
362  {
364  }
365  else
366  {
368  }
369 
370  std::cout << std::endl;
371 
372  for (auto app : *scenario->getApplications())
373  {
374  std::cout << "\t " << app->getName() << " : ";
376  {
378  }
380  {
382  }
384  {
386  }
387  else
388  {
390  }
391 
392  std::cout << std::endl;
393  }
394  return;
395  }
396  else if (command == "periodic_status")
397  {
398  while (true)
399  {
400  std::cout << "Status of " << scenario->getName() << " is: ";
401 
402  if (scenario->getStatus() == "Running")
403  {
404  coloredStdOut("Running", 92);
405  }
406  else if (scenario->getStatus() == "Stopped")
407  {
408  coloredStdOut("Stopped", 31);
409  }
410  else if (scenario->getStatus() == "Mixed")
411  {
412  coloredStdOut("Mixed", 93);
413  }
414  std::cout << std::endl;
415  for (auto app : *scenario->getApplications())
416  {
417  app->setStatus(executor.getApplicationStatus(app));
418  }
419  TimeUtil::SleepMS(1000);
420  }
421  }
422  else if (command == "start")
423  {
424  if (!printOnly)
425  {
426  std::cout << "Starting Scenario ";
427  }
428  result = executor.startScenario(scenario, printOnly, commandLineParameters);
429  }
430  else if (command == "stop")
431  {
432  std::cout << "Stopping Scenario ";
433  result = executor.stopScenario(scenario);
434  }
435  else if (command == "kill")
436  {
437  std::cout << "Killing Scenario ";
438  executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(StopperFactory::getFactory()->getPidStopper(), 500), scenario);
439 
440  result = executor.stopScenario(scenario);
441  }
442  else if (command == "restart")
443  {
444  ARMARX_INFO << "Restarting Scenario";
445  executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(StopperFactory::getFactory()->getPidStopper(), 500), scenario);
446 
447  result = executor.restartScenario(scenario, printOnly);
448  }
449 
450  if (!printOnly)
451  {
452  std::cout << scenario->getName() << std::endl;
453  }
454 
455  result.wait();
456  }
457 
458  void ScenarioCli::startApplication(std::string command, ScenarioManager::Data_Structure::ApplicationInstancePtr app, bool printOnly, IceGrid::AdminPrx iceAdmin, const std::string& commandLineParameters)
459  {
460  using namespace ScenarioManager;
461  using namespace Exec;
462  StopStrategyFactory stopStrategyFactory;
463  Executor executor(stopStrategyFactory.getStopStrategy(StopperFactory::getFactory()->getPidStopper()), StarterFactory::getFactory()->getStarter());
464 
465  std::future<void> result;
466 
467  StatusManager manager;
468 
469  //look for app pid
470  app->setStatus(executor.getApplicationStatus(app));
471 
472  if (command == "status")
473  {
474  std::cout << "Status of " << app->getName() << "is: ";
476  {
478  }
480  {
482  }
484  {
486  }
487  else
488  {
490  }
491  std::cout << std::endl;
492  return;
493  }
494  else if (command == "start")
495  {
496  if (!printOnly)
497  {
498  std::cout << "Starting Application ";
499  }
500 
501  result = executor.startApplication(app, printOnly, commandLineParameters);
502  }
503  else if (command == "stop")
504  {
505  std::cout << "Stopping Application ";
506  result = executor.stopApplication(app);
507  }
508  else if (command == "kill")
509  {
510  std::cout << "Killing Application ";
511  executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(StopperFactory::getFactory()->getByNameStopper(), 0), app->getScenario());
512  result = executor.stopApplication(app);
513  }
514  else if (command == "restart")
515  {
516  std::cout << "Restarting Application ";
517  executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(StopperFactory::getFactory()->getByNameStopper(), 0), app->getScenario());
518  result = executor.restartApplication(app, printOnly);
519  }
520 
521  if (!printOnly)
522  {
523  std::cout << app->getName() << std::endl;
524  }
525  result.wait();
526  }
527 
528  void ScenarioCli::coloredStdOut(std::string message, int colorCode)
529  {
530  std::cout << "\033[" << colorCode << "m" << message << "\033[0m";
531  }
532 }
armarx::CmdOptions::command
std::string command
Definition: ScenarioCliOptions.h:40
armarx::Application::run
int run(int argc, char *argv[]) override
Ice::Application replacement for the main function.
Definition: Application.cpp:363
armarx::ScenarioManagerCliOptions::showHelp
void showHelp(CmdOptions options, std::string errorMessage="")
Definition: ScenarioCliOptions.cpp:140
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
armarx::ApplicationOptions::mergeProperties
Ice::PropertiesPtr mergeProperties(Ice::PropertiesPtr properties, int argc, char *argv[])
Merge command line options into properties.
Definition: ApplicationOptions.cpp:59
ScenarioManager::Generator::IceGridXmlGenerator::generateLocalApplication
void generateLocalApplication(Data_Structure::ScenarioPtr scenario)
Definition: IceGridXmlGenerator.cpp:45
armarx::ScenarioManagerCliOptions::GetScenarioNameByCommandLineInput
static std::string GetScenarioNameByCommandLineInput(CmdOptions string)
Definition: ScenarioCliOptions.cpp:150
StopperFactory.h
ScenarioManager::Data_Structure::ApplicationStatus::Stopped
static const std::string Stopped
Definition: ApplicationInstance.h:47
armarx::ScenarioCli::exec
int exec(const ArmarXManagerPtr &armarXManager) override
Exec method is the main process of the application.
Definition: ScenarioCli.cpp:57
message
message(STATUS "Boost-Library-Dir: " "${Boost_LIBRARY_DIRS}") message(STATUS "Boost-LIBRARIES
Definition: CMakeLists.txt:8
ScenarioManager::Generator::IceGridXmlGenerator::generateRemoteApplication
void generateRemoteApplication(Data_Structure::ScenarioPtr scenario)
Definition: IceGridXmlGenerator.cpp:114
ScenarioManager::Data_Structure::ApplicationStatus::Running
static const std::string Running
Definition: ApplicationInstance.h:48
ApplicationInstancePtr
std::shared_ptr< ScenarioManager::Data_Structure::ApplicationInstance > ApplicationInstancePtr
Definition: StopStrategy.h:7
ApplicationOptions.h
armarx::CmdOptions::print
bool print
Definition: ScenarioCliOptions.h:37
IceInternal::Handle< ::Ice::Properties >
armarx::CmdOptions::parameters
std::string parameters
Definition: ScenarioCliOptions.h:43
PackageBuilder.h
armarx::ScenarioCli::ScenarioCli
ScenarioCli()
Definition: ScenarioCli.cpp:46
ScenarioManager::Data_Structure::PackagePtr
std::shared_ptr< Package > PackagePtr
Definition: Package.h:121
ScenarioCliOptions.h
armarx::IceProperties::create
static Ice::PropertiesPtr create(const Ice::PropertiesPtr &iceProperties=nullptr)
Definition: IceProperties.cpp:32
ScenarioManager::Data_Structure::ApplicationStatus::Inactive
static const std::string Inactive
Definition: ApplicationInstance.h:52
XMLScenarioParser.h
IceGridAdmin.h
ScenarioManager::Data_Structure::ApplicationStatus::Mixed
static const std::string Mixed
Definition: ApplicationInstance.h:50
ScenarioManager::Data_Structure::ApplicationStatus::Unknown
static const std::string Unknown
Definition: ApplicationInstance.h:51
ScenarioManager::StatusManager
Definition: StatusManager.h:7
IceGridXmlGenerator.h
armarx::CmdOptions::error
bool error
Definition: ScenarioCliOptions.h:36
armarx::CmdOptions::wait
bool wait
Definition: ScenarioCliOptions.h:38
armarx::CmdOptions::applicationName
std::string applicationName
Definition: ScenarioCliOptions.h:42
IceStorm::parser
Parser * parser
Definition: Parser.cpp:33
armarx::Application::setIceProperties
void setIceProperties(Ice::PropertiesPtr properties) override
Overrides PropertyUser::setIceProperties() which is called internally.
Definition: Application.cpp:306
armarx::TimeUtil::SleepMS
static void SleepMS(float milliseconds)
Definition: TimeUtil.h:195
TimeUtil.h
ScenarioManager
Definition: Application.cpp:166
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
StopStrategyFactory.h
IceUtil::Handle< ManagedIceObjectRegistryInterface >
armarx::Application::getArmarXPackageNames
std::vector< std::string > getArmarXPackageNames()
getDefaultPackageNames returns the value of the ArmarX.DefaultPackages property It splits the string ...
Definition: Application.cpp:670
ScenarioManager::Generator::IceGridXmlGenerator
Definition: IceGridXmlGenerator.h:37
IceStorm::Parser::error
void error(const char *)
Logging.h
ScenarioCli.h
armarx::ScenarioCli::setup
void setup(const ManagedIceObjectRegistryInterfacePtr &registry, Ice::PropertiesPtr properties) override
Setup method to be implemented by user applications.
Definition: ScenarioCli.cpp:51
ArmarXDataPath.h
StarterFactory.h
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
ScenarioManager::Parser::StringList
std::vector< std::string > StringList
Definition: PackageBuilder.h:34