Browse Source

[5280] leaseWipe4,6 implemented in lease managers (base and memfile)

Tomek Mrugalski 7 years ago
parent
commit
574356fa9e

+ 11 - 1
src/lib/dhcpsrv/cql_lease_mgr.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 - 2016 Deutsche Telekom AG.
+// Copyright (C) 2015 - 2017 Deutsche Telekom AG.
 //
 // Author: Razvan Becheriu <razvan.becheriu@qualitance.com>
 //
@@ -1885,6 +1885,16 @@ CqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
     return (result);
 }
 
+size_t
+CqlLeaseMgr::wipeLeases4(const SubnetID& /*subnet_id*/) {
+    isc_throw(NotImplemented, "wipeLeases4 is not implemented for Cassandra backend");
+}
+
+size_t
+CqlLeaseMgr::wipeLeases6(const SubnetID& /*subnet_id*/) {
+    isc_throw(NotImplemented, "wipeLeases6 is not implemented for Cassandra backend");
+}
+
 std::string
 CqlLeaseMgr::getName() const {
     std::string name = "";

+ 23 - 1
src/lib/dhcpsrv/cql_lease_mgr.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 - 2016 Deutsche Telekom AG.
+// Copyright (C) 2015 - 2017 Deutsche Telekom AG.
 //
 // Author: Razvan Becheriu <razvan.becheriu@qualitance.com>
 //
@@ -379,6 +379,28 @@ public:
     /// @return Number of leases deleted.
     virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t );
 
+    /// @brief Removes specified IPv4 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @todo: Not implemented yet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases4(const SubnetID& subnet_id);
+
+    /// @brief Removed specified IPv6 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @todo: Not implemented yet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases6(const SubnetID& subnet_id);
+
     /// @brief Return backend type
     ///
     /// @return Type of the backend.

+ 21 - 0
src/lib/dhcpsrv/dhcpsrv_messages.mes

@@ -545,6 +545,27 @@ lease from the memory file database for the specified address.
 A debug message issued when the server is attempting to update IPv6
 lease from the memory file database for the specified address.
 
+% DHCPSRV_MEMFILE_WIPE_LEASES4 removing all IPv4 leases from subnet %1
+This informational message is printed when removal of all leases from
+specified IPv4 subnet is commencing. This is a result of receiving administrative
+command.
+
+% DHCPSRV_MEMFILE_WIPE_LEASES4_FINISHED removing all IPv4 leases from subnet %1 finished, removed %2 leases
+This informational message is printed when removal of all leases from
+a specified IPv4 subnet has finished. The number of removed leases is
+printed.
+
+% DHCPSRV_MEMFILE_WIPE_LEASES6 removing all IPv6 leases from subnet %1
+This informational message is printed when removal of all leases from
+specified IPv6 subnet is commencing. This is a result of receiving administrative
+command.
+
+% DHCPSRV_MEMFILE_WIPE_LEASES6_FINISHED removing all IPv6 leases from subnet %1 finished, removed %2 leases
+This informational message is printed when removal of all leases from
+a specified IPv6 subnet has finished. The number of removed leases is
+printed.
+
+
 % DHCPSRV_MULTIPLE_RAW_SOCKETS_PER_IFACE current configuration will result in opening multiple broadcast capable sockets on some interfaces and some DHCP messages may be duplicated
 A warning message issued when the current configuration indicates that multiple
 sockets, capable of receiving broadcast traffic, will be opened on some of the

+ 19 - 5
src/lib/dhcpsrv/lease_mgr.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-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
@@ -539,6 +539,24 @@ public:
     /// @return A populated LeaseStatsQuery
     virtual LeaseStatsQueryPtr startLeaseStatsQuery6();
 
+    /// @brief Virtual method which removes specified leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @param subnet_id identifier of the subnet (or 0 for all subnets)
+    /// @return number of leases removed.
+    virtual size_t wipeLeases4(const SubnetID& subnet_id) = 0;
+
+    /// @brief Virtual method which removes specified leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @param subnet_id identifier of the subnet (or 0 for all subnets)
+    /// @return number of leases removed.
+    virtual size_t wipeLeases6(const SubnetID& subnet_id) = 0;
+
     /// @brief Return backend type
     ///
     /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
