]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2596] Extended buildExtendedInfoTables6
authorFrancis Dupont <fdupont@isc.org>
Fri, 28 Oct 2022 20:40:03 +0000 (22:40 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 16 Nov 2022 22:48:28 +0000 (23:48 +0100)
src/lib/dhcpsrv/dhcpsrv_messages.cc
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/lease_mgr.h
src/lib/dhcpsrv/memfile_lease_mgr.cc
src/lib/dhcpsrv/memfile_lease_mgr.h
src/lib/dhcpsrv/mysql_lease_mgr.cc
src/lib/dhcpsrv/mysql_lease_mgr.h
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/pgsql_lease_mgr.h
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc

index f0f9029dbb5ab195af28ddbe01c0ea3fd9464f1c..68a04ae8328ac2860782e047971255a36e666aaa 100644 (file)
@@ -321,9 +321,9 @@ const char* values[] = {
     "DHCPSRV_LEASE_SANITY_FIXED", "The lease %1 with subnet-id %2 failed subnet-id checks, but was corrected to subnet-id %3.",
     "DHCPSRV_MEMFILE_ADD_ADDR4", "adding IPv4 lease with address %1",
     "DHCPSRV_MEMFILE_ADD_ADDR6", "adding IPv6 lease with address %1",
-    "DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6", "building extended info tables with %1 sanity check level (%2)",
+    "DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6", "building extended info tables with %1 sanity check level%2, tables %3",
     "DHCPSRV_MEMFILE_BEGIN_TRANSACTION", "committing to memory file database",
-    "DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6", "building extended info tables saw %1 leases, extended info sanity checks modified %2 leases and %3 leases were entered into tables",
+    "DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6", "building extended info tables saw %1 leases, extended info sanity checks modified %2 / updated %3 leases and %4 leases were entered into tables",
     "DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6_ERROR", "building extended info tables got an exception on the lease for %1: %2",
     "DHCPSRV_MEMFILE_COMMIT", "committing to memory file database",
     "DHCPSRV_MEMFILE_CONVERTING_LEASE_FILES", "running LFC now to convert lease files to the current schema: %1.%2",
index d3e04367ab3dbe139ec594af2d44ddd153cbf694..f1e2ce991797bf659d61e8182439e689bd0fc531 100644 (file)
@@ -386,10 +386,10 @@ with the specified address to the memory file backend database.
 A debug message issued when the server is about to add an IPv6 lease
 with the specified address to the memory file backend database.
 
-% DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6 building extended info tables with %1 sanity check level (%2)
+% DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6 building extended info tables with %1 sanity check level%2, tables %3
 A debug message issued when the server is building extended info tables.
-The extended info sanity check level and the fact tables are enabled or
-disabled are displayed.
+The extended info sanity check level, update in file when requested
+and the fact tables are enabled or disabled are displayed.
 
 % DHCPSRV_MEMFILE_BEGIN_TRANSACTION committing to memory file database
 The code has issued a begin transaction call.  For the memory file database, this is
@@ -399,8 +399,9 @@ a no-op.
 A debug message issued when the server is building extended info tables and
 receives an exception processing a lease.
 
-% DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6 building extended info tables saw %1 leases, extended info sanity checks modified %2 leases and %3 leases were entered into tables
-Extended info tables build was finished. Some statistics are displayed.
+% DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6 building extended info tables saw %1 leases, extended info sanity checks modified %2 / updated %3 leases and %4 leases were entered into tables
+Extended info tables build was finished. Some statistics are displayed, the
+updated in database is returned to the command interface.
 
 % DHCPSRV_MEMFILE_COMMIT committing to memory file database
 The code has issued a commit call.  For the memory file database, this is
index 519d7d7961280eb3f3b1ebf7e76feb5e11c97eb1..038fb4ee886163efbfc5f2d3bf18a8d89df3d135 100644 (file)
@@ -962,7 +962,10 @@ public:
     }
 
     /// @brief Build extended info v6 tables.
-    virtual void buildExtendedInfoTables6() = 0;
+    ///
+    /// @param update Update extended info in database.
+    /// @return The number of updates in the database or 0.
+    virtual size_t buildExtendedInfoTables6(bool update) = 0;
 
 protected:
 
index 22ffd53c14b8c790a6d6326ac3124fa1897bc113..30cb0b6a4ea7516de92f478b4fc4d05b938b2d26 100644 (file)
@@ -660,7 +660,9 @@ Memfile_LeaseMgr::Memfile_LeaseMgr(const DatabaseConnection::ParameterMap& param
                                                  CSVLeaseFile6>(file6,
                                                                 lease_file6_,
                                                                 storage6_);
-            buildExtendedInfoTables6Internal();
+            CfgConsistency::ExtendedInfoSanity check =
+                CfgMgr::instance().getStagingCfg()->getConsistency()->getExtendedInfoSanityCheck();
+            static_cast<void>(buildExtendedInfoTables6Internal(check, false));
         }
     }
 
@@ -2845,30 +2847,34 @@ Memfile_LeaseMgr::getLeases6ByLinkInternal(const IOAddress& link_addr,
     return (collection);
 }
 
-void
-Memfile_LeaseMgr::buildExtendedInfoTables6Internal() {
+size_t
+Memfile_LeaseMgr::buildExtendedInfoTables6Internal(CfgConsistency::ExtendedInfoSanity check,
+                                                   bool update) {
     bool enabled = getExtendedInfoTablesEnabled();
-    // Use staging config here.
-    CfgConsistency::ExtendedInfoSanity check =
-        CfgMgr::instance().getStagingCfg()->getConsistency()->getExtendedInfoSanityCheck();
 
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
               DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6)
         .arg(CfgConsistency::sanityCheckToText(check))
+        .arg(update ? " updating in file" : "")
         .arg(enabled ? "enabled" : "disabled");
 
     size_t leases = 0;
     size_t modified = 0;
+    size_t updated = 0;
     size_t processed = 0;
 
     for (auto lease : storage6_) {
-        leases++;
+        ++leases;
         try {
             if (upgradeLease6ExtendedInfo(lease, check)) {
-                modified++;
+                ++modified;
+                if (update && persistLeases(V6)) {
+                    lease_file6_->append(*lease);
+                    ++updated;
+                }
             }
             if (enabled && addExtendedInfo6(lease)) {
-                processed++;
+                ++processed;
             }
         } catch (const std::exception& ex) {
             LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
@@ -2881,7 +2887,22 @@ Memfile_LeaseMgr::buildExtendedInfoTables6Internal() {
     LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6)
         .arg(leases)
         .arg(modified)
+        .arg(updated)
         .arg(processed);
+
+    return (updated);
+}
+
+size_t
+Memfile_LeaseMgr::buildExtendedInfoTables6(bool update) {
+    CfgConsistency::ExtendedInfoSanity check =
+        CfgMgr::instance().getCurrentCfg()->getConsistency()->getExtendedInfoSanityCheck();
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        return (buildExtendedInfoTables6Internal(check, update));
+    } else {
+        return (buildExtendedInfoTables6Internal(check, update));
+    }
 }
 
 void
index 4d765c26561e46bf6cdd2ad9fad08f658681332e..952eb61b9a6a77ae6947806202e0013ad88f8b67 100644 (file)
@@ -1372,12 +1372,12 @@ public:
 
     /// @brief Build extended info v6 tables.
     ///
-    /// @note: this method is a nop for memfile as tables are built at
-    /// start time.
-    virtual void buildExtendedInfoTables6() override {
-        isc_throw(isc::NotImplemented,
-                  "buildExtendedInfoTables6 is not yet implemented by memfile");
-    }
+    /// @note: this method is a nop for memfile when update is false
+    /// as tables are built at start time.
+    ///
+    /// @param update Update extended info in database.
+    /// @return The number of updates in the database or 0.
+    virtual size_t buildExtendedInfoTables6(bool update) override;
 
 private:
 
@@ -1470,8 +1470,11 @@ private:
 
     /// @brief Build extended info v6 tables.
     ///
-    /// @note: called at start time.
-    void buildExtendedInfoTables6Internal();
+    /// @param check Extended info sanity level.
+    /// @param update Update extended info in database.
+    /// @return The number of updates in the database or 0.
+    size_t buildExtendedInfoTables6Internal(isc::dhcp::CfgConsistency::ExtendedInfoSanity check,
+                                            bool update);
 
 public:
 
index 52bdeb97d08d2d653b87136096f9864726c3c553..ddf4a5df2728ed0c414dddb1ddd2763f468cc5f1 100644 (file)
@@ -3431,5 +3431,11 @@ MySqlLeaseMgr::getLeases6ByLink(const IOAddress& /* link_addr */,
     isc_throw(NotImplemented, "MySqlLeaseMgr::getLeases6ByLink not implemented");
 }
 
+size_t
+MySqlLeaseMgr::buildExtendedInfoTables6(bool /* update */) {
+    isc_throw(isc::NotImplemented,
+              "MySqlLeaseMgr::buildExtendedInfoTables6 not implemented");
+}
+
 }  // namespace dhcp
 }  // namespace isc
