Commit 446b43cc authored by Francis Dupont's avatar Francis Dupont

[128-netconf-use-libprocess] Added use of libprocess in netconf

parent 3d0ecb95
......@@ -1505,6 +1505,7 @@ AC_CONFIG_FILES([Makefile
src/bin/netconf/Makefile
src/bin/netconf/tests/Makefile
src/bin/netconf/tests/netconf_tests.sh
src/bin/netconf/tests/test_libraries.h
src/bin/perfdhcp/Makefile
src/bin/perfdhcp/tests/Makefile
src/bin/perfdhcp/tests/testdata/Makefile
......
......@@ -46,7 +46,11 @@ BUILT_SOURCES = netconf_messages.h netconf_messages.cc
noinst_LTLIBRARIES = libnetconf.la
libnetconf_la_SOURCES = netconf_log.cc netconf_log.h
libnetconf_la_SOURCES = netconf_cfg_mgr.cc netconf_cfg_mgr.h
libnetconf_la_SOURCES += netconf_controller.h netconf_controller.cc
libnetconf_la_SOURCES += netconf_log.cc netconf_log.h
libnetconf_la_SOURCES += netconf_process.cc netconf_process.h
libnetconf_la_SOURCES += simple_parser.cc simple_parser.h
nodist_libnetconf_la_SOURCES = netconf_messages.h netconf_messages.cc
......
......@@ -5,135 +5,38 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <kea_version.h>
#include <netconf/netconf_log.h>
#include <netconf/netconf_controller.h>
#include <exceptions/exceptions.h>
#include <process/daemon.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <cstdio>
#include <signal.h>
#include <sysrepo-cpp/Session.h>
using namespace std;
using namespace isc;
using namespace isc::netconf;
using namespace isc::process;
/// @brief Prints Kea Usage and exits
///
/// Note: This function never returns. It terminates the process.
void
usage() {
cerr << "Kea netconf daemon, version " << VERSION << endl
<< endl
<< "Usage: " << endl
<< " -c: config-file" << endl
<< " -d: debug mode (maximum verbosity)" << endl
<< " -v: print version number and exit" << endl
<< " -V: print extended version and exit" << endl;
exit(EXIT_FAILURE);
}
/// @name Temporary code until isc::process::Daemon is used.
///
/// @{
const char* PID_FILENAME = "kea-netconf.test_config.pid";
volatile bool SHUTDOWN_FLAG = false;
void
createPIDFile(int pid) {
// This is not a real implemented. We will soon use the one coming
// from isc::process::Daemon AFTER it's moved to libprocess.
ofstream file(PID_FILENAME, ios::trunc);
file << pid;
}
void
deletePIDFile() {
remove(PID_FILENAME);
}
static void signal_handler(int ) {
SHUTDOWN_FLAG = true;
}
/// @}
int
main(int argc, char* argv[]) {
// The standard config file
std::string config_file("");
int ch;
while ((ch = getopt(argc, argv, "vVc:")) != -1) {
switch (ch) {
case 'v':
cout << string(PACKAGE_VERSION) << endl;
return (EXIT_SUCCESS);
case 'V':
cout << string(PACKAGE_VERSION) << endl;
cout << "git " << EXTENDED_VERSION << endl;
return (EXIT_SUCCESS);
case 'c': // config file
config_file = optarg;
break;
default:
usage();
}
}
// Check for extraneous parameters.
if (argc > optind) {
usage();
}
// Configuration file is required.
if (config_file.empty()) {
cerr << "Configuration file not specified." << endl;
usage();
}
int main(int argc, char* argv[]) {
int ret = EXIT_SUCCESS;
try {
// Temporary code. This will be replaced with isc::process::Daemon
// once it is migrated to libprocess. We DO NOT want to bring
// the whole libdhcpsrv into netconf.
createPIDFile(getpid());
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
// Initialize logging. If verbose, we'll use maximum verbosity.
bool verbose_mode = true;
isc::process::Daemon::loggerInit(NETCONF_LOGGER_NAME, verbose_mode);
LOG_INFO(netconf_logger, NETCONF_STARTING).arg(VERSION).arg(getpid());
Connection conn("kea-netconf");
// Tell the admin we are ready to process packets
LOG_INFO(netconf_logger, NETCONF_STATED).arg(VERSION);
// And run the main loop of the server.
while (!SHUTDOWN_FLAG) {
cout << "Dummy kea-netconf running. Press ctrl-c to terminate."
<< endl;
sleep(1);
// Launch the controller passing in command line arguments.
// Exit program with the controller's return code.
try {
// Instantiate/fetch the application controller singleton.
DControllerBasePtr& controller = NetconfController::instance();
// 'false' value disables test mode.
controller->launch(argc, argv, false);
} catch (const VersionMessage& ex) {
std::string msg(ex.what());
if (!msg.empty()) {
std::cout << msg << std::endl;
}
LOG_INFO(netconf_logger, NETCONF_SHUTDOWN);
deletePIDFile();
} catch (const InvalidUsage& ex) {
std::string msg(ex.what());
if (!msg.empty()) {
std::cerr << msg << std::endl;
}
ret = EXIT_FAILURE;
} catch (const isc::Exception& ex) {
// First, we parint the error on stderr (that should always work)
cerr << "ERROR:" << ex.what() << endl;
std::cerr << "Service failed: " << ex.what() << std::endl;
ret = EXIT_FAILURE;
}
......
// Copyright (C) 2018 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 <netconf/netconf_cfg_mgr.h>
#include <netconf/netconf_log.h>
#include <netconf/simple_parser.h>
#include <cc/simple_parser.h>
#include <cc/command_interpreter.h>
#include <exceptions/exceptions.h>
using namespace isc::dhcp;
using namespace isc::process;
using namespace isc::data;
namespace isc {
namespace netconf {
NetconfCfgContext::NetconfCfgContext() {
}
NetconfCfgContext::NetconfCfgContext(const NetconfCfgContext& orig)
: DCfgContextBase(), hooks_config_(orig.hooks_config_) {
}
NetconfCfgMgr::NetconfCfgMgr()
: DCfgMgrBase(DCfgContextBasePtr(new NetconfCfgContext())) {
}
NetconfCfgMgr::~NetconfCfgMgr() {
}
std::string
NetconfCfgMgr::getConfigSummary(const uint32_t /*selection*/) {
NetconfCfgContextPtr ctx = getNetconfCfgContext();
std::ostringstream s;
// Finally, print the hook libraries names
const isc::hooks::HookLibsCollection libs = ctx->getHooksConfig().get();
s << ", " << libs.size() << " lib(s):";
for (auto lib = libs.begin(); lib != libs.end(); ++lib) {
s << lib->first << " ";
}
return (s.str());
}
DCfgContextBasePtr
NetconfCfgMgr::createNewContext() {
return (DCfgContextBasePtr(new NetconfCfgContext()));
}
isc::data::ConstElementPtr
NetconfCfgMgr::parse(isc::data::ConstElementPtr config_set,
bool check_only) {
// Do a sanity check first.
if (!config_set) {
isc_throw(DhcpConfigError, "Mandatory config parameter not provided");
}
NetconfCfgContextPtr ctx = getNetconfCfgContext();
// Set the defaults
ElementPtr cfg = boost::const_pointer_cast<Element>(config_set);
NetconfSimpleParser::setAllDefaults(cfg);
// And parse the configuration.
ConstElementPtr answer;
std::string excuse;
try {
// Do the actual parsing
NetconfSimpleParser parser;
parser.parse(ctx, cfg, check_only);
} catch (const isc::Exception& ex) {
excuse = ex.what();
answer = isc::config::createAnswer(2, excuse);
} catch (...) {
excuse = "undefined configuration parsing error";
answer = isc::config::createAnswer(2, excuse);
}
// At this stage the answer was created only in case of exception.
if (answer) {
if (check_only) {
LOG_ERROR(netconf_logger, NETCONF_CONFIG_CHECK_FAIL).arg(excuse);
} else {
LOG_ERROR(netconf_logger, NETCONF_CONFIG_FAIL).arg(excuse);
}
return (answer);
}
if (check_only) {
answer = isc::config::createAnswer(0, "Configuration check successful");
} else {
answer = isc::config::createAnswer(0, "Configuration applied successfully.");
}
return (answer);
}
ElementPtr
NetconfCfgContext::toElement() const {
ElementPtr netconf = Element::createMap();
// Set user-context
contextToElement(netconf);
// Set hooks-libraries
netconf->set("hooks-libraries", hooks_config_.toElement());
// Set Netconf
ElementPtr result = Element::createMap();
result->set("Netconf", netconf);
// Set Logging (not yet)
return (result);
}
} // namespace isc::netconf
} // namespace isc
// Copyright (C) 2018 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 NETCONF_CFG_MGR_H
#define NETCONF_CFG_MGR_H
#include <cc/data.h>
#include <hooks/hooks_config.h>
#include <process/d_cfg_mgr.h>
#include <boost/pointer_cast.hpp>
#include <map>
#include <string>
namespace isc {
namespace netconf {
class NetconfCfgContext;
/// @brief Pointer to a configuration context.
typedef boost::shared_ptr<NetconfCfgContext> NetconfCfgContextPtr;
/// @brief Netconf Configuration Context.
///
/// Implement the storage container for configuration context.
/// It provides a single enclosure for the storage of configuration parameters
/// and any other Netconf specific information that needs to be accessible
/// during configuration parsing as well as to the application as a whole.
/// It is derived from the context base class, DCfgContextBase.
class NetconfCfgContext : public process::DCfgContextBase {
public:
/// @brief Default constructor
NetconfCfgContext();
/// @brief Creates a clone of this context object.
///
/// @return A pointer to the new clone.
virtual process::DCfgContextBasePtr clone() {
return (process::DCfgContextBasePtr(new NetconfCfgContext(*this)));
}
/// @brief Returns non-const reference to configured hooks libraries.
///
/// @return non-const reference to configured hooks libraries.
isc::hooks::HooksConfig& getHooksConfig() {
return (hooks_config_);
}
/// @brief Returns const reference to configured hooks libraries.
///
/// @return const reference to configured hooks libraries.
const isc::hooks::HooksConfig& getHooksConfig() const {
return (hooks_config_);
}
/// @brief Unparse a configuration object
///
/// Returns an element which must parse into the same object, i.e.
/// @code
/// for all valid config C parse(parse(C)->toElement()) == parse(C)
/// @endcode
///
/// @return a pointer to a configuration which can be parsed into
/// the initial configuration object
virtual isc::data::ElementPtr toElement() const;
private:
/// @brief Private copy constructor
///
/// It is private to forbid anyone outside of this class to make copies.
/// The only legal way to copy a context is to call @ref clone().
///
/// @param orig the original context to copy from
NetconfCfgContext(const NetconfCfgContext& orig);
/// @brief Private assignment operator to avoid potential for slicing.
///
/// @param rhs Context to be assigned.
NetconfCfgContext& operator=(const NetconfCfgContext& rhs);
/// @brief Configured hooks libraries.
isc::hooks::HooksConfig hooks_config_;
};
/// @brief Ctrl Netconf Configuration Manager.
///
/// Provides the mechanisms for managing the Netconf application's
/// configuration.
class NetconfCfgMgr : public process::DCfgMgrBase {
public:
/// @brief Constructor.
NetconfCfgMgr();
/// @brief Destructor
virtual ~NetconfCfgMgr();
/// @brief Convenience method that returns the Netconf configuration
/// context.
///
/// @return returns a pointer to the configuration context.
NetconfCfgContextPtr getNetconfCfgContext() {
return (boost::dynamic_pointer_cast<NetconfCfgContext>(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 Netconf.
///
/// @return Summary of the configuration in the textual format.
virtual std::string getConfigSummary(const uint32_t selection);
protected:
/// @brief Parses configuration of Netconf.
///
/// @param config Pointer to a configuration specified for netconf.
/// @param check_only Boolean flag indicating if this method should
/// only verify correctness of the provided configuration.
/// @return Pointer to a result of configuration parsing.
virtual isc::data::ConstElementPtr
parse(isc::data::ConstElementPtr config, bool check_only);
/// @brief Creates a new, blank NetconfCfgContext context.
///
///
/// This method is used at the beginning of configuration process to
/// create a fresh, empty copy of a NetconfCfgContext. 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();
};
/// @brief Defines a shared pointer to NetconfCfgMgr.
typedef boost::shared_ptr<NetconfCfgMgr> NetconfCfgMgrPtr;
} // namespace isc::netconf
} // namespace isc
#endif // NETCONF_CFG_MGR_H
// Copyright (C) 2018 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 <netconf/netconf_controller.h>
#include <netconf/netconf_process.h>
#ifdef notyet
#include <netconf/parser_context.h>
#endif
using namespace isc::process;
namespace isc {
namespace netconf {
/// @brief Defines the application name, this is passed into base class
/// it may be used to locate configuration data and appears in log statement.
const char* NetconfController::netconf_app_name_ = "Netconf";
/// @brief Defines the executable name. This is passed into the base class
const char* NetconfController::netconf_bin_name_ = "kea-netconf";
DControllerBasePtr&
NetconfController::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 NetconfController());
setController(controller_ptr);
}
return (getController());
}
DProcessBase*
NetconfController::createProcess() {
// Instantiate and return an instance of the D2 application process. Note
// that the process is passed the controller's io_service.
return (new NetconfProcess(getAppName().c_str(), getIOService()));
}
isc::data::ConstElementPtr
NetconfController::parseFile(const std::string& name) {
#ifdef notyet
ParserContext parser;
return (parser.parseFile(name, ParserContext::PARSER_NETCONF));
#else
isc_throw(NotImplemented, "NetconfController::parseFile("
<< name << ")");
#endif
}
NetconfController::NetconfController()
: DControllerBase(netconf_app_name_, netconf_bin_name_) {
}
NetconfController::~NetconfController() {
}
NetconfProcessPtr
NetconfController::getNetconfProcess() {
return (boost::dynamic_pointer_cast<NetconfProcess>(getProcess()));
}
} // namespace isc::netconf
} // namespace isc
// Copyright (C) 2018 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 NETCONF_CONTROLLER_H
#define NETCONF_CONTROLLER_H
#include <netconf/netconf_process.h>
#include <process/d_controller.h>
namespace isc {
namespace netconf {
/// @brief Process Controller for Netconf Process.
///
/// This class is the Netconf specific derivation of the DControllerBase.
/// It creates and manages an instance of the Netconf application process,
/// NetconfProcess.
class NetconfController : 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 ~NetconfController();
/// @brief Returns pointer to an instance of the underlying process object.
NetconfProcessPtr getNetconfProcess();
/// @brief Defines the application name, this is passed into base class
/// and appears in log statements.
static const char* netconf_app_name_;
/// @brief Defines the executable name. This is passed into the base class
/// by convention this should match the executable name.
static const char* netconf_bin_name_;
/// @brief Parses the configuration file using Netconf::ParserContext (bison)
///
/// @param name name of the text file to be parsed
/// @return Element tree structure representing parsed configuration
isc::data::ConstElementPtr
parseFile(const std::string& name);
private:
/// @brief Creates an instance of the Netconf 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 Constructor is declared private to maintain the integrity of
/// the singleton instance.
NetconfController();
};
// @Defines a shared pointer to NetconfController
typedef boost::shared_ptr<NetconfController> NetconfControllerPtr;
} // namespace isc::netconf
} // namespace isc
#endif // NETCONF_CONTROLLER_H
......@@ -6,14 +6,25 @@
$NAMESPACE isc::netconf
% NETCONF_STARTING Kea-netconf agent (version %1) is starting with process-id %2
Describe it later.
% NETCONF_CONFIG_CHECK_FAIL Netconf configuration check failed: %1
This error message indicates that Netconf had failed configuration
check. Details are provided. Additional details may be available
in earlier log entries, possibly on lower levels.
% NETCONF_STATED Kea-netconf agent (version %1) started
Describe it later.
% NETCONF_CONFIG_FAIL Netconf configuration failed: %1
This error message indicates that Netconf had failed configuration
attempt. Details are provided. Additional details may be available
in earlier log entries, possibly on lower levels.
% NETCONF_SHUTDOWN Kea-netconf agent shutting down.
Describe it later.
% NETCONF_FAILED application experienced a fatal error: %1
This is a debug message issued when the Netconf application
encounters an unrecoverable error from within the event loop.
% NETCONF_EXCEPTION Exception encountered: %1
Oops.
% NETCONF_RUN_EXIT application is exiting the event loop
This is a debug message issued when the Netconf application exits its
event loop.
% NETCONF_STARTED Netconf (version %1) started
This informational message indicates that Netconf has processed
all configuration information and is ready to begin processing.
The version is also printed.
// Copyright (C) 2018 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 <asiolink/asio_wrapper.h>
#include <netconf/netconf_process.h>
#include <netconf/netconf_controller.h>
#include <netconf/netconf_log.h>
#include <asiolink/io_address.h>
#include <asiolink/io_error.h>
#include <cc/command_interpreter.h>
#include <config/timeouts.h>
#include <boost/pointer_cast.hpp>
using namespace isc::asiolink;
using namespace isc::config;
using namespace isc::data;
using namespace isc::http;
using namespace isc::process;
namespace isc {
namespace netconf {
NetconfProcess::NetconfProcess(const char* name,
const asiolink::IOServicePtr& io_service)
: DProcessBase(name, io_service, DCfgMgrBasePtr(new NetconfCfgMgr())) {
}
NetconfProcess::~NetconfProcess() {
}
void
NetconfProcess::init() {
}
void
NetconfProcess::run() {
LOG_INFO(netconf_logger, NETCONF_STARTED).arg(VERSION);
try {
// Let's process incoming data or expiring timers in a loop until
// shutdown condition is detected.
while (!shouldShutdown()) {
getIoService()->get_io_service().poll();
}
stopIOService();
} catch (const std::exception& ex) {
LOG_FATAL(netconf_logger, NETCONF_FAILED).arg(ex.what());