]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#579] MySQL CB returns server tag for each returned config element.
authorMarcin Siodelski <marcin@isc.org>
Thu, 25 Apr 2019 17:08:26 +0000 (19:08 +0200)
committerMarcin Siodelski <marcin@isc.org>
Thu, 25 Apr 2019 17:08:26 +0000 (19:08 +0200)
17 files changed:
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
src/lib/cc/stamped_element.cc
src/lib/cc/stamped_element.h
src/lib/cc/tests/stamped_element_unittest.cc
src/lib/config_backend/constants.h
src/lib/dhcpsrv/cfg_option.cc
src/lib/dhcpsrv/cfg_option.h
src/lib/dhcpsrv/cfg_option_def.cc
src/lib/dhcpsrv/cfg_option_def.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 901df2542dad7086c210b515e72e6c05623907e6..af2be2fdfb47fa648064d6fea86691355c286876 100644 (file)
@@ -280,7 +280,8 @@ public:
             MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
             MySqlBinding::createInteger<float>(), // t1_percent
             MySqlBinding::createInteger<float>(), // t2_percent
-            MySqlBinding::createInteger<uint8_t>() // authoritative
+            MySqlBinding::createInteger<uint8_t>(), // authoritative
+            MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
         };
 
         uint64_t last_pool_id = 0;
@@ -447,6 +448,9 @@ public:
                     last_subnet->setAuthoritative(out_bindings[52]->getBool());
                 }
 
+                // server_tag
+                last_subnet->setServerTag(out_bindings[53]->getString());
+
                 // Subnet ready. Add it to the list.
                 subnets.push_back(last_subnet);
             }
@@ -1017,7 +1021,8 @@ public:
             MySqlBinding::createInteger<uint8_t>(), // authoritative
             MySqlBinding::createString(BOOT_FILE_NAME_BUF_LENGTH), // boot_file_name
             MySqlBinding::createInteger<uint32_t>(), // next_server
-            MySqlBinding::createString(SERVER_HOSTNAME_BUF_LENGTH) // server_hostname
+            MySqlBinding::createString(SERVER_HOSTNAME_BUF_LENGTH), // server_hostname
+            MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
         };
 
         uint64_t last_network_id = 0;
@@ -1152,6 +1157,9 @@ public:
                     last_network->setSname(out_bindings[31]->getString());
                 }
 
+                // server_tag
+                last_network->setServerTag(out_bindings[32]->getString());
+
                 shared_networks.push_back(last_network);
             }
 
index bff148d02aa3f1073f04f784dd0de469a5c23788..629b98b59a71b5b74a341f553280363374f79d7f 100644 (file)
@@ -302,7 +302,8 @@ public:
             MySqlBinding::createInteger<uint64_t>(), // option: pd_pool_id
             MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
             MySqlBinding::createInteger<float>(), // t1_percent
-            MySqlBinding::createInteger<float>() // t2_percent
+            MySqlBinding::createInteger<float>(), // t2_percent
+            MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
         };
 
         uint64_t last_pool_id = 0;
@@ -453,6 +454,9 @@ public:
                     last_subnet->setT2Percent(out_bindings[67]->getFloat());
                 }
 
+                // server_tag
+                last_subnet->setServerTag(out_bindings[68]->getString());
+
                 // Subnet ready. Add it to the list.
                 subnets.push_back(last_subnet);
             }
@@ -1185,7 +1189,8 @@ public:
             MySqlBinding::createInteger<uint64_t>(), // option: pd_pool_id
             MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
             MySqlBinding::createInteger<float>(), // t1_percent
-            MySqlBinding::createInteger<float>() // t2_percent
+            MySqlBinding::createInteger<float>(), // t2_percent
+            MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
         };
 
         uint64_t last_network_id = 0;
@@ -1306,6 +1311,9 @@ public:
                     last_network->setT2Percent(out_bindings[29]->getFloat());
                 }
 
+                // server_tag
+                last_network->setServerTag(out_bindings[30]->getString());
+
                 shared_networks.push_back(last_network);
             }
 
index daf6115cfa8143eefc28810c3513cce6d133ed74..aa0b94a68d6a002695db9c3d7f5e4454a4d66758 100644 (file)
@@ -202,7 +202,8 @@ MySqlConfigBackendImpl::getGlobalParameters(const int index,
         MySqlBinding::createString(GLOBAL_PARAMETER_NAME_BUF_LENGTH), // name
         MySqlBinding::createString(GLOBAL_PARAMETER_VALUE_BUF_LENGTH), // value
         MySqlBinding::createInteger<uint8_t>(), // parameter_type
-        MySqlBinding::createTimestamp() // modification_ts
+        MySqlBinding::createTimestamp(), // modification_ts
+        MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
     };
 
     conn_.selectQuery(index, in_bindings, out_bindings,
@@ -218,6 +219,7 @@ MySqlConfigBackendImpl::getGlobalParameters(const int index,
                                      (out_bindings[3]->getInteger<uint8_t>()));
 
             stamped_value->setModificationTime(out_bindings[4]->getTimestamp());
+            stamped_value->setServerTag(out_bindings[5]->getString());
             parameters.insert(stamped_value);
         }
     });
@@ -290,7 +292,8 @@ MySqlConfigBackendImpl::getOptionDefs(const int index,
         MySqlBinding::createInteger<uint8_t>(), // array
         MySqlBinding::createString(OPTION_ENCAPSULATE_BUF_LENGTH), // encapsulate
         MySqlBinding::createString(OPTION_RECORD_TYPES_BUF_LENGTH), // record_types
-        MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH) // user_context
+        MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
+        MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
     };
 
     uint64_t last_def_id = 0;
@@ -360,6 +363,9 @@ MySqlConfigBackendImpl::getOptionDefs(const int index,
             // Update modification time.
             last_def->setModificationTime(out_bindings[5]->getTimestamp());
 
+            // server_tag
+            last_def->setServerTag(out_bindings[10]->getString());
+
             // Store created option definition.
             option_defs.push_back(last_def);
         }
@@ -656,6 +662,8 @@ MySqlConfigBackendImpl::getOptions(const int index,
     out_bindings.push_back(MySqlBinding::createInteger<uint64_t>());
     // modification_ts
     out_bindings.push_back(MySqlBinding::createTimestamp());
+    // server_tag
+    out_bindings.push_back(MySqlBinding::createString(SERVER_TAG_BUF_LENGTH));
     // pd_pool_id
     if (universe == Option::V6) {
         out_bindings.push_back(MySqlBinding::createInteger<uint64_t>());
@@ -674,6 +682,8 @@ MySqlConfigBackendImpl::getOptions(const int index,
 
             OptionDescriptorPtr desc = processOptionRow(universe, out_bindings.begin());
             if (desc) {
+                // server_tag for the global option
+                desc->setServerTag(out_bindings[12]->getString());
                 options.push_back(*desc);
             }
         }
index ea9d8a4aeecf73ad63451f3dbb9a184a4331f84e..9891efe0d3648b7152238f5784697f53c2dd3840 100644 (file)
@@ -36,7 +36,8 @@ namespace {
     "  g.name," \
     "  g.value," \
     "  g.parameter_type," \
-    "  g.modification_ts " \
+    "  g.modification_ts," \
+    "  s.tag " \
     "FROM " #table_prefix "_global_parameter AS g " \
     "INNER JOIN " #table_prefix "_global_parameter_server AS a " \
     "  ON g.id = a.parameter_id " \
@@ -102,7 +103,8 @@ namespace {
     "  s.calculate_tee_times," \
     "  s.t1_percent," \
     "  s.t2_percent," \
-    "  s.authoritative " \
+    "  s.authoritative," \
+    "  srv.tag " \
     "FROM dhcp4_subnet AS s " \
     "INNER JOIN dhcp4_subnet_server AS a " \
     "  ON s.subnet_id = a.subnet_id " \
@@ -185,7 +187,8 @@ namespace {
     "  o.pd_pool_id, " \
     "  s.calculate_tee_times," \
     "  s.t1_percent," \
-    "  s.t2_percent " \
+    "  s.t2_percent," \
+    "  srv.tag " \
     "FROM dhcp6_subnet AS s " \
     "INNER JOIN dhcp6_subnet_server AS a " \
     "  ON s.subnet_id = a.subnet_id " \
@@ -234,7 +237,8 @@ namespace {
     "  n.authoritative," \
     "  n.boot_file_name," \
     "  n.next_server," \
-    "  n.server_hostname " \
+    "  n.server_hostname," \
+    "  s.tag " \
     "FROM dhcp4_shared_network AS n " \
     "INNER JOIN dhcp4_shared_network_server AS a " \
     "  ON n.id = a.shared_network_id " \
@@ -277,7 +281,8 @@ namespace {
     "  o.pd_pool_id, " \
     "  n.calculate_tee_times," \
     "  n.t1_percent," \
-    "  n.t2_percent " \
+    "  n.t2_percent," \
+    "  s.tag " \
     "FROM dhcp6_shared_network AS n " \
     "INNER JOIN dhcp6_shared_network_server AS a " \
     "  ON n.id = a.shared_network_id " \
@@ -300,7 +305,8 @@ namespace {
     "  d.array," \
     "  d.encapsulate," \
     "  d.record_types," \
-    "  d.user_context " \
+    "  d.user_context," \
+    "  s.tag " \
     "FROM " #table_prefix "_option_def AS d " \
     "INNER JOIN " #table_prefix "_option_def_server AS a" \
     "  ON d.id = a.option_def_id " \
@@ -324,7 +330,8 @@ namespace {
     "  o.user_context," \
     "  o.shared_network_name," \
     "  o.pool_id," \
-    "  o.modification_ts " \
+    "  o.modification_ts," \
+    "  s.tag " \
     pd_pool_id \
     "FROM " #table_prefix "_options AS o " \
     "INNER JOIN " #table_prefix "_options_server AS a" \
index ab215a30697470a6709dbc2a5655beb6b238bdd0..5aac4e41e8f05a5801ac51a411d62a48b031c2c1 100644 (file)
@@ -462,6 +462,7 @@ 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());
 
     // Because we have added the global parameter for all servers, it
     // should be also returned for the explicitly specified server.
@@ -472,6 +473,7 @@ 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());
 
     // Check that the parameter is udpated when selector is specified correctly.
     global_parameter = StampedValue::create("global", "fish");
@@ -484,6 +486,7 @@ 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());
 
     {
         SCOPED_TRACE("UPDATE audit entry for the global parameter");
@@ -538,6 +541,11 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllGlobalParameters4) {
     EXPECT_TRUE((*parameters_index.find("name4"))->getBoolValue());
     EXPECT_EQ(1.65, (*parameters_index.find("name5"))->getDoubleValue());
 
+    for (auto param = parameters_index.begin(); param != parameters_index.end();
+         ++param) {
+        EXPECT_EQ("all", (*param)->getServerTag());
+    }
+
     // Should be able to fetch these parameters when explicitly providing
     // the server tag.
     parameters = cbptr_->getAllGlobalParameters4(ServerSelector::ONE("server1"));
@@ -604,6 +612,7 @@ 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());
 
     // The easiest way to verify whether the returned subnet matches the inserted
     // subnet is to convert both to text.
@@ -782,6 +791,7 @@ 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());
 
     // Verify subnet contents.
     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
@@ -826,6 +836,7 @@ 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());
         EXPECT_EQ(test_subnets_[i + 1]->toElement()->str(),
                   subnets[i]->toElement()->str());
     }
@@ -964,6 +975,9 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetworkSubnets4) {
     EXPECT_TRUE(isEquivalent(test_subnets_[1]->toElement(),
                              subnets[0]->toElement()));
 
+    // Check server tag
+    EXPECT_EQ("all", subnets[0]->getServerTag());
+
     // Fetch all subnets belonging to shared network level2.
     subnets = cbptr_->getSharedNetworkSubnets4(ServerSelector::ALL(), "level2");
     ASSERT_EQ(2, subnets.size());
@@ -1003,6 +1017,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4) {
     ASSERT_TRUE(returned_network);
 
     EXPECT_GT(returned_network->getId(), 0);
+    EXPECT_EQ("all", returned_network->getServerTag());
 
     // The easiest way to verify whether the returned shared network matches the
     // inserted shared network is to convert both to text.
@@ -1270,6 +1285,7 @@ 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());
 
     EXPECT_TRUE(returned_option_def->equals(*option_def));
 
@@ -1342,6 +1358,7 @@ 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());
         bool success = false;
         for (auto i = 1; i < test_option_defs_.size(); ++i) {
             if ((*def)->equals(*test_option_defs_[i])) {
@@ -1536,6 +1553,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
         ASSERT_FALSE(option0 == index.end());
         testOptionsEquivalent(*test_options_[0], *option0);
         EXPECT_GT(option0->getId(), 0);
+        EXPECT_EQ("all", option0->getServerTag());
     }
 
     {
@@ -1544,6 +1562,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
         ASSERT_FALSE(option1 == index.end());
         testOptionsEquivalent(*test_options_[1], *option1);
         EXPECT_GT(option1->getId(), 0);
+        EXPECT_EQ("all", option1->getServerTag());
     }
 
     {
@@ -1552,6 +1571,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
         ASSERT_FALSE(option5 == index.end());
         testOptionsEquivalent(*test_options_[5], *option5);
         EXPECT_GT(option5->getId(), 0);
+        EXPECT_EQ("all", option5->getServerTag());
     }
 }
 
index 298fb30104e23b6b407a0d48ef373370309b2a22..ebef76a34ce8160e90c8b36a1613ec7b94d9471f 100644 (file)
@@ -494,6 +494,7 @@ 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());
 
     // Because we have added the global parameter for all servers, it
     // should be also returned for the explicitly specified server.
