Commit bc3ea9d7 authored by Francis Dupont's avatar Francis Dupont

[5351] Added global and option def

parent b6a202af
......@@ -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_);
......
......@@ -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
;
......
......@@ -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") ||
......
......@@ -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();
......
......@@ -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();
......
......@@ -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_);
......
......@@ -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
;
......
......@@ -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;
}
......
......@@ -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();
......
......@@ -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
......
......@@ -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 <dhcpsrv/user_context.h>
#include <cc/user_context.h>
using namespace isc::data;
......
......@@ -10,6 +10,7 @@
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
#include <dhcp/option_space_container.h>
#include <cc/user_context.h>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
......@@ -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_;
};
......
......@@ -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
......
......@@ -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
......@@ -10,12 +10,12 @@
#include <asiolink/io_address.h>
#include <cc/cfg_to_element.h>
#include <cc/data.h>
#include <cc/user_context.h>
#include <dhcp/classify.h>
#include <dhcp/option.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfg_4o6.h>
#include <dhcpsrv/triplet.h>
#include <dhcpsrv/user_context.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstdint>
......
......@@ -84,12 +84,6 @@ void ControlSocketParser::parse(SrvConfig& srv_cfg, isc::data::ConstElementPtr v
srv_cfg.setControlSocketInfo(value);
}
template<typename SearchKey>
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<std::string> record_tokens =
isc::util::str::tokens(record_types, ",");
......
......@@ -11,9 +11,9 @@
#include <dhcp/option6_pdexclude.h>
#include <boost/shared_ptr.hpp>
#include <cc/data.h>
#include <cc/user_context.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/user_context.h>
#include <boost/shared_ptr.hpp>
#include <vector>
......
......@@ -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<long long>(decline_timer_)));
......
......@@ -26,6 +26,7 @@
#include <dhcpsrv/logging_info.h>
#include <hooks/hooks_config.h>
#include <cc/data.h>
#include <cc/user_context.h>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <stdint.h>
......@@ -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
///
......
......@@ -9,13 +9,13 @@
#include <asiolink/io_address.h>
#include <cc/data.h>
#include <cc/user_context.h>
#include <dhcp/option_space_container.h>
#include <dhcpsrv/assignable_network.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet_id.h>
#include <dhcpsrv/triplet.h>
#include <dhcpsrv/user_context.h>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/indexed_by.hpp>
......
......@@ -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"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment