From: Francis Dupont Date: Fri, 19 Oct 2018 22:52:10 +0000 (+0200) Subject: [65-libyang-config-adaptor] Added config adaptor code from kea-yang X-Git-Tag: 65-libyang-config-translator_base~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=48c5eb9b88343431f8fb69a3ba14c2f13e5d62c8;p=thirdparty%2Fkea.git [65-libyang-config-adaptor] Added config adaptor code from kea-yang --- diff --git a/src/lib/yang/Makefile.am b/src/lib/yang/Makefile.am index 74aae0da0c..80ba2fc377 100644 --- a/src/lib/yang/Makefile.am +++ b/src/lib/yang/Makefile.am @@ -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 \ diff --git a/src/lib/yang/adaptor_config.cc b/src/lib/yang/adaptor_config.cc new file mode 100644 index 0000000000..142546424c --- /dev/null +++ b/src/lib/yang/adaptor_config.cc @@ -0,0 +1,445 @@ +// 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 + +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(dhcp); + mutable_dhcp->remove("hosts-database"); + ElementPtr list = Element::createList(); + list->add(boost::const_pointer_cast(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(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 diff --git a/src/lib/yang/adaptor_config.h b/src/lib/yang/adaptor_config.h new file mode 100644 index 0000000000..f06fbcbbe5 --- /dev/null +++ b/src/lib/yang/adaptor_config.h @@ -0,0 +1,218 @@ +// 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 +#include +#include +#include +#include + +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