Commit 48c5eb9b authored by Francis Dupont's avatar Francis Dupont Committed by Tomek Mrugalski

[65-libyang-config-adaptor] Added config adaptor code from kea-yang

parent 7b18ca62
......@@ -10,6 +10,7 @@ libkea_yang_la_SOURCES += adaptor_host.cc adaptor_host.h
libkea_yang_la_SOURCES += adaptor_pool.cc adaptor_pool.h
libkea_yang_la_SOURCES += adaptor_option.cc adaptor_option.h
libkea_yang_la_SOURCES += adaptor_subnet.cc adaptor_subnet.h
libkea_yang_la_SOURCES += adaptor_config.cc adaptor_config.h
libkea_yang_la_SOURCES += sysrepo_error.h
libkea_yang_la_SOURCES += translator.cc translator.h
libkea_yang_la_SOURCES += translator_control_socket.cc
......@@ -43,6 +44,7 @@ libkea_yang_la_LDFLAGS = -no-undefined -version-info 0:0:0
libkea_yang_includedir = $(pkgincludedir)/yang
libkea_yang_include_HEADERS = \
adaptor.h \
adaptor_config.h \
adaptor_host.h \
adaptor_option.h \
adaptor_pool.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 <yang/adaptor_config.h>
using namespace std;
using namespace isc::data;
using namespace isc::dhcp;
namespace isc {
namespace yang {
AdaptorConfig::AdaptorConfig() {
}
AdaptorConfig::~AdaptorConfig() {
}
bool
AdaptorConfig::subnetsCollectID(ConstElementPtr subnets, SubnetIDSet& set) {
bool have_ids = true;
if (subnets && (subnets->size() > 0)) {
for (ConstElementPtr subnet : subnets->listValue()) {
if (!collectID(subnet, set)) {
have_ids = false;
}
}
}
return (have_ids);
}
bool
AdaptorConfig::shareNetworksCollectID(ConstElementPtr networks,
SubnetIDSet& set, const string& subsel) {
bool have_ids = true;
if (networks && (networks->size() > 0)) {
for (size_t i = 0; i < networks->size(); ++i) {
ElementPtr network = networks->getNonConst(i);
ConstElementPtr subnets = network->get(subsel);
if (subnets) {
if (subnets->size() > 0) {
if (!subnetsCollectID(subnets, set)) {
have_ids = false;
}
} else {
network->remove(subsel);
}
}
}
}
return (have_ids);
}
void
AdaptorConfig::subnetsAssignID(ConstElementPtr subnets, SubnetIDSet& set,
SubnetID& next) {
if (subnets && (subnets->size() > 0)) {
for (size_t i = 0; i < subnets->size(); ++i) {
ElementPtr subnet = subnets->getNonConst(i);
assignID(subnet, set, next);
}
}
}
void
AdaptorConfig::shareNetworksAssignID(ConstElementPtr networks,
SubnetIDSet& set, SubnetID& next,
const string& subsel) {
if (networks && (networks->size() > 0)) {
for (ConstElementPtr network : networks->listValue()) {
ConstElementPtr subnets = network->get(subsel);
if (subnets && (subnets->size() > 0)) {
for (size_t i = 0; i < subnets->size(); ++i) {
ElementPtr subnet = subnets->getNonConst(i);
assignID(subnet, set, next);
}
}
}
}
}
void
AdaptorConfig::canonizePools(ConstElementPtr pools) {
if (pools && (pools->size() > 0)) {
for (size_t i = 0; i < pools->size(); ++i) {
ElementPtr pool = pools->getNonConst(i);
AdaptorPool::canonizePool(pool);
}
}
}
void
AdaptorConfig::poolSubnets(ConstElementPtr subnets) {
if (subnets && (subnets->size() > 0)) {
for (ConstElementPtr subnet : subnets->listValue()) {
canonizePools(subnet->get("pools"));
}
}
}
void
AdaptorConfig::poolShareNetworks(ConstElementPtr networks,
const string& subsel) {
if (networks && (networks->size() > 0)) {
for (ConstElementPtr network : networks->listValue()) {
poolSubnets(network->get(subsel));
}
}
}
void
AdaptorConfig::optionDefList(ConstElementPtr defs,
const string& space,
OptionCodes& codes) {
if (defs && (defs->size() > 0)) {
for (size_t i = 0; i < defs->size(); ++i) {
ElementPtr def = defs->getNonConst(i);
checkCode(def);
checkType(def);
setSpace(def, space);
collect(def, codes);
}
}
}
void
AdaptorConfig::optionDataList(ConstElementPtr options,const string& space,
const OptionCodes& codes) {
if (options && (options->size() > 0)) {
for (size_t i = 0; i < options->size(); ++i) {
ElementPtr option = options->getNonConst(i);
setSpace(option, space);
setCode(option, codes);
}
}
}
void
AdaptorConfig::optionClasses(ConstElementPtr classes, const string& space,
OptionCodes& codes) {
if (classes && (classes->size() > 0)) {
for (size_t i = 0; i < classes->size(); ++i) {
ElementPtr cclass = classes->getNonConst(i);
if (space == "dhcp4") {
ConstElementPtr options = cclass->get("option-def");
if (options) {
if (options->size() > 0) {
optionDefList(options, space, codes);
} else {
cclass->remove("option-def");
}
}
}
ConstElementPtr options = cclass->get("option-data");
if (options) {
if (options->size() > 0) {
optionDataList(options, space, codes);
} else {
cclass->remove("option-data");
}
}
}
}
}
void
AdaptorConfig::optionPools(ConstElementPtr pools, const string& space,
const OptionCodes& codes) {
if (pools && (pools->size() > 0)) {
for (size_t i = 0; i < pools->size(); ++i) {
ElementPtr pool = pools->getNonConst(i);
ConstElementPtr options = pool->get("option-data");
if (options) {
if (options->size() > 0) {
optionDataList(options, space, codes);
} else {
pool->remove("option-data");
}
}
}
}
}
void
AdaptorConfig::optionHosts(ConstElementPtr hosts, const string& space,
const OptionCodes& codes) {
if (hosts && (hosts->size() > 0)) {
for (size_t i = 0; i < hosts->size(); ++i) {
ElementPtr host = hosts->getNonConst(i);
ConstElementPtr options = host->get("option-data");
if (options) {
if (options->size() > 0) {
optionDataList(options, space, codes);
} else {
host->remove("option-data");
}
}
}
}
}
void
AdaptorConfig::optionSubnets(ConstElementPtr subnets, const string& space,
const OptionCodes& codes) {
if (subnets && (subnets->size() > 0)) {
for (size_t i = 0; i < subnets->size(); ++i) {
ElementPtr subnet = subnets->getNonConst(i);
ConstElementPtr options = subnet->get("option-data");
if (options) {
if (options->size() > 0) {
optionDataList(options, space, codes);
} else {
subnet->remove("option-data");
}
}
ConstElementPtr pools = subnet->get("pools");
if (pools) {
if (pools->size() > 0) {
optionPools(pools, space, codes);
} else {
subnet->remove("pools");
}
}
if (space == "dhcp6") {
ConstElementPtr pools = subnet->get("pd-pools");
if (pools) {
if (pools->size() > 0) {
optionPools(pools, space, codes);
} else {
subnet->remove("pd-pools");
}
}
}
ConstElementPtr hosts = subnet->get("reservations");
if (hosts) {
if (hosts->size() > 0) {
optionHosts(hosts, space, codes);
} else {
subnet->remove("reservations");
}
}
}
}
}
void
AdaptorConfig::optionSharedNetworks(ConstElementPtr networks,
const string& space,
const OptionCodes& codes) {
if (networks && (networks->size() > 0)) {
for (size_t i = 0; i < networks->size(); ++i) {
ElementPtr network = networks->getNonConst(i);
ConstElementPtr options = network->get("option-data");
if (options) {
if (options->size() > 0) {
optionDataList(options, space, codes);
} else {
network->remove("option-data");
}
}
string subnet = "subnet";
if (space == "dhcp4") {
subnet += "4";
} else {
subnet += "6";
}
ConstElementPtr subnets = network->get(subnet);
if (subnets) {
if (subnets->size() > 0) {
optionSubnets(subnets, space, codes);
} else {
network->remove(subnet);
}
}
}
}
}
void
AdaptorConfig::hostList(ConstElementPtr hosts) {
if (hosts && (hosts->size() > 0)) {
for (size_t i = 0; i < hosts->size(); ++i) {
ElementPtr host = hosts->getNonConst(i);
quoteIdentifier(host);
}
}
}
void
AdaptorConfig::hostSubnets(ConstElementPtr subnets) {
if (subnets && (subnets->size() > 0)) {
for (ConstElementPtr subnet : subnets->listValue()) {
hostList(subnet->get("reservations"));
}
}
}
void
AdaptorConfig::hostSharedNetworks(ConstElementPtr networks,
const string& space) {
if (networks && (networks->size() > 0)) {
for (ConstElementPtr network : networks->listValue()) {
if (space == "dhcp4") {
hostSubnets(network->get("subnet4"));
} else {
hostSubnets(network->get("subnet6"));
}
}
}
}
void
AdaptorConfig::relaySubnets(ConstElementPtr subnets) {
if (subnets && (subnets->size() > 0)) {
for (size_t i = 0; i < subnets->size(); ++i) {
ElementPtr subnet = subnets->getNonConst(i);
updateRelay(subnet);
}
}
}
void
AdaptorConfig::relaySharedNetworks(ConstElementPtr networks,
const string& subsel) {
if (networks && (networks->size() > 0)) {
for (size_t i = 0; i < networks->size(); ++i) {
ElementPtr network = networks->getNonConst(i);
updateRelay(network);
relaySubnets(network->get(subsel));
}
}
}
void
AdaptorConfig::updateDatabase(ConstElementPtr dhcp) {
ConstElementPtr database = dhcp->get("hosts-database");
if (!database) {
return;
}
ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
mutable_dhcp->remove("hosts-database");
ElementPtr list = Element::createList();
list->add(boost::const_pointer_cast<Element>(database));
mutable_dhcp->set("hosts-databases", list);
}
void
AdaptorConfig::preProcess(ConstElementPtr dhcp, const string& subsel,
const string& space) {
ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
bool have_ids = true;
SubnetIDSet set;
ConstElementPtr subnets = dhcp->get(subsel);
if (subnets) {
if (subnets->size() > 0) {
if (!subnetsCollectID(subnets, set)) {
have_ids = false;
}
} else {
mutable_dhcp->remove(subsel);
}
}
ConstElementPtr networks = dhcp->get("shared-networks");
if (networks) {
if (networks->size() > 0) {
if (!shareNetworksCollectID(networks, set, subsel)) {
have_ids = false;
}
} else {
mutable_dhcp->remove("shared-networks");
}
}
if (!have_ids) {
SubnetID next(1);
subnetsAssignID(subnets, set, next);
shareNetworksAssignID(networks, set, next, subsel);
}
OptionCodes codes;
initCodes(codes, space);;
ConstElementPtr defs = dhcp->get("option-def");
if (defs) {
if (defs->size() > 0) {
optionDefList(defs, space, codes);
} else {
mutable_dhcp->remove("option-def");
}
}
ConstElementPtr options = dhcp->get("option-data");
if (options) {
if (options->size() > 0) {
optionDataList(options, space, codes);
} else {
mutable_dhcp->remove("option-data");
}
}
ConstElementPtr classes = dhcp->get("client-classes");
if (classes) {
if (classes->size() > 0) {
optionClasses(classes, space, codes);
} else {
mutable_dhcp->remove("client-classes");
}
}
ConstElementPtr hosts = dhcp->get("reservations");
if (hosts) {
if (hosts->size() > 0) {
optionHosts(hosts, space, codes);
} else {
mutable_dhcp->remove("reservations");
}
}
optionSubnets(subnets, space, codes);
optionSharedNetworks(networks, space, codes);
poolSubnets(subnets);
poolShareNetworks(networks, subsel);
hostSubnets(subnets);
hostSharedNetworks(networks, space);
relaySubnets(subnets);
relaySharedNetworks(networks, subsel);
updateDatabase(dhcp);
}
void
AdaptorConfig::preProcess4(ConstElementPtr config) {
ConstElementPtr dhcp = config->get("Dhcp4");
preProcess(config->get("Dhcp4"), "subnet4", "dhcp4");
}
void
AdaptorConfig::preProcess6(ConstElementPtr config) {
ConstElementPtr dhcp = config->get("Dhcp6");
preProcess(config->get("Dhcp6"), "subnet6", "dhcp6");
}
}; // end of namespace isc::yang
}; // end of 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 ISC_ADAPTOR_CONFIG_H
#define ISC_ADAPTOR_CONFIG_H 1
#include <yang/adaptor_host.h>
#include <yang/adaptor_option.h>
#include <yang/adaptor_pool.h>
#include <yang/adaptor_subnet.h>
#include <list>
namespace isc {
namespace yang {
/// @brief JSON adaptor for configurations.
class AdaptorConfig : public AdaptorHost, public AdaptorOption,
public AdaptorSubnet {
public:
/// @brief Constructor.
AdaptorConfig();
/// @brief Destructor.
virtual ~AdaptorConfig();
/// @brief Pre process a DHCPv4 configuration.
///
/// Assign subnet IDs, check and set default in options.
///
/// @param config The configuration.
/// @throw MissingKey when a required key is missing.
static void preProcess4(isc::data::ConstElementPtr config);
/// @brief Pre process a DHCPv6 configuration.
///
/// Assign subnet IDs, check and set default in options.
///
/// @param config The configuration.
/// @throw MissingKey when a required key is missing.
static void preProcess6(isc::data::ConstElementPtr config);
protected:
/// @brief collectID for a subnet list.
///
/// @param subnets The subnet list.
/// @param set The reference to the set of assigned IDs.
/// @return True if all subnets have an ID, false otherwise.
static bool subnetsCollectID(isc::data::ConstElementPtr subnets,
SubnetIDSet& set);
/// @brief collectID for a shared network list.
///
/// @param networks The shared network list.
/// @param set The reference to the set of assigned IDs.
/// @param subsel The subnet list name.
/// @return True if all subnets have an ID, false otherwise.
static bool shareNetworksCollectID(isc::data::ConstElementPtr networks,
SubnetIDSet& set,
const std::string& subsel);
/// @brief assignID for a subnet list.
///
/// @param subnets The subnet list.
/// @param set The reference to the set of assigned IDs.
/// @param next The next ID.
/// @return True if all subnets have an ID, false otherwise.
static void subnetsAssignID(isc::data::ConstElementPtr subnets,
SubnetIDSet& set, isc::dhcp::SubnetID& next);
/// @brief assignID for a shared network list.
///
/// @param networks The shared network list.
/// @param set The reference to the set of assigned IDs.
/// @param next The next ID.
/// @param subsel The subnet list name.
/// @return True if all subnets have an ID, false otherwise.
static void shareNetworksAssignID(isc::data::ConstElementPtr networks,
SubnetIDSet& set,
isc::dhcp::SubnetID& next,
const std::string& subsel);
/// @brief canonizePool for a pool list.
///
/// @param pools The pool list.
static void canonizePools(isc::data::ConstElementPtr pools);
/// @brief canonizePool for a subnet list.
///
/// @param subnets The subnet list.
static void poolSubnets(isc::data::ConstElementPtr subnets);
/// @brief canonizePool for a shared network list.
///
/// @param networks The shared network list.
/// @param subsel The subnet list name.
static void poolShareNetworks(isc::data::ConstElementPtr networks,
const std::string& subsel);
/// @brief Process an option definition list.
///
/// @param defs The option definition list.
/// @param space The default space name.
/// @param codes Option definitions.
static void optionDefList(isc::data::ConstElementPtr defs,
const std::string& space,
OptionCodes& codes);
/// @brief Process an option data list.
///
/// @param options The option data list.
/// @param space The default space name.
/// @param codes Option definitions.
static void optionDataList(isc::data::ConstElementPtr options,
const std::string& space,
const OptionCodes& codes);
/// @brief Process options in a client class list.
///
/// @param classes The client class list.
/// @param space The default space name.
/// @param codes Option definitions.
static void optionClasses(isc::data::ConstElementPtr classes,
const std::string& space,
OptionCodes& codes);
/// @brief Process options in a pool list.
///
/// @param pools The pool list.
/// @param space The default space name.
/// @param codes Option definitions.
static void optionPools(isc::data::ConstElementPtr pools,
const std::string& space,
const OptionCodes& codes);
/// @brief Process options in a host reservation list.
///
/// @param hosts The host reservation list.
/// @param space The default space name.
/// @param codes Option definitions.
static void optionHosts(isc::data::ConstElementPtr hosts,
const std::string& space,
const OptionCodes& codes);
/// @brief Process options in a subnet list.
///
/// @param subnets The subnet list.
/// @param space The default space name.
/// @param codes Option definitions.
static void optionSubnets(isc::data::ConstElementPtr subnets,
const std::string& space,
const OptionCodes& codes);
/// @brief Process options in a shared network list.
///
/// @param networks The shared network list.
/// @param space The default space name.
/// @param codes Option definitions.
static void optionSharedNetworks(isc::data::ConstElementPtr networks,
const std::string& space,
const OptionCodes& codes);
/// @brief Process host reservation list.
///
/// @param hosts The host reservation list.
static void hostList(isc::data::ConstElementPtr hosts);
/// @brief Process host reservations in a subnet list.
///
/// @param subnets The subnet list.
static void hostSubnets(isc::data::ConstElementPtr subnets);
/// @brief Process host reservations in a shared network list.
///
/// @param networks The shared network list.
/// @param space The default space name.
static void hostSharedNetworks(isc::data::ConstElementPtr networks,
const std::string& space);
/// @brief updateRelay in a subnet list.
///
/// @param subnets The subnet list.
static void relaySubnets(isc::data::ConstElementPtr subnets);
/// @brief updateRelay in a shared network list.
///
/// @param networks The shared network list.
/// @param subsel The subnet list name.
static void relaySharedNetworks(isc::data::ConstElementPtr networks,
const std::string& subsel);
/// @brief Update (hosts) database.
///
/// Force the use of hosts-databases vs. hosts-database.
///
/// @param dhcp The DHCP server.
static void updateDatabase(isc::data::ConstElementPtr dhcp);
/// @brief Pre process a configuration.
///
/// Assign subnet IDs, check and set default in options.
///
/// @param dhcp The server configuration.
/// @param subsel The subnet list name.
/// @param space The default option space name.
/// @throw MissingKey when a required key is missing.
static void preProcess(isc::data::ConstElementPtr dhcp,
const std::string& subsel,
const std::string& space);
};
}; // end of namespace isc::yang
}; // end of namespace isc
#endif // ISC_ADAPTOR_CONFIG_H