]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[712-cb_cmds-add-support-for-server-tags-in-the-shared-networks] Updated CB API descr...
authorFrancis Dupont <fdupont@isc.org>
Tue, 9 Jul 2019 22:26:01 +0000 (00:26 +0200)
committerFrancis Dupont <fdupont@isc.org>
Fri, 12 Jul 2019 17:16:11 +0000 (19:16 +0200)
src/lib/dhcpsrv/config_backend_dhcp4.h
src/lib/dhcpsrv/config_backend_dhcp6.h
src/lib/dhcpsrv/testutils/test_config_backend.h
src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.cc
src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.cc

index e5199057c3d56d146eb1b6f4a4f488a39dce9388..840cfd7ebf593f8920c3056aa90454aa7ea1bcdd 100644 (file)
@@ -185,7 +185,7 @@ public:
     /// @brief Retrieves single option definition by code and space.
     ///
     /// Allowed server selectors: ALL, ONE.
-    /// Not allowed server selector: ANY, UNASSIGNED, MULTIPLE.
+    /// Not allowed server selectors: ANY, UNASSIGNED, MULTIPLE.
     ///
     /// @param server_selector Server selector.
     /// @param code Code of the option to be retrieved.
@@ -223,7 +223,7 @@ public:
     /// @brief Retrieves single option by code and space.
     ///
     /// Allowed server selectors: ALL, ONE.
-    /// Not allowed server selector: ANY, UNASSIGNED, MULTIPLE.
+    /// Not allowed server selectors: ANY, UNASSIGNED, MULTIPLE.
     ///
     /// @param server_selector Server selector.
     /// @param code Option code.
@@ -261,7 +261,7 @@ public:
     /// @brief Retrieves global parameter value.
     ///
     /// Allowed server selectors: ALL, ONE.
-    /// Not allowed server selector: ANY, UNASSIGNED, MULTIPLE.
+    /// Not allowed server selectors: ANY, UNASSIGNED, MULTIPLE.
     ///
     /// @param selector Server selector.
     /// @param name Name of the global parameter to be retrieved.
@@ -503,7 +503,8 @@ public:
     /// @param space Option space of the option to be deleted.
     /// @return Number of deleted option definitions.
     virtual uint64_t
