Browse Source

[5305] Basic toElement() data dump for shared network implemented.

Marcin Siodelski 7 years ago
parent
commit
47215e3743

+ 1 - 1
src/lib/dhcpsrv/Makefile.am

@@ -141,7 +141,7 @@ libkea_dhcpsrv_la_SOURCES += mysql_host_data_source.cc mysql_host_data_source.h
 endif
 
 libkea_dhcpsrv_la_SOURCES += ncr_generator.cc ncr_generator.h
-libkea_dhcpsrv_la_SOURCES += network.h
+libkea_dhcpsrv_la_SOURCES += network.cc network.h
 
 if HAVE_PGSQL
 libkea_dhcpsrv_la_SOURCES += pgsql_connection.cc pgsql_connection.h

+ 32 - 0
src/lib/dhcpsrv/network.cc

@@ -0,0 +1,32 @@
+// Copyright (C) 2017 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 <dhcpsrv/network.h>
+
+using namespace isc::data;
+
+namespace isc {
+namespace dhcp {
+
+ElementPtr
+Network::toElement() const {
+    ElementPtr map = Element::createMap();
+
+    // Set interface
+    const std::string& iface = getIface();
+    if (!iface.empty()) {
+        map->set("interface", Element::create(iface));
+    }
+
+    // Set options
+    ConstCfgOptionPtr opts = getCfgOption();
+    map->set("option-data", opts->toElement());
+
+    return (map);
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc

+ 28 - 1
src/lib/dhcpsrv/network.h

@@ -7,6 +7,10 @@
 #ifndef NETWORK_H
 #define NETWORK_H
 
+#include <cc/cfg_to_element.h>
+#include <cc/data.h>
+#include <dhcpsrv/cfg_option.h>
+#include <dhcpsrv/cfg_4o6.h>
 #include <boost/shared_ptr.hpp>
 #include <string>
 
@@ -30,9 +34,14 @@ namespace dhcp {
 /// class provides an abstract interface that must be implemented by derived
 /// classes and, where appropriate, implements common methods used by the
 /// derived classes.
-class Network {
+class Network : public data::CfgToElement {
 public:
 
+    /// @brief Constructor.
+    Network()
+        : iface_name_(), cfg_option_(new CfgOption()) {
+    }
+
     /// @brief Virtual destructor.
     ///
     /// Does nothing at the moment.
@@ -58,11 +67,29 @@ public:
         return (iface_name_);
     };
 
+    /// @brief Returns pointer to the option data configuration for this subnet.
+    CfgOptionPtr getCfgOption() {
+        return (cfg_option_);
+    }
+
+    /// @brief Returns const pointer to the option data configuration for this
+    /// subnet.
+    ConstCfgOptionPtr getCfgOption() const {
+        return (cfg_option_);
+    }
+
+    /// @brief Unparses network object.
+    ///
+    /// @return A pointer to unparsed network configuration.
+    virtual data::ElementPtr toElement() const;
+
 protected:
 
     /// @brief Holds interface name for which this network is selected.
     std::string iface_name_;
 
+    /// @brief Pointer to the option data configuration for this subnet.
+    CfgOptionPtr cfg_option_;
 };
 
 /// @brief Pointer to the @ref Network object.

+ 41 - 0
src/lib/dhcpsrv/shared_network.cc

@@ -6,11 +6,24 @@
 
 #include <dhcpsrv/shared_network.h>
 
+using namespace isc::data;
 using namespace isc::dhcp;
 
 namespace isc {
 namespace dhcp {
 
+ElementPtr
+SharedNetwork::toElement() const {
+    ElementPtr map = Network::toElement();
+
+    // Set shared network name.
+    if (!name_.empty()) {
+        map->set("name", Element::create(name_));
+    }
+
+    return (map);
+}
+
 NetworkPtr
 SharedNetwork4::sharedFromThis() {
     return (shared_from_this());
@@ -38,6 +51,20 @@ SharedNetwork4::getNextSubnet(const Subnet4Ptr& first_subnet,
                                          current_subnet));
 }
 
+ElementPtr
+SharedNetwork4::toElement() const {
+    ElementPtr map = SharedNetwork::toElement();
+
+    ElementPtr subnet4 = Element::createList();
+    for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
+        subnet4->add((*subnet)->toElement());
+    }
+
+    map->set("subnet4", subnet4);
+
+    return (map);
+}
+
 NetworkPtr
 SharedNetwork6::sharedFromThis() {
     return (shared_from_this());
@@ -65,5 +92,19 @@ SharedNetwork6::getNextSubnet(const Subnet6Ptr& first_subnet,
                                          current_subnet));
 }
 
+ElementPtr
+SharedNetwork6::toElement() const {
+    ElementPtr map = SharedNetwork::toElement();
+
+    ElementPtr subnet6 = Element::createList();
+    for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
+        subnet6->add((*subnet)->toElement());
+    }
+
+    map->set("subnet6", subnet6);
+
+    return (map);
+}
+
 } // end of namespace isc::dhcp
 } // end of namespace isc

+ 15 - 1
src/lib/dhcpsrv/shared_network.h

@@ -7,6 +7,7 @@
 #ifndef SHARED_NETWORK_H
 #define SHARED_NETWORK_H
 
+#include <cc/data.h>
 #include <exceptions/exceptions.h>
 #include <dhcpsrv/assignable_network.h>
 #include <dhcpsrv/subnet.h>
@@ -245,7 +246,10 @@ protected:
         return (*subnet_it);
     }
 
-protected:
+    /// @brief Unparses shared network object.
+    ///
+    /// @return A pointer to unparsed shared network configuration.
+    virtual data::ElementPtr toElement() const;
 
     /// @brief Holds a name of a shared network.
     std::string name_;
@@ -322,6 +326,11 @@ public:
     Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet,
                              const Subnet4Ptr& current_subnet) const;
 
+    /// @brief Unparses shared network object.
+    ///
+    /// @return A pointer to unparsed shared network configuration.
+    virtual data::ElementPtr toElement() const;
+
 private:
 
     /// @brief Collection of IPv4 subnets within shared network.
@@ -402,6 +411,11 @@ public:
     Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet,
                              const Subnet6Ptr& current_subnet) const;
 
+    /// @brief Unparses shared network object.
+    ///
+    /// @return A pointer to unparsed shared network configuration.
+    virtual data::ElementPtr toElement() const;
+
 private:
 
     /// @brief Collection of IPv6 subnets within shared network.

+ 8 - 19
src/lib/dhcpsrv/subnet.cc

@@ -55,13 +55,13 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
                const Triplet<uint32_t>& valid_lifetime,
                const isc::dhcp::Subnet::RelayInfo& relay,
                const SubnetID id)
