Commit 7e5e5a0b authored by Marcin Siodelski's avatar Marcin Siodelski

[#717,!417] Added support to delete a subnet with ANY server selector.

parent 8dc1f640
......@@ -115,8 +115,10 @@ public:
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,
......@@ -1003,11 +1005,27 @@ public:
/// @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.
......@@ -2422,24 +2440,34 @@ TaggedStatementArray tagged_statements = { {
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.
......@@ -2862,9 +2890,7 @@ MySqlConfigBackendDHCPv4::deleteSubnet4(const ServerSelector& server_selector,
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);
......
......@@ -120,8 +120,10 @@ public:
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,
......@@ -1190,11 +1192,27 @@ public:
/// @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.
......@@ -2780,24 +2798,34 @@ TaggedStatementArray tagged_statements = { {
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.
......@@ -3241,9 +3269,7 @@ MySqlConfigBackendDHCPv6::deleteSubnet6(const ServerSelector& server_selector,
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);
......
......@@ -711,13 +711,21 @@ namespace {
#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
......
......@@ -1428,6 +1428,114 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4WithServerTags) {
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
......@@ -2094,7 +2202,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4) {
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)
);
......
......@@ -1446,6 +1446,114 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllSubnets6WithServerTags) {
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment