]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[712-cb_cmds-add-support-for-server-tags-in-the-shared-networks] Finished CB tests
authorFrancis Dupont <fdupont@isc.org>
Wed, 10 Jul 2019 12:11:35 +0000 (14:11 +0200)
committerFrancis Dupont <fdupont@isc.org>
Fri, 12 Jul 2019 17:21:09 +0000 (19:21 +0200)
src/lib/dhcpsrv/config_backend_dhcp4.h
src/lib/dhcpsrv/config_backend_dhcp6.h
src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.cc
src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.cc

index 840cfd7ebf593f8920c3056aa90454aa7ea1bcdd..bf09e154fdc2d0315a6ec566f74c9a831ead023e 100644 (file)
@@ -123,12 +123,12 @@ public:
 
     /// @brief Retrieves all subnets belonging to a specified shared network.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
     /// @param shared_network_name Name of the shared network for which the
-    /// subnets should be retrieved.
+    /// retrieved subnets should belongs to.
     /// @return Collection of subnets or empty collection if no subnet found.
     virtual Subnet4Collection
     getSharedNetworkSubnets4(const db::ServerSelector& server_selector,
@@ -369,7 +369,7 @@ public:
 
     /// @brief Creates or updates shared network level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param selector Server selector.
@@ -383,7 +383,7 @@ public:
 
     /// @brief Creates or updates subnet level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -396,7 +396,7 @@ public:
 
     /// @brief Creates or updates pool level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -463,9 +463,12 @@ public:
 
     /// @brief Deletes all subnets belonging to a specified shared network.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE.
+    /// Not allowed server selectors: ANY, MULTIPLE.
+    ///
     /// @param server_selector Server selector.
     /// @param shared_network_name Name of the shared network for which the
-    /// subnets should be deleted.
+    /// deleted subnets should belongs to.
     /// @return Number of deleted subnets.
     virtual uint64_t
     deleteSharedNetworkSubnets4(const db::ServerSelector& server_selector,
@@ -533,7 +536,7 @@ public:
 
     /// @brief Deletes shared network level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param selector Server selector.
@@ -549,7 +552,7 @@ public:
 
     /// @brief Deletes subnet level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -566,7 +569,7 @@ public:
 
     /// @brief Deletes pool level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
index f65244fb50133fb2d0ea4d7831f9fc73b956b78a..d0cc58a4fc8fc7d70bd3c487628c6b2b4aa8c285 100644 (file)
@@ -124,12 +124,12 @@ public:
 
     /// @brief Retrieves all subnets belonging to a specified shared network.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
     /// @param shared_network_name Name of the shared network for which the
-    /// subnets should be retrieved.
+    /// retrieved subnets should belongs to.
     /// @return Collection of subnets or empty collection if no subnet found.
     virtual Subnet6Collection
     getSharedNetworkSubnets6(const db::ServerSelector& server_selector,
@@ -370,8 +370,8 @@ public:
 
     /// @brief Creates or updates shared network level option.
     ///
-    /// Allowed server selectors: ALL.
-    /// Not allowed server selectors: ANY, UNASSIGNED, ONE, MULTIPLE.
+    /// Allowed server selector: ANY.
+    /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param selector Server selector.
     /// @param shared_network_name Name of a shared network to which option
@@ -384,7 +384,7 @@ public:
 
     /// @brief Creates or updates subnet level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -397,7 +397,7 @@ public:
 
     /// @brief Creates or updates pool level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -414,7 +414,7 @@ public:
 
     /// @brief Creates or updates prefix delegation pool level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -481,9 +481,12 @@ public:
 
     /// @brief Deletes all subnets belonging to a specified shared network.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE.
+    /// Not allowed server selectors: ANY, MULTIPLE.
+    ///
     /// @param server_selector Server selector.
     /// @param shared_network_name Name of the shared network for which the
-    /// subnets should be deleted.
+    /// deleted subnets should belongs to.
     /// @return Number of deleted subnets.
     virtual uint64_t
     deleteSharedNetworkSubnets6(const db::ServerSelector& server_selector,
@@ -551,6 +554,9 @@ public:
 
     /// @brief Deletes shared network level option.
     ///
+    /// Allowed server selectors: ANY, UNASSIGNED, ALL, ONE.
+    /// Not allowed server selector: MULTIPLE.
+    ///
     /// @param selector Server selector.
     /// @param shared_network_name Name of the shared network which option
     /// belongs to.
@@ -564,7 +570,7 @@ public:
 
     /// @brief Deletes subnet level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -581,7 +587,7 @@ public:
 
     /// @brief Deletes pool level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
@@ -601,7 +607,7 @@ public:
 
     /// @brief Deletes prefix delegation pool level option.
     ///
-    /// Allowed server selectors: ANY.
+    /// Allowed server selector: ANY.
     /// Not allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
     ///
     /// @param server_selector Server selector.
index 353bb07b9348bef0156dfbc26339279601dadfb3..3b70d981a7e908d94e0278060a47210c099fceab 100644 (file)
@@ -152,25 +152,43 @@ TestConfigBackendDHCPv4::getModifiedSubnets4(const db::ServerSelector& server_se
 }
 
 Subnet4Collection
-TestConfigBackendDHCPv4::getSharedNetworkSubnets4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::getSharedNetworkSubnets4(const db::ServerSelector& server_selector,
                                                   const std::string& shared_network_name) const {
     Subnet4Collection subnets;
 
     // Subnet collection does not include the index by shared network name.
     // We need to iterate over the subnets and pick those that are associated
     // with a shared network.
-    for (auto subnet = subnets_.begin(); subnet != subnets_.end();
-         ++subnet) {
+    for (auto subnet : subnets_) {
+        // Skip subnets which do not match the server selector.
+        if (server_selector.amUnassigned() &&
+            !subnet->getServerTags().empty()) {
+            continue;
+        }
+        if (!server_selector.amAny()) {
+            bool got = false;
+            auto tags = server_selector.getTags();
+            for (auto tag : tags) {
+                if (subnet->hasServerTag(ServerTag(tag))) {
+                    got = true;
+                    break;
+                }
+            }
+            if (!got && !subnet->hasAllServerTag()) {
+                continue;
+            }
+        }
+
         // The subnet can be associated with a shared network instance or
         // it may just point to the shared network name. The former is
         // the case when the subnet belongs to the server configuration.
         // The latter is the case when the subnet is fetched from the
         // database.
         SharedNetwork4Ptr network;
-        (*subnet)->getSharedNetwork(network);
+        subnet->getSharedNetwork(network);
         if (((network && (network->getName() == shared_network_name)) ||
-             ((*subnet)->getSharedNetworkName() == shared_network_name))) {
-            subnets.push_back(*subnet);
+             (subnet->getSharedNetworkName() == shared_network_name))) {
+            subnets.push_back(subnet);
         }
     }
     return (subnets);
@@ -613,8 +631,16 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_se
     }
 
     auto shared_network = *network_it;
-    if (!shared_network->hasAllServerTag()) {
-        bool found = false;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (shared_network->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (shared_network->hasAllServerTag()) {
+        found = true;
+    } else {
         auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (shared_network->hasServerTag(ServerTag(tag))) {
@@ -622,11 +648,11 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_se
                 break;
             }
         }
-        if (!found) {
-            isc_throw(BadValue, "attempted to create or update option in a "
-                      "shared network " << shared_network_name
-                      << " not present in a selected server");
-        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to create or update option in a "
+                  "shared network " << shared_network_name
+                  << " not present in a selected server");
     }
 
     shared_network->getCfgOption()->del(option->space_name_, option->option_->getType());
@@ -646,8 +672,16 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_se
     }
 
     auto subnet = *subnet_it;
-    if (!subnet->hasAllServerTag()) {
-        bool found = false;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (subnet->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (subnet->hasAllServerTag()) {
+        found = true;
+    } else {
         auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (subnet->hasServerTag(ServerTag(tag))) {
@@ -655,11 +689,11 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_se
                 break;
             }
         }
-        if (!found) {
-            isc_throw(BadValue, "attempted to create or update option in a "
-                      "subnet ID " << subnet_id
-                      << " not present in a selected server");
-        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to create or update option in a "
+                  "subnet ID " << subnet_id
+                  << " not present in a selected server");
     }
 
     subnet->getCfgOption()->del(option->space_name_, option->option_->getType());
@@ -671,18 +705,23 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_se
                                              const asiolink::IOAddress& pool_start_address,
                                              const asiolink::IOAddress& pool_end_address,
                                              const OptionDescriptorPtr& option) {
-    auto tags = server_selector.getTags();
-    auto not_in_tags = false;
+    auto not_in_selected_servers = false;
     for (auto subnet : subnets_) {
         // Get the pool: if it is not here we can directly go to the next subnet.
-        auto pool = subnet->getPool(Lease::TYPE_V4, pool_start_address);
+        auto pool = subnet->getPool(Lease::TYPE_NA, pool_start_address);
         if (!pool) {
             continue;
         }
 
-        // Verify the subnet is in all or one of the given servers.
-        if (!subnet->hasAllServerTag()) {
+        // Verify the subnet is in a selected server.
+        if (server_selector.amUnassigned()) {
+            if (!subnet->getServerTags().empty()) {
+                not_in_selected_servers = true;
+                continue;
+            }
+        } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
             auto in_tags = false;
+            auto tags = server_selector.getTags();
             for (auto tag : tags) {
                 if (subnet->hasServerTag(ServerTag(tag))) {
                     in_tags = true;
@@ -691,7 +730,7 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_se
             }
             if (!in_tags) {
                 // Records the fact a subnet was found but not in a server.
-                not_in_tags = true;
+                not_in_selected_servers = true;
                 continue;
             }
         }
@@ -703,15 +742,15 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_se
         return;
     }
 
-    if (not_in_tags) {
-        isc_throw(BadValue, "attempted to create or update option in "
-                  "a non existing pool " << pool_start_address
-                  << " - " << pool_end_address);
-    } else {
+    if (not_in_selected_servers) {
         isc_throw(BadValue, "attempted to create or update option in "
                   "a pool " << pool_start_address
                   << " - " << pool_end_address
                   << " not present in a selected server");
+    } else {
+        isc_throw(BadValue, "attempted to create or update option in "
+                  "a non existing pool " << pool_start_address
+                  << " - " << pool_end_address);
     }
 }
 
@@ -847,11 +886,32 @@ TestConfigBackendDHCPv4::deleteAllSubnets4(const db::ServerSelector& server_sele
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteSharedNetworkSubnets4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::deleteSharedNetworkSubnets4(const db::ServerSelector& server_selector,
                                                      const std::string& shared_network_name) {
     uint64_t cnt = 0;
     auto& index = subnets_.get<SubnetRandomAccessIndexTag>();
     for (auto subnet = index.begin(); subnet != index.end(); ) {
+        // Skip subnets which do not match the server selector.
+        if (server_selector.amUnassigned() &&
+           !(*subnet)->getServerTags().empty()) {
+            ++subnet;
+            continue;
+        }
+        if (!server_selector.amAny()) {
+            bool got = false;
+            auto tags = server_selector.getTags();
+            for (auto tag : tags) {
+                if ((*subnet)->hasServerTag(ServerTag(tag))) {
+                    got = true;
+                    break;
+                }
+            }
+            if (!got && !(*subnet)->hasAllServerTag()) {
+                ++subnet;
+                continue;
+            }
+        }
+
         SharedNetwork4Ptr network;
         (*subnet)->getSharedNetwork(network);
         if (network && (network->getName() == shared_network_name)) {
@@ -1000,56 +1060,135 @@ TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector,
                                        const std::string& shared_network_name,
                                        const uint16_t code,
                                        const std::string& space) {
     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(shared_network_name);
 
-    if (network_it != index.end()) {
-        auto shared_network = *network_it;
-        return (shared_network->getCfgOption()->del(space, code));
-
-    } else {
+    if (network_it == index.end()) {
         isc_throw(BadValue, "attempted to delete an option in a non existing "
                   "shared network " << shared_network_name);
     }
+
+    auto shared_network = *network_it;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (shared_network->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (shared_network->hasAllServerTag()) {
+        found = true;
+    } else {
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (shared_network->hasServerTag(ServerTag(tag))) {
+                found = true;
+                break;
+            }
+        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to delete option in a "
+                  "shared network " << shared_network_name
+                  << " not present in a selected server");
+    }
+
+    return (shared_network->getCfgOption()->del(space, code));
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector,
                                        const SubnetID& subnet_id,
                                        const uint16_t code,
                                        const std::string& space) {
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet_id);
 
-    if (subnet_it != index.cend()) {
-        auto subnet = *subnet_it;
-        return (subnet->getCfgOption()->del(space, code));
-
-    } else {
+    if (subnet_it == index.cend()) {
         isc_throw(BadValue, "attempted to delete an option in a non existing "
                   "subnet ID " << subnet_id);
     }
+
+    auto subnet = *subnet_it;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (subnet->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (subnet->hasAllServerTag()) {
+        found = true;
+    } else {
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (subnet->hasServerTag(ServerTag(tag))) {
+                found = true;
+                break;
+            }
+        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to delete option in a "
+                  "subnet ID " << subnet_id
+                  << " not present in a selected server");
+    }
+
+    return (subnet->getCfgOption()->del(space, code));
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector,
                                        const asiolink::IOAddress& pool_start_address,
                                        const asiolink::IOAddress& pool_end_address,
                                        const uint16_t code,
                                        const std::string& space) {
-    for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ++subnet) {
-        auto pool = (*subnet)->getPool(Lease::TYPE_V4, pool_start_address);
-        if (pool) {
-            return (pool->getCfgOption()->del(space, code));
+    auto not_in_selected_servers = false;
+    for (auto subnet : subnets_) {
+        // Get the pool: if it is not here we can directly go to the next subnet.
+
+        auto pool = subnet->getPool(Lease::TYPE_V4, pool_start_address);
+        if (!pool) {
+            continue;
+        }
+
+        // Verify the subnet is in a selected server.
+        if (server_selector.amUnassigned()) {
+            if (!subnet->getServerTags().empty()) {
+                not_in_selected_servers = true;
+                continue;
+            }
+        } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
+            auto in_tags = false;
+            auto tags = server_selector.getTags();
+            for (auto tag : tags) {
+                if (subnet->hasServerTag(ServerTag(tag))) {
+                    in_tags = true;
+                    break;
+                }
+            }
+            if (!in_tags) {
+                // Records the fact a subnet was found but not in a server.
+                not_in_selected_servers = true;
+                continue;
+            }
         }
+
+        return (pool->getCfgOption()->del(space, code));
     }
 
-    isc_throw(BadValue, "attempted to delete an option in a non existing "
-              "pool " << pool_start_address << " - " << pool_end_address);
+    if (not_in_selected_servers) {
+        isc_throw(BadValue, "attempted to delete an option in a pool "
+                  << pool_start_address << " - " << pool_end_address
+                  << " not present in a selected server");
+    } else {
+        isc_throw(BadValue, "attempted to delete an option in a non existing "
+                  "pool " << pool_start_address << " - " << pool_end_address);
+    }
 }
 
 uint64_t
index e6209ee8e88b316382ba16d0519d6a20d6f3adec..69b10d56f5eb5ce6767baf7932f7e54800b89866 100644 (file)
@@ -151,25 +151,43 @@ TestConfigBackendDHCPv6::getModifiedSubnets6(const db::ServerSelector& server_se
 }
 
 Subnet6Collection
-TestConfigBackendDHCPv6::getSharedNetworkSubnets6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::getSharedNetworkSubnets6(const db::ServerSelector& server_selector,
                                                   const std::string& shared_network_name) const {
     Subnet6Collection subnets;
 
     // Subnet collection does not include the index by shared network name.
     // We need to iterate over the subnets and pick those that are associated
     // with a shared network.
-    for (auto subnet = subnets_.begin(); subnet != subnets_.end();
-         ++subnet) {
+    for (auto subnet : subnets_) {
+        // Skip subnets which do not match the server selector.
+        if (server_selector.amUnassigned() &&
+            !subnet->getServerTags().empty()) {
+            continue;
+        }
+        if (!server_selector.amAny()) {
+            bool got = false;
+            auto tags = server_selector.getTags();
+            for (auto tag : tags) {
+                if (subnet->hasServerTag(ServerTag(tag))) {
+                    got = true;
+                    break;
+                }
+            }
+            if (!got && !subnet->hasAllServerTag()) {
+                continue;
+            }
+        }
+
         // The subnet can be associated with a shared network instance or
         // it may just point to the shared network name. The former is
         // the case when the subnet belongs to the server configuration.
         // The latter is the case when the subnet is fetched from the
         // database.
         SharedNetwork6Ptr network;
-        (*subnet)->getSharedNetwork(network);
+        subnet->getSharedNetwork(network);
         if (((network && (network->getName() == shared_network_name)) ||
-             ((*subnet)->getSharedNetworkName() == shared_network_name))) {
-            subnets.push_back(*subnet);
+             (subnet->getSharedNetworkName() == shared_network_name))) {
+            subnets.push_back(subnet);
         }
     }
     return (subnets);
@@ -612,8 +630,16 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
     }
 
     auto shared_network = *network_it;
-    if (!shared_network->hasAllServerTag()) {
-        bool found = false;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (shared_network->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (shared_network->hasAllServerTag()) {
+        found = true;
+    } else {
         auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (shared_network->hasServerTag(ServerTag(tag))) {
@@ -621,11 +647,11 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
                 break;
             }
         }
-        if (!found) {
-            isc_throw(BadValue, "attempted to create or update option in a "
-                      "shared network " << shared_network_name
-                      << " not present in a selected server");
-        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to create or update option in a "
+                  "shared network " << shared_network_name
+                  << " not present in a selected server");
     }
 
     shared_network->getCfgOption()->del(option->space_name_, option->option_->getType());
@@ -645,8 +671,16 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
     }
 
     auto subnet = *subnet_it;
-    if (!subnet->hasAllServerTag()) {
-        bool found = false;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (subnet->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (subnet->hasAllServerTag()) {
+        found = true;
+    } else {
         auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (subnet->hasServerTag(ServerTag(tag))) {
@@ -654,11 +688,11 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
                 break;
             }
         }
-        if (!found) {
-            isc_throw(BadValue, "attempted to create or update option in a "
-                      "subnet ID " << subnet_id
-                      << " not present in a selected server");
-        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to create or update option in a "
+                  "subnet ID " << subnet_id
+                  << " not present in a selected server");
     }
 
     subnet->getCfgOption()->del(option->space_name_, option->option_->getType());
@@ -670,8 +704,7 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
                                              const asiolink::IOAddress& pool_start_address,
                                              const asiolink::IOAddress& pool_end_address,
                                              const OptionDescriptorPtr& option) {
-    auto tags = server_selector.getTags();
-    auto not_in_tags = false;
+    auto not_in_selected_servers = false;
     for (auto subnet : subnets_) {
         // Get the pool: if it is not here we can directly go to the next subnet.
         auto pool = subnet->getPool(Lease::TYPE_NA, pool_start_address);
@@ -679,9 +712,15 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
             continue;
         }
 
-        // Verify the subnet is in all or one of the given servers.
-        if (!subnet->hasAllServerTag()) {
+        // Verify the subnet is in a selected server.
+        if (server_selector.amUnassigned()) {
+            if (!subnet->getServerTags().empty()) {
+                not_in_selected_servers = true;
+                continue;
+            }
+        } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
             auto in_tags = false;
+            auto tags = server_selector.getTags();
             for (auto tag : tags) {
                 if (subnet->hasServerTag(ServerTag(tag))) {
                     in_tags = true;
@@ -690,7 +729,7 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
             }
             if (!in_tags) {
                 // Records the fact a subnet was found but not in a server.
-                not_in_tags = true;
+                not_in_selected_servers = true;
                 continue;
             }
         }
@@ -702,15 +741,15 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
         return;
     }
 
-    if (not_in_tags) {
-        isc_throw(BadValue, "attempted to create or update option in "
-                  "a non existing pool " << pool_start_address
-                  << " - " << pool_end_address);
-    } else {
+    if (not_in_selected_servers) {
         isc_throw(BadValue, "attempted to create or update option in "
                   "a pool " << pool_start_address
                   << " - " << pool_end_address
                   << " not present in a selected server");
+    } else {
+        isc_throw(BadValue, "attempted to create or update option in "
+                  "a non existing pool " << pool_start_address
+                  << " - " << pool_end_address);
     }
 }
 
@@ -719,8 +758,7 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
                                              const asiolink::IOAddress& pd_pool_prefix,
                                              const uint8_t pd_pool_prefix_length,
                                              const OptionDescriptorPtr& option) {
-    auto tags = server_selector.getTags();
-    auto not_in_tags = false;
+    auto not_in_selected_servers = false;
     for (auto subnet : subnets_) {
         // Get the pd pool: if it is not here we can directly go to the next subnet.
         auto pdpool = subnet->getPool(Lease::TYPE_PD, pd_pool_prefix);
@@ -728,9 +766,15 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
             continue;
         }
 
-        // Verify the subnet is in all or one of the given servers.
-        if (!subnet->hasAllServerTag()) {
+        // Verify the subnet is in a selected server.
+        if (server_selector.amUnassigned()) {
+            if (!subnet->getServerTags().empty()) {
+                not_in_selected_servers = true;
+                continue;
+            }
+        } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
             auto in_tags = false;
+            auto tags = server_selector.getTags();
             for (auto tag : tags) {
                 if (subnet->hasServerTag(ServerTag(tag))) {
                     in_tags = true;
@@ -739,7 +783,7 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
             }
             if (!in_tags) {
                 // Records the fact a subnet was found but not in a server.
-                not_in_tags = true;
+                not_in_selected_servers = true;
                 continue;
             }
         }
@@ -751,15 +795,15 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_se
         return;
     }
 
-    if (not_in_tags) {
-        isc_throw(BadValue, "attempted to create or update option in "
-                  "a non existing prefix pool " << pd_pool_prefix
-                  << "/" << static_cast<unsigned>(pd_pool_prefix_length));
-    } else {
+    if (not_in_selected_servers) {
         isc_throw(BadValue, "attempted to create or update option in "
                   "a prefix pool " << pd_pool_prefix
                   << "/" << static_cast<unsigned>(pd_pool_prefix_length)
                   << " not present in a selected server");
+    } else {
+        isc_throw(BadValue, "attempted to create or update option in "
+                  "a non existing prefix pool " << pd_pool_prefix
+                  << "/" << static_cast<unsigned>(pd_pool_prefix_length));
     }
 }
 
@@ -895,11 +939,32 @@ TestConfigBackendDHCPv6::deleteAllSubnets6(const db::ServerSelector& server_sele
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteSharedNetworkSubnets6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteSharedNetworkSubnets6(const db::ServerSelector& server_selector,
                                                      const std::string& shared_network_name) {
     uint64_t cnt = 0;
     auto& index = subnets_.get<SubnetRandomAccessIndexTag>();
     for (auto subnet = index.begin(); subnet != index.end(); ) {
+        // Skip subnets which do not match the server selector.
+        if (server_selector.amUnassigned() &&
+           !(*subnet)->getServerTags().empty()) {
+            ++subnet;
+            continue;
+        }
+        if (!server_selector.amAny()) {
+            bool got = false;
+            auto tags = server_selector.getTags();
+            for (auto tag : tags) {
+                if ((*subnet)->hasServerTag(ServerTag(tag))) {
+                    got = true;
+                    break;
+                }
+            }
+            if (!got && !(*subnet)->hasAllServerTag()) {
+                ++subnet;
+                continue;
+            }
+        }
+
         SharedNetwork6Ptr network;
         (*subnet)->getSharedNetwork(network);
         if (network && (network->getName() == shared_network_name)) {
@@ -1048,74 +1113,186 @@ TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& server_selector
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& server_selector,
                                        const std::string& shared_network_name,
                                        const uint16_t code,
                                        const std::string& space) {
     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(shared_network_name);
 
-    if (network_it != index.end()) {
-        auto shared_network = *network_it;
-        return (shared_network->getCfgOption()->del(space, code));
-
-    } else {
+    if (network_it == index.end()) {
         isc_throw(BadValue, "attempted to delete an option in a non existing "
                   "shared network " << shared_network_name);
     }
+
+    auto shared_network = *network_it;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (shared_network->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (shared_network->hasAllServerTag()) {
+        found = true;
+    } else {
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (shared_network->hasServerTag(ServerTag(tag))) {
+                found = true;
+                break;
+            }
+        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to delete option in a "
+                  "shared network " << shared_network_name
+                  << " not present in a selected server");
+    }
+
+    return (shared_network->getCfgOption()->del(space, code));
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& server_selector,
                                        const SubnetID& subnet_id,
                                        const uint16_t code,
                                        const std::string& space) {
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet_id);
 
-    if (subnet_it != index.cend()) {
-        auto subnet = *subnet_it;
-        return (subnet->getCfgOption()->del(space, code));
-
-    } else {
+    if (subnet_it == index.cend()) {
         isc_throw(BadValue, "attempted to delete an option in a non existing "
                   "subnet ID " << subnet_id);
     }
+
+    auto subnet = *subnet_it;
+    bool found = false;
+    if (server_selector.amUnassigned()) {
+        if (subnet->getServerTags().empty()) {
+            found = true;
+        }
+    } else if (server_selector.amAny()) {
+        found = true;
+    } else if (subnet->hasAllServerTag()) {
+        found = true;
+    } else {
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (subnet->hasServerTag(ServerTag(tag))) {
+                found = true;
+                break;
+            }
+        }
+    }
+    if (!found) {
+        isc_throw(BadValue, "attempted to delete option in a "
+                  "subnet ID " << subnet_id
+                  << " not present in a selected server");
+    }
+
+    return (subnet->getCfgOption()->del(space, code));
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& server_selector,
                                        const asiolink::IOAddress& pool_start_address,
                                        const asiolink::IOAddress& pool_end_address,
                                        const uint16_t code,
                                        const std::string& space) {
-    for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ++subnet) {
-        auto pool = (*subnet)->getPool(Lease::TYPE_NA, pool_start_address);
-        if (pool) {
-            return (pool->getCfgOption()->del(space, code));
+    auto not_in_selected_servers = false;
+    for (auto subnet : subnets_) {
+        // Get the pool: if it is not here we can directly go to the next subnet.
+
+        auto pool = subnet->getPool(Lease::TYPE_NA, pool_start_address);
+        if (!pool) {
+            continue;
         }
+
+        // Verify the subnet is in a selected server.
+        if (server_selector.amUnassigned()) {
+            if (!subnet->getServerTags().empty()) {
+                not_in_selected_servers = true;
+                continue;
+            }
+        } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
+            auto in_tags = false;
+            auto tags = server_selector.getTags();
+            for (auto tag : tags) {
+                if (subnet->hasServerTag(ServerTag(tag))) {
+                    in_tags = true;
+                    break;
+                }
+            }
+            if (!in_tags) {
+                // Records the fact a subnet was found but not in a server.
+                not_in_selected_servers = true;
+                continue;
+            }
+        }
+
+        return (pool->getCfgOption()->del(space, code));
     }
 
-    isc_throw(BadValue, "attempted to delete an option in a non existing "
-              "pool " << pool_start_address << " - " << pool_end_address);
+    if (not_in_selected_servers) {
+        isc_throw(BadValue, "attempted to delete an option in a pool "
+                  << pool_start_address << " - " << pool_end_address
+                  << " not present in a selected server");
+    } else {
+        isc_throw(BadValue, "attempted to delete an option in a non existing "
+                  "pool " << pool_start_address << " - " << pool_end_address);
+    }
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteOption6(const db::ServerSelector& server_selector,
                                        const asiolink::IOAddress& pd_pool_prefix,
                                        const uint8_t pd_pool_prefix_length,
                                        const uint16_t code,
                                        const std::string& space) {
-    for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ++subnet) {
-        auto pdpool = (*subnet)->getPool(Lease::TYPE_PD, pd_pool_prefix);
-        if (pdpool) {
-            return (pdpool->getCfgOption()->del(space, code));
+    auto not_in_selected_servers = false;
+    for (auto subnet : subnets_) {
+        // Get the pd pool: if it is not here we can directly go to the next subnet.
+        auto pdpool = subnet->getPool(Lease::TYPE_PD, pd_pool_prefix);
+        if (!pdpool) {
+            continue;
+        }
+
+        // Verify the subnet is in a selected server.
+        if (server_selector.amUnassigned()) {
+            if (!subnet->getServerTags().empty()) {
+                not_in_selected_servers = true;
+                continue;
+            }
+        } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
+            auto in_tags = false;
+            auto tags = server_selector.getTags();
+            for (auto tag : tags) {
+                if (subnet->hasServerTag(ServerTag(tag))) {
+                    in_tags = true;
+                    break;
+                }
+            }
+            if (!in_tags) {
+                // Records the fact a subnet was found but not in a server.
+                not_in_selected_servers = true;
+                continue;
+            }
         }
+
+        return (pdpool->getCfgOption()->del(space, code));
     }
 
-    isc_throw(BadValue, "attempted to delete an option in a non existing "
-              "pd pool " << pd_pool_prefix << "/"
-              << static_cast<unsigned>(pd_pool_prefix_length));
+    if (not_in_selected_servers) {
+        isc_throw(BadValue, "attempted to delete an option in "
+                  "a prefix pool " << pd_pool_prefix
+                  << "/" << static_cast<unsigned>(pd_pool_prefix_length)
+                  << " not present in a selected server");
+    } else {
+        isc_throw(BadValue, "attempted to delete an option in "
+                  "a non existing prefix pool " << pd_pool_prefix
+                  << "/" << static_cast<unsigned>(pd_pool_prefix_length));
+    }
 }
 
 uint64_t