-    :id_(id == 0 ? generateNextID() : id), prefix_(prefix), prefix_len_(len),
-     t1_(t1), t2_(t2), valid_(valid_lifetime),
-     last_allocated_ia_(lastAddrInPrefix(prefix, len)),
-     last_allocated_ta_(lastAddrInPrefix(prefix, len)),
-     last_allocated_pd_(lastAddrInPrefix(prefix, len)), relay_(relay),
-     host_reservation_mode_(HR_ALL), cfg_option_(new CfgOption())
-      {
+    : Network(), id_(id == 0 ? generateNextID() : id), prefix_(prefix),
+      prefix_len_(len),
+      t1_(t1), t2_(t2), valid_(valid_lifetime),
+      last_allocated_ia_(lastAddrInPrefix(prefix, len)),
+      last_allocated_ta_(lastAddrInPrefix(prefix, len)),
+      last_allocated_pd_(lastAddrInPrefix(prefix, len)), relay_(relay),
+      host_reservation_mode_(HR_ALL) {
     if ((prefix.isV6() && len > 128) ||
         (prefix.isV4() && len > 32)) {
         isc_throw(BadValue,
@@ -465,8 +465,7 @@ void Subnet6::checkType(Lease::Type type) const {
 
 data::ElementPtr
 Subnet::toElement() const {
-    // Prepare the map
-    ElementPtr map = Element::createMap();
+    ElementPtr map = Network::toElement();
 
     // Set subnet id
     SubnetID id = getID();
@@ -481,12 +480,6 @@ Subnet::toElement() const {
     // Set subnet
     map->set("subnet", Element::create(toText()));
 
-    // Set interface
-    const std::string& iface = getIface();
-    if (!iface.empty()) {
-        map->set("interface", Element::create(iface));
-    }
-
     // Set renew-timer
     map->set("renew-timer",
              Element::create(static_cast<long long>
@@ -528,10 +521,6 @@ Subnet::toElement() const {
         map->set("client-class", Element::create(*cclasses.cbegin()));
     }
 
-    // Set options
-    ConstCfgOptionPtr opts = getCfgOption();
-    map->set("option-data", opts->toElement());
-
     return (map);
 }
 

+ 0 - 16
src/lib/dhcpsrv/subnet.h

@@ -13,8 +13,6 @@
 #include <dhcp/classify.h>
 #include <dhcp/option_space_container.h>
 #include <dhcpsrv/assignable_network.h>
-#include <dhcpsrv/cfg_option.h>
-#include <dhcpsrv/cfg_4o6.h>
 #include <dhcpsrv/lease.h>
 #include <dhcpsrv/pool.h>
 #include <dhcpsrv/subnet_id.h>
@@ -114,17 +112,6 @@ public:
         return (t2_);
     }
 
-    /// @brief Returns pointer to the option data configuration for this subnet.
-    CfgOptionPtr getCfgOption() {
-        return (cfg_option_);
-    }
-
-    /// @brief Returns const pointer to the option data configuration for this
-    /// subnet.
-    ConstCfgOptionPtr getCfgOption() const {
-        return (cfg_option_);
-    }
-
     /// @brief returns the last address that was tried from this pool
     ///
     /// This method returns the last address that was attempted to be allocated
@@ -551,9 +538,6 @@ protected:
     /// See @ref HRMode type for details.
     HRMode host_reservation_mode_;
 
-    /// @brief Pointer to the option data configuration for this subnet.
-    CfgOptionPtr cfg_option_;
-
     NetworkPtr shared_network_;
 };
 

+ 120 - 0
src/lib/dhcpsrv/tests/shared_network_unittest.cc

@@ -4,12 +4,14 @@
 // 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/io_address.h>
 #include <dhcpsrv/shared_network.h>
 #include <dhcpsrv/subnet.h>
 #include <dhcpsrv/subnet_id.h>
 #include <dhcpsrv/triplet.h>
 #include <exceptions/exceptions.h>
+#include <testutils/test_to_element.h>
 #include <gtest/gtest.h>
 #include <cstdint>
 #include <vector>
@@ -181,6 +183,68 @@ TEST(SharedNetwork4Test, getNextSubnet) {
     }
 }
 
+// This test verifies that unparsing shared network returns valid structure.
+TEST(SharedNetwork4Test, unparse) {
+    SharedNetwork4Ptr network(new SharedNetwork4("frog"));
+
+    // Set interface name.
+    network->setIface("eth1");
+
+    // Add several subnets.
+    Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30,
+                                   SubnetID(1)));
+    Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.0"), 24, 10, 20, 30,
+                                   SubnetID(2)));
+    network->add(subnet1);
+    network->add(subnet2);
+
+    std::string expected = "{\n"
+        "    \"interface\": \"eth1\",\n"
+        "    \"name\": \"frog\",\n"
+        "    \"option-data\": [ ],\n"
+        "    \"subnet4\": [\n"
+        "      {\n"
+        "        \"4o6-interface\": \"\",\n"
+        "        \"4o6-interface-id\": \"\",\n"
+        "        \"4o6-subnet\": \"\",\n"
+        "        \"id\": 1,\n"
+        "        \"match-client-id\": true,\n"
+        "        \"next-server\": \"0.0.0.0\",\n"
+        "        \"option-data\": [ ],\n"
+        "        \"pools\": [ ],\n"
+        "        \"rebind-timer\": 20,\n"
+        "        \"relay\": {\n"
+        "          \"ip-address\": \"0.0.0.0\"\n"
+        "        },\n"
+        "        \"renew-timer\": 10,\n"
+        "        \"reservation-mode\": \"all\",\n"
+        "        \"subnet\": \"10.0.0.0/8\",\n"
+        "        \"valid-lifetime\": 30\n"
+        "      },\n"
+        "      {\n"
+        "        \"4o6-interface\": \"\",\n"
+        "        \"4o6-interface-id\": \"\",\n"
+        "        \"4o6-subnet\": \"\",\n"
+        "        \"id\": 2,\n"
+        "        \"match-client-id\": true,\n"
+        "        \"next-server\": \"0.0.0.0\",\n"
+        "        \"option-data\": [ ],\n"
+        "        \"pools\": [ ],\n"
+        "        \"rebind-timer\": 20,\n"
+        "        \"relay\": {\n"
+        "          \"ip-address\": \"0.0.0.0\"\n"
+        "        },\n"
+        "        \"renew-timer\": 10,\n"
+        "        \"reservation-mode\": \"all\",\n"
+        "        \"subnet\": \"192.0.2.0/24\",\n"
+        "        \"valid-lifetime\": 30\n"
+        "      }\n"
+        "    ]\n"
+        "}\n";
+
+    test::runToElementTest<SharedNetwork4>(expected, *network);
+}
+
 // This test verifies that shared network can be given a name and that
 // this name can be retrieved.
 TEST(SharedNetwork6Test, getName) {
@@ -342,4 +406,60 @@ TEST(SharedNetwork6Test, getNextSubnet) {
     }
 }
 
+// This test verifies that unparsing shared network returns valid structure.
+TEST(SharedNetwork6Test, unparse) {
+    SharedNetwork6Ptr network(new SharedNetwork6("frog"));
+    network->setIface("eth1");
+
+    // Add several subnets.
+    Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 10, 20, 30,
+                                   40, SubnetID(1)));
+    Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 16, 10, 20, 30, 40,
+                                   SubnetID(2)));
+    network->add(subnet1);
+    network->add(subnet2);
+
+    std::string expected = "{\n"
+        "    \"interface\": \"eth1\",\n"
+        "    \"name\": \"frog\",\n"
+        "    \"option-data\": [ ],\n"
+        "    \"subnet6\": [\n"
+        "      {\n"
+        "        \"id\": 1,\n"
+        "        \"option-data\": [ ],\n"
+        "        \"pd-pools\": [ ],\n"
+        "        \"pools\": [ ],\n"
+        "        \"preferred-lifetime\": 30,\n"
+        "        \"rapid-commit\": false,\n"
+        "        \"rebind-timer\": 20,\n"
+        "        \"relay\": {\n"
+        "          \"ip-address\": \"::\"\n"
+        "        },\n"
+        "        \"renew-timer\": 10,\n"
+        "        \"reservation-mode\": \"all\",\n"
+        "        \"subnet\": \"2001:db8:1::/64\",\n"
+        "        \"valid-lifetime\": 40\n"
+        "      },\n"
+        "      {\n"
+        "        \"id\": 2,\n"
+        "        \"option-data\": [ ],\n"
+        "        \"pd-pools\": [ ],\n"
+        "        \"pools\": [ ],\n"
+        "        \"preferred-lifetime\": 30,\n"
+        "        \"rapid-commit\": false,\n"
+        "        \"rebind-timer\": 20,\n"
+        "        \"relay\": {\n"
+        "          \"ip-address\": \"::\"\n"
+        "        },\n"
+        "        \"renew-timer\": 10,\n"
+        "        \"reservation-mode\": \"all\",\n"
+        "        \"subnet\": \"3000::/16\",\n"
+        "        \"valid-lifetime\": 40\n"
+        "      }\n"
+        "    ]\n"
+        "}\n";
+
+    test::runToElementTest<SharedNetwork6>(expected, *network);
+}
+
 } // end of anonymous namespace