Kea  1.5.0
d_controller.cc
Go to the documentation of this file.
1 // Copyright (C) 2013-2018 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 <boost/bind.hpp>
19 #include <sstream>
20 #include <unistd.h>
21 
22 using namespace isc::data;
23 using namespace isc::config;
24 
25 namespace isc {
26 namespace process {
27 
28 DControllerBasePtr DControllerBase::controller_;
29 
30 // Note that the constructor instantiates the controller's primary IOService.
31 DControllerBase::DControllerBase(const char* app_name, const char* bin_name)
32  : app_name_(app_name), bin_name_(bin_name),
33  verbose_(false), check_only_(false),
34  io_service_(new isc::asiolink::IOService()),
35  io_signal_queue_() {
36 }
37 
38 void
40  if (controller_) {
41  // This shouldn't happen, but let's make sure it can't be done.
42  // It represents a programmatic error.
44  "Multiple controller instances attempted.");
45  }
46 
47  controller_ = controller;
48 }
49 
51 DControllerBase::parseFile(const std::string&) {
52  ConstElementPtr elements;
53  return (elements);
54 }
55 
56 void
57 DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
58 
59  // Step 1 is to parse the command line arguments.
60  try {
61  parseArgs(argc, argv);
62  } catch (const InvalidUsage& ex) {
63  usage(ex.what());
64  // rethrow it with an empty message
66  }
67 
68  setProcName(bin_name_);
69 
70  if (isCheckOnly()) {
72  return;
73  }
74 
75  // It is important that we set a default logger name because this name
76  // will be used when the user doesn't provide the logging configuration
77  // in the Kea configuration file.
79 
80  // Logger's default configuration depends on whether we are in the
81  // verbose mode or not. CfgMgr manages the logger configuration so
82  // the verbose mode is set for CfgMgr.
83  Daemon::setVerbose(verbose_);
84 
85  // Do not initialize logger here if we are running unit tests. It would
86  // replace an instance of unit test specific logger.
87  if (!test_mode) {
88  // Now that we know what the mode flags are, we can init logging.
89  Daemon::loggerInit(bin_name_.c_str(), verbose_);
90  }
91 
92  try {
94  } catch (const std::exception& ex) {
95  LOG_FATAL(dctl_logger, DCTL_CONFIG_FILE_LOAD_FAIL)
96  .arg(app_name_).arg(ex.what());
97  isc_throw (LaunchError, "Launch Failed: " << ex.what());
98  }
99 
100  try {
101  createPIDFile();
102  } catch (const DaemonPIDExists& ex) {
103  LOG_FATAL(dctl_logger, DCTL_ALREADY_RUNNING)
104  .arg(bin_name_).arg(ex.what());
105  isc_throw (LaunchError, "Launch Failed: " << ex.what());
106  } catch (const std::exception& ex) {
107  LOG_FATAL(dctl_logger, DCTL_PID_FILE_ERROR)
108  .arg(app_name_).arg(ex.what());
109  isc_throw (LaunchError, "Launch failed: " << ex.what());
110  }
111 
112  // Log the starting of the service.
113  LOG_INFO(dctl_logger, DCTL_STARTING)
114  .arg(app_name_).arg(getpid()).arg(VERSION);
115  try {
116  // Step 2 is to create and initialize the application process object.
117  initProcess();
118  } catch (const std::exception& ex) {
119  LOG_FATAL(dctl_logger, DCTL_INIT_PROCESS_FAIL)
120  .arg(app_name_).arg(ex.what());
122  "Application Process initialization failed: " << ex.what());
123  }
124 
126  .arg(app_name_);
127 
128  // Step 3 is to load configuration from file.
129  int rcode;
130  ConstElementPtr comment = parseAnswer(rcode, configFromFile());
131  if (rcode != 0) {
132  LOG_FATAL(dctl_logger, DCTL_CONFIG_FILE_LOAD_FAIL)
133  .arg(app_name_).arg(comment->stringValue());
134  isc_throw (ProcessInitError, "Could Not load configuration file: "
135  << comment->stringValue());
136  }
137 
138  // Everything is clear for launch, so start the application's
139  // event loop.
140  try {
141  // Now that we have a proces, we can set up signal handling.
143  runProcess();
144  } catch (const std::exception& ex) {
145  LOG_FATAL(dctl_logger, DCTL_PROCESS_FAILED)
146  .arg(app_name_).arg(ex.what());
148  "Application process event loop failed: " << ex.what());
149  }
150 
151  // All done, so bail out.
152  LOG_INFO(dctl_logger, DCTL_SHUTDOWN)
153  .arg(app_name_).arg(getpid()).arg(VERSION);
154 }
155 
156 void
158  try {
159  // We need to initialize logging, in case any error
160  // messages are to be printed.
161  // This is just a test, so we don't care about lockfile.
162  setenv("KEA_LOCKFILE_DIR", "none", 0);
163  Daemon::setDefaultLoggerName(bin_name_);
164  Daemon::setVerbose(verbose_);
165  Daemon::loggerInit(bin_name_.c_str(), verbose_);
166 
167  // Check the syntax first.
168  std::string config_file = getConfigFile();
169  if (config_file.empty()) {
170  // Basic sanity check: file name must not be empty.
171  isc_throw(InvalidUsage, "JSON configuration file not specified");
172  }
173  ConstElementPtr whole_config = parseFile(config_file);
174  if (!whole_config) {
175  // No fallback to fromJSONFile
176  isc_throw(InvalidUsage, "No configuration found");
177  }
178  if (verbose_) {
179  std::cerr << "Syntax check OK" << std::endl;
180  }
181 
182  // Check the logic next.
183  ConstElementPtr module_config;
184  module_config = whole_config->get(getAppName());
185  if (!module_config) {
186  isc_throw(InvalidUsage, "Config file " << config_file <<
187  " does not include '" << getAppName() << "' entry");
188  }
189 
190  // Get an application process object.
191  initProcess();
192 
193  ConstElementPtr answer = checkConfig(module_config);
194  int rcode = 0;
195  answer = parseAnswer(rcode, answer);
196  if (rcode != 0) {
197  isc_throw(InvalidUsage, "Error encountered: "
198  << answer->stringValue());
199  }
200  } catch (const VersionMessage&) {
201  throw;
202  } catch (const InvalidUsage&) {
203  throw;
204  } catch (const std::exception& ex) {
205  isc_throw(InvalidUsage, "Syntax check failed with: " << ex.what());
206  }
207  return;
208 }
209 
210 void
211 DControllerBase::parseArgs(int argc, char* argv[])
212 {
213 
214  if (argc == 1) {
215  isc_throw(InvalidUsage, "");
216  }
217 
218  // Iterate over the given command line options. If its a stock option
219  // ("c" or "d") handle it here. If its a valid custom option, then
220  // invoke customOption.
221  int ch;
222  opterr = 0;
223  optind = 1;
224  std::string opts("dvVWc:t:" + getCustomOpts());
225  while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
226  switch (ch) {
227  case 'd':
228  // Enables verbose logging.
229  verbose_ = true;
230  break;
231 
232  case 'v':
233  // gather Kea version and throw so main() can catch and return
234  // rather than calling exit() here which disrupts gtest.
236  break;
237 
238  case 'V':
239  // gather Kea version and throw so main() can catch and return
240  // rather than calling exit() here which disrupts gtest.
242  break;
243 
244  case 'W':
245  // gather Kea config report and throw so main() can catch and
246  // return rather than calling exit() here which disrupts gtest.
248  break;
249 
250  case 'c':
251  case 't':
252  // config file name
253  if (optarg == NULL) {
254  isc_throw(InvalidUsage, "configuration file name missing");
255  }
256 
257  setConfigFile(optarg);
258 
259  if (ch == 't') {
260  check_only_ = true;
261  }
262  break;
263 
264  case '?': {
265  // We hit an invalid option.
266  isc_throw(InvalidUsage, "unsupported option: ["
267  << static_cast<char>(optopt) << "] "
268  << (!optarg ? "" : optarg));
269 
270  break;
271  }
272 
273  default:
274  // We hit a valid custom option
275  if (!customOption(ch, optarg)) {
276  // This would be a programmatic error.
277  isc_throw(InvalidUsage, " Option listed but implemented?: ["
278  << static_cast<char>(ch) << "] "
279  << (!optarg ? "" : optarg));
280  }
281  break;
282  }
283  }
284 
285  // There was too much information on the command line.
286  if (argc > optind) {
287  isc_throw(InvalidUsage, "extraneous command line information");
288  }
289 }
290 
291 bool
292 DControllerBase::customOption(int /* option */, char* /*optarg*/)
293 {
294  // Default implementation returns false.
295  return (false);
296 }
297 
298 void
301  .arg(app_name_);
302 
303  // Invoke virtual method to instantiate the application process.
304  try {
305  process_.reset(createProcess());
306  } catch (const std::exception& ex) {
307  isc_throw(DControllerBaseError, std::string("createProcess failed: ")
308  + ex.what());
309  }
310 
311  // This is pretty unlikely, but will test for it just to be safe..
312  if (!process_) {
313  isc_throw(DControllerBaseError, "createProcess returned NULL");
314  }
315 
316  // Invoke application's init method (Note this call should throw
317  // DProcessBaseError if it fails).
318  process_->init();
319 }
320 
323  // Rollback any previous staging configuration. For D2, only a
324  // logger configuration is used here.
325  // We're not using cfgmgr to store logging configuration anymore.
326  // isc::dhcp::CfgMgr::instance().rollback();
327 
328  // Will hold configuration.
329  ConstElementPtr module_config;
330  // Will receive configuration result.
331  ConstElementPtr answer;
332  try {
333  std::string config_file = getConfigFile();
334  if (config_file.empty()) {
335  // Basic sanity check: file name must not be empty.
336  isc_throw(BadValue, "JSON configuration file not specified. Please "
337  "use -c command line option.");
338  }
339 
340  // If parseFile returns an empty pointer, then pass the file onto the
341  // original JSON parser.
342  ConstElementPtr whole_config = parseFile(config_file);
343  if (!whole_config) {
344  // Read contents of the file and parse it as JSON
345  whole_config = Element::fromJSONFile(config_file, true);
346  }
347 
348  // Let's configure logging before applying the configuration,
349  // so we can log things during configuration process.
350 
351  // Temporary storage for logging configuration
352  ConfigPtr storage = process_->getCfgMgr()->getContext();
353 
354  // Get 'Logging' element from the config and use it to set up
355  // logging. If there's no such element, we'll just pass NULL.
356  Daemon::configureLogger(whole_config->get("Logging"), storage);
357 
358  // Extract derivation-specific portion of the configuration.
359  module_config = whole_config->get(getAppName());
360  if (!module_config) {
361  isc_throw(BadValue, "Config file " << config_file <<
362  " does not include '" <<
363  getAppName() << "' entry.");
364  }
365 
366  answer = updateConfig(module_config);
367  int rcode = 0;
368  parseAnswer(rcode, answer);
369  if (!rcode) {
370  // Configuration successful, so apply the logging configuration
371  // to log4cplus.
372  storage->applyLoggingCfg();
373  }
374 
375  } catch (const std::exception& ex) {
376  // Rollback logging configuration.
377  // We don't use CfgMgr to store logging information anymore.
378  // isc::dhcp::CfgMgr::instance().rollback();
379 
380  // build an error result
381  ConstElementPtr error = createAnswer(COMMAND_ERROR,
382  std::string("Configuration parsing failed: ") + ex.what());
383  return (error);
384  }
385 
386  return (answer);
387 }
388 
389 void
392  .arg(app_name_);
393  if (!process_) {
394  // This should not be possible.
395  isc_throw(DControllerBaseError, "Process not initialized");
396  }
397 
398  // Invoke the application process's run method. This may throw
399  // DProcessBaseError
400  process_->run();
401 }
402 
403 // Instance method for handling new config
406  return (process_->configure(new_config, false));
407 }
408 
409 // Instance method for checking new config
412  return (process_->configure(new_config, true));
413 }
414 
417  ConstElementPtr /*args*/) {
418  ConstElementPtr config = process_->getCfgMgr()->getContext()->toElement();
419 
420  return (createAnswer(COMMAND_SUCCESS, config));
421 }
422 
425  ConstElementPtr args) {
426  std::string filename;
427 
428  if (args) {
429  if (args->getType() != Element::map) {
430  return (createAnswer(COMMAND_ERROR, "Argument must be a map"));
431  }
432  ConstElementPtr filename_param = args->get("filename");
433  if (filename_param) {
434  if (filename_param->getType() != Element::string) {
435  return (createAnswer(COMMAND_ERROR,
436  "passed parameter 'filename' "
437  "is not a string"));
438  }
439  filename = filename_param->stringValue();
440  }
441  }
442 
443  if (filename.empty()) {
444  // filename parameter was not specified, so let's use
445  // whatever we remember
446  filename = getConfigFile();
447  if (filename.empty()) {
448  return (createAnswer(COMMAND_ERROR,
449  "Unable to determine filename."
450  "Please specify filename explicitly."));
451  }
452  }
453 
454 
455  // Ok, it's time to write the file.
456  size_t size = 0;
457  ElementPtr cfg = process_->getCfgMgr()->getContext()->toElement();
458 
459  // Logging storage is messed up in CA. During its configuration (see
460  // DControllerBase::configFromFile() it calls Daemon::configureLogger()
461  // that stores the logging info in isc::dhcp::CfgMgr::getStagingCfg().
462  // This is later moved to getCurrentCfg() when the configuration is
463  // commited. All control-agent specific configuration is stored in
464  // a structure accessible by process_->getCfgMgr()->getContext(). Note
465  // logging information is not stored there.
466  //
467  // As a result, we need to extract the CA configuration from one
468  // place and logging from another.
469  if (!cfg->contains("Logging")) {
470  ConfigPtr base_cfg = process_->getCfgMgr()->getContext();
471 
472  ConstElementPtr loginfo = base_cfg->toElement();
473  if (loginfo) {
474  // If there was a config stored in dhcp::CfgMgr, try to get Logging info from it.
475  loginfo = loginfo->get("Logging");
476  }
477  if (loginfo) {
478  // If there is some logging information, add it to our config.
479  cfg->set("Logging", loginfo);
480  }
481  }
482 
483  try {
484  size = writeConfigFile(filename, cfg);
485  } catch (const isc::Exception& ex) {
486  return (createAnswer(COMMAND_ERROR,
487  std::string("Error during write-config:")
488  + ex.what()));
489  }
490  if (size == 0) {
491  return (createAnswer(COMMAND_ERROR,
492  "Error writing configuration to " + filename));
493  }
494 
495  // Ok, it's time to return the successful response.
496  ElementPtr params = Element::createMap();
497  params->set("size", Element::create(static_cast<long long>(size)));
498  params->set("filename", Element::create(filename));
499 
500  return (createAnswer(CONTROL_RESULT_SUCCESS, "Configuration written to "
501  + filename + " successful", params));
502 }
503 
506  const int status_code = COMMAND_ERROR; // 1 indicates an error
507  ConstElementPtr module_config;
508  std::string app_name = getAppName();
509  std::string message;
510 
511  // Command arguments are expected to be:
512  // { "Module": { ... }, "Logging": { ... } }
513  // The Logging component is technically optional. If it's not supplied
514  // logging will revert to default logging.
515  if (!args) {
516  message = "Missing mandatory 'arguments' parameter.";
517  } else {
518  module_config = args->get(app_name);
519  if (!module_config) {
520  message = "Missing mandatory '" + app_name + "' parameter.";
521  } else if (module_config->getType() != Element::map) {
522  message = "'" + app_name + "' parameter expected to be a map.";
523  }
524  }
525 
526  if (!message.empty()) {
527  // Something is amiss with arguments, return a failure response.
528  ConstElementPtr result = isc::config::createAnswer(status_code,
529  message);
530  return (result);
531  }
532 
533  // We are starting the configuration process so we should remove any
534  // staging configuration that has been created during previous
535  // configuration attempts.
536  // We're not using cfgmgr to store logging information anymore.
537  // isc::dhcp::CfgMgr::instance().rollback();
538 
539  // Now we check the server proper.
540  return (checkConfig(module_config));
541 }
542 
545  ConstElementPtr answer;
546 
547  // For version-get put the extended version in arguments
548  ElementPtr extended = Element::create(getVersion(true));
549  ElementPtr arguments = Element::createMap();
550  arguments->set("extended", extended);
551  answer = createAnswer(COMMAND_SUCCESS, getVersion(false), arguments);
552  return (answer);
553 }
554 
557  return (createAnswer(COMMAND_SUCCESS, isc::detail::getConfigReport()));
558 }
559 
562  // Shutdown is universal. If its not that, then try it as
563  // a custom command supported by the derivation. If that
564  // doesn't pan out either, than send to it the application
565  // as it may be supported there.
566  return (shutdownProcess(args));
567 }
568 
571  if (process_) {
572  return (process_->shutdown(args));
573  }
574 
575  // Not really a failure, but this condition is worth noting. In reality
576  // it should be pretty hard to cause this.
577  LOG_WARN(dctl_logger, DCTL_NOT_RUNNING).arg(app_name_);
578  return (createAnswer(COMMAND_SUCCESS, "Process has not been initialized"));
579 }
580 
581 void
584 
585  // Create our signal queue.
586  io_signal_queue_.reset(new IOSignalQueue(io_service_));
587 
588  // Install the on-receipt handler
591  this, _1));
592  // Register for the signals we wish to handle.
593  signal_set_.reset(new util::SignalSet(SIGHUP,SIGINT,SIGTERM));
594 }
595 
596 bool
598  // Create a IOSignal to propagate the signal to IOService.
599  io_signal_queue_->pushSignal(signum, boost::bind(&DControllerBase::
601  this, _1));
602  return (true);
603 }
604 
605 void
607  // Pop the signal instance off the queue. This should make us
608  // the only one holding it, so when we leave it should be freed.
609  // (note that popSignal will throw if signal is not found, which
610  // in turn will caught, logged, and swallowed by IOSignal callback
611  // invocation code.)
612  IOSignalPtr io_signal = io_signal_queue_->popSignal(sequence_id);
613 
614  // Now call virtual signal processing method.
615  processSignal(io_signal->getSignum());
616 }
617 
618 void
620  switch (signum) {
621  case SIGHUP:
622  {
623  LOG_INFO(dctl_logger, DCTL_CFG_FILE_RELOAD_SIGNAL_RECVD)
624  .arg(signum).arg(getConfigFile());
625  int rcode;
626  ConstElementPtr comment = parseAnswer(rcode, configFromFile());
627  if (rcode != 0) {
628  LOG_ERROR(dctl_logger, DCTL_CFG_FILE_RELOAD_ERROR)
629  .arg(comment->stringValue());
630  }
631 
632  break;
633  }
634 
635  case SIGINT:
636  case SIGTERM:
637  {
639  DCTL_SHUTDOWN_SIGNAL_RECVD).arg(signum);
640  ElementPtr arg_set;
641  shutdownHandler(SHUT_DOWN_COMMAND, arg_set);
642  break;
643  }
644 
645  default:
646  LOG_WARN(dctl_logger, DCTL_UNSUPPORTED_SIGNAL).arg(signum);
647  break;
648  }
649 }
650 
651 void
652 DControllerBase::usage(const std::string & text)
653 {
654  if (text != "") {
655  std::cerr << "Usage error: " << text << std::endl;
656  }
657 
658  std::cerr << "Usage: " << bin_name_ << std::endl
659  << " -v: print version number and exit" << std::endl
660  << " -V: print extended version information and exit"
661  << std::endl
662  << " -W: display the configuration report and exit"
663  << std::endl
664  << " -d: optional, verbose output " << std::endl
665  << " -c <config file name> : mandatory,"
666  << " specify name of configuration file" << std::endl
667  << " -t <config file name> : check the"
668  << " configuration file and exit" << std::endl;
669 
670  // add any derivation specific usage
671  std::cerr << getUsageText() << std::endl;
672 }
673 
675 }
676 
677 // Refer to config_report so it will be embedded in the binary
679 
680 std::string
682  std::stringstream tmp;
683 
684  tmp << VERSION;
685  if (extended) {
686  tmp << std::endl << EXTENDED_VERSION << std::endl;
687  tmp << "linked with:" << std::endl;
688  tmp << isc::log::Logger::getVersion() << std::endl;
689  tmp << getVersionAddendum();
690  }
691 
692  return (tmp.str());
693 }
694 
695 }; // namespace isc::process
696 
697 }; // namespace isc
bool osSignalHandler(int signum)
Handler for processing OS-level signals.
virtual isc::data::ConstElementPtr parseFile(const std::string &file_name)
Parse a given file into Elements.
Definition: d_controller.cc:51
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 configTestHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-test 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.
static void setOnReceiptHandler(BoolSignalHandler handler)
Registers a handler as the onreceipt signal handler.
Definition: signal_set.cc:307
#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.
Creates and manages IOSignals.
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.
void checkConfigFile() const
Checks the configuration file name.
Definition: daemon.cc:115
virtual ~DControllerBase()
Destructor.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
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
isc::util::SignalSetPtr signal_set_
A pointer to the object installing custom signal handlers.
Definition: daemon.h:238
void runProcess()
Invokes the application process's event loop,(DBaseProcess::run).
virtual bool customOption(int option, char *optarg)
Virtual method that provides derivations the opportunity to support additional command line options.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
isc::data::ConstElementPtr shutdownHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for 'shutdown' command
std::string getConfigFile() const
Returns config file name.
Definition: daemon.cc:105
virtual void 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:57
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:582
static void setDefaultLoggerName(const std::string &logger)
Sets the default logger name.
Definition: daemon.h:216
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...
Exception thrown when the controller encounters an operational error.
Definition: d_controller.h:70
void setProcName(const std::string &proc_name)
Sets the process name.
Definition: daemon.cc:135
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
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.
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...
Represents a collection of signals handled in a customized way.
Definition: signal_set.h:87
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:39
Defines the logger used by the top-level component of kea-dhcp-ddns.
const char *const config_report[]
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 ioSignalHandler(IOSignalId sequence_id)
Handler for processing IOSignals.
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
const char *const * d2_config_report
void initProcess()
Instantiates the application process and then initializes it.
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
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
boost::shared_ptr< IOSignal > IOSignalPtr
Defines a pointer to an IOSignal.
virtual const std::string getUsageText() const
Virtual method which can be used to contribute derivation specific usage text.
Definition: d_controller.h:340
static std::string getVersion()
Version.
Definition: log/logger.cc:49
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
isc::data::ConstElementPtr buildReportHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for 'build-report' command
Exception thrown when a the PID file points to a live PID.
Definition: daemon.h:21
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:350
Exception thrown when the application process encounters an operation in its event loop (i....
Definition: d_controller.h:63
void initSignalHandling()
Initializes signal handling.
void createPIDFile(int pid=0)
Creates the PID file.
Definition: daemon.cc:203
Application Controller.
Definition: d_controller.h:104
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
bool isCheckOnly() const
Supplies whether or not check only mode is enabled.
Definition: d_controller.h:396
virtual DProcessBase * createProcess()=0
Abstract method that is responsible for instantiating the application process object.
std::string getAppName() const
Fetches the name of the application under control.
Definition: d_controller.h:224
isc::data::ConstElementPtr versionGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for version-get command
uint64_t IOSignalId
Defines a unique identifier type for IOSignal.
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the SrvConfig.
Definition: config_base.h:119
static void configureLogger(const isc::data::ConstElementPtr &log_config, const isc::process::ConfigPtr &storage)
Configures logger.
Definition: daemon.cc:66