Browse Source

[3798] subnet[id].total-addresses implemented.

Tomek Mrugalski 10 years ago
parent
commit
9c9ef6973e

+ 35 - 0
doc/guide/dhcp4-srv.xml

@@ -2583,6 +2583,41 @@ temporarily override a list of interface names and listen on all interfaces.
     </section>
 
 
+<!-- proper section structure added in ticket 3794, will merge it
+appropiately -->
+
+
+<section id="dummy">
+  <title>MERGE ME</title>
+  <para>
+    <itemizedlist>
+      <listitem>
+        <simpara><emphasis>subnet[id].total-addresses</emphasis> (integer) -
+        this statistic shows the total number of addresses available for the
+        DHCPv4 management. In other words, this is the sum of all addresses in
+        all configured pools. This statistic changes only during configuration
+        changes. Note it does not take into account any addresses that may be
+        reserved due to host reservation. The <emphasis>id</emphasis> is the
+        subnet-id of a given subnet. This statistic is exposed for each subnet
+	separately. This statistic is reset during reconfiguration event.
+	</simpara>
+      </listitem>
+      <listitem>
+        <simpara><emphasis>subnet[id].assigned-addresses</emphasis> (integer) -
+        this statistic shows the number of assigned addresses in a given subnet.
+        This statistic increases every time a new lease is allocated (as a result
+        of receiving a REQUEST message) and is decreased every time a lease is
+        released (a RELEASE message is received). When proper lease expiration
+        is implemented (planned for Kea 1.0), it will also decrease when a lease
+        is expired. The <emphasis>id</emphasis> is the subnet-id of a given
+        subnet. This statistic is exposed for each subnet separately. This
+        statistic is reset during reconfiguration event.
+	</simpara>
+      </listitem>
+    </itemizedlist>
+    </para>
+</section>
+
     <section id="dhcp4-std">
       <title>Supported DHCP Standards</title>
       <para>The following standards are currently supported:</para>

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

@@ -141,6 +141,7 @@ libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/hooks/libkea-hooks.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/log/libkea-log.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/util/libkea-util.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/cc/libkea-cc.la
+libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/stats/libkea-stats.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/hooks/libkea-hooks.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 

+ 46 - 0
src/lib/dhcpsrv/cfgmgr.cc

@@ -19,10 +19,13 @@
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/subnet_id.h>
+#include <stats/stats_mgr.h>
+#include <sstream>
 #include <string>
 
 using namespace isc::asiolink;
 using namespace isc::util;