@@ -504,6 +505,7 @@ 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());
 
     // Check that the parameter is udpated when selector is specified correctly.
     global_parameter = StampedValue::create("global", "fish");
@@ -563,6 +565,11 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllGlobalParameters6) {
 
     const auto& parameters_index = parameters.get<StampedValueNameIndexTag>();
 
+    for (auto param = parameters_index.begin(); param != parameters_index.end();
+         ++param) {
+        EXPECT_EQ("all", (*param)->getServerTag());
+    }
+
     // Verify their values.
     EXPECT_EQ("value1", (*parameters_index.find("name1"))->getValue());
     EXPECT_EQ(65, (*parameters_index.find("name2"))->getIntegerValue());
@@ -636,6 +643,7 @@ 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());
 
     // The easiest way to verify whether the returned subnet matches the inserted
     // subnet is to convert both to text.
@@ -778,6 +786,7 @@ 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());
 
     // The easiest way to verify whether the returned subnet matches the inserted
     // subnet is to convert both to text.
@@ -798,6 +807,7 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6ByPrefix) {
     Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
                                                     "2001:db8::/64");
     ASSERT_TRUE(returned_subnet);
+    EXPECT_EQ("all", returned_subnet->getServerTag());
 
     // Verify subnet contents.
     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
@@ -844,6 +854,7 @@ 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());
     }
 
     // Attempt to remove the non existing subnet should  return 0.
@@ -1019,6 +1030,7 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSharedNetwork6) {
     ASSERT_TRUE(returned_network);
 
     EXPECT_GT(returned_network->getId(), 0);
+    EXPECT_EQ("all", returned_network->getServerTag());
 
     // The easiest way to verify whether the returned shared network matches the
     // inserted shared network is to convert both to text.
@@ -1143,6 +1155,7 @@ 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());
     }
 
     // Add some subnets.
@@ -1286,6 +1299,7 @@ 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());
 
     EXPECT_TRUE(returned_option_def->equals(*option_def));
 
@@ -1358,6 +1372,7 @@ 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());
         bool success = false;
         for (auto i = 1; i < test_option_defs_.size(); ++i) {
             if ((*def)->equals(*test_option_defs_[i])) {
@@ -1554,6 +1569,7 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
         ASSERT_FALSE(option0 == index.end());
         testOptionsEquivalent(*test_options_[0], *option0);
         EXPECT_GT(option0->getId(), 0);
+        EXPECT_EQ("all", option0->getServerTag());
     }
 
     {
@@ -1562,6 +1578,7 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
         ASSERT_FALSE(option1 == index.end());
         testOptionsEquivalent(*test_options_[1], *option1);
         EXPECT_GT(option1->getId(), 0);
+        EXPECT_EQ("all", option1->getServerTag());
     }
 
     {
@@ -1570,6 +1587,7 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
         ASSERT_FALSE(option5 == index.end());
         testOptionsEquivalent(*test_options_[5], *option5);
         EXPECT_GT(option5->getId(), 0);
+        EXPECT_EQ("all", option5->getServerTag());
     }
 }
 
index 0da5aa373577aae74a07d3524b0aa573355aa371..01bd7e172baa9da86deecf423b6f4ac8d53b4f25 100644 (file)
@@ -12,7 +12,8 @@ namespace data {
 StampedElement::StampedElement()
     /// @todo Change it to microsec_clock once we transition to subsecond
     /// precision.
-    : id_(0), timestamp_(boost::posix_time::second_clock::local_time()) {
+    : id_(0), timestamp_(boost::posix_time::second_clock::local_time()),
+      server_tag_() {
 }
 
 void
@@ -22,5 +23,12 @@ StampedElement::updateModificationTime() {
     setModificationTime(boost::posix_time::second_clock::local_time());
 }
 
+ElementPtr
+StampedElement::getMetadata() const {
+    ElementPtr metadata = Element::createMap();
+    metadata->set("server-tag", Element::create(getServerTag()));
+    return (metadata);
+}
+
 } // end of namespace isc::data
 } // end of namespace isc
