Kea 1.9.11
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>
11#include <log/logger.h>
12#include <log/logger_support.h>
13#include <process/daemon.h>
14#include <process/d_log.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
23using namespace isc::asiolink;
24using namespace isc::data;
25using namespace isc::config;
26namespace ph = std::placeholders;
27
28namespace isc {
29namespace process {
30
31DControllerBasePtr DControllerBase::controller_;
32
33// Note that the constructor instantiates the controller's primary IOService.
34DControllerBase::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
41void
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
54DControllerBase::parseFile(const std::string&) {
55 ConstElementPtr elements;
56 return (elements);
57}
58
59int
60DControllerBase::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 {
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
171void
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);
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
235void
236DControllerBase::parseArgs(int argc, char* argv[]) {
237
238 if (argc == 1) {
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
315bool
316DControllerBase::customOption(int /* option */, char* /*optarg*/) {
317 // Default implementation returns false.
318 return (false);
319}
320
321void
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
419void
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
510std::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
737void
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
752void
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
785void
786DControllerBase::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
813std::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
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
static std::string getVersion()
Version.
Definition: log/logger.cc:62
Base class for all configurations.
Definition: config_base.h:33
Exception thrown when the controller encounters an operational error.
Definition: d_controller.h:70
Application Controller.
Definition: d_controller.h:104
isc::data::ConstElementPtr configReloadHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-reload command
isc::data::ConstElementPtr buildReportHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for 'build-report' command
void runProcess()
Invokes the application process's event loop,(DBaseProcess::run).
void initProcess()
Instantiates the application process and then initializes it.
virtual std::string getVersionAddendum()
Fetches text containing additional version specifics.
Definition: d_controller.h:601
isc::data::ConstElementPtr statusGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for status-get command
void usage(const std::string &text)
Prints the program usage text to std error.
isc::data::ConstElementPtr shutdownProcess(isc::data::ConstElementPtr args)
Initiates shutdown procedure.
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
virtual void processSignal(int signum)
Application-level signal processing method.
virtual ~DControllerBase()
Destructor.
isc::data::ConstElementPtr configWriteHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-write command
static void setController(const DControllerBasePtr &controller)
Static setter which sets the singleton instance.
Definition: d_controller.cc:42
std::string handleOtherObjects(isc::data::ConstElementPtr args)
Deals with other (i.e.
isc::data::ConstElementPtr versionGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for version-get command
isc::data::ConstElementPtr configSetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-set command
void initSignalHandling()
Initializes signal handling.
virtual const std::string getUsageText() const
Virtual method which can be used to contribute derivation specific usage text.
Definition: d_controller.h:387
virtual isc::data::ConstElementPtr checkConfig(isc::data::ConstElementPtr new_config)
Instance method invoked by the configuration event handler and which processes the actual configurati...
virtual DProcessBase * createProcess()=0
Abstract method that is responsible for instantiating the application process object.
bool isCheckOnly() const
Supplies whether or not check only mode is enabled.
Definition: d_controller.h:442
isc::data::ConstElementPtr configGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-get command
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
void parseArgs(int argc, char *argv[])
Processes the command line arguments.
virtual bool customOption(int option, char *optarg)
Virtual method that provides derivations the opportunity to support additional command line options.
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
std::string getAppName() const
Fetches the name of the application under control.
Definition: d_controller.h:222
virtual isc::data::ConstElementPtr parseFile(const std::string &file_name)
Parse a given file into Elements.
Definition: d_controller.cc:54
virtual isc::data::ConstElementPtr configFromFile()
Reconfigures the process from a configuration file.
std::string getVersion(bool extended)
returns Kea version on stdout and exit.
DControllerBase(const char *app_name, const char *bin_name)
Constructor.
Definition: d_controller.cc:34
virtual isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr new_config)
Instance method invoked by the configuration event handler and which processes the actual configurati...
void checkConfigOnly()
Check the configuration.
isc::data::ConstElementPtr shutdownHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for 'shutdown' command
Exception thrown when the PID file points to a live PID.
Definition: daemon.h:25
std::string getConfigFile() const
Returns config file name.
Definition: daemon.cc:105
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
static void setVerbose(const bool verbose)
Sets or clears verbose mode.
Definition: daemon.cc:79
static void configureLogger(const isc::data::ConstElementPtr &log_config, const isc::process::ConfigPtr &storage)
Configures logger.
Definition: daemon.cc:66
boost::posix_time::ptime start_
Timestamp of the start of the daemon.
Definition: daemon.h:263
static void loggerInit(const char *log_name, bool verbose)
Initializes logger.
Definition: daemon.cc:88
void setExitValue(int value)
Sets the exit value.
Definition: daemon.h:227
void checkConfigFile() const
Checks the configuration file name.
Definition: daemon.cc:115
static void setDefaultLoggerName(const std::string &logger)
Sets the default logger name.
Definition: daemon.h:215
static void setProcName(const std::string &proc_name)
Sets the process name.
Definition: daemon.cc:135
int getExitValue()
Fetches the exit value.
Definition: daemon.h:220
void createPIDFile(int pid=0)
Creates the PID file.
Definition: daemon.cc:203
void setConfigFile(const std::string &config_file)
Sets the configuration file name.
Definition: daemon.cc:110
Exception thrown when the command line is invalid.
Definition: d_controller.h:30
Exception thrown when the controller launch fails.
Definition: d_controller.h:48
Exception thrown when the application process fails.
Definition: d_controller.h:55
Exception thrown when the application process encounters an operation in its event loop (i....
Definition: d_controller.h:63
Exception used to convey version info upwards.
Definition: d_controller.h:41
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Logging initialization functions.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#define LOG_FATAL(LOGGER, MESSAGE)
Macro to conveniently test fatal output and log it.
Definition: macros.h:38
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
@ error
Definition: db_log.h:118
std::string getConfigReport()
Definition: cfgrpt.cc:20
const char *const config_report[]
Definition: config_report.h:15
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
isc::log::Logger dctl_logger("dctl")
Defines the logger used within libkea-process library.
Definition: d_log.h:18
const char *const * d_config_report
const isc::log::MessageID DCTL_DEVELOPMENT_VERSION
const isc::log::MessageID DCTL_SHUTDOWN
const isc::log::MessageID DCTL_CFG_FILE_RELOAD_ERROR
const isc::log::MessageID DCTL_CFG_FILE_RELOAD_SIGNAL_RECVD
const isc::log::MessageID DCTL_RUN_PROCESS
const isc::log::MessageID DCTL_STANDALONE
const isc::log::MessageID DCTL_PID_FILE_ERROR
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition: config_base.h:176
boost::shared_ptr< DControllerBase > DControllerBasePtr
Definition: d_controller.h:78
const isc::log::MessageID DCTL_STARTING
const isc::log::MessageID DCTL_PROCESS_FAILED
const isc::log::MessageID DCTL_SHUTDOWN_SIGNAL_RECVD
const isc::log::MessageID DCTL_INIT_PROCESS_FAIL
const isc::log::MessageID DCTL_ALREADY_RUNNING
const isc::log::MessageID DCTL_NOT_RUNNING
const isc::log::MessageID DCTL_CONFIG_FILE_LOAD_FAIL
const isc::log::MessageID DCTL_CONFIG_DEPRECATED
const isc::log::MessageID DCTL_UNSUPPORTED_SIGNAL
const isc::log::MessageID DCTL_INIT_PROCESS
Defines the logger used by the top-level component of kea-lfc.