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