mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 14:35:29 +00:00
[master] Merged trac3978 (new leases-reclaim command)
This commit is contained in:
@@ -71,6 +71,32 @@ ControlledDhcpv4Srv::commandConfigReloadHandler(const string&,
|
|||||||
return (processConfig(args));
|
return (processConfig(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConstElementPtr
|
||||||
|
ControlledDhcpv4Srv::commandLeasesReclaimHandler(const string& command,
|
||||||
|
ConstElementPtr args) {
|
||||||
|
int status_code = 1;
|
||||||
|
string message;
|
||||||
|
|
||||||
|
// args must be { "remove": <bool> }
|
||||||
|
if (!args) {
|
||||||
|
message = "Missing mandatory 'remove' parameter.";
|
||||||
|
} else {
|
||||||
|
ConstElementPtr remove_name = args->get("remove");
|
||||||
|
if (!remove_name) {
|
||||||
|
message = "Missing mandatory 'remove' parameter.";
|
||||||
|
} else if (remove_name->getType() != Element::boolean) {
|
||||||
|
message = "'remove' parameter expected to be a boolean.";
|
||||||
|
} else {
|
||||||
|
bool remove_lease = remove_name->boolValue();
|
||||||
|
server_->alloc_engine_->reclaimExpiredLeases4(0, 0, remove_lease);
|
||||||
|
status_code = 0;
|
||||||
|
message = "Reclamation of expired leases is complete.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConstElementPtr answer = isc::config::createAnswer(status_code, message);
|
||||||
|
return (answer);
|
||||||
|
}
|
||||||
|
|
||||||
ConstElementPtr
|
ConstElementPtr
|
||||||
ControlledDhcpv4Srv::processCommand(const string& command,
|
ControlledDhcpv4Srv::processCommand(const string& command,
|
||||||
ConstElementPtr args) {
|
ConstElementPtr args) {
|
||||||
@@ -96,6 +122,8 @@ ControlledDhcpv4Srv::processCommand(const string& command,
|
|||||||
} else if (command == "config-reload") {
|
} else if (command == "config-reload") {
|
||||||
return (srv->commandConfigReloadHandler(command, args));
|
return (srv->commandConfigReloadHandler(command, args));
|
||||||
|
|
||||||
|
} else if (command == "leases-reclaim") {
|
||||||
|
return (srv->commandLeasesReclaimHandler(command, args));
|
||||||
}
|
}
|
||||||
ConstElementPtr answer = isc::config::createAnswer(1,
|
ConstElementPtr answer = isc::config::createAnswer(1,
|
||||||
"Unrecognized command:" + command);
|
"Unrecognized command:" + command);
|
||||||
@@ -212,6 +240,9 @@ ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t port /*= DHCP4_SERVER_PORT*/)
|
|||||||
/// @todo: register config-reload (see CtrlDhcpv4Srv::commandConfigReloadHandler)
|
/// @todo: register config-reload (see CtrlDhcpv4Srv::commandConfigReloadHandler)
|
||||||
/// @todo: register libreload (see CtrlDhcpv4Srv::commandLibReloadHandler)
|
/// @todo: register libreload (see CtrlDhcpv4Srv::commandLibReloadHandler)
|
||||||
|
|
||||||
|
CommandMgr::instance().registerCommand("leases-reclaim",
|
||||||
|
boost::bind(&ControlledDhcpv4Srv::commandLeasesReclaimHandler, this, _1, _2));
|
||||||
|
|
||||||
// Register statistic related commands
|
// Register statistic related commands
|
||||||
CommandMgr::instance().registerCommand("statistic-get",
|
CommandMgr::instance().registerCommand("statistic-get",
|
||||||
boost::bind(&StatsMgr::statisticGetHandler, _1, _2));
|
boost::bind(&StatsMgr::statisticGetHandler, _1, _2));
|
||||||
@@ -251,6 +282,7 @@ ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
|
|||||||
|
|
||||||
// Deregister any registered commands
|
// Deregister any registered commands
|
||||||
CommandMgr::instance().deregisterCommand("shutdown");
|
CommandMgr::instance().deregisterCommand("shutdown");
|
||||||
|
CommandMgr::instance().deregisterCommand("leases-reclaim");
|
||||||
CommandMgr::instance().deregisterCommand("statistic-get");
|
CommandMgr::instance().deregisterCommand("statistic-get");
|
||||||
CommandMgr::instance().deregisterCommand("statistic-reset");
|
CommandMgr::instance().deregisterCommand("statistic-reset");
|
||||||
CommandMgr::instance().deregisterCommand("statistic-remove");
|
CommandMgr::instance().deregisterCommand("statistic-remove");
|
||||||
|
@@ -70,6 +70,7 @@ public:
|
|||||||
/// - shutdown
|
/// - shutdown
|
||||||
/// - libreload
|
/// - libreload
|
||||||
/// - config-reload
|
/// - config-reload
|
||||||
|
/// - leases-reclaim
|
||||||
///
|
///
|
||||||
/// @note It never throws.
|
/// @note It never throws.
|
||||||
///
|
///
|
||||||
@@ -151,6 +152,23 @@ private:
|
|||||||
isc::data::ConstElementPtr args);
|
isc::data::ConstElementPtr args);
|
||||||
|
|
||||||
|
|
||||||
|
/// @brief Handler for processing 'leases-reclaim' command
|
||||||
|
///
|
||||||
|
/// This handler processes leases-reclaim command, which triggers
|
||||||
|
/// the leases reclamation immediately.
|
||||||
|
/// No limit for processing time or number of processed leases applies.
|
||||||
|
///
|
||||||
|
/// @param command (parameter ignored)
|
||||||
|
/// @param args arguments map { "remove": <bool> }
|
||||||
|
/// if true a lease is removed when it is reclaimed,
|
||||||
|
/// if false its state is changed to "expired-reclaimed".
|
||||||
|
///
|
||||||
|
/// @return status of the command (should be success unless args
|
||||||
|
/// was not a Bool Element).
|
||||||
|
isc::data::ConstElementPtr
|
||||||
|
commandLeasesReclaimHandler(const std::string& command,
|
||||||
|
isc::data::ConstElementPtr args);
|
||||||
|
|
||||||
/// @brief Reclaims expired IPv4 leases and reschedules timer.
|
/// @brief Reclaims expired IPv4 leases and reschedules timer.
|
||||||
///
|
///
|
||||||
/// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases4.
|
/// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases4.
|
||||||
|
@@ -69,11 +69,11 @@ void configure(const std::string& file_name) {
|
|||||||
// works only for map.
|
// works only for map.
|
||||||
if (json->getType() != isc::data::Element::map) {
|
if (json->getType() != isc::data::Element::map) {
|
||||||
isc_throw(isc::BadValue, "Configuration file is expected to be "
|
isc_throw(isc::BadValue, "Configuration file is expected to be "
|
||||||
"a map, i.e., start with { and end with } and contain "
|
"a map, i.e., start with { and end with } and contain "
|
||||||
"at least an entry called 'Dhcp4' that itself is a map. "
|
"at least an entry called 'Dhcp4' that itself is a map. "
|
||||||
<< file_name
|
<< file_name
|
||||||
<< " is a valid JSON, but its top element is not a map."
|
<< " is a valid JSON, but its top element is not a map."
|
||||||
" Did you forget to add { } around your configuration?");
|
" Did you forget to add { } around your configuration?");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no logging element, we'll just pass NULL pointer,
|
// If there's no logging element, we'll just pass NULL pointer,
|
||||||
|
@@ -3665,7 +3665,7 @@ TEST_F(Dhcp4ParserTest, declineTimerDefault) {
|
|||||||
// returned value should be 0 (success)
|
// returned value should be 0 (success)
|
||||||
checkResult(status, 0);
|
checkResult(status, 0);
|
||||||
|
|
||||||
// The value of decline-probation-perion must be equal to the
|
// The value of decline-probation-period must be equal to the
|
||||||
// default value.
|
// default value.
|
||||||
EXPECT_EQ(DEFAULT_DECLINE_PROBATION_PERIOD,
|
EXPECT_EQ(DEFAULT_DECLINE_PROBATION_PERIOD,
|
||||||
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
||||||
@@ -3687,7 +3687,7 @@ TEST_F(Dhcp4ParserTest, declineTimer) {
|
|||||||
// returned value should be 0 (success)
|
// returned value should be 0 (success)
|
||||||
checkResult(status, 0);
|
checkResult(status, 0);
|
||||||
|
|
||||||
// The value of decline-probation-perion must be equal to the
|
// The value of decline-probation-period must be equal to the
|
||||||
// value specified.
|
// value specified.
|
||||||
EXPECT_EQ(12345,
|
EXPECT_EQ(12345,
|
||||||
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
||||||
@@ -3738,7 +3738,7 @@ TEST_F(Dhcp4ParserTest, expiredLeasesProcessing) {
|
|||||||
// Returned value should be 0 (success)
|
// Returned value should be 0 (success)
|
||||||
checkResult(status, 0);
|
checkResult(status, 0);
|
||||||
|
|
||||||
// The value of decline-probation-perion must be equal to the
|
// The value of decline-probation-period must be equal to the
|
||||||
// value specified.
|
// value specified.
|
||||||
CfgExpirationPtr cfg = CfgMgr::instance().getStagingCfg()->getCfgExpiration();
|
CfgExpirationPtr cfg = CfgMgr::instance().getStagingCfg()->getCfgExpiration();
|
||||||
ASSERT_TRUE(cfg);
|
ASSERT_TRUE(cfg);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2012-2013, 2015 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -19,7 +19,10 @@
|
|||||||
#include <dhcp/dhcp4.h>
|
#include <dhcp/dhcp4.h>
|
||||||
#include <dhcp4/ctrl_dhcp4_srv.h>
|
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||||
#include <dhcpsrv/cfgmgr.h>
|
#include <dhcpsrv/cfgmgr.h>
|
||||||
|
#include <dhcpsrv/lease.h>
|
||||||
|
#include <dhcpsrv/lease_mgr_factory.h>
|
||||||
#include <hooks/hooks_manager.h>
|
#include <hooks/hooks_manager.h>
|
||||||
|
#include <stats/stats_mgr.h>
|
||||||
#include <testutils/unix_control_client.h>
|
#include <testutils/unix_control_client.h>
|
||||||
|
|
||||||
#include "marker_file.h"
|
#include "marker_file.h"
|
||||||
@@ -43,6 +46,7 @@ using namespace isc::data;
|
|||||||
using namespace isc::dhcp;
|
using namespace isc::dhcp;
|
||||||
using namespace isc::dhcp::test;
|
using namespace isc::dhcp::test;
|
||||||
using namespace isc::hooks;
|
using namespace isc::hooks;
|
||||||
|
using namespace isc::stats;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -80,6 +84,8 @@ public:
|
|||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
~CtrlChannelDhcpv4SrvTest() {
|
~CtrlChannelDhcpv4SrvTest() {
|
||||||
|
LeaseMgrFactory::destroy();
|
||||||
|
StatsMgr::instance().removeAll();
|
||||||
server_.reset();
|
server_.reset();
|
||||||
reset();
|
reset();
|
||||||
};
|
};
|
||||||
@@ -94,6 +100,11 @@ public:
|
|||||||
" \"interfaces-config\": {"
|
" \"interfaces-config\": {"
|
||||||
" \"interfaces\": [ \"*\" ]"
|
" \"interfaces\": [ \"*\" ]"
|
||||||
" },"
|
" },"
|
||||||
|
" \"expired-leases-processing\": {"
|
||||||
|
" \"reclaim-timer-wait-time\": 60,"
|
||||||
|
" \"hold-reclaimed-time\": 500,"
|
||||||
|
" \"flush-reclaimed-timer-wait-time\": 60"
|
||||||
|
" },"
|
||||||
" \"rebind-timer\": 2000, "
|
" \"rebind-timer\": 2000, "
|
||||||
" \"renew-timer\": 1000, "
|
" \"renew-timer\": 1000, "
|
||||||
" \"subnet4\": [ ],"
|
" \"subnet4\": [ ],"
|
||||||
@@ -333,6 +344,103 @@ TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelShutdown) {
|
|||||||
EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutting down.\" }",response);
|
EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutting down.\" }",response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that the DHCP server immediately reclaims expired
|
||||||
|
// leases on leases-reclaim command
|
||||||
|
TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaim) {
|
||||||
|
createUnixChannelServer();
|
||||||
|
|
||||||
|
// Create expired leases. Leases are expired by 40 seconds ago
|
||||||
|
// (valid lifetime = 60, cltt = now - 100).
|
||||||
|
HWAddrPtr hwaddr0(new HWAddr(HWAddr::fromText("00:01:02:03:04:05")));
|
||||||
|
Lease4Ptr lease0(new Lease4(IOAddress("10.0.0.1"), hwaddr0,
|
||||||
|
ClientIdPtr(), 60, 10, 20,
|
||||||
|
time(NULL) - 100, SubnetID(1)));
|
||||||
|
HWAddrPtr hwaddr1(new HWAddr(HWAddr::fromText("01:02:03:04:05:06")));
|
||||||
|
Lease4Ptr lease1(new Lease4(IOAddress("10.0.0.2"), hwaddr1,
|
||||||
|
ClientIdPtr(), 60, 10, 20,
|
||||||
|
time(NULL) - 100, SubnetID(1)));
|
||||||
|
|
||||||
|
// Add leases to the database.
|
||||||
|
LeaseMgr& lease_mgr = LeaseMgrFactory().instance();
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease0));
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease1));
|
||||||
|
|
||||||
|
// Make sure they have been added.
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.1")));
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.2")));
|
||||||
|
|
||||||
|
// No arguments
|
||||||
|
std::string response;
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\" }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 1, \"text\": "
|
||||||
|
"\"Missing mandatory 'remove' parameter.\" }", response);
|
||||||
|
|
||||||
|
// Bad argument name
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"reclaim\": true } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 1, \"text\": "
|
||||||
|
"\"Missing mandatory 'remove' parameter.\" }", response);
|
||||||
|
|
||||||
|
// Bad remove argument type
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"remove\": \"bogus\" } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 1, \"text\": "
|
||||||
|
"\"'remove' parameter expected to be a boolean.\" }", response);
|
||||||
|
|
||||||
|
// Send the command
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"remove\": false } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 0, \"text\": "
|
||||||
|
"\"Reclamation of expired leases is complete.\" }", response);
|
||||||
|
|
||||||
|
// Leases should be reclaimed, but not removed
|
||||||
|
ASSERT_NO_THROW(lease0 = lease_mgr.getLease4(IOAddress("10.0.0.1")));
|
||||||
|
ASSERT_NO_THROW(lease1 = lease_mgr.getLease4(IOAddress("10.0.0.2")));
|
||||||
|
ASSERT_TRUE(lease0);
|
||||||
|
ASSERT_TRUE(lease1);
|
||||||
|
EXPECT_TRUE(lease0->stateExpiredReclaimed());
|
||||||
|
EXPECT_TRUE(lease1->stateExpiredReclaimed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thist test verifies that the DHCP server immediately removed expired
|
||||||
|
// leases on leases-reclaim command with remove = true
|
||||||
|
TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaimRemove) {
|
||||||
|
createUnixChannelServer();
|
||||||
|
|
||||||
|
// Create expired leases. Leases are expired by 40 seconds ago
|
||||||
|
// (valid lifetime = 60, cltt = now - 100).
|
||||||
|
HWAddrPtr hwaddr0(new HWAddr(HWAddr::fromText("00:01:02:03:04:05")));
|
||||||
|
Lease4Ptr lease0(new Lease4(IOAddress("10.0.0.1"), hwaddr0,
|
||||||
|
ClientIdPtr(), 60, 10, 20,
|
||||||
|
time(NULL) - 100, SubnetID(1)));
|
||||||
|
HWAddrPtr hwaddr1(new HWAddr(HWAddr::fromText("01:02:03:04:05:06")));
|
||||||
|
Lease4Ptr lease1(new Lease4(IOAddress("10.0.0.2"), hwaddr1,
|
||||||
|
ClientIdPtr(), 60, 10, 20,
|
||||||
|
time(NULL) - 100, SubnetID(1)));
|
||||||
|
|
||||||
|
// Add leases to the database.
|
||||||
|
LeaseMgr& lease_mgr = LeaseMgrFactory().instance();
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease0));
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease1));
|
||||||
|
|
||||||
|
// Make sure they have been added.
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.1")));
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.2")));
|
||||||
|
|
||||||
|
// Send the command
|
||||||
|
std::string response;
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"remove\": true } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 0, \"text\": "
|
||||||
|
"\"Reclamation of expired leases is complete.\" }", response);
|
||||||
|
|
||||||
|
// Leases should have been removed.
|
||||||
|
ASSERT_NO_THROW(lease0 = lease_mgr.getLease4(IOAddress("10.0.0.1")));
|
||||||
|
ASSERT_NO_THROW(lease1 = lease_mgr.getLease4(IOAddress("10.0.0.2")));
|
||||||
|
EXPECT_FALSE(lease0);
|
||||||
|
EXPECT_FALSE(lease1);
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the server properly responds to statistics commands. Note this
|
// Tests that the server properly responds to statistics commands. Note this
|
||||||
// is really only intended to verify that the appropriate Statistics handler
|
// is really only intended to verify that the appropriate Statistics handler
|
||||||
// is called based on the command. It is not intended to be an exhaustive
|
// is called based on the command. It is not intended to be an exhaustive
|
||||||
@@ -379,5 +487,4 @@ TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelStats) {
|
|||||||
response);
|
response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // End of anonymous namespace
|
} // End of anonymous namespace
|
||||||
|
@@ -69,6 +69,32 @@ ControlledDhcpv6Srv::commandConfigReloadHandler(const string&, ConstElementPtr a
|
|||||||
return (processConfig(args));
|
return (processConfig(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConstElementPtr
|
||||||
|
ControlledDhcpv6Srv::commandLeasesReclaimHandler(const string& command,
|
||||||
|
ConstElementPtr args) {
|
||||||
|
int status_code = 1;
|
||||||
|
string message;
|
||||||
|
|
||||||
|
// args must be { "remove": <bool> }
|
||||||
|
if (!args) {
|
||||||
|
message = "Missing mandatory 'remove' parameter.";
|
||||||
|
} else {
|
||||||
|
ConstElementPtr remove_name = args->get("remove");
|
||||||
|
if (!remove_name) {
|
||||||
|
message = "Missing mandatory 'remove' parameter.";
|
||||||
|
} else if (remove_name->getType() != Element::boolean) {
|
||||||
|
message = "'remove' parameter expected to be a boolean.";
|
||||||
|
} else {
|
||||||
|
bool remove_lease = remove_name->boolValue();
|
||||||
|
server_->alloc_engine_->reclaimExpiredLeases6(0, 0, remove_lease);
|
||||||
|
status_code = 0;
|
||||||
|
message = "Reclamation of expired leases is complete.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConstElementPtr answer = isc::config::createAnswer(status_code, message);
|
||||||
|
return (answer);
|
||||||
|
}
|
||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
ControlledDhcpv6Srv::processCommand(const std::string& command,
|
ControlledDhcpv6Srv::processCommand(const std::string& command,
|
||||||
isc::data::ConstElementPtr args) {
|
isc::data::ConstElementPtr args) {
|
||||||
@@ -93,6 +119,9 @@ ControlledDhcpv6Srv::processCommand(const std::string& command,
|
|||||||
|
|
||||||
} else if (command == "config-reload") {
|
} else if (command == "config-reload") {
|
||||||
return (srv->commandConfigReloadHandler(command, args));
|
return (srv->commandConfigReloadHandler(command, args));
|
||||||
|
|
||||||
|
} else if (command == "leases-reclaim") {
|
||||||
|
return (srv->commandLeasesReclaimHandler(command, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (isc::config::createAnswer(1, "Unrecognized command:"
|
return (isc::config::createAnswer(1, "Unrecognized command:"
|
||||||
@@ -208,6 +237,9 @@ ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port)
|
|||||||
/// @todo: register config-reload (see CtrlDhcpv4Srv::commandConfigReloadHandler)
|
/// @todo: register config-reload (see CtrlDhcpv4Srv::commandConfigReloadHandler)
|
||||||
/// @todo: register libreload (see CtrlDhcpv4Srv::commandLibReloadHandler)
|
/// @todo: register libreload (see CtrlDhcpv4Srv::commandLibReloadHandler)
|
||||||
|
|
||||||
|
CommandMgr::instance().registerCommand("leases-reclaim",
|
||||||
|
boost::bind(&ControlledDhcpv6Srv::commandLeasesReclaimHandler, this, _1, _2));
|
||||||
|
|
||||||
// Register statistic related commands
|
// Register statistic related commands
|
||||||
CommandMgr::instance().registerCommand("statistic-get",
|
CommandMgr::instance().registerCommand("statistic-get",
|
||||||
boost::bind(&StatsMgr::statisticGetHandler, _1, _2));
|
boost::bind(&StatsMgr::statisticGetHandler, _1, _2));
|
||||||
@@ -247,6 +279,7 @@ ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
|
|||||||
|
|
||||||
// Deregister any registered commands
|
// Deregister any registered commands
|
||||||
CommandMgr::instance().deregisterCommand("shutdown");
|
CommandMgr::instance().deregisterCommand("shutdown");
|
||||||
|
CommandMgr::instance().deregisterCommand("leases-reclaim");
|
||||||
CommandMgr::instance().deregisterCommand("statistic-get");
|
CommandMgr::instance().deregisterCommand("statistic-get");
|
||||||
CommandMgr::instance().deregisterCommand("statistic-reset");
|
CommandMgr::instance().deregisterCommand("statistic-reset");
|
||||||
CommandMgr::instance().deregisterCommand("statistic-remove");
|
CommandMgr::instance().deregisterCommand("statistic-remove");
|
||||||
|
@@ -70,6 +70,7 @@ public:
|
|||||||
/// - shutdown
|
/// - shutdown
|
||||||
/// - libreload
|
/// - libreload
|
||||||
/// - config-reload
|
/// - config-reload
|
||||||
|
/// - leases-reclaim
|
||||||
///
|
///
|
||||||
/// @note It never throws.
|
/// @note It never throws.
|
||||||
///
|
///
|
||||||
@@ -150,6 +151,23 @@ private:
|
|||||||
commandConfigReloadHandler(const std::string& command,
|
commandConfigReloadHandler(const std::string& command,
|
||||||
isc::data::ConstElementPtr args);
|
isc::data::ConstElementPtr args);
|
||||||
|
|
||||||
|
/// @brief Handler for processing 'leases-reclaim' command
|
||||||
|
///
|
||||||
|
/// This handler processes leases-reclaim command, which triggers
|
||||||
|
/// the leases reclamation immediately.
|
||||||
|
/// No limit for processing time or number of processed leases applies.
|
||||||
|
///
|
||||||
|
/// @param command (parameter ignored)
|
||||||
|
/// @param args arguments map { "remove": <bool> }
|
||||||
|
/// if true a lease is removed when it is reclaimed,
|
||||||
|
/// if false its state is changed to "expired-reclaimed".
|
||||||
|
///
|
||||||
|
/// @return status of the command (should be success unless args
|
||||||
|
/// was not a Bool Element).
|
||||||
|
isc::data::ConstElementPtr
|
||||||
|
commandLeasesReclaimHandler(const std::string& command,
|
||||||
|
isc::data::ConstElementPtr args);
|
||||||
|
|
||||||
/// @brief Reclaims expired IPv6 leases and reschedules timer.
|
/// @brief Reclaims expired IPv6 leases and reschedules timer.
|
||||||
///
|
///
|
||||||
/// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases6.
|
/// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases6.
|
||||||
|
@@ -73,11 +73,11 @@ void configure(const std::string& file_name) {
|
|||||||
// works only for map.
|
// works only for map.
|
||||||
if (json->getType() != isc::data::Element::map) {
|
if (json->getType() != isc::data::Element::map) {
|
||||||
isc_throw(isc::BadValue, "Configuration file is expected to be "
|
isc_throw(isc::BadValue, "Configuration file is expected to be "
|
||||||
"a map, i.e., start with { and end with } and contain "
|
"a map, i.e., start with { and end with } and contain "
|
||||||
"at least an entry called 'Dhcp6' that itself is a map. "
|
"at least an entry called 'Dhcp6' that itself is a map. "
|
||||||
<< file_name
|
<< file_name
|
||||||
<< " is a valid JSON, but its top element is not a map."
|
<< " is a valid JSON, but its top element is not a map."
|
||||||
" Did you forget to add { } around your configuration?");
|
" Did you forget to add { } around your configuration?");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's configure logging before applying the configuration,
|
// Let's configure logging before applying the configuration,
|
||||||
|
@@ -3999,7 +3999,7 @@ TEST_F(Dhcp6ParserTest, declineTimerDefault) {
|
|||||||
// returned value should be 0 (success)
|
// returned value should be 0 (success)
|
||||||
checkResult(status, 0);
|
checkResult(status, 0);
|
||||||
|
|
||||||
// The value of decline-probation-perion must be equal to the
|
// The value of decline-probation-period must be equal to the
|
||||||
// default value.
|
// default value.
|
||||||
EXPECT_EQ(DEFAULT_DECLINE_PROBATION_PERIOD,
|
EXPECT_EQ(DEFAULT_DECLINE_PROBATION_PERIOD,
|
||||||
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
||||||
@@ -4021,7 +4021,7 @@ TEST_F(Dhcp6ParserTest, declineTimer) {
|
|||||||
// returned value should be 0 (success)
|
// returned value should be 0 (success)
|
||||||
checkResult(status, 0);
|
checkResult(status, 0);
|
||||||
|
|
||||||
// The value of decline-probation-perion must be equal to the
|
// The value of decline-probation-period must be equal to the
|
||||||
// value specified.
|
// value specified.
|
||||||
EXPECT_EQ(12345,
|
EXPECT_EQ(12345,
|
||||||
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
|
||||||
@@ -4072,7 +4072,7 @@ TEST_F(Dhcp6ParserTest, expiredLeasesProcessing) {
|
|||||||
// Returned value should be 0 (success)
|
// Returned value should be 0 (success)
|
||||||
checkResult(status, 0);
|
checkResult(status, 0);
|
||||||
|
|
||||||
// The value of decline-probation-perion must be equal to the
|
// The value of decline-probation-period must be equal to the
|
||||||
// value specified.
|
// value specified.
|
||||||
CfgExpirationPtr cfg = CfgMgr::instance().getStagingCfg()->getCfgExpiration();
|
CfgExpirationPtr cfg = CfgMgr::instance().getStagingCfg()->getCfgExpiration();
|
||||||
ASSERT_TRUE(cfg);
|
ASSERT_TRUE(cfg);
|
||||||
|
@@ -14,11 +14,15 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <asiolink/io_address.h>
|
||||||
#include <cc/command_interpreter.h>
|
#include <cc/command_interpreter.h>
|
||||||
#include <config/command_mgr.h>
|
#include <config/command_mgr.h>
|
||||||
#include <dhcpsrv/cfgmgr.h>
|
#include <dhcpsrv/cfgmgr.h>
|
||||||
|
#include <dhcpsrv/lease.h>
|
||||||
|
#include <dhcpsrv/lease_mgr_factory.h>
|
||||||
#include <dhcp6/ctrl_dhcp6_srv.h>
|
#include <dhcp6/ctrl_dhcp6_srv.h>
|
||||||
#include <hooks/hooks_manager.h>
|
#include <hooks/hooks_manager.h>
|
||||||
|
#include <stats/stats_mgr.h>
|
||||||
#include <testutils/unix_control_client.h>
|
#include <testutils/unix_control_client.h>
|
||||||
|
|
||||||
#include "marker_file.h"
|
#include "marker_file.h"
|
||||||
@@ -32,11 +36,13 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace isc::asiolink;
|
||||||
using namespace isc::config;
|
using namespace isc::config;
|
||||||
using namespace isc::data;
|
using namespace isc::data;
|
||||||
using namespace isc::dhcp;
|
using namespace isc::dhcp;
|
||||||
using namespace isc::dhcp::test;
|
using namespace isc::dhcp::test;
|
||||||
using namespace isc::hooks;
|
using namespace isc::hooks;
|
||||||
|
using namespace isc::stats;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -59,6 +65,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CtrlDhcpv6SrvTest() {
|
virtual ~CtrlDhcpv6SrvTest() {
|
||||||
|
LeaseMgrFactory::destroy();
|
||||||
|
StatsMgr::instance().removeAll();
|
||||||
reset();
|
reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,6 +126,11 @@ public:
|
|||||||
" \"interfaces-config\": {"
|
" \"interfaces-config\": {"
|
||||||
" \"interfaces\": [ \"*\" ]"
|
" \"interfaces\": [ \"*\" ]"
|
||||||
" },"
|
" },"
|
||||||
|
" \"expired-leases-processing\": {"
|
||||||
|
" \"reclaim-timer-wait-time\": 60,"
|
||||||
|
" \"hold-reclaimed-time\": 500,"
|
||||||
|
" \"flush-reclaimed-timer-wait-time\": 60"
|
||||||
|
" },"
|
||||||
" \"rebind-timer\": 2000, "
|
" \"rebind-timer\": 2000, "
|
||||||
" \"renew-timer\": 1000, "
|
" \"renew-timer\": 1000, "
|
||||||
" \"subnet6\": [ ],"
|
" \"subnet6\": [ ],"
|
||||||
@@ -406,6 +419,111 @@ TEST_F(CtrlChannelDhcpv6SrvTest, controlChannelShutdown) {
|
|||||||
EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutting down.\" }",response);
|
EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutting down.\" }",response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that the DHCP server immediately reclaims expired
|
||||||
|
// leases on leases-reclaim command
|
||||||
|
TEST_F(CtrlChannelDhcpv6SrvTest, controlLeasesReclaim) {
|
||||||
|
createUnixChannelServer();
|
||||||
|
|
||||||
|
// Create expired leases. Leases are expired by 40 seconds ago
|
||||||
|
// (valid lifetime = 60, cltt = now - 100).
|
||||||
|
DuidPtr duid0(new DUID(DUID::fromText("00:01:02:03:04:05:06").getDuid()));
|
||||||
|
Lease6Ptr lease0(new Lease6(Lease::TYPE_NA, IOAddress("3000::1"),
|
||||||
|
duid0, 1, 50, 60, 10, 20, SubnetID(1)));
|
||||||
|
lease0->cltt_ = time(NULL) - 100;
|
||||||
|
DuidPtr duid1(new DUID(DUID::fromText("01:02:03:04:05:06:07").getDuid()));
|
||||||
|
Lease6Ptr lease1(new Lease6(Lease::TYPE_NA, IOAddress("3000::2"),
|
||||||
|
duid1, 1, 50, 60, 10, 20, SubnetID(1)));
|
||||||
|
lease1->cltt_ = time(NULL) - 100;
|
||||||
|
|
||||||
|
// Add leases to the database.
|
||||||
|
LeaseMgr& lease_mgr = LeaseMgrFactory().instance();
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease0));
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease1));
|
||||||
|
|
||||||
|
// Make sure they have been added.
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::1")));
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::2")));
|
||||||
|
|
||||||
|
// No arguments
|
||||||
|
std::string response;
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\" }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 1, \"text\": "
|
||||||
|
"\"Missing mandatory 'remove' parameter.\" }", response);
|
||||||
|
|
||||||
|
// Bad argument name
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"reclaim\": true } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 1, \"text\": "
|
||||||
|
"\"Missing mandatory 'remove' parameter.\" }", response);
|
||||||
|
|
||||||
|
// Bad remove argument type
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"remove\": \"bogus\" } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 1, \"text\": "
|
||||||
|
"\"'remove' parameter expected to be a boolean.\" }", response);
|
||||||
|
|
||||||
|
// Send the command
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"remove\": false } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 0, \"text\": "
|
||||||
|
"\"Reclamation of expired leases is complete.\" }", response);
|
||||||
|
|
||||||
|
// Leases should be reclaimed, but not removed
|
||||||
|
ASSERT_NO_THROW(
|
||||||
|
lease0 = lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::1"))
|
||||||
|
);
|
||||||
|
ASSERT_NO_THROW(
|
||||||
|
lease1 = lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::2"))
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(lease0);
|
||||||
|
ASSERT_TRUE(lease1);
|
||||||
|
EXPECT_TRUE(lease0->stateExpiredReclaimed());
|
||||||
|
EXPECT_TRUE(lease1->stateExpiredReclaimed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test verifies that the DHCP server immediately reclaims expired
|
||||||
|
// leases on leases-reclaim command with remove = true
|
||||||
|
TEST_F(CtrlChannelDhcpv6SrvTest, controlLeasesReclaimRemove) {
|
||||||
|
createUnixChannelServer();
|
||||||
|
|
||||||
|
// Create expired leases. Leases are expired by 40 seconds ago
|
||||||
|
// (valid lifetime = 60, cltt = now - 100).
|
||||||
|
DuidPtr duid0(new DUID(DUID::fromText("00:01:02:03:04:05:06").getDuid()));
|
||||||
|
Lease6Ptr lease0(new Lease6(Lease::TYPE_NA, IOAddress("3000::1"),
|
||||||
|
duid0, 1, 50, 60, 10, 20, SubnetID(1)));
|
||||||
|
lease0->cltt_ = time(NULL) - 100;
|
||||||
|
DuidPtr duid1(new DUID(DUID::fromText("01:02:03:04:05:06:07").getDuid()));
|
||||||
|
Lease6Ptr lease1(new Lease6(Lease::TYPE_NA, IOAddress("3000::2"),
|
||||||
|
duid1, 1, 50, 60, 10, 20, SubnetID(1)));
|
||||||
|
lease1->cltt_ = time(NULL) - 100;
|
||||||
|
|
||||||
|
// Add leases to the database.
|
||||||
|
LeaseMgr& lease_mgr = LeaseMgrFactory().instance();
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease0));
|
||||||
|
ASSERT_NO_THROW(lease_mgr.addLease(lease1));
|
||||||
|
|
||||||
|
// Make sure they have been added.
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::1")));
|
||||||
|
ASSERT_TRUE(lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::2")));
|
||||||
|
|
||||||
|
// Send the command
|
||||||
|
std::string response;
|
||||||
|
sendUnixCommand("{ \"command\": \"leases-reclaim\", "
|
||||||
|
"\"arguments\": { \"remove\": true } }", response);
|
||||||
|
EXPECT_EQ("{ \"result\": 0, \"text\": "
|
||||||
|
"\"Reclamation of expired leases is complete.\" }", response);
|
||||||
|
|
||||||
|
// Leases should have been removed.
|
||||||
|
ASSERT_NO_THROW(
|
||||||
|
lease0 = lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::1"))
|
||||||
|
);
|
||||||
|
ASSERT_NO_THROW(
|
||||||
|
lease1 = lease_mgr.getLease6(Lease::TYPE_NA, IOAddress("3000::2"))
|
||||||
|
);
|
||||||
|
ASSERT_FALSE(lease0);
|
||||||
|
ASSERT_FALSE(lease1);
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the server properly responds to statistics commands. Note this
|
// Tests that the server properly responds to statistics commands. Note this
|
||||||
// is really only intended to verify that the appropriate Statistics handler
|
// is really only intended to verify that the appropriate Statistics handler
|
||||||
// is called based on the command. It is not intended to be an exhaustive
|
// is called based on the command. It is not intended to be an exhaustive
|
||||||
|
@@ -65,7 +65,7 @@ public:
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// CommandsMgr does not implement the commands (except one, "commands-list")
|
/// CommandsMgr does not implement the commands (except one, "list-commands")
|
||||||
/// itself, but rather provides an interface (see @ref registerCommand,
|
/// itself, but rather provides an interface (see @ref registerCommand,
|
||||||
/// @ref deregisterCommand, @ref processCommand) for other components to use
|
/// @ref deregisterCommand, @ref processCommand) for other components to use
|
||||||
/// it. The @ref CommandHandler type is specified in a way to easily use
|
/// it. The @ref CommandHandler type is specified in a way to easily use
|
||||||
|
Reference in New Issue
Block a user