Kea  1.9.9-git
d_controller.cc
Go to the documentation of this file.
1 // Copyright (C) 2013-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
9 #include <cfgrpt/config_report.h>
10 #include <exceptions/exceptions.h>
11 #include <log/logger.h>
12 #include <log/logger_support.h>
13 #include <process/daemon.h>
14 #include <process/d_log.h>
15 #include <process/d_controller.h>
16 #include <process/config_base.h>
17 #include <kea_version.h>
18 #include <functional>
19 #include <sstream>
20 #include <unistd.h>
21 #include <signal.h>
22 
23 using namespace isc::asiolink;
24 using namespace isc::data;
25 using namespace isc::config;
26 namespace ph = std::placeholders;
27 
28 namespace isc {
29 namespace process {
30 
31 DControllerBasePtr DControllerBase::controller_;
32 
33 // Note that the constructor instantiates the controller's primary IOService.
34 DControllerBase::DControllerBase(const char* app_name, const char* bin_name)
35  : app_name_(app_name), bin_name_(bin_name),
36  verbose_(false), check_only_(false),
37  io_service_(new isc::asiolink::IOService()),
38  io_signal_set_() {
39 }
40 
41 void
43  if (controller_) {
44  // This shouldn't happen, but let's make sure it can't be done.
45  // It represents a programmatic error.
47  "Multiple controller instances attempted.");
48  }
49 
50  controller_ = controller;
51 }
52 
54 DControllerBase::parseFile(const std::string&) {
55  ConstElementPtr elements;
56  return (elements);
57 }
58 
59 int
60 DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
61 
62  // Step 1 is to parse the command line arguments.
63  try {
64  parseArgs(argc, argv);
65  } catch (const InvalidUsage& ex) {
66  usage(ex.what());
67  // rethrow it with an empty message
69  }
70 
71  setProcName(bin_name_);
72 
73  if (isCheckOnly()) {
75  return (EXIT_SUCCESS);
76  }
77 
78  // It is important that we set a default logger name because this name
79  // will be used when the user doesn't provide the logging configuration
80  // in the Kea configuration file.
82 
83  // Logger's default configuration depends on whether we are in the
84  // verbose mode or not. CfgMgr manages the logger configuration so
85  // the verbose mode is set for CfgMgr.
86  Daemon::setVerbose(verbose_);
87 
88  // Do not initialize logger here if we are running unit tests. It would
89  // replace an instance of unit test specific logger.
90  if (!test_mode) {
91  // Now that we know what the mode flags are, we can init logging.
92  Daemon::loggerInit(bin_name_.c_str(), verbose_);
93  }
94 
95  try {
97  } catch (const std::exception& ex) {
99  .arg(app_name_).arg(ex.what());
100  isc_throw (LaunchError, "Launch Failed: " << ex.what());
101  }
102 
103  try {
104  createPIDFile();
105  } catch (const DaemonPIDExists& ex) {
107  .arg(bin_name_).arg(ex.what());
108  isc_throw (LaunchError, "Launch Failed: " << ex.what());
109  } catch (const std::exception& ex) {
111  .arg(app_name_).arg(ex.what());
112  isc_throw (LaunchError, "Launch failed: " << ex.what());
113  }
114 
115  // Log the starting of the service.
117  .arg(app_name_)
118  .arg(getpid())
119  .arg(VERSION)
120  .arg(PACKAGE_VERSION_TYPE);
121  // When it is not a stable version dissuade use in production.
122  if (std::string(PACKAGE_VERSION_TYPE) == "development") {
124  }
125  try {
126  // Step 2 is to create and initialize the application process object.
127  initProcess();
128  } catch (const std::exception& ex) {
130  .arg(app_name_).arg(ex.what());
132  "Application Process initialization failed: " << ex.what());
133  }
134 
136  .arg(app_name_);
137 
138  // Step 3 is to load configuration from file.
139  int rcode;
140  ConstElementPtr comment = parseAnswer(rcode, configFromFile());
141  if (rcode != 0) {
143  .arg(app_name_).arg(comment->stringValue());
144  isc_throw (ProcessInitError, "Could Not load configuration file: "
145  << comment->stringValue());
146  }
147 
148  // Note that the controller was started.
149  start_ = boost::posix_time::second_clock::universal_time();
150 
151  // Everything is clear for launch, so start the application's
152  // event loop.
153  try {
154  // Now that we have a process, we can set up signal handling.
156  runProcess();
157  } catch (const std::exception& ex) {
159  .arg(app_name_).arg(ex.what());
161  "Application process event loop failed: " << ex.what());
162  }
163 
164  // All done, so bail out.
166  .arg(app_name_).arg(getpid()).arg(VERSION);
167 
168  return (getExitValue());
169 }
170 
171 void
173  try {
174  // We need to initialize logging, in case any error
175  // messages are to be printed.
176  // This is just a test, so we don't care about lockfile.
177  setenv("KEA_LOCKFILE_DIR", "none", 0);
178  Daemon::setDefaultLoggerName(bin_name_);
179  Daemon::setVerbose(verbose_);
180  Daemon::loggerInit(bin_name_.c_str(), verbose_);
181 
182  // Check the syntax first.
183  std::string config_file = getConfigFile();
184  if (config_file.empty()) {
185  // Basic sanity check: file name must not be empty.
186  isc_throw(InvalidUsage, "JSON configuration file not specified");
187  }
188  ConstElementPtr whole_config = parseFile(config_file);
189  if (!whole_config) {
190  // No fallback to fromJSONFile
191  isc_throw(InvalidUsage, "No configuration found");
192  }
193  if (verbose_) {
194  std::cerr << "Syntax check OK" << std::endl;
195  }
196 
197  // Check the logic next.
198  ConstElementPtr module_config;
199  module_config = whole_config->get(getAppName());
200  if (!module_config) {
201  isc_throw(InvalidUsage, "Config file " << config_file <<
202  " does not include '" << getAppName() << "' entry");
203  }
204  if (module_config->getType() != Element::map) {
205  isc_throw(InvalidUsage, "Config file " << config_file <<
206  " includes not map '" << getAppName() << "' entry");
207  }
208 
209  // Handle other (i.e. not application name) objects.
210  std::string errmsg = handleOtherObjects(whole_config);
211  if (!errmsg.empty()) {
212  isc_throw(InvalidUsage, "Config file " << config_file << errmsg);
213  }
214 
215  // Get an application process object.
216  initProcess();
217 
218  ConstElementPtr answer = checkConfig(module_config);
219  int rcode = 0;
220  answer = parseAnswer(rcode, answer);
221  if (rcode != 0) {
222  isc_throw(InvalidUsage, "Error encountered: "
223  << answer->stringValue());
224  }
225  } catch (const VersionMessage&) {
226  throw;
227  } catch (const InvalidUsage&) {
228  throw;
229  } catch (const std::exception& ex) {
230  isc_throw(InvalidUsage, "Syntax check failed with: " << ex.what());
231  }
232  return;
233 }
234 
235 void
236 DControllerBase::parseArgs(int argc, char* argv[]) {
237 
238  if (argc == 1) {
239  isc_throw(InvalidUsage, "");
240  }
241 
242  // Iterate over the given command line options. If its a stock option
243  // ("c" or "d") handle it here. If its a valid custom option, then
244  // invoke customOption.
245  int ch;
246  opterr = 0;
247  optind = 1;
248  std::string opts("dvVWc:t:" + getCustomOpts());
249  while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
250  switch (ch) {
251  case 'd':
252  // Enables verbose logging.
253  verbose_ = true;
254  break;
255 
256  case 'v':
257  // gather Kea version and throw so main() can catch and return
258  // rather than calling exit() here which disrupts gtest.
260  break;
261 
262  case 'V':
263  // gather Kea version and throw so main() can catch and return
264  // rather than calling exit() here which disrupts gtest.
266  break;
267 
268  case 'W':
269  // gather Kea config report and throw so main() can catch and
270  // return rather than calling exit() here which disrupts gtest.
272  break;
273 
274  case 'c':
275  case 't':
276  // config file name
277  if (optarg == NULL) {
278  isc_throw(InvalidUsage, "configuration file name missing");
279  }
280 
281  setConfigFile(optarg);
282 
283  if (ch == 't') {
284  check_only_ = true;
285  }
286  break;
287 
288  case '?': {
289  // We hit an invalid option.
290  isc_throw(InvalidUsage, "unsupported option: ["
291  << static_cast<char>(optopt) << "] "
292  << (!optarg ? "" : optarg));
293 
294  break;
295  }
296 
297  default:
298  // We hit a valid custom option
299  if (!customOption(ch, optarg)) {
300  // This would be a programmatic error.
301  isc_throw(InvalidUsage, " Option listed but implemented?: ["
302  << static_cast<char>(ch) << "] "
303  << (!optarg ? "" : optarg));
304  }
305  break;
306  }
307  }
308 
309  // There was too much information on the command line.
310  if (argc > optind) {
311  isc_throw(InvalidUsage, "extraneous command line information");
312  }
313 }
314 
315 bool
316 DControllerBase::customOption(int /* option */, char* /*optarg*/) {
317  // Default implementation returns false.
318  return (false);
319 }
320 
321 void
324  .arg(app_name_);
325 
326  // Invoke virtual method to instantiate the application process.
327  try {
328  process_.reset(createProcess());
329  } catch (const std::exception& ex) {
330  isc_throw(DControllerBaseError, std::string("createProcess failed: ")
331  + ex.what());
332  }
333 
334  // This is pretty unlikely, but will test for it just to be safe..
335  if (!process_) {
336  isc_throw(DControllerBaseError, "createProcess returned NULL");
337  }
338 
339  // Invoke application's init method (Note this call should throw
340  // DProcessBaseError if it fails).
341  process_->init();
342 }
343 
346  // Rollback any previous staging configuration. For D2, only a
347  // logger configuration is used here.
348  // We're not using cfgmgr to store logging configuration anymore.
349  // isc::dhcp::CfgMgr::instance().rollback();
350 
351  // Will hold configuration.
352  ConstElementPtr module_config;
353  // Will receive configuration result.
354  ConstElementPtr answer;
355  try {
356  std::string config_file = getConfigFile();
357  if (config_file.empty()) {
358  // Basic sanity check: file name must not be empty.
359  isc_throw(BadValue, "JSON configuration file not specified. Please "
360  "use -c command line option.");
361  }
362 
363  // If parseFile returns an empty pointer, then pass the file onto the
364  // original JSON parser.
365  ConstElementPtr whole_config = parseFile(config_file);
366  if (!whole_config) {
367  // Read contents of the file and parse it as JSON
368  whole_config = Element::fromJSONFile(config_file, true);
369  }
370 
371  // Extract derivation-specific portion of the configuration.
372  module_config = whole_config->get(getAppName());
373  if (!module_config) {
374  isc_throw(BadValue, "Config file " << config_file <<
375  " does not include '" <<
376  getAppName() << "' entry.");
377  }
378  if (module_config->getType() != Element::map) {
379  isc_throw(InvalidUsage, "Config file " << config_file <<
380  " includes not map '" << getAppName() << "' entry");
381  }
382 
383  // Handle other (i.e. not application name) objects.
384  std::string errmsg = handleOtherObjects(whole_config);
385  if (!errmsg.empty()) {
386  isc_throw(InvalidUsage, "Config file " << config_file << errmsg);
387  }
388 
389  // Let's configure logging before applying the configuration,
390  // so we can log things during configuration process.
391 
392  // Temporary storage for logging configuration
393  ConfigPtr storage(new ConfigBase());
394 
395  // Configure logging to the temporary storage.
396  Daemon::configureLogger(module_config, storage);
397 
398  // Let's apply the new logging. We do it early, so we'll be able
399  // to print out what exactly is wrong with the new config in
400  // case of problems.
401  storage->applyLoggingCfg();
402 
403  answer = updateConfig(module_config);
404  // In all cases the right logging configuration is in the context.
405  process_->getCfgMgr()->getContext()->applyLoggingCfg();
406  } catch (const std::exception& ex) {
407  // Rollback logging configuration.
408  process_->getCfgMgr()->getContext()->applyLoggingCfg();
409 
410  // build an error result
411  ConstElementPtr error = createAnswer(COMMAND_ERROR,
412  std::string("Configuration parsing failed: ") + ex.what());
413  return (error);
414  }
415 
416  return (answer);
417 }
418 
419 void
422  .arg(app_name_);
423  if (!process_) {
424  // This should not be possible.
425  isc_throw(DControllerBaseError, "Process not initialized");
426  }
427 
428  // Invoke the application process's run method. This may throw
429  // DProcessBaseError
430  process_->run();
431 }
432 
433 // Instance method for handling new config
436  return (process_->configure(new_config, false));
437 }
438 
439 // Instance method for checking new config
442  return (process_->configure(new_config, true));
443 }
444 
447  ConstElementPtr /*args*/) {
448  ConstElementPtr config = process_->getCfgMgr()->getContext()->toElement();
449 
450  return (createAnswer(COMMAND_SUCCESS, config));
451 }
452 
455  ConstElementPtr args) {
456  std::string filename;
457 
458  if (args) {
459  if (args->getType() != Element::map) {
460  return (createAnswer(COMMAND_ERROR, "Argument must be a map"));
461  }
462  ConstElementPtr filename_param = args->get("filename");
463  if (filename_param) {
464  if (filename_param->getType() != Element::string) {
465  return (createAnswer(COMMAND_ERROR,
466  "passed parameter 'filename' "
467  "is not a string"));
468  }
469  filename = filename_param->stringValue();
470  }
471  }
472 
473  if (filename.empty()) {
474  // filename parameter was not specified, so let's use
475  // whatever we remember
476  filename = getConfigFile();
477  if (filename.empty()) {
478  return (createAnswer(COMMAND_ERROR,
479  "Unable to determine filename."
480  "Please specify filename explicitly."));
481  }
482  }
483 
484 
485  // Ok, it's time to write the file.
486  size_t size = 0;
487  ElementPtr cfg = process_->getCfgMgr()->getContext()->toElement();
488 
489  try {
490  size = writeConfigFile(filename, cfg);
491  } catch (const isc::Exception& ex) {
492  return (createAnswer(COMMAND_ERROR,
493  std::string("Error during write-config:")
494  + ex.what()));
495  }
496  if (size == 0) {
497  return (createAnswer(COMMAND_ERROR,
498  "Error writing configuration to " + filename));
499  }
500 
501  // Ok, it's time to return the successful response.
502  ElementPtr params = Element::createMap();
503  params->set("size", Element::create(static_cast<long long>(size)));
504  params->set("filename", Element::create(filename));
505 
506  return (createAnswer(CONTROL_RESULT_SUCCESS, "Configuration written to "
507  + filename + " successful", params));
508 }
509 
510 std::string
512  // Check obsolete or unknown (aka unsupported) objects.
513  const std::string& app_name = getAppName();
514  std::string errmsg;
515  for (auto obj : args->mapValue()) {
516  const std::string& obj_name = obj.first;
517  if (obj_name == app_name) {
518  continue;
519  }
521  .arg("'" + obj_name + "', defining anything in global level besides '"
522  + app_name + "' is no longer supported.");
523  if (errmsg.empty()) {
524  errmsg = " contains unsupported '" + obj_name + "' parameter";
525  } else {
526  errmsg += " (and '" + obj_name + "')";
527  }
528  }
529  return (errmsg);
530 }
531 
534  const int status_code = COMMAND_ERROR; // 1 indicates an error
535  ConstElementPtr module_config;
536  std::string app_name = getAppName();
537  std::string message;
538 
539  // Command arguments are expected to be:
540  // { "Module": { ... } }
541  if (!args) {
542  message = "Missing mandatory 'arguments' parameter.";
543  } else {
544  module_config = args->get(app_name);
545  if (!module_config) {
546  message = "Missing mandatory '" + app_name + "' parameter.";
547  } else if (module_config->getType() != Element::map) {
548  message = "'" + app_name + "' parameter expected to be a map.";
549  }
550  }
551 
552  if (message.empty()) {
553  // Handle other (i.e. not application name) objects.
554  std::string errmsg = handleOtherObjects(args);
555  if (!errmsg.empty()) {
556  message = "'arguments' parameter" + errmsg;
557  }
558  }
559 
560  if (!message.empty()) {
561  // Something is amiss with arguments, return a failure response.
562  ConstElementPtr result = isc::config::createAnswer(status_code,
563  message);
564  return (result);
565  }
566 
567 
568  // We are starting the configuration process so we should remove any
569  // staging configuration that has been created during previous
570  // configuration attempts.
571  // We're not using cfgmgr to store logging information anymore.
572  // isc::dhcp::CfgMgr::instance().rollback();
573 
574  // Now we check the server proper.
575  return (checkConfig(module_config));
576 }
577 
580  // Add reload in message?
581  return (configFromFile());
582 }
583 
586  const int status_code = COMMAND_ERROR; // 1 indicates an error
587  ConstElementPtr module_config;
588  std::string app_name = getAppName();
589  std::string message;
590 
591  // Command arguments are expected to be:
592  // { "Module": { ... } }
593  if (!args) {
594  message = "Missing mandatory 'arguments' parameter.";
595  } else {
596  module_config = args->get(app_name);
597  if (!module_config) {
598  message = "Missing mandatory '" + app_name + "' parameter.";
599  } else if (module_config->getType() != Element::map) {
600  message = "'" + app_name + "' parameter expected to be a map.";
601  }
602  }
603 
604  if (!message.empty()) {
605  // Something is amiss with arguments, return a failure response.
606  ConstElementPtr result = isc::config::createAnswer(status_code,
607  message);
608  return (result);
609  }
610 
611  try {
612 
613  // Handle other (i.e. not application name) objects.
614  handleOtherObjects(args);
615 
616  // We are starting the configuration process so we should remove any
617  // staging configuration that has been created during previous
618  // configuration attempts.
619  // We're not using cfgmgr to store logging information anymore.
620  // isc::dhcp::CfgMgr::instance().rollback();
621 
622  // Temporary storage for logging configuration
623  ConfigPtr storage(new ConfigBase());
624 
625  // Configure logging to the temporary storage.
626  Daemon::configureLogger(module_config, storage);
627 
628  // Let's apply the new logging. We do it early, so we'll be able
629  // to print out what exactly is wrong with the new config in
630  // case of problems.
631  storage->applyLoggingCfg();
632 
633  ConstElementPtr answer = updateConfig(module_config);
634  int rcode = 0;
635  parseAnswer(rcode, answer);
636  // In all cases the right logging configuration is in the context.
637  process_->getCfgMgr()->getContext()->applyLoggingCfg();
638  return (answer);
639  } catch (const std::exception& ex) {
640  // Rollback logging configuration.
641  process_->getCfgMgr()->getContext()->applyLoggingCfg();
642 
643  // build an error result
644  ConstElementPtr error = createAnswer(COMMAND_ERROR,
645  std::string("Configuration parsing failed: ") + ex.what());
646  return (error);
647  }
648 }
649 
652  const std::string& tag = process_->getCfgMgr()->getContext()->getServerTag();
653  ElementPtr response = Element::createMap();
654  response->set("server-tag", Element::create(tag));
655 
656  return (createAnswer(COMMAND_SUCCESS, response));
657 }
658 
661  ElementPtr status = Element::createMap();
662  status->set("pid", Element::create(static_cast<int>(getpid())));
663 
664  auto now = boost::posix_time::second_clock::universal_time();
665  if (!start_.is_not_a_date_time()) {
666  auto uptime = now - start_;
667  status->set("uptime", Element::create(uptime.total_seconds()));
668  }
669 
670  auto last_commit = process_->getCfgMgr()->getContext()->getLastCommitTime();
671  if (!last_commit.is_not_a_date_time()) {
672  auto reload = now - last_commit;
673  status->set("reload", Element::create(reload.total_seconds()));
674  }
675 
676  return (createAnswer(COMMAND_SUCCESS, status));
677 }
678 
681  ConstElementPtr answer;
682 
683  // For version-get put the extended version in arguments
684  ElementPtr extended = Element::create(getVersion(true));
685  ElementPtr arguments = Element::createMap();
686  arguments->set("extended", extended);
687  answer = createAnswer(COMMAND_SUCCESS, getVersion(false), arguments);
688  return (answer);
689 }
690 
693  return (createAnswer(COMMAND_SUCCESS, isc::detail::getConfigReport()));
694 }
695 
698  // Shutdown is universal. If its not that, then try it as
699  // a custom command supported by the derivation. If that
700  // doesn't pan out either, than send to it the application
701  // as it may be supported there.
702 
703  int exit_value = EXIT_SUCCESS;
704  if (args) {
705  // @todo Should we go ahead and shutdown even if the args are invalid?
706  if (args->getType() != Element::map) {
707  return (createAnswer(CONTROL_RESULT_ERROR, "Argument must be a map"));
708  }
709 
710  ConstElementPtr param = args->get("exit-value");
711  if (param) {
712  if (param->getType() != Element::integer) {
714  "parameter 'exit-value' is not an integer"));
715  }
716 
717  exit_value = param->intValue();
718  }
719  }
720 
721  setExitValue(exit_value);
722  return (shutdownProcess(args));
723 }
724 
727  if (process_) {
728  return (process_->shutdown(args));
729  }
730 
731  // Not really a failure, but this condition is worth noting. In reality
732  // it should be pretty hard to cause this.
733  LOG_WARN(dctl_logger, DCTL_NOT_RUNNING).arg(app_name_);
734  return (createAnswer(COMMAND_SUCCESS, "Process has not been initialized"));
735 }
736 
737 void
740 
741  // Create our signal set.
742  io_signal_set_.reset(new IOSignalSet(io_service_,
743  std::bind(&DControllerBase::
745  this, ph::_1)));
746  // Register for the signals we wish to handle.
747  io_signal_set_->add(SIGHUP);
748  io_signal_set_->add(SIGINT);
749  io_signal_set_->add(SIGTERM);
750 }
751 
752 void
754  switch (signum) {
755  case SIGHUP:
756  {
758  .arg(signum).arg(getConfigFile());
759  int rcode;
760  ConstElementPtr comment = parseAnswer(rcode, configFromFile());
761  if (rcode != 0) {
763  .arg(comment->stringValue());
764  }
765 
766  break;
767  }
768 
769  case SIGINT:
770  case SIGTERM:
771  {
773  DCTL_SHUTDOWN_SIGNAL_RECVD).arg(signum);
774  ElementPtr arg_set;
775  shutdownHandler(SHUT_DOWN_COMMAND, arg_set);
776  break;
777  }
778 
779  default:
781  break;
782  }
783 }
784 
785 void
786 DControllerBase::usage(const std::string & text) {
787  if (text != "") {
788  std::cerr << "Usage error: " << text << std::endl;
789  }
790 
791  std::cerr << "Usage: " << bin_name_ << std::endl
792  << " -v: print version number and exit" << std::endl
793  << " -V: print extended version information and exit"
794  << std::endl
795  << " -W: display the configuration report and exit"
796  << std::endl
797  << " -d: optional, verbose output " << std::endl
798  << " -c <config file name> : mandatory,"
799  << " specify name of configuration file" << std::endl
800  << " -t <config file name> : check the"
801  << " configuration file and exit" << std::endl;
802 
803  // add any derivation specific usage
804  std::cerr << getUsageText() << std::endl;
805 }
806 
808 }
809 
810 // Refer to config_report so it will be embedded in the binary
812 
813 std::string
815  std::stringstream tmp;
816 
817  tmp << VERSION;
818  if (extended) {
819  tmp << std::endl << EXTENDED_VERSION << std::endl;
820  tmp << "linked with:" << std::endl;
821  tmp << isc::log::Logger::getVersion() << std::endl;
822  tmp << getVersionAddendum();
823  }
824 
825  return (tmp.str());
826 }
827 
828 } // end of namespace isc::process
829 
830 } // end of namespace isc
virtual isc::data::ConstElementPtr parseFile(const std::string &file_name)
Parse a given file into Elements.
Definition: d_controller.cc:54
boost::shared_ptr< DControllerBase > DControllerBasePtr
Definition: d_controller.h:78
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
std::string getVersion(bool extended)
returns Kea version on stdout and exit.
isc::data::ConstElementPtr statusGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for status-get command
isc::data::ConstElementPtr configTestHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-test command
isc::data::ConstElementPtr serverTagGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for server-tag-get command
virtual isc::data::ConstElementPtr configFromFile()
Reconfigures the process from a configuration file.
void usage(const std::string &text)
Prints the program usage text to std error.
virtual size_t writeConfigFile(const std::string &config_file, isc::data::ConstElementPtr cfg=isc::data::ConstElementPtr()) const
Writes current configuration to specified file.
Definition: daemon.cc:229
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
const isc::log::MessageID DCTL_INIT_PROCESS
isc::data::ConstElementPtr configReloadHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-reload command
Exception thrown when the application process fails.
Definition: d_controller.h:55
virtual void processSignal(int signum)
Application-level signal processing method.
void parseArgs(int argc, char *argv[])
Processes the command line arguments.
const isc::log::MessageID DCTL_RUN_PROCESS
virtual ~DControllerBase()
Destructor.
const isc::log::MessageID DCTL_STANDALONE
Base class for all configurations.
Definition: config_base.h:33
const isc::log::MessageID DCTL_CFG_FILE_RELOAD_SIGNAL_RECVD
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
isc::log::Logger dctl_logger("dctl")
Defines the logger used within libkea-process library.
Definition: d_log.h:18
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
boost::posix_time::ptime start_
Timestamp of the start of the daemon.
Definition: daemon.h:263
void runProcess()
Invokes the application process's event loop,(DBaseProcess::run).
const isc::log::MessageID DCTL_INIT_PROCESS_FAIL
int getExitValue()
Fetches the exit value.
Definition: daemon.h:220
virtual bool customOption(int option, char *optarg)
Virtual method that provides derivations the opportunity to support additional command line options...
const isc::log::MessageID DCTL_CFG_FILE_RELOAD_ERROR
isc::data::ConstElementPtr shutdownHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for 'shutdown' command
const isc::log::MessageID DCTL_SHUTDOWN_SIGNAL_RECVD
Exception used to convey version info upwards.
Definition: d_controller.h:41
virtual std::string getVersionAddendum()
Fetches text containing additional version specifics.
Definition: d_controller.h:601
static void setDefaultLoggerName(const std::string &logger)
Sets the default logger name.
Definition: daemon.h:215
const isc::log::MessageID DCTL_DEVELOPMENT_VERSION
isc::data::ConstElementPtr shutdownProcess(isc::data::ConstElementPtr args)
Initiates shutdown procedure.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const std::string getCustomOpts() const
Virtual method which returns a string containing the option letters for any custom command line optio...
Definition: d_controller.h:397
const isc::log::MessageID DCTL_ALREADY_RUNNING
const char *const * d_config_report
Exception thrown when the controller encounters an operational error.
Definition: d_controller.h:70
const char *const config_report[]
Definition: config_report.h:15
static void setProcName(const std::string &proc_name)
Sets the process name.
Definition: daemon.cc:135
const isc::log::MessageID DCTL_PROCESS_FAILED
virtual isc::data::ConstElementPtr checkConfig(isc::data::ConstElementPtr new_config)
Instance method invoked by the configuration event handler and which processes the actual configurati...
void setConfigFile(const std::string &config_file)
Sets the configuration file name.
Definition: daemon.cc:110
bool isCheckOnly() const
Supplies whether or not check only mode is enabled.
Definition: d_controller.h:442
std::string handleOtherObjects(isc::data::ConstElementPtr args)
Deals with other (i.e.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
isc::data::ConstElementPtr configWriteHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-write command
void checkConfigOnly()
Check the configuration.
virtual const std::string getUsageText() const
Virtual method which can be used to contribute derivation specific usage text.
Definition: d_controller.h:387
const isc::log::MessageID DCTL_STARTING
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
static void setVerbose(const bool verbose)
Sets or clears verbose mode.
Definition: daemon.cc:79
virtual isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr new_config)
Instance method invoked by the configuration event handler and which processes the actual configurati...
virtual int launch(int argc, char *argv[], const bool test_mode)
Acts as the primary entry point into the controller execution and provides the outermost application ...
Definition: d_controller.cc:60
Exception thrown when the command line is invalid.
Definition: d_controller.h:30
This is a base class for exceptions thrown from the DNS library module.
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
static void setController(const DControllerBasePtr &controller)
Static setter which sets the singleton instance.
Definition: d_controller.cc:42
Defines the logger used by the top-level component of kea-dhcp-ddns.
const isc::log::MessageID DCTL_CONFIG_DEPRECATED
isc::data::ConstElementPtr configGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-get command
static void loggerInit(const char *log_name, bool verbose)
Initializes logger.
Definition: daemon.cc:88
Logging initialization functions.
void setExitValue(int value)
Sets the exit value.
Definition: daemon.h:227
void initProcess()
Instantiates the application process and then initializes it.
const isc::log::MessageID DCTL_NOT_RUNNING
isc::data::ConstElementPtr configSetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-set command
This file contains several functions and constants that are used for handling commands and responses ...
Exception thrown when the controller launch fails.
Definition: d_controller.h:48
std::string getAppName() const
Fetches the name of the application under control.
Definition: d_controller.h:222
std::string getConfigFile() const
Returns config file name.
Definition: daemon.cc:105
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
static std::string getVersion()
Version.
Definition: log/logger.cc:62
std::string getConfigReport()
Definition: cfgrpt.cc:20
#define LOG_FATAL(LOGGER, MESSAGE)
Macro to conveniently test fatal output and log it.
Definition: macros.h:38
const isc::log::MessageID DCTL_SHUTDOWN
isc::data::ConstElementPtr buildReportHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for 'build-report' command
Exception thrown when the PID file points to a live PID.
Definition: daemon.h:25
Exception thrown when the application process encounters an operation in its event loop (i...
Definition: d_controller.h:63
void initSignalHandling()
Initializes signal handling.
const isc::log::MessageID DCTL_CONFIG_FILE_LOAD_FAIL
void createPIDFile(int pid=0)
Creates the PID file.
Definition: daemon.cc:203
Application Controller.
Definition: d_controller.h:104
void checkConfigFile() const
Checks the configuration file name.
Definition: daemon.cc:115
const int DBGLVL_START_SHUT
This is given a value of 0 as that is the level selected if debugging is enabled without giving a lev...
Definition: log_dbglevels.h:50
const isc::log::MessageID DCTL_PID_FILE_ERROR
virtual DProcessBase * createProcess()=0
Abstract method that is responsible for instantiating the application process object.
isc::data::ConstElementPtr versionGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for version-get command
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition: config_base.h:176
static void configureLogger(const isc::data::ConstElementPtr &log_config, const isc::process::ConfigPtr &storage)
Configures logger.
Definition: daemon.cc:66
const isc::log::MessageID DCTL_UNSUPPORTED_SIGNAL