]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#642,!373] Server tags supported for global params in MySQL CB.
authorMarcin Siodelski <marcin@isc.org>
Mon, 17 Jun 2019 12:09:13 +0000 (14:09 +0200)
committerMarcin Siodelski <marcin@isc.org>
Thu, 27 Jun 2019 18:51:31 +0000 (14:51 -0400)
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc
src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc

index 58a31c34da45e8e471b52cd9eebf9c3228df7bc5..61a4f7116b79b4f0ae3cfa3e0507f3d1358b799a 100644 (file)
@@ -2658,7 +2658,7 @@ MySqlConfigBackendDHCPv4::createUpdateGlobalParameter4(const ServerSelector& ser
 void
 MySqlConfigBackendDHCPv4::createUpdateServer4(const ServerPtr& server) {
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SERVER4)
-        .arg(server->getServerTag());
+        .arg(server->getServerTagAsText());
     impl_->createUpdateServer(MySqlConfigBackendDHCPv4Impl::CREATE_AUDIT_REVISION,
                               MySqlConfigBackendDHCPv4Impl::INSERT_SERVER4,
                               MySqlConfigBackendDHCPv4Impl::UPDATE_SERVER4,
index 089e0f42f4ef49a2bedeb75aba295316d665d8c7..121531992e56363bf6f2239524ad576bca831122 100644 (file)
@@ -3030,7 +3030,7 @@ MySqlConfigBackendDHCPv6::createUpdateGlobalParameter6(const ServerSelector& ser
 void
 MySqlConfigBackendDHCPv6::createUpdateServer6(const ServerPtr& server) {
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SERVER6)
-        .arg(server->getServerTag());
+        .arg(server->getServerTagAsText());
     impl_->createUpdateServer(MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
                               MySqlConfigBackendDHCPv6Impl::INSERT_SERVER6,
                               MySqlConfigBackendDHCPv6Impl::UPDATE_SERVER6,
index 2d86f301f93b7e57de8a2d16947e0d9d5d7c1e6f..e5a9787f76204db0c2f4a20c17654dd503658907 100644 (file)
@@ -250,81 +250,68 @@ MySqlConfigBackendImpl::getGlobalParameters(const int index,
         MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
     };
 
-    // This remembers id of the last entry processed.
-    uint64_t last_id = 0;
+    StampedValuePtr last_param;
+
+    StampedValueCollection local_parameters;
 
     conn_.selectQuery(index, in_bindings, out_bindings,
-                      [&last_id, &parameters] (MySqlBindingCollection& out_bindings) {
+                      [&last_param, &local_parameters]
+                      (MySqlBindingCollection& out_bindings) {
 
-        // Store id of the current entry.
         uint64_t id = out_bindings[0]->getInteger<uint64_t>();
 
         // If we're starting or if this is new parameter being processed...
-        if ((last_id == 0) || (last_id != id)) {
+        if (!last_param || (last_param->getId() != id)) {
 
             // parameter name
             std::string name = out_bindings[1]->getString();
 
             if (!name.empty()) {
-
-                // Remember last processed entry.
-                last_id = id;
-
-                // The server may use one of the two values present in the
-                // database, i.e. the value specified for the particular
-                // server tag or the value specified for all servers. The
-                // former takes precedence. Therefore, we check here if the
-                // value already present in the parameters collection is
-                // specified for all servers or selected server.
-                auto& index = parameters.get<StampedValueNameIndexTag>();
+                last_param = StampedValue::create(out_bindings[1]->getString(),
+                                                  out_bindings[2]->getString(),
+                                                  static_cast<Element::types>
+                                                  (out_bindings[3]->getInteger<uint8_t>()));
+
+                // id
+                last_param->setId(id);
+
+                // modification_ts
+                last_param->setModificationTime(out_bindings[4]->getTimestamp());
+
+                // server_tag
+                ServerTag last_param_server_tag(out_bindings[5]->getString());
+                last_param->setServerTag(last_param_server_tag.get());
+                // If we're fetching parameters for a given server (explicit server
+                // tag is provided), it takes precedence over the same parameter
+                // specified for all servers. Therefore, we check if the given
+                // parameter already exists and belongs to 'all'.
+                auto& index = local_parameters.get<StampedValueNameIndexTag>();
                 auto existing = index.find(name);
-                if (existing != index.end()) {
-                    // The value of this parameter has been already seen.
-                    // Let's check if the value we stored is for all
-                    // servers or one server.
-                    try {
-                        ServerTag existing_tag((*existing)->getServerTag());
-                        ServerTag new_tag(out_bindings[5]->getString());
-                        if (!existing_tag.amAll() && new_tag.amAll()) {
-                            // The stored value is for one server and the
-                            // currently fetched value is for all servers,
-                            // so let's drop the currently processed value.
-                            return;
-                        }
-
-                    } catch (...) {
-                        // This shouldn't occur because the value comes
-                        // from the database and should have been validated.
+                if (existing != local_parameters.end()) {
+                    // This parameter was already fetched. Let's check if we should
+                    // replace it or not.
+                    if (!last_param_server_tag.amAll() && (*existing)->hasAllServerTag()) {
+                        // Replace parameter specified for 'all' with the one associated
+                        // with the particular server tag.
+                        local_parameters.replace(existing, last_param);
                         return;
                     }
+
                 }
 
-                // Convert value read as string from the database to the actual
-                // data type known from the database as binding #3.
-                StampedValuePtr stamped_value =
-                    StampedValue::create(out_bindings[1]->getString(),
-                                         out_bindings[2]->getString(),
-                                         static_cast<Element::types>
-                                         (out_bindings[3]->getInteger<uint8_t>()));
-
-                stamped_value->setId(id);
-                stamped_value->setModificationTime(out_bindings[4]->getTimestamp());
-                stamped_value->setServerTag(out_bindings[5]->getString());
-
-                // If the parameter is already stored, it means that the
-                // stored value is for all servers and the one we're fetching
-                // is for a server tag. Let's replace the value.
-                if (existing != index.end()) {
-                    parameters.replace(existing, stamped_value);
-
-                } else {
-                    // The parameter doesn't exist, so insert it whether
-                    // it is for all or one server.
-                    parameters.insert(stamped_value);
+                // If there is no such parameter yet or the existing parameter
+                // belongs to a different server and the inserted parameter is
+                // not for all servers.
+                if ((existing == local_parameters.end()) ||
+                    (!(*existing)->hasServerTag(last_param_server_tag) &&
+                     !last_param_server_tag.amAll())) {
+                    local_parameters.insert(last_param);
                 }
             }
         }
     });
+
+    parameters.insert(local_parameters.begin(), local_parameters.end());
 }
 
 OptionDefinitionPtr
@@ -958,7 +945,7 @@ MySqlConfigBackendImpl::createUpdateServer(const int create_audit_revision_index
     MySqlTransaction transaction(conn_);
 
     MySqlBindingCollection in_bindings = {
-        MySqlBinding::createString(server->getServerTag()),
+        MySqlBinding::createString(server->getServerTagAsText()),
         MySqlBinding::createString(server->getDescription()),
         MySqlBinding::createTimestamp(server->getModificationTime())
     };
@@ -967,7 +954,7 @@ MySqlConfigBackendImpl::createUpdateServer(const int create_audit_revision_index
         conn_.insertQuery(create_index, in_bindings);
 
     } catch (const DuplicateEntry&) {
-        in_bindings.push_back(MySqlBinding::createString(server->getServerTag()));
+        in_bindings.push_back(MySqlBinding::createString(server->getServerTagAsText()));
         conn_.updateDeleteQuery(update_index, in_bindings);
     }
 
index b6f9e86ee78a991e0b48c9c452a17ecb556bcf47..4f0180d52135782be7309c1fe525489508ccfadc 100644 (file)
@@ -42,9 +42,9 @@ namespace {
     "INNER JOIN " #table_prefix "_global_parameter_server AS a " \
     "  ON g.id = a.parameter_id " \
     "INNER JOIN " #table_prefix "_server AS s " \
-    "  ON (a.server_id = s.id) OR (a.server_id = 1) " \
+    "  ON (a.server_id = s.id) " \
     "WHERE (s.tag = ? OR s.id = 1) " #__VA_ARGS__ \
-    " ORDER BY g.id"
+    " ORDER BY g.id, s.id"
 
 #endif
 
index fda518dfee80367be060ebfb80c752a8146b4886..2c5d95df3e42d9afec9a93995506ab25568b92dc 100644 (file)
@@ -478,7 +478,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteServer) {
     // Try to fetch the server which we expect to exist.
     EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
     ASSERT_TRUE(returned_server);
-    EXPECT_EQ("server1", returned_server->getServerTag());
+    EXPECT_EQ("server1", returned_server->getServerTag().get());
     EXPECT_EQ("this is server 1", returned_server->getDescription());
     EXPECT_EQ(timestamps_["yesterday"], returned_server->getModificationTime());
 
@@ -495,7 +495,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteServer) {
     // Verify that the server has been updated. 
     EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
     ASSERT_TRUE(returned_server);
-    EXPECT_EQ("server1", returned_server->getServerTag());
+    EXPECT_EQ("server1", returned_server->getServerTag().get());
     EXPECT_EQ("this is server 1 bis", returned_server->getDescription());
     EXPECT_EQ(timestamps_["today"], returned_server->getModificationTime());
 
@@ -586,7 +586,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteGlobalParameter4) {
     EXPECT_EQ("whale", returned_global_parameter->getValue());
     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
                 global_parameter->getModificationTime());
-    EXPECT_EQ("all", returned_global_parameter->getServerTag());
+    ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
+    EXPECT_EQ("all", returned_global_parameter->getServerTags()[0].get());
 
     // Because we have added the global parameter for all servers, it
     // should be also returned for the explicitly specified server.
@@ -597,7 +598,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteGlobalParameter4) {
     EXPECT_EQ("whale", returned_global_parameter->getValue());
     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
                 global_parameter->getModificationTime());
-    EXPECT_EQ("all", returned_global_parameter->getServerTag());
+    ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
+    EXPECT_EQ("all", returned_global_parameter->getServerTags()[0].get());
 
     // Check that the parameter is udpated when selector is specified correctly.
     global_parameter = StampedValue::create("global", "fish");
@@ -610,7 +612,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteGlobalParameter4) {
     EXPECT_EQ("fish", returned_global_parameter->getValue());
     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
                 global_parameter->getModificationTime());
-    EXPECT_EQ("all", returned_global_parameter->getServerTag());
+    ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
+    EXPECT_EQ("all", returned_global_parameter->getServerTags()[0].get());
 
     {
         SCOPED_TRACE("UPDATE audit entry for the global parameter");
@@ -678,7 +681,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, globalParameters4WithServerTags) {
     );
     ASSERT_TRUE(returned_global);
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 
     // Try to fetch the value specified for the server1. This should override the
     // value specified for all servers.
@@ -688,7 +692,9 @@ TEST_F(MySqlConfigBackendDHCPv4Test, globalParameters4WithServerTags) {
     );
     ASSERT_TRUE(returned_global);
     EXPECT_EQ(global_parameter1->getValue(), returned_global->getValue());
-    EXPECT_EQ("server1", returned_global->getServerTag());
+
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("server1", returned_global->getServerTags()[0].get());
 
     // The same in case of the server2.
     EXPECT_NO_THROW(
@@ -697,19 +703,33 @@ TEST_F(MySqlConfigBackendDHCPv4Test, globalParameters4WithServerTags) {
     );
     ASSERT_TRUE(returned_global);
     EXPECT_EQ(global_parameter2->getValue(), returned_global->getValue());
-    EXPECT_EQ("server2", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("server2", returned_global->getServerTags()[0].get());
 
     StampedValueCollection returned_globals;
 
-    // Try to fetch the collection of globals for the server2. It should contain
-    // server specific values.
+    // Try to fetch the collection of globals for the server1, server2 and server3.
+    // The server3 does not have an explicit value so for this server we should get
+    /// the value for 'all'.
     EXPECT_NO_THROW(
-        returned_globals = cbptr_->getAllGlobalParameters4(ServerSelector::ONE("server2"))
+        returned_globals = cbptr_->getAllGlobalParameters4(ServerSelector::
+                                                           MULTIPLE({ "server1", "server2",
+                                                                      "server3" }));
     );
-    ASSERT_EQ(1, returned_globals.size());
-    returned_global = *returned_globals.begin();
-    EXPECT_EQ(global_parameter2->getValue(), returned_global->getValue());
-    EXPECT_EQ("server2", returned_global->getServerTag());
+    ASSERT_EQ(3, returned_globals.size());
+
+    // Capture the returned values into the map so as we can check the
+    // values against the servers.
+    std::map<std::string, std::string> values;
+    for (auto g = returned_globals.begin(); g != returned_globals.end(); ++g) {
+        ASSERT_EQ(1, (*g)->getServerTags().size());
+        values[(*g)->getServerTags()[0].get()] = ((*g)->getValue());
+    }
+
+    ASSERT_EQ(3, values.size());
+    EXPECT_EQ(global_parameter1->getValue(), values["server1"]);
+    EXPECT_EQ(global_parameter2->getValue(), values["server2"]);
+    EXPECT_EQ(global_parameter3->getValue(), values["all"]);
 
     // Try to fetch the collection of global parameters specified for all servers.
     // This excludes the values specific to server1 and server2. It returns only the
@@ -720,7 +740,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, globalParameters4WithServerTags) {
     ASSERT_EQ(1, returned_globals.size());
     returned_global = *returned_globals.begin();
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 
     // Delete the server1. It should remove associations of this server with the
     // global parameters.
@@ -734,7 +755,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, globalParameters4WithServerTags) {
     // all servers, rather than the one dedicated for server1. The association of
     // the server1 specific value with the server1 should be gone.
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 
     // Attempt to delete global parameter for server1.
     uint64_t deleted_num = 0;
@@ -760,7 +782,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, globalParameters4WithServerTags) {
     // The common value for all servers should still be available because 'all'
     // logical server should not be deleted.
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 }
 
 // This test verifies that all global parameters can be retrieved and deleted.
@@ -792,7 +815,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllGlobalParameters4) {
 
     for (auto param = parameters_index.begin(); param != parameters_index.end();
          ++param) {
-        EXPECT_EQ("all", (*param)->getServerTag());
+        ASSERT_EQ(1, (*param)->getServerTags().size());
+        EXPECT_EQ("all", (*param)->getServerTags()[0].get());
     }
 
     // Should be able to fetch these parameters when explicitly providing
@@ -861,7 +885,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4) {
     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
                                                     test_subnets_[0]->getID());
     ASSERT_TRUE(returned_subnet);
-    EXPECT_EQ("all", returned_subnet->getServerTag());
+    ASSERT_EQ(1, returned_subnet->getServerTags().size());
+    EXPECT_EQ("all", returned_subnet->getServerTags()[0].get());
 
     // The easiest way to verify whether the returned subnet matches the inserted
     // subnet is to convert both to text.
@@ -996,7 +1021,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4WithOptionalUnspecified) {
     EXPECT_EQ(128, returned_subnet->get4o6().getSubnet4o6().get().second);
 
     // The easiest way to verify whether the returned subnet matches the inserted
-    // subnet is to convert both to text.
+   // subnet is to convert both to text.
     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 }
 
@@ -1040,7 +1065,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4ByPrefix) {
     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
                                                     "192.0.2.0/24");
     ASSERT_TRUE(returned_subnet);
-    EXPECT_EQ("all", returned_subnet->getServerTag());
+    ASSERT_EQ(1, returned_subnet->getServerTags().size());
+    EXPECT_EQ("all", returned_subnet->getServerTags()[0].get());
 
     // Verify subnet contents.
     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
@@ -1085,7 +1111,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4) {
 
     // See if the subnets are returned ok.
     for (auto i = 0; i < subnets.size(); ++i) {
-        EXPECT_EQ("all", subnets[i]->getServerTag());
+        ASSERT_EQ(1, subnets[i]->getServerTags().size());
+        EXPECT_EQ("all", subnets[i]->getServerTags()[0].get());
         EXPECT_EQ(test_subnets_[i + 1]->toElement()->str(),
                   subnets[i]->toElement()->str());
     }
@@ -1252,7 +1279,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetworkSubnets4) {
                              subnets[0]->toElement()));
 
     // Check server tag
-    EXPECT_EQ("all", subnets[0]->getServerTag());
+    ASSERT_EQ(1, subnets[0]->getServerTags().size());
+    EXPECT_EQ("all", subnets[0]->getServerTags()[0].get());
 
     // Fetch all subnets belonging to shared network level2.
     subnets = cbptr_->getSharedNetworkSubnets4(ServerSelector::ALL(), "level2");
@@ -1293,7 +1321,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4) {
     ASSERT_TRUE(returned_network);
 
     EXPECT_GT(returned_network->getId(), 0);
-    EXPECT_EQ("all", returned_network->getServerTag());
+    ASSERT_EQ(1, returned_network->getServerTags().size());
+    EXPECT_EQ("all", returned_network->getServerTags()[0].get());
 
     // The easiest way to verify whether the returned shared network matches the
     // inserted shared network is to convert both to text.
@@ -1590,7 +1619,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getOptionDef4) {
                               test_option_defs_[0]->getOptionSpaceName());
     ASSERT_TRUE(returned_option_def);
     EXPECT_GT(returned_option_def->getId(), 0);
-    EXPECT_EQ("all", returned_option_def->getServerTag());
+    ASSERT_EQ(1, returned_option_def->getServerTags().size());
+    EXPECT_EQ("all", returned_option_def->getServerTags()[0].get());
 
     EXPECT_TRUE(returned_option_def->equals(*option_def));
 
@@ -1663,7 +1693,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptionDefs4) {
 
     // See if option definitions are returned ok.
     for (auto def = option_defs.begin(); def != option_defs.end(); ++def) {
-        EXPECT_EQ("all", (*def)->getServerTag());
+        ASSERT_EQ(1, (*def)->getServerTags().size());
+        EXPECT_EQ("all", (*def)->getServerTags()[0].get());
         bool success = false;
         for (auto i = 1; i < test_option_defs_.size(); ++i) {
             if ((*def)->equals(*test_option_defs_[i])) {
@@ -1858,7 +1889,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
         ASSERT_FALSE(option0 == index.end());
         testOptionsEquivalent(*test_options_[0], *option0);
         EXPECT_GT(option0->getId(), 0);
-        EXPECT_EQ("all", option0->getServerTag());
+        ASSERT_EQ(1, option0->getServerTags().size());
+        EXPECT_EQ("all", option0->getServerTags()[0].get());
     }
 
     {
@@ -1867,7 +1899,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
         ASSERT_FALSE(option1 == index.end());
         testOptionsEquivalent(*test_options_[1], *option1);
         EXPECT_GT(option1->getId(), 0);
-        EXPECT_EQ("all", option1->getServerTag());
+        ASSERT_EQ(1, option1->getServerTags().size());
+        EXPECT_EQ("all", option1->getServerTags()[0].get());
     }
 
     {
@@ -1876,7 +1909,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
         ASSERT_FALSE(option5 == index.end());
         testOptionsEquivalent(*test_options_[5], *option5);
         EXPECT_GT(option5->getId(), 0);
-        EXPECT_EQ("all", option5->getServerTag());
+        ASSERT_EQ(1, option5->getServerTags().size());
+        EXPECT_EQ("all", option5->getServerTags()[0].get());
     }
 }
 
index 30e6331f827a79bfbbc510e7ee2693c6ec5ff63f..15c7d9ce0e95b8c9dee83d63701acb64deaf4dcb 100644 (file)
@@ -519,7 +519,7 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateDeleteServer) {
     // Try to fetch the server which we expect to exist.
     EXPECT_NO_THROW(returned_server = cbptr_->getServer6(ServerTag("server1")));
     ASSERT_TRUE(returned_server);
-    EXPECT_EQ("server1", returned_server->getServerTag());
+    EXPECT_EQ("server1", returned_server->getServerTagAsText());
     EXPECT_EQ("this is server 1", returned_server->getDescription());
     EXPECT_EQ(timestamps_["yesterday"], returned_server->getModificationTime());
 
@@ -536,7 +536,7 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateDeleteServer) {
     // Verify that the server has been updated. 
     EXPECT_NO_THROW(returned_server = cbptr_->getServer6(ServerTag("server1")));
     ASSERT_TRUE(returned_server);
-    EXPECT_EQ("server1", returned_server->getServerTag());
+    EXPECT_EQ("server1", returned_server->getServerTag().get());
     EXPECT_EQ("this is server 1 bis", returned_server->getDescription());
     EXPECT_EQ(timestamps_["today"], returned_server->getModificationTime());
 
@@ -627,7 +627,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateDeleteGlobalParameter6) {
     EXPECT_EQ("whale", returned_global_parameter->getValue());
     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
                 global_parameter->getModificationTime());
-    EXPECT_EQ("all", returned_global_parameter->getServerTag());
+    ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
+    EXPECT_EQ("all", returned_global_parameter->getServerTags()[0].get());
 
     // Because we have added the global parameter for all servers, it
     // should be also returned for the explicitly specified server.
@@ -638,7 +639,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateDeleteGlobalParameter6) {
     EXPECT_EQ("whale", returned_global_parameter->getValue());
     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
                 global_parameter->getModificationTime());
-    EXPECT_EQ("all", returned_global_parameter->getServerTag());
+    ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
+    EXPECT_EQ("all", returned_global_parameter->getServerTags()[0].get());
 
     // Check that the parameter is udpated when selector is specified correctly.
     global_parameter = StampedValue::create("global", "fish");
@@ -718,7 +720,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, globalParameters6WithServerTags) {
     );
     ASSERT_TRUE(returned_global);
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 
     // Try to fetch the value specified for the server1. This should override the
     // value specified for all servers.
@@ -728,7 +731,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, globalParameters6WithServerTags) {
     );
     ASSERT_TRUE(returned_global);
     EXPECT_EQ(global_parameter1->getValue(), returned_global->getValue());
-    EXPECT_EQ("server1", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("server1", returned_global->getServerTags()[0].get());
 
     // The same in case of the server2.
     EXPECT_NO_THROW(
@@ -737,19 +741,33 @@ TEST_F(MySqlConfigBackendDHCPv6Test, globalParameters6WithServerTags) {
     );
     ASSERT_TRUE(returned_global);
     EXPECT_EQ(global_parameter2->getValue(), returned_global->getValue());
-    EXPECT_EQ("server2", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("server2", returned_global->getServerTags()[0].get());
 
     StampedValueCollection returned_globals;
 
-    // Try to fetch the collection of globals for the server2. It should contain
-    // server specific values.
+    // Try to fetch the collection of globals for the server1, server2 and server3.
+    // The server3 does not have an explicit value so for this server we should get
+    /// the value for 'all'.
     EXPECT_NO_THROW(
-        returned_globals = cbptr_->getAllGlobalParameters6(ServerSelector::ONE("server2"))
+        returned_globals = cbptr_->getAllGlobalParameters6(ServerSelector::
+                                                           MULTIPLE({ "server1", "server2",
+                                                                       "server3"}));
     );
-    ASSERT_EQ(1, returned_globals.size());
-    returned_global = *returned_globals.begin();
-    EXPECT_EQ(global_parameter2->getValue(), returned_global->getValue());
-    EXPECT_EQ("server2", returned_global->getServerTag());
+    ASSERT_EQ(3, returned_globals.size());
+
+    // Capture the returned values into the map so as we can check the
+    // values against the servers.
+    std::map<std::string, std::string> values;
+    for (auto g = returned_globals.begin(); g != returned_globals.end(); ++g) {
+        ASSERT_EQ(1, (*g)->getServerTags().size());
+        values[(*g)->getServerTags()[0].get()] = ((*g)->getValue());
+    }
+
+    ASSERT_EQ(3, values.size());
+    EXPECT_EQ(global_parameter1->getValue(), values["server1"]);
+    EXPECT_EQ(global_parameter2->getValue(), values["server2"]);
+    EXPECT_EQ(global_parameter3->getValue(), values["all"]);
 
     // Try to fetch the collection of global parameters specified for all servers.
     // This excludes the values specific to server1 and server2. It returns only the
@@ -760,7 +778,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, globalParameters6WithServerTags) {
     ASSERT_EQ(1, returned_globals.size());
     returned_global = *returned_globals.begin();
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 
     // Delete the server1. It should remove associations of this server with the
     // global parameters.
@@ -774,7 +793,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, globalParameters6WithServerTags) {
     // all servers, rather than the one dedicated for server1. The association of
     // the server1 specific value with the server1 should be gone.
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 
     // Attempt to delete global parameter for server1.
     uint64_t deleted_num = 0;
@@ -800,7 +820,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, globalParameters6WithServerTags) {
     // The common value for all servers should still be available because 'all'
     // logical server should not be deleted.
     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
-    EXPECT_EQ("all", returned_global->getServerTag());
+    ASSERT_EQ(1, returned_global->getServerTags().size());
+    EXPECT_EQ("all", returned_global->getServerTags()[0].get());
 }
 
 // This test verifies that all global parameters can be retrieved and deleted.
@@ -825,7 +846,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllGlobalParameters6) {
 
     for (auto param = parameters_index.begin(); param != parameters_index.end();
          ++param) {
-        EXPECT_EQ("all", (*param)->getServerTag());
+        ASSERT_EQ(1, (*param)->getServerTags().size());
+        EXPECT_EQ("all", (*param)->getServerTags()[0].get());
     }
 
     // Verify their values.
@@ -901,7 +923,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6) {
     Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
                                                     test_subnets_[0]->getID());
     ASSERT_TRUE(returned_subnet);
-    EXPECT_EQ("all", returned_subnet->getServerTag());
+    ASSERT_EQ(1, returned_subnet->getServerTags().size());
+    EXPECT_EQ("all", returned_subnet->getServerTags()[0].get());
 
     // The easiest way to verify whether the returned subnet matches the inserted
     // subnet is to convert both to text.
@@ -1044,7 +1067,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6SharedNetwork) {
     Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
                                                     test_subnets_[0]->getID());
     ASSERT_TRUE(returned_subnet);
-    EXPECT_EQ("all", returned_subnet->getServerTag());
+    ASSERT_EQ(1, returned_subnet->getServerTags().size());
+    EXPECT_EQ("all", returned_subnet->getServerTags()[0].get());
 
     // The easiest way to verify whether the returned subnet matches the inserted
     // subnet is to convert both to text.
@@ -1065,7 +1089,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6ByPrefix) {
     Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
                                                     "2001:db8::/64");
     ASSERT_TRUE(returned_subnet);
-    EXPECT_EQ("all", returned_subnet->getServerTag());
+    ASSERT_EQ(1, returned_subnet->getServerTags().size());
+    EXPECT_EQ("all", returned_subnet->getServerTags()[0].get());
 
     // Verify subnet contents.
     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
@@ -1112,7 +1137,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllSubnets6) {
     for (auto i = 0; i < subnets.size(); ++i) {
         EXPECT_EQ(test_subnets_[i + 1]->toElement()->str(),
                   subnets[i]->toElement()->str());
-        EXPECT_EQ("all", subnets[i]->getServerTag());
+        ASSERT_EQ(1, subnets[i]->getServerTags().size());
+        EXPECT_EQ("all", subnets[i]->getServerTags()[0].get());
     }
 
     // Attempt to remove the non existing subnet should  return 0.
@@ -1316,7 +1342,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSharedNetwork6) {
     ASSERT_TRUE(returned_network);
 
     EXPECT_GT(returned_network->getId(), 0);
-    EXPECT_EQ("all", returned_network->getServerTag());
+    ASSERT_EQ(1, returned_network->getServerTags().size());
+    EXPECT_EQ("all", returned_network->getServerTags()[0].get());
 
     // The easiest way to verify whether the returned shared network matches the
     // inserted shared network is to convert both to text.
@@ -1441,7 +1468,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllSharedNetworks6) {
     for (auto i = 0; i < networks.size(); ++i) {
         EXPECT_EQ(test_networks_[i + 1]->toElement()->str(),
                   networks[i]->toElement()->str());
-        EXPECT_EQ("all", networks[i]->getServerTag());
+        ASSERT_EQ(1, networks[i]->getServerTags().size());
+        EXPECT_EQ("all", networks[i]->getServerTags()[0].get());
     }
 
     // Add some subnets.
@@ -1616,7 +1644,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getOptionDef6) {
                               test_option_defs_[0]->getOptionSpaceName());
     ASSERT_TRUE(returned_option_def);
     EXPECT_GT(returned_option_def->getId(), 0);