+using namespace isc::stats;
 
 namespace isc {
 namespace dhcp {
@@ -116,6 +119,12 @@ CfgMgr::clear() {
 
 void
 CfgMgr::commit() {
+
+    // First we need to remove statistics. The new configuration can have fewer
+    // subnets. Also, it may change subnet-ids. So we need to remove them all
+    // and add it back.
+    removeStatistics();
+
     ensureCurrentAllocated();
     if (!configs_.back()->sequenceEquals(*configuration_)) {
         configuration_ = configs_.back();
@@ -127,6 +136,9 @@ CfgMgr::commit() {
             configs_.erase(configs_.begin(), it);
         }
     }
+
+    // Now we need to set the statistics back.
+    updateStatistics();
 }
 
 void
@@ -186,6 +198,40 @@ CfgMgr::getStagingCfg() {
     return (configs_.back());
 }
 
+void
+CfgMgr::removeStatistics() {
+    const Subnet4Collection* subnets = getCurrentCfg()->getCfgSubnets4()->getAll();
+
+    // For each subnet currently configured, remove the statistic
+    for (Subnet4Collection::const_iterator subnet = subnets->begin();
+         subnet != subnets->end(); ++subnet) {
+
+        /// @todo: Once stat contexts are implemented, we'll need to remove all
+        /// statistics from the subnet[subnet-id] context.
+        std::stringstream stat1;
+        stat1 << "subnet[" << (*subnet)->getID() << "].total-addresses";
+        StatsMgr::instance().del(stat1.str());
+
+        std::stringstream stat2;
+        stat2 << "subnet[" << (*subnet)->getID() << "].assigned-addresses";
+        isc::stats::StatsMgr::instance().del(stat2.str());
+    }
+}
+
+void
+CfgMgr::updateStatistics() {
+    const Subnet4Collection* subnets = getCurrentCfg()->getCfgSubnets4()->getAll();
+
+    for (Subnet4Collection::const_iterator subnet = subnets->begin();
+         subnet != subnets->end(); ++subnet) {
+        std::stringstream name;
+        name << "subnet[" << (*subnet)->getID() << "].total-addresses";
+
+        StatsMgr::instance().setValue(name.str(),
+                                      (*subnet)->getPoolCapacity(Lease::TYPE_V4));
+    }
+}
+
 CfgMgr::CfgMgr()
     : datadir_(DHCP_DATA_DIR), echo_v4_client_id_(true),
       d2_client_mgr_(), verbose_mode_(false) {

+ 17 - 0
src/lib/dhcpsrv/cfgmgr.h

@@ -339,6 +339,23 @@ private:
     /// @return true if the duplicate subnet exists.
     bool isDuplicate(const Subnet6& subnet) const;
 
+    /// @brief Updates statistics.
+    ///
+    /// This method updates statistics that are affected by the newly committed
+    /// configuration. In particular, it updates the number of available addresses
+    /// in each subnet. Other statistics may be added in the future. In general,
+    /// these are statistics that are dependant only on configuration, so they are
+    /// not expected to change until the next reconfiguration event.
+    void updateStatistics();
+
+    /// @brief Removes statistics.
+    ///
+    /// During commitment of a new configuration, we need to get rid of the old
+    /// statistics for the old configuration. In particular, we need to remove
+    /// anything related to subnets, as there may be fewer subnets in the new
+    /// configuration and also subnet-ids may change.
+    void removeStatistics();
+
     /// @brief Container for defined DHCPv6 option spaces.
     OptionSpaceCollection spaces6_;
 

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

@@ -139,6 +139,7 @@ libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
 libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
 libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
 libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
+libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
 libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 libdhcpsrv_unittests_LDADD += $(GTEST_LDADD)
 endif

+ 42 - 0
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc

@@ -20,6 +20,7 @@
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/subnet_id.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
+#include <stats/stats_mgr.h>
 
 #include <gtest/gtest.h>
 
@@ -34,6 +35,7 @@ using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::dhcp::test;
 using namespace isc::util;
+using namespace isc::stats;
 using namespace isc;
 
 // don't import the entire boost namespace.  It will unexpectedly hide uint8_t
@@ -574,6 +576,46 @@ TEST_F(CfgMgrTest, verbosity) {
     EXPECT_FALSE(CfgMgr::instance().isVerbose());
 }
 
+// This test verifies that once the configuration is committed, statistics
+// are updated appropriately.
+TEST_F(CfgMgrTest, commitStats) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    StatsMgr& stats_mgr = StatsMgr::instance();
+
+    // Let's prepare the "old" configuration: a subnet with id 123
+    // and pretent there ware addresses assigned, so statistics are non-zero.
+    Subnet4Ptr subnet1(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3, 123));
+    CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
+    subnets->add(subnet1);
+    cfg_mgr.commit();
+    stats_mgr.addValue("subnet[123].total-addresses", static_cast<uint64_t>(256));
+    stats_mgr.setValue("subnet[123].assigned-addresses", static_cast<uint64_t>(150));
+
+    // Now, let's change the configuration to something new.
+
+    // There's a subnet 192.1.2.0/24 with ID=42
+    Subnet4Ptr subnet2(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3, 42));
+
+    // Let's make a pool with 128 addresses available.
+    PoolPtr pool(new Pool4(IOAddress("192.1.2.0"), 25)); // 128 addrs
+    subnet2->addPool(pool);
+
+    subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
+    subnets->add(subnet2);
+
+    // Let's commit it
+    cfg_mgr.commit();
+
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-addresses"));
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-addresses"));
+
+    ObservationPtr total_addrs;
+    EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-addresses"));
+    ASSERT_TRUE(total_addrs);
+    EXPECT_EQ(128, total_addrs->getInteger().first);
+}
+
+
 /// @todo Add unit-tests for testing:
 /// - addActiveIface() with invalid interface name
 /// - addActiveIface() with the same interface twice