index 63e69d1bf7b026692f8543b4c7abd5cf2b091129..ae67026cffccfc649b4ce812bb944c9cf0d026ca 100644 (file)
@@ -7,8 +7,10 @@
 #ifndef STAMPED_ELEMENT_H
 #define STAMPED_ELEMENT_H
 
+#include <cc/data.h>
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <cstdint>
+#include <string>
 
 namespace isc {
 namespace data {
@@ -65,6 +67,24 @@ public:
         return (timestamp_);
     }
 
+    /// @brief Sets new server tag.
+    ///
+    /// @param server_tag
+    void setServerTag(const std::string& server_tag) {
+        server_tag_ = server_tag;
+    }
+
+    /// @brief Returns server tag.
+    std::string getServerTag() const {
+        return (server_tag_);
+    }
+
+    /// @brief Returns an object representing metadata to be returned
+    /// with objects from the configuration backend.
+    ///
+    /// @return Pointer to the metadata element.
+    isc::data::ElementPtr getMetadata() const;
+
 private:
 
     /// @brief Database identifier of the configuration element.
@@ -76,6 +96,8 @@ private:
     /// @brief Holds timestamp value.
     boost::posix_time::ptime timestamp_;
 
+    /// @brief Holds server tag.
+    std::string server_tag_;
 };
 
 } // end of namespace isc::data
index 8ca5378297a059b178ae7c5023d5eb7787df30aa..c67fded8045f7081e3951394e5494b494d22d43b 100644 (file)
@@ -23,6 +23,9 @@ TEST(StampedElementTest, create) {
     // Default identifier is 0.
     EXPECT_EQ(0, element.getId());
 
+    // Default server tag is empty.
+    EXPECT_TRUE(element.getServerTag().empty());
+
     // Checking that the delta between now and the timestamp is within
     // 5s range should be sufficient.
     boost::posix_time::time_duration delta =
@@ -67,4 +70,25 @@ TEST(StampedElementTest, update) {
     EXPECT_LT(delta.seconds(), 5);
 }
 
+// Tests that server tag can be overriden by a new value.
+TEST(StampedElementTest, setServerTag) {
+    StampedElement element;
+    element.setServerTag("foo");
+    EXPECT_EQ("foo", element.getServerTag());
+}
+
+// Test that metadata can be created from the StampedElement.
+TEST(StampedElementTest, getMetadata) {
+    StampedElement element;
+    element.setServerTag("world");
+    auto metadata = element.getMetadata();
+    ASSERT_TRUE(metadata);
+    ASSERT_EQ(Element::map, metadata->getType());
+
+    auto server_tag_element = metadata->get("server-tag");
+    ASSERT_TRUE(server_tag_element);
+    EXPECT_EQ(Element::string, server_tag_element->getType());
+    EXPECT_EQ("world", server_tag_element->stringValue());
+}
+
 }
index c85366eebe3e60d9ae2c0296da3f407f3d00ee52..8cbd993ca5584e6d03049bc30bc01f40be20bf86 100644 (file)
@@ -64,6 +64,8 @@ constexpr unsigned long AUDIT_ENTRY_OBJECT_TYPE_BUF_LENGTH = 256;
 
 constexpr unsigned long AUDIT_ENTRY_LOG_MESSAGE_BUF_LENGTH = 65536;
 
+constexpr unsigned long SERVER_TAG_BUF_LENGTH = 256;
+
 //*}
 
 } // end of namespace isc::cb
index cde3ae31a90a9bfdbbea2b47e3422cfdefa06aba..f581715863076acea68c992e067ca9ba45981884 100644 (file)
@@ -424,6 +424,11 @@ CfgOption::del(const uint64_t id) {
 
 ElementPtr
 CfgOption::toElement() const {
+    return (toElementWithMetadata(false));
+}
+
+ElementPtr
+CfgOption::toElementWithMetadata(const bool include_metadata) const {
     // option-data value is a list of maps
     ElementPtr result = Element::createList();
     // Iterate first on options using space names
@@ -465,6 +470,12 @@ CfgOption::toElement() const {
             }
             // Set the persistency flag
             map->set("always-send", Element::create(opt->persistent_));
+
+            // Include metadata if requested.
+            if (include_metadata) {
+                map->set("metadata", opt->getMetadata());
+            }
+
             // Push on the list
             result->add(map);
         }
@@ -517,5 +528,6 @@ CfgOption::toElement() const {
     return (result);
 }
 
+
 }  // namespace dhcp
 }  // namespace isc
