Commit ca6f2698 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[5468] Implemented lease4-get-all command.

parent a1697ce6
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2017-2018 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
......@@ -25,6 +25,7 @@
#include <boost/bind.hpp>
#include <string>
#include <sstream>
using namespace isc::dhcp;
using namespace isc::data;
......@@ -129,6 +130,18 @@ public:
int
leaseGetHandler(CalloutHandle& handle);
/// @brief lease4-get-all command handler
///
/// This command attempts to retrieve all IPv4 leases or all IPv4 leases
/// belonging to the particular subnets. If no subnet identifiers are
/// provided, it returns all IPv4 leases from the database.
///
/// @param handle Callout context - which is expected to contain the
/// get command JSON text in the "command" argument
/// return 0 upon success, non-zero otherwise.
int
lease4GetAllHandler(CalloutHandle& handle);
/// @brief lease4-del command handler
///
/// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::lease4DelHandler
......@@ -455,6 +468,65 @@ LeaseCmdsImpl::leaseGetHandler(CalloutHandle& handle) {
return (0);
}
int
LeaseCmdsImpl::lease4GetAllHandler(CalloutHandle& handle) {
try {
extractCommand(handle);
ElementPtr leases_json = Element::createList();
// The argument may contain a list of subnets for which leases should
// be returned.
if (cmd_args_) {
ConstElementPtr subnets = cmd_args_->get("subnets");
if (subnets) {
if (subnets->getType() != Element::list) {
isc_throw(BadValue, "'subnets' parameter must be a list");
}
const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
for (auto subnet_id = subnet_ids.begin(); subnet_id != subnet_ids.end();
++subnet_id) {
if ((*subnet_id)->getType() != Element::integer) {
isc_throw(BadValue, "listed subnet identifiers must be numbers");
}
Lease4Collection leases =
LeaseMgrFactory::instance().getLeases4((*subnet_id)->intValue());
for (auto lease = leases.begin(); lease != leases.end(); ++lease) {
ElementPtr lease_json = (*lease)->toElement();
leases_json->add(lease_json);
}
}
} else {
isc_throw(BadValue, "'subnets' parameter not specified");
}
} else {
// There is no 'subnets' argument so let's return all leases.
Lease4Collection leases = LeaseMgrFactory::instance().getLeases4();
for (auto lease = leases.begin(); lease != leases.end(); ++lease) {
ElementPtr lease_json = (*lease)->toElement();
leases_json->add(lease_json);
}
}
std::ostringstream s;
s << leases_json->size() << " IPv4 lease(s) found.";
ConstElementPtr response = createAnswer(CONTROL_RESULT_SUCCESS,
s.str(), leases_json);
setResponse(handle, response);
} catch (const std::exception& ex) {
setErrorResponse(handle, ex.what());
return (CONTROL_RESULT_ERROR);
}
return (0);
}
int
LeaseCmdsImpl::lease4DelHandler(CalloutHandle& handle) {
Parameters p;
......@@ -707,6 +779,11 @@ LeaseCmds::leaseGetHandler(CalloutHandle& handle) {
return(impl_->leaseGetHandler(handle));
}
int
LeaseCmds::lease4GetAllHandler(hooks::CalloutHandle& handle) {
return (impl_->lease4GetAllHandler(handle));
}
int
LeaseCmds::lease4DelHandler(CalloutHandle& handle) {
return(impl_->lease4DelHandler(handle));
......
......@@ -131,6 +131,31 @@ public:
int
leaseGetHandler(hooks::CalloutHandle& handle);
/// @brief lease4-get-all command handler
///
/// This command attempts to retrieve all IPv4 leases or all IPv4 leases
/// belonging to the particular subnets. If no subnet identifiers are
/// provided, it returns all IPv4 leases from the database.
///
/// Example command for query by (subnet-ids):
/// {
/// "command": "lease4-get-all",
/// "arguments": {
/// "subnets": [ 1, 2, 3, 4 ]
/// }
/// }
///
/// Example command for retrieving all leases:
/// {
/// "command": "lease4-get-all",
/// }
///
/// @param handle Callout context - which is expected to contain the
/// get command JSON text in the "command" argument
/// @return result of the operation.
int
lease4GetAllHandler(hooks::CalloutHandle& handle);
/// @brief lease4-del command handler
///
/// This command attempts to delete an IPv4 lease that match selected
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the End User License
// Agreement. See COPYING file in the premium/ directory.
......@@ -53,6 +53,17 @@ int lease4_get(CalloutHandle& handle) {
return(lease_cmds.leaseGetHandler(handle));
}
/// @brief This is a command callout for 'lease4-get-all' command.
///
/// @param handle Callout handle used to retrieve a command and
/// provide a response.
/// @return 0 if this callout has been invoked successfully,
/// 1 otherwise.
int lease4_get_all(CalloutHandle& handle) {
LeaseCmds lease_cmds;
return (lease_cmds.lease4GetAllHandler(handle));
}
/// @brief This is a command callout for 'lease6-get' command.
///
/// @param handle Callout handle used to retrieve a command and
......@@ -138,6 +149,7 @@ int load(LibraryHandle& handle) {
handle.registerCommandCallout("lease4-add", lease4_add);
handle.registerCommandCallout("lease6-add", lease6_add);
handle.registerCommandCallout("lease4-get", lease4_get);
handle.registerCommandCallout("lease4-get-all", lease4_get_all);
handle.registerCommandCallout("lease6-get", lease6_get);
handle.registerCommandCallout("lease4-del", lease4_del);
handle.registerCommandCallout("lease6-del", lease6_del);
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2017-2018 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
......@@ -260,9 +260,11 @@ public:
subnets->add(subnet6);
cfg_mgr.commit();
} else {
Subnet4Ptr subnet4(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3, 44));
Subnet4Ptr subnet44(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3, 44));
Subnet4Ptr subnet88(new Subnet4(IOAddress("192.0.3.0"), 24, 1, 2, 3, 88));
CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
subnets->add(subnet4);
subnets->add(subnet44);
subnets->add(subnet88);
cfg_mgr.commit();
}
......@@ -270,34 +272,43 @@ public:
if (v6) {
lmptr_->addLease(createLease6());
} else {
lmptr_->addLease(createLease4());
lmptr_->addLease(createLease4("192.0.2.1", 44, 0x08, 0x42));
lmptr_->addLease(createLease4("192.0.2.2", 44, 0x09, 0x56));
lmptr_->addLease(createLease4("192.0.3.1", 88, 0x08, 0x42));
lmptr_->addLease(createLease4("192.0.3.2", 88, 0x09, 0x56));
}
}
}
/// @brief Creates an IPv4 lease
///
/// Lease parameters: ip-address = 192.0.2.1, hwaddr = 08:08:08:08:08:08,
/// client-id = 42:42:42:42:42:42:42:42, valid lifetime = 3600,
/// cltt = 12345678, subnet-id = 44, fqdn-fwd = false, fqdn-rev = true
/// hostname = myhost.example.com
/// Lease parameters: valid lifetime = 3600, cltt = 12345678, fqdn-fwd = false,
/// fqdn-rev = true, hostname = myhost.example.com
///
/// @param ip_address IP address for the lease.
/// @param subnet_id subnet identifier
/// @param hw_address_pattern value to be used for generating HW address by repating
/// it 6 times.
/// @param client_id_pattern value to be used for generating client identifier by
/// repeating it 8 times.
/// @return Returns the lease created
Lease4Ptr createLease4() {
Lease4Ptr createLease4(const std::string& ip_address, const SubnetID& subnet_id,
const uint8_t hw_address_pattern,
const uint8_t client_id_pattern) {
Lease4Ptr lease(new Lease4());
lease->addr_ = IOAddress("192.0.2.1");
lease->addr_ = IOAddress(ip_address);
// Initialize unused fields.
lease->t1_ = 0; // Not saved
lease->t2_ = 0; // Not saved
// Set other parameters. For historical reasons, address 0 is not used.
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x08), HTYPE_ETHER));
lease->client_id_ = ClientIdPtr(new ClientId(vector<uint8_t>(8, 0x42)));
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, hw_address_pattern), HTYPE_ETHER));
lease->client_id_ = ClientIdPtr(new ClientId(vector<uint8_t>(8, client_id_pattern)));
lease->valid_lft_ = 3600;
lease->cltt_ = 12345678;
lease->subnet_id_ = 44;
lease->subnet_id_ = subnet_id;
lease->fqdn_fwd_ = false;
lease->fqdn_rev_ = true;
lease->hostname_ = "myhost.example.com.";
......@@ -343,6 +354,20 @@ public:
uint32_t subnet_id, std::string hwaddr,
bool client_id_required) {
ASSERT_TRUE(l);
// If the element is a list we need to retrieve the lease that
// we're interested in.
if (l->getType() == Element::list) {
std::vector<ElementPtr> e = l->listValue();
for (auto it = e.begin(); it != e.end(); ++it) {
ConstElementPtr ip_address = (*it)->get("ip-address");
if (ip_address && ip_address->stringValue() == ip) {
l = (*it);
break;
}
}
}
ASSERT_TRUE(l->get("ip-address"));
EXPECT_EQ(ip, l->get("ip-address")->stringValue());
......@@ -1099,6 +1124,132 @@ TEST_F(LeaseCmdsTest, Lease4GetByHWAddr) {
checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
}
// Checks that lease4-get-all returns all leases.
TEST_F(LeaseCmdsTest, Lease4GetAll) {
// Initialize lease manager (false = v4, true = add a lease)
initLeaseMgr(false, true);
// Query for all leases.
string cmd =
"{\n"
" \"command\": \"lease4-get-all\"\n"
"}";
string exp_rsp = "4 IPv4 lease(s) found.";
ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease parameters were indeed returned.
ASSERT_TRUE(rsp);
ConstElementPtr leases = rsp->get("arguments");
ASSERT_TRUE(leases);
ASSERT_EQ(Element::list, leases->getType());
// Let's check if the response contains desired leases.
checkLease4(leases, "192.0.2.1", 44, "08:08:08:08:08:08", true);
checkLease4(leases, "192.0.2.2", 44, "09:09:09:09:09:09", true);
checkLease4(leases, "192.0.3.1", 88, "08:08:08:08:08:08", true);
checkLease4(leases, "192.0.3.2", 88, "09:09:09:09:09:09", true);
}
// Checks that lease4-get-all returns all leases for a subnet.
TEST_F(LeaseCmdsTest, Lease4GetAllBySubnetId) {
// Initialize lease manager (false = v4, true = add a lease)
initLeaseMgr(false, true);
// Query for leases from subnet 44. Subnet 127 will be ignored because
// it doesn't contain any leases.
string cmd =
"{\n"
" \"command\": \"lease4-get-all\",\n"
" \"arguments\": {\n"
" \"subnets\": [ 44, 127 ]"
" }\n"
"}";
string exp_rsp = "2 IPv4 lease(s) found.";
ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease parameters were indeed returned.
ASSERT_TRUE(rsp);
ConstElementPtr leases = rsp->get("arguments");
ASSERT_TRUE(leases);
ASSERT_EQ(Element::list, leases->getType());
// Let's check if the response contains desired leases.
checkLease4(leases, "192.0.2.1", 44, "08:08:08:08:08:08", true);
checkLease4(leases, "192.0.2.2", 44, "09:09:09:09:09:09", true);
}
// Checks that lease4-get-all returns leases from multiple subnets.
TEST_F(LeaseCmdsTest, Lease4GetAllByMultipleSubnetIds) {
// Initialize lease manager (false = v4, true = add a lease)
initLeaseMgr(false, true);
// Query for leases from subnet 44 and 88.
string cmd =
"{\n"
" \"command\": \"lease4-get-all\",\n"
" \"arguments\": {\n"
" \"subnets\": [ 44, 88 ]"
" }\n"
"}";
string exp_rsp = "4 IPv4 lease(s) found.";
ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease parameters were indeed returned.
ASSERT_TRUE(rsp);
ConstElementPtr leases = rsp->get("arguments");
ASSERT_TRUE(leases);
ASSERT_EQ(Element::list, leases->getType());
// Let's check if the response contains desired leases.
checkLease4(leases, "192.0.2.1", 44, "08:08:08:08:08:08", true);
checkLease4(leases, "192.0.2.2", 44, "09:09:09:09:09:09", true);
checkLease4(leases, "192.0.3.1", 88, "08:08:08:08:08:08", true);
checkLease4(leases, "192.0.3.2", 88, "09:09:09:09:09:09", true);
}
// Checks that lease4-get-all checks its input arguments.
TEST_F(LeaseCmdsTest, Lease4GetBySubnetIdInvalidArguments) {
// Initialize lease manager (false = v4, true = add a lease)
initLeaseMgr(false, true);
// Subnets not specified in arguments.
string cmd =
"{\n"
" \"command\": \"lease4-get-all\",\n"
" \"arguments\": {"
" \"foo\": 1\n"
" }\n"
"}";
string exp_rsp = "'subnets' parameter not specified";
testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
// Subnets are not a list.
cmd =
"{\n"
" \"command\": \"lease4-get-all\",\n"
" \"arguments\": {"
" \"subnets\": 1\n"
" }\n"
"}";
exp_rsp = "'subnets' parameter must be a list";
testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
// Subnets list must contain numbers.
cmd =
"{\n"
" \"command\": \"lease4-get-all\",\n"
" \"arguments\": {"
" \"subnets\": [ \"x\", \"y\" ]\n"
" }\n"
"}";
exp_rsp = "listed subnet identifiers must be numbers";
testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
}
// Checks that lease6-get(addr) can handle a situation when
// the query is correctly formed, but the lease is not there.
TEST_F(LeaseCmdsTest, Lease6GetByAddr6NotFound) {
......@@ -2098,7 +2249,7 @@ TEST_F(LeaseCmdsTest, Lease4Wipe) {
" \"subnet-id\": 44"
" }\n"
"}";
string exp_rsp = "Deleted 1 IPv4 lease(s).";
string exp_rsp = "Deleted 2 IPv4 lease(s).";
testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
// Make sure the lease is really gone.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment