From: Marcin Siodelski Date: Mon, 15 Oct 2018 11:11:23 +0000 (+0200) Subject: [#93,!63] Server selection is partially supported for option definitions. X-Git-Tag: 153-netconf-configs_base~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=20858243fbaedac9b418c3de598f91846376608f;p=thirdparty%2Fkea.git [#93,!63] Server selection is partially supported for option definitions. --- diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc index 01d15248e8..479ab9a765 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc @@ -78,6 +78,7 @@ public: INSERT_SHARED_NETWORK4, INSERT_SHARED_NETWORK4_SERVER, INSERT_OPTION_DEF4, + INSERT_OPTION_DEF4_SERVER, INSERT_OPTION4, UPDATE_GLOBAL_PARAMETER4, UPDATE_SUBNET4, @@ -1331,11 +1332,19 @@ public: /// /// @return Pointer to the returned option definition or NULL if such /// option definition doesn't exist. - OptionDefinitionPtr getOptionDef4(const ServerSelector& /* server_selector */, + OptionDefinitionPtr getOptionDef4(const ServerSelector& server_selector, const uint16_t code, const std::string& space) { + auto tags = getServerTags(server_selector); + if (tags.size() != 1) { + isc_throw(InvalidOperation, "expected exactly one server tag to be" + " specified while fetching an option definition. Got: " + << getServerTagsAsText(server_selector)); + } + OptionDefContainer option_defs; MySqlBindingCollection in_bindings = { + MySqlBinding::createString(*tags.begin()), MySqlBinding::createInteger(static_cast(code)), MySqlBinding::createString(space) }; @@ -1346,13 +1355,19 @@ public: /// @brief Sends query to retrieve all option definitions. /// /// @param server_selector Server selector. - /// @return Container holding returned option definitions. - OptionDefContainer getAllOptionDefs4(const ServerSelector& /* server_selector */) { - OptionDefContainer option_defs; - MySqlBindingCollection in_bindings; - getOptionDefs(MySqlConfigBackendDHCPv4Impl::GET_ALL_OPTION_DEFS4, - in_bindings, option_defs); - return (option_defs); + /// @param [out] option_defs Reference to the container where option + /// definitions are to be stored. + void + getAllOptionDefs4(const ServerSelector& server_selector, + OptionDefContainer& option_defs) { + auto tags = getServerTags(server_selector); + for (auto tag : tags) { + MySqlBindingCollection in_bindings = { + MySqlBinding::createString(tag) + }; + getOptionDefs(MySqlConfigBackendDHCPv4Impl::GET_ALL_OPTION_DEFS4, + in_bindings, option_defs); + } } /// @brief Sends query to retrieve option definitions with modification @@ -1360,17 +1375,21 @@ public: /// /// @param server_selector Server selector. /// @param modification_time Lower bound subnet modification time. - /// @return Container holding returned option definitions. - OptionDefContainer - getModifiedOptionDefs4(const ServerSelector& /* server_selector */, - const boost::posix_time::ptime& modification_time) { - OptionDefContainer option_defs; - MySqlBindingCollection in_bindings = { - MySqlBinding::createTimestamp(modification_time) - }; - getOptionDefs(MySqlConfigBackendDHCPv4Impl::GET_MODIFIED_OPTION_DEFS4, - in_bindings, option_defs); - return (option_defs); + /// @param [out] option_defs Reference to the container where option + /// definitions are to be stored. + void + getModifiedOptionDefs4(const ServerSelector& server_selector, + const boost::posix_time::ptime& modification_time, + OptionDefContainer& option_defs) { + auto tags = getServerTags(server_selector); + for (auto tag : tags) { + MySqlBindingCollection in_bindings = { + MySqlBinding::createString(tag), + MySqlBinding::createTimestamp(modification_time) + }; + getOptionDefs(MySqlConfigBackendDHCPv4Impl::GET_MODIFIED_OPTION_DEFS4, + in_bindings, option_defs); + } } /// @brief Sends query to retrieve single global option by code and @@ -1509,6 +1528,13 @@ public: /// @param option_def Pointer to the option definition to be inserted or updated. void createUpdateOptionDef4(const ServerSelector& server_selector, const OptionDefinitionPtr& option_def) { + auto tags = getServerTags(server_selector); + if (tags.size() != 1) { + isc_throw(InvalidOperation, "expected exactly one server tag to be" + " specified while creating or updating option definition." + " Got: " << getServerTagsAsText(server_selector)); + } + ElementPtr record_types = Element::createList(); for (auto field : option_def->getRecordFields()) { record_types->add(Element::create(static_cast(field))); @@ -1554,6 +1580,20 @@ public: // If the option definition doesn't exist, let's insert it. conn_.insertQuery(MySqlConfigBackendDHCPv4Impl::INSERT_OPTION_DEF4, in_bindings); + + // Fetch unique identifier of the inserted option definition and use it + // as input to the next query. + uint64_t id = mysql_insert_id(conn_.mysql_); + + MySqlBindingCollection in_server_bindings = { + MySqlBinding::createInteger(id), // option_def_id + MySqlBinding::createString(*tags.begin()), // tag used to obtain server_id + MySqlBinding::createTimestamp(option_def->getModificationTime()), // modification_ts + }; + + // Insert association. + conn_.insertQuery(MySqlConfigBackendDHCPv4Impl::INSERT_OPTION_DEF4_SERVER, + in_server_bindings); } transaction.commit(); @@ -1566,10 +1606,17 @@ public: /// @param code Option code. /// @param name Option name. /// @return Number of deleted option definitions. - uint64_t deleteOptionDef4(const ServerSelector& /* server_selector */, + uint64_t deleteOptionDef4(const ServerSelector& server_selector, const uint16_t code, const std::string& space) { + auto tags = getServerTags(server_selector); + if (tags.size() != 1) { + isc_throw(InvalidOperation, "expected exactly one server tag to be" + " specified while deleting option definition. Got: " + << getServerTagsAsText(server_selector)); + } MySqlBindingCollection in_bindings = { + MySqlBinding::createString(*tags.begin()), MySqlBinding::createInteger(static_cast(code)), MySqlBinding::createString(space) }; @@ -2155,7 +2202,11 @@ TaggedStatementArray tagged_statements = { { " d.record_types," " d.user_context " "FROM dhcp4_option_def AS d " - "WHERE d.code = ? AND d.space = ? " + "INNER JOIN dhcp4_option_def_server AS a" + " ON d.id = a.option_def_id " + "INNER JOIN dhcp4_server AS s " + " ON (a.server_id = s.id) OR (a.server_id = 1) " + "WHERE (s.tag = ? OR s.id = 1) AND (d.code = ? AND d.space = ?) " "ORDER BY d.id" }, // Retrieves all option definitions. @@ -2172,6 +2223,11 @@ TaggedStatementArray tagged_statements = { { " d.record_types," " d.user_context " "FROM dhcp4_option_def AS d " + "INNER JOIN dhcp4_option_def_server AS a" + " ON d.id = a.option_def_id " + "INNER JOIN dhcp4_server AS s " + " ON (a.server_id = s.id) OR (a.server_id = 1) " + "WHERE (s.tag = ? OR s.id = 1) " "ORDER BY d.id" }, // Retrieves modified option definitions. @@ -2188,7 +2244,11 @@ TaggedStatementArray tagged_statements = { { " d.record_types," " d.user_context " "FROM dhcp4_option_def AS d " - "WHERE modification_ts > ? " + "INNER JOIN dhcp4_option_def_server AS a" + " ON d.id = a.option_def_id " + "INNER JOIN dhcp4_server AS s " + " ON (a.server_id = s.id) OR (a.server_id = 1) " + "WHERE (s.tag = ? OR s.id = 1) AND d.modification_ts > ? " "ORDER BY d.id" }, // Retrieves global option by code and space. @@ -2412,6 +2472,14 @@ TaggedStatementArray tagged_statements = { { "user_context" ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" }, + // Insert association of the option definition with a server. + { MySqlConfigBackendDHCPv4Impl::INSERT_OPTION_DEF4_SERVER, + "INSERT INTO dhcp4_option_def_server(" + " option_def_id," + " server_id," + " modification_ts" + ") VALUES (?, (SELECT id FROM dhcp4_server WHERE tag = ?), ?)" }, + // Insert subnet specific option. { MySqlConfigBackendDHCPv4Impl::INSERT_OPTION4, "INSERT INTO dhcp4_options (" @@ -2643,12 +2711,21 @@ TaggedStatementArray tagged_statements = { { // Delete option definition. { MySqlConfigBackendDHCPv4Impl::DELETE_OPTION_DEF4_CODE_NAME, - "DELETE FROM dhcp4_option_def " - "WHERE code = ? AND space = ?" }, + "DELETE d FROM dhcp4_option_def AS d " + "INNER JOIN dhcp4_option_def_server AS a" + " ON d.id = a.option_def_id " + "INNER JOIN dhcp4_server AS s" + " ON a.server_id = s.id " + "WHERE s.tag = ? AND code = ? AND space = ?" }, // Delete all option definitions. { MySqlConfigBackendDHCPv4Impl::DELETE_ALL_OPTION_DEFS4, - "DELETE FROM dhcp4_option_def" }, + "DELETE d FROM dhcp4_option_def AS d " + "INNER JOIN dhcp4_option_def_server AS a" + " ON d.id = a.option_def_id " + "INNER JOIN dhcp4_server AS s" + " ON a.server_id = s.id " + "WHERE s.tag = ?" }, // Delete single global option. { MySqlConfigBackendDHCPv4Impl::DELETE_OPTION4, @@ -2760,14 +2837,18 @@ MySqlConfigBackendDHCPv4::getOptionDef4(const ServerSelector& server_selector, OptionDefContainer MySqlConfigBackendDHCPv4::getAllOptionDefs4(const ServerSelector& server_selector) const { - return (impl_->getAllOptionDefs4(server_selector)); + OptionDefContainer option_defs; + impl_->getAllOptionDefs4(server_selector, option_defs); + return (option_defs); } OptionDefContainer MySqlConfigBackendDHCPv4:: getModifiedOptionDefs4(const ServerSelector& server_selector, const boost::posix_time::ptime& modification_time) const { - return (impl_->getModifiedOptionDefs4(server_selector, modification_time)); + OptionDefContainer option_defs; + impl_->getModifiedOptionDefs4(server_selector, modification_time, option_defs); + return (option_defs); } OptionDescriptorPtr @@ -2920,8 +3001,9 @@ MySqlConfigBackendDHCPv4::deleteOptionDef4(const ServerSelector& server_selector } uint64_t -MySqlConfigBackendDHCPv4::deleteAllOptionDefs4(const ServerSelector& /* server_selector */) { - return (impl_->deleteFromTable(MySqlConfigBackendDHCPv4Impl::DELETE_ALL_OPTION_DEFS4)); +MySqlConfigBackendDHCPv4::deleteAllOptionDefs4(const ServerSelector& server_selector) { + return (impl_->deleteFromTable(MySqlConfigBackendDHCPv4Impl::DELETE_ALL_OPTION_DEFS4, + server_selector)); } uint64_t 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 f6bbaaff86..b7bac61eaf 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 @@ -754,6 +754,13 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getOptionDef4) { test_option_defs_[1]->getCode(), test_option_defs_[1]->getOptionSpaceName()); EXPECT_TRUE(returned_option_def->equals(*option_def2)); + + // Fetching option definition for an explicitly specified server tag + // should succeed too. + returned_option_def = cbptr_->getOptionDef4(ServerSelector::ONE("server1"), + test_option_defs_[1]->getCode(), + test_option_defs_[1]->getOptionSpaceName()); + EXPECT_TRUE(returned_option_def->equals(*option_def2)); } // Test that all option definitions can be fetched. @@ -769,6 +776,11 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptionDefs4) { OptionDefContainer option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ALL()); ASSERT_EQ(test_option_defs_.size() - 1, option_defs.size()); + // All option definitions should also be returned for explicitly specified + // server tag. + option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ONE("server1")); + ASSERT_EQ(test_option_defs_.size() - 1, option_defs.size()); + // See if option definitions are returned ok. for (auto def = option_defs.begin(); def != option_defs.end(); ++def) { bool success = false; @@ -787,6 +799,15 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptionDefs4) { // All option definitions should be still there. ASSERT_EQ(test_option_defs_.size() - 1, option_defs.size()); + // Should not delete option definition for explicit server tag + // because our option definition is for all servers. + EXPECT_EQ(0, cbptr_->deleteOptionDef4(ServerSelector::ONE("server1"), + test_option_defs_[1]->getCode(), + test_option_defs_[1]->getOptionSpaceName())); + + // Same for all option definitions. + EXPECT_EQ(0, cbptr_->deleteAllOptionDefs4(ServerSelector::ONE("server1"))); + // Delete one of the option definitions and see if it is gone. EXPECT_EQ(1, cbptr_->deleteOptionDef4(ServerSelector::ALL(), test_option_defs_[2]->getCode(),