From: Marcin Siodelski Date: Thu, 25 Apr 2019 17:08:26 +0000 (+0200) Subject: [#579] MySQL CB returns server tag for each returned config element. X-Git-Tag: Kea-1.6.0-beta~193 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dab1f03feef685963f10fecf3a1b819bc4a3b524;p=thirdparty%2Fkea.git [#579] MySQL CB returns server tag for each returned config element. --- diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc index 901df2542d..af2be2fdfb 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc @@ -280,7 +280,8 @@ public: MySqlBinding::createInteger(), // calculate_tee_times MySqlBinding::createInteger(), // t1_percent MySqlBinding::createInteger(), // t2_percent - MySqlBinding::createInteger() // authoritative + MySqlBinding::createInteger(), // 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(), // authoritative MySqlBinding::createString(BOOT_FILE_NAME_BUF_LENGTH), // boot_file_name MySqlBinding::createInteger(), // 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); } diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc index bff148d02a..629b98b59a 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc @@ -302,7 +302,8 @@ public: MySqlBinding::createInteger(), // option: pd_pool_id MySqlBinding::createInteger(), // calculate_tee_times MySqlBinding::createInteger(), // t1_percent - MySqlBinding::createInteger() // t2_percent + MySqlBinding::createInteger(), // 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(), // option: pd_pool_id MySqlBinding::createInteger(), // calculate_tee_times MySqlBinding::createInteger(), // t1_percent - MySqlBinding::createInteger() // t2_percent + MySqlBinding::createInteger(), // 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); } diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc index daf6115cfa..aa0b94a68d 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc @@ -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(), // 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())); 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(), // 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()); // 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()); @@ -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); } } diff --git a/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h b/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h index ea9d8a4aee..9891efe0d3 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h +++ b/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h @@ -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" \ diff --git a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc index ab215a3069..5aac4e41e8 100644 --- a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc +++ b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc @@ -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()); } } diff --git a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc index 298fb30104..ebef76a34c 100644 --- a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc +++ b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc @@ -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(); + 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()); } } diff --git a/src/lib/cc/stamped_element.cc b/src/lib/cc/stamped_element.cc index 0da5aa3735..01bd7e172b 100644 --- a/src/lib/cc/stamped_element.cc +++ b/src/lib/cc/stamped_element.cc @@ -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 diff --git a/src/lib/cc/stamped_element.h b/src/lib/cc/stamped_element.h index 63e69d1bf7..ae67026cff 100644 --- a/src/lib/cc/stamped_element.h +++ b/src/lib/cc/stamped_element.h @@ -7,8 +7,10 @@ #ifndef STAMPED_ELEMENT_H #define STAMPED_ELEMENT_H +#include #include #include +#include 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 diff --git a/src/lib/cc/tests/stamped_element_unittest.cc b/src/lib/cc/tests/stamped_element_unittest.cc index 8ca5378297..c67fded804 100644 --- a/src/lib/cc/tests/stamped_element_unittest.cc +++ b/src/lib/cc/tests/stamped_element_unittest.cc @@ -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()); +} + } diff --git a/src/lib/config_backend/constants.h b/src/lib/config_backend/constants.h index c85366eebe..8cbd993ca5 100644 --- a/src/lib/config_backend/constants.h +++ b/src/lib/config_backend/constants.h @@ -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 diff --git a/src/lib/dhcpsrv/cfg_option.cc b/src/lib/dhcpsrv/cfg_option.cc index cde3ae31a9..f581715863 100644 --- a/src/lib/dhcpsrv/cfg_option.cc +++ b/src/lib/dhcpsrv/cfg_option.cc @@ -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 diff --git a/src/lib/dhcpsrv/cfg_option.h b/src/lib/dhcpsrv/cfg_option.h index de3a849c50..6cd428e634 100644 --- a/src/lib/dhcpsrv/cfg_option.h +++ b/src/lib/dhcpsrv/cfg_option.h @@ -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. diff --git a/src/lib/dhcpsrv/cfg_option_def.cc b/src/lib/dhcpsrv/cfg_option_def.cc index f8d0a25c45..5b66495e90 100644 --- a/src/lib/dhcpsrv/cfg_option_def.cc +++ b/src/lib/dhcpsrv/cfg_option_def.cc @@ -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); } diff --git a/src/lib/dhcpsrv/cfg_option_def.h b/src/lib/dhcpsrv/cfg_option_def.h index 3c58b77aaf..7b9a86ccd3 100644 --- a/src/lib/dhcpsrv/cfg_option_def.h +++ b/src/lib/dhcpsrv/cfg_option_def.h @@ -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. /// diff --git a/src/lib/dhcpsrv/testutils/test_config_backend.h b/src/lib/dhcpsrv/testutils/test_config_backend.h index e945d7d9b1..acb7515ecc 100644 --- a/src/lib/dhcpsrv/testutils/test_config_backend.h +++ b/src/lib/dhcpsrv/testutils/test_config_backend.h @@ -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 tags = server_selector.getTags(); + if (!tags.empty()) { + return (*tags.begin()); + } + return (""); + } + /// @brief Fake database connection db::DatabaseConnection connection_; diff --git a/src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.cc b/src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.cc index 9dc6e2604d..70b2ba830f 100644 --- a/src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.cc +++ b/src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.cc @@ -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(); 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(); 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(); auto global_it = index.find(value->getName()); diff --git a/src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.cc b/src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.cc index 35c456a4a9..74303f673d 100644 --- a/src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.cc +++ b/src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.cc @@ -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(); 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(); 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(); auto global_it = index.find(value->getName());