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