-    EXPECT_EQ("all", returned_option_def->getServerTag());
+    ASSERT_EQ(1, returned_option_def->getServerTags().size());
+    EXPECT_EQ("all", returned_option_def->getServerTags()[0].get());
 
     EXPECT_TRUE(returned_option_def->equals(*option_def));
 
@@ -1689,7 +1718,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptionDefs6) {
 
     // See if option definitions are returned ok.
     for (auto def = option_defs.begin(); def != option_defs.end(); ++def) {
-        EXPECT_EQ("all", (*def)->getServerTag());
+        ASSERT_EQ(1, (*def)->getServerTags().size());
+        EXPECT_EQ("all", (*def)->getServerTags()[0].get());
         bool success = false;
         for (auto i = 1; i < test_option_defs_.size(); ++i) {
             if ((*def)->equals(*test_option_defs_[i])) {
@@ -1886,7 +1916,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
         ASSERT_FALSE(option0 == index.end());
         testOptionsEquivalent(*test_options_[0], *option0);
         EXPECT_GT(option0->getId(), 0);
-        EXPECT_EQ("all", option0->getServerTag());
+        ASSERT_EQ(1, option0->getServerTags().size());
+        EXPECT_EQ("all", option0->getServerTags()[0].get());
     }
 
     {
@@ -1895,7 +1926,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
         ASSERT_FALSE(option1 == index.end());
         testOptionsEquivalent(*test_options_[1], *option1);
         EXPECT_GT(option1->getId(), 0);
-        EXPECT_EQ("all", option1->getServerTag());
+        ASSERT_EQ(1, option1->getServerTags().size());
+        EXPECT_EQ("all", option1->getServerTags()[0].get());
     }
 
     {
@@ -1904,7 +1936,8 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
         ASSERT_FALSE(option5 == index.end());
         testOptionsEquivalent(*test_options_[5], *option5);
         EXPECT_GT(option5->getId(), 0);
-        EXPECT_EQ("all", option5->getServerTag());
+        ASSERT_EQ(1, option5->getServerTags().size());
+        EXPECT_EQ("all", option5->getServerTags()[0].get());
     }
 }