DELETE_GLOBAL_PARAMETER4,
DELETE_ALL_GLOBAL_PARAMETERS4,
DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED,
- DELETE_SUBNET4_ID,
- DELETE_SUBNET4_PREFIX,
+ DELETE_SUBNET4_ID_WITH_TAG,
+ DELETE_SUBNET4_ID_ANY,
+ DELETE_SUBNET4_PREFIX_WITH_TAG,
+ DELETE_SUBNET4_PREFIX_ANY,
DELETE_ALL_SUBNETS4,
DELETE_ALL_SUBNETS4_SHARED_NETWORK_NAME,
DELETE_SUBNET4_SERVER,
/// @return Number of deleted subnets.
uint64_t deleteSubnet4(const ServerSelector& server_selector,
const SubnetID& subnet_id) {
- return (deleteTransactional(DELETE_SUBNET4_ID, server_selector,
- "deleting a subnet",
- "subnet deleted",
- true,
- static_cast<uint32_t>(subnet_id)));
+ int index = (server_selector.amAny() ?
+ MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_ANY :
+ MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_WITH_TAG);
+ return (deleteTransactional(index, server_selector,
+ "deleting a subnet", "subnet deleted",
+ true, static_cast<uint32_t>(subnet_id)));
+ }
+
+ /// @brief Sends query to delete subnet by id.
+ ///
+ /// @param server_selector Server selector.
+ /// @param subnet_prefix Prefix of the subnet to be deleted.
+ /// @return Number of deleted subnets.
+ uint64_t deleteSubnet4(const ServerSelector& server_selector,
+ const std::string& subnet_prefix) {
+ int index = (server_selector.amAny() ?
+ MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_ANY :
+ MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_WITH_TAG);
+ return (deleteTransactional(index, server_selector,
+ "deleting a subnet", "subnet deleted",
+ true, subnet_prefix));
}
/// @brief Deletes pools belonging to a subnet from the database.
MYSQL_DELETE_GLOBAL_PARAMETER_UNASSIGNED(dhcp4)
},
- // Delete subnet by id.
- { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID,
- MYSQL_DELETE_SUBNET(dhcp4, AND s.subnet_id = ?)
+ // Delete subnet by id with specifying server tag.
+ { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_WITH_TAG,
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4, AND s.subnet_id = ?)
+ },
+
+ // Delete subnet by id without specifying server tag.
+ { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_ANY,
+ MYSQL_DELETE_SUBNET_ANY(dhcp4, WHERE s.subnet_id = ?)
+ },
+
+ // Delete subnet by prefix with specifying server tag.
+ { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_WITH_TAG,
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4, AND s.subnet_prefix = ?)
},
- // Delete subnet by prefix.
- { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX,
- MYSQL_DELETE_SUBNET(dhcp4, AND s.subnet_prefix = ?)
+ // Delete subnet by prefix without specifying server tag.
+ { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_ANY,
+ MYSQL_DELETE_SUBNET_ANY(dhcp4, WHERE s.subnet_prefix = ?)
},
// Delete all subnets.
{ MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SUBNETS4,
- MYSQL_DELETE_SUBNET(dhcp4)
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4)
},
// Delete all subnets for a shared network.
{ MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SUBNETS4_SHARED_NETWORK_NAME,
- MYSQL_DELETE_SUBNET(dhcp4, AND s.shared_network_name = ?)
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4, AND s.shared_network_name = ?)
},
// Delete associations of a subnet with server.
const std::string& subnet_prefix) {
LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET4)
.arg(subnet_prefix);
- uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX,
- server_selector, "deleting a subnet by prefix",
- "subnet deleted", true, subnet_prefix);
+ uint64_t result = impl_->deleteSubnet4(server_selector, subnet_prefix);
LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET4_RESULT)
.arg(result);
return (result);
DELETE_GLOBAL_PARAMETER6,
DELETE_ALL_GLOBAL_PARAMETERS6,
DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
- DELETE_SUBNET6_ID,
- DELETE_SUBNET6_PREFIX,
+ DELETE_SUBNET6_ID_WITH_TAG,
+ DELETE_SUBNET6_ID_ANY,
+ DELETE_SUBNET6_PREFIX_WITH_TAG,
+ DELETE_SUBNET6_PREFIX_ANY,
DELETE_ALL_SUBNETS6,
DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
DELETE_SUBNET6_SERVER,
/// @return Number of deleted subnets.
uint64_t deleteSubnet6(const ServerSelector& server_selector,
const SubnetID& subnet_id) {
- return (deleteTransactional(DELETE_SUBNET6_ID, server_selector,
- "deleting a subnet",
- "subnet deleted",
- true,
- static_cast<uint32_t>(subnet_id)));
+ int index = (server_selector.amAny() ?
+ MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY :
+ MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG);
+ return (deleteTransactional(index, server_selector,
+ "deleting a subnet", "subnet deleted",
+ true, static_cast<uint32_t>(subnet_id)));
+ }
+
+ /// @brief Sends query to delete subnet by id.
+ ///
+ /// @param server_selector Server selector.
+ /// @param subnet_prefix Prefix of the subnet to be deleted.
+ /// @return Number of deleted subnets.
+ uint64_t deleteSubnet6(const ServerSelector& server_selector,
+ const std::string& subnet_prefix) {
+ int index = (server_selector.amAny() ?
+ MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY :
+ MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG);
+ return (deleteTransactional(index, server_selector,
+ "deleting a subnet", "subnet deleted",
+ true, subnet_prefix));
}
/// @brief Deletes pools belonging to a subnet from the database.
MYSQL_DELETE_GLOBAL_PARAMETER(dhcp6)
},
- // Delete subnet by id.
- { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID,
- MYSQL_DELETE_SUBNET(dhcp6, AND s.subnet_id = ?)
+ // Delete subnet by id with specifying server tag.
+ { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG,
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_id = ?)
+ },
+
+ // Delete subnet by id without specifying server tag.
+ { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY,
+ MYSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_id = ?)
+ },
+
+ // Delete subnet by prefix with specifying server tag.
+ { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG,
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_prefix = ?)
},
- // Delete subnet by prefix.
- { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX,
- MYSQL_DELETE_SUBNET(dhcp6, AND s.subnet_prefix = ?)
+ // Delete subnet by prefix without specifying server tag.
+ { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY,
+ MYSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_prefix = ?)
},
// Delete all subnets.
{ MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6,
- MYSQL_DELETE_SUBNET(dhcp6)
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6)
},
// Delete all subnets for a shared network.
{ MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
- MYSQL_DELETE_SUBNET(dhcp6, AND s.shared_network_name = ?)
+ MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.shared_network_name = ?)
},
// Delete associations of a subnet with server.
const std::string& subnet_prefix) {
LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET6)
.arg(subnet_prefix);
- uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX,
- server_selector, "deleting a subnet by prefix",
- "subnet deleted", true, subnet_prefix);
+ uint64_t result = impl_->deleteSubnet6(server_selector, subnet_prefix);
LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET6_RESULT)
.arg(result);
return (result);
#endif
#ifndef MYSQL_DELETE_SUBNET
-#define MYSQL_DELETE_SUBNET(table_prefix, ...) \
+#define MYSQL_DELETE_SUBNET_COMMON(table_prefix, ...) \
"DELETE s FROM " #table_prefix "_subnet AS s " \
"INNER JOIN " #table_prefix "_subnet_server AS a " \
" ON s.subnet_id = a.subnet_id " \
"INNER JOIN " #table_prefix "_server AS srv" \
" ON a.server_id = srv.id " \
- "WHERE srv.tag = ? " #__VA_ARGS__
+ #__VA_ARGS__
+
+#define MYSQL_DELETE_SUBNET_WITH_TAG(table_prefix, ...) \
+ MYSQL_DELETE_SUBNET_COMMON(table_prefix, WHERE srv.tag = ? __VA_ARGS__)
+
+#define MYSQL_DELETE_SUBNET_ANY(table_prefix, ...) \
+ "DELETE s FROM " #table_prefix "_subnet AS s " \
+ #__VA_ARGS__
+
#endif
#ifndef MYSQL_DELETE_SUBNET_SERVER
EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
}
+// Test that selected subnet can be deleted.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4) {
+ // 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 subnet1 = test_subnets_[0];
+ auto subnet2 = test_subnets_[2];
+ auto subnet3 = test_subnets_[3];
+
+ auto create_test_subnets = [&] () {
+ // Insert three subnets, one for all servers, one for server2 and one for two
+ // servers: server1 and server2.
+ EXPECT_NO_THROW(
+ cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet1)
+ );
+ EXPECT_NO_THROW(
+ cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"), subnet2)
+ );
+ EXPECT_NO_THROW(
+ cbptr_->createUpdateSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+ subnet3)
+ );
+ };
+
+ create_test_subnets();
+
+ // Test that subnet is not deleted for a specified server selector.
+ auto test_no_delete = [this] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const Subnet4Ptr& subnet) {
+ SCOPED_TRACE(test_case_name);
+ uint64_t deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->getID())
+ );
+ EXPECT_EQ(0, deleted_count);
+
+ deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->toText())
+ );
+ EXPECT_EQ(0, deleted_count);
+ };
+
+ {
+ SCOPED_TRACE("Test valid but non matching server selectors");
+ test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
+ subnet1);
+ test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
+ subnet2);
+ test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
+ subnet3);
+ }
+
+ // Test successful deletion of a subnet by ID.
+ auto test_delete_by_id = [this] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const Subnet4Ptr& subnet) {
+ SCOPED_TRACE(test_case_name);
+ uint64_t deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->getID())
+ );
+ EXPECT_EQ(1, deleted_count);
+
+ EXPECT_FALSE(cbptr_->getSubnet4(server_selector, subnet->getID()));
+ };
+
+ test_delete_by_id("all servers", ServerSelector::ALL(), subnet1);
+ test_delete_by_id("any server", ServerSelector::ANY(), subnet2);
+ test_delete_by_id("one server", ServerSelector::ONE("server1"), subnet3);
+
+ // Re-create deleted subnets.
+ create_test_subnets();
+
+ // Test successful deletion of a subnet by prefix.
+ auto test_delete_by_prefix = [this] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const Subnet4Ptr& subnet) {
+ SCOPED_TRACE(test_case_name);
+ uint64_t deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->toText())
+ );
+ EXPECT_EQ(1, deleted_count);
+
+ EXPECT_FALSE(cbptr_->getSubnet4(server_selector, subnet->toText()));
+ };
+
+ test_delete_by_prefix("all servers", ServerSelector::ALL(), subnet1);
+ test_delete_by_prefix("any server", ServerSelector::ANY(), subnet2);
+ test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3);
+}
+
// Test that subnets modified after given time can be fetched.
TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSubnets4) {
// Explicitly set timestamps of subnets. First subnet has a timestamp
auto shared_network2 = test_networks_[2];
auto shared_network3 = test_networks_[3];
- // Insert two shared networks, one for all servers, and one for server2.
+ // Insert three shared networks, one for all servers, one for server2 and
+ // one for two servers: server1 and server2.
EXPECT_NO_THROW(
cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), shared_network1)
);
EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
}
+// Test that selected subnet can be deleted.
+TEST_F(MySqlConfigBackendDHCPv6Test, deleteSubnet6) {
+ // 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 subnet1 = test_subnets_[0];
+ auto subnet2 = test_subnets_[2];
+ auto subnet3 = test_subnets_[3];
+
+ auto create_test_subnets = [&] () {
+ // Insert three subnets, one for all servers, one for server2 and one for two
+ // servers: server1 and server2.
+ EXPECT_NO_THROW(
+ cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet1)
+ );
+ EXPECT_NO_THROW(
+ cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2)
+ );
+ EXPECT_NO_THROW(
+ cbptr_->createUpdateSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+ subnet3)
+ );
+ };
+
+ create_test_subnets();
+
+ // Test that subnet is not deleted for a specified server selector.
+ auto test_no_delete = [this] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const Subnet6Ptr& subnet) {
+ SCOPED_TRACE(test_case_name);
+ uint64_t deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->getID())
+ );
+ EXPECT_EQ(0, deleted_count);
+
+ deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->toText())
+ );
+ EXPECT_EQ(0, deleted_count);
+ };
+
+ {
+ SCOPED_TRACE("Test valid but non matching server selectors");
+ test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
+ subnet1);
+ test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
+ subnet2);
+ test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
+ subnet3);
+ }
+
+ // Test successful deletion of a subnet by ID.
+ auto test_delete_by_id = [this] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const Subnet6Ptr& subnet) {
+ SCOPED_TRACE(test_case_name);
+ uint64_t deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->getID())
+ );
+ EXPECT_EQ(1, deleted_count);
+
+ EXPECT_FALSE(cbptr_->getSubnet6(server_selector, subnet->getID()));
+ };
+
+ test_delete_by_id("all servers", ServerSelector::ALL(), subnet1);
+ test_delete_by_id("any server", ServerSelector::ANY(), subnet2);
+ test_delete_by_id("one server", ServerSelector::ONE("server1"), subnet3);
+
+ // Re-create deleted subnets.
+ create_test_subnets();
+
+ // Test successful deletion of a subnet by prefix.
+ auto test_delete_by_prefix = [this] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const Subnet6Ptr& subnet) {
+ SCOPED_TRACE(test_case_name);
+ uint64_t deleted_count = 0;
+ EXPECT_NO_THROW(
+ deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->toText())
+ );
+ EXPECT_EQ(1, deleted_count);
+
+ EXPECT_FALSE(cbptr_->getSubnet6(server_selector, subnet->toText()));
+ };
+
+ test_delete_by_prefix("all servers", ServerSelector::ALL(), subnet1);
+ test_delete_by_prefix("any server", ServerSelector::ANY(), subnet2);
+ test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3);
+}
+
// Test that subnets modified after given time can be fetched.
TEST_F(MySqlConfigBackendDHCPv6Test, getModifiedSubnets6) {
// Explicitly set timestamps of subnets. First subnet has a timestamp