]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#716,!412] It is now possible to delete shared network by tags.
authorMarcin Siodelski <marcin@isc.org>
Sun, 7 Jul 2019 19:09:53 +0000 (21:09 +0200)
committerMarcin Siodelski <marcin@isc.org>
Tue, 9 Jul 2019 18:37:28 +0000 (14:37 -0400)
Support added for: any server, explicit server, all servers.

src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc

index 9c8ce4e9bbe2ec02ebaf5ad7e32cdf428f66af53..1d532f6d80cc244c96f3e0c9e6133561c090b9e6 100644 (file)
@@ -111,7 +111,8 @@ public:
         DELETE_ALL_SUBNETS4,
         DELETE_ALL_SUBNETS4_SHARED_NETWORK_NAME,
         DELETE_POOLS4_SUBNET_ID,
-        DELETE_SHARED_NETWORK4_NAME,
+        DELETE_SHARED_NETWORK4_NAME_WITH_TAG,
+        DELETE_SHARED_NETWORK4_NAME_NO_TAG,
         DELETE_ALL_SHARED_NETWORKS4,
         DELETE_SHARED_NETWORK4_SERVER,
         DELETE_OPTION_DEF4_CODE_NAME,
@@ -1391,7 +1392,6 @@ public:
         transaction.commit();
     }
 
-
     /// @brief Sends query to insert DHCP option.
     ///
     /// This method expects that the server selector contains exactly one
@@ -2351,14 +2351,19 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_DELETE_POOLS(dhcp4)
     },
 
-    // Delete shared network by name.
-    { MySqlConfigBackendDHCPv4Impl::DELETE_SHARED_NETWORK4_NAME,
-      MYSQL_DELETE_SHARED_NETWORK(dhcp4, AND n.name = ?)
+    // Delete shared network by name with specifying server tag.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_SHARED_NETWORK4_NAME_WITH_TAG,
+      MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp4, AND n.name = ?)
+    },
+
+    // Delete shared network by name without specifying server tag.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_SHARED_NETWORK4_NAME_NO_TAG,
+      MYSQL_DELETE_SHARED_NETWORK_NO_TAG(dhcp4, AND n.name = ?)
     },
 
     // Delete all shared networks.
     { MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SHARED_NETWORKS4,
-      MYSQL_DELETE_SHARED_NETWORK(dhcp4)
+      MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp4)
     },
 
     // Delete associations of a shared network with server.
@@ -2806,8 +2811,11 @@ MySqlConfigBackendDHCPv4::deleteSharedNetwork4(const ServerSelector& server_sele
                                                const std::string& name) {
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK4)
         .arg(name);
-    uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv4Impl::DELETE_SHARED_NETWORK4_NAME,
-                                                 server_selector, "deleting a shared network",
+    int index = (server_selector.amAny() ?
+                 MySqlConfigBackendDHCPv4Impl::DELETE_SHARED_NETWORK4_NAME_NO_TAG :
+                 MySqlConfigBackendDHCPv4Impl::DELETE_SHARED_NETWORK4_NAME_WITH_TAG);
+    uint64_t result = impl_->deleteTransactional(index, server_selector,
+                                                 "deleting a shared network",
                                                  "shared network deleted", true, name);
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK4_RESULT)
         .arg(result);
index 00f82bc16f918e0481b8b6edb003d96cad0951db..de1503ce1d951408d182e3ca233a0aaf29200220 100644 (file)
@@ -117,7 +117,8 @@ public:
         DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
         DELETE_POOLS6_SUBNET_ID,
         DELETE_PD_POOLS_SUBNET_ID,
-        DELETE_SHARED_NETWORK6_NAME,
+        DELETE_SHARED_NETWORK6_NAME_WITH_TAG,
+        DELETE_SHARED_NETWORK6_NAME_NO_TAG,
         DELETE_ALL_SHARED_NETWORKS6,
         DELETE_SHARED_NETWORK6_SERVER,
         DELETE_OPTION_DEF6_CODE_NAME,
@@ -2711,14 +2712,19 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_DELETE_PD_POOLS()
     },
 
-    // Delete shared network by name.
-    { MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME,
-      MYSQL_DELETE_SHARED_NETWORK(dhcp6, AND n.name = ?)
+    // Delete shared network by name with specifying server tag.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_WITH_TAG,
+      MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp6, AND n.name = ?)
+    },
+
+    // Delete shared network by name without specifying server tag.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_NO_TAG,
+      MYSQL_DELETE_SHARED_NETWORK_NO_TAG(dhcp6, AND n.name = ?)
     },
 
     // Delete all shared networks.
     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6,
-      MYSQL_DELETE_SHARED_NETWORK(dhcp6)
+      MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp6)
     },
 
     // Delete associations of a shared network with server.
@@ -3177,8 +3183,11 @@ MySqlConfigBackendDHCPv6::deleteSharedNetwork6(const ServerSelector& server_sele
                                                const std::string& name) {
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK6)
         .arg(name);
-    uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME,
-                                                 server_selector, "deleting a shared network",
+    int index = (server_selector.amAny() ?
+                 MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_NO_TAG :
+                 MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_WITH_TAG);
+    uint64_t result = impl_->deleteTransactional(index, server_selector,
+                                                 "deleting a shared network",
                                                  "shared network deleted", true, name);
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK6_RESULT)
         .arg(result);
index 855022cb4e37471b1d2aaee2d679b6a84bc50a45..9f5dc3fe838fd27b0be3ad125659303ee11880bc 100644 (file)
@@ -659,14 +659,22 @@ namespace {
     "WHERE subnet_id = ?"
 #endif
 
-#ifndef MYSQL_DELETE_SHARED_NETWORK
-#define MYSQL_DELETE_SHARED_NETWORK(table_prefix, ...) \
+#ifndef MYSQL_DELETE_SHARED_NETWORK_COMMON
+#define MYSQL_DELETE_SHARED_NETWORK_COMMON(table_prefix, ...) \
     "DELETE n FROM " #table_prefix "_shared_network AS n " \
     "INNER JOIN " #table_prefix "_shared_network_server AS a" \
     "  ON n.id = a.shared_network_id " \
     "INNER JOIN " #table_prefix "_server AS s" \
     "  ON a.server_id = s.id " \
-    "WHERE s.tag = ? " #__VA_ARGS__
+    #__VA_ARGS__
+
+#define MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(table_prefix, ...) \
+    MYSQL_DELETE_SHARED_NETWORK_COMMON(table_prefix, WHERE s.tag = ? __VA_ARGS__)
+
+#define MYSQL_DELETE_SHARED_NETWORK_NO_TAG(table_prefix, ...) \
+    MYSQL_DELETE_SHARED_NETWORK_COMMON(table_prefix, __VA_ARGS__)
+
+
 #endif
 
 #ifndef MYSQL_DELETE_SHARED_NETWORK_SERVER
index 971e15d984d07e103e117dd30c862967a0dd1e05..d8db0ebd8f8ca58f59a2087725514900082d540d 100644 (file)
@@ -1801,6 +1801,96 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSharedNetworks4) {
     ASSERT_TRUE(networks.empty());
 }
 