@@ -588,10 +606,6 @@ public:
     /// Rolls back all pending database operations.  On databases that don't
     /// support transactions, this is a no-op.
     virtual void rollback() = 0;
-
-    /// @todo: Add host management here
-    /// As host reservation is outside of scope for 2012, support for hosts
-    /// is currently postponed.
 };
 
 }; // end of isc::dhcp namespace

+ 57 - 0
src/lib/dhcpsrv/memfile_lease_mgr.cc

@@ -1323,5 +1323,62 @@ Memfile_LeaseMgr::startLeaseStatsQuery6() {
     return(query);
 }
 
+size_t Memfile_LeaseMgr::wipeLeases4(const SubnetID& subnet_id) {
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_WIPE_LEASES4)
+        .arg(subnet_id);
+
+    // Get the index by DUID, IAID, lease type.
+    const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
+
+    // Try to get the lease using the DUID, IAID and lease type.
+    std::pair<Lease4StorageSubnetIdIndex::const_iterator,
+              Lease4StorageSubnetIdIndex::const_iterator> l =
+        idx.equal_range(subnet_id);
+
+    // Let's collect all leases.
+    Lease4Collection leases;
+    for(auto lease = l.first; lease != l.second; ++lease) {
+        leases.push_back(*lease);
+    }
+
+    size_t num = leases.size();
+    for (auto l = leases.begin(); l != leases.end(); ++l) {
+        deleteLease((*l)->addr_);
+    }
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_WIPE_LEASES4_FINISHED)
+        .arg(subnet_id).arg(num);
+
+    return (num);
+}
+
+size_t Memfile_LeaseMgr::wipeLeases6(const SubnetID& subnet_id) {
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_WIPE_LEASES6)
+        .arg(subnet_id);
+
+    // Get the index by DUID, IAID, lease type.
+    const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
+
+    // Try to get the lease using the DUID, IAID and lease type.
+    std::pair<Lease6StorageSubnetIdIndex::const_iterator,
+              Lease6StorageSubnetIdIndex::const_iterator> l =
+        idx.equal_range(subnet_id);
+
+    // Let's collect all leases.
+    Lease6Collection leases;
+    for(auto lease = l.first; lease != l.second; ++lease) {
+        leases.push_back(*lease);
+    }
+
+    size_t num = leases.size();
+    for (auto l = leases.begin(); l != leases.end(); ++l) {
+        deleteLease((*l)->addr_);
+    }
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_WIPE_LEASES6_FINISHED)
+        .arg(subnet_id).arg(num);
+
+    return (num);
+}
+
+
 } // end of namespace isc::dhcp
 } // end of namespace isc

+ 18 - 0
src/lib/dhcpsrv/memfile_lease_mgr.h

@@ -332,6 +332,24 @@ public:
     /// @return Number of leases deleted.
     virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs);
 
+    /// @brief Removes specified IPv4 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases4(const SubnetID& subnet_id);
+
+    /// @brief Removed specified IPv6 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases6(const SubnetID& subnet_id);
+
 private:
 
     /// @brief Deletes all expired-reclaimed leases.

+ 24 - 0
src/lib/dhcpsrv/memfile_lease_storage.h

@@ -42,6 +42,9 @@ struct ClientIdSubnetIdIndexTag { };
 /// @brief Tag for indexes by client id, HW address and subnet id.
 struct ClientIdHWAddressSubnetIdIndexTag { };
 
+/// @brief Tag for indexs by subnet-id.
+struct SubnetIdIndexTag { };
+
 /// @name Multi index containers holding DHCPv4 and DHCPv6 leases.
 ///
 //@{
@@ -103,6 +106,13 @@ typedef boost::multi_index_container<
                 boost::multi_index::const_mem_fun<Lease, int64_t,
                                                   &Lease::getExpirationTime>
             >
+        >,
+
+        // Specification of the fourth index starts here.
+        // This index sorts leases by SubnetID.
+        boost::multi_index::ordered_non_unique<
+            boost::multi_index::tag<SubnetIdIndexTag>,
+            boost::multi_index::member<Lease, isc::dhcp::SubnetID, &Lease::subnet_id_>
         >
      >
 > Lease6Storage; // Specify the type name of this container.
@@ -210,7 +220,15 @@ typedef boost::multi_index_container<
                 boost::multi_index::const_mem_fun<Lease, int64_t,
                                                   &Lease::getExpirationTime>
             >
+        >,
+
+        // Specification of the sixth index starts here.
+        // This index sorts leases by SubnetID.
+        boost::multi_index::ordered_non_unique<
+            boost::multi_index::tag<SubnetIdIndexTag>,
+            boost::multi_index::member<Lease, isc::dhcp::SubnetID, &Lease::subnet_id_>
         >
+
     >
 > Lease4Storage; // Specify the type name for this container.
 
@@ -229,6 +247,9 @@ typedef Lease6Storage::index<DuidIaidTypeIndexTag>::type Lease6StorageDuidIaidTy
 /// @brief DHCPv6 lease storage index by expiration time.
 typedef Lease6Storage::index<ExpirationIndexTag>::type Lease6StorageExpirationIndex;
 
+/// @brief DHCPv6 lease storage index by Subnet-id.
+typedef Lease6Storage::index<SubnetIdIndexTag>::type Lease6StorageSubnetIdIndex;
+
 /// @brief DHCPv4 lease storage index by address.
 typedef Lease4Storage::index<AddressIndexTag>::type Lease4StorageAddressIndex;
 
@@ -247,6 +268,9 @@ Lease4StorageClientIdSubnetIdIndex;
 typedef Lease4Storage::index<ClientIdHWAddressSubnetIdIndexTag>::type
 Lease4StorageClientIdHWAddressSubnetIdIndex;
 
+/// @brief DHCPv4 lease storage index by client id, HW address and subnet id.
+typedef Lease4Storage::index<SubnetIdIndexTag>::type Lease4StorageSubnetIdIndex;
+
 //@}
 } // end of isc::dhcp namespace
 } // end of isc namespace

+ 8 - 0
src/lib/dhcpsrv/mysql_lease_mgr.cc

@@ -2100,7 +2100,15 @@ MySqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
     return (deleted_leases);
 }
 
+size_t
+MySqlLeaseMgr::wipeLeases4(const SubnetID& /*subnet_id*/) {
+    isc_throw(NotImplemented, "wipeLeases4 is not implemented for MySQL backend");
+}
 
+size_t
+MySqlLeaseMgr::wipeLeases6(const SubnetID& /*subnet_id*/) {
+    isc_throw(NotImplemented, "wipeLeases6 is not implemented for MySQL backend");
+}
 
 // Miscellaneous database methods.
 

+ 22 - 0
src/lib/dhcpsrv/mysql_lease_mgr.h

@@ -329,6 +329,28 @@ public:
     /// @return Number of leases deleted.
     virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs);
 
+    /// @brief Removes specified IPv4 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @todo: Not implemented yet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases4(const SubnetID& subnet_id);
+
+    /// @brief Removed specified IPv6 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @todo: Not implemented yet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases6(const SubnetID& subnet_id);
+
     /// @brief Deletes all expired-reclaimed DHCPv6 leases.
     ///
     /// @param secs Number of seconds since expiration of leases before

+ 10 - 0
src/lib/dhcpsrv/pgsql_lease_mgr.cc

@@ -1363,6 +1363,16 @@ PgSqlLeaseMgr::startLeaseStatsQuery6() {
     return(query);
 }
 
