mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-22 09:57:41 +00:00
[#3811] Return sn name in subnet lists commands
/doc/sphinx/arm/hooks-subnet-cmds.rst Updated doc to include shared-network-name in returns /src/hooks/dhcp/subnet_cmds/subnet_cmds.cc subnetToElement() - now optionally inserts the shared network name /src/hooks/dhcp/subnet_cmds/tests/subnet4_cmds_unittest.cc /src/hooks/dhcp/subnet_cmds/tests/subnet6_cmds_unittest.cc /src/hooks/dhcp/subnet_cmds/tests/subnet6_cmds_unittest.cc updated tests added change log entry
This commit is contained in:
parent
b66fe236f8
commit
11504bff67
@ -0,0 +1,6 @@
|
||||
[func] tmark
|
||||
The subnet commands hook library was modified such that
|
||||
the subnet's shared network name is now included for each
|
||||
subnet returned by the subnet4-list and subnet6-list
|
||||
commands.
|
||||
(Gitlab #3811)
|
@ -94,11 +94,13 @@ The list of subnets is returned in the following format:
|
||||
"subnets": [
|
||||
{
|
||||
"id": 10,
|
||||
"shared-network-name": "net1",
|
||||
"subnet": "10.0.0.0/8"
|
||||
},
|
||||
{
|
||||
"id": 100,
|
||||
"subnet": "192.0.2.0/24"
|
||||
"shared-network-name": null,
|
||||
"subnet": "192.0.2.0/24",
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -137,10 +139,12 @@ The list of subnets is returned in the following format:
|
||||
"subnets": [
|
||||
{
|
||||
"id": 11,
|
||||
"shared-network-name": null,
|
||||
"subnet": "2001:db8:1::/64"
|
||||
},
|
||||
{
|
||||
"id": 233,
|
||||
"shared-network-name": "some-net",
|
||||
"subnet": "3000::/16"
|
||||
}
|
||||
]
|
||||
|
@ -347,7 +347,7 @@ public:
|
||||
// Iterate over all subnets and retrieve the information we're interested in.
|
||||
for (auto const& s : *subnets) {
|
||||
// Information for the individual subnets is held in the map.
|
||||
subnet_list->add(subnetToElement(*s));
|
||||
subnet_list->add(subnetToElement(*s, true));
|
||||
}
|
||||
|
||||
// Generate the status message including the number of subnets found.
|
||||
@ -927,7 +927,7 @@ public:
|
||||
|
||||
ElementPtr details = Element::createMap();
|
||||
ElementPtr lst = Element::createList();
|
||||
lst->add(subnetToElement(*subnet));
|
||||
lst->add(subnetToElement(*subnet, false));
|
||||
details->set("subnets", lst);
|
||||
|
||||
// Create the response.
|
||||
@ -945,11 +945,22 @@ public:
|
||||
///
|
||||
/// @brief subnet details of that subnet will be returned
|
||||
/// @return id and subnet in Element format
|
||||
ElementPtr subnetToElement(const Subnet& subnet) const {
|
||||
ElementPtr subnetToElement(const Subnet& subnet, bool include_shared_network) const {
|
||||
ElementPtr subnet_element = Element::createMap();
|
||||
subnet_element->set("id",
|
||||
Element::create(static_cast<long int>(subnet.getID())));
|
||||
subnet_element->set("subnet", Element::create(subnet.toText()));
|
||||
|
||||
if (include_shared_network) {
|
||||
std::string sn_name = subnet.getSharedNetworkName();
|
||||
if (!sn_name.empty()) {
|
||||
subnet_element->set("shared-network-name", data::Element::create(sn_name));
|
||||
} else {
|
||||
// Shared network name is null.
|
||||
subnet_element->set("shared-network-name", data::Element::create());
|
||||
}
|
||||
}
|
||||
|
||||
return (subnet_element);
|
||||
}
|
||||
|
||||
|
@ -1742,9 +1742,9 @@ public:
|
||||
// of sending the 'subnet4-list' command.
|
||||
TEST_F(Subnet4CmdsTest, subnet4List) {
|
||||
// Add several IPv4 subnets to the server configuration.
|
||||
addSubnet("10.0.0.0/8", SubnetID(5));
|
||||
addSubnet("10.0.0.0/8", SubnetID(5), "net1");
|
||||
addSubnet("192.168.50.0/24", SubnetID(10));
|
||||
addSubnet("192.0.2.0/29", SubnetID(123));
|
||||
addSubnet("192.0.2.0/29", SubnetID(123), "net2");
|
||||
// Add one IPv6 subnet to the configuration. We want to make sure that
|
||||
// this subnet is not returned within the response to the command.
|
||||
addSubnet("2001:db8:1::/64", SubnetID(17));
|
||||
@ -1758,15 +1758,31 @@ TEST_F(Subnet4CmdsTest, subnet4List) {
|
||||
CONTROL_RESULT_SUCCESS,
|
||||
"3 IPv4 subnets found");
|
||||
|
||||
// Verify that the response has appropriate structure.
|
||||
ASSERT_NO_FATAL_FAILURE(checkSubnetListStructure(response, 3));
|
||||
// Verify that the response has appropriate structure and returned
|
||||
// the expected arguments.
|
||||
std::string exp_args=R"(
|
||||
{
|
||||
"subnets": [
|
||||
{
|
||||
"id": 5,
|
||||
"shared-network-name": "net1",
|
||||
"subnet": "10.0.0.0/8"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"shared-network-name": null,
|
||||
"subnet": "192.168.50.0/24"
|
||||
},
|
||||
{
|
||||
"id": 123,
|
||||
"shared-network-name": "net2",
|
||||
"subnet": "192.0.2.0/29"
|
||||
}
|
||||
]
|
||||
}
|
||||
)";
|
||||
|
||||
// Our 3 IPv4 subnets should be returned in the response.
|
||||
ASSERT_TRUE(hasSubnet(response, "10.0.0.0/8", SubnetID(5)));
|
||||
ASSERT_TRUE(hasSubnet(response, "192.168.50.0/24", SubnetID(10)));
|
||||
ASSERT_TRUE(hasSubnet(response, "192.0.2.0/29", SubnetID(123)));
|
||||
// The IPv6 subnet should not be included.
|
||||
ASSERT_FALSE(hasSubnet(response, "2001:db8:1::/64", SubnetID(17)));
|
||||
ASSERT_NO_FATAL_FAILURE(checkResponseArgs(response, exp_args));
|
||||
}
|
||||
|
||||
// This test verifies that 'subnet4-list' returns empty list of subnets when
|
||||
@ -1780,7 +1796,13 @@ TEST_F(Subnet4CmdsTest, noSubnet4List) {
|
||||
|
||||
// Verify that the response has appropriate structure and no subnets
|
||||
// are included.
|
||||
ASSERT_NO_FATAL_FAILURE(checkSubnetListStructure(response, 0));
|
||||
std::string exp_args=R"(
|
||||
{
|
||||
"subnets": [ ]
|
||||
}
|
||||
)";
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(checkResponseArgs(response, exp_args));
|
||||
}
|
||||
|
||||
// This test verifies that IPv4 subnet can be retrieved by subnet id
|
||||
|
@ -2433,9 +2433,9 @@ public:
|
||||
// of sending the 'subnet6-list' command.
|
||||
TEST_F(Subnet6CmdsTest, subnet6List) {
|
||||
// Add several IPv6 subnets to the server configuration.
|
||||
addSubnet("3000::/16", SubnetID(9));
|
||||
addSubnet("3000::/16", SubnetID(9), "net1");
|
||||
addSubnet("3001:23::/92", SubnetID(11));
|
||||
addSubnet("2001:db8:1::/64", SubnetID(1023));
|
||||
addSubnet("2001:db8:1::/64", SubnetID(1023), "net2");
|
||||
// Add one IPv4 subnet to the configuration. We want to make sure that
|
||||
// this subnet is not returned within the response to the command.
|
||||
addSubnet("10.2.30.0/24", SubnetID(33));
|
||||
@ -2449,15 +2449,30 @@ TEST_F(Subnet6CmdsTest, subnet6List) {
|
||||
CONTROL_RESULT_SUCCESS,
|
||||
"3 IPv6 subnets found");
|
||||
|
||||
// Verify that the response has appropriate structure.
|
||||
ASSERT_NO_FATAL_FAILURE(checkSubnetListStructure(response, 3));
|
||||
// Verify that the response has appropriate structure and returned
|
||||
// the expected arguments.
|
||||
std::string exp_args=R"(
|
||||
{
|
||||
"subnets": [
|
||||
{
|
||||
"id": 9,
|
||||
"shared-network-name": "net1",
|
||||
"subnet": "3000::/16"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"shared-network-name": null,
|
||||
"subnet": "3001:23::/92"
|
||||
},
|
||||
{
|
||||
"id": 1023,
|
||||
"shared-network-name": "net2",
|
||||
"subnet": "2001:db8:1::/64"
|
||||
}]
|
||||
}
|
||||
)";
|
||||
|
||||
// Our 3 IPv6 subnets should be returned in the response.
|
||||
ASSERT_TRUE(hasSubnet(response, "3000::/16", SubnetID(9)));
|
||||
ASSERT_TRUE(hasSubnet(response, "3001:23::/92", SubnetID(11)));
|
||||
ASSERT_TRUE(hasSubnet(response, "2001:db8:1::/64", SubnetID(1023)));
|
||||
// The IPv4 subnet should not be included.
|
||||
ASSERT_FALSE(hasSubnet(response, "10.2.30.0/24", SubnetID(33)));
|
||||
ASSERT_NO_FATAL_FAILURE(checkResponseArgs(response, exp_args));
|
||||
}
|
||||
|
||||
// This test verifies that 'subnet6-list' returns empty list of subnets when
|
||||
@ -2468,10 +2483,15 @@ TEST_F(Subnet6CmdsTest, noSubnet6List) {
|
||||
ConstElementPtr response = testCommand("{ \"command\": \"subnet6-list\" }",
|
||||
CONTROL_RESULT_EMPTY,
|
||||
"0 IPv6 subnets found");
|
||||
|
||||
// Verify that the response has appropriate structure and no subnets
|
||||
// are included.
|
||||
ASSERT_NO_FATAL_FAILURE(checkSubnetListStructure(response, 0));
|
||||
std::string exp_args=R"(
|
||||
{
|
||||
"subnets": [ ]
|
||||
}
|
||||
)";
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(checkResponseArgs(response, exp_args));
|
||||
}
|
||||
|
||||
// This test verifies that IPv6 subnet can be retrieved by subnet id
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <dhcpsrv/subnet_id.h>
|
||||
#include <process/daemon.h>
|
||||
#include <stats/stats_mgr.h>
|
||||
#include <testutils/gtest_utils.h>
|
||||
#include <testutils/test_to_element.h>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <sstream>
|
||||
@ -172,7 +174,9 @@ public:
|
||||
/// @param subnet_str Subnet in a textual form, e.g. 10.0.0.0/8 or
|
||||
/// 2001:db8::/64.
|
||||
/// @param subnet_id Subnet id.
|
||||
void addSubnet(const std::string& subnet_str, const isc::dhcp::SubnetID& subnet_id) {
|
||||
/// @param shared_network_name name of shared-network, defaults to empty string.
|
||||
void addSubnet(const std::string& subnet_str, const isc::dhcp::SubnetID& subnet_id,
|
||||
const std::string& shared_network_name = "") {
|
||||
try {
|
||||
// Split prefix and prefix length.
|
||||
auto split_pos = subnet_str.find('/');
|
||||
@ -193,12 +197,20 @@ public:
|
||||
if (prefix.isV4()) {
|
||||
isc::dhcp::CfgSubnets4Ptr cfg = isc::dhcp::CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
|
||||
isc::dhcp::Subnet4Ptr subnet(new isc::dhcp::Subnet4(prefix, prefix_length, 30, 40, 60, subnet_id));
|
||||
if (!shared_network_name.empty()) {
|
||||
subnet->setSharedNetworkName(shared_network_name);
|
||||
}
|
||||
|
||||
cfg->add(subnet);
|
||||
addReservations(subnet, isc::dhcp::CfgMgr::instance().getStagingCfg()->getCfgHosts());
|
||||
|
||||
} else {
|
||||
isc::dhcp::CfgSubnets6Ptr cfg = isc::dhcp::CfgMgr::instance().getStagingCfg()->getCfgSubnets6();
|
||||
isc::dhcp::Subnet6Ptr subnet(new isc::dhcp::Subnet6(prefix, prefix_length, 30, 40, 50, 60, subnet_id));
|
||||
if (!shared_network_name.empty()) {
|
||||
subnet->setSharedNetworkName(shared_network_name);
|
||||
}
|
||||
|
||||
cfg->add(subnet);
|
||||
addReservations(subnet, isc::dhcp::CfgMgr::instance().getStagingCfg()->getCfgHosts());
|
||||
}
|
||||
@ -479,49 +491,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Verifies that the structure of the list of subnets returned
|
||||
/// contains allowed values.
|
||||
/// @brief Verifies that the content of the "args" element in the response.
|
||||
///
|
||||
/// @param answer Server's response to a command.
|
||||
/// @param exp_list_size Expected number of subnets returned.
|
||||
void checkSubnetListStructure(const isc::data::ConstElementPtr& answer,
|
||||
const size_t exp_list_size) {
|
||||
/// @param exp_args JSON map of the expected arguments contents.
|
||||
void checkResponseArgs(const isc::data::ConstElementPtr& answer,
|
||||
const std::string exp_args) {
|
||||
// Retrieve "arguments" and make sure it is a map.
|
||||
int rcode = 0;
|
||||
isc::data::ConstElementPtr args = isc::config::parseAnswer(rcode, answer);
|
||||
ASSERT_TRUE(args);
|
||||
ASSERT_EQ(isc::data::Element::map, args->getType());
|
||||
|
||||
// Retrieve "subnets" list from "arguments".
|
||||
isc::data::ConstElementPtr subnet_ids = args->get("subnets");
|
||||
ASSERT_TRUE(subnet_ids);
|
||||
EXPECT_EQ(isc::data::Element::list, subnet_ids->getType());
|
||||
isc::data::ConstElementPtr exp_args_map;
|
||||
ASSERT_NO_THROW_LOG(exp_args_map = isc::data::Element::fromJSON(exp_args));
|
||||
|
||||
// Make sure that the list contains expected number of subnets.
|
||||
EXPECT_EQ(exp_list_size, subnet_ids->size());
|
||||
|
||||
// Iterate over the list of subnets in the list and make sure that
|
||||
// it contains expected parameters. It does not verify the values though.
|
||||
for (unsigned index = 0; index != subnet_ids->size(); ++index) {
|
||||
// Get the element in the list.
|
||||
isc::data::ConstElementPtr subnet_element = subnet_ids->get(index);
|
||||
ASSERT_TRUE(subnet_element);
|
||||
|
||||
// There should be exactly two parameters: "id" and "subnet".
|
||||
ASSERT_EQ(2, subnet_element->size());
|
||||
ASSERT_TRUE(subnet_element->contains("id"));
|
||||
ASSERT_TRUE(subnet_element->contains("subnet"));
|
||||
|
||||
// Subnet identifier is a number.
|
||||
isc::data::ConstElementPtr subnet_id = subnet_element->get("id");
|
||||
ASSERT_TRUE(subnet_id);
|
||||
EXPECT_EQ(isc::data::Element::integer, subnet_id->getType());
|
||||
|
||||
// Subnet prefix is a string.
|
||||
isc::data::ConstElementPtr subnet_value = subnet_element->get("subnet");
|
||||
ASSERT_TRUE(subnet_value);
|
||||
EXPECT_EQ(isc::data::Element::string, subnet_value->getType());
|
||||
}
|
||||
isc::test::expectEqWithDiff(args, exp_args_map);
|
||||
}
|
||||
|
||||
/// @brief Checks that the response includes a given subnet.
|
||||
|
Loading…
x
Reference in New Issue
Block a user