]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[65-libyang-config-adaptor] Added config adaptor code from kea-yang
authorFrancis Dupont <fdupont@isc.org>
Fri, 19 Oct 2018 22:52:10 +0000 (00:52 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Mon, 22 Oct 2018 18:28:37 +0000 (20:28 +0200)
src/lib/yang/Makefile.am
src/lib/yang/adaptor_config.cc [new file with mode: 0644]
src/lib/yang/adaptor_config.h [new file with mode: 0644]

index 74aae0da0c5c013e949492489eff2cb63b749482..80ba2fc3773321a2859e3a92856da8271fffb518 100644 (file)
@@ -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 (file)
index 0000000..1425464
--- /dev/null
@@ -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 <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
diff --git a/src/lib/yang/adaptor_config.h b/src/lib/yang/adaptor_config.h
new file mode 100644 (file)
index 0000000..f06fbcb
--- /dev/null
@@ -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 <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