+size_t
+PgSqlLeaseMgr::wipeLeases4(const SubnetID& /*subnet_id*/) {
+    isc_throw(NotImplemented, "wipeLeases4 is not implemented for PgSQL backend");
+}
+
+size_t
+PgSqlLeaseMgr::wipeLeases6(const SubnetID& /*subnet_id*/) {
+    isc_throw(NotImplemented, "wipeLeases6 is not implemented for PgSQL backend");
+}
+
 string
 PgSqlLeaseMgr::getName() const {
     string name = "";

+ 24 - 2
src/lib/dhcpsrv/pgsql_lease_mgr.h

@@ -319,7 +319,7 @@ public:
     /// invokes its start method, which fetches its statistical data
     /// result set by executing the RECOUNT_LEASE_STATS4 query.
     /// The query object is then returned.
-    /// 
+    ///
     /// @return The populated query as a pointer to an LeaseStatsQuery
     virtual LeaseStatsQueryPtr startLeaseStatsQuery4();
 
@@ -329,10 +329,32 @@ public:
     /// invokes its start method, which fetches its statistical data
     /// result set by executing the RECOUNT_LEASE_STATS6 query.
     /// The query object is then returned.
-    /// 
+    ///
     /// @return The populated query as a pointer to an LeaseStatsQuery
     virtual LeaseStatsQueryPtr startLeaseStatsQuery6();
 
+    /// @brief Removes specified IPv4 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @todo: Not implemented yet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases4(const SubnetID& subnet_id);
+
+    /// @brief Removed specified IPv6 leases.
+    ///
+    /// This rather dangerous method is able to remove all leases from specified
+    /// subnet.
+    ///
+    /// @todo: Not implemented yet.
+    ///
+    /// @param subnet_id identifier of the subnet
+    /// @return number of leases removed.
+    virtual size_t wipeLeases6(const SubnetID& subnet_id);
+
     /// @brief Return backend type
     ///
     /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)

+ 10 - 0
src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc

@@ -643,4 +643,14 @@ TEST_F(CqlLeaseMgrTest, deleteExpiredReclaimedLeases4) {
     testDeleteExpiredReclaimedLeases4();
 }
 
+// Tests that leases from specific subnet can be removed.
+TEST_F(CqlLeaseMgrTest, DISABLED_wipeLeases4) {
+    testWipeLeases4();
+}
+
+// Tests that leases from specific subnet can be removed.
+TEST_F(CqlLeaseMgrTest, DISABLED_wipeLeases6) {
+    testWipeLeases6();
+}
+
 }; // Of anonymous namespace

+ 63 - 0
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc

@@ -2684,6 +2684,69 @@ GenericLeaseMgrTest::testRecountLeaseStats6() {
     ASSERT_NO_FATAL_FAILURE(checkLeaseStats(expectedStats));
 }
 
+void
+GenericLeaseMgrTest::testWipeLeases6() {
+    // Get the leases to be used for the test and add to the database
+    vector<Lease6Ptr> leases = createLeases6();
+    leases[0]->subnet_id_ = 1;
+    leases[1]->subnet_id_ = 1;
+    leases[2]->subnet_id_ = 1;
+    leases[3]->subnet_id_ = 22;
+    leases[4]->subnet_id_ = 333;
+    leases[5]->subnet_id_ = 333;
+    leases[6]->subnet_id_ = 333;
+    leases[7]->subnet_id_ = 333;
+
+    for (size_t i = 0; i < leases.size(); ++i) {
+        EXPECT_TRUE(lmptr_->addLease(leases[i]));
+    }
+
+    // Let's try something simple. There shouldn't be any leases in
+    // subnet 2. The keep deleting the leases, perhaps in a different
+    // order they were added.
+    EXPECT_EQ(0, lmptr_->wipeLeases6(2));
+    EXPECT_EQ(4, lmptr_->wipeLeases6(333));
+    EXPECT_EQ(3, lmptr_->wipeLeases6(1));
+    EXPECT_EQ(1, lmptr_->wipeLeases6(22));
+
+    // All the leases should be gone now. Check that that repeated
+    // attempt to delete them will not result in any additional removals.
+    EXPECT_EQ(0, lmptr_->wipeLeases6(1));
+    EXPECT_EQ(0, lmptr_->wipeLeases6(22));
+    EXPECT_EQ(0, lmptr_->wipeLeases6(333));
+}
+
+void
+GenericLeaseMgrTest::testWipeLeases4() {
+    // Get the leases to be used for the test and add to the database
+    vector<Lease4Ptr> leases = createLeases4();
+    leases[0]->subnet_id_ = 1;
+    leases[1]->subnet_id_ = 1;
+    leases[2]->subnet_id_ = 1;
+    leases[3]->subnet_id_ = 22;
+    leases[4]->subnet_id_ = 333;
+    leases[5]->subnet_id_ = 333;
+    leases[6]->subnet_id_ = 333;
+    leases[7]->subnet_id_ = 333;
+
+    for (size_t i = 0; i < leases.size(); ++i) {
+        EXPECT_TRUE(lmptr_->addLease(leases[i]));
+    }
+
+    // Let's try something simple. There shouldn't be any leases in
+    // subnet 2. The keep deleting the leases, perhaps in a different
+    // order they were added.
+    EXPECT_EQ(0, lmptr_->wipeLeases4(2));
+    EXPECT_EQ(4, lmptr_->wipeLeases4(333));
+    EXPECT_EQ(3, lmptr_->wipeLeases4(1));
+    EXPECT_EQ(1, lmptr_->wipeLeases4(22));
+
+    // All the leases should be gone now. Check that that repeated
+    // attempt to delete them will not result in any additional removals.
+    EXPECT_EQ(0, lmptr_->wipeLeases4(1));
+    EXPECT_EQ(0, lmptr_->wipeLeases4(22));
+    EXPECT_EQ(0, lmptr_->wipeLeases4(333));
+}
 
 }; // namespace test
 }; // namespace dhcp

