Kea 2.5.5
d_controller.cc
Go to the documentation of this file.
1// Copyright (C) 2013-2023 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>
12#include <config/command_mgr.h>
13#include <hooks/hooks_manager.h>
14#include <log/logger.h>
15#include <log/logger_support.h>
16#include <util/encode/hex.h>
17#include <process/daemon.h>
18#include <process/d_log.h>
20#include <process/config_base.h>
21#include <kea_version.h>
22#include <functional>
23#include <sstream>
24#include <string>
25#include <unistd.h>
26#include <signal.h>
27
28using namespace isc::asiolink;
29using namespace isc::config;
30using namespace isc::data;
31using namespace isc::hooks;
32using namespace isc::util;
33namespace ph = std::placeholders;
34
35namespace isc {
36namespace process {
37
38DControllerBasePtr DControllerBase::controller_;
39
40// Note that the constructor instantiates the controller's primary IOService.
41DControllerBase::DControllerBase(const char* app_name, const char* bin_name)
42 : app_name_(app_name), bin_name_(bin_name),
43 verbose_(false), check_only_(false),
44 io_service_(new isc::asiolink::IOService()),
45 io_signal_set_() {
46}
47
48void
50 if (controller_) {
51 // This shouldn't happen, but let's make sure it can't be done.
52 // It represents a programmatic error.
54 "Multiple controller instances attempted.");
55 }
56
57 controller_ = controller;
58}
59
61DControllerBase::parseFile(const std::string&) {
62 ConstElementPtr elements;
63 return (elements);
64}
65
66int
67DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
68
69 // Step 1 is to parse the command line arguments.
70 try {
71 parseArgs(argc, argv);
72 } catch (const InvalidUsage& ex) {
73 usage(ex.what());
74 // rethrow it with an empty message
76 }
77
78 setProcName(bin_name_);
79
80 if (isCheckOnly()) {
82 return (EXIT_SUCCESS);
83 }
84
85 // It is important that we set a default logger name because this name
86 // will be used when the user doesn't provide the logging configuration
87 // in the Kea configuration file.
89
90 // Logger's default configuration depends on whether we are in the
91 // verbose mode or not. CfgMgr manages the logger configuration so
92 // the verbose mode is set for CfgMgr.
93 Daemon::setVerbose(verbose_);
94
95 // Do not initialize logger here if we are running unit tests. It would
96 // replace an instance of unit test specific logger.
97 if (!test_mode) {
98 // Now that we know what the mode flags are, we can init logging.
99 Daemon::loggerInit(bin_name_.c_str(), verbose_);
100 }
101
102 try {
104 } catch (const std::exception& ex) {
106 .arg(app_name_).arg(ex.what());
107 isc_throw (LaunchError, "Launch Failed: " << ex.what());
108 }
109
110 try {
112 } catch (const DaemonPIDExists& ex) {
114 .arg(bin_name_).arg(ex.what());
115 isc_throw (LaunchError, "Launch Failed: " << ex.what());
116 } catch (const std::exception& ex) {
118 .arg(app_name_).arg(ex.what());
119 isc_throw (LaunchError, "Launch failed: " << ex.what());
120 }
121
122 // Log the starting of the service.
124 .arg(app_name_)
125 .arg(getpid())
126 .arg(VERSION)
127 .arg(PACKAGE_VERSION_TYPE);
128 // When it is not a stable version dissuade use in production.
129 if (std::string(PACKAGE_VERSION_TYPE) == "development") {
131 }
132 try {
133 // Step 2 is to create and initialize the application process object.
134 initProcess();
135 } catch (const std::exception& ex) {
137 .arg(app_name_).arg(ex.what());
139 "Application Process initialization failed: " << ex.what());
140 }
141
143 .arg(app_name_);
144
145 // Step 3 is to load configuration from file.
146 int rcode;
147 ConstElementPtr comment = parseAnswer(rcode, configFromFile());
148 if (rcode != 0) {
150 .arg(app_name_).arg(comment->stringValue());
151 isc_throw (ProcessInitError, "Could Not load configuration file: "
152 << comment->stringValue());
153 }
154
155 // Note that the controller was started.
156 start_ = boost::posix_time::second_clock::universal_time();
157
158 // Everything is clear for launch, so start the application's
159 // event loop.
160 try {
161 // Now that we have a process, we can set up signal handling.
163 runProcess();
164 } catch (const std::exception& ex) {
166 .arg(app_name_).arg(ex.what());
168 "Application process event loop failed: " << ex.what());
169 }
170
171 // All done, so bail out.
173 .arg(app_name_).arg(getpid()).arg(VERSION);
174
175 return (getExitValue());
176}
177
178void
180 try {
181 // We need to initialize logging, in case any error
182 // messages are to be printed.
183 // This is just a test, so we don't care about lockfile.
184 setenv("KEA_LOCKFILE_DIR", "none", 0);
186 Daemon::setVerbose(verbose_);
187 Daemon::loggerInit(bin_name_.c_str(), verbose_);
188
189 // Check the syntax first.
190 std::string config_file = getConfigFile();
191 if (config_file.empty()) {
192 // Basic sanity check: file name must not be empty.
193 isc_throw(InvalidUsage, "JSON configuration file not specified");
194 }
195 ConstElementPtr whole_config = parseFile(config_file);
196 if (!whole_config) {
197 // No fallback to fromJSONFile
198 isc_throw(InvalidUsage, "No configuration found");
199 }
200 if (verbose_) {
201 std::cerr << "Syntax check OK" << std::endl;
202 }
203
204 // Check the logic next.
205 ConstElementPtr module_config;
206 module_config = whole_config->get(getAppName());
207 if (!module_config) {
208 isc_throw(InvalidUsage, "Config file " << config_file <<
209 " does not include '" << getAppName() << "' entry");
210 }
211 if (module_config->getType() != Element::map) {
212 isc_throw(InvalidUsage, "Config file " << config_file <<
213 " includes not map '" << getAppName() << "' entry");
214 }
215
216 // Handle other (i.e. not application name) objects.
217 std::string errmsg = handleOtherObjects(whole_config);
218 if (!errmsg.empty()) {
219 isc_throw(InvalidUsage, "Config file " << config_file << errmsg);
220 }
221
222 // Get an application process object.
223 initProcess();
224
225 ConstElementPtr answer = checkConfig(module_config);
226 int rcode = 0;
227 answer = parseAnswer(rcode, answer);
228 if (rcode != 0) {
229 isc_throw(InvalidUsage, "Error encountered: "
230 << answer->stringValue());
231 }
232 } catch (const VersionMessage&) {
233 throw;
234 } catch (const InvalidUsage&) {
235 throw;
236 } catch (const std::exception& ex) {
237 isc_throw(InvalidUsage, "Syntax check failed with: " << ex.what());
238 }
239 return;
240}
241
242void
243DControllerBase::parseArgs(int argc, char* argv[]) {
244
245 if (argc == 1) {
247 }
248
249 // Iterate over the given command line options. If its a stock option
250 // ("c" or "d") handle it here. If its a valid custom option, then
251 // invoke customOption.
252 int ch;
253 opterr = 0;
254 optind = 1;
255 std::string opts("dvVWc:t:" + getCustomOpts());
256 while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
257 switch (ch) {
258 case 'd':
259 // Enables verbose logging.
260 verbose_ = true;
261 break;
262
263 case 'v':
264 // gather Kea version and throw so main() can catch and return
265 // rather than calling exit() here which disrupts gtest.
267 break;
268
269 case 'V':
270 // gather Kea version and throw so main() can catch and return
271 // rather than calling exit() here which disrupts gtest.
273 break;
274
275 case 'W':
276 // gather Kea config report and throw so main() can catch and
277 // return rather than calling exit() here which disrupts gtest.
279 break;
280
281 case 'c':
282 case 't':
283 // config file name
284 if (optarg == NULL) {
285 isc_throw(InvalidUsage, "configuration file name missing");
286 }
287
288 setConfigFile(optarg);
289
290 if (ch == 't') {
291 check_only_ = true;
292 }
293 break;
294
295 case '?': {
296 // We hit an invalid option.
297 isc_throw(InvalidUsage, "unsupported option: ["
298 << static_cast<char>(optopt) << "] "
299 << (!optarg ? "" : optarg));
300
301 break;
302 }
303
304 default:
305 // We hit a valid custom option
306 if (!customOption(ch, optarg)) {
307 // This would be a programmatic error.
308 isc_throw(InvalidUsage, " Option listed but implemented?: ["
309 << static_cast<char>(ch) << "] "
310 << (!optarg ? "" : optarg));
311 }
312 break;
313 }
314 }
315
316 // There was too much information on the command line.
317 if (argc > optind) {
318 isc_throw(InvalidUsage, "extraneous command line information");
319 }
320}
321
322bool
323DControllerBase::customOption(int /* option */, char* /*optarg*/) {
324 // Default implementation returns false.
325 return (false);
326}
327
328void
331 .arg(app_name_);
332
333 // Invoke virtual method to instantiate the application process.
334 try {
335 process_.reset(createProcess());
336 } catch (const std::exception& ex) {
337 isc_throw(DControllerBaseError, std::string("createProcess failed: ")
338 + ex.what());
339 }
340
341 // This is pretty unlikely, but will test for it just to be safe..
342 if (!process_) {
343 isc_throw(DControllerBaseError, "createProcess returned NULL");
344 }
345
346 // Invoke application's init method (Note this call should throw
347 // DProcessBaseError if it fails).
348 process_->init();
349}
350
353 // Rollback any previous staging configuration. For D2, only a
354 // logger configuration is used here.
355 // We're not using cfgmgr to store logging configuration anymore.
356 // isc::dhcp::CfgMgr::instance().rollback();
357
358 // Will hold configuration.
359 ConstElementPtr module_config;
360 // Will receive configuration result.
361 ConstElementPtr answer;
362 try {
363 std::string config_file = getConfigFile();
364 if (config_file.empty()) {
365 // Basic sanity check: file name must not be empty.
366 isc_throw(BadValue, "JSON configuration file not specified. Please "
367 "use -c command line option.");
368 }
369
370 // If parseFile returns an empty pointer, then pass the file onto the
371 // original JSON parser.
372 ConstElementPtr whole_config = parseFile(config_file);
373 if (!whole_config) {
374 // Read contents of the file and parse it as JSON
375 whole_config = Element::fromJSONFile(config_file, true);
376 }
377
378 // Extract derivation-specific portion of the configuration.
379 module_config = whole_config->get(getAppName());
380 if (!module_config) {
381 isc_throw(BadValue, "Config file " << config_file <<
382 " does not include '" <<
383 getAppName() << "' entry.");
384 }
385 if (module_config->getType() != Element::map) {
386 isc_throw(InvalidUsage, "Config file " << config_file <<
387 " includes not map '" << getAppName() << "' entry");
388 }
389
390 // Handle other (i.e. not application name) objects.
391 std::string errmsg = handleOtherObjects(whole_config);
392 if (!errmsg.empty()) {
393 isc_throw(InvalidUsage, "Config file " << config_file << errmsg);
394 }
395
396 // Let's configure logging before applying the configuration,
397 // so we can log things during configuration process.
398
399 // Temporary storage for logging configuration
400 ConfigPtr storage(new ConfigBase());
401
402 // Configure logging to the temporary storage.
403 Daemon::configureLogger(module_config, storage);
404
405 // Let's apply the new logging. We do it early, so we'll be able
406 // to print out what exactly is wrong with the new config in
407 // case of problems.
408 storage->applyLoggingCfg();
409
410 answer = updateConfig(module_config);
411 // In all cases the right logging configuration is in the context.
412 process_->getCfgMgr()->getContext()->applyLoggingCfg();
413 } catch (const std::exception& ex) {
414 // Rollback logging configuration.
415 process_->getCfgMgr()->getContext()->applyLoggingCfg();
416
417 // build an error result
419 std::string("Configuration parsing failed: ") + ex.what());
420 return (error);
421 }
422
423 return (answer);
424}
425
426void
429 .arg(app_name_);
430 if (!process_) {
431 // This should not be possible.
432 isc_throw(DControllerBaseError, "Process not initialized");
433 }
434
435 // Invoke the application process's run method. This may throw
436 // DProcessBaseError
437 process_->run();
438}
439
440// Instance method for handling new config
443 return (process_->configure(new_config, false));
444}
445
446// Instance method for checking new config
449 return (process_->configure(new_config, true));
450}
451
454 ConstElementPtr /*args*/) {
455 ElementPtr config = process_->getCfgMgr()->getContext()->toElement();
456 std::string hash = BaseCommandMgr::getHash(config);
457 config->set("hash", Element::create(hash));
458
459 return (createAnswer(CONTROL_RESULT_SUCCESS, config));
460}
461
464 ConstElementPtr /*args*/) {
465 ConstElementPtr config = process_->getCfgMgr()->getContext()->toElement();
466 std::string hash = BaseCommandMgr::getHash(config);
467 ElementPtr params = Element::createMap();
468 params->set("hash", Element::create(hash));
469 return (createAnswer(CONTROL_RESULT_SUCCESS, params));
470}
471
474 ConstElementPtr args) {
475 std::string filename;
476
477 if (args) {
478 if (args->getType() != Element::map) {
479 return (createAnswer(CONTROL_RESULT_ERROR, "Argument must be a map"));
480 }
481 ConstElementPtr filename_param = args->get("filename");
482 if (filename_param) {
483 if (filename_param->getType() != Element::string) {
485 "passed parameter 'filename' "
486 "is not a string"));
487 }
488 filename = filename_param->stringValue();
489 }
490 }
491
492 if (filename.empty()) {
493 // filename parameter was not specified, so let's use
494 // whatever we remember
495 filename = getConfigFile();
496 if (filename.empty()) {
498 "Unable to determine filename."
499 "Please specify filename explicitly."));
500 }
501 }
502
503 // Ok, it's time to write the file.
504 size_t size = 0;
505 ElementPtr cfg = process_->getCfgMgr()->getContext()->toElement();
506
507 try {
508 size = writeConfigFile(filename, cfg);
509 } catch (const isc::Exception& ex) {
511 std::string("Error during write-config:")
512 + ex.what()));
513 }
514 if (size == 0) {
516 "Error writing configuration to " + filename));
517 }
518
519 // Ok, it's time to return the successful response.
520 ElementPtr params = Element::createMap();
521 params->set("size", Element::create(static_cast<long long>(size)));
522 params->set("filename", Element::create(filename));
523
524 return (createAnswer(CONTROL_RESULT_SUCCESS, "Configuration written to "
525 + filename + " successful", params));
526}
527
528std::string
530 // Check obsolete or unknown (aka unsupported) objects.
531 const std::string& app_name = getAppName();
532 std::string errmsg;
533 for (auto obj : args->mapValue()) {
534 const std::string& obj_name = obj.first;
535 if (obj_name == app_name) {
536 continue;
537 }
539 .arg("'" + obj_name + "', defining anything in global level besides '"
540 + app_name + "' is no longer supported.");
541 if (errmsg.empty()) {
542 errmsg = " contains unsupported '" + obj_name + "' parameter";
543 } else {
544 errmsg += " (and '" + obj_name + "')";
545 }
546 }
547 return (errmsg);
548}
549
552 const int status_code = CONTROL_RESULT_ERROR; // 1 indicates an error
553 ConstElementPtr module_config;
554 std::string app_name = getAppName();
555 std::string message;
556
557 // Command arguments are expected to be:
558 // { "Module": { ... } }
559 if (!args) {
560 message = "Missing mandatory 'arguments' parameter.";
561 } else {
562 module_config = args->get(app_name);
563 if (!module_config) {
564 message = "Missing mandatory '" + app_name + "' parameter.";
565 } else if (module_config->getType() != Element::map) {
566 message = "'" + app_name + "' parameter expected to be a map.";
567 }
568 }
569
570 if (message.empty()) {
571 // Handle other (i.e. not application name) objects.
572 std::string errmsg = handleOtherObjects(args);
573 if (!errmsg.empty()) {
574 message = "'arguments' parameter" + errmsg;
575 }
576 }
577
578 if (!message.empty()) {
579 // Something is amiss with arguments, return a failure response.
580 ConstElementPtr result = isc::config::createAnswer(status_code,
581 message);
582 return (result);
583 }
584
585 // We are starting the configuration process so we should remove any
586 // staging configuration that has been created during previous
587 // configuration attempts.
588 // We're not using cfgmgr to store logging information anymore.
589 // isc::dhcp::CfgMgr::instance().rollback();
590
591 // Now we check the server proper.
592 return (checkConfig(module_config));
593}
594
597 // Add reload in message?
598 return (configFromFile());
599}
600
603 const int status_code = CONTROL_RESULT_ERROR; // 1 indicates an error
604 ConstElementPtr module_config;
605 std::string app_name = getAppName();
606 std::string message;
607
608 // Command arguments are expected to be:
609 // { "Module": { ... } }
610 if (!args) {
611 message = "Missing mandatory 'arguments' parameter.";
612 } else {
613 module_config = args->get(app_name);
614 if (!module_config) {
615 message = "Missing mandatory '" + app_name + "' parameter.";
616 } else if (module_config->getType() != Element::map) {
617 message = "'" + app_name + "' parameter expected to be a map.";
618 }
619 }
620
621 if (!message.empty()) {
622 // Something is amiss with arguments, return a failure response.
623 ConstElementPtr result = isc::config::createAnswer(status_code,
624 message);
625 return (result);
626 }
627
628 try {
629
630 // Handle other (i.e. not application name) objects.
631 handleOtherObjects(args);
632
633 // We are starting the configuration process so we should remove any
634 // staging configuration that has been created during previous
635 // configuration attempts.
636 // We're not using cfgmgr to store logging information anymore.
637 // isc::dhcp::CfgMgr::instance().rollback();
638
639 // Temporary storage for logging configuration
640 ConfigPtr storage(new ConfigBase());
641
642 // Configure logging to the temporary storage.
643 Daemon::configureLogger(module_config, storage);
644
645 // Let's apply the new logging. We do it early, so we'll be able
646 // to print out what exactly is wrong with the new config in
647 // case of problems.
648 storage->applyLoggingCfg();
649
650 ConstElementPtr answer = updateConfig(module_config);
651 int rcode = 0;
652 parseAnswer(rcode, answer);
653 // In all cases the right logging configuration is in the context.
654 process_->getCfgMgr()->getContext()->applyLoggingCfg();
655 return (answer);
656 } catch (const std::exception& ex) {
657 // Rollback logging configuration.
658 process_->getCfgMgr()->getContext()->applyLoggingCfg();
659
660 // build an error result
662 std::string("Configuration parsing failed: ") + ex.what());
663 return (error);
664 }
665}
666
669 const std::string& tag = process_->getCfgMgr()->getContext()->getServerTag();
670 ElementPtr response = Element::createMap();
671 response->set("server-tag", Element::create(tag));
672
673 return (createAnswer(CONTROL_RESULT_SUCCESS, response));
674}
675
678 ElementPtr status = Element::createMap();
679 status->set("pid", Element::create(static_cast<int>(getpid())));
680
681 auto now = boost::posix_time::second_clock::universal_time();
682 if (!start_.is_not_a_date_time()) {
683 auto uptime = now - start_;
684 status->set("uptime", Element::create(uptime.total_seconds()));
685 }
686
687 auto last_commit = process_->getCfgMgr()->getContext()->getLastCommitTime();
688 if (!last_commit.is_not_a_date_time()) {
689 auto reload = now - last_commit;
690 status->set("reload", Element::create(reload.total_seconds()));
691 }
692
693 return (createAnswer(CONTROL_RESULT_SUCCESS, status));
694}
695
698 ConstElementPtr answer;
699
700 // For version-get put the extended version in arguments
701 ElementPtr extended = Element::create(getVersion(true));
702 ElementPtr arguments = Element::createMap();
703 arguments->set("extended", extended);
704 answer = createAnswer(CONTROL_RESULT_SUCCESS, getVersion(false), arguments);
705 return (answer);
706}
707
711}
712
715 // Shutdown is universal. If its not that, then try it as
716 // a custom command supported by the derivation. If that
717 // doesn't pan out either, than send to it the application
718 // as it may be supported there.
719
720 int exit_value = EXIT_SUCCESS;
721 if (args) {
722 // @todo Should we go ahead and shutdown even if the args are invalid?
723 if (args->getType() != Element::map) {
724 return (createAnswer(CONTROL_RESULT_ERROR, "Argument must be a map"));
725 }
726
727 ConstElementPtr param = args->get("exit-value");
728 if (param) {
729 if (param->getType() != Element::integer) {
731 "parameter 'exit-value' is not an integer"));
732 }
733
734 exit_value = param->intValue();
735 }
736 }
737
738 setExitValue(exit_value);
739 return (shutdownProcess(args));
740}
741
744 if (process_) {
745 return (process_->shutdown(args));
746 }
747
748 // Not really a failure, but this condition is worth noting. In reality
749 // it should be pretty hard to cause this.
750 LOG_WARN(dctl_logger, DCTL_NOT_RUNNING).arg(app_name_);
751 return (createAnswer(CONTROL_RESULT_SUCCESS, "Process has not been initialized"));
752}
753
754void
757
758 // Create our signal set.
759 io_signal_set_.reset(new IOSignalSet(io_service_,
760 std::bind(&DControllerBase::
762 this, ph::_1)));
763 // Register for the signals we wish to handle.
764 io_signal_set_->add(SIGHUP);
765 io_signal_set_->add(SIGINT);
766 io_signal_set_->add(SIGTERM);
767}
768
769void
771 switch (signum) {
772 case SIGHUP:
773 {
775 .arg(signum).arg(getConfigFile());
776 int rcode;
777 ConstElementPtr comment = parseAnswer(rcode, configFromFile());
778 if (rcode != 0) {
780 .arg(comment->stringValue());
781 }
782
783 break;
784 }
785
786 case SIGINT:
787 case SIGTERM:
788 {
790 DCTL_SHUTDOWN_SIGNAL_RECVD).arg(signum);
791 ElementPtr arg_set;
792 shutdownHandler(SHUT_DOWN_COMMAND, arg_set);
793 break;
794 }
795
796 default:
798 break;
799 }
800}
801
802void
803DControllerBase::usage(const std::string & text) {
804 if (text != "") {
805 std::cerr << "Usage error: " << text << std::endl;
806 }
807
808 std::cerr << "Usage: " << bin_name_ << std::endl
809 << " -v: print version number and exit" << std::endl
810 << " -V: print extended version information and exit"
811 << std::endl
812 << " -W: display the configuration report and exit"
813 << std::endl
814 << " -d: optional, verbose output " << std::endl
815 << " -c <config file name> : mandatory,"
816 << " specify name of configuration file" << std::endl
817 << " -t <config file name> : check the"
818 << " configuration file and exit" << std::endl;
819
820 // add any derivation specific usage
821 std::cerr << getUsageText() << std::endl;
822}
823
825 // Explicitly unload hooks
826 HooksManager::prepareUnloadLibraries();
827 if (!HooksManager::unloadLibraries()) {
828 auto names = HooksManager::getLibraryNames();
829 std::string msg;
830 if (!names.empty()) {
831 msg = names[0];
832 for (size_t i = 1; i < names.size(); ++i) {
833 msg += std::string(", ") + names[i];
834 }
835 }
837 }
838
839 io_signal_set_.reset();
840 getIOService()->poll();
841}
842
843std::string
845 std::stringstream tmp;
846
847 tmp << VERSION;
848 if (extended) {
849 tmp << std::endl << EXTENDED_VERSION << std::endl;
850 tmp << "linked with:" << std::endl;
851 tmp << isc::log::Logger::getVersion() << std::endl;
852 tmp << getVersionAddendum();
853 }
854
855 return (tmp.str());
856}
857
858} // end of namespace isc::process
859
860} // 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:103
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:611
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.
asiolink::IOServicePtr & getIOService()
Getter for fetching the controller's IOService.
Definition: d_controller.h:469
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:408
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:49
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:398
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:453
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:67
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 configHashGetHandler(const std::string &command, isc::data::ConstElementPtr args)
handler for config-hash-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
std::string getAppName() const
Fetches the name of the application under control.
Definition: d_controller.h:221
virtual isc::data::ConstElementPtr parseFile(const std::string &file_name)
Parse a given file into Elements.
Definition: d_controller.cc:61
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:41
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:104
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:228
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:114
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:134
int getExitValue()
Fetches the exit value.
Definition: daemon.h:220
void createPIDFile(int pid=0)
Creates the PID file.
Definition: daemon.cc:202
void setConfigFile(const std::string &config_file)
Sets the configuration file name.
Definition: daemon.cc:109
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:29
boost::shared_ptr< Element > ElementPtr
Definition: data.h:28
@ error
Definition: db_log.h:116
std::string getConfigReport()
Definition: cfgrpt.cc:20
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 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_UNLOAD_LIBRARIES_ERROR
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
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.