index e4c48265e692fa9408bf0f308d99857c207a8f04..bb503c0cc9f129ef5e4235d8147c793b1bc4d4d3 100644 (file)
@@ -1110,10 +1110,10 @@ private:
                      const LeasePageSize& page_size) override;
 
     /// @brief Build extended info v6 tables.
-    virtual void buildExtendedInfoTables6() override {
-        isc_throw(isc::NotImplemented,
-                  "buildExtendedInfoTables6 is not yet implemented by mysql");
-    }
+    ///
+    /// @param update Update extended info in database.
+    /// @return The number of updates in the database or 0.
+    virtual size_t buildExtendedInfoTables6(bool update) override;
 
     /// @brief Context RAII Allocator.
     class MySqlLeaseContextAlloc {
index 96bf15a826db0b74db46f2808d71d47904dd9fd3..e9acf0faff623b721acc764c8ad95a27018a09b4 100644 (file)
@@ -2625,5 +2625,11 @@ PgSqlLeaseMgr::getLeases6ByLink(const IOAddress& /* link_addr */,
     isc_throw(NotImplemented, "PgSqlLeaseMgr::getLeases6ByLink not implemented");
 }
 
+size_t
+PgSqlLeaseMgr::buildExtendedInfoTables6(bool /* update */) {
+    isc_throw(isc::NotImplemented,
+              "PgSqlLeaseMgr::buildExtendedInfoTables6 not implemented");
+}
+
 }  // namespace dhcp
 }  // namespace isc
index 8a575680ed905ffdb7ddbb9f52818b9bcceab888..238eb7900bdf5e57f94fd8d134ed94ee0a75fad0 100644 (file)
@@ -1063,10 +1063,10 @@ private:
                      const LeasePageSize& page_size) override;
 
     /// @brief Build extended info v6 tables.
-    virtual void buildExtendedInfoTables6() override {
-        isc_throw(isc::NotImplemented,
-                  "buildExtendedInfoTables6 is not yet implemented by postgresql");
-    }
+    ///
+    /// @param update Update extended info in database.
+    /// @return The number of updates in the database or 0.
+    virtual size_t buildExtendedInfoTables6(bool update) override;
 
     /// @brief Write V4 leases to a file.
     virtual void writeLeases4(const std::string& /*filename*/) override;
index 786148142f62c32ab0ed9ce2a68c17ade693ebda..d5577e3087b5a516e6f37061dfca260fa655d943 100644 (file)
@@ -505,7 +505,7 @@ public:
     }
 
     /// @brief Stub implementation.
-    virtual void buildExtendedInfoTables6() override {
+    virtual size_t buildExtendedInfoTables6(bool /* update */) override {
         isc_throw(isc::NotImplemented, "ConcreteLeaseMgr:buildExtendedInfoTables6 not implemented");
     }
     ///  @brief Pretends to write V4 leases to a file.
index f73874b37cc1e0556a84119966276e0fe0abd870..e086f83d088cefeb7e4fe1e3c02fb0c01d3c95ac 100644 (file)
@@ -3564,7 +3564,7 @@ TEST_F(MemfileLeaseMgrTest, buildExtendedInfoTables6) {
         "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02,"
         "200,200,8,100,0,7,0,1,1,,,1,"
         "{ \"ISC\": { \"relays\": [ { \"hop\": 44&#x2c"
-        " \"link\": \"2001:db8::4\"&#x2c  \"peer\": \"2001:db8::5\"&#x2c"
+        " \"link\": \"2001:db8::4\"&#x2c \"peer\": \"2001:db8::5\"&#x2c"
         " \"options\": \"0x00250006010203040506003500086464646464646464\""
         " } ] } },,\n"
     );
@@ -3644,7 +3644,7 @@ TEST_F(MemfileLeaseMgrTest, buildExtendedInfoTables6noSanitize) {
         "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02,"
         "200,200,8,100,0,7,0,1,1,,,1,"
         "{ \"ISC\": { \"relays\": [ { \"hop\": 44&#x2c"
-        " \"link\": \"2001:db8::4\"&#x2c  \"peer\": \"2001:db8::5\"&#x2c"
+        " \"link\": \"2001:db8::4\"&#x2c \"peer\": \"2001:db8::5\"&#x2c"
         " \"options\": \"0x00250006010203040506003500086464646464646464\""
         " } ] } },,\n"
     );
@@ -3707,7 +3707,7 @@ TEST_F(MemfileLeaseMgrTest, buildExtendedInfoTables6enabled) {
         "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02,"
         "200,200,8,100,0,7,0,1,1,,,1,"
         "{ \"ISC\": { \"relay-info\": [ { \"hop\": 44&#x2c"
-        " \"link\": \"2001:db8::4\"&#x2c  \"peer\": \"2001:db8::5\"&#x2c"
+        " \"link\": \"2001:db8::4\"&#x2c \"peer\": \"2001:db8::5\"&#x2c"
         " \"remote-id\": \"010203040506\"&#x2c"
         " \"relay-id\": \"6464646464646464\"&#x2c"
         " \"options\": \"0x00250006010203040506003500086464646464646464\""
@@ -3786,7 +3786,7 @@ TEST_F(MemfileLeaseMgrTest, buildExtendedInfoTables6disabled) {
         "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02,"
         "200,200,8,100,0,7,0,1,1,,,1,"
         "{ \"ISC\": { \"relay-info\": [ { \"hop\": 44&#x2c"
-        " \"link\": \"2001:db8::4\"&#x2c  \"peer\": \"2001:db8::5\"&#x2c"
+        " \"link\": \"2001:db8::4\"&#x2c \"peer\": \"2001:db8::5\"&#x2c"
         " \"remote-id\": \"010203040506\"&#x2c"
         " \"relay-id\": \"6464646464646464\"&#x2c"
         " \"options\": \"0x00250006010203040506003500086464646464646464\""
@@ -3814,4 +3814,101 @@ TEST_F(MemfileLeaseMgrTest, buildExtendedInfoTables6disabled) {
     EXPECT_TRUE(lease_mgr->link_addr6_.empty());
 }
 
+/// @brief Checks that buildExtendedInfoTables6 updates when explicitly
+/// requested.
+TEST_F(MemfileLeaseMgrTest, buildExtendedInfoTables6ExplicitSanitize) {
+    // Add some leases to the CSV file: one empty map, one old extended
+    // info format.
+    string lease_file = getLeaseFilePath("leasefile6_0.csv");
+    LeaseFileIO io(lease_file);
+    string content =
+        "address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,"
+        "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,"
+        "hwaddr,state,user_context,hwtype,hwaddr_source\n"
+
+        "2001:db8:1::1,01:01:01:01:01:01:01:01:01:01:01:01:01,"
+        "400,1000,8,100,0,7,0,1,1,,,1,"
+        "{},,\n"
+
+        "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02,"
+        "200,200,8,100,0,7,0,1,1,,,1,"
+        "{ \"ISC\": { \"relays\": [ { \"hop\": 44&#x2c"
+        " \"link\": \"2001:db8::4\"&#x2c \"peer\": \"2001:db8::5\"&#x2c"
+        " \"options\": \"0x00250006010203040506003500086464646464646464\""
+        " } ] } },,\n";
+    io.writeFile(content);
+
+    // Disable sanitizing.
+    CfgMgr::instance().getStagingCfg()->getConsistency()->
+        setExtendedInfoSanityCheck(CfgConsistency::EXTENDED_INFO_CHECK_NONE);
+
+    // Start the lease manager.
+    DatabaseConnection::ParameterMap pmap;
+    pmap["type"] = "memfile";
+    pmap["universe"] = "6";
+    pmap["name"] = lease_file;
+    pmap["lfc-interval"] = "0";
+    boost::scoped_ptr<NakedMemfileLeaseMgr> lease_mgr;
+    EXPECT_NO_THROW(lease_mgr.reset(new NakedMemfileLeaseMgr(pmap)));
+
+    // Check the lease with empty user context was not updated.
+    Lease6Ptr lease = lease_mgr->getLease6(Lease::TYPE_NA,
+                                           IOAddress("2001:db8:1::1"));
+    ASSERT_TRUE(lease);
+    ConstElementPtr user_context = lease->getContext();
+    ASSERT_TRUE(user_context);
+    ASSERT_EQ(Element::map, user_context->getType());
+    EXPECT_TRUE(user_context->empty());
+
+    // Check the lease with extended info was not upgraded.
+    lease = lease_mgr->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2"));
+    ASSERT_TRUE(lease);
+    user_context = lease->getContext();
+    ASSERT_TRUE(user_context);
+    ConstElementPtr isc = user_context->get("ISC");
+    ASSERT_TRUE(isc);
+    EXPECT_TRUE(isc->contains("relays"));
+    EXPECT_FALSE(isc->contains("relay-info"));
+
+    // Enable sanitizing.
+    CfgMgr::instance().getCurrentCfg()->getConsistency()->
+        setExtendedInfoSanityCheck(CfgConsistency::EXTENDED_INFO_CHECK_FIX);
+
+    // Now run buildExtendedInfoTables6 with update set to true.
+    size_t updated = 0;
+    EXPECT_NO_THROW(updated = lease_mgr->buildExtendedInfoTables6(true));
+    EXPECT_EQ(2, updated);
+
+    // Check the lease with empty user context was updated.
+    lease = lease_mgr->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+    ASSERT_TRUE(lease);
+    EXPECT_FALSE(lease->getContext());
+
+    // Check the lease with extended info was upgraded.
+    lease = lease_mgr->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2"));
+    ASSERT_TRUE(lease);
+    user_context = lease->getContext();
+    ASSERT_TRUE(user_context);
+    isc = user_context->get("ISC");
+    ASSERT_TRUE(isc);
+    EXPECT_FALSE(isc->contains("relays"));
+    EXPECT_TRUE(isc->contains("relay-info"));
+
+    // Check the lease file was updated.
+    string new_content =
+        "2001:db8:1::1,01:01:01:01:01:01:01:01:01:01:01:01:01,"
+        "400,1000,8,100,0,7,0,1,1,,,1,,,\n"
+
+        "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02,"
+        "200,200,8,100,0,7,0,1,1,,,1,"
+        "{ \"ISC\": { \"relay-info\": [ { \"hop\": 44&#x2c"
+        " \"link\": \"2001:db8::4\"&#x2c"
+        " \"options\": \"0x00250006010203040506003500086464646464646464\""
+        "&#x2c \"peer\": \"2001:db8::5\"&#x2c"
+        " \"relay-id\": \"6464646464646464\"&#x2c"
+        " \"remote-id\": \"010203040506\" } ] } },,\n";
+    string expected = content + new_content;
+    EXPECT_EQ(expected, io.readFile());
+}
+
 }  // namespace