summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/sphinx/arm/ctrl-channel.rst19
-rw-r--r--src/bin/dhcp4/ctrl_dhcp4_srv.cc42
-rw-r--r--src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc50
-rw-r--r--src/bin/dhcp6/ctrl_dhcp6_srv.cc42
-rw-r--r--src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc50
-rw-r--r--src/hooks/dhcp/high_availability/command_creator.cc10
-rw-r--r--src/hooks/dhcp/high_availability/command_creator.h12
-rw-r--r--src/hooks/dhcp/high_availability/ha_impl.cc59
-rw-r--r--src/hooks/dhcp/high_availability/ha_impl.h4
-rw-r--r--src/hooks/dhcp/high_availability/ha_service.cc25
-rw-r--r--src/hooks/dhcp/high_availability/ha_service.h15
-rw-r--r--src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc8
-rw-r--r--src/hooks/dhcp/high_availability/tests/command_creator_unittest.cc29
-rw-r--r--src/hooks/dhcp/high_availability/tests/ha_impl_unittest.cc14
-rw-r--r--src/hooks/dhcp/high_availability/tests/ha_mt_unittest.cc12
-rw-r--r--src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc106
-rw-r--r--src/lib/dhcpsrv/network_state.cc156
-rw-r--r--src/lib/dhcpsrv/network_state.h129
-rw-r--r--src/lib/dhcpsrv/tests/network_state_unittest.cc236
19 files changed, 562 insertions, 456 deletions
diff --git a/doc/sphinx/arm/ctrl-channel.rst b/doc/sphinx/arm/ctrl-channel.rst
index d1d1318431..66c8772d52 100644
--- a/doc/sphinx/arm/ctrl-channel.rst
+++ b/doc/sphinx/arm/ctrl-channel.rst
@@ -715,11 +715,11 @@ Since Kea 1.9.4, there is an additional ``origin`` parameter that specifies the
command source. A server administrator should typically omit this parameter
because the default value "user" indicates that the administrator sent the
command. This command can also be sent by the partner server running HA hooks
-library. In that case, the partner server sets the parameter to "ha-partner".
-This value is reserved for the communication between HA partners and should not
-be specified in the administrator's commands, as it may interfere with
-HA operation. The administrator should either omit this parameter or set it to
-"user".
+library. In that case, the partner server sets the parameter to a unique
+integer identifier of a HA service. The integer values are reserved for the
+communication between HA partners and should not be specified in the
+administrator's commands, as it may interfere with HA operation. The
+administrator should either omit this parameter or set it to "user".
::
@@ -743,10 +743,11 @@ Since Kea 1.9.4, there is an additional ``origin`` parameter that specifies the
command source. A server administrator should typically omit this parameter
because the default value "user" indicates that the administrator sent the
command. This command can also be sent by the partner server running the HA hook
-library. In that case, the partner server sets the parameter to "ha-partner".
-This value is reserved for the communication between HA partners and should not
-be specified in the administrator's commands, as it may interfere with
-HA operation. The administrator should either omit this parameter or set it to
+library. In that case, the partner server sets the parameter to a unique
+integer identifier of a HA service. The integer values are reserved for the
+communication between HA partners and should not be specified in the
+administrator's commands, as it may interfere with HA operation. The
+administrator should either omit this parameter or set it to
"user".
::
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
index e5a5e88217..972a3436a3 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
@@ -520,7 +520,7 @@ ControlledDhcpv4Srv::commandDhcpDisableHandler(const std::string&,
// If the args map does not contain 'origin' parameter, the default type
// will be used (user command).
- NetworkState::Origin type = NetworkState::Origin::USER_COMMAND;
+ auto type = NetworkState::USER_COMMAND;
// Parse arguments to see if the 'max-period' or 'origin' parameters have
// been specified.
@@ -548,14 +548,11 @@ ControlledDhcpv4Srv::commandDhcpDisableHandler(const std::string&,
ConstElementPtr origin_element = args->get("origin");
// The 'origin' parameter is optional.
if (origin_element) {
- // It must be a string, if specified.
- if (origin_element->getType() != Element::string) {
- message << "'origin' argument must be a string";
-
- } else {
+ switch (origin_element->getType()) {
+ case Element::string:
origin = origin_element->stringValue();
if (origin == "ha-partner") {
- type = NetworkState::Origin::HA_COMMAND;
+ type = NetworkState::HA_REMOTE_COMMAND;
} else if (origin != "user") {
if (origin.empty()) {
origin = "(empty string)";
@@ -563,6 +560,13 @@ ControlledDhcpv4Srv::commandDhcpDisableHandler(const std::string&,
message << "invalid value used for 'origin' parameter: "
<< origin;
}
+ break;
+ case Element::integer:
+ type = origin_element->intValue();
+ break;
+ default:
+ // It must be a string or a number, if specified.
+ message << "'origin' argument must be a string or a number";
}
}
}
@@ -598,7 +602,7 @@ ControlledDhcpv4Srv::commandDhcpEnableHandler(const std::string&,
// If the args map does not contain 'origin' parameter, the default type
// will be used (user command).
- NetworkState::Origin type = NetworkState::Origin::USER_COMMAND;
+ auto type = NetworkState::USER_COMMAND;
// Parse arguments to see if the 'origin' parameter has been specified.
if (args) {
@@ -610,14 +614,11 @@ ControlledDhcpv4Srv::commandDhcpEnableHandler(const std::string&,
ConstElementPtr origin_element = args->get("origin");
// The 'origin' parameter is optional.
if (origin_element) {
- // It must be a string, if specified.
- if (origin_element->getType() != Element::string) {
- message << "'origin' argument must be a string";
-
- } else {
+ switch (origin_element->getType()) {
+ case Element::string:
origin = origin_element->stringValue();
if (origin == "ha-partner") {
- type = NetworkState::Origin::HA_COMMAND;
+ type = NetworkState::HA_REMOTE_COMMAND;
} else if (origin != "user") {
if (origin.empty()) {
origin = "(empty string)";
@@ -625,6 +626,13 @@ ControlledDhcpv4Srv::commandDhcpEnableHandler(const std::string&,
message << "invalid value used for 'origin' parameter: "
<< origin;
}
+ break;
+ case Element::integer:
+ type = origin_element->intValue();
+ break;
+ default:
+ // It must be a string or a number, if specified.
+ message << "'origin' argument must be a string or a number";
}
}
}
@@ -948,7 +956,7 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
cfg_db->setAppendedParameters(params);
cfg_db->createManagers();
// Reset counters related to connections as all managers have been recreated.
- srv->getNetworkState()->reset(NetworkState::Origin::DB_CONNECTION);
+ srv->getNetworkState()->reset(NetworkState::DB_CONNECTION);
} catch (const std::exception& ex) {
err << "Unable to open database: " << ex.what();
@@ -1337,7 +1345,7 @@ ControlledDhcpv4Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
// Disable service until the connection is recovered.
if (db_reconnect_ctl->retriesLeft() == db_reconnect_ctl->maxRetries() &&
db_reconnect_ctl->alterServiceState()) {
- network_state_->disableService(NetworkState::Origin::DB_CONNECTION);
+ network_state_->disableService(NetworkState::DB_CONNECTION);
}
LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_LOST_CONNECTION);
@@ -1368,7 +1376,7 @@ ControlledDhcpv4Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
// Enable service after the connection is recovered.
if (db_reconnect_ctl->alterServiceState()) {
- network_state_->enableService(NetworkState::Origin::DB_CONNECTION);
+ network_state_->enableService(NetworkState::DB_CONNECTION);
}
LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_SUCCEEDED);
diff --git a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
index 963cfd12b2..2046ec92fd 100644
--- a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
+++ b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
@@ -1765,7 +1765,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, dhcpDisable) {
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
- server_->network_state_->enableService(NetworkState::Origin::USER_COMMAND);
+ server_->network_state_->enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
@@ -1785,7 +1785,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, dhcpDisable) {
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
- server_->network_state_->enableService(NetworkState::Origin::USER_COMMAND);
+ server_->network_state_->enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
@@ -1805,7 +1805,27 @@ TEST_F(CtrlChannelDhcpv4SrvTest, dhcpDisable) {
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
- server_->network_state_->enableService(NetworkState::Origin::HA_COMMAND);
+ server_->network_state_->enableService(NetworkState::HA_REMOTE_COMMAND);
+
+ EXPECT_TRUE(server_->network_state_->isServiceEnabled());
+
+ sendUnixCommand("{"
+ " \"command\": \"dhcp-disable\","
+ " \"arguments\": {"
+ " \"origin\": 1102"
+ " }"
+ "}", response);
+
+ // The response should be a valid JSON.
+ EXPECT_NO_THROW(rsp = Element::fromJSON(response));
+ ASSERT_TRUE(rsp);
+
+ cfg = parseAnswer(status, rsp);
+ EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
+
+ EXPECT_FALSE(server_->network_state_->isServiceEnabled());
+
+ server_->network_state_->enableService(NetworkState::HA_REMOTE_COMMAND+2);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
}
@@ -1894,7 +1914,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, dhcpEnable) {
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
- server_->network_state_->disableService(NetworkState::Origin::USER_COMMAND);
+ server_->network_state_->disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
@@ -1914,7 +1934,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, dhcpEnable) {
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
- server_->network_state_->disableService(NetworkState::Origin::HA_COMMAND);
+ server_->network_state_->disableService(NetworkState::HA_REMOTE_COMMAND);
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
@@ -1933,6 +1953,26 @@ TEST_F(CtrlChannelDhcpv4SrvTest, dhcpEnable) {
EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
+
+ server_->network_state_->disableService(NetworkState::HA_REMOTE_COMMAND+1);
+
+ EXPECT_FALSE(server_->network_state_->isServiceEnabled());
+
+ sendUnixCommand("{"
+ " \"command\": \"dhcp-enable\","
+ " \"arguments\": {"
+ " \"origin\": 1101"
+ " }"
+ "}", response);
+
+ // The response should be a valid JSON.
+ EXPECT_NO_THROW(rsp = Element::fromJSON(response));
+ ASSERT_TRUE(rsp);
+
+ 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
diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
index 433ae2e3bc..3e99d48fa5 100644
--- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc
+++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
@@ -522,7 +522,7 @@ ControlledDhcpv6Srv::commandDhcpDisableHandler(const std::string&,
// If the args map does not contain 'origin' parameter, the default type
// will be used (user command).
- NetworkState::Origin type = NetworkState::Origin::USER_COMMAND;
+ auto type = NetworkState::USER_COMMAND;
// Parse arguments to see if the 'max-period' or 'origin' parameters have
// been specified.
@@ -550,14 +550,11 @@ ControlledDhcpv6Srv::commandDhcpDisableHandler(const std::string&,
ConstElementPtr origin_element = args->get("origin");
// The 'origin' parameter is optional.
if (origin_element) {
- // It must be a string, if specified.
- if (origin_element->getType() != Element::string) {
- message << "'origin' argument must be a string";
-
- } else {
+ switch (origin_element->getType()) {
+ case Element::string:
origin = origin_element->stringValue();
if (origin == "ha-partner") {
- type = NetworkState::Origin::HA_COMMAND;
+ type = NetworkState::HA_REMOTE_COMMAND;
} else if (origin != "user") {
if (origin.empty()) {
origin = "(empty string)";
@@ -565,6 +562,13 @@ ControlledDhcpv6Srv::commandDhcpDisableHandler(const std::string&,
message << "invalid value used for 'origin' parameter: "
<< origin;
}
+ break;
+ case Element::integer:
+ type = origin_element->intValue();
+ break;
+ default:
+ // It must be a string or a number, if specified.
+ message << "'origin' argument must be a string or a number";
}
}
}
@@ -600,7 +604,7 @@ ControlledDhcpv6Srv::commandDhcpEnableHandler(const std::string&,
// If the args map does not contain 'origin' parameter, the default type
// will be used (user command).
- NetworkState::Origin type = NetworkState::Origin::USER_COMMAND;
+ auto type = NetworkState::USER_COMMAND;
// Parse arguments to see if the 'origin' parameter has been specified.
if (args) {
@@ -612,14 +616,11 @@ ControlledDhcpv6Srv::commandDhcpEnableHandler(const std::string&,
ConstElementPtr origin_element = args->get("origin");
// The 'origin' parameter is optional.
if (origin_element) {
- // It must be a string, if specified.
- if (origin_element->getType() != Element::string) {
- message << "'origin' argument must be a string";
-
- } else {
+ switch (origin_element->getType()) {
+ case Element::string:
origin = origin_element->stringValue();
if (origin == "ha-partner") {
- type = NetworkState::Origin::HA_COMMAND;
+ type = NetworkState::HA_REMOTE_COMMAND;
} else if (origin != "user") {
if (origin.empty()) {
origin = "(empty string)";
@@ -627,6 +628,13 @@ ControlledDhcpv6Srv::commandDhcpEnableHandler(const std::string&,
message << "invalid value used for 'origin' parameter: "
<< origin;
}
+ break;
+ case Element::integer:
+ type = origin_element->intValue();
+ break;
+ default:
+ // It must be a string or a number, if specified.
+ message << "'origin' argument must be a string or a number";
}
}
}
@@ -953,7 +961,7 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
cfg_db->setAppendedParameters(params);
cfg_db->createManagers();
// Reset counters related to connections as all managers have been recreated.
- srv->getNetworkState()->reset(NetworkState::Origin::DB_CONNECTION);
+ srv->getNetworkState()->reset(NetworkState::DB_CONNECTION);
} catch (const std::exception& ex) {
err << "Unable to open database: " << ex.what();
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
@@ -1356,7 +1364,7 @@ ControlledDhcpv6Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
// Disable service until the connection is recovered.
if (db_reconnect_ctl->retriesLeft() == db_reconnect_ctl->maxRetries() &&
db_reconnect_ctl->alterServiceState()) {
- network_state_->disableService(NetworkState::Origin::DB_CONNECTION);
+ network_state_->disableService(NetworkState::DB_CONNECTION);
}
LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_LOST_CONNECTION);
@@ -1387,7 +1395,7 @@ ControlledDhcpv6Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
// Enable service after the connection is recovered.
if (db_reconnect_ctl->alterServiceState()) {
- network_state_->enableService(NetworkState::Origin::DB_CONNECTION);
+ network_state_->enableService(NetworkState::DB_CONNECTION);
}
LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_SUCCEEDED);
diff --git a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
index 5baa867c7b..d467a249ff 100644
--- a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
@@ -1796,7 +1796,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, dhcpDisable) {
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
- server_->network_state_->enableService(NetworkState::Origin::USER_COMMAND);
+ server_->network_state_->enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
@@ -1816,7 +1816,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, dhcpDisable) {
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
- server_->network_state_->enableService(NetworkState::Origin::USER_COMMAND);
+ server_->network_state_->enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
@@ -1836,7 +1836,27 @@ TEST_F(CtrlChannelDhcpv6SrvTest, dhcpDisable) {
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
- server_->network_state_->enableService(NetworkState::Origin::HA_COMMAND);
+ server_->network_state_->enableService(NetworkState::HA_REMOTE_COMMAND);
+
+ EXPECT_TRUE(server_->network_state_->isServiceEnabled());
+
+ sendUnixCommand("{"
+ " \"command\": \"dhcp-disable\","
+ " \"arguments\": {"
+ " \"origin\": 1101"
+ " }"
+ "}", response);
+
+ // The response should be a valid JSON.
+ EXPECT_NO_THROW(rsp = Element::fromJSON(response));
+ ASSERT_TRUE(rsp);
+
+ cfg = parseAnswer(status, rsp);
+ EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
+
+ EXPECT_FALSE(server_->network_state_->isServiceEnabled());
+
+ server_->network_state_->enableService(NetworkState::HA_REMOTE_COMMAND+1);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
}
@@ -1925,7 +1945,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, dhcpEnable) {
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
- server_->network_state_->disableService(NetworkState::Origin::USER_COMMAND);
+ server_->network_state_->disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
@@ -1945,7 +1965,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, dhcpEnable) {
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
- server_->network_state_->disableService(NetworkState::Origin::HA_COMMAND);
+ server_->network_state_->disableService(NetworkState::HA_REMOTE_COMMAND);
EXPECT_FALSE(server_->network_state_->isServiceEnabled());
@@ -1964,6 +1984,26 @@ TEST_F(CtrlChannelDhcpv6SrvTest, dhcpEnable) {
EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
EXPECT_TRUE(server_->network_state_->isServiceEnabled());
+
+ server_->network_state_->disableService(NetworkState::HA_REMOTE_COMMAND+2);
+
+ EXPECT_FALSE(server_->network_state_->isServiceEnabled());
+
+ sendUnixCommand("{"
+ " \"command\": \"dhcp-enable\","
+ " \"arguments\": {"
+ " \"origin\": 1102"
+ " }"
+ "}", response);
+
+ // The response should be a valid JSON.
+ EXPECT_NO_THROW(rsp = Element::fromJSON(response));
+ ASSERT_TRUE(rsp);
+
+ 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
diff --git a/src/hooks/dhcp/high_availability/command_creator.cc b/src/hooks/dhcp/high_availability/command_creator.cc
index 75c4e41a7a..447bdc4069 100644
--- a/src/hooks/dhcp/high_availability/command_creator.cc
+++ b/src/hooks/dhcp/high_availability/command_creator.cc
@@ -38,11 +38,12 @@ unordered_set<string> CommandCreator::ha_commands6_ = {
};
ConstElementPtr
-CommandCreator::createDHCPDisable(const unsigned int max_period,
+CommandCreator::createDHCPDisable(const unsigned int origin,
+ const unsigned int max_period,
const HAServerType& server_type) {
ElementPtr args;
args = Element::createMap();
- args->set("origin", Element::create("ha-partner"));
+ args->set("origin", Element::create(origin));
// max-period is optional. A value of 0 means that it is not specified.
if (max_period > 0) {
args->set("max-period", Element::create(static_cast<long int>(max_period)));
@@ -53,10 +54,11 @@ CommandCreator::createDHCPDisable(const unsigned int max_period,
}
ConstElementPtr
-CommandCreator::createDHCPEnable(const HAServerType& server_type) {
+CommandCreator::createDHCPEnable(const unsigned int origin,
+ const HAServerType& server_type) {
ElementPtr args;
args = Element::createMap();
- args->set("origin", Element::create("ha-partner"));
+ args->set("origin", Element::create(origin));
ConstElementPtr command = config::createCommand("dhcp-enable", args);
insertService(command, server_type);
return (command);
diff --git a/src/hooks/dhcp/high_availability/command_creator.h b/src/hooks/dhcp/high_availability/command_creator.h
index 276f405df5..a9ec33b72a 100644
--- a/src/hooks/dhcp/high_availability/command_creator.h
+++ b/src/hooks/dhcp/high_availability/command_creator.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2023 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
@@ -24,22 +24,28 @@ public:
/// @brief Creates dhcp-disable command for DHCP server.
///
+ /// @param origin A numeric value of the origin created from the
+ /// @c HAService identifier.
/// @param max_period The max-period time the service can stay disabled
/// before automatically transitioning to enabled state.
/// @param server_type type of the DHCP server, i.e. v4 or v6.
///
/// @return Pointer to the JSON representation of the command.
static data::ConstElementPtr
- createDHCPDisable(const unsigned int max_period,
+ createDHCPDisable(const unsigned int origin,
+ const unsigned int max_period,
const HAServerType& server_type);
/// @brief Creates dhcp-enable command for DHCP server.
///
+ /// @param origin A numeric value of the origin created from the
+ /// @c HAService identifier.
/// @param server_type type of the DHCP server, i.e. v4 or v6.
///
/// @return Pointer to the JSON representation of the command.
static data::ConstElementPtr
- createDHCPEnable(const HAServerType& server_type);
+ createDHCPEnable(const unsigned int origin,
+ const HAServerType& server_type);
/// @brief Creates ha-reset command.
///
diff --git a/src/hooks/dhcp/high_availability/ha_impl.cc b/src/hooks/dhcp/high_availability/ha_impl.cc
index 9eee6f0250..410772fb5f 100644
--- a/src/hooks/dhcp/high_availability/ha_impl.cc
+++ b/src/hooks/dhcp/high_availability/ha_impl.cc
@@ -28,7 +28,7 @@ namespace isc {
namespace ha {
HAImpl::HAImpl()
- : config_() {
+ : config_(), services_(new HAServiceMapper()) {
}
void
@@ -40,19 +40,34 @@ void
HAImpl::startService(const IOServicePtr& io_service,
const NetworkStatePtr& network_state,
const HAServerType& server_type) {
- // Create the HA service and crank up the state machine.
- service_ = boost::make_shared<HAService>(io_service, network_state,
- config_->get(), server_type);
+ auto configs = config_->getAll();
+ for (auto id = 0; id < configs.size(); ++id) {
+ // Create the HA service and crank up the state machine.
+ auto service = boost::make_shared<HAService>(id, io_service, network_state,
+ configs[id], server_type);
+ for (auto peer_config : configs[id]->getAllServersConfig()) {
+ services_->map(peer_config.first, service);
+ }
+
+ /// @todo Running multiple HA services concurrently is not yet implemented.
+ /// The work is in progress. This break should be removed shortly, when we
+ /// finish up adding support for running multiple services.
+ break;
+ }
// Schedule a start of the services. This ensures we begin after
// the dust has settled and Kea MT mode has been firmly established.
- io_service->post([&]() { service_->startClientAndListener(); } );
+ io_service->post([&]() {
+ for (auto service : services_->getAll()) {
+ service->startClientAndListener();
+ }
+ });
}
HAImpl::~HAImpl() {
- if (service_) {
+ for (auto service : services_->getAll()) {
// Shut down the services explicitly, we need finer control
// than relying on destruction order.
- service_->stopClientAndListener();
+ service->stopClientAndListener();
}
}
@@ -97,7 +112,7 @@ HAImpl::buffer4Receive(hooks::CalloutHandle& callout_handle) {
}
// Check if we should process this query. If not, drop it.
- if (!service_->inScope(query4)) {
+ if (!services_->get()->inScope(query4)) {
LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_BUFFER4_RECEIVE_NOT_FOR_US)
.arg(query4->getLabel());
callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
@@ -153,7 +168,7 @@ HAImpl::leases4Committed(CalloutHandle& callout_handle) {
// servers. In those cases we simply return without parking the DHCP query.
// The response will be sent to the client immediately.
try {
- if (service_->asyncSendLeaseUpdates(query4, leases4, deleted_leases4, parking_lot) == 0) {
+ if (services_->get()->asyncSendLeaseUpdates(query4, leases4, deleted_leases4, parking_lot) == 0) {
// Dereference the parked packet. This releases our stake in it.
parking_lot->dereference(query4);
return;
@@ -211,7 +226,7 @@ HAImpl::buffer6Receive(hooks::CalloutHandle& callout_handle) {
}
// Check if we should process this query. If not, drop it.
- if (!service_->inScope(query6)) {
+ if (!services_->get()->inScope(query6)) {
LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_BUFFER6_RECEIVE_NOT_FOR_US)
.arg(query6->getLabel());
callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
@@ -267,7 +282,7 @@ HAImpl::leases6Committed(CalloutHandle& callout_handle) {
// servers. In those cases we simply return without parking the DHCP query.
// The response will be sent to the client immediately.
try {
- if (service_->asyncSendLeaseUpdates(query6, leases6, deleted_leases6, parking_lot) == 0) {
+ if (services_->get()->asyncSendLeaseUpdates(query6, leases6, deleted_leases6, parking_lot) == 0) {
// Dereference the parked packet. This releases our stake in it.
parking_lot->dereference(query6);
return;
@@ -309,7 +324,7 @@ HAImpl::commandProcessed(hooks::CalloutHandle& callout_handle) {
/// our sole relationship in a list.
auto ha_relationships = Element::createList();
auto ha_relationship = Element::createMap();
- ConstElementPtr ha_servers = service_->processStatusGet();
+ ConstElementPtr ha_servers = services_->get()->processStatusGet();
ha_relationship->set("ha-servers", ha_servers);
ha_relationship->set("ha-mode", Element::create(HAConfig::HAModeToString(config_->get()->getHAMode())));
ha_relationships->add(ha_relationship);
@@ -319,7 +334,7 @@ HAImpl::commandProcessed(hooks::CalloutHandle& callout_handle) {
void
HAImpl::heartbeatHandler(CalloutHandle& callout_handle) {
- ConstElementPtr response = service_->processHeartbeat();
+ ConstElementPtr response = services_->get()->processHeartbeat();
callout_handle.setArgument("response", response);
}
@@ -380,8 +395,8 @@ HAImpl::synchronizeHandler(hooks::CalloutHandle& callout_handle) {
}
// Command parsing was successful, so let's process the command.
- ConstElementPtr response = service_->processSynchronize(server_name->stringValue(),
- max_period_value);
+ ConstElementPtr response = services_->get()->processSynchronize(server_name->stringValue(),
+ max_period_value);
callout_handle.setArgument("response", response);
}
@@ -438,13 +453,13 @@ HAImpl::scopesHandler(hooks::CalloutHandle& callout_handle) {
}
// Command parsing was successful, so let's process the command.
- ConstElementPtr response = service_->processScopes(scopes_vector);
+ ConstElementPtr response = services_->get()->processScopes(scopes_vector);
callout_handle.setArgument("response", response);
}
void
HAImpl::continueHandler(hooks::CalloutHandle& callout_handle) {
- ConstElementPtr response = service_->processContinue();
+ ConstElementPtr response = services_->get()->processContinue();
callout_handle.setArgument("response", response);
}
@@ -467,31 +482,31 @@ HAImpl::maintenanceNotifyHandler(hooks::CalloutHandle& callout_handle) {
isc_throw(BadValue, "'cancel' must be a boolean in the 'ha-maintenance-notify' command");
}
- ConstElementPtr response = service_->processMaintenanceNotify(cancel_op->boolValue());
+ ConstElementPtr response = services_->get()->processMaintenanceNotify(cancel_op->boolValue());
callout_handle.setArgument("response", response);
}
void
HAImpl::maintenanceStartHandler(hooks::CalloutHandle& callout_handle) {
- ConstElementPtr response = service_->processMaintenanceStart();
+ ConstElementPtr response = services_->get()->processMaintenanceStart();
callout_handle.setArgument("response", response);
}
void
HAImpl::maintenanceCancelHandler(hooks::CalloutHandle& callout_handle) {
- ConstElementPtr response = service_->processMaintenanceCancel();
+ ConstElementPtr response = services_->get()->processMaintenanceCancel();
callout_handle.setArgument("response", response);
}
void
HAImpl::haResetHandler(hooks::CalloutHandle& callout_handle) {
- ConstElementPtr response = service_->processHAReset();
+ ConstElementPtr response = services_->get()->processHAReset();
callout_handle.setArgument("response", response);
}
void
HAImpl::syncCompleteNotifyHandler(hooks::CalloutHandle& callout_handle) {
- ConstElementPtr response = service_->processSyncCompleteNotify();
+ ConstElementPtr response = services_->get()->processSyncCompleteNotify();
callout_handle.setArgument("response", response);
}
diff --git a/src/hooks/dhcp/high_availability/ha_impl.h b/src/hooks/dhcp/high_availability/ha_impl.h
index b5e96ec49a..cb5bcf7882 100644
--- a/src/hooks/dhcp/high_availability/ha_impl.h
+++ b/src/hooks/dhcp/high_availability/ha_impl.h
@@ -183,8 +183,8 @@ protected:
/// @brief Holds parsed configuration.
HAConfigMapperPtr config_;
- /// @brief Pointer to the high availability service (state machine).
- HAServicePtr service_;
+ /// @brief Pointer to the high availability services (state machines).
+ HAServiceMapperPtr services_;
};
diff --git a/src/hooks/dhcp/high_availability/ha_service.cc b/src/hooks/dhcp/high_availability/ha_service.cc
index e6abe0dc19..9dc44a37b5 100644
--- a/src/hooks/dhcp/high_availability/ha_service.cc
+++ b/src/hooks/dhcp/high_availability/ha_service.cc
@@ -71,9 +71,10 @@ const int HAService::HA_MAINTENANCE_CANCEL_EVT;
const int HAService::HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED;
const int HAService::HA_SYNCED_PARTNER_UNAVAILABLE_EVT;
-HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& network_state,
- const HAConfigPtr& config, const HAServerType& server_type)
- : io_service_(io_service), network_state_(network_state), config_(config),
+HAService::HAService(const unsigned int id, const IOServicePtr& io_service,
+ const NetworkStatePtr& network_state, const HAConfigPtr& config,
+ const HAServerType& server_type)
+ : id_(id), io_service_(io_service), network_state_(network_state), config_(config),
server_type_(server_type), client_(), listener_(), communication_state_(),
query_filter_(config), mutex_(), pending_requests_(),
lease_update_backlog_(config->getDelayedUpdatesLimit()),
@@ -86,7 +87,7 @@ HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& netw
communication_state_.reset(new CommunicationState6(io_service_, config));
}
- network_state_->reset(NetworkState::Origin::HA_COMMAND);
+ network_state_->reset(NetworkState::HA_LOCAL_COMMAND+id_);
startModel(HA_WAITING_ST);
@@ -144,7 +145,7 @@ HAService::~HAService() {
// Stop client and/or listener.
stopClientAndListener();
- network_state_->reset(NetworkState::Origin::HA_COMMAND);
+ network_state_->reset(NetworkState::HA_LOCAL_COMMAND+id_);
}
void
@@ -1066,7 +1067,7 @@ HAService::adjustNetworkState() {
LOG_INFO(ha_logger, HA_LOCAL_DHCP_DISABLE)
.arg(config_->getThisServerName())
.arg(current_state_name);
- network_state_->disableService(NetworkState::Origin::HA_COMMAND);
+ network_state_->disableService(NetworkState::HA_LOCAL_COMMAND+id_);
} else if (should_enable && !network_state_->isServiceEnabled()) {
std::string current_state_name = getStateLabel(getCurrState());
@@ -1074,7 +1075,7 @@ HAService::adjustNetworkState() {
LOG_INFO(ha_logger, HA_LOCAL_DHCP_ENABLE)
.arg(config_->getThisServerName())
.arg(current_state_name);
- network_state_->enableService(NetworkState::Origin::HA_COMMAND);
+ network_state_->enableService(NetworkState::HA_LOCAL_COMMAND+id_);
}
}
@@ -1854,7 +1855,8 @@ HAService::asyncDisableDHCPService(HttpClient& http_client,
HostHttpHeader(remote_config->getUrl().getStrippedHostname()));
remote_config->addBasicAuthHttpHeader(request);
- request->setBodyAsJson(CommandCreator::createDHCPDisable(max_period,
+ request->setBodyAsJson(CommandCreator::createDHCPDisable(NetworkState::HA_REMOTE_COMMAND+id_,
+ max_period,
server_type_));
request->finalize();
@@ -1932,7 +1934,8 @@ HAService::asyncEnableDHCPService(HttpClient& http_client,
(HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(),
HostHttpHeader(remote_config->getUrl().getStrippedHostname()));
remote_config->addBasicAuthHttpHeader(request);
- request->setBodyAsJson(CommandCreator::createDHCPEnable(server_type_));
+ request->setBodyAsJson(CommandCreator::createDHCPEnable(NetworkState::HA_REMOTE_COMMAND+id_,
+ server_type_));
request->finalize();
// Response object should also be created because the HTTP client needs
@@ -2000,12 +2003,12 @@ HAService::asyncEnableDHCPService(HttpClient& http_client,
void
HAService::localDisableDHCPService() {
- network_state_->disableService(NetworkState::Origin::HA_COMMAND);
+ network_state_->disableService(NetworkState::HA_LOCAL_COMMAND+id_);
}
void
HAService::localEnableDHCPService() {
- network_state_->enableService(NetworkState::Origin::HA_COMMAND);
+ network_state_->enableService(NetworkState::HA_LOCAL_COMMAND+id_);
}
void
diff --git a/src/hooks/dhcp/high_availability/ha_service.h b/src/hooks/dhcp/high_availability/ha_service.h
index 80ecf7760c..fa6c5d49eb 100644
--- a/src/hooks/dhcp/high_availability/ha_service.h
+++ b/src/hooks/dhcp/high_availability/ha_service.h
@@ -35,6 +35,14 @@
namespace isc {
namespace ha {
+class HAService;
+
+/// @brief Type of an object mapping @c HAService to relationships.
+typedef HARelationshipMapper<HAService> HAServiceMapper;
+
+/// @brief Pointer to an object mapping @c HAService to relationships.
+typedef boost::shared_ptr<HAServiceMapper> HAServiceMapperPtr;
+
/// @brief High availability service.
///
/// This class derives from the @c util::StateModel and implements a
@@ -98,12 +106,14 @@ public:
/// state model in waiting state. Creates and starts the client and the
/// listener (if one).
///
+ /// @param id Unique @c HAService id.
/// @param io_service Pointer to the IO service used by the DHCP server.
/// @param config Parsed HA hook library configuration.
/// @param network_state Object holding state of the DHCP service
/// (enabled/disabled).
/// @param server_type Server type, i.e. DHCPv4 or DHCPv6 server.
- HAService(const asiolink::IOServicePtr& io_service,
+ HAService(const unsigned int id,
+ const asiolink::IOServicePtr& io_service,
const dhcp::NetworkStatePtr& network_state,
const HAConfigPtr& config,
const HAServerType& server_type = HAServerType::DHCPv4);
@@ -1153,6 +1163,9 @@ protected:
/// @param tcp_native_fd socket descriptor to register
void clientCloseHandler(int tcp_native_fd);
+ /// @brief Unique service id.
+ unsigned int id_;
+
/// @brief Pointer to the IO service object shared between this hooks
/// library and the DHCP server.
asiolink::IOServicePtr io_service_;
diff --git a/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc b/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc
index 1c91e1c959..36df83e94d 100644
--- a/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc
+++ b/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc
@@ -373,7 +373,7 @@ TEST_F(CloseHATest, close4) {
// Check that the disabled state is reset on dhcp4_srv_configured.
ASSERT_TRUE(network_state->isServiceEnabled());
- network_state->disableService(NetworkState::Origin::HA_COMMAND);
+ network_state->disableService(NetworkState::HA_LOCAL_COMMAND);
ASSERT_FALSE(network_state->isServiceEnabled());
// Start HA service.
@@ -508,7 +508,7 @@ TEST_F(CloseHATest, close4Backup) {
// It is first reset by the constructor and then adjusted by running the
// state model.
ASSERT_TRUE(network_state->isServiceEnabled());
- network_state->disableService(NetworkState::Origin::HA_COMMAND);
+ network_state->disableService(NetworkState::HA_LOCAL_COMMAND);
ASSERT_FALSE(network_state->isServiceEnabled());
// Start HA service.
@@ -612,7 +612,7 @@ TEST_F(CloseHATest, close6) {
// Check that the disabled state is reset on dhcp6_srv_configured.
ASSERT_TRUE(network_state->isServiceEnabled());
- network_state->disableService(NetworkState::Origin::HA_COMMAND);
+ network_state->disableService(NetworkState::HA_LOCAL_COMMAND);
ASSERT_FALSE(network_state->isServiceEnabled());
// Start HA service.
@@ -747,7 +747,7 @@ TEST_F(CloseHATest, close6Backup) {
// It is first reset by the constructor and then adjusted by running the
// state model.
ASSERT_TRUE(network_state->isServiceEnabled());
- network_state->disableService(NetworkState::Origin::HA_COMMAND);
+ network_state->disableService(NetworkState::HA_LOCAL_COMMAND);
ASSERT_FALSE(network_state->isServiceEnabled());
// Start HA service.
diff --git a/src/hooks/dhcp/high_availability/tests/command_creator_unittest.cc b/src/hooks/dhcp/high_availability/tests/command_creator_unittest.cc
index 8966b4cb9c..d2bf2f4afe 100644
--- a/src/hooks/dhcp/high_availability/tests/command_creator_unittest.cc
+++ b/src/hooks/dhcp/high_availability/tests/command_creator_unittest.cc
@@ -14,6 +14,7 @@
#include <exceptions/exceptions.h>
#include <dhcp/hwaddr.h>
#include <dhcpsrv/lease.h>
+#include <dhcpsrv/network_state.h>
#include <boost/pointer_cast.hpp>
#include <gtest/gtest.h>
#include <vector>
@@ -150,7 +151,8 @@ testCommandBasics(const ConstElementPtr& command,
// This test verifies that the dhcp-disable command is correct.
TEST(CommandCreatorTest, createDHCPDisable4) {
// Create command with max-period value set to 20.
- ConstElementPtr command = CommandCreator::createDHCPDisable(20, HAServerType::DHCPv4);
+ ConstElementPtr command = CommandCreator::createDHCPDisable(NetworkState::HA_REMOTE_COMMAND+1, 20,
+ HAServerType::DHCPv4);
ConstElementPtr arguments;
ASSERT_NO_FATAL_FAILURE(testCommandBasics(command, "dhcp-disable", "dhcp4",
arguments));
@@ -161,28 +163,30 @@ TEST(CommandCreatorTest, createDHCPDisable4) {
EXPECT_EQ(20, max_period->intValue());
ConstElementPtr origin = arguments->get("origin");
ASSERT_TRUE(origin);
- ASSERT_EQ("ha-partner", origin->stringValue());
+ ASSERT_EQ(NetworkState::HA_REMOTE_COMMAND+1, origin->intValue());
// Repeat the test but this time the max-period is not specified.
- command = CommandCreator::createDHCPDisable(0, HAServerType::DHCPv4);
+ command = CommandCreator::createDHCPDisable(NetworkState::HA_REMOTE_COMMAND+1, 0,
+ HAServerType::DHCPv4);
ASSERT_NO_FATAL_FAILURE(testCommandBasics(command, "dhcp-disable", "dhcp4",
arguments));
ASSERT_EQ(1, arguments->size());
origin = arguments->get("origin");
ASSERT_TRUE(origin);
- ASSERT_EQ("ha-partner", origin->stringValue());
+ ASSERT_EQ(NetworkState::HA_REMOTE_COMMAND+1, origin->intValue());
}
// This test verifies that the dhcp-enable command is correct.
TEST(CommandCreatorTest, createDHCPEnable4) {
ConstElementPtr arguments;
- ConstElementPtr command = CommandCreator::createDHCPEnable(HAServerType::DHCPv4);
+ ConstElementPtr command = CommandCreator::createDHCPEnable(NetworkState::HA_REMOTE_COMMAND+1,
+ HAServerType::DHCPv4);
ASSERT_NO_FATAL_FAILURE(testCommandBasics(command, "dhcp-enable", "dhcp4",
arguments));
ASSERT_EQ(1, arguments->size());
ConstElementPtr origin = arguments->get("origin");
ASSERT_TRUE(origin);
- ASSERT_EQ("ha-partner", origin->stringValue());
+ ASSERT_EQ(NetworkState::HA_REMOTE_COMMAND+1, origin->intValue());
}
// This test verifies that the ha-reset command sent to DHCPv4 server is correct.
@@ -283,7 +287,8 @@ TEST(CommandCreatorTest, createLease4GetPageZeroLimit) {
// correct.
TEST(CommandCreatorTest, createDHCPDisable6) {
// Create command with max-period value set to 20.
- ConstElementPtr command = CommandCreator::createDHCPDisable(20, HAServerType::DHCPv6);
+ ConstElementPtr command = CommandCreator::createDHCPDisable(NetworkState::HA_REMOTE_COMMAND+2, 20,
+ HAServerType::DHCPv6);
ConstElementPtr arguments;
ASSERT_NO_FATAL_FAILURE(testCommandBasics(command, "dhcp-disable", "dhcp6",
arguments));
@@ -294,29 +299,29 @@ TEST(CommandCreatorTest, createDHCPDisable6) {
EXPECT_EQ(20, max_period->intValue());
ConstElementPtr origin = arguments->get("origin");
ASSERT_TRUE(origin);
- ASSERT_EQ("ha-partner", origin->stringValue());
+ ASSERT_EQ(NetworkState::HA_REMOTE_COMMAND+2, origin->intValue());
// Repeat the test but this time the max-period is not specified.
- command = CommandCreator::createDHCPDisable(0, HAServerType::DHCPv6);
+ command = CommandCreator::createDHCPDisable(NetworkState::HA_REMOTE_COMMAND+2, 0, HAServerType::DHCPv6);
ASSERT_NO_FATAL_FAILURE(testCommandBasics(command, "dhcp-disable", "dhcp6",
arguments));
ASSERT_EQ(1, arguments->size());
origin = arguments->get("origin");
ASSERT_TRUE(origin);
- ASSERT_EQ("ha-partner", origin->stringValue());
+ ASSERT_EQ(NetworkState::HA_REMOTE_COMMAND+2, origin->intValue());
}
// This test verifies that the dhcp-enable command (DHCPv6 case) is
// correct.
TEST(CommandCreatorTest, createDHCPEnable6) {
ConstElementPtr arguments;
- ConstElementPtr command = CommandCreator::createDHCPEnable(HAServerType::DHCPv6);
+ ConstElementPtr command = CommandCreator::createDHCPEnable(NetworkState::HA_REMOTE_COMMAND+2, HAServerType::DHCPv6);
ASSERT_NO_FATAL_FAILURE(testCommandBasics(command, "dhcp-enable", "dhcp6",
arguments));
ASSERT_EQ(1, arguments->size());
ConstElementPtr origin = arguments->get("origin");
ASSERT_TRUE(origin);
- ASSERT_EQ("ha-partner", origin->stringValue());
+ ASSERT_EQ(NetworkState::HA_REMOTE_COMMAND+2, origin->intValue());
}
// This test verifies that the ha-reset command sent to DHCPv6 server is correct.
diff --git a/src/hooks/dhcp/high_availability/tests/ha_impl_unittest.cc b/src/hooks/dhcp/high_availability/tests/ha_impl_unittest.cc
index cb6e71522a..c2b5d5f0d1 100644
--- a/src/hooks/dhcp/high_availability/tests/ha_impl_unittest.cc
+++ b/src/hooks/dhcp/high_availability/tests/ha_impl_unittest.cc
@@ -61,7 +61,7 @@ class TestHAImpl : public HAImpl {
public:
using HAImpl::config_;
- using HAImpl::service_;
+ using HAImpl::services_;
};
/// @brief Test fixture class for @c HAImpl.
@@ -115,8 +115,8 @@ TEST_F(HAImplTest, startService) {
// Make sure that the HA service has been created for the requested
// server type.
- ASSERT_TRUE(ha_impl.service_);
- EXPECT_EQ(HAServerType::DHCPv4, ha_impl.service_->getServerType());
+ ASSERT_TRUE(ha_impl.services_);
+ EXPECT_EQ(HAServerType::DHCPv4, ha_impl.services_->get()->getServerType());
}
// Tests that HAService object is created for DHCPv6 service.
@@ -134,8 +134,8 @@ TEST_F(HAImplTest, startService6) {
// Make sure that the HA service has been created for the requested
// server type.
- ASSERT_TRUE(ha_impl.service_);
- EXPECT_EQ(HAServerType::DHCPv6, ha_impl.service_->getServerType());
+ ASSERT_TRUE(ha_impl.services_);
+ EXPECT_EQ(HAServerType::DHCPv6, ha_impl.services_->get()->getServerType());
}
// Tests for buffer4_receive callout implementation.
@@ -155,7 +155,7 @@ TEST_F(HAImplTest, buffer4Receive) {
// Initially the HA service is in the waiting state and serves no scopes.
// We need to explicitly enable the scope to be served.
- ha_impl.service_->serveDefaultScopes();
+ ha_impl.services_->get()->serveDefaultScopes();
// Create callout handle to be used for passing arguments to the
// callout.
@@ -263,7 +263,7 @@ TEST_F(HAImplTest, buffer6Receive) {
// Initially the HA service is in the waiting state and serves no scopes.
// We need to explicitly enable the scope to be served.
- ha_impl.service_->serveDefaultScopes();
+ ha_impl.services_->get()->serveDefaultScopes();
// Create callout handle to be used for passing arguments to the
// callout.
diff --git a/src/hooks/dhcp/high_availability/tests/ha_mt_unittest.cc b/src/hooks/dhcp/high_availability/tests/ha_mt_unittest.cc
index f6076a61c7..2749f92556 100644
--- a/src/hooks/dhcp/high_availability/tests/ha_mt_unittest.cc
+++ b/src/hooks/dhcp/high_availability/tests/ha_mt_unittest.cc
@@ -36,16 +36,18 @@ public:
/// @brief Constructor.
///
+ /// @param id Unique service id.
/// @param io_service Pointer to the IO service used by the DHCP server.
/// @param network_state Object holding state of the DHCP service
/// (enabled/disabled).
/// @param config Parsed HA hook library configuration.
/// @param server_type Server type, i.e. DHCPv4 or DHCPv6 server.
- TestHAService(const IOServicePtr& io_service,
+ TestHAService(const unsigned int id,
+ const IOServicePtr& io_service,
const NetworkStatePtr& network_state,
const HAConfigPtr& config,
const HAServerType& server_type = HAServerType::DHCPv4)
- : HAService(io_service, network_state, config, server_type) {
+ : HAService(id, io_service, network_state, config, server_type) {
}
/// @brief Test version of the @c HAService::runModel.
@@ -192,7 +194,7 @@ TEST_F(HAMtServiceTest, multiThreadingBasics) {
// Instantiate the service.
TestHAServicePtr service;
- ASSERT_NO_THROW_LOG(service.reset(new TestHAService(io_service_, network_state_,
+ ASSERT_NO_THROW_LOG(service.reset(new TestHAService(1, io_service_, network_state_,
ha_config->get())));
// Multi-threading should be enabled.
ASSERT_TRUE(ha_config->get()->getEnableMultiThreading());
@@ -312,7 +314,7 @@ TEST_F(HAMtServiceTest, multiThreadingTls) {
// Instantiate the service.
TestHAServicePtr service;
- ASSERT_NO_THROW_LOG(service.reset(new TestHAService(io_service_, network_state_,
+ ASSERT_NO_THROW_LOG(service.reset(new TestHAService(1, io_service_, network_state_,
ha_config->get())));
// Multi-threading should be enabled.
ASSERT_TRUE(ha_config->get()->getEnableMultiThreading());
@@ -505,7 +507,7 @@ TEST_F(HAMtServiceTest, multiThreadingConfigStartup) {
// Instantiate the service.
TestHAServicePtr service;
- ASSERT_NO_THROW_LOG(service.reset(new TestHAService(io_service_, network_state_,
+ ASSERT_NO_THROW_LOG(service.reset(new TestHAService(1, io_service_, network_state_,
ha_config->get())));
ASSERT_NO_THROW_LOG(service->startClientAndListener());
diff --git a/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc b/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc
index 866f30a297..5280aa945a 100644
--- a/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc
+++ b/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc
@@ -135,16 +135,18 @@ public:
/// @brief Constructor.
///
+ /// @parma id Unique service identifier.
/// @param io_service Pointer to the IO service used by the DHCP server.
/// @param network_state Object holding state of the DHCP service
/// (enabled/disabled).
/// @param config Parsed HA hook library configuration.
/// @param server_type Server type, i.e. DHCPv4 or DHCPv6 server.
- TestHAService(const IOServicePtr& io_service,
+ TestHAService(const unsigned int id,
+ const IOServicePtr& io_service,
const NetworkStatePtr& network_state,
const HAConfigPtr& config,
const HAServerType& server_type = HAServerType::DHCPv4)
- : HAService(io_service, network_state, config, server_type) {
+ : HAService(id, io_service, network_state, config, server_type) {
}
/// @brief Test version of the @c HAService::runModel.
@@ -650,7 +652,7 @@ public:
const HAServerType& server_type = HAServerType::DHCPv4) {
ASSERT_FALSE(config->getEnableMultiThreading());
- ASSERT_NO_THROW_LOG(service_.reset(new TestHAService(io_service_, state,
+ ASSERT_NO_THROW_LOG(service_.reset(new TestHAService(1, io_service_, state,
config, server_type)));
ASSERT_TRUE(service_->client_);
ASSERT_FALSE(service_->client_->getThreadIOService());
@@ -1054,7 +1056,7 @@ public:
state->modifyPokeTime(-30);
// Create the service and replace the default communication state object.
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
service.communication_state_ = state;
EXPECT_FALSE(state->isPoked());
@@ -2058,7 +2060,7 @@ public:
listener3_->start();
});
- HAService service(io_service_, network_state_, config_storage);
+ HAService service(1, io_service_, network_state_, config_storage);
// The tested function is synchronous, so we need to run server side IO service
// in bakckground to not block the main thread.
@@ -2107,7 +2109,7 @@ public:
listener3_->start();
});
- HAService service(io_service_, network_state_, config_storage,
+ HAService service(1, io_service_, network_state_, config_storage,
HAServerType::DHCPv6);
// The tested function is synchronous, so we need to run server side IO service
@@ -2176,7 +2178,7 @@ TEST_F(HAServiceTest, loadBalancingScopeSelection) {
// Create HA configuration for load balancing.
HAConfigPtr config_storage = createValidConfiguration();
// ... and HA service using this configuration.
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
service.verboseTransition(HA_LOAD_BALANCING_ST);
service.runModel(HAService::NOP_EVT);
@@ -2218,7 +2220,7 @@ TEST_F(HAServiceTest, hotStandbyScopeSelectionThisPrimary) {
config_storage->getPeerConfig("server2")->setRole("standby");
// ... and HA service using this configuration.
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
service.verboseTransition(HA_HOT_STANDBY_ST);
service.runModel(HAService::NOP_EVT);
@@ -2268,7 +2270,7 @@ TEST_F(HAServiceTest, hotStandbyScopeSelectionThisStandby) {
config_storage->setThisServerName("server2");
// ... and HA service using this configuration.
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Check the reported info about servers.
ConstElementPtr ha_servers = service.processStatusGet();
@@ -2738,7 +2740,7 @@ TEST_F(HAServiceTest, processHeartbeat) {
HAConfigMapperPtr config_storage;
ASSERT_NO_THROW(config_storage = HAConfigParser::parse(Element::fromJSON(config_text)));
- TestHAService service(io_service_, network_state_, config_storage->get());
+ TestHAService service(1, io_service_, network_state_, config_storage->get());
service.query_filter_.serveDefaultScopes();
int unsent_updates = 6;
@@ -2812,7 +2814,7 @@ TEST_F(HAServiceTest, recurringHeartbeatDelay) {
NakedCommunicationState4Ptr state(new NakedCommunicationState4(io_service_,
config_storage));
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
service.communication_state_ = state;
// Let's explicitly transition the state machine to the load balancing state
@@ -2985,7 +2987,7 @@ TEST_F(HAServiceTest, asyncSyncLeases4) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Setting the heartbeat delay to 0 disables the recurring heartbeat.
// We just want to synchronize leases and not send the heartbeat.
config_storage->setHeartbeatDelay(0);
@@ -3114,7 +3116,7 @@ TEST_F(HAServiceTest, asyncSyncLeases4Authorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Setting the heartbeat delay to 0 disables the recurring heartbeat.
// We just want to synchronize leases and not send the heartbeat.
config_storage->setHeartbeatDelay(0);
@@ -3202,7 +3204,7 @@ TEST_F(HAServiceTest, asyncSyncLeases4WrongAnswer) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Start fetching leases asynchronously.
ASSERT_NO_THROW(service.asyncSyncLeases());
@@ -3220,7 +3222,7 @@ TEST_F(HAServiceTest, asyncSyncLeases4ServerOffline) {
// We just want to synchronize leases and not send the heartbeat.
config_storage->setHeartbeatDelay(0);
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Start fetching leases asynchronously.
ASSERT_NO_THROW(service.asyncSyncLeases());
@@ -3257,7 +3259,7 @@ TEST_F(HAServiceTest, asyncSyncLeases4ServerUnauthorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Start fetching leases asynchronously.
ASSERT_NO_THROW(service.asyncSyncLeases());
@@ -3326,7 +3328,7 @@ TEST_F(HAServiceTest, asyncSyncLeases6) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage,
+ TestHAService service(1, io_service_, network_state_, config_storage,
HAServerType::DHCPv6);
// Setting the heartbeat delay to 0 disables the recurring heartbeat.
// We just want to synchronize leases and not send the heartbeat.
@@ -3456,7 +3458,7 @@ TEST_F(HAServiceTest, asyncSyncLeases6Authorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage,
+ TestHAService service(1, io_service_, network_state_, config_storage,
HAServerType::DHCPv6);
// Setting the heartbeat delay to 0 disables the recurring heartbeat.
// We just want to synchronize leases and not send the heartbeat.
@@ -3545,7 +3547,7 @@ TEST_F(HAServiceTest, asyncSyncLeases6WrongAnswer) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage,
+ TestHAService service(1, io_service_, network_state_, config_storage,
HAServerType::DHCPv6);
// Start fetching leases asynchronously.
@@ -3564,7 +3566,7 @@ TEST_F(HAServiceTest, asyncSyncLeases6ServerOffline) {
// We just want to synchronize leases and not send the heartbeat.
config_storage->setHeartbeatDelay(0);
- TestHAService service(io_service_, network_state_, config_storage,
+ TestHAService service(1, io_service_, network_state_, config_storage,
HAServerType::DHCPv6);
// Start fetching leases asynchronously.
@@ -3602,7 +3604,7 @@ TEST_F(HAServiceTest, asyncSyncLeases6Unauthorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage,
+ TestHAService service(1, io_service_, network_state_, config_storage,
HAServerType::DHCPv6);
// Start fetching leases asynchronously.
@@ -4022,7 +4024,7 @@ TEST_F(HAServiceTest, asyncDisableDHCPService4) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-disable command with max-period of 10 seconds.
// When the transaction is finished, the IO service gets stopped.
@@ -4068,7 +4070,7 @@ TEST_F(HAServiceTest, asyncDisableDHCPService4Authorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-disable command with max-period of 10 seconds.
// When the transaction is finished, the IO service gets stopped.
@@ -4097,7 +4099,7 @@ TEST_F(HAServiceTest, asyncDisableDHCPService4ServerOffline) {
// Create HA configuration.
HAConfigPtr config_storage = createValidConfiguration();
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-disable command with max-period of 10 seconds.
// When the transaction is finished, the IO service gets stopped.
@@ -4132,7 +4134,7 @@ TEST_F(HAServiceTest, asyncDisableDHCPService4ControlResultError) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-disable command with max-period of 10 seconds.
// When the transaction is finished, the IO service gets stopped.
@@ -4166,7 +4168,7 @@ TEST_F(HAServiceTest, asyncDisableDHCPService4ControlResultUnauthorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-disable command with max-period of 10 seconds.
// When the transaction is finished, the IO service gets stopped.
@@ -4196,7 +4198,7 @@ TEST_F(HAServiceTest, asyncEnableDHCPService4) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-enable command. When the transaction is finished,
// the IO service gets stopped.
@@ -4241,7 +4243,7 @@ TEST_F(HAServiceTest, asyncEnableDHCPService4Authorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-enable command. When the transaction is finished,
// the IO service gets stopped.
@@ -4269,7 +4271,7 @@ TEST_F(HAServiceTest, asyncEnableDHCPService4ServerOffline) {
// Create HA configuration.
HAConfigPtr config_storage = createValidConfiguration();
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-enable command. When the transaction is finished,
// the IO service gets stopped.
@@ -4304,7 +4306,7 @@ TEST_F(HAServiceTest, asyncEnableDHCPService4ControlResultError) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-enable command. When the transaction is finished,
// the IO service gets stopped.
@@ -4338,7 +4340,7 @@ TEST_F(HAServiceTest, asyncEnableDHCPService4ControlResultUnauthorized) {
listener3_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Send dhcp-enable command. When the transaction is finished,
// the IO service gets stopped.
@@ -4361,7 +4363,7 @@ TEST_F(HAServiceTest, processScopes) {
HAConfigPtr config_storage = createValidConfiguration();
// Create HA service using this configuration.
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Enable "server1" and "server2" scopes.
ConstElementPtr rsp;
@@ -4409,7 +4411,7 @@ TEST_F(HAServiceTest, processContinue) {
ASSERT_NO_THROW(config_storage->getStateMachineConfig()->
getStateConfig(HA_WAITING_ST)->setPausing("always"));
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Pause the state machine.
EXPECT_NO_THROW(service.transition(HA_WAITING_ST, HAService::NOP_EVT));
@@ -4462,7 +4464,7 @@ TEST_F(HAServiceTest, processMaintenanceNotify) {
HA_HOT_STANDBY_ST,
};
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Test transition from the states for which it is allowed.
for (auto state : valid_states) {
@@ -4528,7 +4530,7 @@ TEST_F(HAServiceTest, processMaintenanceStartSuccess) {
listener2_->start();
});
- HAService service(io_service_, network_state_, config_storage);
+ HAService service(1, io_service_, network_state_, config_storage);
// The tested function is synchronous, so we need to run server side IO service
// in background to not block the main thread.
@@ -4580,7 +4582,7 @@ TEST_F(HAServiceTest, processMaintenanceStartSuccessAuthorized) {
listener2_->start();
});
- HAService service(io_service_, network_state_, config_storage);
+ HAService service(1, io_service_, network_state_, config_storage);
// The tested function is synchronous, so we need to run server side IO service
// in background to not block the main thread.
@@ -4623,7 +4625,7 @@ TEST_F(HAServiceTest, processMaintenanceStartPartnerDown) {
listener_->start();
});
- HAService service(io_service_, network_state_, config_storage);
+ HAService service(1, io_service_, network_state_, config_storage);
// The tested function is synchronous, so we need to run server side IO service
// in background to not block the main thread.
@@ -4667,7 +4669,7 @@ TEST_F(HAServiceTest, processMaintenanceStartPartnerError) {
listener2_->start();
});
- HAService service(io_service_, network_state_, config_storage);
+ HAService service(1, io_service_, network_state_, config_storage);
// The tested function is synchronous, so we need to run server side IO service
// in background to not block the main thread.
@@ -4709,7 +4711,7 @@ TEST_F(HAServiceTest, processMaintenanceStartPartnerUnauthorized) {
listener2_->start();
});
- HAService service(io_service_, network_state_, config_storage);
+ HAService service(1, io_service_, network_state_, config_storage);
// The tested function is synchronous, so we need to run server side IO service
// in background to not block the main thread.
@@ -4752,7 +4754,7 @@ TEST_F(HAServiceTest, processMaintenanceStartNotAllowed) {
listener2_->start();
});
- HAService service(io_service_, network_state_, config_storage);
+ HAService service(1, io_service_, network_state_, config_storage);
// The tested function is synchronous, so we need to run server side IO service
// in background to not block the main thread.
@@ -4794,7 +4796,7 @@ TEST_F(HAServiceTest, processMaintenanceCancelSuccess) {
listener2_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
ASSERT_NO_THROW(service.verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST));
@@ -4845,7 +4847,7 @@ TEST_F(HAServiceTest, processMaintenanceCancelSuccessAuthorized) {
listener2_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
ASSERT_NO_THROW(service.verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST));
@@ -4888,7 +4890,7 @@ TEST_F(HAServiceTest, processMaintenanceCancelPartnerError) {
listener2_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
ASSERT_NO_THROW(service.verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST));
@@ -4934,7 +4936,7 @@ TEST_F(HAServiceTest, processMaintenanceCancelPartnerUnauthorized) {
listener2_->start();
});
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
ASSERT_NO_THROW(service.verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST));
@@ -4966,7 +4968,7 @@ TEST_F(HAServiceTest, processMaintenanceCancelPartnerUnauthorized) {
// This test verifies that the ha-reset command is processed successfully.
TEST_F(HAServiceTest, processHAReset) {
HAConfigPtr config_storage = createValidConfiguration();
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Transition the server to the load-balancing state.
EXPECT_NO_THROW(service.transition(HA_LOAD_BALANCING_ST, HAService::NOP_EVT));
@@ -4991,7 +4993,7 @@ TEST_F(HAServiceTest, processHAReset) {
// the server is already in the waiting state.
TEST_F(HAServiceTest, processHAResetWaiting) {
HAConfigPtr config_storage = createValidConfiguration();
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Transition the server to the waiting state.
EXPECT_NO_THROW(service.transition(HA_WAITING_ST, HAService::NOP_EVT));
@@ -5018,14 +5020,14 @@ TEST_F(HAServiceTest, processHAResetWaiting) {
// state and enables the service when it is in another state.
TEST_F(HAServiceTest, processSyncCompleteNotify) {
HAConfigPtr config_storage = createValidConfiguration();
- TestHAService service(io_service_, network_state_, config_storage);
+ TestHAService service(1, io_service_, network_state_, config_storage);
// Transition the server to the partner-down state.
EXPECT_NO_THROW(service.transition(HA_PARTNER_DOWN_ST, HAService::NOP_EVT));
// Simulate disabling the DHCP service for synchronization.
if (service.network_state_->isServiceEnabled()) {
- EXPECT_NO_THROW(service.network_state_->disableService(NetworkState::Origin::HA_COMMAND));
+ EXPECT_NO_THROW(service.network_state_->disableService(NetworkState::HA_LOCAL_COMMAND+1));
}
ConstElementPtr rsp;
@@ -5054,7 +5056,7 @@ TEST_F(HAServiceTest, processSyncCompleteNotify) {
EXPECT_NO_THROW(service.transition(HA_LOAD_BALANCING_ST, HAService::NOP_EVT));
// Disable the service again.
- EXPECT_NO_THROW(service.network_state_->disableService(NetworkState::Origin::HA_COMMAND));
+ EXPECT_NO_THROW(service.network_state_->disableService(NetworkState::HA_LOCAL_COMMAND+1));
EXPECT_NO_THROW(rsp = service.processSyncCompleteNotify());
@@ -5537,12 +5539,12 @@ public:
// state.
if (dhcp_enabled) {
if (service_->network_state_->isServiceEnabled()) {
- service_->network_state_->disableService(NetworkState::Origin::HA_COMMAND);
+ service_->network_state_->disableService(NetworkState::HA_LOCAL_COMMAND+1);
}
} else {
if (!service_->network_state_->isServiceEnabled()) {
- service_->network_state_->enableService(NetworkState::Origin::HA_COMMAND);
+ service_->network_state_->enableService(NetworkState::HA_LOCAL_COMMAND+1);
}
}
@@ -8011,7 +8013,7 @@ TEST_F(HAServiceStateMachineTest, clearRejectedLeaseUpdatesPassiveBackup) {
// Verifies that the server doesn't terminate when the partner is unavailable.
TEST_F(HAServiceStateMachineTest, doNotTerminateWhenPartnerUnavailable) {
HAConfigPtr config_storage = createValidConfiguration();
- ASSERT_NO_THROW_LOG(service_.reset(new TestHAService(io_service_, network_state_,
+ ASSERT_NO_THROW_LOG(service_.reset(new TestHAService(1, io_service_, network_state_,
config_storage)));
NakedCommunicationState4Ptr state(new NakedCommunicationState4(io_service_,
config_storage));
diff --git a/src/lib/dhcpsrv/network_state.cc b/src/lib/dhcpsrv/network_state.cc
index 14e4fe7efb..7dd77311bd 100644
--- a/src/lib/dhcpsrv/network_state.cc
+++ b/src/lib/dhcpsrv/network_state.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2023 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
@@ -12,18 +12,12 @@
#include <util/multi_threading_mgr.h>
#include <boost/enable_shared_from_this.hpp>
#include <functional>
+#include <sstream>
#include <string>
+#include <unordered_set>
using namespace isc::util;
-namespace {
-
-/// @brief Name of the timer used by the @c NetworkState class.
-const std::string NETWORK_STATE_TIMER_NAME_USER_CMD = "network-state-timer-user-cmd";
-const std::string NETWORK_STATE_TIMER_NAME_HA_CMD = "network-state-timer-ha-cmd";
-
-} // end of anonymous namespace
-
namespace isc {
namespace dhcp {
@@ -35,14 +29,15 @@ public:
NetworkStateImpl(const NetworkState::ServerType& server_type)
: server_type_(server_type), globally_disabled_(false),
disabled_subnets_(), disabled_networks_(),
- timer_mgr_(TimerMgr::instance()), disabled_by_user_command_(false),
- disabled_by_ha_command_(false), disabled_by_db_connection_(0) {
+ timer_mgr_(TimerMgr::instance()), disabled_by_origin_(),
+ disabled_by_db_connection_(0) {
}
/// @brief Destructor.
~NetworkStateImpl() {
- destroyTimer(NetworkState::Origin::USER_COMMAND);
- destroyTimer(NetworkState::Origin::HA_COMMAND);
+ for (auto origin : disabled_by_origin_) {
+ destroyTimer(origin);
+ }
}
/// @brief Sets appropriate disabled or enabled DHCP service state for the
@@ -57,49 +52,27 @@ public:
///
/// @param disable The value of the flag used to perform the transition.
/// @param origin The origin of the state transition.
- void setDisableService(const bool disable,
- const NetworkState::Origin& origin) {
+ void setDisableService(const bool disable, unsigned int origin) {
if (disable) {
// Disable the service for any flag.
globally_disabled_ = true;
- switch (origin) {
- case NetworkState::Origin::USER_COMMAND:
- disabled_by_user_command_ = true;
- break;
- case NetworkState::Origin::HA_COMMAND:
- disabled_by_ha_command_ = true;
- break;
- case NetworkState::Origin::DB_CONNECTION:
+ if (origin == NetworkState::DB_CONNECTION) {
++disabled_by_db_connection_;
- break;
- default:
- isc_throw(NotImplemented, "origin value not handled when "
- "disabling the network state");
- break;
+ } else {
+ disabled_by_origin_.insert(origin);
}
} else {
- switch (origin) {
- case NetworkState::Origin::USER_COMMAND:
- disabled_by_user_command_ = false;
- break;
- case NetworkState::Origin::HA_COMMAND:
- disabled_by_ha_command_ = false;
- break;
- case NetworkState::Origin::DB_CONNECTION:
+ if (origin == NetworkState::DB_CONNECTION) {
// Never go below 0 (using unsigned type).
// This should never happen anyway.
if (disabled_by_db_connection_) {
--disabled_by_db_connection_;
}
- break;
- default:
- isc_throw(NotImplemented, "origin value not handled when "
- "enabling the network state");
- break;
+ } else {
+ disabled_by_origin_.erase(origin);
}
// Enable the service only if all flags have been cleared.
- if (!disabled_by_user_command_ && !disabled_by_ha_command_ &&
- disabled_by_db_connection_ == 0) {
+ if (disabled_by_origin_.empty() && disabled_by_db_connection_ == 0) {
globally_disabled_ = false;
}
}
@@ -110,25 +83,14 @@ public:
/// @note The dhcp service will remain disabled until all flags are cleared.
///
/// @param origin The origin of the state transition.
- void reset(const NetworkState::Origin& origin) {
- switch (origin) {
- case NetworkState::Origin::USER_COMMAND:
- disabled_by_user_command_ = false;
- break;
- case NetworkState::Origin::HA_COMMAND:
- disabled_by_ha_command_ = false;
- break;
- case NetworkState::Origin::DB_CONNECTION:
+ void reset(unsigned int origin) {
+ if (origin == NetworkState::DB_CONNECTION) {
disabled_by_db_connection_ = 0;
- break;
- default:
- isc_throw(NotImplemented, "origin value not handled when "
- "resetting the network state");
- break;
+ } else {
+ disabled_by_origin_.erase(origin);
}
// Enable the service only if all flags have been cleared.
- if (!disabled_by_user_command_ && !disabled_by_ha_command_ &&
- disabled_by_db_connection_ == 0) {
+ if (disabled_by_origin_.empty() && disabled_by_db_connection_ == 0) {
globally_disabled_ = false;
}
}
@@ -138,7 +100,7 @@ public:
/// If delayed enabling DHCP service has been scheduled, it cancels it.
///
/// @param origin The origin of the state transition.
- void enableAll(const NetworkState::Origin& origin) {
+ void enableAll(unsigned int origin) {
setDisableService(false, origin);
/// @todo Enable service for all subnets and networks here.
@@ -155,25 +117,12 @@ public:
/// @param seconds Number of seconds to elapse before the @c enableAll is
/// called.
/// @param origin The origin of the state transition.
- void createTimer(const unsigned int seconds,
- const NetworkState::Origin& origin) {
+ void createTimer(const unsigned int seconds, unsigned int origin) {
destroyTimer(origin);
- std::string timer_name = NETWORK_STATE_TIMER_NAME_USER_CMD;
- switch (origin) {
- case NetworkState::Origin::USER_COMMAND:
- timer_name = NETWORK_STATE_TIMER_NAME_USER_CMD;
- break;
- case NetworkState::Origin::HA_COMMAND:
- timer_name = NETWORK_STATE_TIMER_NAME_HA_CMD;
- break;
- case NetworkState::Origin::DB_CONNECTION:
+ if (origin == NetworkState::DB_CONNECTION) {
isc_throw(BadValue, "DB connection does not support delayed enable");
- break;
- default:
- isc_throw(NotImplemented, "origin value not handled when creating "
- "a timer for delayed enable");
- break;
}
+ auto timer_name = getTimerName(origin);
timer_mgr_->registerTimer(timer_name,
std::bind(&NetworkStateImpl::enableAll,
shared_from_this(), origin),
@@ -185,27 +134,26 @@ public:
/// @brief Destroys a timer if present.
///
/// @param origin The origin of the state transition.
- void destroyTimer(const NetworkState::Origin& origin) {
- std::string timer_name = NETWORK_STATE_TIMER_NAME_USER_CMD;
- switch (origin) {
- case NetworkState::Origin::USER_COMMAND:
- timer_name = NETWORK_STATE_TIMER_NAME_USER_CMD;
- break;
- case NetworkState::Origin::HA_COMMAND:
- timer_name = NETWORK_STATE_TIMER_NAME_HA_CMD;
- break;
- case NetworkState::Origin::DB_CONNECTION:
+ void destroyTimer(unsigned int origin) {
+ if (origin == NetworkState::DB_CONNECTION) {
return;
- default:
- isc_throw(NotImplemented, "origin value not handled when creating "
- "a timer for delayed enable");
- break;
}
+ auto timer_name = getTimerName(origin);
if (timer_mgr_->isTimerRegistered(timer_name)) {
timer_mgr_->unregisterTimer(timer_name);
}
}
+ /// @brief Creates a unique timer name from the origin.
+ ///
+ /// @param origin The origin of the state transition.
+ /// @return Unique timer name for the origin.
+ std::string getTimerName(unsigned int origin) const {
+ std::ostringstream timer_name;
+ timer_name << "network-state-timer-" << origin;
+ return (timer_name.str());
+ }
+
/// @brief Server type.
NetworkState::ServerType server_type_;
@@ -224,13 +172,8 @@ public:
/// destroyed before an instance of this class is destroyed.
TimerMgrPtr timer_mgr_;
- /// @brief Flag which indicates the state has been disabled by an user
- /// command.
- bool disabled_by_user_command_;
-
- /// @brief Flag which indicates the state has been disabled by the HA
- /// command.
- bool disabled_by_ha_command_;
+ /// @brief A set of requests to disable the service by origin.
+ std::unordered_set<unsigned int> disabled_by_origin_;
/// @brief Flag which indicates the state has been disabled by a DB
/// connection loss.
@@ -242,7 +185,7 @@ NetworkState::NetworkState(const NetworkState::ServerType& server_type)
}
void
-NetworkState::disableService(const Origin& origin) {
+NetworkState::disableService(unsigned int origin) {
if (MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lk(*mutex_);
impl_->setDisableService(true, origin);
@@ -252,7 +195,7 @@ NetworkState::disableService(const Origin& origin) {
}
void
-NetworkState::enableService(const Origin& origin) {
+NetworkState::enableService(unsigned int origin) {
if (MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lk(*mutex_);
impl_->setDisableService(false, origin);
@@ -262,7 +205,7 @@ NetworkState::enableService(const Origin& origin) {
}
void
-NetworkState::reset(const NetworkState::Origin& origin) {
+NetworkState::reset(unsigned int origin) {
if (MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lk(*mutex_);
impl_->reset(origin);
@@ -272,7 +215,7 @@ NetworkState::reset(const NetworkState::Origin& origin) {
}
void
-NetworkState::enableAll(const NetworkState::Origin& origin) {
+NetworkState::enableAll(unsigned int origin) {
if (MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lk(*mutex_);
impl_->enableAll(origin);
@@ -282,8 +225,7 @@ NetworkState::enableAll(const NetworkState::Origin& origin) {
}
void
-NetworkState::delayedEnableAll(const unsigned int seconds,
- const NetworkState::Origin& origin) {
+NetworkState::delayedEnableAll(const unsigned int seconds, unsigned int origin) {
if (MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lk(*mutex_);
impl_->createTimer(seconds, origin);
@@ -304,8 +246,12 @@ NetworkState::isServiceEnabled() const {
bool
NetworkState::isDelayedEnableAll() const {
- return (TimerMgr::instance()->isTimerRegistered(NETWORK_STATE_TIMER_NAME_USER_CMD) ||
- TimerMgr::instance()->isTimerRegistered(NETWORK_STATE_TIMER_NAME_HA_CMD));
+ for (auto origin : impl_->disabled_by_origin_) {
+ if (TimerMgr::instance()->isTimerRegistered(impl_->getTimerName(origin))) {
+ return (true);
+ }
+ }
+ return (false);
}
void
diff --git a/src/lib/dhcpsrv/network_state.h b/src/lib/dhcpsrv/network_state.h
index def52e682c..b3d203ff08 100644
--- a/src/lib/dhcpsrv/network_state.h
+++ b/src/lib/dhcpsrv/network_state.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2023 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
@@ -20,53 +20,54 @@ namespace dhcp {
class NetworkStateImpl;
-/// @brief Holds information about DHCP service enabling status.
+/// @brief Controls the DHCP service enabling status.
///
-/// When the DHCP server receives a command to disable DHCP service entirely
-/// or for specific networks, this has to be recorded to allow for re-enabling
-/// DHCP service for these networks as a result of receiving a command from
-/// the administrator or when the timeout for re-enabling the service occurs.
-/// Currently there are two types of command originating either from user or
-/// HA internal mechanism.
-/// The global state can also be altered by the DB recovery mechanism which
-/// disables the service on connection loss and re-enables it after the
-/// connection is restored. Because the server supports recovery for multiple
-/// connections, this is implemented using an internal counter.
-/// Combining all the origins of the alteration of the network state, the
-/// behavior is:
-/// a) the network state is disabled if any of the originators explicitly set
-/// the disabled flag.
-/// b) the network state is restored only if all originators explicitly clear
-/// the disabled flag.
-/// In the future, it will be possible to specify "disabled" parameter for
-/// a subnet (or network) in the configuration file to indicate that this subnet
-/// should be excluded from the service. When a command is subsequently sent to
-/// temporarily disable a service for some other subnets for a specified amount
-/// of time, only these subnets should be re-enabled when the time elapses. This
-/// class fulfills this requirement by recording the subnets disabled with a command
-/// and re-enabling them when required. The subnets specified as "disabled" in
-/// the configuration file should remain disabled until explicitly enabled with a
-/// control command.
+/// Sometimes, a DHCP server must pause responding to the DHCP queries.
+/// Typical cases include a database connection loss when the server tries
+/// to reconnect and various cases related to the High Availability operation.
+/// It is also possible to explicitly turn the DHCP service on and off via the
+/// control channel. This class receives calls from different origins to
+/// disable and re-enable the DHCP service.
///
-/// This class also allows for disabling the DHCP service globally. In this case
-/// the server drops all received packets.
+/// The general rule is that the DHCP service must be disabled when the class
+/// receives at least one request to disable the service from any origin. The
+/// service must be re-enabled when all requestors previously disabling the
+/// service re-enabled it. This class also allows for specifying a timeout value
+/// for each request, after which the service gets re-enabled automatically. It
+/// is particularly useful in HA when there is no guarantee that the HA partner
+/// will be able to re-enable the service because it may experience an unexpected
+/// outage. In that case, the "max-period" parameter must accompany the "dhcp-disable"
+/// command to ensure that the service will eventually be re-enabled.
+
+/// The HA hook library may include several independent relationships. Each
+/// relationship is treated as a separate origin by this class. If one relationship
+/// disables the DHCP service, the service must remain disabled even when any other
+/// relationship requests enabling it. The service is re-enabled after all
+/// relationships requested re-enabling it (e.g., they all finished synchronizing
+/// the lease database).
///
-/// The "dhcp-disable" and "dhcp-enable" commands are used for globally disabling
-/// and enabling the DHCP service. The "dhcp-disable-scopes" and "dhcp-enable-scopes"
-/// commands are used to disable and enable DHCP service for subnets and networks.
-/// In case of the "dhcp-disable" and "dhcp-disable-scopes" commands, it is possible
-/// to specify "max-period" parameter which provides a timeout, after which the
-/// settings are reverted (service is re-enabled globally and/or for specific
-/// scopes).
+/// The HA service instances must have unique identifiers they use to specify the
+/// origin. For example, an @c HAService with the identifier of 1 should request
+/// disabling the local service like this:
///
-/// Disabling DHCP service with a timeout is useful to guard against issues when
-/// the controlling client dies after disabling the DHCP service on the server,
-/// e.g. failover peers may instruct each other to disable the DHCP service while
-/// database synchronization takes place. If the peer subsequently dies, the
-/// surviving server must re-enable DHCP on its own.
+/// @code
+/// NetworkState state;
+/// state.disableService(NetworkState::HA_LOCAL_COMMAND + 1);
+/// @endcode
///
-/// @todo This class currently supports only the case of globally disabling
-/// the DHCP service. Disabling per network/subnet will be added later.
+/// The DHCP state can also be altered by the database recovery mechanism, which
+/// disables the service on connection loss and re-enables it after the connection
+/// is restored. Unlike in HA, this is implemented using an internal counter. In
+/// this case, there is one origin for all database connections. The requests for
+/// the @c NetworkState::DB_CONNECTION are counted, and the DHCP service is
+/// re-enabled when the counter reaches 0.
+///
+/// @todo We should consider migrating the database recovery to the same mechanism
+/// we use for the HA. The reference counting works because the database connection
+/// classes ensure that for each request to disable the DHCP service, there is a
+/// corresponding request to enable the service. It prevents the situation that the
+/// service remains disabled because there were more requests to disable than to
+/// enable the service. It is hard to ensure the same consistency for the HA.
class NetworkState {
public:
@@ -81,15 +82,29 @@ public:
/// The enumeration indicates the originator of the state transition of the
/// network state: either user command, HA internal command or DB connection
/// recovery mechanism.
- enum class Origin {
- /// @brief The network state is being altered by a user command.
- USER_COMMAND,
- /// @brief The network state is being altered by a HA internal command.
- HA_COMMAND,
- /// @brief The network state is being altered by the DB connection
- /// recovery mechanics.
- DB_CONNECTION
- };
+
+ /// @brief The network state is being altered by a user command.
+ ///
+ /// Specify unique origins for different commands by adding a number to this
+ /// constant.
+ static const unsigned int USER_COMMAND = 1;
+
+ /// @brief The network state is being altered by an HA internal command.
+ ///
+ /// Specify HA service-specific origins by adding a unique local service
+ /// identifier to this constant.
+ static const unsigned int HA_LOCAL_COMMAND = 1000;
+
+ /// @brief The network state is being altered by a "dhcp-disable" or "dhcp-enable"
+ /// command sent by a HA partner.
+ ///
+ /// Specify HA service-specific origins by adding a unique remote service
+ /// identifier to this constant.
+ static const unsigned int HA_REMOTE_COMMAND = 1100;
+
+ /// @brief The network state is being altered by the DB connection
+ /// recovery mechanics.
+ static const unsigned int DB_CONNECTION = 2000;
/// @brief Type of the container holding collection of subnet identifiers.
typedef std::set<SubnetID> Subnets;
@@ -107,7 +122,7 @@ public:
/// disabled until all flags are cleared.
///
/// @param origin The origin of the state transition.
- void disableService(const NetworkState::Origin& origin);
+ void disableService(unsigned int origin);
/// @brief Enable the DHCP service state for respective transition origin.
///
@@ -116,7 +131,7 @@ public:
/// disabled until all flags are cleared.
///
/// @param origin The origin of the state transition.
- void enableService(const NetworkState::Origin& origin);
+ void enableService(unsigned int origin);
/// @brief Reset internal counters.
///
@@ -124,13 +139,13 @@ public:
/// been reconfigured or all the connections have been restored.
///
/// @param type The origin for which the state flags need to be reset.
- void reset(const NetworkState::Origin& type);
+ void reset(unsigned int type);
/// @brief Enables DHCP service globally and for scopes which have been
/// disabled as a result of control command.
///
/// @param origin The origin of the state transition.
- void enableAll(const NetworkState::Origin& origin);
+ void enableAll(unsigned int origin);
/// @brief Schedules enabling DHCP service in the future.
///
@@ -138,7 +153,7 @@ public:
/// unless @c enableAll is enabled before that time.
/// @param origin The origin of the state transition.
void delayedEnableAll(const unsigned int seconds,
- const NetworkState::Origin& origin);
+ unsigned int origin);
/// @brief Checks if the DHCP service is globally enabled.
///
diff --git a/src/lib/dhcpsrv/tests/network_state_unittest.cc b/src/lib/dhcpsrv/tests/network_state_unittest.cc
index 7edf4581ae..8c3b8708a9 100644
--- a/src/lib/dhcpsrv/tests/network_state_unittest.cc
+++ b/src/lib/dhcpsrv/tests/network_state_unittest.cc
@@ -174,19 +174,19 @@ NetworkStateTest::disableEnableService4UsingUserCommandOriginTest() {
NetworkState state(NetworkState::DHCPv4);
// Test that enable/disable using 'user command' origin works
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
// Test that using 'user command' origin does not use internal counter
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -197,19 +197,19 @@ NetworkStateTest::disableEnableService4UsingHACommandOriginTest() {
NetworkState state(NetworkState::DHCPv4);
// Test that enable/disable using 'HA command' origin works
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
// Test that using 'HA command' origin does not use internal counter
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -220,23 +220,23 @@ NetworkStateTest::disableEnableService4UsingDBConnectionOriginTest() {
NetworkState state(NetworkState::DHCPv4);
// Test that enable/disable using 'DB connection' origin works
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
// Test that using 'DB connection' origin uses internal counter
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -253,25 +253,25 @@ NetworkStateTest::disableEnableService4UsingMultipleOriginsTest() {
NetworkState state(NetworkState::DHCPv4);
// Test that a combination properly affects the state
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -282,19 +282,19 @@ NetworkStateTest::disableEnableService6UsingUserCommandOriginTest() {
NetworkState state(NetworkState::DHCPv6);
// Test that enable/disable using 'user command' origin works
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
// Test that using 'user command' origin does not use internal counter
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -305,19 +305,19 @@ NetworkStateTest::disableEnableService6UsingHACommandOriginTest() {
NetworkState state(NetworkState::DHCPv6);
// Test that enable/disable using 'HA command' origin works
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
// Test that using 'HA command' origin does not use internal counter
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -328,23 +328,23 @@ NetworkStateTest::disableEnableService6UsingDBConnectionOriginTest() {
NetworkState state(NetworkState::DHCPv6);
// Test that enable/disable using 'DB connection' origin works
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
// Test that using 'DB connection' origin uses internal counter
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -361,25 +361,25 @@ NetworkStateTest::disableEnableService6UsingMultipleOriginsTest() {
NetworkState state(NetworkState::DHCPv6);
// Test that a combination properly affects the state
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -398,31 +398,31 @@ NetworkStateTest::resetUsingUserCommandOriginTest() {
NetworkState state(NetworkState::DHCPv4);
// Test User COMMAND + HA COMMAND + DB CONNECTION origins
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.reset(NetworkState::Origin::USER_COMMAND);
+ state.reset(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
// Test User COMMAND origin only
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.reset(NetworkState::Origin::USER_COMMAND);
+ state.reset(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -441,31 +441,31 @@ NetworkStateTest::resetUsingHACommandOriginTest() {
NetworkState state(NetworkState::DHCPv4);
// Test HA COMMAND + User COMMAND + DB CONNECTION origins
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.reset(NetworkState::Origin::HA_COMMAND);
+ state.reset(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::DB_CONNECTION);
+ state.enableService(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
// Test HA COMMAND origin only
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.reset(NetworkState::Origin::HA_COMMAND);
+ state.reset(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -484,31 +484,31 @@ NetworkStateTest::resetUsingDBConnectionOriginTest() {
NetworkState state(NetworkState::DHCPv4);
// Test DB CONNECTION + User COMMAND + HA COMMAND origins
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.reset(NetworkState::Origin::DB_CONNECTION);
+ state.reset(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::USER_COMMAND);
+ state.enableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableService(NetworkState::Origin::HA_COMMAND);
+ state.enableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
// Test DB CONNECTION origin only
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.reset(NetworkState::Origin::DB_CONNECTION);
+ state.reset(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -517,17 +517,17 @@ NetworkStateTest::resetUsingDBConnectionOriginTest() {
void
NetworkStateTest::enableAllTest() {
NetworkState state(NetworkState::DHCPv4);
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableAll(NetworkState::Origin::USER_COMMAND);
+ state.enableAll(NetworkState::USER_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableAll(NetworkState::Origin::HA_COMMAND);
+ state.enableAll(NetworkState::HA_LOCAL_COMMAND);
EXPECT_TRUE(state.isServiceEnabled());
- state.disableService(NetworkState::Origin::DB_CONNECTION);
+ state.disableService(NetworkState::DB_CONNECTION);
EXPECT_FALSE(state.isServiceEnabled());
- state.enableAll(NetworkState::Origin::DB_CONNECTION);
+ state.enableAll(NetworkState::DB_CONNECTION);
EXPECT_TRUE(state.isServiceEnabled());
}
@@ -537,24 +537,24 @@ void
NetworkStateTest::delayedEnableAllTest() {
NetworkState state(NetworkState::DHCPv4);
// Disable the service and then schedule enabling it in 1 second.
- state.disableService(NetworkState::Origin::USER_COMMAND);
- state.delayedEnableAll(1, NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
+ state.delayedEnableAll(1, NetworkState::USER_COMMAND);
// Initially the service should be still disabled.
EXPECT_FALSE(state.isServiceEnabled());
// After running IO service for 2 seconds, the service should be enabled.
runIOService(2000);
EXPECT_TRUE(state.isServiceEnabled());
// Disable the service and then schedule enabling it in 1 second.
- state.disableService(NetworkState::Origin::HA_COMMAND);
- state.delayedEnableAll(1, NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
+ state.delayedEnableAll(1, NetworkState::HA_LOCAL_COMMAND);
// Initially the service should be still disabled.
EXPECT_FALSE(state.isServiceEnabled());
// After running IO service for 2 seconds, the service should be enabled.
runIOService(2000);
EXPECT_TRUE(state.isServiceEnabled());
// Disable the service and then schedule enabling it in 1 second.
- state.disableService(NetworkState::Origin::DB_CONNECTION);
- EXPECT_THROW(state.delayedEnableAll(1, NetworkState::Origin::DB_CONNECTION), BadValue);
+ state.disableService(NetworkState::DB_CONNECTION);
+ EXPECT_THROW(state.delayedEnableAll(1, NetworkState::DB_CONNECTION), BadValue);
}
// This test verifies that explicitly enabling the service cancels the timer
@@ -563,12 +563,12 @@ void
NetworkStateTest::earlyEnableAllTest() {
NetworkState state(NetworkState::DHCPv4);
// Disable the service.
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
EXPECT_FALSE(state.isServiceEnabled());
// Schedule enabling the service in 2 seconds.
- state.delayedEnableAll(2, NetworkState::Origin::USER_COMMAND);
+ state.delayedEnableAll(2, NetworkState::USER_COMMAND);
// Explicitly enable the service.
- state.enableAll(NetworkState::Origin::USER_COMMAND);
+ state.enableAll(NetworkState::USER_COMMAND);
// The timer should be now canceled and the service should be enabled.
EXPECT_FALSE(state.isDelayedEnableAll());
EXPECT_TRUE(state.isServiceEnabled());
@@ -580,12 +580,12 @@ void
NetworkStateTest::multipleDelayedEnableAllTest() {
NetworkState state(NetworkState::DHCPv4);
// Disable the service and then schedule enabling it in 5 second.
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
// Schedule the first timer for 5 seconds.
- state.delayedEnableAll(5, NetworkState::Origin::USER_COMMAND);
+ state.delayedEnableAll(5, NetworkState::USER_COMMAND);
// When calling it the second time the old timer should be destroyed and
// the timeout should be set to 2 seconds.
- state.delayedEnableAll(2, NetworkState::Origin::USER_COMMAND);
+ state.delayedEnableAll(2, NetworkState::USER_COMMAND);
// Initially the service should be still disabled.
EXPECT_FALSE(state.isServiceEnabled());
// After running IO service for 3 seconds, the service should be enabled.
@@ -602,14 +602,14 @@ void
NetworkStateTest::multipleDifferentOriginsDelayedEnableAllTest() {
NetworkState state(NetworkState::DHCPv4);
// Disable the service and then schedule enabling it in 5 second.
- state.disableService(NetworkState::Origin::HA_COMMAND);
+ state.disableService(NetworkState::HA_LOCAL_COMMAND);
// Disable the service and then schedule enabling it in 2 second.
- state.disableService(NetworkState::Origin::USER_COMMAND);
+ state.disableService(NetworkState::USER_COMMAND);
// Schedule the first timer for 5 seconds.
- state.delayedEnableAll(5, NetworkState::Origin::HA_COMMAND);
+ state.delayedEnableAll(5, NetworkState::HA_LOCAL_COMMAND);
// When calling it the second time the old timer should not be destroyed and
// the new timeout should be set to 2 seconds.
- state.delayedEnableAll(2, NetworkState::Origin::USER_COMMAND);
+ state.delayedEnableAll(2, NetworkState::USER_COMMAND);
// Initially the service should be still disabled.
EXPECT_FALSE(state.isServiceEnabled());
// After running IO service for 3 seconds, the service should not be enabled.