} catch (const std::exception& ex) {
// Log the unsuccessful reconfiguration. The reason for failure
// should be already logged. Don't rethrow an exception so as
- // the control channel perhaps keeps working.
+ // the server keeps working.
LOG_FATAL(dhcp4_logger, DHCP4_DYNAMIC_RECONFIGURATION_FAIL)
.arg(file);
return (createAnswer(CONTROL_RESULT_ERROR,
// the logging first in case there's a configuration failure.
int rcode = 0;
isc::config::parseAnswer(rcode, result);
- if (rcode == 0) {
+ if (rcode == CONTROL_RESULT_SUCCESS) {
CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
// Use new configuration.
ConstElementPtr args) {
std::ostringstream message;
int64_t max_period = 0;
+ int64_t handle_id = 0;
+
+ NetworkState::ControllerType type = NetworkState::COMMAND;
// Parse arguments to see if the 'max-period' parameter has been specified.
if (args) {
network_state_->delayedEnableAll(static_cast<unsigned>(max_period));
}
}
+ ConstElementPtr handle_id_element = args->get("handle-id");
+ // handle-id is optional.
+ if (handle_id_element) {
+ // It must be an integer, if specified.
+ if (handle_id_element->getType() != Element::integer) {
+ message << "'handle-id' argument must be a number";
+
+ } else {
+ // It must be positive integer.
+ handle_id = handle_id_element->intValue();
+ if (handle_id <= 0) {
+ message << "'handle-id' must be positive integer";
+ }
+ type = NetworkState::HA;
+ }
+ }
}
}
// No error occurred, so let's disable the service.
if (message.tellp() == 0) {
- network_state_->disableService(NetworkState::COMMAND);
+ network_state_->disableService(type);
message << "DHCPv4 service disabled";
if (max_period > 0) {
}
ConstElementPtr
-ControlledDhcpv4Srv::commandDhcpEnableHandler(const std::string&, ConstElementPtr) {
- network_state_->enableService(NetworkState::COMMAND);
- return (config::createAnswer(CONTROL_RESULT_SUCCESS, "DHCP service successfully enabled"));
+ControlledDhcpv4Srv::commandDhcpEnableHandler(const std::string&,
+ ConstElementPtr args) {
+ std::ostringstream message;
+ int64_t handle_id = 0;
+
+ NetworkState::ControllerType type = NetworkState::COMMAND;
+
+ // 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-enable' command must be a map";
+
+ } else {
+ ConstElementPtr handle_id_element = args->get("handle-id");
+ // handle-id is optional.
+ if (handle_id_element) {
+ // It must be an integer, if specified.
+ if (handle_id_element->getType() != Element::integer) {
+ message << "'handle-id' argument must be a number";
+
+ } else {
+ // It must be positive integer.
+ handle_id = handle_id_element->intValue();
+ if (handle_id <= 0) {
+ message << "'handle-id' must be positive integer";
+ }
+ type = NetworkState::HA;
+ }
+ }
+ }
+ }
+
+ // No error occurred, so let's disable the service.
+ if (message.tellp() == 0) {
+ network_state_->enableService(type);
+
+ // Success.
+ return (config::createAnswer(CONTROL_RESULT_SUCCESS, "DHCP service successfully enabled"));
+ }
+
+ // Failure.
+ return (config::createAnswer(CONTROL_RESULT_ERROR, message.str()));
}
ConstElementPtr
CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
cfg_db->setAppendedParameters("universe=4");
cfg_db->createManagers();
+ // Reset counters related to connections as all managers have been recreated.
+ srv->getNetworkState()->resetInternalCounters();
} catch (const std::exception& ex) {
err << "Unable to open database: " << ex.what();
return (isc::config::createAnswer(1, err.str()));
ConstElementPtr args) {
std::ostringstream message;
int64_t max_period = 0;
+ int64_t handle_id = 0;
+
+ NetworkState::ControllerType type = NetworkState::COMMAND;
// Parse arguments to see if the 'max-period' parameter has been specified.
if (args) {
network_state_->delayedEnableAll(static_cast<unsigned>(max_period));
}
}
+ ConstElementPtr handle_id_element = args->get("handle-id");
+ // handle-id is optional.
+ if (handle_id_element) {
+ // It must be an integer, if specified.
+ if (handle_id_element->getType() != Element::integer) {
+ message << "'handle-id' argument must be a number";
+
+ } else {
+ // It must be positive integer.
+ handle_id = handle_id_element->intValue();
+ if (handle_id <= 0) {
+ message << "'handle-id' must be positive integer";
+ }
+ type = NetworkState::HA;
+ }
+ }
}
}
// No error occurred, so let's disable the service.
if (message.tellp() == 0) {
- network_state_->disableService(NetworkState::COMMAND);
+ network_state_->disableService(type);
message << "DHCPv6 service disabled";
if (max_period > 0) {
}
ConstElementPtr
-ControlledDhcpv6Srv::commandDhcpEnableHandler(const std::string&, ConstElementPtr) {
- network_state_->enableService(NetworkState::COMMAND);
- return (config::createAnswer(CONTROL_RESULT_SUCCESS, "DHCP service successfully enabled"));
+ControlledDhcpv6Srv::commandDhcpEnableHandler(const std::string&,
+ ConstElementPtr args) {
+ std::ostringstream message;
+ int64_t handle_id = 0;
+
+ NetworkState::ControllerType type = NetworkState::COMMAND;
+
+ // 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-enable' command must be a map";
+
+ } else {
+ ConstElementPtr handle_id_element = args->get("handle-id");
+ // handle-id is optional.
+ if (handle_id_element) {
+ // It must be an integer, if specified.
+ if (handle_id_element->getType() != Element::integer) {
+ message << "'handle-id' argument must be a number";
+
+ } else {
+ // It must be positive integer.
+ handle_id = handle_id_element->intValue();
+ if (handle_id <= 0) {
+ message << "'handle-id' must be positive integer";
+ }
+ type = NetworkState::HA;
+ }
+ }
+ }
+ }
+
+ // No error occurred, so let's disable the service.
+ if (message.tellp() == 0) {
+ network_state_->enableService(type);
+
+ // Success.
+ return (config::createAnswer(CONTROL_RESULT_SUCCESS, "DHCP service successfully enabled"));
+ }
+
+ // Failure.
+ return (config::createAnswer(CONTROL_RESULT_ERROR, message.str()));
}
ConstElementPtr
CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
cfg_db->setAppendedParameters("universe=6");
cfg_db->createManagers();
+ // Reset counters related to connections as all managers have been recreated.
+ srv->getNetworkState()->resetInternalCounters();
} catch (const std::exception& ex) {
err << "Unable to open database: " << ex.what();
return (isc::config::createAnswer(1, err.str()));
// This test verifies that it is possible to disable and then enable DHCPv4 service.
TEST_F(NetworkStateTest, disableEnableService4) {
NetworkState state(NetworkState::DHCPv4);
+
+ // Test that enable/disable command works
state.disableService(NetworkState::COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
state.enableService(NetworkState::COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that command does not use internal counter
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::COMMAND);
+ EXPECT_TRUE(state.isServiceEnabled());
+ state.enableService(NetworkState::COMMAND);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that enable/disable ha works
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that command does not use internal counter
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_TRUE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that enable/disable connection works
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that connection uses internal counter
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that a combination properly affect the state
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
}
// This test verifies that it is possible to disable and then enable DHCPv6 service.
TEST_F(NetworkStateTest, disableEnableService6) {
NetworkState state(NetworkState::DHCPv6);
+
+ // Test that enable/disable command works
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::COMMAND);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that command does not use internal counter
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::COMMAND);
+ EXPECT_TRUE(state.isServiceEnabled());
+ state.enableService(NetworkState::COMMAND);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that enable/disable ha works
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that command does not use internal counter
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_TRUE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that enable/disable connection works
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that connection uses internal counter
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
+
+ // Test that a combination properly affect the state
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
state.disableService(NetworkState::COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
state.enableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::CONNECTION);
+ EXPECT_TRUE(state.isServiceEnabled());
+}
+
+// This test verifies that resetInternalCounters works, so that internal counter
+// is reset after all managers are recreated.
+TEST_F(NetworkStateTest, resetInternalCounters) {
+ NetworkState state(NetworkState::DHCPv4);
+ state.disableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::HA);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.resetInternalCounters();
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::COMMAND);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.enableService(NetworkState::HA);
+ EXPECT_TRUE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.disableService(NetworkState::CONNECTION);
+ EXPECT_FALSE(state.isServiceEnabled());
+ state.resetInternalCounters();
EXPECT_TRUE(state.isServiceEnabled());
}
EXPECT_FALSE(state.isDelayedEnableAll());
}
-
} // end of anonymous namespace