From: Francis Dupont Date: Fri, 8 Mar 2019 22:21:39 +0000 (+0100) Subject: [465-add-subnet4-update-and-subnet6-update-commands-to-subnet-cmds-hook] Added missin... X-Git-Tag: Kea-1.6.0-beta~203 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b878f24a705e87fd2da2f7eed516da755e7efae;p=thirdparty%2Fkea.git [465-add-subnet4-update-and-subnet6-update-commands-to-subnet-cmds-hook] Added missing tests and updated doc --- diff --git a/doc/Makefile.am b/doc/Makefile.am index c884546ea5..4a10675091 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -116,8 +116,10 @@ EXTRA_DIST += api/statistic-reset-all.json api/statistic-reset.json EXTRA_DIST += api/stat-lease4-get.json api/stat-lease6-get.json EXTRA_DIST += api/subnet4-add.json api/subnet4-del.json EXTRA_DIST += api/subnet4-get.json api/subnet4-list.json +EXTRA_DIST += api/subnet4-update.json EXTRA_DIST += api/subnet6-add.json api/subnet6-del.json EXTRA_DIST += api/subnet6-get.json api/subnet6-list.json +EXTRA_DIST += api/subnet6-update.json EXTRA_DIST += api/_template.json api/version-get.json devel: diff --git a/doc/api/subnet4-update.json b/doc/api/subnet4-update.json new file mode 100644 index 0000000000..5926b47dc5 --- /dev/null +++ b/doc/api/subnet4-update.json @@ -0,0 +1,30 @@ +{ + "name": "subnet4-update", + "brief": "This command is used to update a subnet in the existing server configuration.", + "description": "See ", + "support": [ "kea-dhcp4"], + "avail": "1.6.0", + "hook": "subnet_cmds", + "cmd-syntax": "{ + \"command\": \"subnet4-update\", + \"arguments\": { + \"subnets\": [ { + \"id\": 123, + \"subnet\": \"10.20.30.0/24\", + ... + } ] + } +}", + "resp-syntax": "{ + \"result\": 0, + \"text\": \"IPv4 subnet updated\", + \"arguments\": { + \"subnets\": [ + { + \"id\": 123, + \"subnet\": \"10.20.30.0/24\" + } + ] + } +}" +} diff --git a/doc/api/subnet6-update.json b/doc/api/subnet6-update.json new file mode 100644 index 0000000000..9360a37799 --- /dev/null +++ b/doc/api/subnet6-update.json @@ -0,0 +1,30 @@ +{ + "name": "subnet6-update", + "brief": "This command is used to update a subnet in the existing server configuration. This operation has no impact on other subnets.", + "description": "See ", + "support": [ "kea-dhcp6" ], + "avail": "1.6.0", + "hook": "subnet_cmds", + "cmd-syntax": "{ + \"command\": \"subnet6-update\", + \"arguments\": { + \"subnet6\": [ { + \"id\": 234, + \"subnet\": \"2001:db8:1::/64\", + ... + } ] + } +}", + "resp-syntax": "{ + \"result\": 0, + \"text\": \"IPv6 subnet updated\", + \"arguments\": { + \"subnet6\": [ + { + \"id\": 234, + \"subnet\": \"2001:db8:1::/64\" + } + ] + } +}" +} diff --git a/doc/guide/api.xml b/doc/guide/api.xml index 660b3d0468..489250204d 100644 --- a/doc/guide/api.xml +++ b/doc/guide/api.xml @@ -78,10 +78,12 @@ , subnet4-del , subnet4-get , subnet4-list +, subnet4-update , subnet6-add , subnet6-del , subnet6-get , subnet6-list +, subnet6-update , version-get . Commands supported by kea-ctrl-agent daemon: build-report @@ -159,6 +161,7 @@ , subnet4-del , subnet4-get , subnet4-list +, subnet4-update , version-get . Commands supported by kea-dhcp6 daemon: build-report @@ -216,6 +219,7 @@ , subnet6-del , subnet6-get , subnet6-list +, subnet6-update , version-get . Commands supported by class_cmds hook library: class-add @@ -274,10 +278,12 @@ , subnet4-del , subnet4-get , subnet4-list +, subnet4-update , subnet6-add , subnet6-del , subnet6-get , subnet6-list +, subnet6-update .
@@ -3175,6 +3181,54 @@ If no IPv4 subnets are found, an error code is returned along with the error des
+ +
+subnet4-update reference +subnet4-update - This command is used to update a subnet in the existing server configuration. + +Supported by: kea-dhcp4 + +Availability: 1.6.0 (subnet_cmds hook) + +Description and examples: See + +Command syntax: + { + "command": "subnet4-update", + "arguments": { + "subnet4": [ { + "id": 123, + "subnet": "10.20.30.0/24", + ... + } ] + } +} + + +Response syntax: + { + "result": 0, + "text": "IPv4 subnet updated", + "arguments": { + "subnets": [ + { + "id": 123, + "subnet": "10.20.30.0/24" + } + ] + } +} +Result is an integer representation of the status. Currently supported statuses are: + + 0 - success + 1 - error + 2 - unsupported + + + +
+ +
subnet6-add reference @@ -3354,6 +3408,54 @@ If no IPv6 subnets are found, an error code is returned along with the error des
+ +
+subnet6-update reference +subnet6-update - This command is used to update a subnet in the existing server configuration. This operation has no impact on other subnets. + +Supported by: kea-dhcp6 + +Availability: 1.6.0 (subnet_cmds hook) + +Description and examples: See + +Command syntax: + { + "command": "subnet6-update", + "arguments": { + "subnet6": [ { + "id": 234, + "subnet": "2001:db8:1::/64", + ... + } ] + } +} + + +Response syntax: + { + "result": 0, + "text": "IPv6 subnet updated", + "arguments": { + "subnet6": [ + { + "id": 234, + "subnet": "2001:db8:1::/64" + } + ] + } +} +Result is an integer representation of the status. Currently supported statuses are: + + 0 - success + 1 - error + 2 - unsupported + + + +
+ +
version-get reference diff --git a/doc/guide/hooks.xml b/doc/guide/hooks.xml index c8946447e4..a1823ee0e2 100644 --- a/doc/guide/hooks.xml +++ b/doc/guide/hooks.xml @@ -1714,7 +1714,7 @@ An example result returned when the query was malformed: reservation-get-page instead (see ). - + For a reference, see . @@ -1973,6 +1973,10 @@ An example deletion by (subnet-id, identifier-type, identifier) looks as follows + subnet4-update/subnet6-update: updates subnet in server's configuration + + + subnet4-del/subnet6-del: removes a subnet from the server's configuration @@ -2336,6 +2340,105 @@ If the subnet exists the response will be similar to this:
+
+ subnet4-update + + This command is used to update a subnet in the existing + server configuration. This operation has no impact on other + subnets. The subnet identifier is used to identify the + subnet to replace, it must be specified and must be unique + among all subnets. The subnet prefix should not be updated. + + + The subnet information within this command has the same structure + as the subnet information in the server configuration file with the + exception that static host reservations must not be specified + within subnet4-update. The commands described in + should be used to update, remove and + modify static reservations. + +{ + "command": "subnet4-update", + "arguments": { + "subnet4": [ { + "id": 123, + "subnet": "10.20.30.0/24", + ... + } ] + } +} + + + + + The response to this command has the following structure: + +{ + "result": 0, + "text": "IPv4 subnet updated", + "arguments": { + "subnet4": [ + { + "id": 123, + "subnet": "10.20.30.0/24" + } + ] + } +} + + +
+ +
+ subnet6-update + + This command is used to update a subnet in the existing + server configuration. This operation has no impact on other + subnets. The subnet identifier is used to identify the + subnet to replace, it must be specified and must be unique + among all subnets. The subnet prefix should not be updated. + + + The subnet information within this command has the same structure + as the subnet information in the server configuration file with the + exception that static host reservations must not be specified + within subnet6-update. The commands described in + should be used to update, remove and + modify static reservations. + +{ + "command": "subnet6-update", + "arguments": { + "subnet6": [ { + "id": 234, + "subnet": "2001:db8:1::/64", + ... + } ] + } +} + + + + + The response to this command has the following structure: + +{ + "result": 0, + "text": "IPv6 subnet updated", + "arguments": { + "subnet6": [ + { + "id": 234, + "subnet": "2001:db8:1::/64" + } + ] + } +} + + + +
+
subnet4-del command @@ -2354,7 +2457,7 @@ If the subnet exists the response will be similar to this: loose track of leases assigned to the clients from this subnet. However, removal of the subnet may still cause configuration errors and conflicts. For example: after removal of the subnet, - the server administrator may add a new subnet with the ID used + the server administrator may update a new subnet with the ID used previously for the removed subnet. This means that the existing leases and static reservations will be in conflict with this new subnet. Thus, we recommend that this command is used with extreme diff --git a/src/lib/dhcpsrv/cfg_subnets4.cc b/src/lib/dhcpsrv/cfg_subnets4.cc index 244b39f290..ffb323502f 100644 --- a/src/lib/dhcpsrv/cfg_subnets4.cc +++ b/src/lib/dhcpsrv/cfg_subnets4.cc @@ -51,12 +51,13 @@ CfgSubnets4::replace(const Subnet4Ptr& subnet) { isc_throw(BadValue, "ID of the IPv4 subnet '" << subnet_id << "' is not in use"); } + Subnet4Ptr old = *subnet_it; bool ret = index.replace(subnet_it, subnet); LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_UPDATE_SUBNET4) .arg(subnet_id).arg(ret); if (ret) { - return (*subnet_it); + return (old); } else { return (Subnet4Ptr()); } diff --git a/src/lib/dhcpsrv/cfg_subnets6.cc b/src/lib/dhcpsrv/cfg_subnets6.cc index 210ad8a9b6..2405594736 100644 --- a/src/lib/dhcpsrv/cfg_subnets6.cc +++ b/src/lib/dhcpsrv/cfg_subnets6.cc @@ -51,12 +51,13 @@ CfgSubnets6::replace(const Subnet6Ptr& subnet) { isc_throw(BadValue, "ID of the IPv6 subnet '" << subnet_id << "' is not in use"); } + Subnet6Ptr old = *subnet_it; bool ret = index.replace(subnet_it, subnet); LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_UPDATE_SUBNET6) .arg(subnet_id).arg(ret); if (ret) { - return (*subnet_it); + return (old); } else { return (Subnet6Ptr()); } diff --git a/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc b/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc index 600adce08b..64f436ec53 100644 --- a/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc @@ -150,6 +150,68 @@ TEST(CfgSubnets4Test, deleteSubnet) { EXPECT_FALSE(cfg.getByPrefix("192.0.2.0/26")); } +// This test verifies that replace a subnet works as expected. +TEST(CfgSubnets4Test, replaceSubnet) { + CfgSubnets4 cfg; + + // Create 3 subnets. + Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.1.0"), + 26, 1, 2, 100, SubnetID(10))); + Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.0"), + 26, 1, 2, 100, SubnetID(2))); + Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.3.0"), + 26, 1, 2, 100, SubnetID(13))); + + ASSERT_NO_THROW(cfg.add(subnet1)); + ASSERT_NO_THROW(cfg.add(subnet2)); + ASSERT_NO_THROW(cfg.add(subnet3)); + + // There should be three subnets. + ASSERT_EQ(3, cfg.getAll()->size()); + // We're going to replace the subnet #2. Let's make sure it exists before + // we replace it. + ASSERT_TRUE(cfg.getByPrefix("192.0.3.0/26")); + + // Replace the subnet and make sure it was updated. + Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), + 26, 10, 20, 1000, SubnetID(2))); + Subnet4Ptr replaced = cfg.replace(subnet); + ASSERT_TRUE(replaced); + EXPECT_TRUE(replaced == subnet2); + ASSERT_EQ(3, cfg.getAll()->size()); + Subnet4Ptr returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet); + + // Rollback. + replaced = cfg.replace(replaced); + ASSERT_TRUE(replaced); + EXPECT_TRUE(replaced == subnet); + ASSERT_EQ(3, cfg.getAll()->size()); + returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet2); + + // Prefix conflict returns null. + subnet.reset(new Subnet4(IOAddress("192.0.3.0"), + 26, 10, 20, 1000, SubnetID(2))); + replaced = cfg.replace(subnet); + EXPECT_FALSE(replaced); + returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet2); + + // Changing prefix works even it is highly not recommended. + subnet.reset(new Subnet4(IOAddress("192.0.10.0"), + 26, 10, 20, 1000, SubnetID(2))); + replaced = cfg.replace(subnet); + ASSERT_TRUE(replaced); + EXPECT_TRUE(replaced == subnet2); + returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet); +} + // This test verifies that subnets configuration is properly merged. TEST(CfgSubnets4Test, mergeSubnets) { // Create custom options dictionary for testing merge. We're keeping it diff --git a/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc b/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc index 9d631039da..53124bf5ba 100644 --- a/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -148,6 +148,68 @@ TEST(CfgSubnets6Test, deleteSubnet) { EXPECT_FALSE(cfg.getByPrefix("2001:db8:1::/48")); } +// This test verifies that replace a subnet works as expected. +TEST(CfgSubnets6Test, replaceSubnet) { + CfgSubnets6 cfg; + + // Create 3 subnets. + Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), + 48, 1, 2, 3, 100, SubnetID(10))); + Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), + 48, 1, 2, 3, 100, SubnetID(2))); + Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), + 48, 1, 2, 3, 100, SubnetID(13))); + + ASSERT_NO_THROW(cfg.add(subnet1)); + ASSERT_NO_THROW(cfg.add(subnet2)); + ASSERT_NO_THROW(cfg.add(subnet3)); + + // There should be three subnets. + ASSERT_EQ(3, cfg.getAll()->size()); + // We're going to replace the subnet #2. Let's make sure it exists before + // we replace it. + ASSERT_TRUE(cfg.getByPrefix("2001:db8:2::/48")); + + // Replace the subnet and make sure it was updated. + Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:2::"), + 48, 10, 20, 30, 1000, SubnetID(2))); + Subnet6Ptr replaced = cfg.replace(subnet); + ASSERT_TRUE(replaced); + EXPECT_TRUE(replaced == subnet2); + ASSERT_EQ(3, cfg.getAll()->size()); + Subnet6Ptr returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet); + + // Rollback. + replaced = cfg.replace(replaced); + ASSERT_TRUE(replaced); + EXPECT_TRUE(replaced == subnet); + ASSERT_EQ(3, cfg.getAll()->size()); + returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet2); + + // Prefix conflict returns null. + subnet.reset(new Subnet6(IOAddress("2001:db8:3::"), + 48, 10, 20, 30, 1000, SubnetID(2))); + replaced = cfg.replace(subnet); + EXPECT_FALSE(replaced); + returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet2); + + // Changing prefix works even it is highly not recommended. + subnet.reset(new Subnet6(IOAddress("2001:db8:10::"), + 48, 10, 20, 30, 1000, SubnetID(2))); + replaced = cfg.replace(subnet); + ASSERT_TRUE(replaced); + EXPECT_TRUE(replaced == subnet2); + returned = cfg.getAll()->at(1); + ASSERT_TRUE(returned); + EXPECT_TRUE(returned == subnet); +} + // This test checks that the subnet can be selected using a relay agent's // link address. TEST(CfgSubnets6Test, selectSubnetByRelayAddress) {