From bc3ea9d7d11ae14e1f76ea60487977c04801290d Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Wed, 29 Nov 2017 08:09:49 +0100 Subject: [PATCH] [5351] Added global and option def --- src/bin/dhcp4/dhcp4_lexer.ll | 4 ++ src/bin/dhcp4/dhcp4_parser.yy | 4 ++ src/bin/dhcp4/json_config_parser.cc | 13 ++++++- src/bin/dhcp4/tests/config_parser_unittest.cc | 38 ++++++++++++++++++- .../dhcp4/tests/shared_network_unittest.cc | 6 +-- src/bin/dhcp6/dhcp6_lexer.ll | 4 ++ src/bin/dhcp6/dhcp6_parser.yy | 4 ++ src/bin/dhcp6/json_config_parser.cc | 15 ++++++-- src/bin/dhcp6/tests/config_parser_unittest.cc | 38 ++++++++++++++++++- src/lib/cc/Makefile.am | 5 ++- src/lib/{dhcpsrv => cc}/user_context.cc | 2 +- src/lib/{dhcpsrv => cc}/user_context.h | 0 src/lib/dhcp/option_definition.h | 25 ++++++++++++ src/lib/dhcpsrv/Makefile.am | 2 - src/lib/dhcpsrv/cfg_option_def.cc | 5 ++- src/lib/dhcpsrv/network.h | 2 +- src/lib/dhcpsrv/parsers/dhcp_parsers.cc | 11 +++--- src/lib/dhcpsrv/pool.h | 2 +- src/lib/dhcpsrv/srv_config.cc | 2 + src/lib/dhcpsrv/srv_config.h | 3 +- src/lib/dhcpsrv/subnet.h | 2 +- .../dhcpsrv/tests/cfg_option_def_unittest.cc | 3 ++ 22 files changed, 161 insertions(+), 29 deletions(-) rename src/lib/{dhcpsrv => cc}/user_context.cc (96%) rename src/lib/{dhcpsrv => cc}/user_context.h (100%) diff --git a/src/bin/dhcp4/dhcp4_lexer.ll b/src/bin/dhcp4/dhcp4_lexer.ll index 34e68a1eef..823d87f6e3 100644 --- a/src/bin/dhcp4/dhcp4_lexer.ll +++ b/src/bin/dhcp4/dhcp4_lexer.ll @@ -578,9 +578,11 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"user-context\" { switch(driver.ctx_) { + case isc::dhcp::Parser4Context::DHCP4: case isc::dhcp::Parser4Context::SUBNET4: case isc::dhcp::Parser4Context::POOLS: case isc::dhcp::Parser4Context::SHARED_NETWORK: + case isc::dhcp::Parser4Context::OPTION_DEF: return isc::dhcp::Dhcp4Parser::make_USER_CONTEXT(driver.loc_); default: return isc::dhcp::Dhcp4Parser::make_STRING("user-context", driver.loc_); @@ -589,9 +591,11 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"comment\" { switch(driver.ctx_) { + case isc::dhcp::Parser4Context::DHCP4: case isc::dhcp::Parser4Context::SUBNET4: case isc::dhcp::Parser4Context::POOLS: case isc::dhcp::Parser4Context::SHARED_NETWORK: + case isc::dhcp::Parser4Context::OPTION_DEF: return isc::dhcp::Dhcp4Parser::make_COMMENT(driver.loc_); default: return isc::dhcp::Dhcp4Parser::make_STRING("comment", driver.loc_); diff --git a/src/bin/dhcp4/dhcp4_parser.yy b/src/bin/dhcp4/dhcp4_parser.yy index cd174dc4d9..5b65a7bfa2 100644 --- a/src/bin/dhcp4/dhcp4_parser.yy +++ b/src/bin/dhcp4/dhcp4_parser.yy @@ -433,6 +433,8 @@ global_param: valid_lifetime | next_server | server_hostname | boot_file_name + | user_context + | comment | unknown_map_entry ; @@ -1136,6 +1138,8 @@ option_def_param: option_def_name | option_def_space | option_def_encapsulate | option_def_array + | user_context + | comment | unknown_map_entry ; diff --git a/src/bin/dhcp4/json_config_parser.cc b/src/bin/dhcp4/json_config_parser.cc index 31ce8ec87b..d0cf070db3 100644 --- a/src/bin/dhcp4/json_config_parser.cc +++ b/src/bin/dhcp4/json_config_parser.cc @@ -69,6 +69,7 @@ public: /// - echo-client-id /// - decline-probation-period /// - dhcp4o6-port + /// - user-context /// /// @throw DhcpConfigError if parameters are missing or /// or having incorrect values. @@ -87,6 +88,12 @@ public: // Set the DHCPv4-over-DHCPv6 interserver port. uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port"); cfg->setDhcp4o6Port(dhcp4o6_port); + + // Set the global user context. + ConstElementPtr user_context = global->get("user-context"); + if (user_context) { + cfg->setContext(user_context); + } } /// @brief Copies subnets from shared networks to regular subnets container @@ -445,8 +452,9 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set, // Timers are not used in the global scope. Their values are derived // to specific subnets (see SimpleParser6::deriveParameters). - // decline-probation-period, dhcp4o6-port, echo-client-id are - // handled in global_parser.parse() which sets global parameters. + // decline-probation-period, dhcp4o6-port, echo-client-id, + // user-context are handled in global_parser.parse() which + // sets global parameters. // match-client-id is derived to subnet scope level. if ( (config_pair.first == "renew-timer") || (config_pair.first == "rebind-timer") || @@ -454,6 +462,7 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set, (config_pair.first == "decline-probation-period") || (config_pair.first == "dhcp4o6-port") || (config_pair.first == "echo-client-id") || + (config_pair.first == "user-context") || (config_pair.first == "match-client-id") || (config_pair.first == "next-server") || (config_pair.first == "server-hostname") || diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc index 1a8cb35ee4..fcea2b5b00 100644 --- a/src/bin/dhcp4/tests/config_parser_unittest.cc +++ b/src/bin/dhcp4/tests/config_parser_unittest.cc @@ -5611,9 +5611,17 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) { TEST_F(Dhcp4ParserTest, comments) { string config = "{\n" + "\"comment\": \"A DHCPv4 server\",\n" + "\"option-def\": [ {\n" + " \"name\": \"foo\",\n" + " \"code\": 100,\n" + " \"comment\": \"An option definition\",\n" + " \"type\": \"ipv4-address\",\n" + " \"space\": \"isc\"\n" + " } ],\n" "\"shared-networks\": [ {\n" " \"name\": \"foo\"\n," - " \"comment\": \"A shared-network\"\n," + " \"comment\": \"A shared network\"\n," " \"subnet4\": [\n" " { \n" " \"subnet\": \"192.0.1.0/24\",\n" @@ -5632,6 +5640,32 @@ TEST_F(Dhcp4ParserTest, comments) { extractConfig(config); configure(config, CONTROL_RESULT_SUCCESS, ""); + // Check global user context. + ConstElementPtr ctx = CfgMgr::instance().getStagingCfg()->getContext(); + ASSERT_TRUE(ctx); + ASSERT_EQ(1, ctx->size()); + ASSERT_TRUE(ctx->get("comment")); + EXPECT_EQ("\"A DHCPv4 server\"", ctx->get("comment")->str()); + + // Make the option definition available. + LibDHCP::commitRuntimeOptionDefs(); + + // Get and verify the option definition. + OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100); + ASSERT_TRUE(opt_def); + EXPECT_EQ("foo", opt_def->getName()); + EXPECT_EQ(1, opt_def->getCode()); + EXPECT_FALSE(opt_def->getArrayType()); + EXPECT_EQ(OPT_IPV4_ADDRESS_TYPE, opt_def->getType()); + EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty()); + + // Check option definition user context + ConstElementPtr ctx_opt_def = opt_def->getContext(); + ASSERT_TRUE(ctx_opt_def); + ASSERT_EQ(1, ctx_opt_def->size()); + ASSERT_TRUE(ctx_opt_def->get("comment")); + EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str()); + // Now verify that the shared network was indeed configured. CfgSharedNetworks4Ptr cfg_net = CfgMgr::instance().getStagingCfg() ->getCfgSharedNetworks4(); @@ -5647,7 +5681,7 @@ TEST_F(Dhcp4ParserTest, comments) { ASSERT_TRUE(ctx_net); ASSERT_EQ(1, ctx_net->size()); ASSERT_TRUE(ctx_net->get("comment")); - EXPECT_EQ("\"A shared-network\"", ctx_net->get("comment")->str()); + EXPECT_EQ("\"A shared network\"", ctx_net->get("comment")->str()); // The shared network has a subnet. const Subnet4Collection * subs = net->getAllSubnets(); diff --git a/src/bin/dhcp4/tests/shared_network_unittest.cc b/src/bin/dhcp4/tests/shared_network_unittest.cc index 58dae25098..c5c47007da 100644 --- a/src/bin/dhcp4/tests/shared_network_unittest.cc +++ b/src/bin/dhcp4/tests/shared_network_unittest.cc @@ -1081,9 +1081,9 @@ TEST_F(Dhcpv4SharedNetworkTest, parse) { ConstElementPtr comment = config::parseAnswer(rcode, status); ASSERT_EQ(0, rcode); ASSERT_NO_THROW( { - CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess(); - cfg_db->setAppendedParameters("universe=4"); - cfg_db->createManagers(); + CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess(); + cfg_db->setAppendedParameters("universe=4"); + cfg_db->createManagers(); } ); CfgMgr::instance().commit(); diff --git a/src/bin/dhcp6/dhcp6_lexer.ll b/src/bin/dhcp6/dhcp6_lexer.ll index bd6421250b..785481fa2e 100644 --- a/src/bin/dhcp6/dhcp6_lexer.ll +++ b/src/bin/dhcp6/dhcp6_lexer.ll @@ -808,10 +808,12 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"user-context\" { switch(driver.ctx_) { + case isc::dhcp::Parser6Context::DHCP6: case isc::dhcp::Parser6Context::POOLS: case isc::dhcp::Parser6Context::PD_POOLS: case isc::dhcp::Parser6Context::SUBNET6: case isc::dhcp::Parser6Context::SHARED_NETWORK: + case isc::dhcp::Parser6Context::OPTION_DEF: return isc::dhcp::Dhcp6Parser::make_USER_CONTEXT(driver.loc_); default: return isc::dhcp::Dhcp6Parser::make_STRING("user-context", driver.loc_); @@ -820,10 +822,12 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"comment\" { switch(driver.ctx_) { + case isc::dhcp::Parser6Context::DHCP6: case isc::dhcp::Parser6Context::POOLS: case isc::dhcp::Parser6Context::PD_POOLS: case isc::dhcp::Parser6Context::SUBNET6: case isc::dhcp::Parser6Context::SHARED_NETWORK: + case isc::dhcp::Parser6Context::OPTION_DEF: return isc::dhcp::Dhcp6Parser::make_COMMENT(driver.loc_); default: return isc::dhcp::Dhcp6Parser::make_STRING("comment", driver.loc_); diff --git a/src/bin/dhcp6/dhcp6_parser.yy b/src/bin/dhcp6/dhcp6_parser.yy index 2cec6de1ce..4ed697666c 100644 --- a/src/bin/dhcp6/dhcp6_parser.yy +++ b/src/bin/dhcp6/dhcp6_parser.yy @@ -435,6 +435,8 @@ global_param: preferred_lifetime | dhcp4o6_port | control_socket | dhcp_ddns + | user_context + | comment | unknown_map_entry ; @@ -1100,6 +1102,8 @@ option_def_param: option_def_name | option_def_space | option_def_encapsulate | option_def_array + | user_context + | comment | unknown_map_entry ; diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index f536154c99..d74dab56cf 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -144,6 +144,7 @@ public: /// /// - decline-probation-period /// - dhcp4o6-port + /// - user-context /// /// @throw DhcpConfigError if parameters are missing or /// or having incorrect values. @@ -157,6 +158,12 @@ public: // Set the DHCPv4-over-DHCPv6 interserver port. uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port"); srv_config->setDhcp4o6Port(dhcp4o6_port); + + // Set the global user context. + ConstElementPtr user_context = global->get("user-context"); + if (user_context) { + srv_config->setContext(user_context); + } } /// @brief Copies subnets from shared networks to regular subnets container @@ -557,14 +564,16 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set, // Timers are not used in the global scope. Their values are derived // to specific subnets (see SimpleParser6::deriveParameters). - // decline-probation-period and dhcp4o6-port are handled in the - // global_parser.parse() which sets global parameters. + // decline-probation-period, dhcp4o6-port and user-context + // are handled in the global_parser.parse() which sets + // global parameters. if ( (config_pair.first == "renew-timer") || (config_pair.first == "rebind-timer") || (config_pair.first == "preferred-lifetime") || (config_pair.first == "valid-lifetime") || (config_pair.first == "decline-probation-period") || - (config_pair.first == "dhcp4o6-port")) { + (config_pair.first == "dhcp4o6-port") || + (config_pair.first == "user-context")) { continue; } diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index d6f9073d06..03ac7fdd40 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -6053,9 +6053,17 @@ TEST_F(Dhcp6ParserTest, sharedNetworksRapidCommitMix) { TEST_F(Dhcp6ParserTest, comments) { string config = "{\n" + "\"comment\": \"A DHCPv6 server\",\n" + "\"option-def\": [ {\n" + " \"name\": \"foo\",\n" + " \"code\": 100,\n" + " \"comment\": \"An option definition\",\n" + " \"type\": \"ipv6-address\",\n" + " \"space\": \"isc\"\n" + " } ],\n" "\"shared-networks\": [ {\n" " \"name\": \"foo\"\n," - " \"comment\": \"A shared-network\"\n," + " \"comment\": \"A shared network\"\n," " \"subnet6\": [\n" " { \n" " \"subnet\": \"2001:db1::/48\",\n" @@ -6082,6 +6090,32 @@ TEST_F(Dhcp6ParserTest, comments) { extractConfig(config); configure(config, CONTROL_RESULT_SUCCESS, ""); + // Check global user context + ConstElementPtr ctx = CfgMgr::instance().getStagingCfg()->getContext(); + ASSERT_TRUE(ctx); + ASSERT_EQ(1, ctx->size()); + ASSERT_TRUE(ctx->get("comment")); + EXPECT_EQ("\"A DHCPv6 server\"", ctx->get("comment")->str()); + + // Make the option definition available. + LibDHCP::commitRuntimeOptionDefs(); + + // Get and verify the option definition. + OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100); + ASSERT_TRUE(opt_def); + EXPECT_EQ("foo", opt_def->getName()); + EXPECT_EQ(1, opt_def->getCode()); + EXPECT_FALSE(opt_def->getArrayType()); + EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, opt_def->getType()); + EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty()); + + // Check option definition user context + ConstElementPtr ctx_opt_def = opt_def->getContext(); + ASSERT_TRUE(ctx_opt_def); + ASSERT_EQ(1, ctx_opt_def->size()); + ASSERT_TRUE(ctx_opt_def->get("comment")); + EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str()); + // Now verify that the shared network was indeed configured. CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg() ->getCfgSharedNetworks6(); @@ -6097,7 +6131,7 @@ TEST_F(Dhcp6ParserTest, comments) { ASSERT_TRUE(ctx_net); ASSERT_EQ(1, ctx_net->size()); ASSERT_TRUE(ctx_net->get("comment")); - EXPECT_EQ("\"A shared-network\"", ctx_net->get("comment")->str()); + EXPECT_EQ("\"A shared network\"", ctx_net->get("comment")->str()); // The shared network has a subnet. const Subnet6Collection * subs = net->getAllSubnets(); diff --git a/src/lib/cc/Makefile.am b/src/lib/cc/Makefile.am index 7031653e73..5a0f578959 100644 --- a/src/lib/cc/Makefile.am +++ b/src/lib/cc/Makefile.am @@ -10,6 +10,7 @@ libkea_cc_la_SOURCES += cfg_to_element.h dhcp_config_error.h libkea_cc_la_SOURCES += command_interpreter.cc command_interpreter.h libkea_cc_la_SOURCES += json_feed.cc json_feed.h libkea_cc_la_SOURCES += simple_parser.cc simple_parser.h +libkea_cc_la_SOURCES += user_context.cc user_context.h libkea_cc_la_LIBADD = $(top_builddir)/src/lib/util/libkea-util.la libkea_cc_la_LIBADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la @@ -26,8 +27,8 @@ libkea_cc_include_HEADERS = \ data.h \ dhcp_config_error.h \ json_feed.h \ - simple_parser.h - + simple_parser.h \ + user_context.h EXTRA_DIST = cc.dox diff --git a/src/lib/dhcpsrv/user_context.cc b/src/lib/cc/user_context.cc similarity index 96% rename from src/lib/dhcpsrv/user_context.cc rename to src/lib/cc/user_context.cc index f6d273c506..e7086d4f4a 100644 --- a/src/lib/dhcpsrv/user_context.cc +++ b/src/lib/cc/user_context.cc @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include +#include using namespace isc::data; diff --git a/src/lib/dhcpsrv/user_context.h b/src/lib/cc/user_context.h similarity index 100% rename from src/lib/dhcpsrv/user_context.h rename to src/lib/cc/user_context.h diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h index affe5397d4..02e49f7c15 100644 --- a/src/lib/dhcp/option_definition.h +++ b/src/lib/dhcp/option_definition.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -131,6 +132,7 @@ class OptionIntArray; /// @todo Extend the comment to describe "generic factories". /// @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 { public: @@ -284,6 +286,27 @@ public: /// @return option data type. OptionDataType getType() const { return (type_); }; + /// @brief Returns const pointer to the user context + data::ConstElementPtr getContext() const { + return (user_context_.getContext()); + } + + /// @brief Sets user context. + /// @param ctx user context to be stored. + void setContext(const data::ConstElementPtr& ctx) { + user_context_.setContext(ctx); + } + + /// @brief Merge unparse a user_context object. + /// + /// Add user-context to map, but only if defined. Omit if it was not. + /// Extract comment so it will be pretty-printed first. + /// + /// @param map A pointer to map where the user context will be unparsed. + void contextToElement(data::ElementPtr map) const { + user_context_.contextToElement(map); + } + /// @brief Check if the option definition is valid. /// /// Note that it is a responsibility of the code that created @@ -708,6 +731,8 @@ private: std::string encapsulated_space_; /// Collection of data fields within the record. RecordFieldsCollection record_fields_; + /// User context + UserContext user_context_; }; diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am index 82197774f6..cc3e148634 100644 --- a/src/lib/dhcpsrv/Makefile.am +++ b/src/lib/dhcpsrv/Makefile.am @@ -159,7 +159,6 @@ libkea_dhcpsrv_la_SOURCES += subnet_id.h libkea_dhcpsrv_la_SOURCES += subnet_selector.h libkea_dhcpsrv_la_SOURCES += timer_mgr.cc timer_mgr.h libkea_dhcpsrv_la_SOURCES += triplet.h -libkea_dhcpsrv_la_SOURCES += user_context.cc user_context.h libkea_dhcpsrv_la_SOURCES += utils.h libkea_dhcpsrv_la_SOURCES += writable_host_data_source.h @@ -296,7 +295,6 @@ libkea_dhcpsrv_include_HEADERS = \ subnet_selector.h \ timer_mgr.h \ triplet.h \ - user_context.h \ utils.h \ writable_host_data_source.h diff --git a/src/lib/dhcpsrv/cfg_option_def.cc b/src/lib/dhcpsrv/cfg_option_def.cc index 3a61bb1ef6..42a9226767 100644 --- a/src/lib/dhcpsrv/cfg_option_def.cc +++ b/src/lib/dhcpsrv/cfg_option_def.cc @@ -166,7 +166,9 @@ CfgOptionDef::toElement() const { def != defs->end(); ++def) { // Get and fill the map for this definition ElementPtr map = Element::createMap(); - // First set space from parent iterator + // Set user context + (*def)->contextToElement(map); + // Set space from parent iterator map->set("space", Element::create(*name)); // Set required items: name, code and type map->set("name", Element::create((*def)->getName())); @@ -204,6 +206,5 @@ CfgOptionDef::toElement() const { return (result); } - } // end of namespace isc::dhcp } // end of namespace isc diff --git a/src/lib/dhcpsrv/network.h b/src/lib/dhcpsrv/network.h index bd211ae1f6..11cd5264bb 100644 --- a/src/lib/dhcpsrv/network.h +++ b/src/lib/dhcpsrv/network.h @@ -10,12 +10,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index a2926ecf06..06b97e4858 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -84,12 +84,6 @@ void ControlSocketParser::parse(SrvConfig& srv_cfg, isc::data::ConstElementPtr v srv_cfg.setControlSocketInfo(value); } - - - - - - template OptionDefinitionPtr OptionDataParser::findOptionDefinition(const std::string& option_space, @@ -132,6 +126,7 @@ OptionDefParser::parse(ConstElementPtr option_def) { std::string record_types = getString(option_def, "record-types"); std::string space = getString(option_def, "space"); std::string encapsulates = getString(option_def, "encapsulate"); + ConstElementPtr user_context = option_def->get("user-context"); if (!OptionSpace::validateName(space)) { isc_throw(DhcpConfigError, "invalid option space name '" @@ -168,6 +163,10 @@ OptionDefParser::parse(ConstElementPtr option_def) { } + if (user_context) { + def->setContext(user_context); + } + // Split the list of record types into tokens. std::vector record_tokens = isc::util::str::tokens(record_types, ","); diff --git a/src/lib/dhcpsrv/pool.h b/src/lib/dhcpsrv/pool.h index 55d4235fe3..5bdefceccb 100644 --- a/src/lib/dhcpsrv/pool.h +++ b/src/lib/dhcpsrv/pool.h @@ -11,9 +11,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/lib/dhcpsrv/srv_config.cc b/src/lib/dhcpsrv/srv_config.cc index f155c9c5d4..da3d1e2ef9 100644 --- a/src/lib/dhcpsrv/srv_config.cc +++ b/src/lib/dhcpsrv/srv_config.cc @@ -214,6 +214,8 @@ SrvConfig::toElement() const { ElementPtr result = Element::createMap(); // DhcpX global map ElementPtr dhcp = Element::createMap(); + // Set user-context + contextToElement(dhcp); // Set decline-probation-period dhcp->set("decline-probation-period", Element::create(static_cast(decline_timer_))); diff --git a/src/lib/dhcpsrv/srv_config.h b/src/lib/dhcpsrv/srv_config.h index 35a08eea55..5ca75aefbc 100644 --- a/src/lib/dhcpsrv/srv_config.h +++ b/src/lib/dhcpsrv/srv_config.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,7 @@ class CfgMgr; /// @brief Specifies current DHCP configuration /// /// @todo Migrate all other configuration parameters from cfgmgr.h here -class SrvConfig : public isc::data::CfgToElement { +class SrvConfig : public UserContext, public isc::data::CfgToElement { public: /// @name Constants for selection of parameters returned by @c getConfigSummary /// diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h index d22e3ae12b..ed55698899 100644 --- a/src/lib/dhcpsrv/subnet.h +++ b/src/lib/dhcpsrv/subnet.h @@ -9,13 +9,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include diff --git a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc index 99fd3d69f2..e595f4103f 100644 --- a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc @@ -257,6 +257,8 @@ TEST(CfgOptionDefTest, unparse) { cfg.add(OptionDefinitionPtr(new OptionDefinition("option-baz", 6, "uint16", "dns")), "isc"); OptionDefinitionPtr rec(new OptionDefinition("option-rec", 6, "record")); + std::string json = "{ \"comment\": \"foo\" }"; + rec->setContext(data::Element::fromJSON(json)); rec->addRecordField("uint16"); rec->addRecordField("uint16"); cfg.add(rec, "dns"); @@ -274,6 +276,7 @@ TEST(CfgOptionDefTest, unparse) { "},{\n" " \"name\": \"option-rec\",\n" " \"code\": 6,\n" + " \"comment\": \"foo\",\n" " \"type\": \"record\",\n" " \"array\": false,\n" " \"record-types\": \"uint16, uint16\",\n"