AM_LDFLAGS = -static
endif
-CLEANFILES =
+CLEANFILES =
man_MANS = kea-client.8
DISTCLEANFILES = $(man_MANS)
libclnt_la_SOURCES =
libclnt_la_SOURCES += main.cc
libclnt_la_SOURCES += client_interface.h client_interface.cc
+libclnt_la_SOURCES += executor.cc executor.h
+libclnt_la_SOURCES += clnt_process.cc clnt_process.h
+libclnt_la_SOURCES += clnt_cfg_mgr.cc clnt_cfg_mgr.h
+libclnt_la_SOURCES += clnt_config.cc clnt_config.h
sbin_PROGRAMS = kea-client
+kea_client_SOURCES = main.cc
+
kea_client_LDADD = libclnt.la
kea_client_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
kea_client_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
kea_client_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
kea_client_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+kea_client_LDADD += $(top_builddir)/src/lib/process/libkea-process.la
kea_client_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
kea_client_LDADD += $(BOOST_LIBS)
kea_clntdir = $(pkgdatadir)
-kea_clnt_DATA = dhcp6.spec
if GENERATE_PARSER
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Paublic
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <client/clnt_cfg_mgr.h>
+#include <client/clnt_config.h>
+#include <cc/data.h>
+
+using namespace isc::data;
+
+namespace isc {
+namespace client {
+
+ClntCfgMgr::ClntCfgMgr()
+ :DCfgMgrBase(process::DCfgContextBasePtr(new ClntConfig())) {
+}
+
+std::string
+ClntCfgMgr::getConfigSummary(const uint32_t selection) {
+ return ("not-implemented");
+}
+
+isc::data::ConstElementPtr
+ClntCfgMgr::parse(isc::data::ConstElementPtr config, bool check_only) {
+ return (ConstElementPtr(new MapElement()));
+}
+
+isc::dhcp::ParserPtr
+ClntCfgMgr::createConfigParser(const std::string&,
+ const isc::data::Element::Position& pos) {
+ return (isc::dhcp::ParserPtr());
+}
+
+process::DCfgContextBasePtr
+ClntCfgMgr::createNewContext() {
+ return (process::DCfgContextBasePtr(new ClntConfig()));
+}
+
+void ClntCfgMgr::ensureCurrentAllocated() {
+
+}
+
+};
+};
+
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef CLNT_CFG_MGR_H
+#define CLNT_CFG_MGR_H
+
+#include <client/clnt_config.h>
+#include <cc/data.h>
+#include <hooks/hooks_config.h>
+#include <process/d_cfg_mgr.h>
+#include <process/base_cfg_mgr.h>
+#include <boost/pointer_cast.hpp>
+
+namespace isc {
+namespace client {
+
+class ClntCfgMgr : public process::DCfgMgrBase {
+public:
+
+ /// @brief Constructor.
+ ClntCfgMgr();
+
+ /// @brief Destructor
+ virtual ~ClntCfgMgr() { }
+
+ /// @brief Convenience method that returns the Control Agent configuration
+ /// context.
+ ///
+ /// @return returns a pointer to the configuration context.
+ ClntConfigPtr getCtrlAgentCfgContext() {
+ return (boost::dynamic_pointer_cast<ClntConfig>(getContext()));
+ }
+
+ /// @brief Returns configuration summary in the textual format.
+ ///
+ /// @param selection Bitfield which describes the parts of the configuration
+ /// to be returned. This parameter is ignored for the Control Agent.
+ ///
+ /// @return Summary of the configuration in the textual format.
+ virtual std::string getConfigSummary(const uint32_t selection);
+
+protected:
+
+ virtual void ensureCurrentAllocated();
+
+ /// @brief Parses configuration of the Control Agent.
+ ///
+ /// @param config Pointer to a configuration specified for the agent.
+ /// @param check_only Boolean flag indicating if this method should
+ /// only verify correctness of the provided conifiguration.
+ /// @return Pointer to a result of configuration parsing.
+ virtual isc::data::ConstElementPtr
+ parse(isc::data::ConstElementPtr config, bool check_only);
+
+ /// @brief This is no longer used.
+ ///
+ /// @throw NotImplemented
+ /// @return nothing, always throws
+ virtual isc::dhcp::ParserPtr
+ createConfigParser(const std::string&,
+ const isc::data::Element::Position& pos);
+
+ /// @brief Creates a new, blank CtrlAgentCfgContext context.
+ ///
+ ///
+ /// This method is used at the beginning of configuration process to
+ /// create a fresh, empty copy of a CtrlAgentCfgContext. This new context
+ /// will be populated during the configuration process and will replace the
+ /// existing context provided the configuration process completes without
+ /// error.
+ ///
+ /// @return Returns a DCfgContextBasePtr to the new context instance.
+ virtual process::DCfgContextBasePtr createNewContext();
+};
+
+};
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <client/clnt_cfg_mgr.h>
+#include <cc/data.h>
+
+using namespace isc::data;
+
+namespace isc {
+namespace client {
+
+ClntConfig::ClntConfig() {
+
+}
+
+isc::data::ElementPtr ClntConfig::toElement() const {
+ ElementPtr map(new MapElement());
+ return (map);
+}
+
+std::string ClntConfig::getConfigSummary(const uint32_t selection) const {
+ return ("not-impl");
+}
+
+};
+};
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef CLNT_CONFIG_H
+#define CLNT_CONFIG_H
+
+#include <process/d_cfg_mgr.h>
+
+namespace isc {
+namespace client {
+
+class ClntConfig;
+typedef boost::shared_ptr<ClntConfig> ClntConfigPtr;
+
+class ClntConfig : public process::DCfgContextBase {
+public:
+ ClntConfig();
+
+ virtual process::BaseConfigPtr clone() const {
+ return (process::BaseConfigPtr(new ClntConfig(*this)));
+ }
+
+ virtual isc::data::ElementPtr toElement() const;
+
+ virtual std::string getConfigSummary(const uint32_t selection) const;
+};
+
+
+};
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <client/clnt_process.h>
+#include <client/clnt_cfg_mgr.h>
+#include <cc/command_interpreter.h>
+#include <process/d_cfg_mgr.h>
+
+using namespace isc::client;
+using namespace isc::config;
+
+ClntProcess::ClntProcess(const char* name,
+ const asiolink::IOServicePtr& io_service)
+ :DProcessBase(name, io_service, process::DCfgMgrBasePtr(new ClntCfgMgr())) {
+
+}
+
+void ClntProcess::init() {
+
+}
+
+void ClntProcess::run() {
+ std::cout << "Running...." << std::endl;
+ while (true) {
+ std::cout << ".";
+ sleep(1);
+ }
+}
+
+isc::data::ConstElementPtr
+ClntProcess::configure(isc::data::ConstElementPtr config_set,
+ bool check_only) {
+ return (createAnswer(3, "not implemented"));
+}
+
+isc::data::ConstElementPtr
+ClntProcess::shutdown(isc::data::ConstElementPtr args) {
+ return (createAnswer(3, "not implemented"));
+}
+
+ClntProcess::~ClntProcess() {
+}
+
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef CLNT_PROCESS_H
+#define CLNT_PROCESS_H
+
+#include <process/d_process.h>
+
+namespace isc {
+namespace client {
+
+
+class ClntProcess : public process::DProcessBase {
+
+ public:
+ ClntProcess(const char* nane, const asiolink::IOServicePtr& io_service);
+
+ virtual void init();
+
+ virtual void run();
+
+ virtual isc::data::ConstElementPtr
+ configure(isc::data::ConstElementPtr config_set,
+ bool check_only = false);
+
+ /// @brief Initiates the process's shutdown process.
+ ///
+ /// This is last step in the shutdown event callback chain, that is
+ /// intended to notify the process it is to begin its shutdown process.
+ ///
+ /// @param args an Element set of shutdown arguments (if any) that are
+ /// supported by the process derivation.
+ ///
+ /// @return an Element that contains the results of argument processing,
+ /// consisting of an integer status value (0 means successful,
+ /// non-zero means failure), and a string explanation of the outcome.
+ ///
+ /// @throw DProcessBaseError if an operational error is encountered.
+ virtual isc::data::ConstElementPtr
+ shutdown(isc::data::ConstElementPtr args);
+
+ virtual ~ClntProcess();
+};
+
+};
+};
+
+#endif
+++ /dev/null
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <config.h>
-#include <cc/command_interpreter.h>
-#include <cfgrpt/config_report.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <exceptions/exceptions.h>
-#include <log/logger.h>
-#include <log/logger_support.h>
-#include <process/d_log.h>
-#include <process/d_controller.h>
-
-#ifdef HAVE_MYSQL
-#include <dhcpsrv/mysql_lease_mgr.h>
-#endif
-#ifdef HAVE_PGSQL
-#include <dhcpsrv/pgsql_lease_mgr.h>
-#endif
-#ifdef HAVE_CQL
-#include <dhcpsrv/cql_lease_mgr.h>
-#endif
-#include <dhcpsrv/memfile_lease_mgr.h>
-
-#include <sstream>
-#include <unistd.h>
-
-using namespace isc::data;
-using namespace isc::config;
-
-namespace isc {
-namespace process {
-
-DControllerBasePtr DControllerBase::controller_;
-
-// Note that the constructor instantiates the controller's primary IOService.
-DControllerBase::DControllerBase(const char* app_name, const char* bin_name)
- : app_name_(app_name), bin_name_(bin_name),
- verbose_(false), check_only_(false), spec_file_name_(""),
- io_service_(new isc::asiolink::IOService()),
- io_signal_queue_() {
-}
-
-void
-DControllerBase::setController(const DControllerBasePtr& controller) {
- if (controller_) {
- // This shouldn't happen, but let's make sure it can't be done.
- // It represents a programmatic error.
- isc_throw (DControllerBaseError,
- "Multiple controller instances attempted.");
- }
-
- controller_ = controller;
-}
-
-ConstElementPtr
-DControllerBase::parseFile(const std::string&) {
- ConstElementPtr elements;
- return (elements);
-}
-
-void
-DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
-
- // Step 1 is to parse the command line arguments.
- try {
- parseArgs(argc, argv);
- } catch (const InvalidUsage& ex) {
- usage(ex.what());
- // rethrow it with an empty message
- isc_throw(InvalidUsage, "");
- }
-
- setProcName(bin_name_);
-
- if (isCheckOnly()) {
- checkConfigOnly();
- return;
- }
-
- // It is important that we set a default logger name because this name
- // will be used when the user doesn't provide the logging configuration
- // in the Kea configuration file.
- isc::dhcp::CfgMgr::instance().setDefaultLoggerName(bin_name_);
-
- // Logger's default configuration depends on whether we are in the
- // verbose mode or not. CfgMgr manages the logger configuration so
- // the verbose mode is set for CfgMgr.
- isc::dhcp::CfgMgr::instance().setVerbose(verbose_);
-
- // Do not initialize logger here if we are running unit tests. It would
- // replace an instance of unit test specific logger.
- if (!test_mode) {
- // Now that we know what the mode flags are, we can init logging.
- Daemon::loggerInit(bin_name_.c_str(), verbose_);
- }
-
- try {
- createPIDFile();
- } catch (const dhcp::DaemonPIDExists& ex) {
- LOG_FATAL(dctl_logger, DCTL_ALREADY_RUNNING)
- .arg(bin_name_).arg(ex.what());
- isc_throw (LaunchError, "Launch Failed: " << ex.what());
- } catch (const std::exception& ex) {
- LOG_FATAL(dctl_logger, DCTL_PID_FILE_ERROR)
- .arg(app_name_).arg(ex.what());
- isc_throw (LaunchError, "Launch failed: " << ex.what());
- }
-
- // Log the starting of the service.
- LOG_INFO(dctl_logger, DCTL_STARTING)
- .arg(app_name_).arg(getpid()).arg(VERSION);
- try {
- // Step 2 is to create and initialize the application process object.
- initProcess();
- } catch (const std::exception& ex) {
- LOG_FATAL(dctl_logger, DCTL_INIT_PROCESS_FAIL)
- .arg(app_name_).arg(ex.what());
- isc_throw (ProcessInitError,
- "Application Process initialization failed: " << ex.what());
- }
-
- LOG_DEBUG(dctl_logger, isc::log::DBGLVL_START_SHUT, DCTL_STANDALONE)
- .arg(app_name_);
-
- // Step 3 is to load configuration from file.
- int rcode;
- ConstElementPtr comment = parseAnswer(rcode, configFromFile());
- if (rcode != 0) {
- LOG_FATAL(dctl_logger, DCTL_CONFIG_FILE_LOAD_FAIL)
- .arg(app_name_).arg(comment->stringValue());
- isc_throw (ProcessInitError, "Could Not load configuration file: "
- << comment->stringValue());
- }
-
- // Everything is clear for launch, so start the application's
- // event loop.
- try {
- // Now that we have a proces, we can set up signal handling.
- initSignalHandling();
- runProcess();
- } catch (const std::exception& ex) {
- LOG_FATAL(dctl_logger, DCTL_PROCESS_FAILED)
- .arg(app_name_).arg(ex.what());
- isc_throw (ProcessRunError,
- "Application process event loop failed: " << ex.what());
- }
-
- // All done, so bail out.
- LOG_INFO(dctl_logger, DCTL_SHUTDOWN)
- .arg(app_name_).arg(getpid()).arg(VERSION);
-}
-
-void
-DControllerBase::checkConfigOnly() {
- try {
- // We need to initialize logging, in case any error
- // messages are to be printed.
- // This is just a test, so we don't care about lockfile.
- setenv("KEA_LOCKFILE_DIR", "none", 0);
- isc::dhcp::CfgMgr::instance().setDefaultLoggerName(bin_name_);
- isc::dhcp::CfgMgr::instance().setVerbose(verbose_);
- Daemon::loggerInit(bin_name_.c_str(), verbose_);
-
- // Check the syntax first.
- std::string config_file = getConfigFile();
- if (config_file.empty()) {
- // Basic sanity check: file name must not be empty.
- isc_throw(InvalidUsage, "JSON configuration file not specified");
- }
- ConstElementPtr whole_config = parseFile(config_file);
- if (!whole_config) {
- // No fallback to fromJSONFile
- isc_throw(InvalidUsage, "No configuration found");
- }
- if (verbose_) {
- std::cerr << "Syntax check OK" << std::endl;
- }
-
- // Check the logic next.
- ConstElementPtr module_config;
- module_config = whole_config->get(getAppName());
- if (!module_config) {
- isc_throw(InvalidUsage, "Config file " << config_file <<
- " does not include '" << getAppName() << "' entry");
- }
-
- // Get an application process object.
- initProcess();
-
- ConstElementPtr answer = checkConfig(module_config);
- int rcode = 0;
- answer = parseAnswer(rcode, answer);
- if (rcode != 0) {
- isc_throw(InvalidUsage, "Error encountered: "
- << answer->stringValue());
- }
- } catch (const VersionMessage&) {
- throw;
- } catch (const InvalidUsage&) {
- throw;
- } catch (const std::exception& ex) {
- isc_throw(InvalidUsage, "Syntax check failed with: " << ex.what());
- }
- return;
-}
-
-void
-DControllerBase::parseArgs(int argc, char* argv[])
-{
- // Iterate over the given command line options. If its a stock option
- // ("c" or "d") handle it here. If its a valid custom option, then
- // invoke customOption.
- int ch;
- opterr = 0;
- optind = 1;
- std::string opts("dvVWc:t:" + getCustomOpts());
- while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
- switch (ch) {
- case 'd':
- // Enables verbose logging.
- verbose_ = true;
- break;
-
- case 'v':
- // gather Kea version and throw so main() can catch and return
- // rather than calling exit() here which disrupts gtest.
- isc_throw(VersionMessage, getVersion(false));
- break;
-
- case 'V':
- // gather Kea version and throw so main() can catch and return
- // rather than calling exit() here which disrupts gtest.
- isc_throw(VersionMessage, getVersion(true));
- break;
-
- case 'W':
- // gather Kea config report and throw so main() can catch and
- // return rather than calling exit() here which disrupts gtest.
- isc_throw(VersionMessage, isc::detail::getConfigReport());
- break;
-
- case 'c':
- case 't':
- // config file name
- if (optarg == NULL) {
- isc_throw(InvalidUsage, "configuration file name missing");
- }
-
- setConfigFile(optarg);
-
- if (ch == 't') {
- check_only_ = true;
- }
- break;
-
- case '?': {
- // We hit an invalid option.
- isc_throw(InvalidUsage, "unsupported option: ["
- << static_cast<char>(optopt) << "] "
- << (!optarg ? "" : optarg));
-
- break;
- }
-
- default:
- // We hit a valid custom option
- if (!customOption(ch, optarg)) {
- // This would be a programmatic error.
- isc_throw(InvalidUsage, " Option listed but implemented?: ["
- << static_cast<char>(ch) << "] "
- << (!optarg ? "" : optarg));
- }
- break;
- }
- }
-
- // There was too much information on the command line.
- if (argc > optind) {
- isc_throw(InvalidUsage, "extraneous command line information");
- }
-}
-
-bool
-DControllerBase::customOption(int /* option */, char* /*optarg*/)
-{
- // Default implementation returns false.
- return (false);
-}
-
-void
-DControllerBase::initProcess() {
- LOG_DEBUG(dctl_logger, isc::log::DBGLVL_START_SHUT, DCTL_INIT_PROCESS)
- .arg(app_name_);
-
- // Invoke virtual method to instantiate the application process.
- try {
- process_.reset(createProcess());
- } catch (const std::exception& ex) {
- isc_throw(DControllerBaseError, std::string("createProcess failed: ")
- + ex.what());
- }
-
- // This is pretty unlikely, but will test for it just to be safe..
- if (!process_) {
- isc_throw(DControllerBaseError, "createProcess returned NULL");
- }
-
- // Invoke application's init method (Note this call should throw
- // DProcessBaseError if it fails).
- process_->init();
-}
-
-ConstElementPtr
-DControllerBase::configFromFile() {
- // Rollback any previous staging configuration. For D2, only a
- // logger configuration is used here.
- isc::dhcp::CfgMgr::instance().rollback();
- // Will hold configuration.
- ConstElementPtr module_config;
- // Will receive configuration result.
- ConstElementPtr answer;
- try {
- std::string config_file = getConfigFile();
- if (config_file.empty()) {
- // Basic sanity check: file name must not be empty.
- isc_throw(BadValue, "JSON configuration file not specified. Please "
- "use -c command line option.");
- }
-
- // If parseFile returns an empty pointer, then pass the file onto the
- // original JSON parser.
- ConstElementPtr whole_config = parseFile(config_file);
- if (!whole_config) {
- // Read contents of the file and parse it as JSON
- whole_config = Element::fromJSONFile(config_file, true);
- }
-
- // Let's configure logging before applying the configuration,
- // so we can log things during configuration process.
-
- // Temporary storage for logging configuration
- isc::dhcp::SrvConfigPtr storage =
- isc::dhcp::CfgMgr::instance().getStagingCfg();
-
- // Get 'Logging' element from the config and use it to set up
- // logging. If there's no such element, we'll just pass NULL.
- Daemon::configureLogger(whole_config->get("Logging"), storage);
-
- // Extract derivation-specific portion of the configuration.
- module_config = whole_config->get(getAppName());
- if (!module_config) {
- isc_throw(BadValue, "Config file " << config_file <<
- " does not include '" <<
- getAppName() << "' entry.");
- }
-
- answer = updateConfig(module_config);
- int rcode = 0;
- parseAnswer(rcode, answer);
- if (!rcode) {
- // Configuration successful, so apply the logging configuration
- // to log4cplus.
- isc::dhcp::CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
- isc::dhcp::CfgMgr::instance().commit();
- }
-
- } catch (const std::exception& ex) {
- // Rollback logging configuration.
- isc::dhcp::CfgMgr::instance().rollback();
- // build an error result
- ConstElementPtr error = createAnswer(COMMAND_ERROR,
- std::string("Configuration parsing failed: ") + ex.what());
- return (error);
- }
-
- return (answer);
-}
-
-
-void
-DControllerBase::runProcess() {
- LOG_DEBUG(dctl_logger, isc::log::DBGLVL_START_SHUT, DCTL_RUN_PROCESS)
- .arg(app_name_);
- if (!process_) {
- // This should not be possible.
- isc_throw(DControllerBaseError, "Process not initialized");
- }
-
- // Invoke the application process's run method. This may throw
- // DProcessBaseError
- process_->run();
-}
-
-// Instance method for handling new config
-ConstElementPtr
-DControllerBase::updateConfig(ConstElementPtr new_config) {
- return (process_->configure(new_config, false));
-}
-
-// Instance method for checking new config
-ConstElementPtr
-DControllerBase::checkConfig(ConstElementPtr new_config) {
- return (process_->configure(new_config, true));
-}
-
-ConstElementPtr
-DControllerBase::configGetHandler(const std::string&,
- ConstElementPtr /*args*/) {
- ConstElementPtr config = process_->getCfgMgr()->getContext()->toElement();
-
- return (createAnswer(COMMAND_SUCCESS, config));
-}
-
-ConstElementPtr
-DControllerBase::configWriteHandler(const std::string&,
- ConstElementPtr args) {
- std::string filename;
-
- if (args) {
- if (args->getType() != Element::map) {
- return (createAnswer(COMMAND_ERROR, "Argument must be a map"));
- }
- ConstElementPtr filename_param = args->get("filename");
- if (filename_param) {
- if (filename_param->getType() != Element::string) {
- return (createAnswer(COMMAND_ERROR,
- "passed parameter 'filename' "
- "is not a string"));
- }
- filename = filename_param->stringValue();
- }
- }
-
- if (filename.empty()) {
- // filename parameter was not specified, so let's use
- // whatever we remember
- filename = getConfigFile();
- if (filename.empty()) {
- return (createAnswer(COMMAND_ERROR,
- "Unable to determine filename."
- "Please specify filename explicitly."));
- }
- }
-
-
- // Ok, it's time to write the file.
- size_t size = 0;
- ElementPtr cfg = process_->getCfgMgr()->getContext()->toElement();
-
- // Logging storage is messed up in CA. During its configuration (see
- // DControllerBase::configFromFile() it calls Daemon::configureLogger()
- // that stores the logging info in isc::dhcp::CfgMgr::getStagingCfg().
- // This is later moved to getCurrentCfg() when the configuration is
- // commited. All control-agent specific configuration is stored in
- // a structure accessible by process_->getCfgMgr()->getContext(). Note
- // logging information is not stored there.
- //
- // As a result, we need to extract the CA configuration from one
- // place and logging from another.
- ConstElementPtr loginfo = isc::dhcp::CfgMgr::instance().getCurrentCfg()->toElement();
- if (loginfo) {
- // If there was a config stored in dhcp::CfgMgr, try to get Logging info from it.
- loginfo = loginfo->get("Logging");
- }
- if (loginfo) {
- // If there is some logging information, add it to our config.
- cfg->set("Logging", loginfo);
- }
-
- try {
- size = writeConfigFile(filename, cfg);
- } catch (const isc::Exception& ex) {
- return (createAnswer(COMMAND_ERROR,
- std::string("Error during write-config:")
- + ex.what()));
- }
- if (size == 0) {
- return (createAnswer(COMMAND_ERROR,
- "Error writing configuration to " + filename));
- }
-
- // Ok, it's time to return the successful response.
- ElementPtr params = Element::createMap();
- params->set("size", Element::create(static_cast<long long>(size)));
- params->set("filename", Element::create(filename));
-
- return (createAnswer(CONTROL_RESULT_SUCCESS, "Configuration written to "
- + filename + " successful", params));
-}
-
-ConstElementPtr
-DControllerBase::configTestHandler(const std::string&, ConstElementPtr args) {
- const int status_code = COMMAND_ERROR; // 1 indicates an error
- ConstElementPtr module_config;
- std::string app_name = getAppName();
- std::string message;
-
- // Command arguments are expected to be:
- // { "Module": { ... }, "Logging": { ... } }
- // The Logging component is technically optional. If it's not supplied
- // logging will revert to default logging.
- if (!args) {
- message = "Missing mandatory 'arguments' parameter.";
- } else {
- module_config = args->get(app_name);
- if (!module_config) {
- message = "Missing mandatory '" + app_name + "' parameter.";
- } else if (module_config->getType() != Element::map) {
- message = "'" + app_name + "' parameter expected to be a map.";
- }
- }
-
- if (!message.empty()) {
- // Something is amiss with arguments, return a failure response.
- ConstElementPtr result = isc::config::createAnswer(status_code,
- message);
- return (result);
- }
-
- // We are starting the configuration process so we should remove any
- // staging configuration that has been created during previous
- // configuration attempts.
- isc::dhcp::CfgMgr::instance().rollback();
-
- // Now we check the server proper.
- return (checkConfig(module_config));
-}
-
-ConstElementPtr
-DControllerBase::versionGetHandler(const std::string&, ConstElementPtr) {
- ConstElementPtr answer;
-
- // For version-get put the extended version in arguments
- ElementPtr extended = Element::create(getVersion(true));
- ElementPtr arguments = Element::createMap();
- arguments->set("extended", extended);
- answer = createAnswer(COMMAND_SUCCESS, getVersion(false), arguments);
- return (answer);
-}
-
-ConstElementPtr
-DControllerBase::buildReportHandler(const std::string&, ConstElementPtr) {
- return (createAnswer(COMMAND_SUCCESS, isc::detail::getConfigReport()));
-}
-
-ConstElementPtr
-DControllerBase::shutdownHandler(const std::string&, ConstElementPtr args) {
- // Shutdown is universal. If its not that, then try it as
- // a custom command supported by the derivation. If that
- // doesn't pan out either, than send to it the application
- // as it may be supported there.
- return (shutdownProcess(args));
-}
-
-ConstElementPtr
-DControllerBase::shutdownProcess(ConstElementPtr args) {
- if (process_) {
- return (process_->shutdown(args));
- }
-
- // Not really a failure, but this condition is worth noting. In reality
- // it should be pretty hard to cause this.
- LOG_WARN(dctl_logger, DCTL_NOT_RUNNING).arg(app_name_);
- return (createAnswer(COMMAND_SUCCESS, "Process has not been initialized"));
-}
-
-void
-DControllerBase::initSignalHandling() {
- /// @todo block everything we don't handle
-
- // Create our signal queue.
- io_signal_queue_.reset(new IOSignalQueue(io_service_));
-
- // Install the on-receipt handler
- util::SignalSet::setOnReceiptHandler(boost::bind(&DControllerBase::
- osSignalHandler,
- this, _1));
- // Register for the signals we wish to handle.
- signal_set_.reset(new util::SignalSet(SIGHUP,SIGINT,SIGTERM));
-}
-
-bool
-DControllerBase::osSignalHandler(int signum) {
- // Create a IOSignal to propagate the signal to IOService.
- io_signal_queue_->pushSignal(signum, boost::bind(&DControllerBase::
- ioSignalHandler,
- this, _1));
- return (true);
-}
-
-void
-DControllerBase::ioSignalHandler(IOSignalId sequence_id) {
- // Pop the signal instance off the queue. This should make us
- // the only one holding it, so when we leave it should be freed.
- // (note that popSignal will throw if signal is not found, which
- // in turn will caught, logged, and swallowed by IOSignal callback
- // invocation code.)
- IOSignalPtr io_signal = io_signal_queue_->popSignal(sequence_id);
-
- // Now call virtual signal processing method.
- processSignal(io_signal->getSignum());
-}
-
-void
-DControllerBase::processSignal(int signum) {
- switch (signum) {
- case SIGHUP:
- {
- LOG_INFO(dctl_logger, DCTL_CFG_FILE_RELOAD_SIGNAL_RECVD)
- .arg(signum).arg(getConfigFile());
- int rcode;
- ConstElementPtr comment = parseAnswer(rcode, configFromFile());
- if (rcode != 0) {
- LOG_ERROR(dctl_logger, DCTL_CFG_FILE_RELOAD_ERROR)
- .arg(comment->stringValue());
- }
-
- break;
- }
-
- case SIGINT:
- case SIGTERM:
- {
- LOG_DEBUG(dctl_logger, isc::log::DBGLVL_START_SHUT,
- DCTL_SHUTDOWN_SIGNAL_RECVD).arg(signum);
- ElementPtr arg_set;
- shutdownHandler(SHUT_DOWN_COMMAND, arg_set);
- break;
- }
-
- default:
- LOG_WARN(dctl_logger, DCTL_UNSUPPORTED_SIGNAL).arg(signum);
- break;
- }
-}
-
-void
-DControllerBase::usage(const std::string & text)
-{
- if (text != "") {
- std::cerr << "Usage error: " << text << std::endl;
- }
-
- std::cerr << "Usage: " << bin_name_ << std::endl
- << " -v: print version number and exit" << std::endl
- << " -V: print extended version information and exit"
- << std::endl
- << " -W: display the configuration report and exit"
- << std::endl
- << " -d: optional, verbose output " << std::endl
- << " -c <config file name> : mandatory,"
- << " specify name of configuration file" << std::endl
- << " -t <config file name> : check the"
- << " configuration file and exit" << std::endl;
-
- // add any derivation specific usage
- std::cerr << getUsageText() << std::endl;
-}
-
-DControllerBase::~DControllerBase() {
-}
-
-// Refer to config_report so it will be embedded in the binary
-const char* const* d2_config_report = isc::detail::config_report;
-
-std::string
-DControllerBase::getVersion(bool extended) {
- std::stringstream tmp;
-
- tmp << VERSION;
- if (extended) {
- tmp << std::endl << EXTENDED_VERSION << std::endl;
- tmp << "linked with:" << std::endl;
- tmp << isc::log::Logger::getVersion() << std::endl;
- tmp << getVersionAddendum();
- }
-
- return (tmp.str());
-}
-
-}; // namespace isc::process
-
-}; // namespace isc
+++ /dev/null
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef D_CONTROLLER_H
-#define D_CONTROLLER_H
-
-#include <asiolink/io_service.h>
-#include <cc/data.h>
-#include <dhcpsrv/daemon.h>
-#include <exceptions/exceptions.h>
-#include <log/logger_support.h>
-#include <process/d_log.h>
-#include <process/d_process.h>
-#include <process/io_service_signal.h>
-
-#include <boost/shared_ptr.hpp>
-#include <boost/noncopyable.hpp>
-
-#include <string>
-#include <set>
-
-namespace isc {
-namespace process {
-
-/// @brief Exception thrown when the command line is invalid.
-/// Can be used to transmit negative messages too.
-class InvalidUsage : public isc::Exception {
-public:
- InvalidUsage(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) { };
-};
-
-/// @brief Exception used to convey version info upwards.
-/// Since command line argument parsing is done as part of
-/// DControllerBase::launch(), it uses this exception to propagate
-/// version information up to main(), when command line argument
-/// -v, -V or -W is given. Can be used to transmit positive messages too.
-class VersionMessage : public isc::Exception {
-public:
- VersionMessage(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) { };
-};
-
-/// @brief Exception thrown when the controller launch fails.
-class LaunchError: public isc::Exception {
-public:
- LaunchError (const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) { };
-};
-
-/// @brief Exception thrown when the application process fails.
-class ProcessInitError: public isc::Exception {
-public:
- ProcessInitError (const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) { };
-};
-
-/// @brief Exception thrown when the application process encounters an
-/// operation in its event loop (i.e. run method).
-class ProcessRunError: public isc::Exception {
-public:
- ProcessRunError (const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) { };
-};
-
-/// @brief Exception thrown when the controller encounters an operational error.
-class DControllerBaseError : public isc::Exception {
-public:
- DControllerBaseError (const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) { };
-};
-
-
-/// @brief Defines a shared pointer to DControllerBase.
-class DControllerBase;
-typedef boost::shared_ptr<DControllerBase> DControllerBasePtr;
-
-/// @brief Application Controller
-///
-/// DControllerBase is an abstract singleton which provides the framework and
-/// services for managing an application process that implements the
-/// DProcessBase interface. It runs the process like a stand-alone, command
-/// line driven executable, which must be supplied a configuration file at
-/// startup. It coordinates command line argument parsing, process
-/// instantiation and initialization, and runtime control through external
-/// command and configuration event handling.
-/// It creates the IOService instance which is used for runtime control
-/// events and passes the IOService into the application process at process
-/// creation.
-/// It provides the callback handlers for command and configuration events
-/// which could be triggered by an external source. Such sources are intended
-/// to be registered with and monitored by the controller's IOService such that
-/// the appropriate handler can be invoked.
-///
-/// DControllerBase provides dynamic configuration file reloading upon receipt
-/// of SIGHUP, and graceful shutdown upon receipt of either SIGINT or SIGTERM.
-///
-/// NOTE: Derivations must supply their own static singleton instance method(s)
-/// for creating and fetching the instance. The base class declares the instance
-/// member in order for it to be available for static callback functions.
-class DControllerBase : public dhcp::Daemon {
-public:
- /// @brief Constructor
- ///
- /// @param app_name is display name of the application under control. This
- /// name appears in log statements.
- /// @param bin_name is the name of the application executable.
- DControllerBase(const char* app_name, const char* bin_name);
-
- /// @brief Destructor
- virtual ~DControllerBase();
-
- /// @brief returns Kea version on stdout and exit.
- /// redeclaration/redefinition. @ref isc::dhcp::Daemon::getVersion()
- std::string getVersion(bool extended);
-
- /// @brief Acts as the primary entry point into the controller execution
- /// and provides the outermost application control logic:
- ///
- /// 1. parse command line arguments
- /// 2. instantiate and initialize the application process
- /// 3. load the configuration file
- /// 4. initialize signal handling
- /// 5. start and wait on the application process event loop
- /// 6. exit to the caller
- ///
- /// It is intended to be called from main() and be given the command line
- /// arguments.
- ///
- /// This function can be run in "test mode". It prevents initialization
- /// of module logger. This is used in unit tests which initialize logger
- /// in their main function. Such a logger uses environmental variables to
- /// control severity, verbosity etc.
- ///
- /// @param argc is the number of command line arguments supplied
- /// @param argv is the array of string (char *) command line arguments
- /// @param test_mode is a bool value which indicates if
- /// @c DControllerBase::launch should be run in the test mode (if true).
- /// This parameter doesn't have default value to force test implementers to
- /// enable test mode explicitly.
- ///
- /// @throw throws one of the following exceptions:
- /// InvalidUsage - Indicates invalid command line.
- /// ProcessInitError - Failed to create and initialize application
- /// process object.
- /// ProcessRunError - A fatal error occurred while in the application
- /// process event loop.
- virtual void launch(int argc, char* argv[], const bool test_mode);
-
- /// @brief Instance method invoked by the configuration event handler and
- /// which processes the actual configuration update. Provides behavioral
- /// path for both integrated and stand-alone modes. The current
- /// implementation will merge the configuration update into the existing
- /// configuration and then invoke the application process' configure method.
- ///
- /// @param new_config is the new configuration
- ///
- /// @return returns an Element that contains the results of configuration
- /// update composed of an integer status value (0 means successful,
- /// non-zero means failure), and a string explanation of the outcome.
- virtual isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr
- new_config);
-
- /// @brief Instance method invoked by the configuration event handler and
- /// which processes the actual configuration check. Provides behavioral
- /// path for both integrated and stand-alone modes. The current
- /// implementation will merge the configuration update into the existing
- /// configuration and then invoke the application process' configure method
- /// with a final rollback.
- ///
- /// @param new_config is the new configuration
- ///
- /// @return returns an Element that contains the results of configuration
- /// update composed of an integer status value (0 means successful,
- /// non-zero means failure), and a string explanation of the outcome.
- virtual isc::data::ConstElementPtr checkConfig(isc::data::ConstElementPtr
- new_config);
-
- /// @brief Reconfigures the process from a configuration file
- ///
- /// By default the file is assumed to be a JSON text file whose contents
- /// include at least:
- ///
- /// @code
- /// { "<module-name>": {<module-config>}
- ///
- /// # Logging element is optional
- /// ,"Logging": {<logger connfig}
- /// }
- ///
- /// where:
- /// module-name : is a label which uniquely identifies the
- /// configuration data for this controller's application
- ///
- /// module-config: a set of zero or more JSON elements which comprise
- /// the application's configuration values
- /// @endcode
- ///
- /// To translate the JSON content into Elements, @c parseFile() is called
- /// first. This virtual method provides derivations a means to parse the
- /// file content using an alternate parser. If it returns an empty pointer
- /// than the JSON parsing providing by Element::fromJSONFile() is called.
- ///
- /// Once parsed, the method looks for the Element "Logging" and, if present
- /// uses it to configure loging.
- ///
- /// It then extracts the set of configuration elements for the
- /// module-name that matches the controller's app_name_ and passes that
- /// set into @c updateConfig() (or @c checkConfig()).
- ///
- /// The file may contain an arbitrary number of other modules.
- ///
- /// @return returns an Element that contains the results of configuration
- /// update composed of an integer status value (0 means successful,
- /// non-zero means failure), and a string explanation of the outcome.
- virtual isc::data::ConstElementPtr configFromFile();
-
- /// @brief Fetches the name of the application under control.
- ///
- /// @return returns the controller service name string
- std::string getAppName() const {
- return (app_name_);
- }
-
- /// @brief Fetches the name of the application executable.
- ///
- /// @return returns the controller logger name string
- std::string getBinName() const {
- return (bin_name_);
- }
-
- /// @brief handler for version-get command
- ///
- /// This method handles the version-get command. It returns the basic and
- /// extended version.
- ///
- /// @param command (ignored)
- /// @param args (ignored)
- /// @return answer with version details.
- isc::data::ConstElementPtr
- versionGetHandler(const std::string& command,
- isc::data::ConstElementPtr args);
-
- /// @brief handler for 'build-report' command
- ///
- /// This method handles build-report command. It returns the output printed
- /// by configure script which contains most compilation parameters.
- ///
- /// @param command (ignored)
- /// @param args (ignored)
- /// @return answer with build report
- isc::data::ConstElementPtr
- buildReportHandler(const std::string& command,
- isc::data::ConstElementPtr args);
-
- /// @brief handler for config-get command
- ///
- /// This method handles the config-get command, which retrieves
- /// the current configuration and returns it in response.
- ///
- /// @param command (ignored)
- /// @param args (ignored)
- /// @return current configuration wrapped in a response
- isc::data::ConstElementPtr
- configGetHandler(const std::string& command,
- isc::data::ConstElementPtr args);
-
- /// @brief handler for config-write command
- ///
- /// This handle processes write-config comamnd, which writes the
- /// current configuration to disk. This command takes one optional
- /// parameter called filename. If specified, the current configuration
- /// will be written to that file. If not specified, the file used during
- /// Kea start-up will be used. To avoid any exploits, the path is
- /// always relative and .. is not allowed in the filename. This is
- /// a security measure against exploiting file writes remotely.
- ///
- /// @param command (ignored)
- /// @param args may contain optional string argument filename
- /// @return status of the configuration file write
- isc::data::ConstElementPtr
- configWriteHandler(const std::string& command,
- isc::data::ConstElementPtr args);
-
- /// @brief handler for config-test command
- ///
- /// This method handles the config-test command, which checks
- /// configuration specified in args parameter.
- ///
- /// @param command (ignored)
- /// @param args configuration to be checked.
- /// @return status of the command
- isc::data::ConstElementPtr
- configTestHandler(const std::string& command,
- isc::data::ConstElementPtr args);
-
- /// @brief handler for 'shutdown' command
- ///
- /// This method handles shutdown command. It initiates the shutdown procedure
- /// using CPL methods.
- /// @param command (ignored)
- /// @param args (ignored)
- /// @return answer confirming that the shutdown procedure is started
- isc::data::ConstElementPtr
- shutdownHandler(const std::string& command,
- isc::data::ConstElementPtr args);
-
-protected:
- /// @brief Virtual method that provides derivations the opportunity to
- /// support additional command line options. It is invoked during command
- /// line argument parsing (see parseArgs method) if the option is not
- /// recognized as a stock DControllerBase option.
- ///
- /// @param option is the option "character" from the command line, without
- /// any prefixing hyphen(s)
- /// @param optarg is the argument value (if one) associated with the option
- ///
- /// @return must return true if the option was valid, false if it is
- /// invalid. (Note the default implementation always returns false.)
- virtual bool customOption(int option, char *optarg);
-
- /// @brief Abstract method that is responsible for instantiating the
- /// application process object. It is invoked by the controller after
- /// command line argument parsing as part of the process initialization
- /// (see initProcess method).
- ///
- /// @return returns a pointer to the new process object (DProcessBase*)
- /// or NULL if the create fails.
- /// Note this value is subsequently wrapped in a smart pointer.
- virtual DProcessBase* createProcess() = 0;
-
- /// @brief Virtual method which can be used to contribute derivation
- /// specific usage text. It is invoked by the usage() method under
- /// invalid usage conditions.
- ///
- /// @return returns the desired text.
- virtual const std::string getUsageText() const {
- return ("");
- }
-
- /// @brief Virtual method which returns a string containing the option
- /// letters for any custom command line options supported by the derivation.
- /// These are added to the stock options of "c", "d", ..., during command
- /// line interpretation.
- ///
- /// @return returns a string containing the custom option letters.
- virtual const std::string getCustomOpts() const {
- return ("");
- }
-
- /// @brief Check the configuration
- ///
- /// Called by @c launch() when @c check_only_ mode is enabled
- /// @throw VersionMessage when successful but a message should be displayed
- /// @throw InvalidUsage when an error was detected
- void checkConfigOnly();
-
- /// @brief Application-level signal processing method.
- ///
- /// This method is the last step in processing a OS signal occurrence. It
- /// is invoked when an IOSignal's internal timer callback is executed by
- /// IOService. It currently supports the following signals as follows:
- /// -# SIGHUP - instigates reloading the configuration file
- /// -# SIGINT - instigates a graceful shutdown
- /// -# SIGTERM - instigates a graceful shutdown
- /// If it receives any other signal, it will issue a debug statement and
- /// discard it.
- /// Derivations wishing to support additional signals could override this
- /// method with one that: processes the signal if it is one of additional
- /// signals, otherwise invoke this method (DControllerBase::processSignal())
- /// with the signal value.
- /// @todo Provide a convenient way for derivations to register additional
- /// signals.
- virtual void processSignal(int signum);
-
- /// @brief Supplies whether or not verbose logging is enabled.
- ///
- /// @return returns true if verbose logging is enabled.
- bool isVerbose() const {
- return (verbose_);
- }
-
- /// @brief Method for enabling or disabling verbose logging.
- ///
- /// @param value is the new value to assign the flag.
- void setVerbose(bool value) {
- verbose_ = value;
- }
-
- /// @brief Supplies whether or not check only mode is enabled.
- ///
- /// @return returns true if check only is enabled.
- bool isCheckOnly() const {
- return (check_only_);
- }
-
- /// @brief Method for enabling or disabling check only mode.
- ///
- /// @todo this method and @c setVerbose are currently not used.
- ///
- /// @param value is the new value to assign the flag.
- void setCheckOnly(bool value) {
- check_only_ = value;
- }
-
- /// @brief Getter for fetching the controller's IOService
- ///
- /// @return returns a pointer reference to the IOService.
- asiolink::IOServicePtr& getIOService() {
- return (io_service_);
- }
-
- /// @brief Getter for fetching the name of the controller's config spec
- /// file.
- ///
- /// @return returns the file name string.
- const std::string getSpecFileName() const {
- return (spec_file_name_);
- }
-
- /// @brief Setter for setting the name of the controller's config spec file.
- ///
- /// @param spec_file_name the file name string.
- void setSpecFileName(const std::string& spec_file_name) {
- spec_file_name_ = spec_file_name;
- }
-
- /// @brief Static getter which returns the singleton instance.
- ///
- /// @return returns a pointer reference to the private singleton instance
- /// member.
- static DControllerBasePtr& getController() {
- return (controller_);
- }
-
- /// @brief Static setter which sets the singleton instance.
- ///
- /// @param controller is a pointer to the singleton instance.
- ///
- /// @throw throws DControllerBase error if an attempt is made to set the
- /// instance a second time.
- static void setController(const DControllerBasePtr& controller);
-
- /// @brief Processes the command line arguments. It is the first step
- /// taken after the controller has been launched. It combines the stock
- /// list of options with those returned by getCustomOpts(), and uses
- /// cstdlib's getopt to loop through the command line.
- /// It handles stock options directly, and passes any custom options into
- /// the customOption method. Currently there are only some stock options
- /// -c/t for specifying the configuration file, -d for verbose logging,
- /// and -v/V/W for version reports.
- ///
- /// @param argc is the number of command line arguments supplied
- /// @param argv is the array of string (char *) command line arguments
- ///
- /// @throw InvalidUsage when there are usage errors.
- /// @throw VersionMessage if the -v, -V or -W arguments is given.
- void parseArgs(int argc, char* argv[]);
-
-
- ///@brief Parse a given file into Elements
- ///
- /// This method provides a means for deriving classes to use alternate
- /// parsing mechanisms to parse configuration files into the corresponding
- /// isc::data::Elements. The elements produced must be equivalent to those
- /// which would be produced by the original JSON parsing. Implementations
- /// should throw when encountering errors.
- ///
- /// The default implementation returns an empty pointer, signifying to
- /// callers that they should submit the file to the original parser.
- ///
- /// @param file_name pathname of the file to parse
- ///
- /// @return pointer to the elements created
- ///
- virtual isc::data::ConstElementPtr parseFile(const std::string& file_name);
-
- ///@brief Parse text into Elements
- ///
- /// This method provides a means for deriving classes to use alternate
- /// parsing mechanisms to parse configuration text into the corresponding
- /// isc::data::Elements. The elements produced must be equivalent to those
- /// which would be produced by the original JSON parsing. Implementations
- /// should throw when encountering errors.
- ///
- /// The default implementation returns an empty pointer, signifying to
- /// callers that they should submit the text to the original parser.
- ///
- /// @param input text to parse
- ///
- /// @return pointer to the elements created
- ///
- virtual isc::data::ConstElementPtr parseText(const std::string& input) {
- static_cast<void>(input); // just tu shut up the unused parameter warning
- isc::data::ConstElementPtr elements;
- return (elements);
- }
-
- /// @brief Instantiates the application process and then initializes it.
- /// This is the second step taken during launch, following successful
- /// command line parsing. It is used to invoke the derivation-specific
- /// implementation of createProcess, following by an invoking of the
- /// newly instantiated process's init method.
- ///
- /// @throw throws DControllerBaseError or indirectly DProcessBaseError
- /// if there is a failure creating or initializing the application process.
- void initProcess();
-
- /// @brief Invokes the application process's event loop,(DBaseProcess::run).
- /// It is called during launch only after successfully completing the
- /// requested setup: command line parsing, application initialization,
- /// and session establishment (if not stand-alone).
- /// The process event loop is expected to only return upon application
- /// shutdown either in response to the shutdown command or due to an
- /// unrecoverable error.
- ///
- // @throw throws DControllerBaseError or indirectly DProcessBaseError
- void runProcess();
-
- /// @brief Initiates shutdown procedure. This method is invoked
- /// by executeCommand in response to the shutdown command. It will invoke
- /// the application process's shutdown method which causes the process to
- /// to begin its shutdown process.
- ///
- /// Note, it is assumed that the process of shutting down is neither
- /// instantaneous nor synchronous. This method does not "block" waiting
- /// until the process has halted. Rather it is used to convey the
- /// need to shutdown. A successful return indicates that the shutdown
- /// has successfully commenced, but does not indicate that the process
- /// has actually exited.
- ///
- /// @return returns an Element that contains the results of shutdown
- /// command composed of an integer status value (0 means successful,
- /// non-zero means failure), and a string explanation of the outcome.
- ///
- /// @param args is a set of derivation-specific arguments (if any)
- /// for the shutdown command.
- isc::data::ConstElementPtr shutdownProcess(isc::data::ConstElementPtr args);
-
- /// @brief Initializes signal handling
- ///
- /// This method configures the controller to catch and handle signals.
- /// It instantiates an IOSignalQueue, registers @c osSignalHandler() as
- /// the SignalSet "on-receipt" handler, and lastly instantiates a SignalSet
- /// which listens for SIGHUP, SIGINT, and SIGTERM.
- void initSignalHandling();
-
- /// @brief Handler for processing OS-level signals
- ///
- /// This method is installed as the SignalSet "on-receipt" handler. Upon
- /// invocation, it uses the controller's IOSignalQueue to schedule an
- /// IOSignal with for the given signal value.
- ///
- /// @param signum OS signal value (e.g. SIGINT, SIGUSR1 ...) to received
- ///
- /// @return SignalSet "on-receipt" handlers are required to return a
- /// boolean indicating if the OS signal has been processed (true) or if it
- /// should be saved for deferred processing (false). Currently this
- /// method processes all received signals, so it always returns true.
- bool osSignalHandler(int signum);
-
- /// @brief Handler for processing IOSignals
- ///
- /// This method is supplied as the callback when IOSignals are scheduled.
- /// It fetches the IOSignal for the given sequence_id and then invokes
- /// the virtual method, @c processSignal() passing it the signal value
- /// obtained from the IOSignal. This allows derivations to supply a
- /// custom signal processing method, while ensuring IOSignalQueue
- /// integrity.
- ///
- /// @param sequence_id id of the IOSignal instance "received"
- void ioSignalHandler(IOSignalId sequence_id);
-
- /// @brief Fetches the current process
- ///
- /// @return a pointer to the current process instance.
- DProcessBasePtr getProcess() {
- return (process_);
- }
-
- /// @brief Prints the program usage text to std error.
- ///
- /// @param text is a string message which will preceded the usage text.
- /// This is intended to be used for specific usage violation messages.
- void usage(const std::string& text);
-
- /// @brief Fetches text containing additional version specifics
- ///
- /// This method is provided so derivations can append any additional
- /// desired information such as library dependencies to the extended
- /// version text returned when DControllerBase::getVersion(true) is
- /// invoked.
- /// @return a string containing additonal version info
- virtual std::string getVersionAddendum() { return (""); }
-
-private:
- /// @brief Name of the service under control.
- /// This name is used as the configuration module name and appears in log
- /// statements.
- std::string app_name_;
-
- /// @brief Name of the service executable.
- /// By convention this matches the executable name. It is also used to
- /// establish the logger name.
- std::string bin_name_;
-
- /// @brief Indicates if the verbose logging mode is enabled.
- bool verbose_;
-
- /// @brief Indicates if the check only mode for the configuration
- /// is enabled (usually specified by the command line -t argument).
- bool check_only_;
-
- /// @brief The absolute file name of the JSON spec file.
- std::string spec_file_name_;
-
- /// @brief Pointer to the instance of the process.
- ///
- /// This is required for config and command handlers to gain access to
- /// the process
- DProcessBasePtr process_;
-
- /// @brief Shared pointer to an IOService object, used for ASIO operations.
- asiolink::IOServicePtr io_service_;
-
- /// @brief Queue for propagating caught signals to the IOService.
- IOSignalQueuePtr io_signal_queue_;
-
- /// @brief Singleton instance value.
- static DControllerBasePtr controller_;
-
-// DControllerTest is named a friend class to facilitate unit testing while
-// leaving the intended member scopes intact.
-friend class DControllerTest;
-};
-
-}; // namespace isc::process
-}; // namespace isc
-
-#endif
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <client/executor.h>
+#include <client/clnt_process.h>
+#include <cc/command_interpreter.h>
+
+using namespace isc::process;
+
+namespace isc {
+namespace client {
+
+const char* Executor::name_("kea-client");
+
+Executor::Executor()
+ : DControllerBase(name_, name_) {
+}
+
+DControllerBasePtr&
+Executor::instance() {
+ // If the instance hasn't been created yet, create it. Note this method
+ // must use the base class singleton instance methods.
+ if (!getController()) {
+ DControllerBasePtr controller_ptr(new Executor());
+ setController(controller_ptr);
+ }
+
+ return (getController());
+}
+
+DProcessBase* Executor::createProcess() {
+ // Instantiate and return an instance of the D2 application process. Note
+ // that the process is passed the controller's io_service.
+ return (new ClntProcess(getAppName().c_str(), getIOService()));
+}
+
+
+isc::data::ConstElementPtr
+Executor::parseFile(const std::string& file_name) {
+ return (config::createAnswer(3, "sorry, not implemented"));
+}
+
+};
+};
--- /dev/null
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef CLNT_EXECUTOR_H
+#define CLNT_EXECUTOR_H
+
+
+// One of the client requirements is to keep its footprint small. We can't use
+// the DControllerBase until the mess with its dependencies is sorted out.
+// See all the crap in libkea_process_la_LIBADD in src/lib/process/Makefile.am
+// and make your own opinion.
+#include <process/d_controller.h>
+
+namespace isc {
+namespace client {
+
+/// @brief Process Controller for the client process
+///
+/// This class is the client specific derivation of DControllerBase. It
+/// creates and manages an instance of the client application process,
+/// D2Process.
+///
+/// @todo Currently, this class provides only the minimum required specialized
+/// behavior to run the client service. It may very well expand as the
+/// service implementation evolves. Some thought was given to making
+/// DControllerBase a templated class but the labor savings versus the
+/// potential number of virtual methods which may be overridden didn't seem
+/// worth the clutter at this point.
+class Executor : public process::DControllerBase {
+public:
+ /// @brief Static singleton instance method. This method returns the
+ /// base class singleton instance member. It instantiates the singleton
+ /// and sets the base class instance member upon first invocation.
+ ///
+ /// @return returns the pointer reference to the singleton instance.
+ static process::DControllerBasePtr& instance();
+
+ /// @brief Destructor.
+ virtual ~Executor() {}
+
+ static const char* name_;
+
+private:
+ /// @brief Creates an instance of the DHCP-DDNS specific application
+ /// process. This method is invoked during the process initialization
+ /// step of the controller launch.
+ ///
+ /// @return returns a DProcessBase* to the application process created.
+ /// Note the caller is responsible for destructing the process. This
+ /// is handled by the base class, which wraps this pointer with a smart
+ /// pointer.
+ virtual process::DProcessBase* createProcess();
+
+ ///@brief Parse a given file into Elements
+ ///
+ /// Uses bison parsing to parse a JSON configuration file into an
+ /// a element map.
+ ///
+ /// @param file_name pathname of the file to parse
+ ///
+ /// @return pointer to the map of elements created
+ /// @throw BadValue if the file is empty
+ virtual isc::data::ConstElementPtr parseFile(const std::string& file_name);
+
+ /// @brief Constructor is declared private to maintain the integrity of
+ /// the singleton instance.
+ Executor();
+};
+
+}; // namespace isc::d2
+}; // namespace isc
+
+#endif
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
-#include <client/clnt_controller.h>
+#include <client/executor.h>
+#include <client/clnt_config.h>
#include <exceptions/exceptions.h>
#include <iostream>
// Launch the controller passing in command line arguments.
// Exit program with the controller's return code.
try {
+
+ //ClntConfig cfg;
+ //std::cout << cfg.toElement()->str() << std::endl;
+
// Instantiate/fetch the client application controller singleton.
- DControllerBasePtr& controller = ClntController::instance();
+ DControllerBasePtr& controller = Executor::instance();
// 'false' value disables test mode.
controller->launch(argc, argv, false);