index de3a849c50dc1e60b1f0c4f795ff7165ac961ba2..6cd428e634ffc556e641c35eabb419bd98cac50a 100644 (file)
@@ -617,6 +617,16 @@ public:
     /// @return a pointer to unparsed configuration
     virtual isc::data::ElementPtr toElement() const;
 
+    /// @brief Unparse a configuration object with optionally including
+    /// the metadata.
+    ///
+    /// @param include_metadata boolean value indicating if the metadata
+    /// should be included (if true) or not (if false).
+    ///
+    /// @return A pointer to the unparsed configuration.
+    isc::data::ElementPtr
+    toElementWithMetadata(const bool include_metadata) const;
+
 private:
 
     /// @brief Appends encapsulated options to the options in an option space.
index f8d0a25c458ddeb617740edba6ab6c6f984944b9..5b66495e90ead8d2bcdc0893bee696f955fe21d1 100644 (file)
@@ -167,6 +167,11 @@ CfgOptionDef::del(const uint64_t id) {
 
 ElementPtr
 CfgOptionDef::toElement() const {
+    return (toElementWithMetadata(false));
+}
+
+ElementPtr
+CfgOptionDef::toElementWithMetadata(const bool include_metadata) const {
     // option-defs value is a list of maps
     ElementPtr result = Element::createList();
     // Iterate through the container by names and definitions
@@ -212,6 +217,12 @@ CfgOptionDef::toElement() const {
             } else {
                 map->set("record-types", Element::create(std::string()));
             }
+
+            // Include metadata if requested.
+            if (include_metadata) {
+                map->set("metadata", (*def)->getMetadata());
+            }
+
             // Push on the list
             result->add(map);
         }
index 3c58b77aafa4c40cbfb2b806f147a3aa2bd42710..7b9a86ccd3166ebb1c954253d78d95a0f7fb1fec 100644 (file)
@@ -138,6 +138,16 @@ public:
     /// @return a pointer to unparsed configuration
     virtual isc::data::ElementPtr toElement() const;
 
+    /// @brief Unparse a configuration object with optionally including
+    /// the metadata.
+    ///
+    /// @param include_metadata boolean value indicating if the metadata
+    /// should be included (if true) or not (if false).
+    ///
+    /// @return A pointer to the unparsed configuration.
+    isc::data::ElementPtr
+    toElementWithMetadata(const bool include_metadata) const;
+
     /// @brief Merges specified option definitions from a configuration
     /// into this configuration.
     ///
index e945d7d9b1081f4f3718cdbf542190fa0a307aab..acb7515ecc528df14299cbf4c3e41384145bfe94 100644 (file)
@@ -71,6 +71,21 @@ public:
         return (port_);
     }
 
+    /// @brief Returns server tag to be associated with the stored configuration.
+    ///
+    /// @param server_selector Server selector.
+    std::string getServerTag(const db::ServerSelector& server_selector) const {
+        if (server_selector.getType() == db::ServerSelector::Type::ALL) {
+            return ("all");
+        }
+        // Return first tag found.
+        std::set<std::string> tags = server_selector.getTags();
+        if (!tags.empty()) {
+            return (*tags.begin());
+        }
+        return ("");
+    }
+
     /// @brief Fake database connection
     db::DatabaseConnection connection_;
 
index 9dc6e2604def7cfbe162f57b68b550081fbc9c7f..70b2ba830f570d79c80414e6bbf0608ab57de059 100644 (file)
@@ -218,8 +218,10 @@ TestConfigBackendDHCPv4::getRecentAuditEntries(const db::ServerSelector&,
 }
 
 void
-TestConfigBackendDHCPv4::createUpdateSubnet4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::createUpdateSubnet4(const db::ServerSelector& server_selector,
                                              const Subnet4Ptr& subnet) {
+    subnet->setServerTag(getServerTag(server_selector));
+
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet->getID());
 
