From: Marcin Siodelski Date: Wed, 26 Sep 2018 16:54:09 +0000 (+0200) Subject: [#93,!35] Implemented fetching option definitions from the database. X-Git-Tag: 5-netconf-extend-syntax_base~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e74bc092e0b0113adcb198bed81ce63140d9f41d;p=thirdparty%2Fkea.git [#93,!35] Implemented fetching option definitions from the database. --- diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in index 303f82ec2e..e62136b1b3 100644 --- a/src/bin/admin/tests/mysql_tests.sh.in +++ b/src/bin/admin/tests/mysql_tests.sh.in @@ -494,7 +494,7 @@ EOF run_statement "dhcp4_global_parameter_server" "$qry" # table: dhcp4_option_def - qry="select id, code, space, modification_ts, array, encapsulate, record_types, user_context from dhcp4_option_def" + qry="select id, code, name, space, type, modification_ts, array, encapsulate, record_types, user_context from dhcp4_option_def" run_statement "dhcp4_option_def" "$qry" # table: dhcp4_option_def_server @@ -546,7 +546,7 @@ EOF run_statement "dhcp6_global_parameter_server" "$qry" # table: dhcp6_option_def - qry="select id, code, space, modification_ts, array, encapsulate, record_types, user_context from dhcp6_option_def" + qry="select id, code, name, space, type, modification_ts, array, encapsulate, record_types, user_context from dhcp6_option_def" run_statement "dhcp6_option_def" "$qry" # table: dhcp6_option_def_server diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc index 6e962fc6b1..88667acc86 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -48,11 +49,16 @@ public: GET_SHARED_NETWORK4_NAME, GET_ALL_SHARED_NETWORKS4, GET_MODIFIED_SHARED_NETWORKS4, + GET_OPTION_DEF4_CODE_SPACE, + GET_ALL_OPTION_DEFS4, + GET_MODIFIED_OPTION_DEFS4, INSERT_SUBNET4, INSERT_POOL4, INSERT_SHARED_NETWORK4, + INSERT_OPTION_DEF4, UPDATE_SUBNET4, UPDATE_SHARED_NETWORK4, + UPDATE_OPTION_DEF4, DELETE_POOLS4_SUBNET_ID, NUM_STATEMENTS }; @@ -322,12 +328,6 @@ public: (shared_network ? MySqlBinding::createString(shared_network->getName()) : MySqlBinding::createNull()); - // Create user context binding if user context exists. - auto context_element = subnet->getContext(); - MySqlBindingPtr context_binding = - (context_element ? MySqlBinding::createString(context_element->str()) : - MySqlBinding::createNull()); - // Create input bindings. MySqlBindingCollection in_bindings = { MySqlBinding::createInteger(subnet->getID()), @@ -348,7 +348,7 @@ public: MySqlBinding::createInteger(static_cast(subnet->getHostReservationMode())), MySqlBinding::condCreateString(subnet->getSname()), shared_network_binding, - context_binding, + createInputContextBinding(subnet), MySqlBinding::createInteger(subnet->getValid()) }; @@ -452,6 +452,7 @@ public: if ((last_network_id == 0) || (last_network_id != out_bindings[0]->getInteger())) { + last_network_id = out_bindings[0]->getInteger(); last_network.reset(new SharedNetwork4(out_bindings[1]->getString())); // client_class @@ -587,7 +588,171 @@ public: conn_.insertQuery(MySqlConfigBackendDHCPv4Impl::INSERT_SHARED_NETWORK4, in_bindings); } + } + + /// @brief Sends query to the database to retrieve multiple option + /// definitions. + /// + /// Query should order option definitions by id. + /// + /// @param index Index of the query to be used. + /// @param in_bindings Input bindings specifying selection criteria. The + /// size of the bindings collection must match the number of placeholders + /// in the prepared statement. The input bindings collection must be empty + /// if the query contains no WHERE clause. + /// @param [out] option_defs Reference to the container where fetched + /// option definitions will be inserted. + void getOptionDefs4(const StatementIndex& index, + const MySqlBindingCollection& in_bindings, + OptionDefContainer& option_defs) { + // Create output bindings. The order must match that in the prepared + // statement. + MySqlBindingCollection out_bindings = { + MySqlBinding::createInteger(), // id + MySqlBinding::createInteger(), // code + MySqlBinding::createString(128), // name + MySqlBinding::createString(128), // space + MySqlBinding::createInteger(), // type + MySqlBinding::createTimestamp(), // modification_ts + MySqlBinding::createInteger(), // array + MySqlBinding::createString(128), // encapsulate + MySqlBinding::createString(512), // record_types + MySqlBinding::createString(65536) // user_context + }; + + uint64_t last_def_id = 0; + + // Run select query. + conn_.selectQuery(index, in_bindings, out_bindings, + [&option_defs, &last_def_id] + (MySqlBindingCollection& out_bindings) { + // Get pointer to last fetched option definition. + OptionDefinitionPtr last_def; + if (!option_defs.empty()) { + last_def = *option_defs.rbegin(); + } + + // See if the last fetched definition is the one for which we now got + // the row of data. If not, it means that we need to create new option + // definition. + if ((last_def_id == 0) || + (last_def_id != out_bindings[0]->getInteger())) { + + last_def_id = out_bindings[0]->getInteger(); + + // Check array type, because depending on this value we have to use + // different constructor. + bool array_type = static_cast(out_bindings[6]->getInteger()); + if (array_type) { + // Create array option. + last_def.reset(new OptionDefinition(out_bindings[2]->getString(), + out_bindings[1]->getInteger(), + static_cast + (out_bindings[4]->getInteger()), + array_type)); + } else { + // Create non-array option. + last_def.reset(new OptionDefinition(out_bindings[2]->getString(), + out_bindings[1]->getInteger(), + static_cast + (out_bindings[4]->getInteger()), + out_bindings[7]->getStringOrDefault("").c_str())); + } + + // space + last_def->setOptionSpaceName(out_bindings[3]->getStringOrDefault("")); + + // record_types + ElementPtr record_types_element = out_bindings[8]->getJSON(); + if (record_types_element) { + if (record_types_element->getType() != Element::list) { + isc_throw(BadValue, "invalid record_types value " + << out_bindings[8]->getString()); + } + // This element must contain a list of integers specifying + // types of the record fields. + for (auto i = 0; i < record_types_element->size(); ++i) { + auto type_element = record_types_element->get(i); + if (type_element->getType() != Element::integer) { + isc_throw(BadValue, "record type values must be integers"); + } + last_def->addRecordField(static_cast + (type_element->intValue())); + } + } + + // Update modification time. + last_def->setModificationTime(out_bindings[5]->getTimestamp()); + + // Store created option definition. + option_defs.push_back(last_def); + } + }); + } + + /// @brief Sends query to retrieve single option definition by code and + /// option space. + /// + /// @param selector Server selector. + /// @param code Option code. + /// @param space Option space name. + /// + /// @return Pointer to the returned option definition or NULL if such + /// option definition doesn't exist. + OptionDefinitionPtr getOptionDef4(const ServerSelector& selector, + const uint16_t code, + const std::string& space) { + OptionDefContainer option_defs; + MySqlBindingCollection in_bindings = { + MySqlBinding::createInteger(static_cast(code)), + MySqlBinding::createString(space) + }; + getOptionDefs4(GET_OPTION_DEF4_CODE_SPACE, in_bindings, option_defs); + return (option_defs.empty() ? OptionDefinitionPtr() : *option_defs.begin()); + } + + /// @brief Sends query to insert or update option definition. + /// + /// @param selector Server selector. + /// @param option_def Pointer to the option definition to be inserted or updated. + void createUpdateOptionDef4(const ServerSelector& selector, + const OptionDefinitionPtr& option_def) { + ElementPtr record_types = Element::createList(); + for (auto field : option_def->getRecordFields()) { + record_types->add(Element::create(static_cast(field))); + } + MySqlBindingPtr record_types_binding = record_types->empty() ? + MySqlBinding::createNull() : MySqlBinding::createString(record_types->str()); + MySqlBindingCollection in_bindings = { + MySqlBinding::createInteger(static_cast(option_def->getCode())), + MySqlBinding::createString(option_def->getName()), + MySqlBinding::createString(option_def->getOptionSpaceName().empty() ? + "dhcp4" : option_def->getOptionSpaceName()), + MySqlBinding::createInteger(static_cast(option_def->getType())), + MySqlBinding::createTimestamp(option_def->getModificationTime()), + MySqlBinding::createInteger(static_cast(option_def->getArrayType())), + MySqlBinding::createString(option_def->getEncapsulatedSpace()), + record_types_binding, + createInputContextBinding(option_def) + }; + + // If the shared network exists we are going to update this network. + OptionDefinitionPtr existing_definition = getOptionDef4(selector, + option_def->getCode(), + option_def->getOptionSpaceName()); + if (existing_definition) { + // Need to add two more bindings for WHERE clause. + in_bindings.push_back(MySqlBinding::createInteger(existing_definition->getCode())); + in_bindings.push_back(MySqlBinding::createString(existing_definition->getOptionSpaceName())); + conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::UPDATE_OPTION_DEF4, + in_bindings); + + } else { + // If the option definition doesn't exist, let's insert it. + conn_.insertQuery(MySqlConfigBackendDHCPv4Impl::INSERT_OPTION_DEF4, + in_bindings); + } } /// @brief Creates input binding for relay addresses. @@ -632,13 +797,14 @@ public: /// @brief Creates input binding for user context parameter. /// - /// @param network Pointer to a shared network or subnet for which binding - /// should be created. + /// @param network Pointer to a shared network, subnet or other configuration + /// element for which binding should be created. /// @return Pointer to the binding (possibly null binding if context is /// null). - MySqlBindingPtr createInputContextBinding(const NetworkPtr& network) { + template + MySqlBindingPtr createInputContextBinding(const T& config_element) { // Create user context binding if user context exists. - auto context_element = network->getContext(); + auto context_element = config_element->getContext(); return (context_element ? MySqlBinding::createString(context_element->str()) : MySqlBinding::createNull()); } @@ -844,6 +1010,56 @@ TaggedStatementArray tagged_statements = { { "WHERE n.modification_ts > ? " "ORDER BY n.id" }, + // Retrieves option definition by code and space. + { MySqlConfigBackendDHCPv4Impl::GET_OPTION_DEF4_CODE_SPACE, + "SELECT" + " d.id," + " d.code," + " d.name," + " d.space," + " d.type," + " d.modification_ts," + " d.array," + " d.encapsulate," + " d.record_types," + " d.user_context " + "FROM dhcp4_option_def AS d " + "WHERE d.code = ? AND d.space = ? " + "ORDER BY d.id" }, + + // Retrieves all option definitions. + { MySqlConfigBackendDHCPv4Impl::GET_ALL_OPTION_DEFS4, + "SELECT" + " d.id," + " d.code," + " d.name," + " d.space," + " d.type," + " d.modification_ts," + " d.array," + " d.encapsulate," + " d.record_types," + " d.user_context " + "FROM dhcp4_option_def AS d " + "ORDER BY d.id" }, + + // Retrieves modified option definitions. + { MySqlConfigBackendDHCPv4Impl::GET_MODIFIED_OPTION_DEFS4, + "SELECT" + " d.id," + " d.code," + " d.name," + " d.space," + " d.type," + " d.modification_ts," + " d.array," + " d.encapsulate," + " d.record_types," + " d.user_context " + "FROM dhcp4_option_def AS d " + "WHERE modification_ts > ? " + "ORDER BY d.id" }, + // Insert a subnet. { MySqlConfigBackendDHCPv4Impl::INSERT_SUBNET4, "INSERT INTO dhcp4_subnet(" @@ -870,6 +1086,7 @@ TaggedStatementArray tagged_statements = { { ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," "?, ?, ?, ?, ?, ?, ?, ?)" }, + // Insert pool for a subnet. { MySqlConfigBackendDHCPv4Impl::INSERT_POOL4, "INSERT INTO dhcp4_pool(" " start_address," @@ -895,6 +1112,20 @@ TaggedStatementArray tagged_statements = { { "valid_lifetime" ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" }, + // Insert option definition. + { MySqlConfigBackendDHCPv4Impl::INSERT_OPTION_DEF4, + "INSERT INTO dhcp4_option_def (" + "code," + "name," + "space," + "type," + "modification_ts," + "array," + "encapsulate," + "record_types," + "user_context" + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" }, + // Update existing subnet. { MySqlConfigBackendDHCPv4Impl::UPDATE_SUBNET4, "UPDATE dhcp4_subnet SET" @@ -937,6 +1168,20 @@ TaggedStatementArray tagged_statements = { { " valid_lifetime = ? " "WHERE name = ?" }, + // Update existing option definition. + { MySqlConfigBackendDHCPv4Impl::UPDATE_OPTION_DEF4, + "UPDATE dhcp4_option_def SET" + " code = ?," + " name = ?," + " space = ?," + " type = ?," + " modification_ts = ?," + " array = ?," + " encapsulate = ?," + " record_types = ?," + " user_context = ? " + "WHERE code = ? AND space = ?" }, + // Delete pools for a subnet. { MySqlConfigBackendDHCPv4Impl::DELETE_POOLS4_SUBNET_ID, "DELETE FROM dhcp4_pool " @@ -1063,19 +1308,29 @@ OptionDefinitionPtr MySqlConfigBackendDHCPv4::getOptionDef4(const ServerSelector& selector, const uint16_t code, const std::string& space) const { - isc_throw(NotImplemented, "not implemented"); + return (impl_->getOptionDef4(selector, code, space)); } OptionDefContainer MySqlConfigBackendDHCPv4::getAllOptionDefs4(const ServerSelector& selector) const { - isc_throw(NotImplemented, "not implemented"); + OptionDefContainer option_defs; + MySqlBindingCollection in_bindings; + impl_->getOptionDefs4(MySqlConfigBackendDHCPv4Impl::GET_ALL_OPTION_DEFS4, + in_bindings, option_defs); + return (option_defs); } OptionDefContainer MySqlConfigBackendDHCPv4:: getModifiedOptionDefs4(const ServerSelector& selector, const boost::posix_time::ptime& modification_time) const { - isc_throw(NotImplemented, "not implemented"); + OptionDefContainer option_defs; + MySqlBindingCollection in_bindings = { + MySqlBinding::createTimestamp(modification_time) + }; + impl_->getOptionDefs4(MySqlConfigBackendDHCPv4Impl::GET_MODIFIED_OPTION_DEFS4, + in_bindings, option_defs); + return (option_defs); } util::OptionalValue @@ -1110,6 +1365,7 @@ MySqlConfigBackendDHCPv4::createUpdateSharedNetwork4(const ServerSelector& selec void MySqlConfigBackendDHCPv4::createUpdateOptionDef4(const ServerSelector& selector, const OptionDefinitionPtr& option_def) { + impl_->createUpdateOptionDef4(selector, option_def); } void 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 8c24f78c2b..62f5798bf7 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 @@ -51,6 +51,7 @@ public: // Create test data. initTestSubnets(); initTestSharedNetworks(); + initTestOptionDefs(); initTimestamps(); } @@ -147,6 +148,31 @@ public: test_networks_.push_back(shared_network); } + /// @brief Creates several option definitions used in tests. + void initTestOptionDefs() { + ElementPtr user_context = Element::createMap(); + user_context->set("foo", Element::create("bar")); + + OptionDefinitionPtr option_def(new OptionDefinition("foo", 234, "string", + "espace")); + option_def->setOptionSpaceName("dhcp4"); + test_option_defs_.push_back(option_def); + + option_def.reset(new OptionDefinition("bar", 234, "uint32", true)); + option_def->setOptionSpaceName("dhcp4"); + test_option_defs_.push_back(option_def); + + option_def.reset(new OptionDefinition("fish", 235, "record", true)); + option_def->setOptionSpaceName("dhcp4"); + option_def->addRecordField("uint32"); + option_def->addRecordField("string"); + test_option_defs_.push_back(option_def); + + option_def.reset(new OptionDefinition("whale", 236, "string")); + option_def->setOptionSpaceName("xyz"); + test_option_defs_.push_back(option_def); + } + /// @brief Initialize posix time values used in tests. void initTimestamps() { // Current time minus 1 hour to make sure it is in the past. @@ -164,6 +190,9 @@ public: /// @brief Holds pointers to shared networks used in tests. std::vector test_networks_; + /// @brief Holds pointers to option definitions used in tests. + std::vector test_option_defs_; + /// @brief Holds timestamp values used in tests. std::map timestamps_; @@ -352,5 +381,95 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSharedNetworks4) { ASSERT_TRUE(networks.empty()); } +// Test that subnet can be inserted, fetched, updated and then fetched again. +TEST_F(MySqlConfigBackendDHCPv4Test, getOptionDef4) { + // Insert new option definition. + OptionDefinitionPtr option_def = test_option_defs_[0]; + cbptr_->createUpdateOptionDef4(ServerSelector::UNASSIGNED(), option_def); + + // Fetch this option_definition by subnet identifier. + OptionDefinitionPtr returned_option_def = + cbptr_->getOptionDef4(ServerSelector::UNASSIGNED(), + test_option_defs_[0]->getCode(), + test_option_defs_[0]->getOptionSpaceName()); + ASSERT_TRUE(returned_option_def); + + EXPECT_TRUE(returned_option_def->equals(*option_def)); + + // Update the option definition in the database. + OptionDefinitionPtr option_def2 = test_option_defs_[1]; + cbptr_->createUpdateOptionDef4(ServerSelector::UNASSIGNED(), option_def2); + + // Fetch updated option definition and see if it matches. + returned_option_def = cbptr_->getOptionDef4(ServerSelector::UNASSIGNED(), + test_option_defs_[1]->getCode(), + test_option_defs_[1]->getOptionSpaceName()); + EXPECT_TRUE(returned_option_def->equals(*option_def2)); +} + +// Test that all shared networks can be fetched. +TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptionDefs4) { + // Insert test option definitions into the database. Note that the second + // option definition will overwrite the first option definition as they use + // the same code and space. + for (auto option_def : test_option_defs_) { + cbptr_->createUpdateOptionDef4(ServerSelector::UNASSIGNED(), option_def); + } + + // Fetch all option_definitions. + OptionDefContainer option_defs = cbptr_->getAllOptionDefs4(ServerSelector::UNASSIGNED()); + 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; + for (auto i = 1; i < test_option_defs_.size(); ++i) { + if ((*def)->equals(*test_option_defs_[i])) { + success = true; + } + } + ASSERT_TRUE(success) << "failed for option definition " << (*def)->getCode() + << ", option space " << (*def)->getOptionSpaceName(); + } +} + +// Test that option definitions modified after given time can be fetched. +TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedOptionDefinitions4) { + // Explicitly set timestamps of option definitions. First option + // definition has a timestamp pointing to the future. Second option + // definition has timestamp pointing to the past (yesterday). + // Third option definitions has a timestamp pointing to the + // past (an hour ago). + test_option_defs_[1]->setModificationTime(timestamps_["tomorrow"]); + test_option_defs_[2]->setModificationTime(timestamps_["yesterday"]); + test_option_defs_[3]->setModificationTime(timestamps_["today"]); + + // Insert option definitions into the database. + for (int i = 1; i < test_networks_.size(); ++i) { + cbptr_->createUpdateOptionDef4(ServerSelector::UNASSIGNED(), + test_option_defs_[i]); + } + + // Fetch option definitions with timestamp later than today. Only one + // option definition should be returned. + OptionDefContainer + option_defs = cbptr_->getModifiedOptionDefs4(ServerSelector::UNASSIGNED(), + timestamps_["today"]); + ASSERT_EQ(1, option_defs.size()); + + // Fetch option definitions with timestamp later than yesterday. We + // should get two option definitions. + option_defs = cbptr_->getModifiedOptionDefs4(ServerSelector::UNASSIGNED(), + timestamps_["yesterday"]); + ASSERT_EQ(2, option_defs.size()); + + // Fetch option definitions with timestamp later than tomorrow. Nothing + // should be returned. + option_defs = cbptr_->getModifiedOptionDefs4(ServerSelector::UNASSIGNED(), + timestamps_["tomorrow"]); + ASSERT_TRUE(option_defs.empty()); +} + + } diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc index 4f77621a33..b353286477 100644 --- a/src/lib/dhcp/option_definition.cc +++ b/src/lib/dhcp/option_definition.cc @@ -48,7 +48,10 @@ OptionDefinition::OptionDefinition(const std::string& name, code_(code), type_(OPT_UNKNOWN_TYPE), array_type_(array_type), - encapsulated_space_("") { + encapsulated_space_(""), + record_fields_(), + user_context_(), + option_space_name_() { // Data type is held as enum value by this class. // Use the provided option type string to get the // corresponding enum value. @@ -77,7 +80,10 @@ OptionDefinition::OptionDefinition(const std::string& name, // corresponding enum value. type_(OptionDataTypeUtil::getDataType(type)), array_type_(false), - encapsulated_space_(encapsulated_space) { + encapsulated_space_(encapsulated_space), + record_fields_(), + user_context_(), + option_space_name_() { } OptionDefinition::OptionDefinition(const std::string& name, @@ -88,7 +94,10 @@ OptionDefinition::OptionDefinition(const std::string& name, code_(code), type_(type), array_type_(false), - encapsulated_space_(encapsulated_space) { + encapsulated_space_(encapsulated_space), + record_fields_(), + user_context_(), + option_space_name_() { } bool @@ -98,7 +107,8 @@ OptionDefinition::equals(const OptionDefinition& other) const { type_ == other.type_ && array_type_ == other.array_type_ && encapsulated_space_ == other.encapsulated_space_ && - record_fields_ == other.record_fields_); + record_fields_ == other.record_fields_ && + option_space_name_ == other.option_space_name_); } void diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h index 21e021de05..076b96187b 100644 --- a/src/lib/dhcp/option_definition.h +++ b/src/lib/dhcp/option_definition.h @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -133,7 +134,7 @@ class OptionIntArray; /// @todo Extend this class to use custom namespaces. /// @todo Extend this class with more factory functions. /// @todo Derive from UserContext without breaking the multi index. -class OptionDefinition { +class OptionDefinition : public data::StampedElement { public: /// List of fields within the record. @@ -307,6 +308,32 @@ public: user_context_.contextToElement(map); } + /// @brief Returns option space name. + /// + /// Option definitions are associated with option spaces. Typically, + /// such association is made when the option definition is put into + /// the @c CfgOptionDef structure. However, in some cases it is also + /// required to associate option definition with the particular option + /// space outside of that structure. In particular, when the option + /// definition is fetched from a database. The database configuration + /// backend will set option space upon return of the option definition. + /// In other cases this value won't be set. + /// + /// @return Option space name or empty string if option space + /// name is not set. + std::string getOptionSpaceName() const { + return (option_space_name_); + } + + /// @brief Sets option space name for option definition. + /// + /// See @c getOptionSpaceName to learn when option space name is set. + /// + /// @param option_space_name New option space name. + void setOptionSpaceName(const std::string& option_space_name) { + option_space_name_ = option_space_name; + } + /// @brief Check if the option definition is valid. /// /// Note that it is a responsibility of the code that created @@ -733,6 +760,8 @@ private: RecordFieldsCollection record_fields_; /// User context data::UserContext user_context_; + /// Option space name + std::string option_space_name_; }; diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql index fcec8e1779..6c7511d5b7 100644 --- a/src/share/database/scripts/mysql/dhcpdb_create.mysql +++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql @@ -857,7 +857,9 @@ CREATE TABLE IF NOT EXISTS dhcp4_global_parameter_server ( CREATE TABLE IF NOT EXISTS dhcp4_option_def ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, code TINYINT(3) UNSIGNED NOT NULL, + name VARCHAR(128) NOT NULL, space VARCHAR(128) NOT NULL, + type TINYINT UNSIGNED NOT NULL, modification_ts TIMESTAMP NOT NULL, array TINYINT(1) NOT NULL, encapsulate VARCHAR(128) NOT NULL, @@ -1005,7 +1007,7 @@ ALTER TABLE dhcp4_options MODIFY option_id BIGINT(20) UNSIGNED NOT NULL AUTO_INC ALTER TABLE dhcp4_options ADD COLUMN shared_network_name VARCHAR(128) DEFAULT NULL, ADD COLUMN pool_id BIGINT(20) UNSIGNED DEFAULT NULL, - ADD COLUMN modification_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; + ADD COLUMN modification_ts TIMESTAMP NOT NULL; -- ----------------------------------------------------- -- Table `dhcp4_options_server` @@ -1096,7 +1098,9 @@ CREATE TABLE IF NOT EXISTS dhcp6_global_parameter_server ( CREATE TABLE IF NOT EXISTS dhcp6_option_def ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, code TINYINT(3) UNSIGNED NOT NULL, + name VARCHAR(128) NOT NULL, space VARCHAR(128) NOT NULL, + type TINYINT UNSIGNED NOT NULL, modification_ts TIMESTAMP NOT NULL, array TINYINT(1) NOT NULL, encapsulate VARCHAR(128) NOT NULL, @@ -1258,7 +1262,7 @@ ALTER TABLE dhcp6_options ADD COLUMN shared_network_name VARCHAR(128) DEFAULT NULL, ADD COLUMN pool_id BIGINT(20) UNSIGNED DEFAULT NULL, ADD COLUMN pd_pool_id BIGINT(20) UNSIGNED DEFAULT NULL, - ADD COLUMN modification_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; + ADD COLUMN modification_ts TIMESTAMP NOT NULL; -- ----------------------------------------------------- -- Table `dhcp6_options_server` diff --git a/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in b/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in index fcb10c2d31..9549d40355 100644 --- a/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in +++ b/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in @@ -192,6 +192,7 @@ CREATE TABLE IF NOT EXISTS dhcp4_global_parameter_server ( CREATE TABLE IF NOT EXISTS dhcp4_option_def ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, code TINYINT(3) UNSIGNED NOT NULL, + name VARCHAR(128) NOT NULL, space VARCHAR(128) NOT NULL, modification_ts TIMESTAMP NOT NULL, array TINYINT(1) NOT NULL, @@ -333,7 +334,7 @@ ALTER TABLE dhcp4_options MODIFY option_id BIGINT(20) UNSIGNED NOT NULL AUTO_INC ALTER TABLE dhcp4_options ADD COLUMN shared_network_name VARCHAR(128) DEFAULT NULL, ADD COLUMN pool_id BIGINT(20) UNSIGNED DEFAULT NULL, - ADD COLUMN modification_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; + ADD COLUMN modification_ts TIMESTAMP NOT NULL; # Create table dhcp4_options_server # M-to-M cross-reference between options and servers @@ -417,6 +418,7 @@ CREATE TABLE IF NOT EXISTS dhcp6_global_parameter_server ( CREATE TABLE IF NOT EXISTS dhcp6_option_def ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, code TINYINT(3) UNSIGNED NOT NULL, + name VARCHAR(128) NOT NULL, space VARCHAR(128) NOT NULL, modification_ts TIMESTAMP NOT NULL, array TINYINT(1) NOT NULL, @@ -569,7 +571,7 @@ ALTER TABLE dhcp6_options ADD COLUMN shared_network_name VARCHAR(128) DEFAULT NULL, ADD COLUMN pool_id BIGINT(20) UNSIGNED DEFAULT NULL, ADD COLUMN pd_pool_id BIGINT(20) UNSIGNED DEFAULT NULL, - ADD COLUMN modification_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; + ADD COLUMN modification_ts TIMESTAMP NOT NULL; # Create table dhcp6_options_server # M-to-M cross-reference between options and servers