diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in index 65e955c805..8308708ef1 100644 --- a/src/bin/admin/tests/mysql_tests.sh.in +++ b/src/bin/admin/tests/mysql_tests.sh.in @@ -393,6 +393,18 @@ mysql_upgrade_13_to_14_test() { count=$(echo "${OUTPUT}" | grep -Eci 'UPDATE dhcp6_subnet SET shared_network_name = NULL') || true assert_eq 1 "${count}" "function func_dhcp6_shared_network_BDEL() is missing changed line. (expected count %d, returned %d)" + + # user_context should have been added to dhcp4_client_class + qry="select user_context from dhcp4_client_class limit 1;" + run_command \ + mysql_execute "${qry}" + assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + + # user_context should have been added to dhcp6_client_class + qry="select user_context from dhcp6_client_class limit 1;" + run_command \ + mysql_execute "${qry}" + assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" } mysql_upgrade_test() { diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc index c4db02c833..307a982bec 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc @@ -2368,6 +2368,7 @@ public: MySqlBinding::createInteger(), // depend on known directly MySqlBinding::createInteger(), // depend on known indirectly MySqlBinding::createTimestamp(), // modification_ts + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context MySqlBinding::createInteger(), // option def: id MySqlBinding::createInteger(), // option def: code MySqlBinding::createString(OPTION_NAME_BUF_LENGTH), // option def: name @@ -2459,35 +2460,41 @@ public: // modification_ts last_client_class->setModificationTime(out_bindings[12]->getTimestamp()); + // user_context + ElementPtr user_context = out_bindings[13]->getJSON(); + if (user_context) { + last_client_class->setContext(user_context); + } + class_list.push_back(last_client_class); } // server tag - if (!out_bindings[35]->amNull() && - (last_tag != out_bindings[35]->getString())) { - last_tag = out_bindings[35]->getString(); + if (!out_bindings[36]->amNull() && + (last_tag != out_bindings[36]->getString())) { + last_tag = out_bindings[36]->getString(); if (!last_tag.empty() && !last_client_class->hasServerTag(ServerTag(last_tag))) { last_client_class->setServerTag(last_tag); } } - // Parse client class specific option definition from 13 to 22. - if (!out_bindings[13]->amNull() && - (last_option_def_id < out_bindings[13]->getInteger())) { - last_option_def_id = out_bindings[13]->getInteger(); + // Parse client class specific option definition from 14 to 23. + if (!out_bindings[14]->amNull() && + (last_option_def_id < out_bindings[14]->getInteger())) { + last_option_def_id = out_bindings[14]->getInteger(); - auto def = processOptionDefRow(out_bindings.begin() + 13); + auto def = processOptionDefRow(out_bindings.begin() + 14); if (def) { last_client_class->getCfgOptionDef()->add(def); } } - // Parse client class specific option from 23 to 34. - if (!out_bindings[23]->amNull() && - (last_option_id < out_bindings[23]->getInteger())) { - last_option_id = out_bindings[23]->getInteger(); + // Parse client class specific option from 24 to 35. + if (!out_bindings[24]->amNull() && + (last_option_id < out_bindings[24]->getInteger())) { + last_option_id = out_bindings[24]->getInteger(); - OptionDescriptorPtr desc = processOptionRow(Option::V4, out_bindings.begin() + 23); + OptionDescriptorPtr desc = processOptionRow(Option::V4, out_bindings.begin() + 24); if (desc) { last_client_class->getCfgOption()->add(*desc, desc->space_name_); } @@ -2612,6 +2619,7 @@ public: (follow_class_name.empty() ? MySqlBinding::createNull() : MySqlBinding::createString(follow_class_name)), MySqlBinding::createTimestamp(client_class->getModificationTime()), + createInputContextBinding(client_class) }; MySqlTransaction transaction(conn_); @@ -3279,8 +3287,9 @@ TaggedStatementArray tagged_statements = { { " max_valid_lifetime," " depend_on_known_directly," " follow_class_name," - " modification_ts" - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + " modification_ts," + " user_context " + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" }, // Insert association of a client class with a server. diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc index 2c686b0cfc..83b37141a2 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc +++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc @@ -2808,6 +2808,7 @@ public: MySqlBinding::createInteger(), // depend on known directly MySqlBinding::createInteger(), // depend on known indirectly MySqlBinding::createTimestamp(), // modification_ts + MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context MySqlBinding::createInteger(), // option def: id MySqlBinding::createInteger(), // option def: code MySqlBinding::createString(OPTION_NAME_BUF_LENGTH), // option def: name @@ -2887,40 +2888,46 @@ public: // modification_ts last_client_class->setModificationTime(out_bindings[9]->getTimestamp()); + // user_context + ElementPtr user_context = out_bindings[10]->getJSON(); + if (user_context) { + last_client_class->setContext(user_context); + } + // preferred lifetime: default, min, max - last_client_class->setPreferred(createTriplet(out_bindings[33], - out_bindings[34], - out_bindings[35])); + last_client_class->setPreferred(createTriplet(out_bindings[34], + out_bindings[35], + out_bindings[36])); class_list.push_back(last_client_class); } // server tag - if (!out_bindings[32]->amNull() && - (last_tag != out_bindings[32]->getString())) { - last_tag = out_bindings[32]->getString(); + if (!out_bindings[33]->amNull() && + (last_tag != out_bindings[33]->getString())) { + last_tag = out_bindings[33]->getString(); if (!last_tag.empty() && !last_client_class->hasServerTag(ServerTag(last_tag))) { last_client_class->setServerTag(last_tag); } } - // Parse client class specific option definition from 10 to 19. - if (!out_bindings[10]->amNull() && - (last_option_def_id < out_bindings[10]->getInteger())) { - last_option_def_id = out_bindings[10]->getInteger(); + // Parse client class specific option definition from 11 to 20. + if (!out_bindings[11]->amNull() && + (last_option_def_id < out_bindings[11]->getInteger())) { + last_option_def_id = out_bindings[11]->getInteger(); - auto def = processOptionDefRow(out_bindings.begin() + 10); + auto def = processOptionDefRow(out_bindings.begin() + 11); if (def) { last_client_class->getCfgOptionDef()->add(def); } } - // Parse client class specific option from 20 to 31. - if (!out_bindings[20]->amNull() && - (last_option_id < out_bindings[20]->getInteger())) { - last_option_id = out_bindings[20]->getInteger(); + // Parse client class specific option from 21 to 32. + if (!out_bindings[21]->amNull() && + (last_option_id < out_bindings[21]->getInteger())) { + last_option_id = out_bindings[21]->getInteger(); - OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 20); + OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 21); if (desc) { last_client_class->getCfgOption()->add(*desc, desc->space_name_); } @@ -3045,6 +3052,7 @@ public: createMinBinding(client_class->getPreferred()), createMaxBinding(client_class->getPreferred()), MySqlBinding::createTimestamp(client_class->getModificationTime()), + createInputContextBinding(client_class) }; MySqlTransaction transaction(conn_); @@ -3730,8 +3738,9 @@ TaggedStatementArray tagged_statements = { { " preferred_lifetime," " min_preferred_lifetime," " max_preferred_lifetime," - " modification_ts" - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + " modification_ts, " + " user_context " + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" }, // Insert association of a client class with a server. 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 8e95f67840..f0525d44b3 100644 --- a/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h +++ b/src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h @@ -675,6 +675,7 @@ namespace { " c.depend_on_known_directly," \ " o.depend_on_known_indirectly, " \ " c.modification_ts," \ + " c.user_context," \ " d.id," \ " d.code," \ " d.name," \ @@ -737,6 +738,7 @@ namespace { " c.depend_on_known_directly," \ " o.depend_on_known_indirectly, " \ " c.modification_ts," \ + " c.user_context," \ " d.id," \ " d.code," \ " d.name," \ @@ -1073,7 +1075,8 @@ namespace { " max_valid_lifetime = ?," \ " depend_on_known_directly = ?," \ follow_class_name_set \ - " modification_ts = ? " \ + " modification_ts = ?, " \ + " user_context = ? " \ "WHERE name = ?" #endif @@ -1091,7 +1094,8 @@ namespace { " preferred_lifetime = ?, " \ " min_preferred_lifetime = ?, " \ " max_preferred_lifetime = ?, " \ - " modification_ts = ? " \ + " modification_ts = ?, " \ + " user_context = ? " \ "WHERE name = ?" #endif diff --git a/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc b/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc index 587a06bd84..18dde4ae88 100644 --- a/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc +++ b/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc @@ -386,6 +386,9 @@ GenericConfigBackendDHCPv4Test::initTestClientClasses() { class1->setSname("cool"); class1->setFilename("epc.cfg"); class1->setValid(Triplet(30, 60, 90)); + ElementPtr user_context = Element::createMap(); + user_context->set("melon", Element::create("water")); + class1->setContext(user_context); test_client_classes_.push_back(class1); auto class2 = boost::make_shared("bar", match_expr, cfg_option); diff --git a/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc b/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc index eae2097d70..7322d52d7a 100644 --- a/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc +++ b/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc @@ -422,6 +422,9 @@ GenericConfigBackendDHCPv6Test::initTestClientClasses() { class1->setValid(Triplet(30, 60, 90)); class1->setPreferred(Triplet(25, 55, 85)); test_client_classes_.push_back(class1); + ElementPtr user_context = Element::createMap(); + user_context->set("melon", Element::create("water")); + class1->setContext(user_context); auto class2 = boost::make_shared("bar", match_expr, cfg_option); class2->setCfgOptionDef(boost::make_shared()); diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql index 9cf1b9c3d0..c73e544ee1 100644 --- a/src/share/database/scripts/mysql/dhcpdb_create.mysql +++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql @@ -4344,6 +4344,10 @@ CREATE TRIGGER dhcp6_shared_network_BDEL BEFORE DELETE ON dhcp6_shared_network END $$ DELIMITER ; +-- Add user_context column to Client class tables. +ALTER TABLE dhcp4_client_class ADD COLUMN user_context LONGTEXT NULL; +ALTER TABLE dhcp6_client_class ADD COLUMN user_context LONGTEXT NULL; + -- Update the schema version number. UPDATE schema_version SET version = '14', minor = '0'; diff --git a/src/share/database/scripts/mysql/upgrade_013_to_014.sh.in b/src/share/database/scripts/mysql/upgrade_013_to_014.sh.in index 918995e6cf..ffba56e97b 100644 --- a/src/share/database/scripts/mysql/upgrade_013_to_014.sh.in +++ b/src/share/database/scripts/mysql/upgrade_013_to_014.sh.in @@ -110,6 +110,10 @@ CREATE TRIGGER dhcp6_shared_network_BDEL BEFORE DELETE ON dhcp6_shared_network END $$ DELIMITER ; +-- Add user_context column to Client class tables. +ALTER TABLE dhcp4_client_class ADD COLUMN user_context LONGTEXT NULL; +ALTER TABLE dhcp6_client_class ADD COLUMN user_context LONGTEXT NULL; + -- Update the schema version number. UPDATE schema_version SET version = '14', minor = '0';