From: Francis Dupont Date: Sat, 15 Jun 2019 19:07:26 +0000 (+0200) Subject: [659-how-configure-client-class-for-pools-in-db] Checkpoint: code done, todo new... X-Git-Tag: Kea-1.6.0~41^2~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c0be63572be8caa7addde50728520f8d504fcaef;p=thirdparty%2Fkea.git [659-how-configure-client-class-for-pools-in-db] Checkpoint: code done, todo new unit tests --- diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in index 6cf8264538..d0ae3ec1e6 100644 --- a/src/bin/admin/tests/mysql_tests.sh.in +++ b/src/bin/admin/tests/mysql_tests.sh.in @@ -709,6 +709,18 @@ EOF qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_subnet" run_statement "dhcp6_subnet" "$qry" + # table: dhcp4_pool (should include three new columns) + qry="select client_class, require_client_classes, user_context from dhcp4_pool" + run_statement "dhcp4_pool" "$qry" + + # table: dhcp6_pd_pool (should include five new columns) + qry="select excluded_prefix, excluded_prefix_length, client_class, require_client_classes, user_context from dhcp6_pd_pool" + run_statement "dhcp6_pd_pool" "$qry" + + # table: dhcp6_pool (should include three new columns) + qry="select client_class, require_client_classes, user_context from dhcp6_pool" + run_statement "dhcp6_pool" "$qry" + # Verify upgraded schema reports version 8.2 version=$(${keaadmin} db-version mysql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir) assert_str_eq "8.2" ${version} "Expected kea-admin to return %s, returned value was %s" diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc index 7bf1805164..fb70995b1b 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc @@ -306,6 +306,9 @@ public: MySqlBinding::createInteger(), // authoritative MySqlBinding::createInteger(), // min_valid_lifetime MySqlBinding::createInteger(), // max_valid_lifetime + MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class + MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag }; @@ -482,6 +485,10 @@ public: // {min,max}_valid_lifetime + // 3 pool fields + + // server_tag at 58 + // Subnet ready. Add it to the list. auto ret = subnets.push_back(last_subnet); @@ -494,9 +501,9 @@ public: } // Check for new server tags. - if (!out_bindings[55]->amNull() && - (last_tag != out_bindings[55]->getString())) { - last_tag = out_bindings[55]->getString(); + if (!out_bindings[58]->amNull() && + (last_tag != out_bindings[58]->getString())) { + last_tag = out_bindings[58]->getString(); if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) { last_subnet->setServerTag(last_tag); } @@ -512,6 +519,35 @@ public: last_pool_id = out_bindings[20]->getInteger(); last_pool = Pool4::create(IOAddress(out_bindings[21]->getInteger()), IOAddress(out_bindings[22]->getInteger())); + + // pool client_class + if (!out_bindings[55]->amNull()) { + last_pool->allowClientClass(out_bindings[55]->getString()); + } + + // pool require_client_classes + ElementPtr require_element = out_bindings[56]->getJSON(); + if (require_element) { + if (require_element->getType() != Element::list) { + isc_throw(BadValue, "invalid pool require_client_classes value " + << out_bindings[56]->getString()); + } + for (auto i = 0; i < require_element->size(); ++i) { + auto require_item = require_element->get(i); + if (require_item->getType() != Element::string) { + isc_throw(BadValue, "elements of pool require_client_classes list must" + "be valid strings"); + } + last_pool->requireClientClass(require_item->stringValue()); + } + } + + // pool user_context + ElementPtr user_context = out_bindings[57]->getJSON(); + if (user_context) { + last_pool->setContext(user_context); + } + last_subnet->addPool(last_pool); } @@ -689,6 +725,9 @@ public: MySqlBinding::createInteger(), // pool: start_address MySqlBinding::createInteger(), // pool: end_address MySqlBinding::createInteger(), // pool: subnet_id + MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class + MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context MySqlBinding::createTimestamp(), // pool: modification_ts MySqlBinding::createInteger(), // pool option: option_id MySqlBinding::createInteger(), // pool option: code @@ -718,16 +757,46 @@ public: last_pool = Pool4::create(IOAddress(out_bindings[1]->getInteger()), IOAddress(out_bindings[2]->getInteger())); + // pool client_class (4) + if (!out_bindings[4]->amNull()) { + last_pool->allowClientClass(out_bindings[4]->getString()); + } + + // pool require_client_classes (5) + ElementPtr require_element = out_bindings[5]->getJSON(); + if (require_element) { + if (require_element->getType() != Element::list) { + isc_throw(BadValue, "invalid pool require_client_classes value " + << out_bindings[5]->getString()); + } + for (auto i = 0; i < require_element->size(); ++i) { + auto require_item = require_element->get(i); + if (require_item->getType() != Element::string) { + isc_throw(BadValue, "elements of pool require_client_classes list must" + "be valid strings"); + } + last_pool->requireClientClass(require_item->stringValue()); + } + } + + // pool user_context (6) + ElementPtr user_context = out_bindings[6]->getJSON(); + if (user_context) { + last_pool->setContext(user_context); + } + + // pool: modification_ts (7) + pools.push_back(last_pool); pool_ids.push_back(last_pool_id); } - // Parse pool specific option. - if (last_pool && !out_bindings[5]->amNull() && - (last_pool_option_id < out_bindings[5]->getInteger())) { - last_pool_option_id = out_bindings[5]->getInteger(); + // Parse pool specific option (8). + if (last_pool && !out_bindings[8]->amNull() && + (last_pool_option_id < out_bindings[8]->getInteger())) { + last_pool_option_id = out_bindings[8]->getInteger(); - OptionDescriptorPtr desc = processOptionRow(Option::V4, out_bindings.begin() + 5); + OptionDescriptorPtr desc = processOptionRow(Option::V4, out_bindings.begin() + 8); if (desc) { last_pool->getCfgOption()->add(*desc, desc->space_name_); } @@ -952,6 +1021,9 @@ public: MySqlBinding::createInteger(pool->getFirstAddress().toUint32()), MySqlBinding::createInteger(pool->getLastAddress().toUint32()), MySqlBinding::createInteger(static_cast(subnet->getID())), + MySqlBinding::condCreateString(pool->getClientClass()), + createInputRequiredClassesBinding(pool), + createInputContextBinding(pool), MySqlBinding::createTimestamp(subnet->getModificationTime()) }; @@ -2123,6 +2195,9 @@ TaggedStatementArray tagged_statements = { { " p.start_address," " p.end_address," " p.subnet_id," + " p.client_class," + " p.require_client_classes," + " p.user_context," " p.modification_ts," " x.option_id," " x.code," diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc index c1c828348c..17acec5c1c 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc @@ -334,6 +334,14 @@ public: MySqlBinding::createInteger(), // max_preferred_lifetime MySqlBinding::createInteger(), // min_valid_lifetime MySqlBinding::createInteger(), // max_valid_lifetime + MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class + MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context + MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: excluded_prefix + MySqlBinding::createInteger(), // pd pool: excluded_prefix_length + MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pd pool: client_class + MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pd pool: require_client_classes + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool: user_context MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag }; @@ -373,10 +381,10 @@ public: // Reset last server tag as we're now starting to process new subnet. last_tag.clear(); - // subnet_id + // subnet_id (0) SubnetID subnet_id(out_bindings[0]->getInteger()); - // subnet_prefix + // subnet_prefix (1) std::string subnet_prefix = out_bindings[1]->getString(); auto prefix_pair = Subnet6::parsePrefix(subnet_prefix); @@ -385,10 +393,10 @@ public: out_bindings[69], out_bindings[70]); - // renew_timer + // renew_timer (9) auto renew_timer = createTriplet(out_bindings[9]); - // rebind_timer + // rebind_timer (7) auto rebind_timer = createTriplet(out_bindings[7]); // valid_lifetime (and {min,max)_valid_lifetime) @@ -402,28 +410,28 @@ public: preferred_lifetime, valid_lifetime, subnet_id); - // client_class + // client_class (2) if (!out_bindings[2]->amNull()) { last_subnet->allowClientClass(out_bindings[2]->getString()); } - // interface + // interface (3) if (!out_bindings[3]->amNull()) { last_subnet->setIface(out_bindings[3]->getString()); } - // modification_ts + // modification_ts (4) last_subnet->setModificationTime(out_bindings[4]->getTimestamp()); // 5 is preferred_lifetime - // rapid_commit + // rapid_commit (6) if (!out_bindings[6]->amNull()) { last_subnet->setRapidCommit(out_bindings[6]->getBool()); } // 7 is rebind_timer - // relay + // relay (8) ElementPtr relay_element = out_bindings[8]->getJSON(); if (relay_element) { if (relay_element->getType() != Element::list) { @@ -441,7 +449,7 @@ public: // 9 is renew_timer - // require_client_classes + // require_client_classes (10) ElementPtr require_element = out_bindings[10]->getJSON(); if (require_element) { if (require_element->getType() != Element::list) { @@ -458,18 +466,18 @@ public: } } - // reservation_mode + // reservation_mode (11) if (!out_bindings[11]->amNull()) { last_subnet->setHostReservationMode(static_cast (out_bindings[11]->getInteger())); } - // shared_network_name + // shared_network_name (12) if (!out_bindings[12]->amNull()) { last_subnet->setSharedNetworkName(out_bindings[12]->getString()); } - // user_context + // user_context (13) ElementPtr user_context = out_bindings[13]->getJSON(); if (user_context) { last_subnet->setContext(user_context); @@ -477,22 +485,22 @@ public: // 14 is valid_lifetime - // calculate_tee_times + // calculate_tee_times (65) if (!out_bindings[65]->amNull()) { last_subnet->setCalculateTeeTimes(out_bindings[65]->getBool()); } - // t1_percent + // t1_percent (66) if (!out_bindings[66]->amNull()) { last_subnet->setT1Percent(out_bindings[66]->getFloat()); } - // t2_percent + // t2_percent (67) if (!out_bindings[67]->amNull()) { last_subnet->setT2Percent(out_bindings[67]->getFloat()); } - // interface_id + // interface_id (68) if (!out_bindings[68]->amNull()) { auto iface_id_data = out_bindings[68]->getBlob(); if (!iface_id_data.empty()) { @@ -506,6 +514,10 @@ public: // 71 and 72 are {min,max}_valid_lifetime + // 8 pool and pd pool fields + + // server_tag (81 / last) + // Subnet ready. Add it to the list. auto ret = subnets.push_back(last_subnet); @@ -518,15 +530,15 @@ public: } // Check for new server tags. - if (!out_bindings[73]->amNull() && - (last_tag != out_bindings[73]->getString())) { - last_tag = out_bindings[73]->getString(); + if (!out_bindings[81]->amNull() && + (last_tag != out_bindings[81]->getString())) { + last_tag = out_bindings[81]->getString(); if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) { last_subnet->setServerTag(last_tag); } } - // Pool is between 15 and 19 + // Pool is between 15 and 19 with extra between 73 and 75 // If the row contains information about the pool and it // appears to be new pool entry (checked by comparing pool @@ -540,10 +552,38 @@ public: last_pool = Pool6::create(Lease::TYPE_NA, IOAddress(out_bindings[16]->getString()), IOAddress(out_bindings[17]->getString())); + // pool client_class (73) + if (!out_bindings[73]->amNull()) { + last_pool->allowClientClass(out_bindings[73]->getString()); + } + + // pool require_client_classes (74) + ElementPtr require_element = out_bindings[74]->getJSON(); + if (require_element) { + if (require_element->getType() != Element::list) { + isc_throw(BadValue, "invalid pool require_client_classes value " + << out_bindings[74]->getString()); + } + for (auto i = 0; i < require_element->size(); ++i) { + auto require_item = require_element->get(i); + if (require_item->getType() != Element::string) { + isc_throw(BadValue, "elements of pool require_client_classes list must" + "be valid strings"); + } + last_pool->requireClientClass(require_item->stringValue()); + } + } + + // pool user_context (75) + ElementPtr user_context = out_bindings[75]->getJSON(); + if (user_context) { + last_pool->setContext(user_context); + } + last_subnet->addPool(last_pool); } - // Pd Pool is between 20 and 25 + // Pd Pool is between 20 and 25 with extra between 76 and 80 // If the row contains information about the pd pool and // it appears to be new pd pool entry (checked by @@ -555,10 +595,45 @@ public: (out_bindings[23]->getInteger() != 0) && (out_bindings[20]->getInteger() > last_pd_pool_id)) { last_pd_pool_id = out_bindings[20]->getInteger(); - last_pd_pool = Pool6::create(Lease::TYPE_PD, - IOAddress(out_bindings[21]->getString()), + + // excluded_prefix (76) and excluded_prefix_length (77) + IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS(); + if (!out_bindings[76]->amNull()) { + excluded_prefix = IOAddress(out_bindings[76]->getString()); + } + last_pd_pool = Pool6::create(IOAddress(out_bindings[21]->getString()), out_bindings[22]->getInteger(), - out_bindings[23]->getInteger()); + out_bindings[23]->getInteger(), + excluded_prefix, + out_bindings[77]->getInteger()); + // pd pool client_class (78) + if (!out_bindings[78]->amNull()) { + last_pd_pool->allowClientClass(out_bindings[78]->getString()); + } + + // pd pool require_client_classes (79) + ElementPtr require_element = out_bindings[79]->getJSON(); + if (require_element) { + if (require_element->getType() != Element::list) { + isc_throw(BadValue, "invalid pd pool require_client_classes value " + << out_bindings[79]->getString()); + } + for (auto i = 0; i < require_element->size(); ++i) { + auto require_item = require_element->get(i); + if (require_item->getType() != Element::string) { + isc_throw(BadValue, "elements of pd pool require_client_classes list must" + "be valid strings"); + } + last_pd_pool->requireClientClass(require_item->stringValue()); + } + } + + // pd pool user_context (80) + ElementPtr user_context = out_bindings[80]->getJSON(); + if (user_context) { + last_pd_pool->setContext(user_context); + } + last_subnet->addPool(last_pd_pool); } @@ -746,6 +821,9 @@ public: MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pool: start_address MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pool: end_address MySqlBinding::createInteger(), // pool: subnet_id + MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class + MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context MySqlBinding::createTimestamp(), // pool: modification_ts MySqlBinding::createInteger(), // pool option: option_id MySqlBinding::createInteger(), // pool option: code @@ -777,16 +855,46 @@ public: last_pool = Pool6::create(Lease::TYPE_NA, IOAddress(out_bindings[1]->getString()), IOAddress(out_bindings[2]->getString())); + // pool client_class (4) + if (!out_bindings[4]->amNull()) { + last_pool->allowClientClass(out_bindings[4]->getString()); + } + + // pool require_client_classes (5) + ElementPtr require_element = out_bindings[5]->getJSON(); + if (require_element) { + if (require_element->getType() != Element::list) { + isc_throw(BadValue, "invalid pool require_client_classes value " + << out_bindings[5]->getString()); + } + for (auto i = 0; i < require_element->size(); ++i) { + auto require_item = require_element->get(i); + if (require_item->getType() != Element::string) { + isc_throw(BadValue, "elements of pool require_client_classes list must" + "be valid strings"); + } + last_pool->requireClientClass(require_item->stringValue()); + } + } + + // pool user_context (6) + ElementPtr user_context = out_bindings[6]->getJSON(); + if (user_context) { + last_pool->setContext(user_context); + } + + // pool: modification_ts (7) + pools.push_back(last_pool); pool_ids.push_back(last_pool_id); } - // Parse pool specific option. - if (last_pool && !out_bindings[5]->amNull() && - (last_pool_option_id < out_bindings[5]->getInteger())) { - last_pool_option_id = out_bindings[5]->getInteger(); + // Parse pool specific option (8). + if (last_pool && !out_bindings[8]->amNull() && + (last_pool_option_id < out_bindings[8]->getInteger())) { + last_pool_option_id = out_bindings[8]->getInteger(); - OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 5); + OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 8); if (desc) { last_pool->getCfgOption()->add(*desc, desc->space_name_); } @@ -817,6 +925,11 @@ public: MySqlBinding::createInteger(), // pd pool: prefix_length MySqlBinding::createInteger(), // pd pool: delegated_prefix_length MySqlBinding::createInteger(), // pd pool: subnet_id + MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: excluded_prefix + MySqlBinding::createInteger(), // pd pool: excluded_prefix_length + MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pd pool: client_class + MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pd pool: require_client_classes + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool: user_context MySqlBinding::createTimestamp(), // pd pool: modification_ts MySqlBinding::createInteger(), // pd pool option: option_id MySqlBinding::createInteger(), // pd pool option: code @@ -845,20 +958,58 @@ public: last_pd_pool_id = out_bindings[0]->getInteger(); - last_pd_pool = Pool6::create(Lease::TYPE_PD, - IOAddress(out_bindings[1]->getString()), + // excluded_prefix (5) and excluded_prefix_length (6) + IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS(); + if (!out_bindings[5]->amNull()) { + excluded_prefix = IOAddress(out_bindings[5]->getString()); + } + + last_pd_pool = Pool6::create(IOAddress(out_bindings[1]->getString()), out_bindings[2]->getInteger(), - out_bindings[3]->getInteger()); + out_bindings[3]->getInteger(), + excluded_prefix, + out_bindings[6]->getInteger()); + + // pd pool client_class (7) + if (!out_bindings[7]->amNull()) { + last_pd_pool->allowClientClass(out_bindings[7]->getString()); + } + + // pd pool require_client_classes (8) + ElementPtr require_element = out_bindings[8]->getJSON(); + if (require_element) { + if (require_element->getType() != Element::list) { + isc_throw(BadValue, "invalid pd pool require_client_classes value " + << out_bindings[8]->getString()); + } + for (auto i = 0; i < require_element->size(); ++i) { + auto require_item = require_element->get(i); + if (require_item->getType() != Element::string) { + isc_throw(BadValue, "elements of pd pool require_client_classes list must" + "be valid strings"); + } + last_pd_pool->requireClientClass(require_item->stringValue()); + } + } + + // pool user_context (9) + ElementPtr user_context = out_bindings[9]->getJSON(); + if (user_context) { + last_pd_pool->setContext(user_context); + } + + // pd pool user_context (10) + pd_pools.push_back(last_pd_pool); pd_pool_ids.push_back(last_pd_pool_id); } - // Parse pool specific option between 6 and 19 - if (last_pd_pool && !out_bindings[6]->amNull() && - (last_pd_pool_option_id < out_bindings[6]->getInteger())) { - last_pd_pool_option_id = out_bindings[6]->getInteger(); + // Parse pd pool specific option between 11 and 24 + if (last_pd_pool && !out_bindings[11]->amNull() && + (last_pd_pool_option_id < out_bindings[11]->getInteger())) { + last_pd_pool_option_id = out_bindings[11]->getInteger(); - OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 6); + OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 11); if (desc) { last_pd_pool->getCfgOption()->add(*desc, desc->space_name_); } @@ -1104,6 +1255,9 @@ public: MySqlBinding::createString(pool->getFirstAddress().toText()), MySqlBinding::createString(pool->getLastAddress().toText()), MySqlBinding::createInteger(static_cast(subnet->getID())), + MySqlBinding::condCreateString(pool->getClientClass()), + createInputRequiredClassesBinding(pool), + createInputContextBinding(pool), MySqlBinding::createTimestamp(subnet->getModificationTime()) }; @@ -1133,11 +1287,28 @@ public: const Subnet6Ptr& subnet) { int plen = prefixLengthFromRange(pd_pool->getFirstAddress(), pd_pool->getLastAddress()); + + // Extract excluded prefix components. + Optional xprefix_txt; + uint8_t xlen = 0; + const Option6PDExcludePtr& xopt = pd_pool->getPrefixExcludeOption(); + if (xopt) { + const IOAddress& prefix = pd_pool->getFirstAddress(); + const IOAddress& xprefix = xopt->getExcludedPrefix(prefix, plen); + xprefix_txt = xprefix.toText(); + xlen = xopt->getExcludedPrefixLength(); + } + MySqlBindingCollection in_bindings = { MySqlBinding::createString(pd_pool->getFirstAddress().toText()), MySqlBinding::createInteger(static_cast(plen)), MySqlBinding::createInteger(pd_pool->getLength()), MySqlBinding::createInteger(static_cast(subnet->getID())), + MySqlBinding::condCreateString(xprefix_txt), + MySqlBinding::createInteger(xlen), + MySqlBinding::condCreateString(pd_pool->getClientClass()), + createInputRequiredClassesBinding(pd_pool), + createInputContextBinding(pd_pool), MySqlBinding::createTimestamp(subnet->getModificationTime()) }; @@ -2453,6 +2624,9 @@ TaggedStatementArray tagged_statements = { { " p.start_address," " p.end_address," " p.subnet_id," + " p.client_class," + " p.require_client_classes," + " p.user_context," " p.modification_ts," " x.option_id," " x.code," @@ -2481,6 +2655,11 @@ TaggedStatementArray tagged_statements = { { " p.prefix_length," " p.delegated_prefix_length," " p.subnet_id," + " p.excluded_prefix," + " p.excluded_prefix_length," + " p.client_class," + " p.require_client_classes," + " p.user_context," " p.modification_ts," " x.option_id," " x.code," diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc index d2ec66a266..b3a9a32a5e 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc @@ -932,22 +932,6 @@ MySqlConfigBackendImpl::createInputRelayBinding(const NetworkPtr& network) { MySqlBinding::condCreateString(relay_element->str())); } -MySqlBindingPtr -MySqlConfigBackendImpl::createInputRequiredClassesBinding(const NetworkPtr& network) { - // Create JSON list of required classes. - ElementPtr required_classes_element = Element::createList(); - const auto& required_classes = network->getRequiredClasses(); - for (auto required_class = required_classes.cbegin(); - required_class != required_classes.cend(); - ++required_class) { - required_classes_element->add(Element::create(*required_class)); - } - - return (required_classes_element ? - MySqlBinding::createString(required_classes_element->str()) : - MySqlBinding::createNull()); -} - MySqlBindingPtr MySqlConfigBackendImpl::createOptionValueBinding(const OptionDescriptorPtr& option) { OptionPtr opt = option->option_; diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_impl.h b/src/hooks/dhcp/mysql_cb/mysql_cb_impl.h index 461c7670a2..d2e3c6f987 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_impl.h +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_impl.h @@ -575,11 +575,26 @@ public: /// @brief Creates input binding for 'require_client_classes' parameter. /// - /// @param network Pointer to a shared network or subnet for which binding - /// should be created. + /// @tparam T of pointer to objects with getRequiredClasses + /// method, e.g. shared network, subnet, pool or prefix delegation pool. + /// @param object Pointer to an object with getRequiredClasses method /// @return Pointer to the binding (possibly null binding if there are no /// required classes specified). - db::MySqlBindingPtr createInputRequiredClassesBinding(const NetworkPtr& network); + template + db::MySqlBindingPtr createInputRequiredClassesBinding(const T& object) { + // Create JSON list of required classes. + data::ElementPtr required_classes_element = data::Element::createList(); + const auto& required_classes = object->getRequiredClasses(); + for (auto required_class = required_classes.cbegin(); + required_class != required_classes.cend(); + ++required_class) { + required_classes_element->add(data::Element::create(*required_class)); + } + + return (required_classes_element ? + db::MySqlBinding::createString(required_classes_element->str()) : + db::MySqlBinding::createNull()); + } /// @brief Creates input binding for user context parameter. /// 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 7eb8a8a8e0..9670890ede 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h +++ b/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h @@ -106,6 +106,9 @@ namespace { " s.authoritative," \ " s.min_valid_lifetime," \ " s.max_valid_lifetime," \ + " p.client_class," \ + " p.require_client_classes," \ + " p.user_context," \ " srv.tag " \ "FROM dhcp4_subnet AS s " \ server_join \ @@ -217,6 +220,14 @@ namespace { " s.max_preferred_lifetime," \ " s.min_valid_lifetime," \ " s.max_valid_lifetime," \ + " p.client_class," \ + " p.require_client_classes," \ + " p.user_context," \ + " d.excluded_prefix," \ + " d.excluded_prefix_length," \ + " d.client_class," \ + " d.require_client_classes," \ + " d.user_context," \ " srv.tag " \ "FROM dhcp6_subnet AS s " \ server_join \ @@ -518,8 +529,11 @@ namespace { " start_address," \ " end_address," \ " subnet_id," \ + " client_class," \ + " require_client_classes," \ + " user_context," \ " modification_ts" \ - ") VALUES (?, ?, ?, ?)" + ") VALUES (?, ?, ?, ?, ?, ?, ?)" #endif #ifndef MYSQL_INSERT_PD_POOL @@ -529,8 +543,13 @@ namespace { " prefix_length," \ " delegated_prefix_length," \ " subnet_id," \ + " excluded_prefix," \ + " excluded_prefix_length," \ + " client_class," \ + " require_client_classes," \ + " user_context," \ " modification_ts" \ - ") VALUES (?, ?, ?, ?, ?)" + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" #endif #ifndef MYSQL_INSERT_SHARED_NETWORK_SERVER diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql index 7fae77ac53..d2d71c176a 100644 --- a/src/share/database/scripts/mysql/dhcpdb_create.mysql +++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql @@ -2476,6 +2476,24 @@ END $$ DELIMITER ; +# add missing fields in pools. +ALTER TABLE dhcp4_pool + ADD COLUMN client_class VARCHAR(128) DEFAULT NULL, + ADD COLUMN require_client_classes LONGTEXT, + ADD COLUMN user_context LONGTEXT; + +ALTER TABLE dhcp6_pd_pool + ADD COLUMN excluded_prefix VARCHAR(45) DEFAULT NULL, + ADD COLUMN excluded_prefix_length TINYINT(3) NOT NULL, + ADD COLUMN client_class VARCHAR(128) DEFAULT NULL, + ADD COLUMN require_client_classes LONGTEXT, + ADD COLUMN user_context LONGTEXT; + +ALTER TABLE dhcp6_pool + ADD COLUMN client_class VARCHAR(128) DEFAULT NULL, + ADD COLUMN require_client_classes LONGTEXT, + ADD COLUMN user_context LONGTEXT; + # Update the schema version number UPDATE schema_version SET version = '8', minor = '2'; diff --git a/src/share/database/scripts/mysql/upgrade_8.1_to_8.2.sh.in b/src/share/database/scripts/mysql/upgrade_8.1_to_8.2.sh.in index fed3be3aec..dbdc5a02da 100644 --- a/src/share/database/scripts/mysql/upgrade_8.1_to_8.2.sh.in +++ b/src/share/database/scripts/mysql/upgrade_8.1_to_8.2.sh.in @@ -117,6 +117,24 @@ END $$ DELIMITER ; +# add missing fields in pools. +ALTER TABLE dhcp4_pool + ADD COLUMN client_class VARCHAR(128) DEFAULT NULL, + ADD COLUMN require_client_classes LONGTEXT, + ADD COLUMN user_context LONGTEXT; + +ALTER TABLE dhcp6_pd_pool + ADD COLUMN excluded_prefix VARCHAR(45) DEFAULT NULL, + ADD COLUMN excluded_prefix_length TINYINT(3) NOT NULL, + ADD COLUMN client_class VARCHAR(128) DEFAULT NULL, + ADD COLUMN require_client_classes LONGTEXT, + ADD COLUMN user_context LONGTEXT; + +ALTER TABLE dhcp6_pool + ADD COLUMN client_class VARCHAR(128) DEFAULT NULL, + ADD COLUMN require_client_classes LONGTEXT, + ADD COLUMN user_context LONGTEXT; + # Update the schema version number UPDATE schema_version SET version = '8', minor = '2';