+// Test that selected shared network can be deleted.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4) {
+    // Create two servers in the database.
+    EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp4_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp4_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    auto shared_network1 = test_networks_[0];
+    auto shared_network2 = test_networks_[2];
+    auto shared_network3 = test_networks_[3];
+
+    // Insert two shared networks, one for all servers, and one for server2.
+    EXPECT_NO_THROW(
+        cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), shared_network1)
+    );
+    EXPECT_NO_THROW(
+        cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server2"), shared_network2)
+    );
+    EXPECT_NO_THROW(
+        cbptr_->createUpdateSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                           shared_network3)
+    );
+
+    auto test_no_delete = [this] (const std::string& test_case_name,
+                                  const ServerSelector& server_selector,
+                                  const SharedNetwork4Ptr& shared_network) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSharedNetwork4(server_selector,
+                                                         shared_network->getName())
+        );
+        EXPECT_EQ(0, deleted_count);
+    };
+
+    {
+        SCOPED_TRACE("Test valid but non matching server selectors");
+        test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
+                       shared_network1);
+        test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
+                       shared_network2);
+        test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
+                       shared_network3);
+    }
+
+    // We are not going to support deletion of a single entry for multiple servers.
+    EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                              shared_network3->getName()),
+                 isc::InvalidOperation);
+
+    // We currently don't support deleting a shared network with specifying
+    // an unassigned server tag. Use ANY to delete any subnet instead.
+    EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::UNASSIGNED(),
+                                              shared_network1->getName()),
+                 isc::NotImplemented);
+
+    // Test successful deletion of a shared network.
+    auto test_delete = [this] (const std::string& test_case_name,
+                               const ServerSelector& server_selector,
+                               const SharedNetwork4Ptr& shared_network) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSharedNetwork4(server_selector,
+                                                         shared_network->getName())
+        );
+        EXPECT_EQ(1, deleted_count);
+
+        EXPECT_FALSE(cbptr_->getSharedNetwork4(server_selector,
+                                                  shared_network->getName()));
+    };
+
+    test_delete("all servers", ServerSelector::ALL(), shared_network1);
+    test_delete("any server", ServerSelector::ANY(), shared_network2);
+    test_delete("one server", ServerSelector::ONE("server1"), shared_network3);
+
+}
+
 // Test that lifetimes in shared networks are handled as expected.
 TEST_F(MySqlConfigBackendDHCPv4Test, sharedNetworkLifetime) {
     // Insert new shared network with unspecified valid lifetime
index e54164a56014e73dc4c9dfb19a470dbb4ac6de11..ed91ce5b11493a13bfd5a30a04dad4e59494815d 100644 (file)
@@ -1816,6 +1816,95 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getModifiedSharedNetworks6) {
     ASSERT_TRUE(networks.empty());
 }
 
+// Test that selected shared network can be deleted.
+TEST_F(MySqlConfigBackendDHCPv6Test, deleteSharedNetwork6) {
+    // Create two servers in the database.
+    EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp6_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp6_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    auto shared_network1 = test_networks_[0];
+    auto shared_network2 = test_networks_[2];
+    auto shared_network3 = test_networks_[3];
+
+    // Insert two shared networks, one for all servers, and one for server2.
+    EXPECT_NO_THROW(
+        cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network1)
+    );
+    EXPECT_NO_THROW(
+        cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server2"), shared_network2)
+    );
+    EXPECT_NO_THROW(
+        cbptr_->createUpdateSharedNetwork6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                           shared_network3)
+    );
+
+    auto test_no_delete = [this] (const std::string& test_case_name,
+                                  const ServerSelector& server_selector,
+                                  const SharedNetwork6Ptr& shared_network) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSharedNetwork6(server_selector,
+                                                         shared_network->getName())
+        );
+        EXPECT_EQ(0, deleted_count);
+    };
+
+    {
+        SCOPED_TRACE("Test valid but non matching server selectors");
+        test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
+                       shared_network1);
+        test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
+                       shared_network2);
+        test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
+                       shared_network3);
+    }
+
+    // We are not going to support deletion of a single entry for multiple servers.
+    EXPECT_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                              shared_network3->getName()),
+                 isc::InvalidOperation);
+
+    // We currently don't support deleting a shared network with specifying
+    // an unassigned server tag. Use ANY to delete any subnet instead.
+    EXPECT_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::UNASSIGNED(),
+                                              shared_network1->getName()),
+                 isc::NotImplemented);
+
+    // Test successful deletion of a shared network.
+    auto test_delete = [this] (const std::string& test_case_name,
+                               const ServerSelector& server_selector,
+                               const SharedNetwork6Ptr& shared_network) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSharedNetwork6(server_selector,
+                                                         shared_network->getName())
+        );
+        EXPECT_EQ(1, deleted_count);
+
+        EXPECT_FALSE(cbptr_->getSharedNetwork6(server_selector,
+                                               shared_network->getName()));
+    };
+
+    test_delete("all servers", ServerSelector::ALL(), shared_network1);
+    test_delete("any server", ServerSelector::ANY(), shared_network2);
+    test_delete("one server", ServerSelector::ONE("server1"), shared_network3);
+}
+
 // Test that lifetimes in shared networks are handled as expected.
 TEST_F(MySqlConfigBackendDHCPv6Test, sharedNetworkLifetime) {
     // Insert new shared network with unspecified valid lifetime