-    deleteOptionDef4(const db::ServerSelector& server_selector, const uint16_t code,
+    deleteOptionDef4(const db::ServerSelector& server_selector,
+                     const uint16_t code,
                      const std::string& space) = 0;
 
     /// @brief Deletes all option definitions.
@@ -526,7 +527,8 @@ public:
     /// @param space Option space of the option to be deleted.
     /// @return Number of deleted options.
     virtual uint64_t
-    deleteOption4(const db::ServerSelector& server_selector, const uint16_t code,
+    deleteOption4(const db::ServerSelector& server_selector,
+                  const uint16_t code,
                   const std::string& space) = 0;
 
     /// @brief Deletes shared network level option.
@@ -557,8 +559,10 @@ public:
     /// @param space Option space of the deleted option.
     /// @return Number of deleted options.
     virtual uint64_t
-    deleteOption4(const db::ServerSelector& server_selector, const SubnetID& subnet_id,
-                  const uint16_t code, const std::string& space) = 0;
+    deleteOption4(const db::ServerSelector& server_selector,
+                  const SubnetID& subnet_id,
+                  const uint16_t code,
+                  const std::string& space) = 0;
 
     /// @brief Deletes pool level option.
     ///
index 71c811439a3d9eb34911edc9bebff76ff9c02a00..f65244fb50133fb2d0ea4d7831f9fc73b956b78a 100644 (file)
@@ -186,7 +186,7 @@ public:
     /// @brief Retrieves single option definition by code and space.
     ///
     /// Allowed server selectors: ALL, ONE.
-    /// Not allowed server selector: ANY, UNASSIGNED, MULTIPLE.
+    /// Not allowed server selectors: ANY, UNASSIGNED, MULTIPLE.
     ///
     /// @param server_selector Server selector.
     /// @param code Code of the option to be retrieved.
@@ -224,7 +224,7 @@ public:
     /// @brief Retrieves single option by code and space.
     ///
     /// Allowed server selectors: ALL, ONE.
-    /// Not allowed server selector: ANY, UNASSIGNED, MULTIPLE.
+    /// Not allowed server selectors: ANY, UNASSIGNED, MULTIPLE.
     ///
     /// @param server_selector Server selector.
     /// @param code Option code.
@@ -496,7 +496,7 @@ public:
     ///
     /// @param server_selector Server selector.
     /// @param name Name of the shared network to be deleted.
-    /// @return Number of deleted shared networks..
+    /// @return Number of deleted shared networks.
     virtual uint64_t
     deleteSharedNetwork6(const db::ServerSelector& server_selector,
                          const std::string& name) = 0;
@@ -521,7 +521,8 @@ public:
     /// @param space Option space of the option to be deleted.
     /// @return Number of deleted option definitions.
     virtual uint64_t
-    deleteOptionDef6(const db::ServerSelector& server_selector, const uint16_t code,
+    deleteOptionDef6(const db::ServerSelector& server_selector,
+                     const uint16_t code,
                      const std::string& space) = 0;
 
     /// @brief Deletes all option definitions.
@@ -544,7 +545,8 @@ public:
     /// @param space Option space of the option to be deleted.
     /// @return Number of deleted options.
     virtual uint64_t
-    deleteOption6(const db::ServerSelector& server_selector, const uint16_t code,
+    deleteOption6(const db::ServerSelector& server_selector,
+                  const uint16_t code,
                   const std::string& space) = 0;
 
     /// @brief Deletes shared network level option.
@@ -572,8 +574,10 @@ public:
     /// @param space Option space of the deleted option.
     /// @return Number of deleted options.
     virtual uint64_t
-    deleteOption6(const db::ServerSelector& server_selector, const SubnetID& subnet_id,
-                  const uint16_t code, const std::string& space) = 0;
+    deleteOption6(const db::ServerSelector& server_selector,
+                  const SubnetID& subnet_id,
+                  const uint16_t code,
+                  const std::string& space) = 0;
 
     /// @brief Deletes pool level option.
     ///
index 85bcbd9bf39cc535ba8ecb753e34fa296822de3b..d78f97f8fd57b9c288efa17d291ccf8eb46d3f31 100644 (file)
@@ -89,22 +89,6 @@ public:
         return ("");
     }
 
-    /// @brief Copy server tags between two stamped elements.
-    ///
-    /// @param src Pointer to stamped element to copy tags from.
-    /// @param dst Pointer to stamped element to copy tags to.
-    void copyServerTags(const StampedElementPtr& src,
-                        const StampedElementPtr& dst) const {
-        auto tags = src->getServerTags();
-        for (auto tag : tags) {
-            // Until the stamped element tags are in a set (vs a vector)
-            // we have to avoid duplicates.
-            if (!dst->hasServerTag(tag)) {
-                dst->setServerTag(tag.get());
-            }
-        }
-    }
-
     /// @brief Merge server tags for a stamped element and a server selector.
     ///
     /// @param elem Stamped element to update.
@@ -113,11 +97,7 @@ public:
                          const db::ServerSelector& server_selector) const {
         auto tags = server_selector.getTags();
         for (auto tag : tags) {
-            // Until the stamped element tags are in a set (vs a vector)
-            // we have to avoid duplicates.
-            if (!elem->hasServerTag(tag)) {
-                elem->setServerTag(tag.get());
-            }
+            elem->setServerTag(tag.get());
         }
     }
 
index cf24885a5985649f31e5a86745273300e5cf4d8a..353bb07b9348bef0156dfbc26339279601dadfb3 100644 (file)
@@ -35,27 +35,69 @@ TestConfigBackendDHCPv4::unregisterBackendType(ConfigBackendDHCPv4Mgr& mgr,
 }
 
 Subnet4Ptr
-TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& server_selector,
                                     const std::string& subnet_prefix) const{
     const auto& index = subnets_.get<SubnetPrefixIndexTag>();
     auto subnet_it = index.find(subnet_prefix);
-    return ((subnet_it != index.cend()) ? (*subnet_it) : Subnet4Ptr());
+    if (subnet_it == index.cend()) {
+        return (Subnet4Ptr());
+    }
+    Subnet4Ptr subnet = *subnet_it;
+    if (server_selector.amAny()) {
+        return (subnet);
+    }
+    if (server_selector.amUnassigned()) {
+        return (subnet->getServerTags().empty() ? subnet : Subnet4Ptr());
+    }
+    auto tags = server_selector.getTags();
+    for (auto tag : tags) {
+        if (subnet->hasServerTag(ServerTag(tag))) {
+            return (subnet);
+        }
+    }
+    return (subnet->hasAllServerTag() ? subnet : Subnet4Ptr());
 }
 
 Subnet4Ptr
-TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& server_selector,
                                     const SubnetID& subnet_id) const {
     const auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet_id);