+ 13 - 0
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.h

@@ -374,6 +374,19 @@ public:
     /// after altering the lease states in various ways.
     void testRecountLeaseStats6();
 
+
+    /// @brief Check if wipeLeases4 works properly.
+    ///
+    /// This test creates a bunch of leases in several subnets and then
+    /// attempts to delete them, one subnet at a time.
+    void testWipeLeases4();
+
+    /// @brief Check if wipeLeases6 works properly.
+    ///
+    /// This test creates a bunch of leases in several subnets and then
+    /// attempts to delete them, one subnet at a time.
+    void testWipeLeases6();
+
     /// @brief String forms of IPv4 addresses
     std::vector<std::string>  straddress4_;
 

+ 11 - 1
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-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
@@ -223,6 +223,16 @@ public:
                   " is not implemented");
     }
 
+    /// @brief Pretends to will all IPv4 leases from a subnet
+    virtual size_t wipeLeases4(const SubnetID&) {
+        isc_throw(NotImplemented, "ConreteLeaseMgr::wipeLeases4 not implemented");
+    }
+
+    /// @brief Pretends to will all IPv4 leases from a subnet
+    virtual size_t wipeLeases6(const SubnetID&) {
+        isc_throw(NotImplemented, "ConreteLeaseMgr::wipeLeases4 not implemented");
+    }
+
     /// @brief Returns backend type.
     ///
     /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)

+ 12 - 0
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc

@@ -1894,4 +1894,16 @@ TEST_F(MemfileLeaseMgrTest, recountLeaseStats6) {
     testRecountLeaseStats6();
 }
 
+// Tests that leases from specific subnet can be removed.
+TEST_F(MemfileLeaseMgrTest, wipeLeases4) {
+    startBackend(V4);
+    testWipeLeases4();
+}
+
+// Tests that leases from specific subnet can be removed.
+TEST_F(MemfileLeaseMgrTest, wipeLeases6) {
+    startBackend(V6);
+    testWipeLeases6();
+}
+
 }; // end of anonymous namespace

+ 10 - 0
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc

@@ -487,4 +487,14 @@ TEST_F(MySqlLeaseMgrTest, recountLeaseStats6) {
     testRecountLeaseStats6();
 }
 
+// Tests that leases from specific subnet can be removed.
+TEST_F(MySqlLeaseMgrTest, DISABLED_wipeLeases4) {
+    testWipeLeases4();
+}
+
+// Tests that leases from specific subnet can be removed.
+TEST_F(MySqlLeaseMgrTest, DISABLED_wipeLeases6) {
+    testWipeLeases6();
+}
+
 }; // Of anonymous namespace

+ 10 - 0
src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc

@@ -412,4 +412,14 @@ TEST_F(PgSqlLeaseMgrTest, recountLeaseStats6) {
     testRecountLeaseStats6();
 }
 
+// Tests that leases from specific subnet can be removed.
+TEST_F(PgSqlLeaseMgrTest, DISABLED_wipeLeases4) {
+    testWipeLeases4();
+}
+
+// Tests that leases from specific subnet can be removed.
+TEST_F(PgSqlLeaseMgrTest, DISABLED_wipeLeases6) {
+    testWipeLeases6();
+}
+
 }; // namespace