Commit fc7e9a66 authored by Marcin Siodelski's avatar Marcin Siodelski

[5442] Implemented 'dhcp-disable' and 'dhcp-enable' commands for DHCPv6.

parent 8aa14067
......@@ -20,6 +20,7 @@
#include <stats/stats_mgr.h>
#include <cfgrpt/config_report.h>
#include <signal.h>
#include <sstream>
using namespace isc::config;
using namespace isc::dhcp;
......@@ -377,6 +378,64 @@ ControlledDhcpv6Srv::commandConfigTestHandler(const string&,
return (checkConfig(dhcp6));
}
ConstElementPtr
ControlledDhcpv6Srv::commandDhcpDisableHandler(const std::string&,
ConstElementPtr args) {
std::ostringstream message;
int64_t max_period = 0;
// Parse arguments to see if the 'max-period' parameter has been specified.
if (args) {
// Arguments must be a map.
if (args->getType() != Element::map) {
message << "arguments for the 'dhcp-disable' command must be a map";
} else {
ConstElementPtr max_period_element = args->get("max-period");
// max-period is optional.
if (max_period_element) {
// It must be an integer, if specified.
if (max_period_element->getType() != Element::integer) {
message << "'max-period' argument must be a number";
} else {
// It must be positive integer.
max_period = max_period_element->intValue();
if (max_period <= 0) {
message << "'max-period' must be positive integer";
}
// The user specified that the DHCP service should resume not
// later than in max-period seconds. If the 'dhcp-enable' command
// is not sent, the DHCP service will resume automatically.
network_state_.delayedEnableAll(static_cast<unsigned>(max_period));
}
}
}
}
// No error occurred, so let's disable the service.
if (message.tellp() == 0) {
network_state_.disableService();
message << "DHCPv4 service disabled";
if (max_period > 0) {
message << " for " << max_period << " seconds";
}
// Success.
return (config::createAnswer(CONTROL_RESULT_SUCCESS, message.str()));
}
// Failure.
return (config::createAnswer(CONTROL_RESULT_ERROR, message.str()));
}
ConstElementPtr
ControlledDhcpv6Srv::commandDhcpEnableHandler(const std::string&, ConstElementPtr) {
network_state_.enableService();
return (config::createAnswer(CONTROL_RESULT_SUCCESS, "DHCP service successfully enabled"));
}
ConstElementPtr
ControlledDhcpv6Srv::commandVersionGetHandler(const string&, ConstElementPtr) {
ElementPtr extended = Element::create(Dhcpv6Srv::getVersion(true));
......@@ -457,6 +516,12 @@ ControlledDhcpv6Srv::processCommand(const std::string& command,
} else if (command == "config-test") {
return (srv->commandConfigTestHandler(command, args));
} else if (command == "dhcp-disable") {
return (srv->commandDhcpDisableHandler(command, args));
} else if (command == "dhcp-enable") {
return (srv->commandDhcpEnableHandler(command, args));
} else if (command == "version-get") {
return (srv->commandVersionGetHandler(command, args));
......@@ -638,6 +703,12 @@ ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port)
CommandMgr::instance().registerCommand("config-write",
boost::bind(&ControlledDhcpv6Srv::commandConfigWriteHandler, this, _1, _2));
CommandMgr::instance().registerCommand("dhcp-disable",
boost::bind(&ControlledDhcpv6Srv::commandDhcpDisableHandler, this, _1, _2));
CommandMgr::instance().registerCommand("dhcp-enable",
boost::bind(&ControlledDhcpv6Srv::commandDhcpEnableHandler, this, _1, _2));
CommandMgr::instance().registerCommand("leases-reclaim",
boost::bind(&ControlledDhcpv6Srv::commandLeasesReclaimHandler, this, _1, _2));
......@@ -694,6 +765,8 @@ ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
CommandMgr::instance().deregisterCommand("config-reload");
CommandMgr::instance().deregisterCommand("config-test");
CommandMgr::instance().deregisterCommand("config-write");
CommandMgr::instance().deregisterCommand("dhcp-disable");
CommandMgr::instance().deregisterCommand("dhcp-enable");
CommandMgr::instance().deregisterCommand("leases-reclaim");
CommandMgr::instance().deregisterCommand("libreload");
CommandMgr::instance().deregisterCommand("shutdown");
......
......@@ -223,6 +223,27 @@ private:
commandConfigTestHandler(const std::string& command,
isc::data::ConstElementPtr args);
/// @brief A handler for processing 'dhcp-disable' command.
///
/// @param command command name (ignored).
/// @param args aguments for the command. It must be a map and
/// it may include optional 'max-period' parameter.
///
/// @return result of the command.
isc::data::ConstElementPtr
commandDhcpDisableHandler(const std::string& command,
isc::data::ConstElementPtr args);
/// @brief A handler for processing 'dhcp-enable' command.
///
/// @param command command name (ignored)
/// @param args arguments for the command (ignored).
///
/// @return result of the command.
isc::data::ConstElementPtr
commandDhcpEnableHandler(const std::string& command,
isc::data::ConstElementPtr args);
/// @Brief handler for processing 'version-get' command
///
/// This handler processes version-get command, which returns
......
......@@ -83,6 +83,7 @@ public:
/// Expose internal methods for the sake of testing
using Dhcpv6Srv::receivePacket;
using Dhcpv6Srv::network_state_;
};
/// @brief Default control connection timeout.
......@@ -1175,6 +1176,74 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configReloadValid) {
::remove("test8.json");
}
// This test verifies if it is possible to disable DHCP service via command.
TEST_F(CtrlChannelDhcpv6SrvTest, dhcpDisable) {
createUnixChannelServer();
std::string response;
sendUnixCommand("{ \"command\": \"dhcp-disable\" }", response);
ConstElementPtr rsp;
// The response should be a valid JSON.
EXPECT_NO_THROW(rsp = Element::fromJSON(response));
ASSERT_TRUE(rsp);
int status;
ConstElementPtr cfg = parseAnswer(status, rsp);
EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
EXPECT_FALSE(server_->network_state_.isServiceEnabled());
}
// This test verifies that it is possible to disable DHCP service for a short
// period of time, after which the service is automatically enabled.
TEST_F(CtrlChannelDhcpv6SrvTest, dhcpDisableTemporarily) {
createUnixChannelServer();
std::string response;
// Send a command to disable DHCP service for 3 seconds.
sendUnixCommand("{"
" \"command\": \"dhcp-disable\","
" \"arguments\": {"
" \"max-period\": 3"
" }"
"}", response);
ConstElementPtr rsp;
// The response should be a valid JSON.
EXPECT_NO_THROW(rsp = Element::fromJSON(response));
ASSERT_TRUE(rsp);
int status;
ConstElementPtr cfg = parseAnswer(status, rsp);
EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
// The service should be disabled.
EXPECT_FALSE(server_->network_state_.isServiceEnabled());
// And the timer should be scheduled which counts the time to automatic
// enabling of the service.
EXPECT_TRUE(server_->network_state_.isDelayedEnableAll());
}
// This test verifies if it is possible to enable DHCP service via command.
TEST_F(CtrlChannelDhcpv6SrvTest, dhcpEnable) {
createUnixChannelServer();
std::string response;
sendUnixCommand("{ \"command\": \"dhcp-enable\" }", response);
ConstElementPtr rsp;
// The response should be a valid JSON.
EXPECT_NO_THROW(rsp = Element::fromJSON(response));
ASSERT_TRUE(rsp);
int status;
ConstElementPtr cfg = parseAnswer(status, rsp);
EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
EXPECT_TRUE(server_->network_state_.isServiceEnabled());
}
/// Verify that concurrent connections over the control channel can be
/// established.
/// @todo Future Kea 1.3 tickets will modify the behavior of the CommandMgr
......
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