Commit 73cafb6a authored by Francis Dupont's avatar Francis Dupont

[128-netconf-config] Added netconf config code from kea-yang

parent fecd9475
......@@ -1513,6 +1513,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_data_files_config.h
src/bin/netconf/tests/test_libraries.h
src/bin/perfdhcp/Makefile
src/bin/perfdhcp/tests/Makefile
......
......@@ -45,6 +45,7 @@ BUILT_SOURCES = netconf_messages.h netconf_messages.cc
noinst_LTLIBRARIES = libnetconf.la
libnetconf_la_SOURCES = netconf_cfg_mgr.cc netconf_cfg_mgr.h
libnetconf_la_SOURCES += netconf_config.cc netconf_config.h
libnetconf_la_SOURCES += netconf_controller.cc netconf_controller.h
libnetconf_la_SOURCES += netconf_log.cc netconf_log.h
libnetconf_la_SOURCES += netconf_parser.cc netconf_parser.h
......@@ -86,7 +87,7 @@ kea_netconfdir = $(pkgdatadir)
if GENERATE_PARSER
parser: netconf_lexer.cc location.hh position.hh stack.hh netconf_parser.cc netconf_parser.h
# @echo "Flex/bison files regenerated"
@echo "Flex/bison files regenerated"
# --- Flex/Bison stuff below --------------------------------------------------
# When debugging grammar issues, it's useful to add -v to bison parameters.
......
......@@ -20,11 +20,13 @@ using namespace isc::data;
namespace isc {
namespace netconf {
NetconfConfig::NetconfConfig() {
NetconfConfig::NetconfConfig()
: servers_map_(new ServersMap()) {
}
NetconfConfig::NetconfConfig(const NetconfConfig& orig)
: ConfigBase(), hooks_config_(orig.hooks_config_) {
: ConfigBase(), servers_map_(orig.servers_map_),
hooks_config_(orig.hooks_config_) {
}
NetconfCfgMgr::NetconfCfgMgr()
......@@ -39,8 +41,21 @@ NetconfCfgMgr::getConfigSummary(const uint32_t /*selection*/) {
NetconfConfigPtr ctx = getNetconfConfig();
// No globals to print.
std::ostringstream s;
// Then print managed servers.
for (auto serv : *ctx->getServersMap()) {
if (s.tellp() != 0) {
s << " ";
}
s << serv.first;
}
if (s.tellp() == 0) {
s << "none";
}
// Finally, print the hook libraries names
const isc::hooks::HookLibsCollection libs = ctx->getHooksConfig().get();
s << ", " << libs.size() << " lib(s):";
......@@ -106,6 +121,8 @@ NetconfCfgMgr::parse(isc::data::ConstElementPtr config_set,
return (answer);
}
ElementPtr
NetconfConfig::toElement() const {
ElementPtr netconf = Element::createMap();
......@@ -113,6 +130,13 @@ NetconfConfig::toElement() const {
contextToElement(netconf);
// Set hooks-libraries
netconf->set("hooks-libraries", hooks_config_.toElement());
// Set managed-servers
ElementPtr servers = Element::createMap();
for (auto serv : *servers_map_) {
ConstElementPtr server = serv.second->toElement();
servers->set(serv.first, server);
}
netconf->set("managed-servers", servers);
// Set Netconf
ElementPtr result = Element::createMap();
result->set("Netconf", netconf);
......
......@@ -10,6 +10,7 @@
#include <cc/data.h>
#include <hooks/hooks_config.h>
#include <process/d_cfg_mgr.h>
#include <netconf/netconf_config.h>
#include <boost/pointer_cast.hpp>
#include <map>
#include <string>
......@@ -34,6 +35,20 @@ public:
/// @brief Default constructor
NetconfConfig();
/// @brief Returns non-const reference to the managed servers map.
///
/// @return non-const reference to the managed servers map.
ServersMapPtr& getServersMap() {
return (servers_map_);
}
/// @brief Returns const reference to the managed servers map.
///
/// @return const reference to the managed servers map.
const ServersMapPtr& getServersMap() const {
return (servers_map_);
}
/// @brief Returns non-const reference to configured hooks libraries.
///
/// @return non-const reference to configured hooks libraries.
......@@ -73,6 +88,9 @@ private:
/// @param rhs Context to be assigned.
NetconfConfig& operator=(const NetconfConfig& rhs);
/// @brief Servers map.
ServersMapPtr servers_map_;
/// @brief Configured hooks libraries.
isc::hooks::HooksConfig hooks_config_;
};
......
// 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_log.h>
#include <netconf/netconf_cfg_mgr.h>
#include <exceptions/exceptions.h>
#include <asiolink/io_error.h>
#include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <sstream>
#include <string>
using namespace std;
using namespace isc::process;
using namespace isc::data;
using namespace isc::http;
namespace isc {
namespace netconf {
// *********************** ControlSocket *************************
ControlSocket::ControlSocket(Type type, const string& name, const Url& url)
: type_(type), name_(name), url_(url) {
}
ControlSocket::~ControlSocket() {
}
ControlSocket::Type
ControlSocket::stringToType(const string& type) {
if (type == "unix") {
return (ControlSocket::Type::UNIX);
} else if (type == "http") {
return (ControlSocket::Type::HTTP);
} else if (type == "stdout") {
return (ControlSocket::Type::STDOUT);
}
isc_throw(BadValue, "Unknown control socket type: " << type);
}
const string
ControlSocket::typeToString(ControlSocket::Type type) {
switch (type) {
case ControlSocket::Type::UNIX:
return ("unix");
case ControlSocket::Type::HTTP:
return ("http");
case ControlSocket::Type::STDOUT:
return ("stdout");
}
/*UNREACHED*/
}
ElementPtr
ControlSocket::toElement() const {
ElementPtr result = Element::createMap();
// Set user-context
contextToElement(result);
// Set type
result->set("socket-type", Element::create(typeToString(type_)));
// Set name
result->set("socket-name", Element::create(name_));
// Set url
result->set("socket-url", Element::create(url_.toText()));
return (result);
}
// *********************** Server *************************
Server::Server(const string& model, ControlSocketPtr ctrl_sock)
: model_(model), control_socket_(ctrl_sock) {
}
Server::~Server() {
}
string
Server::toText() const {
ostringstream s;
s << "model: " << model_ << ", control socker: ";
if (!control_socket_) {
s << "none";
} else {
switch (control_socket_->getType()) {
case ControlSocket::Type::UNIX:
s << "UNIX:'" << control_socket_->getName() << "'";
break;
case ControlSocket::Type::HTTP:
s << "HTTP:'" << control_socket_->getUrl().toText() << "'";
break;
case ControlSocket::Type::STDOUT:
s << "STDOUT";
break;
}
}
return (s.str());
}
ElementPtr
Server::toElement() const {
ElementPtr result = Element::createMap();
// Set user-context
contextToElement(result);
// Set model
result->set("model", Element::create(model_));
// Set control-socket
if (control_socket_) {
result->set("control-socket", control_socket_->toElement());
}
return (result);
}
ostream&
operator<<(ostream& os, const Server& server) {
os << server.toText();
return (os);
}
// *************************** PARSERS ***********************************
// *********************** ControlSocketParser *************************
ControlSocketPtr
ControlSocketParser::parse(ConstElementPtr ctrl_sock_config) {
ControlSocketPtr result;
string type_str = getString(ctrl_sock_config, "socket-type");
string name = getString(ctrl_sock_config, "socket-name");
string url_str = getString(ctrl_sock_config, "socket-url");
ConstElementPtr user_context = ctrl_sock_config->get("user-context");
// Type must be valid.
ControlSocket::Type type;
try {
type = ControlSocket::stringToType(type_str);
} catch (const std::exception& ex) {
isc_throw(NetconfCfgError, ex.what() << " '" << type_str << "' ("
<< getPosition("socket-type", ctrl_sock_config) << ")");
}
// Url must be valid.
Url url(url_str);
if (!url.isValid()) {
isc_throw(NetconfCfgError, "invalid control socket url: "
<< url.getErrorMessage() << " '" << url_str << "' ("
<< getPosition("socket-url", ctrl_sock_config) << ")");
}
// Create the control socket.
try {
result.reset(new ControlSocket(type, name, url));
} catch (const std::exception& ex) {
isc_throw(NetconfCfgError, ex.what() << " ("
<< ctrl_sock_config->getPosition() << ")");
}
// Add user-context.
if (user_context) {
result->setContext(user_context);
}
return (result);
}
// *********************** ServerParser *************************
ServerPtr
ServerParser::parse(ConstElementPtr server_config) {
ServerPtr result;
string model = getString(server_config, "model");
ConstElementPtr user_context = server_config->get("user-context");
ConstElementPtr ctrl_sock_config = server_config->get("control-socket");
ControlSocketPtr ctrl_sock;
if (ctrl_sock_config) {
ControlSocketParser parser;
ctrl_sock = parser.parse(ctrl_sock_config);
}
try {
result.reset(new Server(model, ctrl_sock));
} catch (const std::exception& ex) {
isc_throw(NetconfCfgError, ex.what() << " ("
<< server_config->getPosition() << ")");
}
// Add user-context.
if (user_context) {
result->setContext(user_context);
}
return (result);
}
}; // end of isc::netconf namespace
}; // end of isc namespace
// 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_CONFIG_H
#define NETCONF_CONFIG_H
#include <cc/data.h>
#include <cc/cfg_to_element.h>
#include <cc/user_context.h>
#include <cc/simple_parser.h>
#include <http/url.h>
#include <exceptions/exceptions.h>
#include <boost/foreach.hpp>
#include <stdint.h>
#include <string>
namespace isc {
namespace netconf {
/// @file netconf_config.h
/// @brief A collection of classes for housing and parsing the application
/// configuration necessary for the Netconf application.
///
/// @note NetconfConfig is not here: this file contains component of
/// this class but not the class itself.
///
/// This file contains the class declarations for the class hierarchy created
/// from the Netconf configuration and the parser classes used to create it.
/// The application configuration consists of a list of managed server.
///
/// The parsing class hierarchy reflects this same scheme. Working top down:
///
/// A ServerMapParser handles the managed servers map invoking a ServerParser
/// to parse each server.
///
/// A ServerParser handles the scalars which belong to the server as well as
/// creating and invoking a CtrlSocketParser to parse its control socket.
///
/// A CtrlSocketParser handles the scalars which belong to the control socket.
///
/// The following is sample configuration in JSON form with extra spacing
/// for clarity:
///
/// @code
/// {
/// "managed-servers" :
/// {
/// "dhcp4":
/// {
/// "model": "kea-dhcp4-server",
/// "control-socket":
/// {
/// "socket-type": "unix",
/// "socket-name": "/tmp/server-v4.sock"
/// }
/// }
/// }
/// }
/// @endcode
/// @brief Exception thrown when the error during configuration handling
/// occurs.
class NetconfCfgError : public isc::Exception {
public:
NetconfCfgError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) { };
};
/// @brief Represents a Control Socket.
///
/// Acts as a storage class containing the basic attributes which
/// describe a Control Socket.
class ControlSocket : public isc::data::UserContext,
public isc::data::CfgToElement {
public:
/// @brief Defines the list of possible constrol socket types.
enum Type {
UNIX, //< Unix socket.
HTTP, //< HTTP socket.
STDOUT //< standard output.
};
/// @brief Constructor.
///
/// @param type The socket type.
/// @param name The Unix socket name.
/// @param url The HTTP server URL.
ControlSocket(Type type, const std::string& name,
const isc::http::Url& url);
/// @brief Destructor (doing nothing).
virtual ~ControlSocket();
/// @brief Getter which returns the socket type.
///
/// @return returns the socket type as a ControlSocket::Type.
Type getType() const {
return (type_);
}
/// @brief Getter which returns the Unix socket name.
///
/// @return returns the Unix socket name as a std::string.
const std::string getName() const {
return (name_);
}
/// @brief Getter which returns the HTTP server URL.
///
/// @return returns the HTTP server URL as an isc::http::Url.
const isc::http::Url getUrl() const {
return (url_);
}
/// @brief Converts socket type name to ControlSocket::Type.
///
/// @param type The type name.
/// Currently supported values are "unix", "http" and "stdout".
///
/// @return The ControlSocket::Type corresponding to the type name.
/// @throw BadValue if the type name isn't recognized.
static Type stringToType(const std::string& type);
/// @brief Converts ControlSocket::Type to string.
///
/// @param type The ControlSocket::Type type.
/// @return The type name corresponding to the enumeration element.
static const std::string typeToString(ControlSocket::Type type);
/// @brief Unparse a configuration object
///
/// @return a pointer to a configuration
virtual isc::data::ElementPtr toElement() const;
private:
/// @brief The socket type.
Type type_;
/// @brief The UNIX socket name.
const std::string name_;
/// @brief The HTTP server URL.
const isc::http::Url url_;
};
/// @brief Defines a pointer for ControlSocket instances.
typedef boost::shared_ptr<ControlSocket> ControlSocketPtr;
/// @brief Represents a Managed Server.
///
/// Acts as a storage class containing the basic attributes and
/// the Control Socket which describe a Managed Server.
class Server : public isc::data::UserContext, public isc::data::CfgToElement {
public:
/// @brief Constructor.
///
/// @param model The model name.
/// @param ctrl_sock The control socket.
Server(const std::string& model, ControlSocketPtr ctrl_sock);
/// @brief Destructor (doing nothing).
virtual ~Server();
/// @brief Getter which returns the model name.
///
/// @return returns the model name as a std::string
const std::string getModel() const {
return (model_);
}
/// @brief Getter which returns the control socket.
///
/// @return returns the control socket as a ControlSocketPtr.
const ControlSocketPtr& getControlSocket() const {
return (control_socket_);
}
/// @brief Returns a text representation for the server.
std::string toText() const;
/// @brief Unparse a configuration object
///
/// @return a pointer to a configuration
virtual isc::data::ElementPtr toElement() const;
private:
/// @brief The model name.
const std::string model_;
/// @brief The control socket.
ControlSocketPtr control_socket_;
};
/// @brief Defines a pointer for Server instances.
typedef boost::shared_ptr<Server> ServerPtr;
/// @brief Defines a map of Servers, keyed by the name.
typedef std::map<std::string, ServerPtr> ServersMap;
/// @brief Defines a iterator pairing of name and Server
typedef std::pair<std::string, ServerPtr> ServersMapPair;
/// @brief Defines a pointer to map of Servers.
typedef boost::shared_ptr<ServersMap> ServersMapPtr;
/// @brief Dumps the contents of a Server as text to a output stream.
///
/// @param os The output stream to which text should be sent.
/// @param server The Server instance to dump.
std::ostream& operator<<(std::ostream& os, const Server& server);
/// @brief Parser for ControlSocket.
///
/// This class parses the configuration element "control-socket"
/// and creates an instance of a ControlSocket.
class ControlSocketParser : public data::SimpleParser {
public:
/// @brief Performs the actual parsing of the given "control-socket" element.
///
/// Parses a configuration for the elements needed to instantiate a
/// ControlSocket, validates those entries, creates a ControlSocket
/// instance.
///
/// @param ctrl_sock_config is the "control-socket" configuration to parse.
///
/// @return pointer to the new ControlSocket instance.
ControlSocketPtr parse(data::ConstElementPtr ctrl_sock_config);
};
/// @brief Parser for Server.
///
/// This class parses the configuration value from the "managed-servers" map
/// and creates an instance of a Server.
class ServerParser : public data::SimpleParser {
public:
/// @brief Performs the actual parsing of the given value from
/// the "managed-servers" map.
///
/// Parses a configuration for the elements needed to instantiate a
/// Server, validates those entries, creates a Server instance.
///
/// @param server_config is the value from the "managed-servers" map to parse.
/// @return pointer to the new Server instance.
ServerPtr parse(data::ConstElementPtr server_config);
};
}; // end of isc::netconf namespace
}; // end of isc namespace
#endif // NETCONF_CONFIG_H
......@@ -8,6 +8,7 @@
#include <netconf/netconf_controller.h>
#include <netconf/netconf_process.h>
#include <netconf/parser_context.h>
using namespace isc::process;
......@@ -42,8 +43,8 @@ NetconfController::createProcess() {
isc::data::ConstElementPtr
NetconfController::parseFile(const std::string& name) {
isc_throw(NotImplemented, "NetconfController::parseFile("
<< name << ")");
ParserContext parser;
return (parser.parseFile(name, ParserContext::PARSER_NETCONF));
}
NetconfController::NetconfController()
......
......@@ -7,6 +7,7 @@
#include <config.h>
#include <netconf/simple_parser.h>
#include <netconf/netconf_config.h>
#include <cc/data.h>
#include <cc/dhcp_config_error.h>
#include <hooks/hooks_parser.h>
......@@ -37,6 +38,33 @@ namespace netconf {
const SimpleDefaults NetconfSimpleParser::NETCONF_DEFAULTS = {
};
/// Supplies defaults for control-socket elements
const SimpleDefaults NetconfSimpleParser::CTRL_SOCK_DEFAULTS = {
{ "socket-type", Element::string, "stdout" },
{ "socket-name", Element::string, "" },
{ "socket-url" , Element::string, "http://127.0.0.1:8000/" }
};
/// Supplies defaults for dhcp4 managed server
const SimpleDefaults NetconfSimpleParser::DHCP4_DEFAULTS = {
{ "model", Element::string, "kea-dhcp4-server" }
};
/// Supplies defaults for dhcp6 managed server
const SimpleDefaults NetconfSimpleParser::DHCP6_DEFAULTS = {
{ "model", Element::string, "kea-dhcp6-server" }
};
/// Supplies defaults for d2 managed server
const SimpleDefaults NetconfSimpleParser::D2_DEFAULTS = {
{ "model", Element::string, "kea-dhcp-ddns" }
};
/// Supplies defaults for ca managed server
const SimpleDefaults NetconfSimpleParser::CA_DEFAULTS = {
{ "model", Element::string, "kea-ctrl-agent" }
};
/// @}
/// ---------------------------------------------------------------------------
......@@ -49,6 +77,41 @@ size_t NetconfSimpleParser::setAllDefaults(const isc::data::ElementPtr& global)
// Set global defaults first.
cnt = setDefaults(global, NETCONF_DEFAULTS);
ConstElementPtr servers = global->get("managed-servers");
if (servers) {
for (auto it : servers->mapValue()) {
cnt += setServerDefaults(it.first, it.second);
}
}
return (cnt);
}
size_t
NetconfSimpleParser::setServerDefaults(const std::string name,
isc::data::ConstElementPtr server) {
size_t cnt = 0;
isc::data::ElementPtr mutable_server =
boost::const_pointer_cast<Element>(server);
if (name == "dhcp4") {
cnt += setDefaults(mutable_server, DHCP4_DEFAULTS);
} else if (name == "dhcp6") {
cnt += setDefaults(mutable_server, DHCP6_DEFAULTS);
} else if (name == "d2") {
cnt += setDefaults(mutable_server, D2_DEFAULTS);
} else if (name == "ca") {
cnt += setDefaults(mutable_server, CA_DEFAULTS);
}
isc::data::ConstElementPtr ctrl_sock = server->get("control-socket");
if (!ctrl_sock) {
return (cnt);
}
isc::data::ElementPtr mutable_ctrl_sock =
boost::const_pointer_cast<Element>(ctrl_sock);
cnt += setDefaults(mutable_ctrl_sock, CTRL_SOCK_DEFAULTS);
return (cnt);
}
......@@ -63,6 +126,16 @@ NetconfSimpleParser::parse(const NetconfConfigPtr& ctx,
ctx->setContext(user_context);
}
// get managed servers.