mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[5351] Checkpoint: fix HR, doc, host DB
This commit is contained in:
parent
a2cc11e0dd
commit
93703b0804
@ -135,6 +135,8 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
|||||||
return isc::dhcp::Dhcp4Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
|
return isc::dhcp::Dhcp4Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
|
||||||
case Parser4Context::PARSER_DHCP_DDNS:
|
case Parser4Context::PARSER_DHCP_DDNS:
|
||||||
return isc::dhcp::Dhcp4Parser::make_SUB_DHCP_DDNS(driver.loc_);
|
return isc::dhcp::Dhcp4Parser::make_SUB_DHCP_DDNS(driver.loc_);
|
||||||
|
case Parser4Context::PARSER_LOGGING:
|
||||||
|
return isc::dhcp::Dhcp4Parser::make_SUB_LOGGING(driver.loc_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
@ -580,8 +582,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
|||||||
switch(driver.ctx_) {
|
switch(driver.ctx_) {
|
||||||
case isc::dhcp::Parser4Context::DHCP4:
|
case isc::dhcp::Parser4Context::DHCP4:
|
||||||
case isc::dhcp::Parser4Context::INTERFACES_CONFIG:
|
case isc::dhcp::Parser4Context::INTERFACES_CONFIG:
|
||||||
case isc::dhcp::Parser4Context::LEASE_DATABASE:
|
|
||||||
case isc::dhcp::Parser4Context::HOSTS_DATABASE:
|
|
||||||
case isc::dhcp::Parser4Context::SUBNET4:
|
case isc::dhcp::Parser4Context::SUBNET4:
|
||||||
case isc::dhcp::Parser4Context::POOLS:
|
case isc::dhcp::Parser4Context::POOLS:
|
||||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||||
@ -602,8 +602,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
|||||||
switch(driver.ctx_) {
|
switch(driver.ctx_) {
|
||||||
case isc::dhcp::Parser4Context::DHCP4:
|
case isc::dhcp::Parser4Context::DHCP4:
|
||||||
case isc::dhcp::Parser4Context::INTERFACES_CONFIG:
|
case isc::dhcp::Parser4Context::INTERFACES_CONFIG:
|
||||||
case isc::dhcp::Parser4Context::LEASE_DATABASE:
|
|
||||||
case isc::dhcp::Parser4Context::HOSTS_DATABASE:
|
|
||||||
case isc::dhcp::Parser4Context::SUBNET4:
|
case isc::dhcp::Parser4Context::SUBNET4:
|
||||||
case isc::dhcp::Parser4Context::POOLS:
|
case isc::dhcp::Parser4Context::POOLS:
|
||||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||||
|
@ -206,6 +206,7 @@ using namespace std;
|
|||||||
SUB_OPTION_DATA
|
SUB_OPTION_DATA
|
||||||
SUB_HOOKS_LIBRARY
|
SUB_HOOKS_LIBRARY
|
||||||
SUB_DHCP_DDNS
|
SUB_DHCP_DDNS
|
||||||
|
SUB_LOGGING
|
||||||
;
|
;
|
||||||
|
|
||||||
%token <std::string> STRING "constant string"
|
%token <std::string> STRING "constant string"
|
||||||
@ -243,6 +244,7 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
|
|||||||
| SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
|
| SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
|
||||||
| SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
|
| SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
|
||||||
| SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
|
| SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
|
||||||
|
| SUB_LOGGING { ctx.ctx_ = ctx.LOGGING; } sub_logging
|
||||||
;
|
;
|
||||||
|
|
||||||
// ---- generic JSON parser ---------------------------------
|
// ---- generic JSON parser ---------------------------------
|
||||||
@ -582,8 +584,6 @@ database_map_param: database_type
|
|||||||
| connect_timeout
|
| connect_timeout
|
||||||
| contact_points
|
| contact_points
|
||||||
| keyspace
|
| keyspace
|
||||||
| user_context
|
|
||||||
| comment
|
|
||||||
| unknown_map_entry
|
| unknown_map_entry
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1861,6 +1861,14 @@ logging_object: LOGGING {
|
|||||||
ctx.leave();
|
ctx.leave();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sub_logging: LCURLY_BRACKET {
|
||||||
|
// Parse the Logging map
|
||||||
|
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||||
|
ctx.stack_.push_back(m);
|
||||||
|
} logging_params RCURLY_BRACKET {
|
||||||
|
// parsing completed
|
||||||
|
};
|
||||||
|
|
||||||
// This defines the list of allowed parameters that may appear
|
// This defines the list of allowed parameters that may appear
|
||||||
// in the top-level Logging object. It can either be a single
|
// in the top-level Logging object. It can either be a single
|
||||||
// parameter or several parameters separated by commas.
|
// parameter or several parameters separated by commas.
|
||||||
|
@ -86,7 +86,10 @@ public:
|
|||||||
PARSER_HOOKS_LIBRARY,
|
PARSER_HOOKS_LIBRARY,
|
||||||
|
|
||||||
/// This will parse the input as dhcp-ddns.
|
/// This will parse the input as dhcp-ddns.
|
||||||
PARSER_DHCP_DDNS
|
PARSER_DHCP_DDNS,
|
||||||
|
|
||||||
|
/// This will parse the content of Logging.
|
||||||
|
PARSER_LOGGING
|
||||||
} ParserType;
|
} ParserType;
|
||||||
|
|
||||||
/// @brief Default constructor.
|
/// @brief Default constructor.
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <cc/command_interpreter.h>
|
#include <cc/command_interpreter.h>
|
||||||
#include <config/module_spec.h>
|
#include <config/module_spec.h>
|
||||||
#include <dhcp4/dhcp4_srv.h>
|
#include <dhcp4/dhcp4_srv.h>
|
||||||
|
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||||
#include <dhcp4/json_config_parser.h>
|
#include <dhcp4/json_config_parser.h>
|
||||||
#include <dhcp/option4_addrlst.h>
|
#include <dhcp/option4_addrlst.h>
|
||||||
#include <dhcp/option_custom.h>
|
#include <dhcp/option_custom.h>
|
||||||
@ -165,7 +166,7 @@ public:
|
|||||||
// Open port 0 means to not do anything at all. We don't want to
|
// Open port 0 means to not do anything at all. We don't want to
|
||||||
// deal with sockets here, just check if configuration handling
|
// deal with sockets here, just check if configuration handling
|
||||||
// is sane.
|
// is sane.
|
||||||
srv_.reset(new Dhcpv4Srv(0));
|
srv_.reset(new ControlledDhcpv4Srv(0));
|
||||||
// Create fresh context.
|
// Create fresh context.
|
||||||
resetConfiguration();
|
resetConfiguration();
|
||||||
}
|
}
|
||||||
@ -5612,57 +5613,83 @@ TEST_F(Dhcp4ParserTest, comments) {
|
|||||||
|
|
||||||
string config = "{\n"
|
string config = "{\n"
|
||||||
"\"comment\": \"A DHCPv4 server\",\n"
|
"\"comment\": \"A DHCPv4 server\",\n"
|
||||||
|
"\"interfaces-config\": {\n"
|
||||||
|
" \"comment\": \"Use wildcard\",\n"
|
||||||
|
" \"interfaces\": [ \"*\" ] },\n"
|
||||||
"\"option-def\": [ {\n"
|
"\"option-def\": [ {\n"
|
||||||
|
" \"comment\": \"An option definition\",\n"
|
||||||
" \"name\": \"foo\",\n"
|
" \"name\": \"foo\",\n"
|
||||||
" \"code\": 100,\n"
|
" \"code\": 100,\n"
|
||||||
" \"comment\": \"An option definition\",\n"
|
|
||||||
" \"type\": \"ipv4-address\",\n"
|
" \"type\": \"ipv4-address\",\n"
|
||||||
" \"space\": \"isc\"\n"
|
" \"space\": \"isc\"\n"
|
||||||
" } ],\n"
|
" } ],\n"
|
||||||
"\"option-data\": [ {\n"
|
"\"option-data\": [ {\n"
|
||||||
" \"name\": \"dhcp-message\",\n"
|
|
||||||
" \"comment\": \"Set option value\",\n"
|
" \"comment\": \"Set option value\",\n"
|
||||||
|
" \"name\": \"dhcp-message\",\n"
|
||||||
" \"data\": \"ABCDEF0105\",\n"
|
" \"data\": \"ABCDEF0105\",\n"
|
||||||
" \"csv-format\": false\n"
|
" \"csv-format\": false\n"
|
||||||
" } ],\n"
|
" } ],\n"
|
||||||
"\"client-classes\": [\n"
|
"\"client-classes\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"all\",\n"
|
|
||||||
" \"comment\": \"match all\",\n"
|
" \"comment\": \"match all\",\n"
|
||||||
|
" \"name\": \"all\",\n"
|
||||||
" \"test\": \"'' == ''\"\n"
|
" \"test\": \"'' == ''\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"none\"\n"
|
" \"name\": \"none\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"two\",\n"
|
|
||||||
" \"comment\": \"first comment\",\n"
|
" \"comment\": \"first comment\",\n"
|
||||||
" \"comment\": \"second comment\"\n"
|
" \"comment\": \"second comment\",\n"
|
||||||
|
" \"name\": \"two\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"both\",\n"
|
|
||||||
" \"comment\": \"a comment\",\n"
|
" \"comment\": \"a comment\",\n"
|
||||||
|
" \"name\": \"both\",\n"
|
||||||
" \"user-context\": {\n"
|
" \"user-context\": {\n"
|
||||||
" \"version\": 1\n"
|
" \"version\": 1\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
"\"control-socket\": {\n"
|
||||||
|
" \"comment\": \"REST API\",\n"
|
||||||
|
" \"socket-type\": \"unix\",\n"
|
||||||
|
" \"socket-name\": \"/tmp/kea4-ctrl-socket\",\n"
|
||||||
|
" \"user-context\": { \"comment\": \"Indirect comment\" }\n"
|
||||||
|
"},\n"
|
||||||
"\"shared-networks\": [ {\n"
|
"\"shared-networks\": [ {\n"
|
||||||
" \"name\": \"foo\"\n,"
|
|
||||||
" \"comment\": \"A shared network\"\n,"
|
" \"comment\": \"A shared network\"\n,"
|
||||||
|
" \"name\": \"foo\"\n,"
|
||||||
" \"subnet4\": [\n"
|
" \"subnet4\": [\n"
|
||||||
" { \n"
|
" { \n"
|
||||||
" \"subnet\": \"192.0.1.0/24\",\n"
|
|
||||||
" \"comment\": \"A subnet\"\n,"
|
" \"comment\": \"A subnet\"\n,"
|
||||||
|
" \"subnet\": \"192.0.1.0/24\",\n"
|
||||||
|
" \"id\": 100,\n"
|
||||||
" \"pools\": [\n"
|
" \"pools\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"pool\": \"192.0.1.1-192.0.1.10\",\n"
|
" \"comment\": \"A pool\",\n"
|
||||||
" \"comment\": \"A pool\"\n"
|
" \"pool\": \"192.0.1.1-192.0.1.10\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ]\n"
|
" ],\n"
|
||||||
" }\n"
|
" \"reservations\": [\n"
|
||||||
" ]\n"
|
" {\n"
|
||||||
|
" \"comment\": \"A host reservation\",\n"
|
||||||
|
" \"hw-address\": \"AA:BB:CC:DD:EE:FF\",\n"
|
||||||
|
" \"hostname\": \"foo.example.com\",\n"
|
||||||
|
" \"option-data\": [ {\n"
|
||||||
|
" \"comment\": \"An option in a reservation\",\n"
|
||||||
|
" \"name\": \"domain-name\",\n"
|
||||||
|
" \"data\": \"example.com\"\n"
|
||||||
" } ]\n"
|
" } ]\n"
|
||||||
|
" }\n"
|
||||||
|
" ]\n"
|
||||||
|
" }\n"
|
||||||
|
" ]\n"
|
||||||
|
" } ],\n"
|
||||||
|
"\"dhcp-ddns\": {\n"
|
||||||
|
" \"comment\": \"No dynamic DNS\",\n"
|
||||||
|
" \"enable-updates\": false\n"
|
||||||
|
"}\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
extractConfig(config);
|
extractConfig(config);
|
||||||
@ -5675,8 +5702,20 @@ TEST_F(Dhcp4ParserTest, comments) {
|
|||||||
ASSERT_TRUE(ctx->get("comment"));
|
ASSERT_TRUE(ctx->get("comment"));
|
||||||
EXPECT_EQ("\"A DHCPv4 server\"", ctx->get("comment")->str());
|
EXPECT_EQ("\"A DHCPv4 server\"", ctx->get("comment")->str());
|
||||||
|
|
||||||
|
// There is a network interface configuration.
|
||||||
|
ConstCfgIfacePtr iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
|
||||||
|
ASSERT_TRUE(iface);
|
||||||
|
|
||||||
|
// Check network interface configuration user context.
|
||||||
|
ConstElementPtr ctx_iface = iface->getContext();
|
||||||
|
ASSERT_TRUE(ctx_iface);
|
||||||
|
ASSERT_EQ(1, ctx_iface->size());
|
||||||
|
ASSERT_TRUE(ctx_iface->get("comment"));
|
||||||
|
EXPECT_EQ("\"Use wildcard\"", ctx_iface->get("comment")->str());
|
||||||
|
|
||||||
// There is a global option definition.
|
// There is a global option definition.
|
||||||
OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
|
const OptionDefinitionPtr& opt_def =
|
||||||
|
LibDHCP::getRuntimeOptionDef("isc", 100);
|
||||||
ASSERT_TRUE(opt_def);
|
ASSERT_TRUE(opt_def);
|
||||||
EXPECT_EQ("foo", opt_def->getName());
|
EXPECT_EQ("foo", opt_def->getName());
|
||||||
EXPECT_EQ(100, opt_def->getCode());
|
EXPECT_EQ(100, opt_def->getCode());
|
||||||
@ -5692,7 +5731,7 @@ TEST_F(Dhcp4ParserTest, comments) {
|
|||||||
EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
|
EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
|
||||||
|
|
||||||
// There is an option descriptor aka option data.
|
// There is an option descriptor aka option data.
|
||||||
OptionDescriptor opt_desc =
|
const OptionDescriptor& opt_desc =
|
||||||
CfgMgr::instance().getStagingCfg()->getCfgOption()->
|
CfgMgr::instance().getStagingCfg()->getCfgOption()->
|
||||||
get(DHCP4_OPTION_SPACE, DHO_DHCP_MESSAGE);
|
get(DHCP4_OPTION_SPACE, DHO_DHCP_MESSAGE);
|
||||||
ASSERT_TRUE(opt_desc.option_);
|
ASSERT_TRUE(opt_desc.option_);
|
||||||
@ -5706,7 +5745,7 @@ TEST_F(Dhcp4ParserTest, comments) {
|
|||||||
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
|
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
|
||||||
|
|
||||||
// And there are some client classes.
|
// And there are some client classes.
|
||||||
ClientClassDictionaryPtr dict =
|
const ClientClassDictionaryPtr& dict =
|
||||||
CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
|
CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
|
||||||
ASSERT_TRUE(dict);
|
ASSERT_TRUE(dict);
|
||||||
EXPECT_EQ(4, dict->getClasses()->size());
|
EXPECT_EQ(4, dict->getClasses()->size());
|
||||||
@ -5752,15 +5791,34 @@ TEST_F(Dhcp4ParserTest, comments) {
|
|||||||
ASSERT_TRUE(ctx_class->get("version"));
|
ASSERT_TRUE(ctx_class->get("version"));
|
||||||
EXPECT_EQ("1", ctx_class->get("version")->str());
|
EXPECT_EQ("1", ctx_class->get("version")->str());
|
||||||
|
|
||||||
|
// There is a control socket.
|
||||||
|
ConstElementPtr socket =
|
||||||
|
CfgMgr::instance().getStagingCfg()->getControlSocketInfo();
|
||||||
|
ASSERT_TRUE(socket);
|
||||||
|
ASSERT_TRUE(socket->get("socket-type"));
|
||||||
|
EXPECT_EQ("\"unix\"", socket->get("socket-type")->str());
|
||||||
|
ASSERT_TRUE(socket->get("socket-name"));
|
||||||
|
EXPECT_EQ("\"/tmp/kea4-ctrl-socket\"", socket->get("socket-name")->str());
|
||||||
|
|
||||||
|
// Check control socket comment and user context.
|
||||||
|
ConstElementPtr ctx_socket = socket->get("comment");
|
||||||
|
ASSERT_TRUE(ctx_socket);
|
||||||
|
EXPECT_EQ("\"REST API\"", ctx_socket->str());
|
||||||
|
ctx_socket = socket->get("user-context");
|
||||||
|
ASSERT_EQ(1, ctx_socket->size());
|
||||||
|
ASSERT_TRUE(ctx_socket->get("comment"));
|
||||||
|
EXPECT_EQ("\"Indirect comment\"", ctx_socket->get("comment")->str());
|
||||||
|
|
||||||
// Now verify that the shared network was indeed configured.
|
// Now verify that the shared network was indeed configured.
|
||||||
CfgSharedNetworks4Ptr cfg_net = CfgMgr::instance().getStagingCfg()
|
const CfgSharedNetworks4Ptr& cfg_net =
|
||||||
->getCfgSharedNetworks4();
|
CfgMgr::instance().getStagingCfg()->getCfgSharedNetworks4();
|
||||||
ASSERT_TRUE(cfg_net);
|
ASSERT_TRUE(cfg_net);
|
||||||
const SharedNetwork4Collection* nets = cfg_net->getAll();
|
const SharedNetwork4Collection* nets = cfg_net->getAll();
|
||||||
ASSERT_TRUE(nets);
|
ASSERT_TRUE(nets);
|
||||||
ASSERT_EQ(1, nets->size());
|
ASSERT_EQ(1, nets->size());
|
||||||
SharedNetwork4Ptr net = nets->at(0);
|
SharedNetwork4Ptr net = nets->at(0);
|
||||||
ASSERT_TRUE(net);
|
ASSERT_TRUE(net);
|
||||||
|
EXPECT_EQ("foo", net->getName());
|
||||||
|
|
||||||
// Check shared network user context.
|
// Check shared network user context.
|
||||||
ConstElementPtr ctx_net = net->getContext();
|
ConstElementPtr ctx_net = net->getContext();
|
||||||
@ -5775,6 +5833,8 @@ TEST_F(Dhcp4ParserTest, comments) {
|
|||||||
ASSERT_EQ(1, subs->size());
|
ASSERT_EQ(1, subs->size());
|
||||||
Subnet4Ptr sub = subs->at(0);
|
Subnet4Ptr sub = subs->at(0);
|
||||||
ASSERT_TRUE(sub);
|
ASSERT_TRUE(sub);
|
||||||
|
EXPECT_EQ(100, sub->getID());
|
||||||
|
EXPECT_EQ("192.0.1.0/24", sub->toText());
|
||||||
|
|
||||||
// Check subnet user context.
|
// Check subnet user context.
|
||||||
ConstElementPtr ctx_sub = sub->getContext();
|
ConstElementPtr ctx_sub = sub->getContext();
|
||||||
@ -5795,6 +5855,66 @@ TEST_F(Dhcp4ParserTest, comments) {
|
|||||||
ASSERT_EQ(1, ctx_pool->size());
|
ASSERT_EQ(1, ctx_pool->size());
|
||||||
ASSERT_TRUE(ctx_pool->get("comment"));
|
ASSERT_TRUE(ctx_pool->get("comment"));
|
||||||
EXPECT_EQ("\"A pool\"", ctx_pool->get("comment")->str());
|
EXPECT_EQ("\"A pool\"", ctx_pool->get("comment")->str());
|
||||||
|
|
||||||
|
// The subnet has a host reservation.
|
||||||
|
uint8_t hw[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
|
||||||
|
HWAddrPtr hwaddr(new HWAddr(hw, sizeof(hw), HTYPE_ETHER));
|
||||||
|
ConstHostPtr host =
|
||||||
|
CfgMgr::instance().getStagingCfg()->getCfgHosts()->get4(100, hwaddr);
|
||||||
|
ASSERT_TRUE(host);
|
||||||
|
EXPECT_EQ(Host::IDENT_HWADDR, host->getIdentifierType());
|
||||||
|
EXPECT_EQ("aa:bb:cc:dd:ee:ff", host->getHWAddress()->toText(false));
|
||||||
|
EXPECT_FALSE(host->getDuid());
|
||||||
|
EXPECT_EQ(100, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(0, host->getIPv6SubnetID());
|
||||||
|
EXPECT_EQ("foo.example.com", host->getHostname());
|
||||||
|
|
||||||
|
// Check host user context.
|
||||||
|
ConstElementPtr ctx_host = host->getContext();
|
||||||
|
ASSERT_TRUE(ctx_host);
|
||||||
|
ASSERT_EQ(1, ctx_host->size());
|
||||||
|
ASSERT_TRUE(ctx_host->get("comment"));
|
||||||
|
EXPECT_EQ("\"A host reservation\"", ctx_host->get("comment")->str());
|
||||||
|
|
||||||
|
// The host reservation has an option data.
|
||||||
|
ConstCfgOptionPtr opts = host->getCfgOption4();
|
||||||
|
ASSERT_TRUE(opts);
|
||||||
|
EXPECT_FALSE(opts->empty());
|
||||||
|
const OptionDescriptor& host_desc =
|
||||||
|
opts->get(DHCP4_OPTION_SPACE, DHO_DOMAIN_NAME);
|
||||||
|
ASSERT_TRUE(host_desc.option_);
|
||||||
|
EXPECT_EQ(DHO_DOMAIN_NAME, host_desc.option_->getType());
|
||||||
|
|
||||||
|
// Check embedded option data user context.
|
||||||
|
ConstElementPtr ctx_host_desc = host_desc.getContext();
|
||||||
|
ASSERT_TRUE(ctx_host_desc);
|
||||||
|
ASSERT_EQ(1, ctx_host_desc->size());
|
||||||
|
ASSERT_TRUE(ctx_host_desc->get("comment"));
|
||||||
|
EXPECT_EQ("\"An option in a reservation\"",
|
||||||
|
ctx_host_desc->get("comment")->str());
|
||||||
|
|
||||||
|
// Finally dynamic DNS update configuration.
|
||||||
|
const D2ClientConfigPtr& d2 =
|
||||||
|
CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
|
||||||
|
ASSERT_TRUE(d2);
|
||||||
|
EXPECT_FALSE(d2->getEnableUpdates());
|
||||||
|
|
||||||
|
// Check dynamic DNS update configuration user context.
|
||||||
|
ConstElementPtr ctx_d2 = d2->getContext();
|
||||||
|
ASSERT_TRUE(ctx_d2);
|
||||||
|
ASSERT_EQ(1, ctx_d2->size());
|
||||||
|
ASSERT_TRUE(ctx_d2->get("comment"));
|
||||||
|
EXPECT_EQ("\"No dynamic DNS\"", ctx_d2->get("comment")->str());
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Loggers section supports comments too.
|
||||||
|
|
||||||
|
string logging = "{\n"
|
||||||
|
"\"loggers\": [ {\n"
|
||||||
|
" \"comment\": \"A logger\",\n"
|
||||||
|
" \"name\": \"kea-dhcp4\"\n"
|
||||||
|
"} ]\n";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <dhcp4/tests/dhcp4_test_utils.h>
|
#include <dhcp4/tests/dhcp4_test_utils.h>
|
||||||
#include <dhcp4/tests/get_config_unittest.h>
|
#include <dhcp4/tests/get_config_unittest.h>
|
||||||
#include <dhcp4/dhcp4_srv.h>
|
#include <dhcp4/dhcp4_srv.h>
|
||||||
|
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||||
#include <dhcp4/json_config_parser.h>
|
#include <dhcp4/json_config_parser.h>
|
||||||
#include <dhcpsrv/parsers/simple_parser4.h>
|
#include <dhcpsrv/parsers/simple_parser4.h>
|
||||||
|
|
||||||
@ -1661,6 +1662,23 @@ const char* EXTRACTED_CONFIGS[] = {
|
|||||||
" }\n"
|
" }\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"control-socket\": {\n"
|
||||||
|
" \"comment\": \"REST API\",\n"
|
||||||
|
" \"socket-name\": \"/tmp/kea4-ctrl-socket\",\n"
|
||||||
|
" \"socket-type\": \"unix\",\n"
|
||||||
|
" \"user-context\": {\n"
|
||||||
|
" \"comment\": \"Indirect comment\"\n"
|
||||||
|
" }\n"
|
||||||
|
" },\n"
|
||||||
|
" \"dhcp-ddns\": {\n"
|
||||||
|
" \"comment\": \"No dynamic DNS\",\n"
|
||||||
|
" \"enable-updates\": false\n"
|
||||||
|
" },\n"
|
||||||
|
" \"interfaces-config\": {\n"
|
||||||
|
" \"comment\": \"Use wildcard\",\n"
|
||||||
|
" \"interfaces\": [ \"*\" ],\n"
|
||||||
|
" \"re-detect\": false\n"
|
||||||
|
" },\n"
|
||||||
" \"option-data\": [\n"
|
" \"option-data\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"Set option value\",\n"
|
" \"comment\": \"Set option value\",\n"
|
||||||
@ -1685,12 +1703,27 @@ const char* EXTRACTED_CONFIGS[] = {
|
|||||||
" \"subnet4\": [\n"
|
" \"subnet4\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"A subnet\",\n"
|
" \"comment\": \"A subnet\",\n"
|
||||||
|
" \"id\": 100,\n"
|
||||||
" \"pools\": [\n"
|
" \"pools\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"A pool\",\n"
|
" \"comment\": \"A pool\",\n"
|
||||||
" \"pool\": \"192.0.1.1-192.0.1.10\"\n"
|
" \"pool\": \"192.0.1.1-192.0.1.10\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"reservations\": [\n"
|
||||||
|
" {\n"
|
||||||
|
" \"comment\": \"A host reservation\",\n"
|
||||||
|
" \"hostname\": \"foo.example.com\",\n"
|
||||||
|
" \"hw-address\": \"AA:BB:CC:DD:EE:FF\",\n"
|
||||||
|
" \"option-data\": [\n"
|
||||||
|
" {\n"
|
||||||
|
" \"comment\": \"An option in a reservation\",\n"
|
||||||
|
" \"data\": \"example.com\",\n"
|
||||||
|
" \"name\": \"domain-name\"\n"
|
||||||
|
" }\n"
|
||||||
|
" ]\n"
|
||||||
|
" }\n"
|
||||||
|
" ],\n"
|
||||||
" \"subnet\": \"192.0.1.0/24\"\n"
|
" \"subnet\": \"192.0.1.0/24\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ]\n"
|
" ]\n"
|
||||||
@ -6384,8 +6417,17 @@ const char* UNPARSED_CONFIGS[] = {
|
|||||||
" \"server-hostname\": \"\"\n"
|
" \"server-hostname\": \"\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"control-socket\": {\n"
|
||||||
|
" \"comment\": \"REST API\",\n"
|
||||||
|
" \"socket-name\": \"/tmp/kea4-ctrl-socket\",\n"
|
||||||
|
" \"socket-type\": \"unix\",\n"
|
||||||
|
" \"user-context\": {\n"
|
||||||
|
" \"comment\": \"Indirect comment\"\n"
|
||||||
|
" }\n"
|
||||||
|
" },\n"
|
||||||
" \"decline-probation-period\": 86400,\n"
|
" \"decline-probation-period\": 86400,\n"
|
||||||
" \"dhcp-ddns\": {\n"
|
" \"dhcp-ddns\": {\n"
|
||||||
|
" \"comment\": \"No dynamic DNS\",\n"
|
||||||
" \"always-include-fqdn\": false,\n"
|
" \"always-include-fqdn\": false,\n"
|
||||||
" \"enable-updates\": false,\n"
|
" \"enable-updates\": false,\n"
|
||||||
" \"generated-prefix\": \"myhost\",\n"
|
" \"generated-prefix\": \"myhost\",\n"
|
||||||
@ -6414,7 +6456,8 @@ const char* UNPARSED_CONFIGS[] = {
|
|||||||
" \"hooks-libraries\": [ ],\n"
|
" \"hooks-libraries\": [ ],\n"
|
||||||
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
|
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
|
||||||
" \"interfaces-config\": {\n"
|
" \"interfaces-config\": {\n"
|
||||||
" \"interfaces\": [ ],\n"
|
" \"comment\": \"Use wildcard\",\n"
|
||||||
|
" \"interfaces\": [ \"*\" ],\n"
|
||||||
" \"re-detect\": false\n"
|
" \"re-detect\": false\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" \"lease-database\": {\n"
|
" \"lease-database\": {\n"
|
||||||
@ -6462,7 +6505,7 @@ const char* UNPARSED_CONFIGS[] = {
|
|||||||
" \"4o6-interface-id\": \"\",\n"
|
" \"4o6-interface-id\": \"\",\n"
|
||||||
" \"4o6-subnet\": \"\",\n"
|
" \"4o6-subnet\": \"\",\n"
|
||||||
" \"boot-file-name\": \"\",\n"
|
" \"boot-file-name\": \"\",\n"
|
||||||
" \"id\": 1,\n"
|
" \"id\": 100,\n"
|
||||||
" \"match-client-id\": true,\n"
|
" \"match-client-id\": true,\n"
|
||||||
" \"next-server\": \"0.0.0.0\",\n"
|
" \"next-server\": \"0.0.0.0\",\n"
|
||||||
" \"option-data\": [ ],\n"
|
" \"option-data\": [ ],\n"
|
||||||
@ -6584,7 +6627,7 @@ public:
|
|||||||
// Open port 0 means to not do anything at all. We don't want to
|
// Open port 0 means to not do anything at all. We don't want to
|
||||||
// deal with sockets here, just check if configuration handling
|
// deal with sockets here, just check if configuration handling
|
||||||
// is sane.
|
// is sane.
|
||||||
srv_.reset(new Dhcpv4Srv(0));
|
srv_.reset(new ControlledDhcpv4Srv(0));
|
||||||
// Create fresh context.
|
// Create fresh context.
|
||||||
resetConfiguration();
|
resetConfiguration();
|
||||||
}
|
}
|
||||||
@ -6686,7 +6729,7 @@ public:
|
|||||||
CfgMgr::instance().setFamily(AF_INET);
|
CfgMgr::instance().setFamily(AF_INET);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::scoped_ptr<Dhcpv4Srv> srv_; ///< DHCP4 server under test
|
boost::scoped_ptr<ControlledDhcpv4Srv> srv_; ///< DHCP4 server under test
|
||||||
int rcode_; ///< Return code from element parsing
|
int rcode_; ///< Return code from element parsing
|
||||||
ConstElementPtr comment_; ///< Reason for parse fail
|
ConstElementPtr comment_; ///< Reason for parse fail
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <dhcp4/tests/dhcp4_test_utils.h>
|
#include <dhcp4/tests/dhcp4_test_utils.h>
|
||||||
#include <dhcp4/tests/get_config_unittest.h>
|
#include <dhcp4/tests/get_config_unittest.h>
|
||||||
#include <dhcp4/dhcp4_srv.h>
|
#include <dhcp4/dhcp4_srv.h>
|
||||||
|
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||||
#include <dhcp4/json_config_parser.h>
|
#include <dhcp4/json_config_parser.h>
|
||||||
#include <dhcpsrv/parsers/simple_parser4.h>
|
#include <dhcpsrv/parsers/simple_parser4.h>
|
||||||
|
|
||||||
@ -168,7 +169,7 @@ public:
|
|||||||
// Open port 0 means to not do anything at all. We don't want to
|
// Open port 0 means to not do anything at all. We don't want to
|
||||||
// deal with sockets here, just check if configuration handling
|
// deal with sockets here, just check if configuration handling
|
||||||
// is sane.
|
// is sane.
|
||||||
srv_.reset(new Dhcpv4Srv(0));
|
srv_.reset(new ControlledDhcpv4Srv(0));
|
||||||
// Create fresh context.
|
// Create fresh context.
|
||||||
resetConfiguration();
|
resetConfiguration();
|
||||||
}
|
}
|
||||||
@ -270,7 +271,7 @@ public:
|
|||||||
CfgMgr::instance().setFamily(AF_INET);
|
CfgMgr::instance().setFamily(AF_INET);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::scoped_ptr<Dhcpv4Srv> srv_; ///< DHCP4 server under test
|
boost::scoped_ptr<ControlledDhcpv4Srv> srv_; ///< DHCP4 server under test
|
||||||
int rcode_; ///< Return code from element parsing
|
int rcode_; ///< Return code from element parsing
|
||||||
ConstElementPtr comment_; ///< Reason for parse fail
|
ConstElementPtr comment_; ///< Reason for parse fail
|
||||||
};
|
};
|
||||||
|
@ -137,6 +137,8 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
|||||||
return isc::dhcp::Dhcp6Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
|
return isc::dhcp::Dhcp6Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
|
||||||
case Parser6Context::PARSER_DHCP_DDNS:
|
case Parser6Context::PARSER_DHCP_DDNS:
|
||||||
return isc::dhcp::Dhcp6Parser::make_SUB_DHCP_DDNS(driver.loc_);
|
return isc::dhcp::Dhcp6Parser::make_SUB_DHCP_DDNS(driver.loc_);
|
||||||
|
case Parser6Context::PARSER_LOGGING:
|
||||||
|
return isc::dhcp::Dhcp6Parser::make_SUB_LOGGING(driver.loc_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
@ -810,8 +812,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
|||||||
switch(driver.ctx_) {
|
switch(driver.ctx_) {
|
||||||
case isc::dhcp::Parser6Context::DHCP6:
|
case isc::dhcp::Parser6Context::DHCP6:
|
||||||
case isc::dhcp::Parser6Context::INTERFACES_CONFIG:
|
case isc::dhcp::Parser6Context::INTERFACES_CONFIG:
|
||||||
case isc::dhcp::Parser6Context::LEASE_DATABASE:
|
|
||||||
case isc::dhcp::Parser6Context::HOSTS_DATABASE:
|
|
||||||
case isc::dhcp::Parser6Context::SUBNET6:
|
case isc::dhcp::Parser6Context::SUBNET6:
|
||||||
case isc::dhcp::Parser6Context::SHARED_NETWORK:
|
case isc::dhcp::Parser6Context::SHARED_NETWORK:
|
||||||
case isc::dhcp::Parser6Context::OPTION_DEF:
|
case isc::dhcp::Parser6Context::OPTION_DEF:
|
||||||
@ -834,8 +834,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
|||||||
switch(driver.ctx_) {
|
switch(driver.ctx_) {
|
||||||
case isc::dhcp::Parser6Context::DHCP6:
|
case isc::dhcp::Parser6Context::DHCP6:
|
||||||
case isc::dhcp::Parser6Context::INTERFACES_CONFIG:
|
case isc::dhcp::Parser6Context::INTERFACES_CONFIG:
|
||||||
case isc::dhcp::Parser6Context::LEASE_DATABASE:
|
|
||||||
case isc::dhcp::Parser6Context::HOSTS_DATABASE:
|
|
||||||
case isc::dhcp::Parser6Context::SUBNET6:
|
case isc::dhcp::Parser6Context::SUBNET6:
|
||||||
case isc::dhcp::Parser6Context::SHARED_NETWORK:
|
case isc::dhcp::Parser6Context::SHARED_NETWORK:
|
||||||
case isc::dhcp::Parser6Context::OPTION_DEF:
|
case isc::dhcp::Parser6Context::OPTION_DEF:
|
||||||
|
@ -210,6 +210,7 @@ using namespace std;
|
|||||||
SUB_OPTION_DATA
|
SUB_OPTION_DATA
|
||||||
SUB_HOOKS_LIBRARY
|
SUB_HOOKS_LIBRARY
|
||||||
SUB_DHCP_DDNS
|
SUB_DHCP_DDNS
|
||||||
|
SUB_LOGGING
|
||||||
;
|
;
|
||||||
|
|
||||||
%token <std::string> STRING "constant string"
|
%token <std::string> STRING "constant string"
|
||||||
@ -247,6 +248,7 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
|
|||||||
| SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
|
| SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
|
||||||
| SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
|
| SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
|
||||||
| SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
|
| SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
|
||||||
|
| SUB_LOGGING { ctx.ctx_ = ctx.LOGGING; } sub_logging
|
||||||
;
|
;
|
||||||
|
|
||||||
// ---- generic JSON parser ---------------------------------
|
// ---- generic JSON parser ---------------------------------
|
||||||
@ -552,8 +554,6 @@ database_map_param: database_type
|
|||||||
| connect_timeout
|
| connect_timeout
|
||||||
| contact_points
|
| contact_points
|
||||||
| keyspace
|
| keyspace
|
||||||
| user_context
|
|
||||||
| comment
|
|
||||||
| unknown_map_entry
|
| unknown_map_entry
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1945,6 +1945,14 @@ logging_object: LOGGING {
|
|||||||
ctx.leave();
|
ctx.leave();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sub_logging: LCURLY_BRACKET {
|
||||||
|
// Parse the Logging map
|
||||||
|
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||||
|
ctx.stack_.push_back(m);
|
||||||
|
} logging_params RCURLY_BRACKET {
|
||||||
|
// parsing completed
|
||||||
|
};
|
||||||
|
|
||||||
// This defines the list of allowed parameters that may appear
|
// This defines the list of allowed parameters that may appear
|
||||||
// in the top-level Logging object. It can either be a single
|
// in the top-level Logging object. It can either be a single
|
||||||
// parameter or several parameters separated by commas.
|
// parameter or several parameters separated by commas.
|
||||||
|
@ -89,7 +89,11 @@ public:
|
|||||||
PARSER_HOOKS_LIBRARY,
|
PARSER_HOOKS_LIBRARY,
|
||||||
|
|
||||||
/// This will parse the input as dhcp-ddns. (D2 client config)
|
/// This will parse the input as dhcp-ddns. (D2 client config)
|
||||||
PARSER_DHCP_DDNS
|
PARSER_DHCP_DDNS,
|
||||||
|
|
||||||
|
/// This will parse the content of Logging.
|
||||||
|
PARSER_LOGGING
|
||||||
|
|
||||||
} ParserType;
|
} ParserType;
|
||||||
|
|
||||||
/// @brief Default constructor.
|
/// @brief Default constructor.
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <dhcp/tests/iface_mgr_test_config.h>
|
#include <dhcp/tests/iface_mgr_test_config.h>
|
||||||
#include <dhcp6/json_config_parser.h>
|
#include <dhcp6/json_config_parser.h>
|
||||||
#include <dhcp6/dhcp6_srv.h>
|
#include <dhcp6/dhcp6_srv.h>
|
||||||
|
#include <dhcp6/ctrl_dhcp6_srv.h>
|
||||||
#include <dhcpsrv/addr_utilities.h>
|
#include <dhcpsrv/addr_utilities.h>
|
||||||
#include <dhcpsrv/cfgmgr.h>
|
#include <dhcpsrv/cfgmgr.h>
|
||||||
#include <dhcpsrv/cfg_expiration.h>
|
#include <dhcpsrv/cfg_expiration.h>
|
||||||
@ -813,7 +814,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
|
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
|
||||||
Dhcpv6Srv srv_; ///< Instance of the Dhcp6Srv used during tests
|
ControlledDhcpv6Srv srv_; ///< Instance of the ControlledDhcp6Srv used during tests
|
||||||
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
|
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
|
||||||
string valid_iface_; ///< Valid network interface name (present in system)
|
string valid_iface_; ///< Valid network interface name (present in system)
|
||||||
string bogus_iface_; ///< invalid network interface name (not in system)
|
string bogus_iface_; ///< invalid network interface name (not in system)
|
||||||
@ -6054,65 +6055,95 @@ TEST_F(Dhcp6ParserTest, comments) {
|
|||||||
|
|
||||||
string config = "{\n"
|
string config = "{\n"
|
||||||
"\"comment\": \"A DHCPv6 server\",\n"
|
"\"comment\": \"A DHCPv6 server\",\n"
|
||||||
|
"\"server-id\": {\n"
|
||||||
|
" \"comment\": \"DHCPv6 specific\",\n"
|
||||||
|
" \"type\": \"LL\"\n"
|
||||||
|
"},\n"
|
||||||
|
"\"interfaces-config\": {\n"
|
||||||
|
" \"comment\": \"Use wildcard\",\n"
|
||||||
|
" \"interfaces\": [ \"*\" ] },\n"
|
||||||
"\"option-def\": [ {\n"
|
"\"option-def\": [ {\n"
|
||||||
|
" \"comment\": \"An option definition\",\n"
|
||||||
" \"name\": \"foo\",\n"
|
" \"name\": \"foo\",\n"
|
||||||
" \"code\": 100,\n"
|
" \"code\": 100,\n"
|
||||||
" \"comment\": \"An option definition\",\n"
|
|
||||||
" \"type\": \"ipv6-address\",\n"
|
" \"type\": \"ipv6-address\",\n"
|
||||||
" \"space\": \"isc\"\n"
|
" \"space\": \"isc\"\n"
|
||||||
" } ],\n"
|
" } ],\n"
|
||||||
"\"option-data\": [ {\n"
|
"\"option-data\": [ {\n"
|
||||||
" \"name\": \"subscriber-id\",\n"
|
|
||||||
" \"comment\": \"Set option value\",\n"
|
" \"comment\": \"Set option value\",\n"
|
||||||
|
" \"name\": \"subscriber-id\",\n"
|
||||||
" \"data\": \"ABCDEF0105\",\n"
|
" \"data\": \"ABCDEF0105\",\n"
|
||||||
" \"csv-format\": false\n"
|
" \"csv-format\": false\n"
|
||||||
" } ],\n"
|
" } ],\n"
|
||||||
"\"client-classes\": [\n"
|
"\"client-classes\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"all\",\n"
|
|
||||||
" \"comment\": \"match all\",\n"
|
" \"comment\": \"match all\",\n"
|
||||||
|
" \"name\": \"all\",\n"
|
||||||
" \"test\": \"'' == ''\"\n"
|
" \"test\": \"'' == ''\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"none\"\n"
|
" \"name\": \"none\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"two\",\n"
|
|
||||||
" \"comment\": \"first comment\",\n"
|
" \"comment\": \"first comment\",\n"
|
||||||
" \"comment\": \"second comment\"\n"
|
" \"comment\": \"second comment\",\n"
|
||||||
|
" \"name\": \"two\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"name\": \"both\",\n"
|
|
||||||
" \"comment\": \"a comment\",\n"
|
" \"comment\": \"a comment\",\n"
|
||||||
|
" \"name\": \"both\",\n"
|
||||||
" \"user-context\": {\n"
|
" \"user-context\": {\n"
|
||||||
" \"version\": 1\n"
|
" \"version\": 1\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
"\"control-socket\": {\n"
|
||||||
|
" \"comment\": \"REST API\",\n"
|
||||||
|
" \"socket-type\": \"unix\",\n"
|
||||||
|
" \"socket-name\": \"/tmp/kea6-ctrl-socket\",\n"
|
||||||
|
" \"user-context\": { \"comment\": \"Indirect comment\" }\n"
|
||||||
|
"},\n"
|
||||||
"\"shared-networks\": [ {\n"
|
"\"shared-networks\": [ {\n"
|
||||||
" \"name\": \"foo\"\n,"
|
|
||||||
" \"comment\": \"A shared network\"\n,"
|
" \"comment\": \"A shared network\"\n,"
|
||||||
|
" \"name\": \"foo\"\n,"
|
||||||
" \"subnet6\": [\n"
|
" \"subnet6\": [\n"
|
||||||
" { \n"
|
" { \n"
|
||||||
" \"subnet\": \"2001:db1::/48\",\n"
|
|
||||||
" \"comment\": \"A subnet\"\n,"
|
" \"comment\": \"A subnet\"\n,"
|
||||||
|
" \"subnet\": \"2001:db1::/48\",\n"
|
||||||
|
" \"id\": 100,\n"
|
||||||
" \"pools\": [\n"
|
" \"pools\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"pool\": \"2001:db1::/64\",\n"
|
" \"comment\": \"A pool\",\n"
|
||||||
" \"comment\": \"A pool\"\n"
|
" \"pool\": \"2001:db1::/64\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
" \"pd-pools\": [\n"
|
" \"pd-pools\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
|
" \"comment\": \"A prefix pool\",\n"
|
||||||
" \"prefix\": \"2001:db2::\",\n"
|
" \"prefix\": \"2001:db2::\",\n"
|
||||||
" \"prefix-len\": 48,\n"
|
" \"prefix-len\": 48,\n"
|
||||||
" \"delegated-len\": 64,\n"
|
" \"delegated-len\": 64\n"
|
||||||
" \"comment\": \"A prefix pool\"\n"
|
|
||||||
" }\n"
|
" }\n"
|
||||||
" ]\n"
|
" ],\n"
|
||||||
" }\n"
|
" \"reservations\": [\n"
|
||||||
" ]\n"
|
" {\n"
|
||||||
|
" \"comment\": \"A host reservation\",\n"
|
||||||
|
" \"hw-address\": \"AA:BB:CC:DD:EE:FF\",\n"
|
||||||
|
" \"hostname\": \"foo.example.com\",\n"
|
||||||
|
" \"option-data\": [ {\n"
|
||||||
|
" \"comment\": \"An option in a reservation\",\n"
|
||||||
|
" \"name\": \"domain-search\",\n"
|
||||||
|
" \"data\": \"example.com\"\n"
|
||||||
" } ]\n"
|
" } ]\n"
|
||||||
|
" }\n"
|
||||||
|
" ]\n"
|
||||||
|
" }\n"
|
||||||
|
" ]\n"
|
||||||
|
" } ],\n"
|
||||||
|
"\"dhcp-ddns\": {\n"
|
||||||
|
" \"comment\": \"No dynamic DNS\",\n"
|
||||||
|
" \"enable-updates\": false\n"
|
||||||
|
"}\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
extractConfig(config);
|
extractConfig(config);
|
||||||
@ -6125,8 +6156,32 @@ TEST_F(Dhcp6ParserTest, comments) {
|
|||||||
ASSERT_TRUE(ctx->get("comment"));
|
ASSERT_TRUE(ctx->get("comment"));
|
||||||
EXPECT_EQ("\"A DHCPv6 server\"", ctx->get("comment")->str());
|
EXPECT_EQ("\"A DHCPv6 server\"", ctx->get("comment")->str());
|
||||||
|
|
||||||
|
// There is a server id.
|
||||||
|
ConstCfgDUIDPtr duid = CfgMgr::instance().getStagingCfg()->getCfgDUID();
|
||||||
|
ASSERT_TRUE(duid);
|
||||||
|
EXPECT_EQ(DUID::DUID_LL, duid->getType());
|
||||||
|
|
||||||
|
// Check server id user context.
|
||||||
|
ConstElementPtr ctx_duid = duid->getContext();
|
||||||
|
ASSERT_TRUE(ctx_duid);
|
||||||
|
ASSERT_EQ(1, ctx_duid->size());
|
||||||
|
ASSERT_TRUE(ctx_duid->get("comment"));
|
||||||
|
EXPECT_EQ("\"DHCPv6 specific\"", ctx_duid->get("comment")->str());
|
||||||
|
|
||||||
|
// There is a network interface configuration.
|
||||||
|
ConstCfgIfacePtr iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
|
||||||
|
ASSERT_TRUE(iface);
|
||||||
|
|
||||||
|
// Check network interface configuration user context.
|
||||||
|
ConstElementPtr ctx_iface = iface->getContext();
|
||||||
|
ASSERT_TRUE(ctx_iface);
|
||||||
|
ASSERT_EQ(1, ctx_iface->size());
|
||||||
|
ASSERT_TRUE(ctx_iface->get("comment"));
|
||||||
|
EXPECT_EQ("\"Use wildcard\"", ctx_iface->get("comment")->str());
|
||||||
|
|
||||||
// There is a global option definition.
|
// There is a global option definition.
|
||||||
OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
|
const OptionDefinitionPtr& opt_def =
|
||||||
|
LibDHCP::getRuntimeOptionDef("isc", 100);
|
||||||
ASSERT_TRUE(opt_def);
|
ASSERT_TRUE(opt_def);
|
||||||
EXPECT_EQ("foo", opt_def->getName());
|
EXPECT_EQ("foo", opt_def->getName());
|
||||||
EXPECT_EQ(100, opt_def->getCode());
|
EXPECT_EQ(100, opt_def->getCode());
|
||||||
@ -6142,7 +6197,7 @@ TEST_F(Dhcp6ParserTest, comments) {
|
|||||||
EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
|
EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
|
||||||
|
|
||||||
// There is an option descriptor aka option data.
|
// There is an option descriptor aka option data.
|
||||||
OptionDescriptor opt_desc =
|
const OptionDescriptor& opt_desc =
|
||||||
CfgMgr::instance().getStagingCfg()->getCfgOption()->
|
CfgMgr::instance().getStagingCfg()->getCfgOption()->
|
||||||
get(DHCP6_OPTION_SPACE, D6O_SUBSCRIBER_ID);
|
get(DHCP6_OPTION_SPACE, D6O_SUBSCRIBER_ID);
|
||||||
ASSERT_TRUE(opt_desc.option_);
|
ASSERT_TRUE(opt_desc.option_);
|
||||||
@ -6156,7 +6211,7 @@ TEST_F(Dhcp6ParserTest, comments) {
|
|||||||
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
|
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
|
||||||
|
|
||||||
// And there there are some client classes.
|
// And there there are some client classes.
|
||||||
ClientClassDictionaryPtr dict =
|
const ClientClassDictionaryPtr& dict =
|
||||||
CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
|
CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
|
||||||
ASSERT_TRUE(dict);
|
ASSERT_TRUE(dict);
|
||||||
EXPECT_EQ(4, dict->getClasses()->size());
|
EXPECT_EQ(4, dict->getClasses()->size());
|
||||||
@ -6202,15 +6257,34 @@ TEST_F(Dhcp6ParserTest, comments) {
|
|||||||
ASSERT_TRUE(ctx_class->get("version"));
|
ASSERT_TRUE(ctx_class->get("version"));
|
||||||
EXPECT_EQ("1", ctx_class->get("version")->str());
|
EXPECT_EQ("1", ctx_class->get("version")->str());
|
||||||
|
|
||||||
|
// There is a control socket.
|
||||||
|
ConstElementPtr socket =
|
||||||
|
CfgMgr::instance().getStagingCfg()->getControlSocketInfo();
|
||||||
|
ASSERT_TRUE(socket);
|
||||||
|
ASSERT_TRUE(socket->get("socket-type"));
|
||||||
|
EXPECT_EQ("\"unix\"", socket->get("socket-type")->str());
|
||||||
|
ASSERT_TRUE(socket->get("socket-name"));
|
||||||
|
EXPECT_EQ("\"/tmp/kea6-ctrl-socket\"", socket->get("socket-name")->str());
|
||||||
|
|
||||||
|
// Check control socket comment and user context.
|
||||||
|
ConstElementPtr ctx_socket = socket->get("comment");
|
||||||
|
ASSERT_TRUE(ctx_socket);
|
||||||
|
EXPECT_EQ("\"REST API\"", ctx_socket->str());
|
||||||
|
ctx_socket = socket->get("user-context");
|
||||||
|
ASSERT_EQ(1, ctx_socket->size());
|
||||||
|
ASSERT_TRUE(ctx_socket->get("comment"));
|
||||||
|
EXPECT_EQ("\"Indirect comment\"", ctx_socket->get("comment")->str());
|
||||||
|
|
||||||
// Now verify that the shared network was indeed configured.
|
// Now verify that the shared network was indeed configured.
|
||||||
CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg()
|
const CfgSharedNetworks6Ptr& cfg_net =
|
||||||
->getCfgSharedNetworks6();
|
CfgMgr::instance().getStagingCfg()->getCfgSharedNetworks6();
|
||||||
ASSERT_TRUE(cfg_net);
|
ASSERT_TRUE(cfg_net);
|
||||||
const SharedNetwork6Collection* nets = cfg_net->getAll();
|
const SharedNetwork6Collection* nets = cfg_net->getAll();
|
||||||
ASSERT_TRUE(nets);
|
ASSERT_TRUE(nets);
|
||||||
ASSERT_EQ(1, nets->size());
|
ASSERT_EQ(1, nets->size());
|
||||||
SharedNetwork6Ptr net = nets->at(0);
|
SharedNetwork6Ptr net = nets->at(0);
|
||||||
ASSERT_TRUE(net);
|
ASSERT_TRUE(net);
|
||||||
|
EXPECT_EQ("foo", net->getName());
|
||||||
|
|
||||||
// Check shared network user context.
|
// Check shared network user context.
|
||||||
ConstElementPtr ctx_net = net->getContext();
|
ConstElementPtr ctx_net = net->getContext();
|
||||||
@ -6232,6 +6306,8 @@ TEST_F(Dhcp6ParserTest, comments) {
|
|||||||
ASSERT_EQ(1, ctx_sub->size());
|
ASSERT_EQ(1, ctx_sub->size());
|
||||||
ASSERT_TRUE(ctx_sub->get("comment"));
|
ASSERT_TRUE(ctx_sub->get("comment"));
|
||||||
EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str());
|
EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str());
|
||||||
|
EXPECT_EQ(100, sub->getID());
|
||||||
|
EXPECT_EQ("2001:db1::/48", sub->toText());
|
||||||
|
|
||||||
// The subnet has a pool.
|
// The subnet has a pool.
|
||||||
const PoolCollection& pools = sub->getPools(Lease::TYPE_NA);
|
const PoolCollection& pools = sub->getPools(Lease::TYPE_NA);
|
||||||
@ -6258,6 +6334,66 @@ TEST_F(Dhcp6ParserTest, comments) {
|
|||||||
ASSERT_EQ(1, ctx_pdpool->size());
|
ASSERT_EQ(1, ctx_pdpool->size());
|
||||||
ASSERT_TRUE(ctx_pdpool->get("comment"));
|
ASSERT_TRUE(ctx_pdpool->get("comment"));
|
||||||
EXPECT_EQ("\"A prefix pool\"", ctx_pdpool->get("comment")->str());
|
EXPECT_EQ("\"A prefix pool\"", ctx_pdpool->get("comment")->str());
|
||||||
|
|
||||||
|
// The subnet has a host reservation.
|
||||||
|
uint8_t hw[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
|
||||||
|
HWAddrPtr hwaddr(new HWAddr(hw, sizeof(hw), HTYPE_ETHER));
|
||||||
|
ConstHostPtr host =
|
||||||
|
CfgMgr::instance().getStagingCfg()->getCfgHosts()->get6(100, DuidPtr(), hwaddr);
|
||||||
|
ASSERT_TRUE(host);
|
||||||
|
EXPECT_EQ(Host::IDENT_HWADDR, host->getIdentifierType());
|
||||||
|
EXPECT_EQ("aa:bb:cc:dd:ee:ff", host->getHWAddress()->toText(false));
|
||||||
|
EXPECT_FALSE(host->getDuid());
|
||||||
|
EXPECT_EQ(0, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(100, host->getIPv6SubnetID());
|
||||||
|
EXPECT_EQ("foo.example.com", host->getHostname());
|
||||||
|
|
||||||
|
// Check host user context.
|
||||||
|
ConstElementPtr ctx_host = host->getContext();
|
||||||
|
ASSERT_TRUE(ctx_host);
|
||||||
|
ASSERT_EQ(1, ctx_host->size());
|
||||||
|
ASSERT_TRUE(ctx_host->get("comment"));
|
||||||
|
EXPECT_EQ("\"A host reservation\"", ctx_host->get("comment")->str());
|
||||||
|
|
||||||
|
// The host reservation has an option data.
|
||||||
|
ConstCfgOptionPtr opts = host->getCfgOption6();
|
||||||
|
ASSERT_TRUE(opts);
|
||||||
|
EXPECT_FALSE(opts->empty());
|
||||||
|
const OptionDescriptor& host_desc =
|
||||||
|
opts->get(DHCP6_OPTION_SPACE, D6O_DOMAIN_SEARCH);
|
||||||
|
ASSERT_TRUE(host_desc.option_);
|
||||||
|
EXPECT_EQ(D6O_DOMAIN_SEARCH, host_desc.option_->getType());
|
||||||
|
|
||||||
|
// Check embedded option data user context.
|
||||||
|
ConstElementPtr ctx_host_desc = host_desc.getContext();
|
||||||
|
ASSERT_TRUE(ctx_host_desc);
|
||||||
|
ASSERT_EQ(1, ctx_host_desc->size());
|
||||||
|
ASSERT_TRUE(ctx_host_desc->get("comment"));
|
||||||
|
EXPECT_EQ("\"An option in a reservation\"",
|
||||||
|
ctx_host_desc->get("comment")->str());
|
||||||
|
|
||||||
|
// Finally dynamic DNS update configuration.
|
||||||
|
const D2ClientConfigPtr& d2 =
|
||||||
|
CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
|
||||||
|
ASSERT_TRUE(d2);
|
||||||
|
EXPECT_FALSE(d2->getEnableUpdates());
|
||||||
|
|
||||||
|
// Check dynamic DNS update configuration user context.
|
||||||
|
ConstElementPtr ctx_d2 = d2->getContext();
|
||||||
|
ASSERT_TRUE(ctx_d2);
|
||||||
|
ASSERT_EQ(1, ctx_d2->size());
|
||||||
|
ASSERT_TRUE(ctx_d2->get("comment"));
|
||||||
|
EXPECT_EQ("\"No dynamic DNS\"", ctx_d2->get("comment")->str());
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Loggers section supports comments too.
|
||||||
|
|
||||||
|
string logging = "{\n"
|
||||||
|
"\"loggers\": [ {\n"
|
||||||
|
" \"comment\": \"A logger\",\n"
|
||||||
|
" \"name\": \"kea-dhcp6\"\n"
|
||||||
|
"} ]\n";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <dhcp6/tests/dhcp6_test_utils.h>
|
#include <dhcp6/tests/dhcp6_test_utils.h>
|
||||||
#include <dhcp6/tests/get_config_unittest.h>
|
#include <dhcp6/tests/get_config_unittest.h>
|
||||||
#include <dhcp6/dhcp6_srv.h>
|
#include <dhcp6/dhcp6_srv.h>
|
||||||
|
#include <dhcp6/ctrl_dhcp6_srv.h>
|
||||||
#include <dhcp6/json_config_parser.h>
|
#include <dhcp6/json_config_parser.h>
|
||||||
#include <dhcpsrv/parsers/simple_parser6.h>
|
#include <dhcpsrv/parsers/simple_parser6.h>
|
||||||
|
|
||||||
@ -1531,6 +1532,23 @@ const char* EXTRACTED_CONFIGS[] = {
|
|||||||
" }\n"
|
" }\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"control-socket\": {\n"
|
||||||
|
" \"comment\": \"REST API\",\n"
|
||||||
|
" \"socket-name\": \"/tmp/kea6-ctrl-socket\",\n"
|
||||||
|
" \"socket-type\": \"unix\",\n"
|
||||||
|
" \"user-context\": {\n"
|
||||||
|
" \"comment\": \"Indirect comment\"\n"
|
||||||
|
" }\n"
|
||||||
|
" },\n"
|
||||||
|
" \"dhcp-ddns\": {\n"
|
||||||
|
" \"comment\": \"No dynamic DNS\",\n"
|
||||||
|
" \"enable-updates\": false\n"
|
||||||
|
" },\n"
|
||||||
|
" \"interfaces-config\": {\n"
|
||||||
|
" \"comment\": \"Use wildcard\",\n"
|
||||||
|
" \"interfaces\": [ \"*\" ],\n"
|
||||||
|
" \"re-detect\": false\n"
|
||||||
|
" },\n"
|
||||||
" \"option-data\": [\n"
|
" \"option-data\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"Set option value\",\n"
|
" \"comment\": \"Set option value\",\n"
|
||||||
@ -1548,6 +1566,10 @@ const char* EXTRACTED_CONFIGS[] = {
|
|||||||
" \"type\": \"ipv6-address\"\n"
|
" \"type\": \"ipv6-address\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"server-id\": {\n"
|
||||||
|
" \"comment\": \"DHCPv6 specific\",\n"
|
||||||
|
" \"type\": \"LL\"\n"
|
||||||
|
" },\n"
|
||||||
" \"shared-networks\": [\n"
|
" \"shared-networks\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"A shared network\",\n"
|
" \"comment\": \"A shared network\",\n"
|
||||||
@ -1555,6 +1577,7 @@ const char* EXTRACTED_CONFIGS[] = {
|
|||||||
" \"subnet6\": [\n"
|
" \"subnet6\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"A subnet\",\n"
|
" \"comment\": \"A subnet\",\n"
|
||||||
|
" \"id\": 100,\n"
|
||||||
" \"pd-pools\": [\n"
|
" \"pd-pools\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"A prefix pool\",\n"
|
" \"comment\": \"A prefix pool\",\n"
|
||||||
@ -1569,6 +1592,20 @@ const char* EXTRACTED_CONFIGS[] = {
|
|||||||
" \"pool\": \"2001:db1::/64\"\n"
|
" \"pool\": \"2001:db1::/64\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"reservations\": [\n"
|
||||||
|
" {\n"
|
||||||
|
" \"comment\": \"A host reservation\",\n"
|
||||||
|
" \"hostname\": \"foo.example.com\",\n"
|
||||||
|
" \"hw-address\": \"AA:BB:CC:DD:EE:FF\",\n"
|
||||||
|
" \"option-data\": [\n"
|
||||||
|
" {\n"
|
||||||
|
" \"comment\": \"An option in a reservation\",\n"
|
||||||
|
" \"data\": \"example.com\",\n"
|
||||||
|
" \"name\": \"domain-search\"\n"
|
||||||
|
" }\n"
|
||||||
|
" ]\n"
|
||||||
|
" }\n"
|
||||||
|
" ],\n"
|
||||||
" \"subnet\": \"2001:db1::/48\"\n"
|
" \"subnet\": \"2001:db1::/48\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ]\n"
|
" ]\n"
|
||||||
@ -5974,8 +6011,17 @@ const char* UNPARSED_CONFIGS[] = {
|
|||||||
" \"option-data\": [ ]\n"
|
" \"option-data\": [ ]\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"control-socket\": {\n"
|
||||||
|
" \"comment\": \"REST API\",\n"
|
||||||
|
" \"socket-name\": \"/tmp/kea6-ctrl-socket\",\n"
|
||||||
|
" \"socket-type\": \"unix\",\n"
|
||||||
|
" \"user-context\": {\n"
|
||||||
|
" \"comment\": \"Indirect comment\"\n"
|
||||||
|
" }\n"
|
||||||
|
" },\n"
|
||||||
" \"decline-probation-period\": 86400,\n"
|
" \"decline-probation-period\": 86400,\n"
|
||||||
" \"dhcp-ddns\": {\n"
|
" \"dhcp-ddns\": {\n"
|
||||||
|
" \"comment\": \"No dynamic DNS\",\n"
|
||||||
" \"always-include-fqdn\": false,\n"
|
" \"always-include-fqdn\": false,\n"
|
||||||
" \"enable-updates\": false,\n"
|
" \"enable-updates\": false,\n"
|
||||||
" \"generated-prefix\": \"myhost\",\n"
|
" \"generated-prefix\": \"myhost\",\n"
|
||||||
@ -6003,7 +6049,8 @@ const char* UNPARSED_CONFIGS[] = {
|
|||||||
" \"hooks-libraries\": [ ],\n"
|
" \"hooks-libraries\": [ ],\n"
|
||||||
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
|
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
|
||||||
" \"interfaces-config\": {\n"
|
" \"interfaces-config\": {\n"
|
||||||
" \"interfaces\": [ ],\n"
|
" \"comment\": \"Use wildcard\",\n"
|
||||||
|
" \"interfaces\": [ \"*\" ],\n"
|
||||||
" \"re-detect\": false\n"
|
" \"re-detect\": false\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" \"lease-database\": {\n"
|
" \"lease-database\": {\n"
|
||||||
@ -6035,12 +6082,13 @@ const char* UNPARSED_CONFIGS[] = {
|
|||||||
" ],\n"
|
" ],\n"
|
||||||
" \"relay-supplied-options\": [ \"65\" ],\n"
|
" \"relay-supplied-options\": [ \"65\" ],\n"
|
||||||
" \"server-id\": {\n"
|
" \"server-id\": {\n"
|
||||||
|
" \"comment\": \"DHCPv6 specific\",\n"
|
||||||
" \"enterprise-id\": 0,\n"
|
" \"enterprise-id\": 0,\n"
|
||||||
" \"htype\": 0,\n"
|
" \"htype\": 0,\n"
|
||||||
" \"identifier\": \"\",\n"
|
" \"identifier\": \"\",\n"
|
||||||
" \"persist\": true,\n"
|
" \"persist\": true,\n"
|
||||||
" \"time\": 0,\n"
|
" \"time\": 0,\n"
|
||||||
" \"type\": \"LLT\"\n"
|
" \"type\": \"LL\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" \"shared-networks\": [\n"
|
" \"shared-networks\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
@ -6058,7 +6106,7 @@ const char* UNPARSED_CONFIGS[] = {
|
|||||||
" \"subnet6\": [\n"
|
" \"subnet6\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" \"comment\": \"A subnet\",\n"
|
" \"comment\": \"A subnet\",\n"
|
||||||
" \"id\": 1,\n"
|
" \"id\": 100,\n"
|
||||||
" \"option-data\": [ ],\n"
|
" \"option-data\": [ ],\n"
|
||||||
" \"pd-pools\": [\n"
|
" \"pd-pools\": [\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
@ -6294,7 +6342,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
|
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
|
||||||
Dhcpv6Srv srv_; ///< Instance of the Dhcp6Srv used during tests
|
ControlledDhcpv6Srv srv_; ///< Instance of the ControlledDhcp6Srv used during tests
|
||||||
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
|
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <dhcp6/tests/dhcp6_test_utils.h>
|
#include <dhcp6/tests/dhcp6_test_utils.h>
|
||||||
#include <dhcp6/tests/get_config_unittest.h>
|
#include <dhcp6/tests/get_config_unittest.h>
|
||||||
#include <dhcp6/dhcp6_srv.h>
|
#include <dhcp6/dhcp6_srv.h>
|
||||||
|
#include <dhcp6/ctrl_dhcp6_srv.h>
|
||||||
#include <dhcp6/json_config_parser.h>
|
#include <dhcp6/json_config_parser.h>
|
||||||
#include <dhcpsrv/parsers/simple_parser6.h>
|
#include <dhcpsrv/parsers/simple_parser6.h>
|
||||||
|
|
||||||
@ -275,7 +276,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
|
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
|
||||||
Dhcpv6Srv srv_; ///< Instance of the Dhcp6Srv used during tests
|
ControlledDhcpv6Srv srv_; ///< Instance of the ControlledDhcp6Srv used during tests
|
||||||
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
|
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,12 +65,12 @@ CfgDbAccess::getAccessString(const std::string& access_string) const {
|
|||||||
return (s.str());
|
return (s.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
ElementPtr
|
||||||
CfgDbAccess::toElementDbAccessString(const std::string& dbaccess,
|
CfgDbAccess::toElementDbAccessString(const std::string& dbaccess) {
|
||||||
ElementPtr map) {
|
ElementPtr result = Element::createMap();
|
||||||
// Code from DatabaseConnection::parse
|
// Code from DatabaseConnection::parse
|
||||||
if (dbaccess.empty()) {
|
if (dbaccess.empty()) {
|
||||||
return;
|
return (result);
|
||||||
}
|
}
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens;
|
||||||
boost::split(tokens, dbaccess, boost::is_any_of(std::string("\t ")));
|
boost::split(tokens, dbaccess, boost::is_any_of(std::string("\t ")));
|
||||||
@ -86,7 +86,7 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess,
|
|||||||
int64_t int_value;
|
int64_t int_value;
|
||||||
try {
|
try {
|
||||||
int_value = boost::lexical_cast<int64_t>(value);
|
int_value = boost::lexical_cast<int64_t>(value);
|
||||||
map->set(keyword, Element::create(int_value));
|
result->set(keyword, Element::create(int_value));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
isc_throw(ToElementError, "invalid DB access "
|
isc_throw(ToElementError, "invalid DB access "
|
||||||
<< "integer parameter: "
|
<< "integer parameter: "
|
||||||
@ -95,9 +95,9 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess,
|
|||||||
} else if ((keyword == "persist") ||
|
} else if ((keyword == "persist") ||
|
||||||
(keyword == "readonly")) {
|
(keyword == "readonly")) {
|
||||||
if (value == "true") {
|
if (value == "true") {
|
||||||
map->set(keyword, Element::create(true));
|
result->set(keyword, Element::create(true));
|
||||||
} else if (value == "false") {
|
} else if (value == "false") {
|
||||||
map->set(keyword, Element::create(false));
|
result->set(keyword, Element::create(false));
|
||||||
} else {
|
} else {
|
||||||
isc_throw(ToElementError, "invalid DB access "
|
isc_throw(ToElementError, "invalid DB access "
|
||||||
<< "boolean parameter: "
|
<< "boolean parameter: "
|
||||||
@ -110,7 +110,7 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess,
|
|||||||
(keyword == "name") ||
|
(keyword == "name") ||
|
||||||
(keyword == "contact_points") ||
|
(keyword == "contact_points") ||
|
||||||
(keyword == "keyspace")) {
|
(keyword == "keyspace")) {
|
||||||
map->set(keyword, Element::create(value));
|
result->set(keyword, Element::create(value));
|
||||||
} else {
|
} else {
|
||||||
isc_throw(ToElementError, "unknown DB access parameter: "
|
isc_throw(ToElementError, "unknown DB access parameter: "
|
||||||
<< keyword << "=" << value);
|
<< keyword << "=" << value);
|
||||||
@ -120,23 +120,6 @@ CfgDbAccess::toElementDbAccessString(const std::string& dbaccess,
|
|||||||
<< ", expected format is name=value");
|
<< ", expected format is name=value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ElementPtr
|
|
||||||
CfgLeaseDbAccess::toElement() const {
|
|
||||||
ElementPtr result = Element::createMap();
|
|
||||||
// Add user context
|
|
||||||
contextToElement(result);
|
|
||||||
CfgDbAccess::toElementDbAccessString(lease_db_access_, result);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
ElementPtr
|
|
||||||
CfgHostDbAccess::toElement() const {
|
|
||||||
ElementPtr result = Element::createMap();
|
|
||||||
// Add user context
|
|
||||||
contextToElement(result);
|
|
||||||
CfgDbAccess::toElementDbAccessString(host_db_access_, result);
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#define CFG_DBACCESS_H
|
#define CFG_DBACCESS_H
|
||||||
|
|
||||||
#include <cc/cfg_to_element.h>
|
#include <cc/cfg_to_element.h>
|
||||||
#include <cc/user_context.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -20,7 +19,7 @@ namespace dhcp {
|
|||||||
///
|
///
|
||||||
/// The database access strings use the same format as the strings
|
/// The database access strings use the same format as the strings
|
||||||
/// passed to the @ref isc::dhcp::LeaseMgrFactory::create function.
|
/// passed to the @ref isc::dhcp::LeaseMgrFactory::create function.
|
||||||
class CfgDbAccess : public UserContext {
|
class CfgDbAccess {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @brief Constructor.
|
/// @brief Constructor.
|
||||||
@ -68,10 +67,9 @@ public:
|
|||||||
/// @brief Unparse an access string
|
/// @brief Unparse an access string
|
||||||
///
|
///
|
||||||
/// @param dbaccess the database access string
|
/// @param dbaccess the database access string
|
||||||
/// @param map the element map where the access string is unparse
|
/// @return a pointer to configuration
|
||||||
static void
|
static
|
||||||
toElementDbAccessString(const std::string& dbaccess,
|
isc::data::ElementPtr toElementDbAccessString(const std::string& dbaccess);
|
||||||
isc::data::ElementPtr map);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -108,7 +106,9 @@ struct CfgLeaseDbAccess : public CfgDbAccess, public isc::data::CfgToElement {
|
|||||||
/// @ref isc::data::CfgToElement::toElement
|
/// @ref isc::data::CfgToElement::toElement
|
||||||
///
|
///
|
||||||
/// @result a pointer to a configuration
|
/// @result a pointer to a configuration
|
||||||
virtual isc::data::ElementPtr toElement() const;
|
virtual isc::data::ElementPtr toElement() const {
|
||||||
|
return (CfgDbAccess::toElementDbAccessString(lease_db_access_));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CfgHostDbAccess : public CfgDbAccess, public isc::data::CfgToElement {
|
struct CfgHostDbAccess : public CfgDbAccess, public isc::data::CfgToElement {
|
||||||
@ -120,9 +120,12 @@ struct CfgHostDbAccess : public CfgDbAccess, public isc::data::CfgToElement {
|
|||||||
/// @ref isc::data::CfgToElement::toElement
|
/// @ref isc::data::CfgToElement::toElement
|
||||||
///
|
///
|
||||||
/// @result a pointer to a configuration
|
/// @result a pointer to a configuration
|
||||||
virtual isc::data::ElementPtr toElement() const;
|
virtual isc::data::ElementPtr toElement() const {
|
||||||
|
return (CfgDbAccess::toElementDbAccessString(host_db_access_));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CFG_DBACCESS_H
|
#endif // CFG_DBACCESS_H
|
||||||
|
@ -56,7 +56,6 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db,
|
|||||||
int64_t lfc_interval = 0;
|
int64_t lfc_interval = 0;
|
||||||
int64_t timeout = 0;
|
int64_t timeout = 0;
|
||||||
int64_t port = 0;
|
int64_t port = 0;
|
||||||
ConstElementPtr user_context;
|
|
||||||
// 2. Update the copy with the passed keywords.
|
// 2. Update the copy with the passed keywords.
|
||||||
BOOST_FOREACH(ConfigPair param, database_config->mapValue()) {
|
BOOST_FOREACH(ConfigPair param, database_config->mapValue()) {
|
||||||
try {
|
try {
|
||||||
@ -79,9 +78,6 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db,
|
|||||||
values_copy[param.first] =
|
values_copy[param.first] =
|
||||||
boost::lexical_cast<std::string>(port);
|
boost::lexical_cast<std::string>(port);
|
||||||
|
|
||||||
} else if (param.first == "user-context") {
|
|
||||||
user_context = param.second;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
values_copy[param.first] = param.second->stringValue();
|
values_copy[param.first] = param.second->stringValue();
|
||||||
}
|
}
|
||||||
@ -162,9 +158,6 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db,
|
|||||||
cfg_db->setHostDbAccessString(getDbAccessString());
|
cfg_db->setHostDbAccessString(getDbAccessString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_context) {
|
|
||||||
cfg_db->setContext(user_context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the database access string
|
// Create the database access string
|
||||||
|
@ -19,7 +19,6 @@ using namespace isc;
|
|||||||
using namespace isc::dhcp;
|
using namespace isc::dhcp;
|
||||||
using namespace isc::dhcp::test;
|
using namespace isc::dhcp::test;
|
||||||
using namespace isc::test;
|
using namespace isc::test;
|
||||||
using namespace isc::data;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -52,12 +51,6 @@ TEST(CfgDbAccessTest, setLeaseDbAccessString) {
|
|||||||
// Additional parameters are not in lease_db_access_
|
// Additional parameters are not in lease_db_access_
|
||||||
runToElementTest<CfgLeaseDbAccess>(expected, CfgLeaseDbAccess(cfg));
|
runToElementTest<CfgLeaseDbAccess>(expected, CfgLeaseDbAccess(cfg));
|
||||||
|
|
||||||
// Add and check user context
|
|
||||||
std::string user_context = "{ \"foo\": \"bar\" }";
|
|
||||||
cfg.setContext(Element::fromJSON(user_context));
|
|
||||||
expected = "{ \"user-context\": { \"foo\": \"bar\" }, \"type\": \"mysql\" }";
|
|
||||||
runToElementTest<CfgLeaseDbAccess>(expected, CfgLeaseDbAccess(cfg));
|
|
||||||
|
|
||||||
// If access string is empty, no parameters will be appended.
|
// If access string is empty, no parameters will be appended.
|
||||||
ASSERT_NO_THROW(cfg.setLeaseDbAccessString(""));
|
ASSERT_NO_THROW(cfg.setLeaseDbAccessString(""));
|
||||||
EXPECT_TRUE(cfg.getLeaseDbAccessString().empty());
|
EXPECT_TRUE(cfg.getLeaseDbAccessString().empty());
|
||||||
@ -82,12 +75,6 @@ TEST(CfgDbAccessTest, setHostDbAccessString) {
|
|||||||
// Additional parameters are not in host_db_access_
|
// Additional parameters are not in host_db_access_
|
||||||
runToElementTest<CfgHostDbAccess>(expected, CfgHostDbAccess(cfg));
|
runToElementTest<CfgHostDbAccess>(expected, CfgHostDbAccess(cfg));
|
||||||
|
|
||||||
// Add and check user context
|
|
||||||
std::string user_context = "{ \"foo\": \"bar\" }";
|
|
||||||
cfg.setContext(Element::fromJSON(user_context));
|
|
||||||
expected = "{ \"user-context\": { \"foo\": \"bar\" }, \"type\": \"mysql\" }";
|
|
||||||
runToElementTest<CfgHostDbAccess>(expected, CfgHostDbAccess(cfg));
|
|
||||||
|
|
||||||
// If access string is empty, no parameters will be appended.
|
// If access string is empty, no parameters will be appended.
|
||||||
ASSERT_NO_THROW(cfg.setHostDbAccessString(""));
|
ASSERT_NO_THROW(cfg.setHostDbAccessString(""));
|
||||||
EXPECT_TRUE(cfg.getHostDbAccessString().empty());
|
EXPECT_TRUE(cfg.getHostDbAccessString().empty());
|
||||||
|
@ -78,6 +78,9 @@ EP moveComments1(EP element) {
|
|||||||
} else if (it->first == "user-context") {
|
} else if (it->first == "user-context") {
|
||||||
// Do not traverse user-context entries
|
// Do not traverse user-context entries
|
||||||
result->set("user-context", it->second);
|
result->set("user-context", it->second);
|
||||||
|
} else if (it->first == "control-socket") {
|
||||||
|
// Do not traverse control-socke entries
|
||||||
|
result->set("control-socket", it->second);
|
||||||
} else {
|
} else {
|
||||||
// Not comment or user-context
|
// Not comment or user-context
|
||||||
try {
|
try {
|
||||||
@ -171,6 +174,9 @@ EP extractComments1(EP element) {
|
|||||||
if (it->first == "comment") {
|
if (it->first == "comment") {
|
||||||
// Do not traverse comment entries
|
// Do not traverse comment entries
|
||||||
result->set("comment", it->second);
|
result->set("comment", it->second);
|
||||||
|
} else if (it->first == "control-socket") {
|
||||||
|
// Do not traverse control-socke entries
|
||||||
|
result->set("control-socket", it->second);
|
||||||
} else if (it->first == "user-context") {
|
} else if (it->first == "user-context") {
|
||||||
if (it->second->contains("comment")) {
|
if (it->second->contains("comment")) {
|
||||||
// Note there is a entry to move
|
// Note there is a entry to move
|
||||||
|
Loading…
x
Reference in New Issue
Block a user