From b6a202af8920d8f9bec57ea37c65f878b732c6ef Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Wed, 29 Nov 2017 04:20:38 +0100 Subject: [PATCH] [5351] Last fix lost reservations: better fix now --- src/bin/dhcp4/tests/get_config_unittest.cc | 108 +++++++++++++++ .../dhcp4/tests/get_config_unittest.cc.skel | 1 + src/bin/dhcp6/tests/config_parser_unittest.cc | 90 ++++++++++++ src/bin/dhcp6/tests/get_config_unittest.cc | 130 ++++++++++++++++++ .../dhcp6/tests/get_config_unittest.cc.skel | 1 + src/lib/dhcpsrv/srv_config.cc | 33 ++--- 6 files changed, 347 insertions(+), 16 deletions(-) diff --git a/src/bin/dhcp4/tests/get_config_unittest.cc b/src/bin/dhcp4/tests/get_config_unittest.cc index 5ee6aca358..222edb15bf 100644 --- a/src/bin/dhcp4/tests/get_config_unittest.cc +++ b/src/bin/dhcp4/tests/get_config_unittest.cc @@ -1584,6 +1584,27 @@ const char* EXTRACTED_CONFIGS[] = { " }\n" " ],\n" " \"valid-lifetime\": 4000\n" +" }\n", + // CONFIGURATION 58 +"{\n" +" \"shared-networks\": [\n" +" {\n" +" \"comment\": \"A shared-network\",\n" +" \"name\": \"foo\",\n" +" \"subnet4\": [\n" +" {\n" +" \"comment\": \"A subnet\",\n" +" \"pools\": [\n" +" {\n" +" \"comment\": \"A pool\",\n" +" \"pool\": \"192.0.1.1-192.0.1.10\"\n" +" }\n" +" ],\n" +" \"subnet\": \"192.0.1.0/24\"\n" +" }\n" +" ]\n" +" }\n" +" ]\n" " }\n" }; @@ -6227,6 +6248,92 @@ const char* UNPARSED_CONFIGS[] = { " \"valid-lifetime\": 4000\n" " }\n" " ]\n" +" }\n", + // CONFIGURATION 58 +"{\n" +" \"decline-probation-period\": 86400,\n" +" \"dhcp-ddns\": {\n" +" \"always-include-fqdn\": false,\n" +" \"enable-updates\": false,\n" +" \"generated-prefix\": \"myhost\",\n" +" \"max-queue-size\": 1024,\n" +" \"ncr-format\": \"JSON\",\n" +" \"ncr-protocol\": \"UDP\",\n" +" \"override-client-update\": false,\n" +" \"override-no-update\": false,\n" +" \"qualifying-suffix\": \"\",\n" +" \"replace-client-name\": \"never\",\n" +" \"sender-ip\": \"0.0.0.0\",\n" +" \"sender-port\": 0,\n" +" \"server-ip\": \"127.0.0.1\",\n" +" \"server-port\": 53001\n" +" },\n" +" \"dhcp4o6-port\": 0,\n" +" \"echo-client-id\": true,\n" +" \"expired-leases-processing\": {\n" +" \"flush-reclaimed-timer-wait-time\": 25,\n" +" \"hold-reclaimed-time\": 3600,\n" +" \"max-reclaim-leases\": 100,\n" +" \"max-reclaim-time\": 250,\n" +" \"reclaim-timer-wait-time\": 10,\n" +" \"unwarned-reclaim-cycles\": 5\n" +" },\n" +" \"hooks-libraries\": [ ],\n" +" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n" +" \"interfaces-config\": {\n" +" \"interfaces\": [ ],\n" +" \"re-detect\": false\n" +" },\n" +" \"lease-database\": {\n" +" \"type\": \"memfile\"\n" +" },\n" +" \"option-data\": [ ],\n" +" \"option-def\": [ ],\n" +" \"shared-networks\": [\n" +" {\n" +" \"comment\": \"A shared-network\",\n" +" \"match-client-id\": true,\n" +" \"name\": \"foo\",\n" +" \"option-data\": [ ],\n" +" \"rebind-timer\": 0,\n" +" \"relay\": {\n" +" \"ip-address\": \"0.0.0.0\"\n" +" },\n" +" \"renew-timer\": 0,\n" +" \"reservation-mode\": \"all\",\n" +" \"subnet4\": [\n" +" {\n" +" \"comment\": \"A subnet\",\n" +" \"4o6-interface\": \"\",\n" +" \"4o6-interface-id\": \"\",\n" +" \"4o6-subnet\": \"\",\n" +" \"boot-file-name\": \"\",\n" +" \"id\": 1,\n" +" \"match-client-id\": true,\n" +" \"next-server\": \"0.0.0.0\",\n" +" \"option-data\": [ ],\n" +" \"pools\": [\n" +" {\n" +" \"comment\": \"A pool\",\n" +" \"option-data\": [ ],\n" +" \"pool\": \"192.0.1.1-192.0.1.10\"\n" +" }\n" +" ],\n" +" \"rebind-timer\": 1800,\n" +" \"relay\": {\n" +" \"ip-address\": \"0.0.0.0\"\n" +" },\n" +" \"renew-timer\": 900,\n" +" \"reservation-mode\": \"all\",\n" +" \"server-hostname\": \"\",\n" +" \"subnet\": \"192.0.1.0/24\",\n" +" \"valid-lifetime\": 7200\n" +" }\n" +" ],\n" +" \"valid-lifetime\": 0\n" +" }\n" +" ],\n" +" \"subnet4\": [ ]\n" " }\n" }; @@ -6474,6 +6581,7 @@ TEST_P(Dhcp4GetConfigTest, run) { expected = UNPARSED_CONFIGS[config_counter]; ConstElementPtr json; ASSERT_NO_THROW(json = parseDHCP4(expected, true)); + ASSERT_NO_THROW(json = parseJSON(expected)); EXPECT_TRUE(isEquivalent(dhcp, json)); std::string current = prettyPrint(dhcp, 4, 4) + "\n"; EXPECT_EQ(expected, current); diff --git a/src/bin/dhcp4/tests/get_config_unittest.cc.skel b/src/bin/dhcp4/tests/get_config_unittest.cc.skel index 19a8ddc2a0..68d8f165d7 100644 --- a/src/bin/dhcp4/tests/get_config_unittest.cc.skel +++ b/src/bin/dhcp4/tests/get_config_unittest.cc.skel @@ -317,6 +317,7 @@ TEST_P(Dhcp4GetConfigTest, run) { expected = UNPARSED_CONFIGS[config_counter]; ConstElementPtr json; ASSERT_NO_THROW(json = parseDHCP4(expected, true)); + ASSERT_NO_THROW(json = parseJSON(expected)); EXPECT_TRUE(isEquivalent(dhcp, json)); std::string current = prettyPrint(dhcp, 4, 4) + "\n"; EXPECT_EQ(expected, current); diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index 946ba5cb9c..d6f9073d06 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -6049,5 +6049,95 @@ TEST_F(Dhcp6ParserTest, sharedNetworksRapidCommitMix) { "shared-network or the shared-network itself used rapid-commit true"); } +// This test checks comments. Please keep it last. +TEST_F(Dhcp6ParserTest, comments) { + + string config = "{\n" + "\"shared-networks\": [ {\n" + " \"name\": \"foo\"\n," + " \"comment\": \"A shared-network\"\n," + " \"subnet6\": [\n" + " { \n" + " \"subnet\": \"2001:db1::/48\",\n" + " \"comment\": \"A subnet\"\n," + " \"pools\": [\n" + " {\n" + " \"pool\": \"2001:db1::/64\",\n" + " \"comment\": \"A pool\"\n" + " }\n" + " ],\n" + " \"pd-pools\": [\n" + " {\n" + " \"prefix\": \"2001:db2::\",\n" + " \"prefix-len\": 48,\n" + " \"delegated-len\": 64,\n" + " \"comment\": \"A prefix pool\"\n" + " }\n" + " ]\n" + " }\n" + " ]\n" + " } ]\n" + "} \n"; + + extractConfig(config); + configure(config, CONTROL_RESULT_SUCCESS, ""); + + // Now verify that the shared network was indeed configured. + CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg() + ->getCfgSharedNetworks6(); + ASSERT_TRUE(cfg_net); + const SharedNetwork6Collection* nets = cfg_net->getAll(); + ASSERT_TRUE(nets); + ASSERT_EQ(1, nets->size()); + SharedNetwork6Ptr net = nets->at(0); + ASSERT_TRUE(net); + + // Check shared network user context + ConstElementPtr ctx_net = net->getContext(); + 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()); + + // The shared network has a subnet. + const Subnet6Collection * subs = net->getAllSubnets(); + ASSERT_TRUE(subs); + ASSERT_EQ(1, subs->size()); + Subnet6Ptr sub = subs->at(0); + ASSERT_TRUE(sub); + + // Check subnet user context + ConstElementPtr ctx_sub = sub->getContext(); + ASSERT_TRUE(ctx_sub); + ASSERT_EQ(1, ctx_sub->size()); + ASSERT_TRUE(ctx_sub->get("comment")); + EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str()); + + // The subnet has a pool + const PoolCollection& pools = sub->getPools(Lease::TYPE_NA); + ASSERT_EQ(1, pools.size()); + PoolPtr pool = pools.at(0); + ASSERT_TRUE(pool); + + // Check pool user context + ConstElementPtr ctx_pool = pool->getContext(); + ASSERT_TRUE(ctx_pool); + ASSERT_EQ(1, ctx_pool->size()); + ASSERT_TRUE(ctx_pool->get("comment")); + EXPECT_EQ("\"A pool\"", ctx_pool->get("comment")->str()); + + // The subnet has a prefix pool + const PoolCollection& pdpools = sub->getPools(Lease::TYPE_PD); + ASSERT_EQ(1, pdpools.size()); + PoolPtr pdpool = pdpools.at(0); + ASSERT_TRUE(pdpool); + + // Check prefix pool user context + ConstElementPtr ctx_pdpool = pdpool->getContext(); + ASSERT_TRUE(ctx_pdpool); + ASSERT_EQ(1, ctx_pdpool->size()); + ASSERT_TRUE(ctx_pdpool->get("comment")); + EXPECT_EQ("\"A prefix pool\"", ctx_pdpool->get("comment")->str()); +} }; diff --git a/src/bin/dhcp6/tests/get_config_unittest.cc b/src/bin/dhcp6/tests/get_config_unittest.cc index dae152ebc2..22a3a81ede 100644 --- a/src/bin/dhcp6/tests/get_config_unittest.cc +++ b/src/bin/dhcp6/tests/get_config_unittest.cc @@ -1459,6 +1459,35 @@ const char* EXTRACTED_CONFIGS[] = { " }\n" " ],\n" " \"valid-lifetime\": 4000\n" +" }\n", + // CONFIGURATION 51 +"{\n" +" \"shared-networks\": [\n" +" {\n" +" \"comment\": \"A shared-network\",\n" +" \"name\": \"foo\",\n" +" \"subnet6\": [\n" +" {\n" +" \"comment\": \"A subnet\",\n" +" \"pd-pools\": [\n" +" {\n" +" \"comment\": \"A prefix pool\",\n" +" \"delegated-len\": 64,\n" +" \"prefix\": \"2001:db2::\",\n" +" \"prefix-len\": 48\n" +" }\n" +" ],\n" +" \"pools\": [\n" +" {\n" +" \"comment\": \"A pool\",\n" +" \"pool\": \"2001:db1::/64\"\n" +" }\n" +" ],\n" +" \"subnet\": \"2001:db1::/48\"\n" +" }\n" +" ]\n" +" }\n" +" ]\n" " }\n" }; @@ -5830,6 +5859,106 @@ const char* UNPARSED_CONFIGS[] = { " \"valid-lifetime\": 4000\n" " }\n" " ]\n" +" }\n", + // CONFIGURATION 51 +"{\n" +" \"decline-probation-period\": 86400,\n" +" \"dhcp-ddns\": {\n" +" \"always-include-fqdn\": false,\n" +" \"enable-updates\": false,\n" +" \"generated-prefix\": \"myhost\",\n" +" \"max-queue-size\": 1024,\n" +" \"ncr-format\": \"JSON\",\n" +" \"ncr-protocol\": \"UDP\",\n" +" \"override-client-update\": false,\n" +" \"override-no-update\": false,\n" +" \"qualifying-suffix\": \"\",\n" +" \"replace-client-name\": \"never\",\n" +" \"sender-ip\": \"0.0.0.0\",\n" +" \"sender-port\": 0,\n" +" \"server-ip\": \"127.0.0.1\",\n" +" \"server-port\": 53001\n" +" },\n" +" \"dhcp4o6-port\": 0,\n" +" \"expired-leases-processing\": {\n" +" \"flush-reclaimed-timer-wait-time\": 25,\n" +" \"hold-reclaimed-time\": 3600,\n" +" \"max-reclaim-leases\": 100,\n" +" \"max-reclaim-time\": 250,\n" +" \"reclaim-timer-wait-time\": 10,\n" +" \"unwarned-reclaim-cycles\": 5\n" +" },\n" +" \"hooks-libraries\": [ ],\n" +" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n" +" \"interfaces-config\": {\n" +" \"interfaces\": [ ],\n" +" \"re-detect\": false\n" +" },\n" +" \"lease-database\": {\n" +" \"type\": \"memfile\"\n" +" },\n" +" \"mac-sources\": [ \"any\" ],\n" +" \"option-data\": [ ],\n" +" \"option-def\": [ ],\n" +" \"relay-supplied-options\": [ \"65\" ],\n" +" \"server-id\": {\n" +" \"enterprise-id\": 0,\n" +" \"htype\": 0,\n" +" \"identifier\": \"\",\n" +" \"persist\": true,\n" +" \"time\": 0,\n" +" \"type\": \"LLT\"\n" +" },\n" +" \"shared-networks\": [\n" +" {\n" +" \"comment\": \"A shared-network\",\n" +" \"name\": \"foo\",\n" +" \"option-data\": [ ],\n" +" \"preferred-lifetime\": 0,\n" +" \"rapid-commit\": false,\n" +" \"rebind-timer\": 0,\n" +" \"relay\": {\n" +" \"ip-address\": \"::\"\n" +" },\n" +" \"renew-timer\": 0,\n" +" \"reservation-mode\": \"all\",\n" +" \"subnet6\": [\n" +" {\n" +" \"comment\": \"A subnet\",\n" +" \"id\": 1,\n" +" \"option-data\": [ ],\n" +" \"pd-pools\": [\n" +" {\n" +" \"comment\": \"A prefix pool\",\n" +" \"delegated-len\": 64,\n" +" \"option-data\": [ ],\n" +" \"prefix\": \"2001:db2::\",\n" +" \"prefix-len\": 48\n" +" }\n" +" ],\n" +" \"pools\": [\n" +" {\n" +" \"comment\": \"A pool\",\n" +" \"option-data\": [ ],\n" +" \"pool\": \"2001:db1::/64\"\n" +" }\n" +" ],\n" +" \"preferred-lifetime\": 3600,\n" +" \"rapid-commit\": false,\n" +" \"rebind-timer\": 1800,\n" +" \"relay\": {\n" +" \"ip-address\": \"::\"\n" +" },\n" +" \"renew-timer\": 900,\n" +" \"reservation-mode\": \"all\",\n" +" \"subnet\": \"2001:db1::/48\",\n" +" \"valid-lifetime\": 7200\n" +" }\n" +" ],\n" +" \"valid-lifetime\": 0\n" +" }\n" +" ],\n" +" \"subnet6\": [ ]\n" " }\n" }; @@ -6080,6 +6209,7 @@ TEST_P(Dhcp6GetConfigTest, run) { expected = UNPARSED_CONFIGS[config_counter]; ConstElementPtr json; ASSERT_NO_THROW(json = parseDHCP6(expected, true)); + ASSERT_NO_THROW(json = parseJSON(expected)); EXPECT_TRUE(isEquivalent(dhcp, json)); std::string current = prettyPrint(dhcp, 4, 4) + "\n"; EXPECT_EQ(expected, current); diff --git a/src/bin/dhcp6/tests/get_config_unittest.cc.skel b/src/bin/dhcp6/tests/get_config_unittest.cc.skel index 182b069bcd..9a5566e4d9 100644 --- a/src/bin/dhcp6/tests/get_config_unittest.cc.skel +++ b/src/bin/dhcp6/tests/get_config_unittest.cc.skel @@ -320,6 +320,7 @@ TEST_P(Dhcp6GetConfigTest, run) { expected = UNPARSED_CONFIGS[config_counter]; ConstElementPtr json; ASSERT_NO_THROW(json = parseDHCP6(expected, true)); + ASSERT_NO_THROW(json = parseJSON(expected)); EXPECT_TRUE(isEquivalent(dhcp, json)); std::string current = prettyPrint(dhcp, 4, 4) + "\n"; EXPECT_EQ(expected, current); diff --git a/src/lib/dhcpsrv/srv_config.cc b/src/lib/dhcpsrv/srv_config.cc index 1b1226c3ac..f155c9c5d4 100644 --- a/src/lib/dhcpsrv/srv_config.cc +++ b/src/lib/dhcpsrv/srv_config.cc @@ -234,21 +234,22 @@ SrvConfig::toElement() const { dhcp->set("option-data", cfg_option_->toElement()); // Set subnets and shared networks. - ConstElementPtr subnets; + std::vector sn_list; if (family == AF_INET) { - subnets = cfg_subnets4_->toElement(); - ElementPtr plain_subnets = Element::createList(); - const Subnet4Collection* subs = cfg_subnets4_->getAll(); - for (Subnet4Collection::const_iterator subnet = subs->cbegin(); - subnet != subs->cend(); ++subnet) { + const Subnet4Collection* subnets = cfg_subnets4_->getAll(); + for (Subnet4Collection::const_iterator subnet = subnets->cbegin(); + subnet != subnets->cend(); ++subnet) { + ElementPtr subnet_cfg = (*subnet)->toElement(); + sn_list.push_back(subnet_cfg); + // Skip subnets which are in a shared-network SharedNetwork4Ptr network; (*subnet)->getSharedNetwork(network); if (network) { continue; } - plain_subnets->add((*subnet)->toElement()); + plain_subnets->add(subnet_cfg); } dhcp->set("subnet4", plain_subnets); @@ -256,19 +257,20 @@ SrvConfig::toElement() const { dhcp->set("shared-networks", shared_networks); } else { - subnets = cfg_subnets6_->toElement(); - ElementPtr plain_subnets = Element::createList(); - const Subnet6Collection* subs = cfg_subnets6_->getAll(); - for (Subnet6Collection::const_iterator subnet = subs->cbegin(); - subnet != subs->cend(); ++subnet) { + const Subnet6Collection* subnets = cfg_subnets6_->getAll(); + for (Subnet6Collection::const_iterator subnet = subnets->cbegin(); + subnet != subnets->cend(); ++subnet) { + ElementPtr subnet_cfg = (*subnet)->toElement(); + sn_list.push_back(subnet_cfg); + // Skip subnets which are in a shared-network SharedNetwork6Ptr network; (*subnet)->getSharedNetwork(network); if (network) { continue; } - plain_subnets->add((*subnet)->toElement()); + plain_subnets->add(subnet_cfg); } dhcp->set("subnet6", plain_subnets); @@ -278,9 +280,8 @@ SrvConfig::toElement() const { // Insert reservations CfgHostsList resv_list; resv_list.internalize(cfg_hosts_->toElement()); - const std::vector& sn_list = subnets->listValue(); - for (std::vector::const_iterator subnet = sn_list.begin(); - subnet != sn_list.end(); ++subnet) { + for (std::vector::const_iterator subnet = sn_list.cbegin(); + subnet != sn_list.cend(); ++subnet) { ConstElementPtr id = (*subnet)->get("id"); if (isNull(id)) { isc_throw(ToElementError, "subnet has no id"); -- 2.47.3