From: Thomas Markwalder Date: Wed, 5 Jun 2013 19:01:24 +0000 (-0400) Subject: [2956] Changes to address review comments. Note that the module name is X-Git-Tag: bind10-1.2.0beta1-release~421^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=21f3ea90672b5bf84886e58f08f97bbcc63dfd6d;p=thirdparty%2Fkea.git [2956] Changes to address review comments. Note that the module name is now b10-dhcp-ddns. --- diff --git a/src/bin/d2/Makefile.am b/src/bin/d2/Makefile.am index c18e4ddf99..97bc249efe 100644 --- a/src/bin/d2/Makefile.am +++ b/src/bin/d2/Makefile.am @@ -18,15 +18,15 @@ pkglibexecdir = $(libexecdir)/@PACKAGE@ CLEANFILES = *.gcno *.gcda spec_config.h d2_messages.h d2_messages.cc -man_MANS = b10-d2.8 +man_MANS = b10-dhcp-ddns.8 DISTCLEANFILES = $(man_MANS) -EXTRA_DIST = $(man_MANS) b10-d2.xml d2.spec +EXTRA_DIST = $(man_MANS) b10-dhcp-ddns.xml dhcp-ddns.spec if GENERATE_DOCS -b10-d2.8: b10-d2.xml +b10-dhcp-ddns.8: b10-dhcp-ddns.xml @XSLTPROC@ --novalid --xinclude --nonet -o $@ \ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl \ - $(srcdir)/b10-d2.xml + $(srcdir)/b10-dchdp-ddns.xml else @@ -44,23 +44,23 @@ d2_messages.h d2_messages.cc: d2_messages.mes BUILT_SOURCES = spec_config.h d2_messages.h d2_messages.cc -pkglibexec_PROGRAMS = b10-d2 +pkglibexec_PROGRAMS = b10-dhcp-ddns -b10_d2_SOURCES = main.cc -b10_d2_SOURCES += d2_log.cc d2_log.h -b10_d2_SOURCES += d_process.h -b10_d2_SOURCES += d2_process.cc d2_process.h -b10_d2_SOURCES += d_controller.cc d_controller.h -b10_d2_SOURCES += d2_controller.cc d2_controller.h +b10_dhcp_ddns_SOURCES = main.cc +b10_dhcp_ddns_SOURCES += d2_log.cc d2_log.h +b10_dhcp_ddns_SOURCES += d_process.h +b10_dhcp_ddns_SOURCES += d2_process.cc d2_process.h +b10_dhcp_ddns_SOURCES += d_controller.cc d_controller.h +b10_dhcp_ddns_SOURCES += d2_controller.cc d2_controller.h -nodist_b10_d2_SOURCES = d2_messages.h d2_messages.cc +nodist_b10_dhcp_ddns_SOURCES = d2_messages.h d2_messages.cc EXTRA_DIST += d2_messages.mes -b10_d2_LDADD = $(top_builddir)/src/lib/log/libb10-log.la -b10_d2_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la -b10_d2_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la -b10_d2_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la -b10_d2_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la +b10_dhcp_ddns_LDADD = $(top_builddir)/src/lib/log/libb10-log.la +b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la +b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la +b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la +b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la -b10_d2dir = $(pkgdatadir) -b10_d2_DATA = d2.spec +b10_dhcp_ddnsdir = $(pkgdatadir) +b10_dhcp_ddns_DATA = dhcp-ddns.spec diff --git a/src/bin/d2/b10-d2.xml b/src/bin/d2/b10-dhcp-ddns.xml similarity index 88% rename from src/bin/d2/b10-d2.xml rename to src/bin/d2/b10-dhcp-ddns.xml index 2202685b02..7867d1ba3c 100644 --- a/src/bin/d2/b10-d2.xml +++ b/src/bin/d2/b10-dhcp-ddns.xml @@ -24,13 +24,13 @@ - b10-d2 + b10-dhcp-ddns 8 BIND10 - b10-d2 + b10-dhcp-ddns D2 process in BIND 10 architecture @@ -43,14 +43,14 @@ - b10-d2 + b10-dhcp-ddns - b10-d2 + b10-dhcp-ddns @@ -59,7 +59,7 @@ DESCRIPTION - The b10-d2 daemon processes requests to + The b10-dhcp-ddns daemon processes requests to to update DNS mapping based on DHCP lease change events. @@ -95,7 +95,7 @@ SEE ALSO - b10-d28 + b10-dhcp-ddns8 , bind108 @@ -106,7 +106,7 @@ HISTORY - The b10-d2 process was first coded in + The b10-dhcp-ddns process was first coded in May 2013 by the ISC Kea/Dhcp team. diff --git a/src/bin/d2/d2_controller.cc b/src/bin/d2/d2_controller.cc index 07a95375af..d5b34940de 100644 --- a/src/bin/d2/d2_controller.cc +++ b/src/bin/d2/d2_controller.cc @@ -23,10 +23,11 @@ DControllerBasePtr& D2Controller::instance() { // If the instance hasn't been created yet, create it. Note this method // must use the base class singleton instance methods. The base class - // must own the singleton in order to use it within BIND10 static function - // callbacks. + // must have access to the singleton in order to use it within BIND10 + // static function callbacks. if (!getController()) { - setController(new D2Controller()); + DControllerBasePtr controller_ptr(new D2Controller()); + setController(controller_ptr); } return (getController()); diff --git a/src/bin/d2/d2_log.cc b/src/bin/d2/d2_log.cc index 40812e3fbf..96803d864f 100644 --- a/src/bin/d2/d2_log.cc +++ b/src/bin/d2/d2_log.cc @@ -21,7 +21,7 @@ namespace d2 { /// @brief Defines the service name which is used in the controller constructor /// and ultimately defines the BIND10 module name. -const char* const D2_MODULE_NAME = "b10-d2"; +const char* const D2_MODULE_NAME = "b10-dhpc-ddns"; /// @brief Defines the logger used within D2. isc::log::Logger d2_logger(D2_MODULE_NAME); diff --git a/src/bin/d2/d2_messages.mes b/src/bin/d2/d2_messages.mes index 86d8996285..82430a52d3 100644 --- a/src/bin/d2/d2_messages.mes +++ b/src/bin/d2/d2_messages.mes @@ -27,11 +27,11 @@ This is a debug message issued when the service process has been instructed to shut down by the controller. % D2PRC_PROCESS_INIT DHCP-DDNS application init invoked -This is a debug message issued when the D2 process enters it's +This is a debug message issued when the D2 process enters its init method. % D2PRC_RUN_ENTER process has entered the event loop -This is a debug message issued when the D2 process enters it's +This is a debug message issued when the D2 process enters its run method. % D2PRC_RUN_EXIT process is exiting the event loop @@ -52,15 +52,17 @@ has been invoked. % D2CTL_INIT_PROCESS initializing application proces This debug message is issued just before the controller attempts -to create and initialize it's process instance. +to create and initialize its process instance. % D2CTL_SESSION_FAIL failed to establish BIND 10 session: %1 The controller has failed to establish communication with the rest of BIND 10 and will exit. % D2CTL_DISCONNECT_FAIL failed to disconnect from BIND 10 session: %1 -The controller has failed to terminate communication with the rest of BIND -10. +This message indicates that while shutting down, the DHCP-DDNS controller +encountered an error terminating communication with the BIND10. The service +will still exit. While theoretically possible, this situation is rather +unlikely. % D2CTL_STANDALONE skipping message queue, running standalone This is a debug message indicating that the controller is running in the diff --git a/src/bin/d2/d2_process.cc b/src/bin/d2/d2_process.cc index be282838a2..293feceb93 100644 --- a/src/bin/d2/d2_process.cc +++ b/src/bin/d2/d2_process.cc @@ -45,7 +45,7 @@ D2Process::run() { } catch (const std::exception& ex) { LOG_FATAL(d2_logger, D2PRC_FAILED).arg(ex.what()); isc_throw (DProcessBaseError, - std::string("Process run method failed:") + ex.what()); + "Process run method failed:" << ex.what()); } } diff --git a/src/bin/d2/d_controller.cc b/src/bin/d2/d_controller.cc index eb83225ee2..e2bf06c35a 100644 --- a/src/bin/d2/d_controller.cc +++ b/src/bin/d2/d_controller.cc @@ -32,7 +32,7 @@ DControllerBase::DControllerBase(const char* name) } void -DControllerBase::setController(DControllerBase* controller) { +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. @@ -40,41 +40,34 @@ DControllerBase::setController(DControllerBase* controller) { "Multiple controller instances attempted."); } - controller_ = DControllerBasePtr(controller); + controller_ = controller; } -int +void DControllerBase::launch(int argc, char* argv[]) { - int ret = d2::NORMAL_EXIT; - // Step 1 is to parse the command line arguments. try { parseArgs(argc, argv); } catch (const InvalidUsage& ex) { usage(ex.what()); - return (d2::INVALID_USAGE); + throw; // rethrow it } -#if 1 - //@TODO During initial development default to max log, no buffer - isc::log::initLogger(name_, isc::log::DEBUG, - isc::log::MAX_DEBUG_LEVEL, NULL, false); -#else // Now that we know what the mode flags are, we can init logging. // If standalone is enabled, do not buffer initial log messages isc::log::initLogger(name_, ((verbose_ && stand_alone_) ? isc::log::DEBUG : isc::log::INFO), isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone_); -#endif LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_STARTING).arg(getpid()); try { - // Step 2 is to create and initialize the application process. + // Step 2 is to create and initialize the application process object. initProcess(); } catch (const std::exception& ex) { - LOG_ERROR(d2_logger, D2CTL_SESSION_FAIL).arg(ex.what()); - return (PROCESS_INIT_ERROR); + LOG_FATAL(d2_logger, D2CTL_INIT_PROCESS).arg(ex.what()); + isc_throw (ProcessInitError, + "Application Process initialization failed:" << ex.what()); } // Next we connect if we are running integrated. @@ -84,8 +77,9 @@ DControllerBase::launch(int argc, char* argv[]) { try { establishSession(); } catch (const std::exception& ex) { - LOG_ERROR(d2_logger, D2CTL_SESSION_FAIL).arg(ex.what()); - return (d2::SESSION_START_ERROR); + LOG_FATAL(d2_logger, D2CTL_SESSION_FAIL).arg(ex.what()); + isc_throw (SessionStartError, + "Session start up failed:" << ex.what()); } } @@ -95,24 +89,25 @@ DControllerBase::launch(int argc, char* argv[]) { runProcess(); } catch (const std::exception& ex) { LOG_FATAL(d2_logger, D2CTL_FAILED).arg(ex.what()); - ret = d2::RUN_ERROR; + isc_throw (ProcessRunError, + "Application process event loop failed:" << ex.what()); } - // If running integrated, always try to disconnect. + // If running integrated, disconnect. if (!stand_alone_) { try { disconnectSession(); } catch (const std::exception& ex) { LOG_ERROR(d2_logger, D2CTL_DISCONNECT_FAIL).arg(ex.what()); - ret = d2::SESSION_END_ERROR; + isc_throw (SessionEndError, "Session end failed:" << ex.what()); } } // All done, so bail out. LOG_INFO(d2_logger, D2CTL_STOPPING); - return (ret); } + void DControllerBase::parseArgs(int argc, char* argv[]) { @@ -137,11 +132,10 @@ DControllerBase::parseArgs(int argc, char* argv[]) case '?': { // We hit an invalid option. - std::stringstream tmp; - tmp << " unsupported option: [" << (char)optopt << "] " - << (!optarg ? "" : optarg); + isc_throw(InvalidUsage, "unsupported option: [" + << static_cast(optopt) << "] " + << (!optarg ? "" : optarg)); - isc_throw(InvalidUsage,tmp.str()); break; } @@ -149,10 +143,9 @@ DControllerBase::parseArgs(int argc, char* argv[]) // We hit a valid custom option if (!customOption(ch, optarg)) { // This would be a programmatic error. - std::stringstream tmp; - tmp << " Option listed but implemented?: [" << - (char)ch << "] " << (!optarg ? "" : optarg); - isc_throw(InvalidUsage,tmp.str()); + isc_throw(InvalidUsage, " Option listed but implemented?: [" + << static_cast(ch) << "] " + << (!optarg ? "" : optarg)); } break; } @@ -160,9 +153,7 @@ DControllerBase::parseArgs(int argc, char* argv[]) // There was too much information on the command line. if (argc > optind) { - std::stringstream tmp; - tmp << "extraneous command line information"; - isc_throw(InvalidUsage,tmp.str()); + isc_throw(InvalidUsage, "extraneous command line information"); } } @@ -181,13 +172,13 @@ DControllerBase::initProcess() { try { process_.reset(createProcess()); } catch (const std::exception& ex) { - isc_throw (DControllerBaseError, std::string("createProcess failed:") - + ex.what()); + 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"); + isc_throw(DControllerBaseError, "createProcess returned NULL"); } // Invoke application's init method (Note this call should throw @@ -300,7 +291,7 @@ DControllerBase::configHandler(isc::data::ConstElementPtr new_config) { // Static callback which invokes non-static handler on singleton isc::data::ConstElementPtr DControllerBase::commandHandler(const std::string& command, - isc::data::ConstElementPtr args) { + isc::data::ConstElementPtr args) { LOG_DEBUG(d2_logger, DBGLVL_COMMAND, D2CTL_COMMAND_RECEIVED) .arg(command).arg(args->str()); @@ -403,14 +394,6 @@ DControllerBase::customControllerCommand(const std::string& command, isc::data::ConstElementPtr DControllerBase::shutdown() { - // @TODO (tmark) - not sure about io_service_->stop here - // IF application is using this service for all of its IO, stopping - // here would mean, no more work by the application.. UNLESS it resets - // it. People have discussed letting the application finish any in-progress - // updates before shutting down. If we don't stop it here, then - // application can't use io_service_->run(), it will never "see" the - // shutdown. - io_service_->stop(); if (process_) { process_->shutdown(); } else { diff --git a/src/bin/d2/d_controller.h b/src/bin/d2/d_controller.h index db371a10ef..8d3094ec8e 100644 --- a/src/bin/d2/d_controller.h +++ b/src/bin/d2/d_controller.h @@ -35,19 +35,6 @@ namespace d2 { /// normal or otherwise, the Controller's launch method will return one of /// these values. -/// @brief Indicates normal shutdown. -static const int NORMAL_EXIT = 0; -/// @brief Indicates invalid command line. -static const int INVALID_USAGE = 1; -/// @brief Failed to create and initialize application process. -static const int PROCESS_INIT_ERROR = 2; -/// @brief Could not connect to BIND10 (integrated mode only). -static const int SESSION_START_ERROR = 3; -/// @brief A fatal error occurred in the application process. -static const int RUN_ERROR = 4; -/// @brief Error occurred disconnecting from BIND10 (integrated mode only). -static const int SESSION_END_ERROR = 5; - /// @brief Exception thrown when the command line is invalid. class InvalidUsage : public isc::Exception { public: @@ -55,6 +42,36 @@ public: 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 session start up fails. +class SessionStartError: public isc::Exception { +public: + SessionStartError (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 session end fails. +class SessionEndError: public isc::Exception { +public: + SessionEndError (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: @@ -82,15 +99,24 @@ typedef boost::shared_ptr ModuleCCSessionPtr; /// integrated mode as a BIND10 module or stand-alone. It coordinates command /// line argument parsing, process instantiation and initialization, and runtime /// control through external command and configuration event handling. -/// It creates the io_service_ instance which is used for runtime control -/// events and passes the io_service into the application process at process +/// It creates the IOService instance which is used for runtime control +/// events and passes the IOService into the application process at process /// creation. In integrated mode it is responsible for establishing BIND10 -/// session(s) and passes this io_service_ into the session creation method(s). -/// It also provides the callback handlers for command and configuration events. +/// session(s) and passes this IOService into the session creation method(s). +/// It also provides the callback handlers for command and configuration events +/// received from the external framework (aka BIND10). For example, when +/// running in integrated mode and a user alters the configuration with the +/// bindctl tool, BIND10 will emit a configuration message which is sensed by +/// the controller's IOService. The IOService in turn invokes the configuration +/// callback, DControllerBase::configHandler(). If the user issues a command +/// such as shutdown via bindctl, BIND10 will emit a command message, which is +/// sensed by controller's IOService which invokes the command callback, +/// DControllerBase::commandHandler(). +/// /// 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 BIND10 callback functions. This -/// would not be required if BIND10 supported instance method callbacks. +/// would not be required if BIND10 supported instance method callbacks. class DControllerBase : public boost::noncopyable { public: /// @brief Constructor @@ -119,16 +145,16 @@ public: /// @param argc is the number of command line arguments supplied /// @param argv is the array of string (char *) command line arguments /// - /// @return returns one of the following integer values: - /// d2::NORMAL_EXIT - Indicates normal shutdown. - /// d2::INVALID_USAGE - Indicates invalid command line. - /// d2::PROCESS_INIT_ERROR - Failed to create and initialize application - /// process - /// d2::SESSION_START_ERROR - Could not connect to BIND10 (integrated mode + /// @throw throws one of the following exceptions: + /// InvalidUsage - Indicates invalid command line. + /// ProcessInitError - Failed to create and initialize application + /// process object. + /// SessionStartError - Could not connect to BIND10 (integrated mode only). + /// ProcessRunError - A fatal error occurred while in the application + /// process event loop. + /// SessionEndError - Could not disconnect from BIND10 (integrated mode /// only). - /// d2::RUN_ERROR - An fatal error occurred in the application process - /// d2::SESSION_END_ERROR = 4; - int launch(int argc, char* argv[]); + void launch(int argc, char* argv[]); /// @brief A dummy configuration handler that always returns success. /// @@ -240,11 +266,11 @@ protected: virtual bool customOption(int option, char *optarg); /// @brief Abstract method that is responsible for instantiating the - /// application process instance. It is invoked by the controller after + /// 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 instance (DProcessBase*) + /// @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; @@ -294,7 +320,7 @@ protected: /// invalid usage conditions. /// /// @return returns the desired text. - virtual const std::string getUsageText() { + virtual const std::string getUsageText() const { return (""); } @@ -304,21 +330,21 @@ protected: /// line interpretation. /// /// @return returns a string containing the custom option letters. - virtual const std::string getCustomOpts() { + virtual const std::string getCustomOpts() const { return (""); } /// @brief Supplies the controller name. /// /// @return returns the controller name string - const std::string& getName() { + const std::string getName() const { return (name_); } /// @brief Supplies whether or not the controller is in stand alone mode. /// /// @return returns true if in stand alone mode, false otherwise - bool isStandAlone() { + const bool isStandAlone() const { return (stand_alone_); } @@ -332,7 +358,7 @@ protected: /// @brief Supplies whether or not verbose logging is enabled. /// /// @return returns true if verbose logging is enabled. - bool isVerbose() { + const bool isVerbose() const { return (verbose_); } @@ -354,7 +380,7 @@ protected: /// file. /// /// @return returns the file name string. - const std::string& getSpecFileName() { + const std::string getSpecFileName() const { return (spec_file_name_); } @@ -373,13 +399,13 @@ protected: return (controller_); } - /// @brief Static setter which returns the singleton instance. + /// @brief Static setter which sets the singleton instance. + /// + /// @param controller is a pointer to the singleton instance. /// - /// @return returns a pointer reference to the private singleton instance - /// member. /// @throw throws DControllerBase error if an attempt is made to set the /// instance a second time. - static void setController(DControllerBase* controller); + static void setController(const DControllerBasePtr& controller); private: /// @brief Processes the command line arguments. It is the first step @@ -452,7 +478,7 @@ private: /// /// @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); + void usage(const std::string& text); private: /// @brief Text label for the controller. Typically this would be the @@ -462,9 +488,10 @@ private: /// @brief Indicates if the controller stand alone mode is enabled. When /// enabled, the controller will not establish connectivity with BIND10. bool stand_alone_; - /// @brief Indicates if the verbose logging mode is enabled. + /// @brief Indicates if the verbose logging mode is enabled. bool verbose_; + /// @brief The absolute file name of the BIND10 spec file. std::string spec_file_name_; diff --git a/src/bin/d2/d_process.h b/src/bin/d2/d_process.h index 73bbc17ba3..018af6368b 100644 --- a/src/bin/d2/d_process.h +++ b/src/bin/d2/d_process.h @@ -72,20 +72,24 @@ public: /// to application. It must be invoked prior to invoking run. This would /// likely include the creation of additional IO sources and their /// integration into the io_service. - /// @throw throws a DProcessBaseError if the initialization fails. + /// @throw throws DProcessBaseError if the initialization fails. virtual void init() = 0; /// @brief Implements the process's event loop. In its simplest form it /// would an invocation io_service_->run(). This method should not exit /// until the process itself is exiting due to a request to shutdown or /// some anomaly is forcing an exit. - /// @throw throws a DProcessBaseError if an operational error is encountered. + /// @throw throws DProcessBaseError if an operational error is encountered. virtual void run() = 0; /// @brief Implements the process's shutdown processing. When invoked, it /// should ensure that the process gracefully exits the run method. - /// @throw throws a DProcessBaseError if an operational error is encountered. - virtual void shutdown() = 0; + /// The default implementation sets the shutdown flag and stops IOService. + /// @throw throws DProcessBaseError if an operational error is encountered. + virtual void shutdown() { + setShutdownFlag(true); + stopIOService(); + }; /// @brief Processes the given configuration. /// @@ -123,7 +127,7 @@ public: /// @brief Checks if the process has been instructed to shut down. /// /// @return returns true if process shutdown flag is true. - bool shouldShutdown() { + const bool shouldShutdown() const { return (shut_down_flag_); } @@ -137,7 +141,7 @@ public: /// @brief Fetches the name of the controller. /// /// @return returns a reference the controller's name string. - const std::string& getName() const { + const std::string getName() const { return (name_); } @@ -148,6 +152,14 @@ public: return (io_service_); } + /// @brief Convenience method for stopping IOservice processing. + /// Invoking this will cause the process to exit any blocking + /// IOService method such as run(). No further IO events will be + /// processed. + void stopIOService() { + io_service_->stop(); + } + private: /// @brief Text label for the process. Generally used in log statements, /// but otherwise can be arbitrary. diff --git a/src/bin/d2/d2.spec b/src/bin/d2/dhcp-ddns.spec similarity index 84% rename from src/bin/d2/d2.spec rename to src/bin/d2/dhcp-ddns.spec index 14b1e11eb3..c594f2b065 100644 --- a/src/bin/d2/d2.spec +++ b/src/bin/d2/dhcp-ddns.spec @@ -7,7 +7,7 @@ "commands": [ { "command_name": "shutdown", - "command_description": "Shut down the stats httpd", + "command_description": "Shut down the DHCP-DDNS service", "command_args": [ { "item_name": "pid", diff --git a/src/bin/d2/main.cc b/src/bin/d2/main.cc index e0e979b44b..fda31038e3 100644 --- a/src/bin/d2/main.cc +++ b/src/bin/d2/main.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -26,23 +27,22 @@ using namespace std; /// This file contains entry point (main() function) for standard DHCP-DDNS /// process, b10-dhcp-ddns, component for BIND10 framework. It fetches /// the D2Controller singleton instance and invokes its launch method. -/// The exit value of the program will the return value of launch: -/// d2::NORMAL_EXIT - Indicates normal shutdown. -/// d2::INVALID_USAGE - Indicates invalid command line. -/// d2::PROCESS_INIT_ERROR - Failed to create and initialize application -/// process -/// d2::SESSION_START_ERROR - Could not connect to BIND10 (integrated mode -/// only). -/// d2::RUN_ERROR - A fatal error occurred in the application process -/// d2::SESSION_END_ERROR - Error occurred disconnecting from BIND10 (integrated -/// mode only). -int -main(int argc, char* argv[]) { +/// The exit value of the program will be EXIT_SUCCESS if there were no +/// errors, EXIT_FAILURE otherwise. +int main(int argc, char* argv[]) { + int ret = EXIT_SUCCESS; // Instantiate/fetch the DHCP-DDNS application controller singleton. DControllerBasePtr& controller = D2Controller::instance(); // Launch the controller passing in command line arguments. // Exit program with the controller's return code. - return (controller->launch(argc, argv)); + try { + controller->launch(argc, argv); + } catch (const isc::Exception& ex) { + std::cerr << "Service failed:" << ex.what() << std::endl; + ret = EXIT_FAILURE; + } + + return (ret); } diff --git a/src/bin/d2/tests/d2_controller_unittests.cc b/src/bin/d2/tests/d2_controller_unittests.cc index c230e363f9..75a7f3bea0 100644 --- a/src/bin/d2/tests/d2_controller_unittests.cc +++ b/src/bin/d2/tests/d2_controller_unittests.cc @@ -81,7 +81,9 @@ TEST_F(D2ControllerTest, basicInstanceTesting) { /// 1. Standard command line options are supported. /// 2. Invalid options are detected. TEST_F(D2ControllerTest, commandLineArgs) { - char* argv[] = { (char*)"progName", (char*)"-s", (char*)"-v" }; + char* argv[] = { const_cast("progName"), + const_cast("-s"), + const_cast("-v") }; int argc = 3; // Verify that both flags are false initially. @@ -96,9 +98,10 @@ TEST_F(D2ControllerTest, commandLineArgs) { EXPECT_TRUE(checkVerbose(true)); // Verify that an unknown option is detected. - char* argv2[] = { (char*)"progName", (char*)"-x" }; + char* argv2[] = { const_cast("progName"), + const_cast("-x") }; argc = 2; - EXPECT_THROW (parseArgs(argc, argv2), InvalidUsage); + EXPECT_THROW(parseArgs(argc, argv2), InvalidUsage); } /// @brief Tests application process creation and initialization. @@ -111,10 +114,11 @@ TEST_F(D2ControllerTest, initProcessTesting) { /// @brief Tests launch and normal shutdown (stand alone mode). /// This creates an interval timer to generate a normal shutdown and then /// launches with a valid, stand-alone command line and no simulated errors. -/// Launch exit code should be d2::NORMAL_EXIT. TEST_F(D2ControllerTest, launchNormalShutdown) { // command line to run standalone - char* argv[] = { (char*)"progName", (char*)"-s", (char*)"-v" }; + char* argv[] = { const_cast("progName"), + const_cast("-s"), + const_cast("-v") }; int argc = 3; // Use an asiolink IntervalTimer and callback to generate the @@ -124,14 +128,11 @@ TEST_F(D2ControllerTest, launchNormalShutdown) { // Record start time, and invoke launch(). ptime start = microsec_clock::universal_time(); - int rcode = launch(argc, argv); + EXPECT_NO_THROW(launch(argc, argv)); // Record stop time. ptime stop = microsec_clock::universal_time(); - // Verify normal shutdown status. - EXPECT_EQ(d2::NORMAL_EXIT, rcode); - // Verify that duration of the run invocation is the same as the // timer duration. This demonstrates that the shutdown was driven // by an io_service event and callback. diff --git a/src/bin/d2/tests/d2_test.py b/src/bin/d2/tests/d2_test.py index bcf3815969..7011cfc3a5 100644 --- a/src/bin/d2/tests/d2_test.py +++ b/src/bin/d2/tests/d2_test.py @@ -159,7 +159,8 @@ class TestD2Daemon(unittest.TestCase): print("Note: Simple test to verify that D2 server can be started.") # note that "-s" for stand alone is necessary in order to flush the log output # soon enough to catch it. - (returncode, output, error) = self.runCommand(["../b10-d2", "-s", "-v"]) + (returncode, output, error) = self.runCommand(["../b10-dhcp-ddns", + "-s", "-v"]) output_text = str(output) + str(error) self.assertEqual(output_text.count("D2CTL_STARTING"), 1) diff --git a/src/bin/d2/tests/d_controller_unittests.cc b/src/bin/d2/tests/d_controller_unittests.cc index 69dcedc342..501fe134c4 100644 --- a/src/bin/d2/tests/d_controller_unittests.cc +++ b/src/bin/d2/tests/d_controller_unittests.cc @@ -78,7 +78,9 @@ TEST_F(DStubControllerTest, commandLineArgs) { EXPECT_TRUE(checkVerbose(false)); // Verify that standard options can be parsed without error. - char* argv[] = { (char*)"progName", (char*)"-s", (char*)"-v" }; + char* argv[] = { const_cast("progName"), + const_cast("-s"), + const_cast("-v") }; int argc = 3; EXPECT_NO_THROW(parseArgs(argc, argv)); @@ -87,23 +89,24 @@ TEST_F(DStubControllerTest, commandLineArgs) { EXPECT_TRUE(checkVerbose(true)); // Verify that the custom command line option is parsed without error. - char xopt[3]=""; - sprintf (xopt, "-%c", *DStubController::stub_option_x_); - char* argv1[] = { (char*)"progName", xopt}; + char xopt[3] = "- "; + xopt[1] = *DStubController::stub_option_x_; + char* argv1[] = { const_cast("progName"), xopt}; argc = 2; EXPECT_NO_THROW (parseArgs(argc, argv1)); // Verify that an unknown option is detected. - char* argv2[] = { (char*)"progName", (char*)"-bs" }; + char* argv2[] = { const_cast("progName"), + const_cast("-bs") }; argc = 2; EXPECT_THROW (parseArgs(argc, argv2), InvalidUsage); // Verify that extraneous information is detected. - char* argv3[] = { (char*)"progName", (char*)"extra", (char*)"information" }; + char* argv3[] = { const_cast("progName"), + const_cast("extra"), + const_cast("information") }; argc = 3; EXPECT_THROW (parseArgs(argc, argv3), InvalidUsage); - - } /// @brief Tests application process creation and initialization. @@ -141,44 +144,42 @@ TEST_F(DStubControllerTest, initProcessTesting) { } /// @brief Tests launch handling of invalid command line. -/// This test launches with an invalid command line which should exit with -/// an status of d2::INVALID_USAGE. +/// This test launches with an invalid command line which should throw +/// an InvalidUsage. TEST_F(DStubControllerTest, launchInvalidUsage) { // Command line to run integrated - char* argv[] = { (char*)"progName",(char*) "-z" }; + char* argv[] = { const_cast("progName"), + const_cast("-z") }; int argc = 2; // Launch the controller in integrated mode. - int rcode = launch(argc, argv); - - // Verify session failure exit status. - EXPECT_EQ(d2::INVALID_USAGE, rcode); + EXPECT_THROW(launch(argc, argv), InvalidUsage); } /// @brief Tests launch handling of failure in application process /// initialization. This test launches with a valid command line but with -/// SimFailure set to fail during process creation. Launch exit code should -/// be d2::PROCESS_INIT_ERROR. +/// SimFailure set to fail during process creation. Launch should throw +/// ProcessInitError. TEST_F(DStubControllerTest, launchProcessInitError) { // Command line to run integrated - char* argv[] = { (char*)"progName", (char*)"-s", (char*)"-v" }; + char* argv[] = { const_cast("progName"), + const_cast("-s"), + const_cast("-v") }; int argc = 3; // Launch the controller in stand alone mode. SimFailure::set(SimFailure::ftCreateProcessException); - int rcode = launch(argc, argv); - - // Verify session failure exit status. - EXPECT_EQ(d2::PROCESS_INIT_ERROR, rcode); + EXPECT_THROW(launch(argc, argv), ProcessInitError); } /// @brief Tests launch and normal shutdown (stand alone mode). /// This creates an interval timer to generate a normal shutdown and then /// launches with a valid, stand-alone command line and no simulated errors. -/// Launch exit code should be d2::NORMAL_EXIT. TEST_F(DStubControllerTest, launchNormalShutdown) { // command line to run standalone - char* argv[] = { (char*)"progName", (char*)"-s", (char*)"-v" }; + char* argv[] = { const_cast("progName"), + const_cast("-s"), + const_cast("-v") }; int argc = 3; // Use an asiolink IntervalTimer and callback to generate the @@ -188,14 +189,11 @@ TEST_F(DStubControllerTest, launchNormalShutdown) { // Record start time, and invoke launch(). ptime start = microsec_clock::universal_time(); - int rcode = launch(argc, argv); + EXPECT_NO_THROW(launch(argc, argv)); // Record stop time. ptime stop = microsec_clock::universal_time(); - // Verify normal shutdown status. - EXPECT_EQ(d2::NORMAL_EXIT, rcode); - // Verify that duration of the run invocation is the same as the // timer duration. This demonstrates that the shutdown was driven // by an io_service event and callback. @@ -207,10 +205,12 @@ TEST_F(DStubControllerTest, launchNormalShutdown) { /// @brief Tests launch with an operational error during application execution. /// This test creates an interval timer to generate a runtime exception during /// the process event loop. It launches wih a valid, stand-alone command line -/// and no simulated errors. Launch exit code should be d2::RUN_ERROR. +/// and no simulated errors. Launch should throw ProcessRunError. TEST_F(DStubControllerTest, launchRuntimeError) { // command line to run standalone - char* argv[] = { (char*)"progName", (char*)"-s", (char*)"-v" }; + char* argv[] = { const_cast("progName"), + const_cast("-s"), + const_cast("-v") }; int argc = 3; // Use an asiolink IntervalTimer and callback to generate the @@ -220,14 +220,11 @@ TEST_F(DStubControllerTest, launchRuntimeError) { // Record start time, and invoke launch(). ptime start = microsec_clock::universal_time(); - int rcode = launch(argc, argv); + EXPECT_THROW(launch(argc, argv), ProcessRunError); // Record stop time. ptime stop = microsec_clock::universal_time(); - // Verify abnormal shutdown status. - EXPECT_EQ(d2::RUN_ERROR, rcode); - // Verify that duration of the run invocation is the same as the // timer duration. This demonstrates that the shutdown was driven // by an io_service event and callback. @@ -239,18 +236,14 @@ TEST_F(DStubControllerTest, launchRuntimeError) { /// @brief Tests launch with a session establishment failure. /// This test launches with a valid command line for integrated mode and no. /// Attempting to connect to BIND10 should fail, even if BIND10 is running -/// UNLESS the test is run as root. Launch exit code should be -/// d2::SESSION_START_ERROR. +/// UNLESS the test is run as root. Launch should throw SessionStartError. TEST_F(DStubControllerTest, launchSessionFailure) { // Command line to run integrated char* argv[] = { (char*)"progName" }; int argc = 1; // Launch the controller in integrated mode. - int rcode = launch(argc, argv); - - // Verify session failure exit status. - EXPECT_EQ(d2::SESSION_START_ERROR, rcode); + EXPECT_THROW(launch(argc, argv), SessionStartError); } /// @brief Configuration update event testing. diff --git a/src/bin/d2/tests/d_test_stubs.cc b/src/bin/d2/tests/d_test_stubs.cc index 1b71e27509..f348dff30a 100644 --- a/src/bin/d2/tests/d_test_stubs.cc +++ b/src/bin/d2/tests/d_test_stubs.cc @@ -12,6 +12,7 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. +#include #include #include @@ -24,7 +25,7 @@ namespace d2 { SimFailure::FailureType SimFailure::failure_type_ = SimFailure::ftNoFailure; // Define custom process command supported by DStubProcess. -const std::string DStubProcess::stub_proc_command_("cool_proc_cmd"); +const char* DStubProcess::stub_proc_command_("cool_proc_cmd"); DStubProcess::DStubProcess(const char* name, IOServicePtr io_service) : DProcessBase(name, io_service) { @@ -69,7 +70,8 @@ DStubProcess::shutdown() { // Simulates a failure during shutdown process. isc_throw(DProcessBaseError, "DStubProcess simulated shutdown failure"); } - setShutdownFlag(true); + + DProcessBase::shutdown(); } isc::data::ConstElementPtr @@ -113,7 +115,7 @@ DStubProcess::~DStubProcess() { //************************** DStubController ************************* // Define custom controller command supported by DStubController. -const std::string DStubController::stub_ctl_command_("spiffy"); +const char* DStubController::stub_ctl_command_("spiffy"); // Define custom command line option command supported by DStubController. const char* DStubController::stub_option_x_ = "x"; @@ -122,7 +124,9 @@ DControllerBasePtr& DStubController::instance() { // If the singleton hasn't been created, do it now. if (!getController()) { - setController(new DStubController()); + //setController(new DStubController()); + DControllerBasePtr p(new DStubController()); + setController(p); } return (getController()); @@ -143,7 +147,7 @@ bool DStubController::customOption(int option, char* /* optarg */) { // Check for the custom option supported by DStubController. - if ((char)(option) == *stub_option_x_) { + if (static_cast(option) == *stub_option_x_) { return (true); } @@ -183,7 +187,7 @@ DStubController::customControllerCommand(const std::string& command, return (answer); } -const std::string DStubController::getCustomOpts(){ +const std::string DStubController::getCustomOpts() const { // Return the "list" of custom options supported by DStubController. return (std::string(stub_option_x_)); } diff --git a/src/bin/d2/tests/d_test_stubs.h b/src/bin/d2/tests/d_test_stubs.h index 412b974191..1659e524d7 100644 --- a/src/bin/d2/tests/d_test_stubs.h +++ b/src/bin/d2/tests/d_test_stubs.h @@ -96,7 +96,7 @@ class DStubProcess : public DProcessBase { public: /// @brief Static constant that defines a custom process command string. - static const std::string stub_proc_command_; + static const char* stub_proc_command_; /// @brief Constructor /// @@ -184,7 +184,7 @@ public: /// @brief Defines a custom controller command string. This is a /// custom command supported by DStubController. - static const std::string stub_ctl_command_; + static const char* stub_ctl_command_; /// @brief Defines a custom command line option supported by /// DStubController. @@ -234,7 +234,7 @@ protected: /// addition option, stub_option_x_. /// /// @return returns a string containing the option letters. - virtual const std::string getCustomOpts(); + virtual const std::string getCustomOpts() const; private: /// @brief Constructor is private to protect singleton integrity. @@ -378,9 +378,9 @@ public: /// @Wrapper to invoke the Controller's launch method. Please refer to /// DControllerBase::launch for details. - int launch(int argc, char* argv[]) { + void launch(int argc, char* argv[]) { optind = 1; - return (getController()->launch(argc, argv)); + getController()->launch(argc, argv); } /// @Wrapper to invoke the Controller's disconnectSession method. Please