Commit a41cac58 authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[master] Merge branch 2956 which adds DControllerBase and D2Controller

classes to bin/src/D2.
parents 31a77cdd 3511d115
......@@ -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-dhcp-ddns.xml
else
......@@ -44,21 +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_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/asiolink/libb10-asiolink.la
b10_d2_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.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
......@@ -24,14 +24,14 @@
</refentryinfo>
<refmeta>
<refentrytitle>b10-d2</refentrytitle>
<refentrytitle>b10-dhcp-ddns</refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo>BIND10</refmiscinfo>
</refmeta>
<refnamediv>
<refname>b10-d2</refname>
<refpurpose>D2 process in BIND 10 architecture</refpurpose>
<refname>b10-dhcp-ddns</refname>
<refpurpose>DHCP-DDNS process in BIND 10 architecture</refpurpose>
</refnamediv>
<docinfo>
......@@ -43,14 +43,14 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>b10-d2</command>
<command>b10-dhcp-ddns</command>
<arg><option>-v</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsynopsisdiv>
<cmdsynopsis>
<command>b10-d2</command>
<command>b10-dhcp-ddns</command>
<arg><option>-s</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
......@@ -59,8 +59,12 @@
<refsect1>
<title>DESCRIPTION</title>
<para>
The <command>b10-d2</command> daemon processes requests to
to update DNS mapping based on DHCP lease change events.
The <command>b10-dhcp-ddns</command> service processes requests to
to update DNS mapping based on DHCP lease change events. The service
may run either as a BIND10 module (integrated mode) or as a individual
process (stand-alone mode) dependent upon command line arguments. The
default is integrated mode. Stand alone operation is strictly for
development purposes and is not suited for production.
</para>
</refsect1>
......@@ -95,7 +99,7 @@
<title>SEE ALSO</title>
<para>
<citerefentry>
<refentrytitle>b10-d2</refentrytitle><manvolnum>8</manvolnum>
<refentrytitle>b10-dhcp-ddns</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
......@@ -106,7 +110,7 @@
<refsect1>
<title>HISTORY</title>
<para>
The <command>b10-d2</command> process was first coded in
The <command>b10-dhcp-ddns</command> process was first coded in
May 2013 by the ISC Kea/Dhcp team.
</para>
</refsect1>
......
{
"module_spec": {
"module_name": "D2",
"module_description": "DHCP-DDNS process",
"config_data": [
],
"commands": [
{
"command_name": "shutdown",
"command_description": "Shuts down the D2 process.",
"command_args": [
{
"item_name": "pid",
"item_type": "integer",
"item_optional": true
}
]
}
]
}
}
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <d2/d2_controller.h>
#include <d2/d2_process.h>
#include <d2/spec_config.h>
namespace isc {
namespace d2 {
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 have access to the singleton in order to use it within BIND10
// static function callbacks.
if (!getController()) {
DControllerBasePtr controller_ptr(new D2Controller());
setController(controller_ptr);
}
return (getController());
}
DProcessBase* D2Controller::createProcess() {
// Instantiate and return an instance of the D2 application process. Note
// that the process is passed the controller's io_service.
return (new D2Process(getName().c_str(), getIOService()));
}
D2Controller::D2Controller()
: DControllerBase(D2_MODULE_NAME) {
// set the BIND10 spec file either from the environment or
// use the production value.
if (getenv("B10_FROM_BUILD")) {
setSpecFileName(std::string(getenv("B10_FROM_BUILD")) +
"/src/bin/d2/d2.spec");
} else {
setSpecFileName(D2_SPECFILE_LOCATION);
}
}
D2Controller::~D2Controller() {
}
}; // end namespace isc::d2
}; // end namespace isc
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef D2_CONTROLLER_H
#define D2_CONTROLLER_H
#include <d2/d_controller.h>
namespace isc {
namespace d2 {
/// @brief Process Controller for D2 Process
/// This class is the DHCP-DDNS specific derivation of DControllerBase. It
/// creates and manages an instance of the DHCP-DDNS application process,
/// D2Process.
/// @TODO Currently, this class provides only the minimum required specialized
/// behavior to run the DHCP-DDNS 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 D2Controller : public 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 DControllerBasePtr& instance();
/// @brief Destructor.
virtual ~D2Controller();
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 DProcessBase* createProcess();
/// @brief Constructor is declared private to maintain the integrity of
/// the singleton instance.
D2Controller();
};
}; // namespace isc::d2
}; // namespace isc
#endif
......@@ -19,7 +19,12 @@
namespace isc {
namespace d2 {
isc::log::Logger d2_logger("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-dhpc-ddns";
/// @brief Defines the logger used within D2.
isc::log::Logger d2_logger(D2_MODULE_NAME);
} // namespace d2
} // namespace isc
......
......@@ -22,12 +22,17 @@
namespace isc {
namespace d2 {
/// @brief Defines the executable name, ultimately this is the BIND10 module
/// name.
extern const char* const D2_MODULE_NAME;
/// Define the logger for the "d2" module part of b10-d2. We could define
/// a logger in each file, but we would want to define a common name to avoid
/// spelling mistakes, so it is just one small step from there to define a
/// module-common logger.
extern isc::log::Logger d2_logger;
} // namespace d2
} // namespace isc
......
......@@ -15,19 +15,23 @@
$NAMESPACE isc::d2
% D2CTL_STARTING DHCP-DDNS controller starting, pid: %1
This is an informational message issued when controller for DHCP-DDNS
This is an informational message issued when controller for DHCP-DDNS
service first starts.
% D2CTL_STOPPING DHCP-DDNS controller is exiting
This is an informational message issued when the controller is exiting
This is an informational message issued when the controller is exiting
following a shut down (normal or otherwise) of the DDHCP-DDNS process.
% D2PRC_SHUTDOWN DHCP-DDNS process is performing a normal shut down
This is a debug message issued when the service process has been instructed
to shut down by the controller.
% D2PRC_RUN_ENTER process has entered the event loop
This is a debug message issued when the D2 process enters it's
% D2PRC_PROCESS_INIT DHCP-DDNS application init invoked
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 its
run method.
% D2PRC_RUN_EXIT process is exiting the event loop
......@@ -46,3 +50,59 @@ has been invoked.
This is a debug message issued when the D2 process command method
has been invoked.
% D2CTL_INIT_PROCESS initializing application proces
This debug message is issued just before the controller attempts
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
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
process in standalone mode. This means it will not connected to the BIND10
message queue. Standalone mode is only useful during program development,
and should not be used in a production environment.
% D2CTL_RUN_PROCESS starting application proces event loop
This debug message is issued just before the controller invokes
the application process run method.
% D2CTL_FAILED process failed: %1
The controller has encountered a fatal error and is terminating.
The reason for the failure is included in the message.
% D2CTL_CCSESSION_STARTING starting control channel session, specfile: %1
This debug message is issued just before the controller attempts
to establish a session with the BIND 10 control channel.
% D2CTL_CCSESSION_ENDING ending control channel session
This debug message is issued just before the controller attempts
to disconnect from its session with the BIND 10 control channel.
% D2CTL_CONFIG_STUB configuration stub handler called
This debug message is issued when the dummy handler for configuration
events is called. This only happens during intial startup.
% D2CTL_CONFIG_LOAD_FAIL failed to load configuration: %1
This critical error message indicates that the initial process
configuration has failed. The service will start, but will not
process requests until the configuration has been corrected.
% D2CTL_COMMAND_RECEIVED received command %1, arguments: %2
A debug message listing the command (and possible arguments) received
from the BIND 10 control system by the controller.
% D2CTL_NOT_RUNNING The application process instance is not running
A warning message is issued when an attempt is made to shut down the
the process when it is not running.
% D2CTL_CONFIG_UPDATE updated configuration received: %1
A debug message indicating that the controller has received an
updated configuration from the BIND 10 configuration system.
......@@ -21,7 +21,7 @@ using namespace asio;
namespace isc {
namespace d2 {
D2Process::D2Process(const char* name, IOServicePtr io_service)
D2Process::D2Process(const char* name, IOServicePtr io_service)
: DProcessBase(name, io_service) {
};
......@@ -29,12 +29,12 @@ void
D2Process::init() {
};
int
void
D2Process::run() {
// Until shut down or an fatal error occurs, wait for and
// execute a single callback. This is a preliminary implementation
// that is likely to evolve as development progresses.
// To use run(), the "managing" layer must issue an io_service::stop
// To use run(), the "managing" layer must issue an io_service::stop
// or the call to run will continue to block, and shutdown will not
// occur.
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_ENTER);
......@@ -44,46 +44,46 @@ D2Process::run() {
io_service->run_one();
} catch (const std::exception& ex) {
LOG_FATAL(d2_logger, D2PRC_FAILED).arg(ex.what());
return (EXIT_FAILURE);
isc_throw (DProcessBaseError,
"Process run method failed: " << ex.what());
}
}
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_EXIT);
return (EXIT_SUCCESS);
};
int
void
D2Process::shutdown() {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_SHUTDOWN);
setShutdownFlag(true);
return (0);
}
}
isc::data::ConstElementPtr
isc::data::ConstElementPtr
D2Process::configure(isc::data::ConstElementPtr config_set) {
// @TODO This is the initial implementation which simply accepts
// any content in config_set as valid. This is sufficient to
// any content in config_set as valid. This is sufficient to
// allow participation as a BIND10 module, while D2 configuration support
// is being developed.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
D2PRC_CONFIGURE).arg(config_set->str());
return (isc::config::createAnswer(0, "Configuration accepted."));
}
isc::data::ConstElementPtr
isc::data::ConstElementPtr
D2Process::command(const std::string& command, isc::data::ConstElementPtr args){
// @TODO This is the initial implementation. If and when D2 is extended
// to support its own commands, this implementation must change. Otherwise
// it should reject all commands as it does now.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
// it should reject all commands as it does now.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
D2PRC_COMMAND).arg(command).arg(args->str());
return (isc::config::createAnswer(1, "Unrecognized command:" + command));
return (isc::config::createAnswer(COMMAND_INVALID, "Unrecognized command: "
+ command));
}
D2Process::~D2Process() {
};
}; // namespace isc::d2
}; // namespace isc::d2
}; // namespace isc
......@@ -20,79 +20,82 @@
namespace isc {
namespace d2 {
/// @brief @TODO DHCP-DDNS Application Process
/// @brief DHCP-DDNS Application Process
///
/// D2Process provides the top level application logic for DHCP-driven DDNS
/// update processing. It provides the asynchronous event processing required
/// to receive DNS mapping change requests and carry them out.
/// D2Process provides the top level application logic for DHCP-driven DDNS
/// update processing. It provides the asynchronous event processing required
/// to receive DNS mapping change requests and carry them out.
/// It implements the DProcessBase interface, which structures it such that it
/// is a managed "application", controlled by a management layer.
/// is a managed "application", controlled by a management layer.
class D2Process : public DProcessBase {
public:
/// @brief Constructor
///
/// @param name name is a text label for the process. Generally used
/// in log statements, but otherwise arbitrary.
/// in log statements, but otherwise arbitrary.
/// @param io_service is the io_service used by the caller for
/// asynchronous event handling.
///
/// @throw DProcessBaseError is io_service is NULL.
/// @throw DProcessBaseError is io_service is NULL.
D2Process(const char* name, IOServicePtr io_service);
/// @brief Will be used after instantiation to perform initialization
/// unique to D2. This will likely include interactions with QueueMgr and
/// UpdateMgr, to prepare for request receipt and processing.
/// @brief Will be used after instantiation to perform initialization
/// unique to D2. @TODO This will likely include interactions with
/// QueueMgr and UpdateMgr, to prepare for request receipt and processing.
/// Current implementation successfully does nothing.
/// @throw throws a DProcessBaseError if the initialization fails.
virtual void init();
/// @brief Implements the process's event loop.
/// The initial implementation is quite basic, surrounding calls to
/// @brief Implements the process's event loop.
/// The initial implementation is quite basic, surrounding calls to
/// io_service->runOne() with a test of the shutdown flag.
/// Once invoked, the method will continue until the process itself is
/// exiting due to a request to shutdown or some anomaly forces an exit.
/// @return returns 0 upon a successful, "normal" termination, non
/// zero to indicate an abnormal termination.
virtual int run();
/// Once invoked, the method will continue until the process itself is
/// exiting due to a request to shutdown or some anomaly forces an exit.
/// @throw throws a DProcessBaseError if an error is encountered.
virtual void run();
// @TODO need brief
virtual int shutdown();
/// @brief Implements the process's shutdown processing. When invoked, it
/// should ensure that the process gracefully exits the run method.
/// Current implementation simply sets the shutdown flag monitored by the
/// run method. @TODO this may need to expand as the implementation evolves.
/// @throw throws a DProcessBaseError if an error is encountered.
virtual void shutdown();
// @TODO need brief
/// @brief Processes the given configuration.
///
/// @brief Processes the given configuration.
///
/// This method may be called multiple times during the process lifetime.
/// Certainly once during process startup, and possibly later if the user
/// alters configuration. This method must not throw, it should catch any
/// processing errors and return a success or failure answer as described
/// below.
/// below.
///
/// @param config_set a new configuration (JSON) for the process
/// @return an Element that contains the results of configuration composed
/// of an integer status value (0 means successful, non-zero means failure),
/// and a string explanation of the outcome.
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr
config_set);
// @TODO need brief
/// @brief Processes the given command.
///
/// This method is called to execute any custom commands supported by the
/// process. This method must not throw, it should catch any processing
/// @brief Processes the given command.
///
/// This method is called to execute any custom commands supported by the
/// process. This method must not throw, it should catch any processing
/// errors and return a success or failure answer as described below.
///
/// @param command is a string label representing the command to execute.
/// @param args is a set of arguments (if any) required for the given
/// command.
/// command.
/// @return an Element that contains the results of command composed
/// of an integer status value (0 means successful, non-zero means failure),
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr command(const std::string& command,
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr command(const std::string& command,
isc::data::ConstElementPtr args);
// @TODO need brief
/// @brief Destructor
virtual ~D2Process();
};
}; // namespace isc::d2
}; // namespace isc::d2
}; // namespace isc
#endif
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <d2/d2_log.h>
#include <d2/d_controller.h>
#include <exceptions/exceptions.h>
#include <log/logger_support.h>
#include <sstream>
namespace isc {
namespace d2 {
DControllerBasePtr DControllerBase::controller_;
// Note that the constructor instantiates the controller's primary IOService.
DControllerBase::DControllerBase(const char* name)
: name_(name), stand_alone_(false), verbose_(false),
spec_file_name_(""), io_service_(new isc::asiolink::IOService()){
}
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.");
}