-    return ((subnet_it != index.cend()) ? (*subnet_it) : Subnet4Ptr());
+    if (subnet_it == index.cend()) {
+        return (Subnet4Ptr());
+    }
+    Subnet4Ptr subnet = *subnet_it;
+    if (server_selector.amAny()) {
+        return (subnet);
+    }
+    if (server_selector.amUnassigned()) {
+        return (subnet->getServerTags().empty() ? subnet : Subnet4Ptr());
+    }
+    auto tags = server_selector.getTags();
+    for (auto tag : tags) {
+        if (subnet->hasServerTag(ServerTag(tag))) {
+            return (subnet);
+        }
+    }
+    return (subnet->hasAllServerTag() ? subnet : Subnet4Ptr());
 }
 
 Subnet4Collection
 TestConfigBackendDHCPv4::getAllSubnets4(const db::ServerSelector& server_selector) const {
-    auto tags = server_selector.getTags();
     Subnet4Collection subnets;
     for (auto subnet : subnets_) {
+        if (server_selector.amAny()) {
+            subnets.push_back(subnet);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (subnet->getServerTags().empty()) {
+                subnets.push_back(subnet);
+            }
+            continue;
+        }
         bool got = false;
+        auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (subnet->hasServerTag(ServerTag(tag))) {
                 subnets.push_back(subnet);
@@ -74,13 +116,37 @@ TestConfigBackendDHCPv4::getAllSubnets4(const db::ServerSelector& server_selecto
 }
 
 Subnet4Collection
-TestConfigBackendDHCPv4::getModifiedSubnets4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::getModifiedSubnets4(const db::ServerSelector& server_selector,
                                              const boost::posix_time::ptime& modification_time) const {
     const auto& index = subnets_.get<SubnetModificationTimeIndexTag>();
     Subnet4Collection subnets;
     auto lb = index.lower_bound(modification_time);
     for (auto subnet = lb; subnet != index.end(); ++subnet) {
-        subnets.push_back(*subnet);
+        if (server_selector.amAny()) {
+            subnets.push_back(*subnet);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if ((*subnet)->getServerTags().empty()) {
+                subnets.push_back(*subnet);
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*subnet)->hasServerTag(ServerTag(tag))) {
+                subnets.push_back(*subnet);
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if ((*subnet)->hasAllServerTag()) {
+            subnets.push_back(*subnet);
+        }
     }
     return (subnets);
 }
@@ -111,19 +177,45 @@ TestConfigBackendDHCPv4::getSharedNetworkSubnets4(const db::ServerSelector& /* s
 }
 
 SharedNetwork4Ptr
-TestConfigBackendDHCPv4::getSharedNetwork4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::getSharedNetwork4(const db::ServerSelector& server_selector,
                                            const std::string& name) const {
     const auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(name);
-    return ((network_it != index.cend()) ? (*network_it) : SharedNetwork4Ptr());
+    if (network_it == index.cend()) {
+        return (SharedNetwork4Ptr());
+    }
+    SharedNetwork4Ptr network = *network_it;
+    if (server_selector.amAny()) {
+        return (network);
+    }
+    if (server_selector.amUnassigned()) {
+        return (network->getServerTags().empty() ? network : SharedNetwork4Ptr());
+    }
+    auto tags = server_selector.getTags();
+    for (auto tag : tags) {
+        if (network->hasServerTag(ServerTag(tag))) {
+            return (network);
+        }
+    }
+    return (network->hasAllServerTag() ? network : SharedNetwork4Ptr());
 }
 
 SharedNetwork4Collection
 TestConfigBackendDHCPv4::getAllSharedNetworks4(const db::ServerSelector& server_selector) const{
-    auto tags = server_selector.getTags();
     SharedNetwork4Collection shared_networks;
     for (auto shared_network : shared_networks_) {
+        if (server_selector.amAny()) {
+            shared_networks.push_back(shared_network);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (shared_network->getServerTags().empty()) {
+                shared_networks.push_back(shared_network);
+            }
+            continue;
+        }
         bool got = false;
+        auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (shared_network->hasServerTag(ServerTag(tag))) {
                 shared_networks.push_back(shared_network);
@@ -142,13 +234,37 @@ TestConfigBackendDHCPv4::getAllSharedNetworks4(const db::ServerSelector& server_
 }
 
 SharedNetwork4Collection
-TestConfigBackendDHCPv4::getModifiedSharedNetworks4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::getModifiedSharedNetworks4(const db::ServerSelector& server_selector,
                                                     const boost::posix_time::ptime& modification_time) const {
     const auto& index = shared_networks_.get<SharedNetworkModificationTimeIndexTag>();
     SharedNetwork4Collection shared_networks;
     auto lb = index.lower_bound(modification_time);
     for (auto shared_network = lb; shared_network != index.end(); ++shared_network) {
-        shared_networks.push_back(*shared_network);
+        if (server_selector.amAny()) {
+            shared_networks.push_back(*shared_network);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if ((*shared_network)->getServerTags().empty()) {
+                shared_networks.push_back(*shared_network);
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*shared_network)->hasServerTag(ServerTag(tag))) {
+                shared_networks.push_back(*shared_network);
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if ((*shared_network)->hasAllServerTag()) {
+            shared_networks.push_back(*shared_network);
+        }
     }
     return (shared_networks);
 }
@@ -399,13 +515,11 @@ TestConfigBackendDHCPv4::createUpdateSubnet4(const db::ServerSelector& server_se
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet->getID());
 
+    mergeServerTags(subnet, server_selector);
+
     if (subnet_it != index.cend()) {
-        copyServerTags(*subnet_it, subnet);
-        mergeServerTags(subnet, server_selector);
         index.replace(subnet_it, subnet);
-
     } else {
-        mergeServerTags(subnet, server_selector);
         index.insert(subnet);
     }
 }
@@ -416,13 +530,11 @@ TestConfigBackendDHCPv4::createUpdateSharedNetwork4(const db::ServerSelector& se
     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(shared_network->getName());
 
+    mergeServerTags(shared_network, server_selector);
+
     if (network_it != index.cend()) {
-        copyServerTags(*network_it, shared_network);
-        mergeServerTags(shared_network, server_selector);
         index.replace(network_it, shared_network);
-
     } else {
-        mergeServerTags(shared_network, server_selector);
         index.insert(shared_network);
     }
 }
@@ -638,24 +750,100 @@ TestConfigBackendDHCPv4::createUpdateServer4(const db::ServerPtr& server) {
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& server_selector,
                                        const std::string& subnet_prefix) {
     auto& index = subnets_.get<SubnetPrefixIndexTag>();
+    auto subnet_it = index.find(subnet_prefix);
+    if (subnet_it == index.end()) {
+        return (0);
+    }
+    if ((server_selector.amUnassigned()) &&
+        !(*subnet_it)->getServerTags().empty()) {
+        return (0);
+    }
+    if (!server_selector.amAny()) {
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*subnet_it)->hasServerTag(ServerTag(tag))) {
+                got = true;
+                break;
+            }
+        }
+        if (!got && !(*subnet_it)->hasAllServerTag()) {
+            return (0);
+        }
+    }
     return (index.erase(subnet_prefix));
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& server_selector,
                                        const SubnetID& subnet_id) {
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
+    auto subnet_it = index.find(subnet_id);
+    if (subnet_it == index.end()) {
+        return (0);
+    }
+    if ((server_selector.amUnassigned()) &&
+        !(*subnet_it)->getServerTags().empty()) {
+        return (0);
+    }
+    if (!server_selector.amAny()) {
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*subnet_it)->hasServerTag(ServerTag(tag))) {
+                got = true;
+                break;
+            }
+        }
+        if (!got && !(*subnet_it)->hasAllServerTag()) {
+            return (0);
+        }
+    }
     return (index.erase(subnet_id));
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteAllSubnets4(const db::ServerSelector& /* server_selector */) {
-    auto subnets_size = subnets_.size();
-    subnets_.clear();
-    return (subnets_size);
+TestConfigBackendDHCPv4::deleteAllSubnets4(const db::ServerSelector& server_selector) {
+    // Collect subnet to remove by ID.
+    std::list<SubnetID> ids;
+    for (auto subnet : subnets_) {
+        if (server_selector.amAny()) {
+            ids.push_back(subnet->getID());
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (subnet->getServerTags().empty()) {
+                ids.push_back(subnet->getID());
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (subnet->hasServerTag(ServerTag(tag))) {
+                ids.push_back(subnet->getID());
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if (subnet->hasAllServerTag()) {
+            ids.push_back(subnet->getID());
+        }
+    }
+
+    // Erase subnets.
+    uint64_t erased = 0;
+    auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
+    for (auto subnet_id : ids) {
+        erased += index.erase(subnet_id);
+    }
+    return (erased);
 }
 
 uint64_t
@@ -682,27 +870,80 @@ TestConfigBackendDHCPv4::deleteSharedNetworkSubnets4(const db::ServerSelector& /
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteSharedNetwork4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::deleteSharedNetwork4(const db::ServerSelector& server_selector,
                                               const std::string& name) {
+    auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
+    auto network_it = index.find(name);
+    if (network_it == index.end()) {
+        return (0);
+    }
+    if ((server_selector.amUnassigned()) &&
+        !(*network_it)->getServerTags().empty()) {
+        return (0);
+    }
+    if (!server_selector.amAny()) {
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*network_it)->hasServerTag(ServerTag(tag))) {
+                got = true;
+                break;
+            }
+        }
+        if (!got && !(*network_it)->hasAllServerTag()) {
+            return (0);
+        }
+    }
+
+    // Remove this shared network.
     for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ++subnet) {
         if ((*subnet)->getSharedNetworkName() == name) {
             (*subnet)->setSharedNetworkName("");
         }
     }
-
-    auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
-    auto network_it = index.find(name);
-    if (network_it != index.end()) {
-        (*network_it)->delAll();
-    }
+    (*network_it)->delAll();
     return (index.erase(name));
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteAllSharedNetworks4(const db::ServerSelector& /* server_selector */) {
-    auto shared_networks_size = shared_networks_.size();
-    shared_networks_.clear();
-    return (shared_networks_size);
+TestConfigBackendDHCPv4::deleteAllSharedNetworks4(const db::ServerSelector& server_selector) {
+    // Collect shared network to remove.
+    std::list<std::string> names;
+    for (auto shared_network : shared_networks_) {
+        if (server_selector.amAny()) {
+            names.push_back(shared_network->getName());
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (shared_network->getServerTags().empty()) {
+                names.push_back(shared_network->getName());
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (shared_network->hasServerTag(ServerTag(tag))) {
+                names.push_back(shared_network->getName());
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if (shared_network->hasAllServerTag()) {
+            names.push_back(shared_network->getName());
+        }
+    }
+
+    // Erase shared networks.
+    uint64_t erased = 0;
+    auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
+    for (auto name : names) {
+        erased += index.erase(name);
+    }
+    return (erased);
 }
 
 uint64_t
index 7acf85d683e2c59c61405114deaba9e9453f3223..e6209ee8e88b316382ba16d0519d6a20d6f3adec 100644 (file)
@@ -34,27 +34,69 @@ TestConfigBackendDHCPv6::unregisterBackendType(ConfigBackendDHCPv6Mgr& mgr,
 }
 
 Subnet6Ptr
-TestConfigBackendDHCPv6::getSubnet6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::getSubnet6(const db::ServerSelector& server_selector,
                                     const std::string& subnet_prefix) const{
     const auto& index = subnets_.get<SubnetPrefixIndexTag>();
     auto subnet_it = index.find(subnet_prefix);
-    return ((subnet_it != index.cend()) ? (*subnet_it) : Subnet6Ptr());
+    if (subnet_it == index.cend()) {
+        return (Subnet6Ptr());
+    }
+    Subnet6Ptr subnet = *subnet_it;
+    if (server_selector.amAny()) {
+        return (subnet);
+    }
+    if (server_selector.amUnassigned()) {
+        return (subnet->getServerTags().empty() ? subnet : Subnet6Ptr());
+    }
+    auto tags = server_selector.getTags();
+    for (auto tag : tags) {
+        if (subnet->hasServerTag(ServerTag(tag))) {
+            return (subnet);
+        }
+    }
+    return (subnet->hasAllServerTag() ? subnet : Subnet6Ptr());
 }
 
 Subnet6Ptr
-TestConfigBackendDHCPv6::getSubnet6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::getSubnet6(const db::ServerSelector& server_selector,
                                     const SubnetID& subnet_id) const {
     const auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet_id);
-    return ((subnet_it != index.cend()) ? (*subnet_it) : Subnet6Ptr());
+    if (subnet_it == index.cend()) {
+        return (Subnet6Ptr());
+    }
+    Subnet6Ptr subnet = *subnet_it;
+    if (server_selector.amAny()) {
+        return (subnet);
+    }
+    if (server_selector.amUnassigned()) {
+        return (subnet->getServerTags().empty() ? subnet : Subnet6Ptr());
+    }
+    auto tags = server_selector.getTags();
+    for (auto tag : tags) {
+        if (subnet->hasServerTag(ServerTag(tag))) {
+            return (subnet);
+        }
+    }
+    return (subnet->hasAllServerTag() ? subnet : Subnet6Ptr());
 }
 
 Subnet6Collection
 TestConfigBackendDHCPv6::getAllSubnets6(const db::ServerSelector& server_selector) const {
-    auto tags = server_selector.getTags();
     Subnet6Collection subnets;
     for (auto subnet : subnets_) {
+        if (server_selector.amAny()) {
+            subnets.push_back(subnet);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (subnet->getServerTags().empty()) {
+                subnets.push_back(subnet);
+            }
+            continue;
+        }
         bool got = false;
+        auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (subnet->hasServerTag(ServerTag(tag))) {
                 subnets.push_back(subnet);
@@ -73,13 +115,37 @@ TestConfigBackendDHCPv6::getAllSubnets6(const db::ServerSelector& server_selecto
 }
 
 Subnet6Collection
-TestConfigBackendDHCPv6::getModifiedSubnets6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::getModifiedSubnets6(const db::ServerSelector& server_selector,
                                              const boost::posix_time::ptime& modification_time) const {
     const auto& index = subnets_.get<SubnetModificationTimeIndexTag>();
     Subnet6Collection subnets;
     auto lb = index.lower_bound(modification_time);
     for (auto subnet = lb; subnet != index.end(); ++subnet) {
-        subnets.push_back(*subnet);
+        if (server_selector.amAny()) {
+            subnets.push_back(*subnet);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if ((*subnet)->getServerTags().empty()) {
+                subnets.push_back(*subnet);
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*subnet)->hasServerTag(ServerTag(tag))) {
+                subnets.push_back(*subnet);
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if ((*subnet)->hasAllServerTag()) {
+            subnets.push_back(*subnet);
+        }
     }
     return (subnets);
 }
@@ -110,19 +176,45 @@ TestConfigBackendDHCPv6::getSharedNetworkSubnets6(const db::ServerSelector& /* s
 }
 
 SharedNetwork6Ptr
-TestConfigBackendDHCPv6::getSharedNetwork6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::getSharedNetwork6(const db::ServerSelector& server_selector,
                                            const std::string& name) const {
     const auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(name);
-    return ((network_it != index.cend()) ? (*network_it) : SharedNetwork6Ptr());
+    if (network_it == index.cend()) {
+        return (SharedNetwork6Ptr());
+    }
+    SharedNetwork6Ptr network = *network_it;
+    if (server_selector.amAny()) {
+        return (network);
+    }
+    if (server_selector.amUnassigned()) {
+        return (network->getServerTags().empty() ? network : SharedNetwork6Ptr());
+    }
+    auto tags = server_selector.getTags();
+    for (auto tag : tags) {
+        if (network->hasServerTag(ServerTag(tag))) {
+            return (network);
+        }
+    }
+    return (network->hasAllServerTag() ? network : SharedNetwork6Ptr());
 }
 
 SharedNetwork6Collection
 TestConfigBackendDHCPv6::getAllSharedNetworks6(const db::ServerSelector& server_selector) const{
-    auto tags = server_selector.getTags();
     SharedNetwork6Collection shared_networks;
     for (auto shared_network : shared_networks_) {
+        if (server_selector.amAny()) {
+            shared_networks.push_back(shared_network);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (shared_network->getServerTags().empty()) {
+                shared_networks.push_back(shared_network);
+            }
+            continue;
+        }
         bool got = false;
+        auto tags = server_selector.getTags();
         for (auto tag : tags) {
             if (shared_network->hasServerTag(ServerTag(tag))) {
                 shared_networks.push_back(shared_network);
@@ -141,13 +233,37 @@ TestConfigBackendDHCPv6::getAllSharedNetworks6(const db::ServerSelector& server_
 }
 
 SharedNetwork6Collection
-TestConfigBackendDHCPv6::getModifiedSharedNetworks6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::getModifiedSharedNetworks6(const db::ServerSelector& server_selector,
                                                     const boost::posix_time::ptime& modification_time) const {
     const auto& index = shared_networks_.get<SharedNetworkModificationTimeIndexTag>();
     SharedNetwork6Collection shared_networks;
     auto lb = index.lower_bound(modification_time);
     for (auto shared_network = lb; shared_network != index.end(); ++shared_network) {
-        shared_networks.push_back(*shared_network);
+        if (server_selector.amAny()) {
+            shared_networks.push_back(*shared_network);
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if ((*shared_network)->getServerTags().empty()) {
+                shared_networks.push_back(*shared_network);
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*shared_network)->hasServerTag(ServerTag(tag))) {
+                shared_networks.push_back(*shared_network);
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if ((*shared_network)->hasAllServerTag()) {
+            shared_networks.push_back(*shared_network);
+        }
     }
     return (shared_networks);
 }
@@ -398,13 +514,11 @@ TestConfigBackendDHCPv6::createUpdateSubnet6(const db::ServerSelector& server_se
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet->getID());
 
+    mergeServerTags(subnet, server_selector);
+
     if (subnet_it != index.cend()) {
-        copyServerTags(*subnet_it, subnet);
-        mergeServerTags(subnet, server_selector);
         index.replace(subnet_it, subnet);
-
     } else {
-        mergeServerTags(subnet, server_selector);
         index.insert(subnet);
     }
 }
@@ -415,13 +529,11 @@ TestConfigBackendDHCPv6::createUpdateSharedNetwork6(const db::ServerSelector& se
     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(shared_network->getName());
 
+    mergeServerTags(shared_network, server_selector);
+
     if (network_it != index.cend()) {
-        copyServerTags(*network_it, shared_network);
-        mergeServerTags(shared_network, server_selector);
         index.replace(network_it, shared_network);
-
     } else {
-        mergeServerTags(shared_network, server_selector);
         index.insert(shared_network);
     }
 }
@@ -686,24 +798,100 @@ TestConfigBackendDHCPv6::createUpdateServer6(const db::ServerPtr& server) {
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteSubnet6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteSubnet6(const db::ServerSelector& server_selector,
                                        const std::string& subnet_prefix) {
     auto& index = subnets_.get<SubnetPrefixIndexTag>();
+    auto subnet_it = index.find(subnet_prefix);
+    if (subnet_it == index.end()) {
+        return (0);
+    }
+    if ((server_selector.amUnassigned()) &&
+        !(*subnet_it)->getServerTags().empty()) {
+        return (0);
+    }
+    if (!server_selector.amAny()) {
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*subnet_it)->hasServerTag(ServerTag(tag))) {
+                got = true;
+                break;
+            }
+        }
+        if (!got && !(*subnet_it)->hasAllServerTag()) {
+            return (0);
+        }
+    }
     return (index.erase(subnet_prefix));
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteSubnet6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteSubnet6(const db::ServerSelector& server_selector,
                                        const SubnetID& subnet_id) {
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
+    auto subnet_it = index.find(subnet_id);
+    if (subnet_it == index.end()) {
+        return (0);
+    }
+    if ((server_selector.amUnassigned()) &&
+        !(*subnet_it)->getServerTags().empty()) {
+        return (0);
+    }
+    if (!server_selector.amAny()) {
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*subnet_it)->hasServerTag(ServerTag(tag))) {
+                got = true;
+                break;
+            }
+        }
+        if (!got && !(*subnet_it)->hasAllServerTag()) {
+            return (0);
+        }
+    }
     return (index.erase(subnet_id));
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteAllSubnets6(const db::ServerSelector& /* server_selector */) {
-    auto subnets_size = subnets_.size();
-    subnets_.clear();
-    return (subnets_size);
+TestConfigBackendDHCPv6::deleteAllSubnets6(const db::ServerSelector& server_selector) {
+    // Collect subnet to remove by ID.
+    std::list<SubnetID> ids;
+    for (auto subnet : subnets_) {
+        if (server_selector.amAny()) {
+            ids.push_back(subnet->getID());
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (subnet->getServerTags().empty()) {
+                ids.push_back(subnet->getID());
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (subnet->hasServerTag(ServerTag(tag))) {
+                ids.push_back(subnet->getID());
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if (subnet->hasAllServerTag()) {
+            ids.push_back(subnet->getID());
+        }
+    }
+
+    // Erase subnets.
+    uint64_t erased = 0;
+    auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
+    for (auto subnet_id : ids) {
+        erased += index.erase(subnet_id);
+    }
+    return (erased);
 }
 
 uint64_t
@@ -730,27 +918,80 @@ TestConfigBackendDHCPv6::deleteSharedNetworkSubnets6(const db::ServerSelector& /
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteSharedNetwork6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::deleteSharedNetwork6(const db::ServerSelector& server_selector,
                                               const std::string& name) {
+    auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
+    auto network_it = index.find(name);
+    if (network_it == index.end()) {
+        return (0);
+    }
+    if ((server_selector.amUnassigned()) &&
+        !(*network_it)->getServerTags().empty()) {
+        return (0);
+    }
+    if (!server_selector.amAny()) {
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if ((*network_it)->hasServerTag(ServerTag(tag))) {
+                got = true;
+                break;
+            }
+        }
+        if (!got && !(*network_it)->hasAllServerTag()) {
+            return (0);
+        }
+    }
+
+    // Remove this shared network.
     for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ++subnet) {
         if ((*subnet)->getSharedNetworkName() == name) {
             (*subnet)->setSharedNetworkName("");
         }
     }
-
-    auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
-    auto network_it = index.find(name);
-    if (network_it != index.end()) {
-        (*network_it)->delAll();
-    }
+    (*network_it)->delAll();
     return (index.erase(name));
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteAllSharedNetworks6(const db::ServerSelector& /* server_selector */) {
-    auto shared_networks_size = shared_networks_.size();
-    shared_networks_.clear();
-    return (shared_networks_size);
+TestConfigBackendDHCPv6::deleteAllSharedNetworks6(const db::ServerSelector& server_selector) {
+    // Collect shared network to remove.
+    std::list<std::string> names;
+    for (auto shared_network : shared_networks_) {
+        if (server_selector.amAny()) {
+            names.push_back(shared_network->getName());
+            continue;
+        }
+        if (server_selector.amUnassigned()) {
+            if (shared_network->getServerTags().empty()) {
+                names.push_back(shared_network->getName());
+            }
+            continue;
+        }
+        bool got = false;
+        auto tags = server_selector.getTags();
+        for (auto tag : tags) {
+            if (shared_network->hasServerTag(ServerTag(tag))) {
+                names.push_back(shared_network->getName());
+                got = true;
+                break;
+            }
+        }
+        if (got) {
+            continue;
+        }
+        if (shared_network->hasAllServerTag()) {
+            names.push_back(shared_network->getName());
+        }
+    }
+
+    // Erase shared networks.
+    uint64_t erased = 0;
+    auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
+    for (auto name : names) {
+        erased += index.erase(name);
+    }
+    return (erased);
 }
 
 uint64_t
@@ -924,7 +1165,6 @@ TestConfigBackendDHCPv6::deleteAllServers6() {
     return (servers_size);
 }
 
-
 } // namespace test
 } // namespace dhcp
 } // namespace isc