@@ -232,8 +234,10 @@ TestConfigBackendDHCPv4::createUpdateSubnet4(const db::ServerSelector& /* server
 }
 
 void
-TestConfigBackendDHCPv4::createUpdateSharedNetwork4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::createUpdateSharedNetwork4(const db::ServerSelector& server_selector,
                                                     const SharedNetwork4Ptr& shared_network) {
+    shared_network->setServerTag(getServerTag(server_selector));
+
     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(shared_network->getName());
 
@@ -246,8 +250,10 @@ TestConfigBackendDHCPv4::createUpdateSharedNetwork4(const db::ServerSelector& /*
 }
 
 void
-TestConfigBackendDHCPv4::createUpdateOptionDef4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::createUpdateOptionDef4(const db::ServerSelector& server_selector,
                                                 const OptionDefinitionPtr& option_def) {
+    option_def->setServerTag(getServerTag(server_selector));
+
     auto& index = option_defs_.get<1>();
     auto option_def_it = index.find(option_def->getCode());
 
@@ -260,8 +266,10 @@ TestConfigBackendDHCPv4::createUpdateOptionDef4(const db::ServerSelector& /* ser
 }
 
 void
-TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_selector,
                                              const OptionDescriptorPtr& option) {
+    option->setServerTag(getServerTag(server_selector));
+
     auto& index = options_.get<1>();
     auto option_it = index.find(option->option_->getType());
 
@@ -329,8 +337,10 @@ TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& /* server
 }
 
 void
-TestConfigBackendDHCPv4::createUpdateGlobalParameter4(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv4::createUpdateGlobalParameter4(const db::ServerSelector& server_selector,
                                                       const data::StampedValuePtr& value) {
+    value->setServerTag(getServerTag(server_selector));
+
     auto& index = globals_.get<StampedValueNameIndexTag>();
     auto global_it = index.find(value->getName());
 
index 35c456a4a93d2824ba2ab9ba746c809f29a416f4..74303f673d16eaa57edff6371401ee3c59fe6893 100644 (file)
@@ -217,8 +217,10 @@ TestConfigBackendDHCPv6::getRecentAuditEntries(const db::ServerSelector&,
 }
 
 void
-TestConfigBackendDHCPv6::createUpdateSubnet6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::createUpdateSubnet6(const db::ServerSelector& server_selector,
                                              const Subnet6Ptr& subnet) {
+    subnet->setServerTag(getServerTag(server_selector));
+
     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
     auto subnet_it = index.find(subnet->getID());
 
@@ -231,8 +233,10 @@ TestConfigBackendDHCPv6::createUpdateSubnet6(const db::ServerSelector& /* server
 }
 
 void
-TestConfigBackendDHCPv6::createUpdateSharedNetwork6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::createUpdateSharedNetwork6(const db::ServerSelector& server_selector,
                                                     const SharedNetwork6Ptr& shared_network) {
+
+    shared_network->setServerTag(getServerTag(server_selector));
     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
     auto network_it = index.find(shared_network->getName());
 
@@ -245,8 +249,10 @@ TestConfigBackendDHCPv6::createUpdateSharedNetwork6(const db::ServerSelector& /*
 }
 
 void
-TestConfigBackendDHCPv6::createUpdateOptionDef6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::createUpdateOptionDef6(const db::ServerSelector& server_selector,
                                                 const OptionDefinitionPtr& option_def) {
+    option_def->setServerTag(getServerTag(server_selector));
+
     auto& index = option_defs_.get<1>();
     auto option_def_it = index.find(option_def->getCode());
 
@@ -259,8 +265,10 @@ TestConfigBackendDHCPv6::createUpdateOptionDef6(const db::ServerSelector& /* ser
 }
 
 void
-TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_selector,
                                              const OptionDescriptorPtr& option) {
+    option->setServerTag(getServerTag(server_selector));
+
     auto& index = options_.get<1>();
     auto option_it = index.find(option->option_->getType());
 
@@ -348,8 +356,10 @@ TestConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& /* server
 }
 
 void
-TestConfigBackendDHCPv6::createUpdateGlobalParameter6(const db::ServerSelector& /* server_selector */,
+TestConfigBackendDHCPv6::createUpdateGlobalParameter6(const db::ServerSelector& server_selector,
                                                       const data::StampedValuePtr& value) {
+    value->setServerTag(getServerTag(server_selector));
+
     auto& index = globals_.get<StampedValueNameIndexTag>();
     auto global_it = index.find(value->getName());