]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3751] backport #3727 to 2.6.2
authorRazvan Becheriu <razvan@isc.org>
Wed, 19 Feb 2025 14:40:04 +0000 (16:40 +0200)
committerRazvan Becheriu <razvan@isc.org>
Mon, 3 Mar 2025 11:37:35 +0000 (13:37 +0200)
36 files changed:
src/bin/agent/agent_lexer.cc
src/bin/d2/d2_lexer.cc
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp4/dhcp4_messages.cc
src/bin/dhcp4/dhcp4_messages.mes
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp6/ctrl_dhcp6_srv.cc
src/bin/dhcp6/dhcp6_messages.cc
src/bin/dhcp6/dhcp6_messages.mes
src/bin/dhcp6/dhcp6_srv.cc
src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc
src/hooks/dhcp/high_availability/tests/ha_impl_unittest.cc
src/hooks/dhcp/high_availability/tests/ha_test.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc
src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc
src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc
src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc
src/lib/database/database_connection.cc
src/lib/database/database_connection.h
src/lib/database/tests/database_connection_unittest.cc
src/lib/dhcpsrv/cfg_iface.cc
src/lib/dhcpsrv/mysql_host_data_source.cc
src/lib/dhcpsrv/mysql_lease_mgr.cc
src/lib/dhcpsrv/network_state.cc
src/lib/dhcpsrv/network_state.h
src/lib/dhcpsrv/pgsql_host_data_source.cc
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/tests/network_state_unittest.cc
src/lib/mysql/mysql_connection.cc
src/lib/mysql/mysql_connection.h
src/lib/pgsql/pgsql_connection.cc
src/lib/pgsql/pgsql_connection.h
src/lib/util/reconnect_ctl.h
src/share/api/status-get.json

index 57c807af165bb32f8d0c51bf7bceba1b6ee0c7cb..577b0bdfff422993a382a783b5c9aa28a29ba1cd 100644 (file)
@@ -1,6 +1,6 @@
-#line 1 "agent_lexer.cc"
+#line 2 "agent_lexer.cc"
 
-#line 3 "agent_lexer.cc"
+#line 4 "agent_lexer.cc"
 
 #define  YY_INT_ALIGNED short int
 
@@ -1606,7 +1606,7 @@ using isc::agent::AgentParser;
 
 /* To avoid the call to exit... oops! */
 #define YY_FATAL_ERROR(msg) isc::agent::ParserContext::fatal(msg)
-#line 1609 "agent_lexer.cc"
+#line 1610 "agent_lexer.cc"
 /* noyywrap disables automatic rewinding for the next file to parse. Since we
    always parse only a single string, there's no need to do any wraps. And
    using yywrap requires linking with -lfl, which provides the default yywrap
@@ -1632,8 +1632,8 @@ using isc::agent::AgentParser;
    by moving it ahead by yyleng bytes. yyleng specifies the length of the
    currently matched token. */
 #define YY_USER_ACTION  driver.loc_.columns(yyleng);
-#line 1635 "agent_lexer.cc"
 #line 1636 "agent_lexer.cc"
+#line 1637 "agent_lexer.cc"
 
 #define INITIAL 0
 #define COMMENT 1
@@ -1947,7 +1947,7 @@ YY_DECL
     }
 
 
-#line 1950 "agent_lexer.cc"
+#line 1951 "agent_lexer.cc"
 
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@ -2937,7 +2937,7 @@ YY_RULE_SETUP
 #line 814 "agent_lexer.ll"
 ECHO;
        YY_BREAK
-#line 2940 "agent_lexer.cc"
+#line 2941 "agent_lexer.cc"
 
        case YY_END_OF_BUFFER:
                {
index 08e3bfd7e72cb54a341057781687739fb570c42d..b600fef06a3ad4ac0ca443d535f39695fdb78e04 100644 (file)
@@ -1,6 +1,6 @@
-#line 1 "d2_lexer.cc"
+#line 2 "d2_lexer.cc"
 
-#line 3 "d2_lexer.cc"
+#line 4 "d2_lexer.cc"
 
 #define  YY_INT_ALIGNED short int
 
@@ -1142,7 +1142,7 @@ unsigned int comment_start_line = 0;
 
 /* To avoid the call to exit... oops! */
 #define YY_FATAL_ERROR(msg) isc::d2::D2ParserContext::fatal(msg)
-#line 1145 "d2_lexer.cc"
+#line 1146 "d2_lexer.cc"
 /* noyywrap disables automatic rewinding for the next file to parse. Since we
    always parse only a single string, there's no need to do any wraps. And
    using yywrap requires linking with -lfl, which provides the default yywrap
@@ -1168,8 +1168,8 @@ unsigned int comment_start_line = 0;
    by moving it ahead by yyleng bytes. yyleng specifies the length of the
    currently matched token. */
 #define YY_USER_ACTION  driver.loc_.columns(yyleng);
-#line 1171 "d2_lexer.cc"
 #line 1172 "d2_lexer.cc"
+#line 1173 "d2_lexer.cc"
 
 #define INITIAL 0
 #define COMMENT 1
@@ -1489,7 +1489,7 @@ YY_DECL
     }
 
 
-#line 1492 "d2_lexer.cc"
+#line 1493 "d2_lexer.cc"
 
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@ -2496,7 +2496,7 @@ YY_RULE_SETUP
 #line 836 "d2_lexer.ll"
 ECHO;
        YY_BREAK
-#line 2499 "d2_lexer.cc"
+#line 2500 "d2_lexer.cc"
 
        case YY_END_OF_BUFFER:
                {
index 84827d62b06176fbaf5e180db1ced059eec3d271..def7d084351424aedf880bce17f0c3387cd344fe 100644 (file)
@@ -301,7 +301,7 @@ ControlledDhcpv4Srv::commandConfigWriteHandler(const string&,
         ConstElementPtr cfg = CfgMgr::instance().getCurrentCfg()->toElement();
         size = writeConfigFile(filename, cfg);
     } catch (const isc::Exception& ex) {
-        return (createAnswer(CONTROL_RESULT_ERROR, string("Error during write-config: ")
+        return (createAnswer(CONTROL_RESULT_ERROR, string("Error during config-write: ")
                              + ex.what()));
     }
     if (size == 0) {
@@ -799,6 +799,8 @@ ControlledDhcpv4Srv::commandStatusGetHandler(const string&,
     }
     status->set("sockets", sockets);
 
+    status->set("dhcp-state", network_state_->toElement());
+
     return (createAnswer(CONTROL_RESULT_SUCCESS, status));
 }
 
@@ -878,6 +880,8 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
         cfg_db->createManagers();
         // Reset counters related to connections as all managers have been recreated.
         srv->getNetworkState()->resetForDbConnection();
+        srv->getNetworkState()->resetForLocalCommands();
+        srv->getNetworkState()->resetForRemoteCommands();
     } catch (const std::exception& ex) {
         err << "Unable to open database: " << ex.what();
         return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
@@ -983,7 +987,6 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
         return (notify_libraries);
     }
 
-
     // Initialize the allocators. If the user selected a Free Lease Queue Allocator
     // for any of the subnets, the server will now populate free leases to the queue.
     // It may take a while!
@@ -1259,10 +1262,12 @@ 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::DB_CONNECTION);
+        network_state_->disableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
-    LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_LOST_CONNECTION);
+    LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_LOST_CONNECTION)
+        .arg(db_reconnect_ctl->id())
+        .arg(db_reconnect_ctl->timerName());
 
     // If reconnect isn't enabled log it, initiate a shutdown if needed and
     // return false.
@@ -1270,7 +1275,9 @@ ControlledDhcpv4Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
         !db_reconnect_ctl->retryInterval()) {
         LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_DISABLED)
             .arg(db_reconnect_ctl->retriesLeft())
-            .arg(db_reconnect_ctl->retryInterval());
+            .arg(db_reconnect_ctl->retryInterval())
+            .arg(db_reconnect_ctl->id())
+            .arg(db_reconnect_ctl->timerName());
         if (db_reconnect_ctl->exitOnFailure()) {
             shutdownServer(EXIT_FAILURE);
         }
@@ -1289,11 +1296,14 @@ ControlledDhcpv4Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
     }
 
     // Enable service after the connection is recovered.
-    if (db_reconnect_ctl->alterServiceState()) {
-        network_state_->enableService(NetworkState::DB_CONNECTION);
+    if (db_reconnect_ctl->retriesLeft() != db_reconnect_ctl->maxRetries() &&
+        db_reconnect_ctl->alterServiceState()) {
+        network_state_->enableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
-    LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_SUCCEEDED);
+    LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_SUCCEEDED)
+        .arg(db_reconnect_ctl->id())
+        .arg(db_reconnect_ctl->timerName());
 
     db_reconnect_ctl->resetRetries();
 
@@ -1309,7 +1319,9 @@ ControlledDhcpv4Srv::dbFailedCallback(ReconnectCtlPtr db_reconnect_ctl) {
     }
 
     LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_FAILED)
-            .arg(db_reconnect_ctl->maxRetries());
+        .arg(db_reconnect_ctl->maxRetries())
+        .arg(db_reconnect_ctl->id())
+        .arg(db_reconnect_ctl->timerName());
 
     if (db_reconnect_ctl->exitOnFailure()) {
         shutdownServer(EXIT_FAILURE);
index 9ed0059925376976098d7657f50b721b6e6ada6e..3307bffcf85e660a50b1dad44a49b1dbfc86cb57 100644 (file)
@@ -227,11 +227,11 @@ const char* values[] = {
     "DHCP4_CONFIG_UNRECOVERABLE_ERROR", "DHCPv4 server new configuration failed with an error which cannot be recovered",
     "DHCP4_CONFIG_UNSUPPORTED_OBJECT", "DHCPv4 server configuration includes an unsupported object: %1",
     "DHCP4_CONFIG_UPDATE", "updated configuration received: %1",
-    "DHCP4_DB_RECONNECT_DISABLED", "database reconnect is disabled: max-reconnect-tries %1, reconnect-wait-time %2",
-    "DHCP4_DB_RECONNECT_FAILED", "maximum number of database reconnect attempts: %1, has been exhausted without success",
-    "DHCP4_DB_RECONNECT_LOST_CONNECTION", "database connection lost.",
+    "DHCP4_DB_RECONNECT_DISABLED", "database reconnect is disabled: retries left: %1, reconnect wait time: %2, manager ID: %3, timer: %4",
+    "DHCP4_DB_RECONNECT_FAILED", "maximum number of database reconnect attempts: %1, has been exhausted without success, manager ID: %2, timer: %3",
+    "DHCP4_DB_RECONNECT_LOST_CONNECTION", "database connection lost: manager ID: %1, timer: %2.",
     "DHCP4_DB_RECONNECT_NO_DB_CTL", "unexpected error in database reconnect",
-    "DHCP4_DB_RECONNECT_SUCCEEDED", "database connection recovered.",
+    "DHCP4_DB_RECONNECT_SUCCEEDED", "database connection recovered: manager ID: %1, timer: %2.",
     "DHCP4_DDNS_REQUEST_SEND_FAILED", "failed sending a request to kea-dhcp-ddns, error: %1,  ncr: %2",
     "DHCP4_DEACTIVATE_INTERFACE", "deactivate interface %1",
     "DHCP4_DECLINE_FAIL", "%1: error on decline lease for address %2: %3",
index 4101afbd48e19500359cec073087b3f16253eae6..7c26da37ab727e50ba4cd3bd9cdc61ef24274886 100644 (file)
@@ -210,18 +210,18 @@ object (i.e. a top level element).
 A debug message indicating that the DHCPv4 server has received an
 updated configuration from the Kea configuration system.
 
-% DHCP4_DB_RECONNECT_DISABLED database reconnect is disabled: max-reconnect-tries %1, reconnect-wait-time %2
+% DHCP4_DB_RECONNECT_DISABLED database reconnect is disabled: retries left: %1, reconnect wait time: %2, manager ID: %3, timer: %4
 This is an informational message indicating that connectivity to either the
 lease or host database or both and that automatic reconnect is not enabled.
 
-% DHCP4_DB_RECONNECT_FAILED maximum number of database reconnect attempts: %1, has been exhausted without success
+% DHCP4_DB_RECONNECT_FAILED maximum number of database reconnect attempts: %1, has been exhausted without success, manager ID: %2, timer: %3
 This error indicates that the server failed to reconnect to the lease and/or
 host database(s) after making the maximum configured number of reconnect
 attempts. This might cause the server to shut down as specified in the
 configuration. Loss of connectivity is typically a network or database server
 issue.
 
-% DHCP4_DB_RECONNECT_LOST_CONNECTION database connection lost.
+% DHCP4_DB_RECONNECT_LOST_CONNECTION database connection lost: manager ID: %1, timer: %2.
 This info message indicates that the connection has been lost and the dhcp
 service might have been disabled, as specified in the configuration, in order to
 try to recover the connection.
@@ -232,7 +232,7 @@ occur. It prohibits the server from attempting to reconnect to its
 databases if connectivity is lost, and the server exits. This error
 should be reported.
 
-% DHCP4_DB_RECONNECT_SUCCEEDED database connection recovered.
+% DHCP4_DB_RECONNECT_SUCCEEDED database connection recovered: manager ID: %1, timer: %2.
 This info message indicates that the connection has been recovered and the dhcp
 service has been restored.
 
index dbbc728327925b291902cda665b78fc6441be2c0..8e2e57bcc90123de5c12bb7b24d41317015eafe7 100644 (file)
@@ -624,7 +624,7 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t server_port, uint16_t client_port,
     : io_service_(new IOService()), server_port_(server_port),
       client_port_(client_port), shutdown_(true),
       alloc_engine_(), use_bcast_(use_bcast),
-      network_state_(new NetworkState(NetworkState::DHCPv4)),
+      network_state_(new NetworkState()),
       cb_control_(new CBControlDHCPv4()),
       test_send_responses_to_source_(false) {
 
index 457eeb46a1cb78469eef708851cfa4b6d3eb7506..21e484e2de5cf95035c3f2135626725469ecef44 100644 (file)
@@ -260,6 +260,7 @@ ConstElementPtr
 ControlledDhcpv6Srv::commandConfigHashGetHandler(const string&,
                                                  ConstElementPtr /*args*/) {
     ConstElementPtr config = CfgMgr::instance().getCurrentCfg()->toElement();
+
     string hash = BaseCommandMgr::getHash(config);
 
     ElementPtr params = Element::createMap();
@@ -303,7 +304,7 @@ ControlledDhcpv6Srv::commandConfigWriteHandler(const string&,
         ConstElementPtr cfg = CfgMgr::instance().getCurrentCfg()->toElement();
         size = writeConfigFile(filename, cfg);
     } catch (const isc::Exception& ex) {
-        return (createAnswer(CONTROL_RESULT_ERROR, string("Error during write-config: ")
+        return (createAnswer(CONTROL_RESULT_ERROR, string("Error during config-write: ")
                              + ex.what()));
     }
     if (size == 0) {
@@ -804,6 +805,8 @@ ControlledDhcpv6Srv::commandStatusGetHandler(const string&,
     }
     status->set("sockets", sockets);
 
+    status->set("dhcp-state", network_state_->toElement());
+
     return (createAnswer(CONTROL_RESULT_SUCCESS, status));
 }
 
@@ -886,6 +889,8 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
         cfg_db->createManagers();
         // Reset counters related to connections as all managers have been recreated.
         srv->getNetworkState()->resetForDbConnection();
+        srv->getNetworkState()->resetForLocalCommands();
+        srv->getNetworkState()->resetForRemoteCommands();
     } catch (const std::exception& ex) {
         err << "Unable to open database: " << ex.what();
         return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
@@ -1283,10 +1288,12 @@ 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::DB_CONNECTION);
+        network_state_->disableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
-    LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_LOST_CONNECTION);
+    LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_LOST_CONNECTION)
+        .arg(db_reconnect_ctl->id())
+        .arg(db_reconnect_ctl->timerName());
 
     // If reconnect isn't enabled log it, initiate a shutdown if needed and
     // return false.
@@ -1294,7 +1301,9 @@ ControlledDhcpv6Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
         !db_reconnect_ctl->retryInterval()) {
         LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_DISABLED)
             .arg(db_reconnect_ctl->retriesLeft())
-            .arg(db_reconnect_ctl->retryInterval());
+            .arg(db_reconnect_ctl->retryInterval())
+            .arg(db_reconnect_ctl->id())
+            .arg(db_reconnect_ctl->timerName());
         if (db_reconnect_ctl->exitOnFailure()) {
             shutdownServer(EXIT_FAILURE);
         }
@@ -1313,11 +1322,14 @@ ControlledDhcpv6Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
     }
 
     // Enable service after the connection is recovered.
-    if (db_reconnect_ctl->alterServiceState()) {
-        network_state_->enableService(NetworkState::DB_CONNECTION);
+    if (db_reconnect_ctl->retriesLeft() != db_reconnect_ctl->maxRetries() &&
+        db_reconnect_ctl->alterServiceState()) {
+        network_state_->enableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
-    LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_SUCCEEDED);
+    LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_SUCCEEDED)
+        .arg(db_reconnect_ctl->id())
+        .arg(db_reconnect_ctl->timerName());
 
     db_reconnect_ctl->resetRetries();
 
@@ -1333,7 +1345,9 @@ ControlledDhcpv6Srv::dbFailedCallback(ReconnectCtlPtr db_reconnect_ctl) {
     }
 
     LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_FAILED)
-            .arg(db_reconnect_ctl->maxRetries());
+        .arg(db_reconnect_ctl->maxRetries())
+        .arg(db_reconnect_ctl->id())
+        .arg(db_reconnect_ctl->timerName());
 
     if (db_reconnect_ctl->exitOnFailure()) {
         shutdownServer(EXIT_FAILURE);
index 7a449c6b2e58f3d331010278ec0421997ccfe737..a02f172ee5ad3b7dbfc956cc4f8dfd922ba199a7 100644 (file)
@@ -209,11 +209,11 @@ const char* values[] = {
     "DHCP6_CONFIG_UNSUPPORTED_OBJECT", "DHCPv6 server configuration includes an unsupported object: %1",
     "DHCP6_CONFIG_UPDATE", "updated configuration received: %1",
     "DHCP6_DB_BACKEND_STARTED", "lease database started (type: %1, name: %2)",
-    "DHCP6_DB_RECONNECT_DISABLED", "database reconnect is disabled: max-reconnect-tries %1, reconnect-wait-time %2",
-    "DHCP6_DB_RECONNECT_FAILED", "maximum number of database reconnect attempts: %1, has been exhausted without success",
-    "DHCP6_DB_RECONNECT_LOST_CONNECTION", "database connection lost.",
+    "DHCP6_DB_RECONNECT_DISABLED", "database reconnect is disabled: retries left: %1, reconnect wait time: %2, manager ID: %3, timer: %4",
+    "DHCP6_DB_RECONNECT_FAILED", "maximum number of database reconnect attempts: %1, has been exhausted without success, manager ID: %2, timer: %3",
+    "DHCP6_DB_RECONNECT_LOST_CONNECTION", "database connection lost: manager ID: %1, timer: %2.",
     "DHCP6_DB_RECONNECT_NO_DB_CTL", "unexpected error in database reconnect",
-    "DHCP6_DB_RECONNECT_SUCCEEDED", "database connection recovered.",
+    "DHCP6_DB_RECONNECT_SUCCEEDED", "database connection recovered: manager ID: %1, timer: %2.",
     "DHCP6_DDNS_CREATE_ADD_NAME_CHANGE_REQUEST", "%1: created name change request: %2",
     "DHCP6_DDNS_FQDN_GENERATED", "%1: generated FQDN for the client: %2",
     "DHCP6_DDNS_GENERATED_FQDN_UPDATE_FAIL", "%1: failed to update the lease using address %2, after generating FQDN for a client, reason: %3",
index a20f16a3599d2ec9b160366736ddefaaf5db4205..aa045e5d0009f1ba52eb9425762db9445938ca90 100644 (file)
@@ -168,18 +168,18 @@ This informational message is printed every time the IPv6 DHCP server
 is started.  It indicates what database backend type is being to store
 lease and other information.
 
-% DHCP6_DB_RECONNECT_DISABLED database reconnect is disabled: max-reconnect-tries %1, reconnect-wait-time %2
+% DHCP6_DB_RECONNECT_DISABLED database reconnect is disabled: retries left: %1, reconnect wait time: %2, manager ID: %3, timer: %4
 This is an informational message indicating that connectivity to either the
 lease or host database or both and that automatic reconnect is not enabled.
 
-% DHCP6_DB_RECONNECT_FAILED maximum number of database reconnect attempts: %1, has been exhausted without success
+% DHCP6_DB_RECONNECT_FAILED maximum number of database reconnect attempts: %1, has been exhausted without success, manager ID: %2, timer: %3
 This error indicates that the server failed to reconnect to the lease and/or
 host database(s) after making the maximum configured number of reconnect
 attempts. This might cause the server to shut down as specified in the
 configuration. Loss of connectivity is typically a network or database server
 issue.
 
-% DHCP6_DB_RECONNECT_LOST_CONNECTION database connection lost.
+% DHCP6_DB_RECONNECT_LOST_CONNECTION database connection lost: manager ID: %1, timer: %2.
 This info message indicates that the connection has been lost and the dhcp
 service might have been disabled, as specified in the configuration, in order to
 try to recover the connection.
@@ -190,7 +190,7 @@ occur. It prohibits the server from attempting to reconnect to its
 databases if connectivity is lost, and the server exits. This error
 should be reported.
 
-% DHCP6_DB_RECONNECT_SUCCEEDED database connection recovered.
+% DHCP6_DB_RECONNECT_SUCCEEDED database connection recovered: manager ID: %1, timer: %2.
 This info message indicates that the connection has been recovered and the dhcp
 service has been restored.
 
index c4783d83c6b028bc4dbf223fe8cd59d1fe48040a..d8b0dd781393dc9fa70deb9490bcf5b5238a989e 100644 (file)
@@ -218,7 +218,7 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t server_port, uint16_t client_port)
     : io_service_(new IOService()), server_port_(server_port),
       client_port_(client_port), serverid_(), shutdown_(true),
       alloc_engine_(), name_change_reqs_(),
-      network_state_(new NetworkState(NetworkState::DHCPv6)),
+      network_state_(new NetworkState()),
       cb_control_(new CBControlDHCPv6()) {
     LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_OPEN_SOCKET)
         .arg(server_port);
index b1b148cc808f539d0c3a1cab2ca7cdab2fa759be..422e063696797ea75752e2494d02a9c0064c2de4 100644 (file)
@@ -355,7 +355,7 @@ TEST_F(CloseHATest, close4) {
 
     // Prepare objects.
     IOServicePtr io_service(new IOService());
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     Pkt4Ptr query(new Pkt4(DHCPREQUEST, 12345));
     HWAddrPtr hwaddr(new HWAddr(std::vector<uint8_t>(6, 1), HTYPE_ETHER));
     query->setHWAddr(hwaddr);
@@ -501,7 +501,7 @@ TEST_F(CloseHATest, close4Backup) {
 
     // Prepare objects.
     IOServicePtr io_service(new IOService());
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
 
     // Check that the state is computed on dhcp4_srv_configured.
     // It is first reset by the constructor and then adjusted by running the
@@ -592,7 +592,7 @@ TEST_F(CloseHATest, close6) {
 
     // Prepare objects.
     IOServicePtr io_service(new IOService());
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 12345));
     DuidPtr duid(new DUID(std::vector<uint8_t>(8, 2)));
     OptionPtr opt_duid(new Option(Option::V6, D6O_CLIENTID, duid->getDuid()));
@@ -738,7 +738,7 @@ TEST_F(CloseHATest, close6Backup) {
 
     // Prepare objects.
     IOServicePtr io_service(new IOService());
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
 
     // Check that the state is computed on dhcp6_srv_configured.
     // It is first reset by the constructor and then adjusted by running the
index 1508b5cc72067c28373379b9e3538629a12cc82f..ee272ba8d98d2a155269814ab9b332c2f78c900b 100644 (file)
@@ -121,7 +121,7 @@ public:
         ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
         // Starting the service is required prior to running any callouts.
-        NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+        NetworkStatePtr network_state(new NetworkState());
         ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                                 HAServerType::DHCPv4));
 
@@ -159,7 +159,7 @@ TEST_F(HAImplTest, startServices) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Network state is also required.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
 
     // Start the service for DHCPv4 server.
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
@@ -179,7 +179,7 @@ TEST_F(HAImplTest, startServices6) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Network state is also required.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
 
     // Start the service for DHCPv4 server.
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
@@ -203,7 +203,7 @@ TEST_F(HAImplTest, buffer4Receive) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -317,7 +317,7 @@ TEST_F(HAImplTest, subnet4Select) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -375,7 +375,7 @@ TEST_F(HAImplTest, subnet4SelectSharedNetwork) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -436,7 +436,7 @@ TEST_F(HAImplTest, subnet4SelectSingleRelationship) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -478,7 +478,7 @@ TEST_F(HAImplTest, subnet4SelectDropNoServerName) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -524,7 +524,7 @@ TEST_F(HAImplTest, subnet4SelectDropInvalidServerNameType) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -574,7 +574,7 @@ TEST_F(HAImplTest, subnet4SelectDropNotInScope) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -627,7 +627,7 @@ TEST_F(HAImplTest, subnet4SelectNoSubnet) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -674,7 +674,7 @@ TEST_F(HAImplTest, buffer6Receive) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -765,7 +765,7 @@ TEST_F(HAImplTest, subnet6Select) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -820,7 +820,7 @@ TEST_F(HAImplTest, subnet6SelectSharedNetwork) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -881,7 +881,7 @@ TEST_F(HAImplTest, subnet6SelectSingleRelationship) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -923,7 +923,7 @@ TEST_F(HAImplTest, subnet6SelectDropNoServerName) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -969,7 +969,7 @@ TEST_F(HAImplTest, subnet6SelectDropInvalidServerNameType) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -1019,7 +1019,7 @@ TEST_F(HAImplTest, subnet6SelectDropNotInScope) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -1072,7 +1072,7 @@ TEST_F(HAImplTest, subnet6SelectNoSubnet) {
     ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -1115,7 +1115,7 @@ TEST_F(HAImplTest, leases4Committed) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -1202,7 +1202,7 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationships) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -1259,7 +1259,7 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsNoServerName) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -1312,7 +1312,7 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsInvalidServerName) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -1367,7 +1367,7 @@ TEST_F(HAImplTest, leases6Committed) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -1453,7 +1453,7 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationships) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -1509,7 +1509,7 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsNoServerName) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -1561,7 +1561,7 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsInvalidServerName) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv6));
 
@@ -1693,7 +1693,7 @@ TEST_F(HAImplTest, continueHandler) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -1723,7 +1723,7 @@ TEST_F(HAImplTest, continueHandlerWithNoServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -1748,7 +1748,7 @@ TEST_F(HAImplTest, continueHandlerWithWrongServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -1778,7 +1778,7 @@ TEST_F(HAImplTest, statusGet) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -1841,7 +1841,7 @@ TEST_F(HAImplTest, statusGetBackupServer) {
     test_ha_impl_->config_->get()->setThisServerName("server3");
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -1891,7 +1891,7 @@ TEST_F(HAImplTest, statusGetPassiveBackup) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidPassiveBackupJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -1941,7 +1941,7 @@ TEST_F(HAImplTest, statusGetHubAndSpoke) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
@@ -2027,7 +2027,7 @@ TEST_F(HAImplTest, maintenanceNotify) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2060,7 +2060,7 @@ TEST_F(HAImplTest, maintenanceNotifyNoServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2092,7 +2092,7 @@ TEST_F(HAImplTest, maintenanceNotifyBadServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2125,7 +2125,7 @@ TEST_F(HAImplTest, haReset) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2157,7 +2157,7 @@ TEST_F(HAImplTest, haResetNoServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2186,7 +2186,7 @@ TEST_F(HAImplTest, haResetBadServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2218,7 +2218,7 @@ TEST_F(HAImplTest, haHeartbeat) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2250,7 +2250,7 @@ TEST_F(HAImplTest, haHeartbeatNoServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2279,7 +2279,7 @@ TEST_F(HAImplTest, haHeartbeatBadServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2312,7 +2312,7 @@ TEST_F(HAImplTest, haSyncCompleteNotifyOriginId) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2357,7 +2357,7 @@ TEST_F(HAImplTest, haSyncCompleteNotifyOrigin) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2401,7 +2401,7 @@ TEST_F(HAImplTest, haSyncCompleteNotifyNoServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2431,7 +2431,7 @@ TEST_F(HAImplTest, haSyncCompleteNotifyBadServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2463,7 +2463,7 @@ TEST_F(HAImplTest, haScopes) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2496,7 +2496,7 @@ TEST_F(HAImplTest, haScopesNoServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2528,7 +2528,7 @@ TEST_F(HAImplTest, haScopesBadServerName) {
     ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(ha_impl_->startServices(network_state,
                                             HAServerType::DHCPv4));
 
@@ -2562,7 +2562,7 @@ TEST_F(HAImplTest, lease4ServerDecline) {
     ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
-    NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+    NetworkStatePtr network_state(new NetworkState());
     ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
                                                  HAServerType::DHCPv4));
 
index bf07480c65068436bf04b20e2a8e6e3b458710b8..350df09a7116fc180e9a16376e7fb233cf2b85ac 100644 (file)
@@ -52,7 +52,7 @@ namespace test {
 
 HATest::HATest()
     : io_service_(new IOService()),
-      network_state_(new NetworkState(NetworkState::DHCPv4)) {
+      network_state_(new NetworkState()) {
 }
 
 HATest::~HATest() {
index fc5bb0df991ca7880ee76b995aba4b633c1c10cd..5a3f74f2898f99017720e7bf983472e19af98c8b 100644 (file)
@@ -2902,8 +2902,10 @@ public:
         }
 
         bool reopened = false;
+        bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -2913,10 +2915,8 @@ public:
             // Something is definitely wrong. Did the configuration change
             // somehow and there is no configuration for CB?
             if (!config_ctl) {
-                std::string reason("No CB configuration found!");
-                LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_ATTEMPT_FAILED4)
-                        .arg(reason);
-                return (true);
+                do_exit = true;
+                isc_throw(Unexpected, "No CB configuration found!");
             }
 
             // Iterate over the configured DBs and instantiate them.
@@ -2932,6 +2932,9 @@ public:
         } catch (const std::exception& ex) {
             LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_ATTEMPT_FAILED4)
                     .arg(ex.what());
+            if (do_exit) {
+                return (true);
+            }
         }
 
         if (reopened) {
@@ -2945,7 +2948,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_FAILED4)
                         .arg(db_reconnect_ctl->maxRetries());
index fa3b457fff337397ae5c2e4652246cc7585bd63e..8b59ae725dbc8255b63ec5f27ff040da73fad65d 100644 (file)
@@ -3329,8 +3329,10 @@ public:
         }
 
         bool reopened = false;
+        bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -3340,10 +3342,8 @@ public:
             // Something is definitely wrong. Did the configuration change
             // somehow and there is no configuration for CB?
             if (!config_ctl) {
-                std::string reason("No CB configuration found!");
-                LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_ATTEMPT_FAILED6)
-                        .arg(reason);
-                return (true);
+                do_exit = true;
+                isc_throw(Unexpected, "No CB configuration found!");
             }
 
             // Iterate over the configured DBs and instantiate them.
@@ -3359,6 +3359,9 @@ public:
         } catch (const std::exception& ex) {
             LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_ATTEMPT_FAILED6)
                     .arg(ex.what());
+            if (do_exit) {
+                return (true);
+            }
         }
 
         if (reopened) {
@@ -3372,7 +3375,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_FAILED6)
                         .arg(db_reconnect_ctl->maxRetries());
index 4e1475b3636dd88f98d3d0e78794935d58adcd2c..3a41d6fe11245ed69b8ad166cce518e4d3978ec4 100644 (file)
@@ -11,6 +11,7 @@
 #include <asiolink/io_address.h>
 #include <config_backend/constants.h>
 #include <dhcp/option_space.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <util/buffer.h>
 
@@ -68,7 +69,7 @@ MySqlConfigBackendImpl(const std::string& space,
     MySqlConnection::ensureSchemaVersion(parameters, db_reconnect_callback, timer_name_);
 
     // Create ReconnectCtl for this connection.
-    conn_.makeReconnectCtl(timer_name_);
+    conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 21);
 
     // Open the database.
     conn_.openDatabase();
index fe309301aa9df3b3c1719c26e77dfe5ecb3dddd6..27cc323c5d9839a5c3521bda84fa62e71bdbb034 100644 (file)
@@ -2707,8 +2707,10 @@ public:
         }
 
         bool reopened = false;
+        bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -2718,10 +2720,8 @@ public:
             // Something is definitely wrong. Did the configuration change
             // somehow and there is no configuration for CB?
             if (!config_ctl) {
-                std::string reason("No CB configuration found!");
-                LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_ATTEMPT_FAILED4)
-                        .arg(reason);
-                return (true);
+                do_exit = true;
+                isc_throw(Unexpected, "No CB configuration found!");
             }
 
             // Iterate over the configured DBs and instantiate them.
@@ -2737,6 +2737,9 @@ public:
         } catch (const std::exception& ex) {
             LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_ATTEMPT_FAILED4)
                     .arg(ex.what());
+            if (do_exit) {
+                return (true);
+            }
         }
 
         if (reopened) {
@@ -2750,7 +2753,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_FAILED4)
                         .arg(db_reconnect_ctl->maxRetries());
index 28fcc1b2cce84b601c5f13c33d35d13bb3932351..3e6be7ba09b4ddc329e35db1602ecf15d98773dd 100644 (file)
@@ -3029,8 +3029,10 @@ public:
         }
 
         bool reopened = false;
+        bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -3040,10 +3042,8 @@ public:
             // Something is definitely wrong. Did the configuration change
             // somehow and there is no configuration for CB?
             if (!config_ctl) {
-                std::string reason("No CB configuration found!");
-                LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_ATTEMPT_FAILED6)
-                        .arg(reason);
-                return (true);
+                do_exit = true;
+                isc_throw(Unexpected, "No CB configuration found!");
             }
 
             // Iterate over the configured DBs and instantiate them.
@@ -3059,6 +3059,9 @@ public:
         } catch (const std::exception& ex) {
             LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_ATTEMPT_FAILED6)
                     .arg(ex.what());
+            if (do_exit) {
+                return (true);
+            }
         }
 
         if (reopened) {
@@ -3072,7 +3075,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_FAILED6)
                         .arg(db_reconnect_ctl->maxRetries());
index 76a643458f49007e57736f850fc95ae606ae944d..75ddd0efd6596f4354b031e9bd246bd7f47393bf 100644 (file)
@@ -10,6 +10,7 @@
 #include <config_backend/constants.h>
 #include <database/db_exceptions.h>
 #include <dhcp/option_space.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <pgsql/pgsql_exchange.h>
 #include <util/buffer.h>
@@ -113,7 +114,7 @@ PgSqlConfigBackendImpl::PgSqlConfigBackendImpl(const std::string& space,
     PgSqlConnection::ensureSchemaVersion(parameters, db_reconnect_callback, timer_name_);
 
     // Create ReconnectCtl for this connection.
-    conn_.makeReconnectCtl(timer_name_);
+    conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 22);
 
     // Open the database.
     conn_.openDatabase();
index 607c706376236b4547e2b626634370f26fd707c3..6a79340f4aa10f36d32ff6ae902421bc1db28de4 100644 (file)
@@ -148,7 +148,7 @@ DatabaseConnection::configuredReadOnly() const {
 }
 
 void
-DatabaseConnection::makeReconnectCtl(const std::string& timer_name) {
+DatabaseConnection::makeReconnectCtl(const std::string& timer_name, unsigned int id) {
     string type = "unknown";
     unsigned int retries = 0;
     unsigned int interval = 0;
@@ -184,7 +184,7 @@ DatabaseConnection::makeReconnectCtl(const std::string& timer_name) {
     }
 
     reconnect_ctl_ = boost::make_shared<ReconnectCtl>(type, timer_name, retries,
-                                                      interval, action);
+                                                      interval, action, id);
 }
 
 bool
index 4729ade919ab37c2216ead41e57aad65b8f45db2..510cda6ad8fea9dc1a268904d5429e8960234c96 100644 (file)
@@ -56,7 +56,6 @@ public:
         isc::Exception(file, line, what) {}
 };
 
-
 /// @brief Invalid type exception
 ///
 /// Thrown when the factory doesn't recognize the type of the backend.
@@ -100,7 +99,6 @@ public:
         isc::Exception(file, line, what) {}
 };
 
-
 /// @brief Defines a callback prototype for propagating events upward
 typedef std::function<bool (util::ReconnectCtlPtr db_reconnect_ctl)> DbCallback;
 
@@ -149,13 +147,14 @@ public:
     }
 
     /// @brief Destructor
-    virtual ~DatabaseConnection(){};
+    virtual ~DatabaseConnection(){}
 
     /// @brief Instantiates a ReconnectCtl based on the connection's
     /// reconnect parameters
     ///
     /// @param timer_name of the timer used for the ReconnectCtl object.
-    virtual void makeReconnectCtl(const std::string& timer_name);
+    /// @param id the ID of the manager.
+    virtual void makeReconnectCtl(const std::string& timer_name, unsigned int id);
 
     /// @brief The reconnect settings.
     ///
@@ -309,7 +308,7 @@ private:
     /// @brief Reconnect settings.
     util::ReconnectCtlPtr reconnect_ctl_;
 
-    /// The IOService object, used for all ASIO operations.
+    /// @brief The IOService object, used for all ASIO operations.
     static isc::asiolink::IOServicePtr io_service_;
 };
 
index 53a71c1a7a0443ed11de257a9eded21f3b4af276..d8fec9e6593a5892eef9608e6465a24bc42e32b3 100644 (file)
@@ -108,7 +108,7 @@ TEST_F(DatabaseConnectionCallbackTest, NoDbLostCallback) {
     pmap[std::string("max-reconnect-tries")] = std::string("3");
     pmap[std::string("reconnect-wait-time")] = std::string("60000");
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
 
     bool ret = false;
     ASSERT_NO_THROW(ret = DatabaseConnection::invokeDbLostCallback(datasrc.reconnectCtl()));
@@ -126,7 +126,7 @@ TEST_F(DatabaseConnectionCallbackTest, NoDbRecoveredCallback) {
     pmap[std::string("max-reconnect-tries")] = std::string("3");
     pmap[std::string("reconnect-wait-time")] = std::string("60000");
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
 
     bool ret = false;
     ASSERT_NO_THROW(ret = DatabaseConnection::invokeDbRecoveredCallback(datasrc.reconnectCtl()));
@@ -144,7 +144,7 @@ TEST_F(DatabaseConnectionCallbackTest, NoDbFailedCallback) {
     pmap[std::string("max-reconnect-tries")] = std::string("3");
     pmap[std::string("reconnect-wait-time")] = std::string("60000");
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
 
     bool ret = false;
     ASSERT_NO_THROW(ret = DatabaseConnection::invokeDbFailedCallback(datasrc.reconnectCtl()));
@@ -170,7 +170,7 @@ TEST_F(DatabaseConnectionCallbackTest, dbLostCallback) {
         std::bind(&DatabaseConnectionCallbackTest::dbLostCallback, this, ph::_1);
     /// Create the connection..
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
     bool ret = false;
 
     /// We should be able to invoke the callback and get
@@ -218,7 +218,7 @@ TEST_F(DatabaseConnectionCallbackTest, dbRecoveredCallback) {
         std::bind(&DatabaseConnectionCallbackTest::dbRecoveredCallback, this, ph::_1);
     /// Create the connection..
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
     bool ret = false;
 
     /// We should be able to invoke the callback and get
@@ -281,7 +281,7 @@ TEST_F(DatabaseConnectionCallbackTest, dbFailedCallback) {
         std::bind(&DatabaseConnectionCallbackTest::dbFailedCallback, this, ph::_1);
     /// Create the connection..
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
     bool ret = false;
 
     /// We should be able to invoke the callback and get
index 3991e223962158a96e91391061f46fba9cb38439..cbe572792b6f685b80fbeb5b41fe6ad46083eaad 100644 (file)
@@ -215,7 +215,7 @@ ReconnectCtlPtr CfgIface::makeReconnectCtl() const {
     auto reconnect_ctl = boost::make_shared<ReconnectCtl>("Socket", timer_name,
                                                           CfgIface::getServiceSocketsMaxRetries(),
                                                           CfgIface::getServiceSocketsRetryWaitTime(),
-                                                          on_fail_action);
+                                                          on_fail_action, 0);
 
     return (reconnect_ctl);
 }
index 317e623ff9aab0ae116cf0ce633ea382e7a9298f..4a8fab5b45e940a29b36facb0100f500c2ced831 100644 (file)
@@ -18,6 +18,7 @@
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/host_mgr.h>
 #include <dhcpsrv/mysql_host_data_source.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <util/buffer.h>
 #include <util/multi_threading_mgr.h>
@@ -2929,7 +2930,7 @@ MySqlHostDataSourceImpl::createContext() const {
     ctx->host_option_exchange_.reset(new MySqlOptionExchange());
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 11);
 
     return (ctx);
 }
@@ -2949,6 +2950,7 @@ MySqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -2977,7 +2979,7 @@ MySqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(dhcpsrv_logger, DHCPSRV_MYSQL_HOST_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -3017,7 +3019,7 @@ MySqlHostDataSourceImpl::getVersion(const std::string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&MySqlHostDataSourceImpl::dbReconnect);
 
-    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 11));
 }
 
 void
@@ -4079,7 +4081,7 @@ MySqlHostDataSource::getDescription() const {
 
 std::pair<uint32_t, uint32_t>
 MySqlHostDataSource::getVersion(const std::string& timer_name) const {
-    return(impl_->getVersion(timer_name));
+    return (impl_->getVersion(timer_name));
 }
 
 void
index b403d66ae19d86a914223e39d32a124d30d7c6f7..0f4fc005e6bb0e83348c89e30c87c90775502cde 100644 (file)
@@ -14,6 +14,7 @@
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/lease_mgr_factory.h>
 #include <dhcpsrv/mysql_lease_mgr.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <mysql/mysql_connection.h>
 #include <util/multi_threading_mgr.h>
@@ -2204,6 +2205,7 @@ MySqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -2226,7 +2228,7 @@ MySqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(dhcpsrv_logger, DHCPSRV_MYSQL_LEASE_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -2268,7 +2270,7 @@ MySqlLeaseMgr::createContext() const {
         &MySqlLeaseMgr::dbReconnect));
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 1);
 
     // Open the database.
     ctx->conn_.openDatabase();
@@ -3861,7 +3863,7 @@ MySqlLeaseMgr::getVersion(const string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&MySqlLeaseMgr::dbReconnect);
 
-    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 1));
 }
 
 void
index 97e84dba50abfa341146d3707604fd137a2e3754..e6ce7690b458d76ab7cbf3bd825950d5ce24281f 100644 (file)
 #include <string>
 #include <unordered_set>
 
+using namespace isc::data;
 using namespace isc::util;
 
 namespace isc {
 namespace dhcp {
 
 /// @brief Implementation of the @c NetworkState class.
-class NetworkStateImpl : public boost::enable_shared_from_this<NetworkStateImpl> {
+class NetworkStateImpl : public boost::enable_shared_from_this<NetworkStateImpl>,
+                         public CfgToElement {
 public:
 
     /// @brief Constructor.
-    NetworkStateImpl(const NetworkState::ServerType& server_type)
-        : server_type_(server_type), globally_disabled_(false),
-          disabled_subnets_(), disabled_networks_(),
-          timer_mgr_(TimerMgr::instance()), disabled_by_origin_(),
-          disabled_by_db_connection_(0) {
+    NetworkStateImpl() : globally_disabled_(false), disabled_subnets_(),
+          disabled_networks_(), timer_mgr_(TimerMgr::instance()),
+          disabled_by_origin_() {
     }
 
     /// @brief Destructor.
@@ -56,23 +56,11 @@ public:
         if (disable) {
             // Disable the service for any flag.
             globally_disabled_ = true;
-            if (origin == NetworkState::DB_CONNECTION) {
-                ++disabled_by_db_connection_;
-            } else {
-                disabled_by_origin_.insert(origin);
-            }
+            disabled_by_origin_.insert(origin);
         } else {
-            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_;
-                }
-            } else {
-                disabled_by_origin_.erase(origin);
-            }
+            disabled_by_origin_.erase(origin);
             // Enable the service only if all flags have been cleared.
-            if (disabled_by_origin_.empty() && disabled_by_db_connection_ == 0) {
+            if (disabled_by_origin_.empty()) {
                 globally_disabled_ = false;
             }
         }
@@ -82,7 +70,44 @@ public:
     ///
     /// @note The dhcp service will remain disabled until all flags are cleared.
     void resetForDbConnection() {
-        disabled_by_db_connection_ = 0;
+        auto disabled_by_origin = disabled_by_origin_;
+        for (auto const& origin : disabled_by_origin) {
+            if (origin >= NetworkState::DB_CONNECTION) {
+                disabled_by_origin_.erase(origin);
+            }
+        }
+        if (disabled_by_origin_.empty()) {
+            globally_disabled_ = false;
+        }
+    }
+
+    /// @brief Reset origin for local commands.
+    ///
+    /// @note The dhcp service will remain disabled until all flags are cleared.
+    void resetForLocalCommands() {
+        auto disabled_by_origin = disabled_by_origin_;
+        for (auto const& origin : disabled_by_origin) {
+            if (origin >= NetworkState::HA_LOCAL_COMMAND &&
+                origin < NetworkState::HA_REMOTE_COMMAND) {
+                disabled_by_origin_.erase(origin);
+            }
+        }
+        if (disabled_by_origin_.empty()) {
+            globally_disabled_ = false;
+        }
+    }
+
+    /// @brief Reset origin for remote commands.
+    ///
+    /// @note The dhcp service will remain disabled until all flags are cleared.
+    void resetForRemoteCommands() {
+        auto disabled_by_origin = disabled_by_origin_;
+        for (auto const& origin : disabled_by_origin) {
+            if (origin >= NetworkState::HA_REMOTE_COMMAND &&
+                origin < NetworkState::DB_CONNECTION) {
+                disabled_by_origin_.erase(origin);
+            }
+        }
         if (disabled_by_origin_.empty()) {
             globally_disabled_ = false;
         }
@@ -109,7 +134,7 @@ public:
     /// @param origin The origin of the state transition.
     void createTimer(const unsigned int seconds, unsigned int origin) {
         destroyTimer(origin);
-        if (origin == NetworkState::DB_CONNECTION) {
+        if (origin >= NetworkState::DB_CONNECTION) {
             isc_throw(BadValue, "DB connection does not support delayed enable");
         }
         auto timer_name = getTimerName(origin);
@@ -125,7 +150,7 @@ public:
     ///
     /// @param origin The origin of the state transition.
     void destroyTimer(unsigned int origin) {
-        if (origin == NetworkState::DB_CONNECTION) {
+        if (origin >= NetworkState::DB_CONNECTION) {
             return;
         }
         auto timer_name = getTimerName(origin);
@@ -144,8 +169,38 @@ public:
         return (timer_name.str());
     }
 
-    /// @brief Server type.
-    NetworkState::ServerType server_type_;
+    /// @brief The network state as Element.
+    ///
+    /// @return The network state as Element.
+    virtual ElementPtr toElement() const {
+        ElementPtr result = Element::createMap();
+        result->set("globally-disabled", Element::create(globally_disabled_));
+        bool disabled_by_user = false;
+        ElementPtr local_origin = Element::createList();
+        ElementPtr remote_origin = Element::createList();
+        ElementPtr db_origin = Element::createList();
+        std::set<unsigned int> ordered(disabled_by_origin_.begin(), disabled_by_origin_.end());
+        for (auto const& origin : ordered) {
+            if (origin == NetworkState::USER_COMMAND) {
+                disabled_by_user = true;
+            }
+            if (origin >= NetworkState::HA_LOCAL_COMMAND && origin < NetworkState::HA_REMOTE_COMMAND) {
+                local_origin->add(Element::create(origin));
+            }
+            if (origin >= NetworkState::HA_REMOTE_COMMAND && origin < NetworkState::DB_CONNECTION) {
+                remote_origin->add(Element::create(origin));
+            }
+            if (origin >= NetworkState::DB_CONNECTION) {
+                db_origin->add(Element::create(origin));
+            }
+        }
+        result->set("disabled-by-user", Element::create(disabled_by_user));
+        result->set("disabled-by-local-command", local_origin);
+        result->set("disabled-by-remote-command", remote_origin);
+        result->set("disabled-by-db-connection", db_origin);
+
+        return (result);
+    }
 
     /// @brief A flag indicating if DHCP service is globally disabled.
     bool globally_disabled_;
@@ -164,14 +219,10 @@ public:
 
     /// @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.
-    uint32_t disabled_by_db_connection_;
 };
 
-NetworkState::NetworkState(const NetworkState::ServerType& server_type)
-    : impl_(new NetworkStateImpl(server_type)), mutex_(new std::mutex()) {
+NetworkState::NetworkState()
+    : impl_(new NetworkStateImpl()), mutex_(new std::mutex()) {
 }
 
 void
@@ -192,6 +243,18 @@ NetworkState::resetForDbConnection() {
     impl_->resetForDbConnection();
 }
 
+void
+NetworkState::resetForLocalCommands() {
+    MultiThreadingLock lock(*mutex_);
+    impl_->resetForLocalCommands();
+}
+
+void
+NetworkState::resetForRemoteCommands() {
+    MultiThreadingLock lock(*mutex_);
+    impl_->resetForRemoteCommands();
+}
+
 void
 NetworkState::delayedEnableService(const unsigned int seconds, unsigned int origin) {
     MultiThreadingLock lock(*mutex_);
@@ -234,5 +297,10 @@ NetworkState::selectiveEnable(const NetworkState::Networks&) {
     isc_throw(NotImplemented, "selectiveEnableService is not implemented");
 }
 
+ElementPtr NetworkState::toElement() const {
+    MultiThreadingLock lock(*mutex_);
+    return (impl_->toElement());
+}
+
 } // end of namespace isc::dhcp
 } // end of namespace isc
index 861d1a78cb33440e776fc5c863ac3a3e04436946..7004375c8f74a1ea16070af002d1ae3a5ab3554d 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef NETWORK_STATE_H
 #define NETWORK_STATE_H
 
+#include <cc/cfg_to_element.h>
 #include <cc/data.h>
 #include <dhcpsrv/subnet_id.h>
 #include <boost/scoped_ptr.hpp>
@@ -57,10 +58,7 @@ class NetworkStateImpl;
 ///
 /// 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.
+/// is restored.
 ///
 /// @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
@@ -68,15 +66,9 @@ class NetworkStateImpl;
 /// 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 {
+class NetworkState : public isc::data::CfgToElement {
 public:
 
-    /// @brief DHCP server type.
-    enum ServerType {
-        DHCPv4,
-        DHCPv6
-    };
-
     /// @brief Origin of the network state transition.
     ///
     /// The enumeration indicates the originator of the state transition of the
@@ -113,7 +105,7 @@ public:
     typedef std::set<std::string> Networks;
 
     /// @brief Constructor.
-    NetworkState(const ServerType& server_type);
+    NetworkState();
 
     /// @brief Disable the DHCP service state for respective transition origin.
     ///
@@ -139,6 +131,18 @@ public:
     /// all other origins is enabled.
     void resetForDbConnection();
 
+    /// @brief Reset origins for local commands.
+    ///
+    /// It results in enabling the network service if network service for
+    /// all other origins is enabled.
+    void resetForLocalCommands();
+
+    /// @brief Reset origins for remote commands.
+    ///
+    /// It results in enabling the network service if network service for
+    /// all other origins is enabled.
+    void resetForRemoteCommands();
+
     /// @brief Schedules enabling DHCP service in the future.
     ///
     /// @param seconds Number of seconds after which the service should be enabled
@@ -196,6 +200,11 @@ public:
     /// @throw isc::NotImplemented
     void selectiveEnable(const NetworkState::Networks& networks);
 
+    /// @brief The network state as Element.
+    ///
+    /// @return The network state as Element.
+    virtual isc::data::ElementPtr toElement() const;
+
     //@}
 
 private:
index 5732f74d9978dc894a909a56124be156084f5c0a..6501f60aadcf088fb08d973255fbe1f4ced50f35 100644 (file)
@@ -17,6 +17,7 @@
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/host_mgr.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/pgsql_host_data_source.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <util/buffer.h>
@@ -2342,7 +2343,7 @@ PgSqlHostDataSourceImpl::createContext() const {
     ctx->host_option_exchange_.reset(new PgSqlOptionExchange());
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 12);
 
     return (ctx);
 }
@@ -2362,6 +2363,7 @@ PgSqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -2390,7 +2392,7 @@ PgSqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(dhcpsrv_logger, DHCPSRV_PGSQL_HOST_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -2616,7 +2618,7 @@ PgSqlHostDataSourceImpl::getVersion(const std::string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&PgSqlHostDataSourceImpl::dbReconnect);
 
-    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 12));
 }
 
 void
@@ -3295,7 +3297,7 @@ PgSqlHostDataSource::getDescription() const {
 
 std::pair<uint32_t, uint32_t>
 PgSqlHostDataSource::getVersion(const std::string& timer_name) const {
-    return(impl_->getVersion(timer_name));
+    return (impl_->getVersion(timer_name));
 }
 
 void
index c860ebbf6bead9fc5a5f99b3bf8f98afd571885e..7bb7bf30e4ae56e94ecc78a95851081f365f63b4 100644 (file)
@@ -14,6 +14,7 @@
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/dhcpsrv_exceptions.h>
 #include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/pgsql_lease_mgr.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <util/multi_threading_mgr.h>
@@ -1667,6 +1668,7 @@ PgSqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -1689,7 +1691,7 @@ PgSqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(dhcpsrv_logger, DHCPSRV_PGSQL_LEASE_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -1731,7 +1733,7 @@ PgSqlLeaseMgr::createContext() const {
         &PgSqlLeaseMgr::dbReconnect));
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 2);
 
     // Open the database.
     ctx->conn_.openDatabase();
@@ -3030,7 +3032,7 @@ PgSqlLeaseMgr::getVersion(const string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&PgSqlLeaseMgr::dbReconnect);
 
-    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 2));
 }
 
 void
index 84f26c6ee3591b7ae95bff7dc40d6f72fd61504a..3be9adb3c160145970588c04694a01f4f98c6adc 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2024 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
@@ -18,7 +18,7 @@ using namespace isc::asiolink;
 using namespace isc::dhcp;
 using namespace isc::util;
 
-namespace  {
+namespace {
 
 /// @brief Test fixture class for @c NetworkState class.
 class NetworkStateTest : public ::testing::Test {
@@ -46,49 +46,39 @@ public:
     /// @brief This test verifies the default is enable state.
     void defaultTest();
 
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv4
+    /// @brief This test verifies that it is possible to disable and then enable
     /// service using 'user command' origin.
-    void disableEnableService4UsingUserCommandOriginTest();
+    void disableEnableServiceUsingUserCommandOriginTest();
 
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv4
-    /// service using 'HA command' origin.
-    void disableEnableService4UsingHACommandOriginTest();
+    /// @brief This test verifies that it is possible to disable and then enable
+    /// service using 'HA local command' origin.
+    void disableEnableServiceUsingHALocalCommandOriginTest();
 
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv4
-    /// service using 'DB connection' origin.
-    void disableEnableService4UsingDBConnectionOriginTest();
+    /// @brief This test verifies that it is possible to disable and then enable
+    /// service using 'HA remote command' origin.
+    void disableEnableServiceUsingHARemoteCommandOriginTest();
 
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv4
-    /// service using a combination of origins.
-    /// 1. Disable using 'user command' origin 2 times (expect disabled state).
-    /// 2. Disable using 'HA command' origin 2 times (expect disabled state).
-    /// 3. Disable using 'DB connection' origin 2 times (expect disabled state).
-    /// 4. Enable using 'user command' origin 1 time (expect disabled state).
-    /// 5. Enable using 'HA command' origin 1 time (expect disabled state).
-    /// 6. Enable using 'DB connection' origin 2 times (expect enabled state).
-    void disableEnableService4UsingMultipleOriginsTest();
-
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv6
-    /// service using 'user command' origin.
-    void disableEnableService6UsingUserCommandOriginTest();
-
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv6
-    /// service using 'HA command' origin.
-    void disableEnableService6UsingHACommandOriginTest();
-
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv6
+    /// @brief This test verifies that it is possible to disable and then enable
     /// service using 'DB connection' origin.
-    void disableEnableService6UsingDBConnectionOriginTest();
+    void disableEnableServiceUsingDBConnectionOriginTest();
 
-    /// @brief This test verifies that it is possible to disable and then enable DHCPv6
+    /// @brief This test verifies that it is possible to disable and then enable
     /// service using a combination of origins.
-    /// 1. Disable using 'user command' origin 2 times (expect disabled state).
-    /// 2. Disable using 'HA command' origin 2 times (expect disabled state).
-    /// 3. Disable using 'DB connection' origin 2 times (expect disabled state).
-    /// 4. Enable using 'user command' origin 1 time (expect disabled state).
-    /// 5. Enable using 'HA command' origin 1 time (expect disabled state).
-    /// 6. Enable using 'DB connection' origin 2 times (expect enabled state).
-    void disableEnableService6UsingMultipleOriginsTest();
+    // 1. Disable using 'user command' origin 2 times (expect disabled state).
+    // 2. Disable using 'HA local command' origin 2 times (expect disabled state).
+    // 3. Disable using 'HA local command' origin 1 time different id (expect disabled state).
+    // 4. Disable using 'HA remote command' origin 2 times (expect disabled state).
+    // 5. Disable using 'HA remote command' origin 1 time different id (expect disabled state).
+    // 6. Disable using 'DB connection' origin 2 times (expect disabled state).
+    // 7. Disable using 'DB connection' origin 1 time different id (expect disabled state).
+    // 8. Enable using 'user command' origin 1 time (expect disabled state).
+    // 9. Enable using 'HA local command' origin 1 time (expect disabled state).
+    // 10. Enable using 'HA local command' origin 1 time different id (expect disabled state).
+    // 11. Enable using 'HA remote command' origin 1 time (expect disabled state).
+    // 12. Enable using 'HA remote command' origin 1 time different id (expect disabled state).
+    // 13. Enable using 'DB connection' origin 1 times (expect disabled state).
+    // 14. Enable using 'DB connection' origin 1 time different id (expect disabled state).
+    void disableEnableServiceUsingMultipleOriginsTest();
 
     /// @brief This test verifies that reset works, so that internal state is reset after
     /// all managers are recreated.
@@ -104,26 +94,92 @@ public:
 
     /// @brief This test verifies that reset works, so that internal state is reset after
     /// all managers are recreated.
-    /// 1. Disable using 'user command' origin 1 time (expect disabled state).
-    /// 2. Disable using 'HA command' origin 3 times (expect disabled state).
-    /// 3. Disable using 'DB connection' origin 1 time (expect disabled state).
-    /// 4. Reset using 'HA command' origin (expect disabled state).
-    /// 5. Enable using 'user command' origin 1 time (expect disabled state).
-    /// 6. Enable using 'DB connection' origin 1 time (expect enabled state).
-    /// 7. Disable using 'HA command' origin 3 times (expect disabled state).
-    /// 8. Reset using 'HA command' origin (expect enabled state).
-    void resetUsingHACommandOriginTest();
+    // 1. Disable using 'user command' origin 1 time (expect disabled state).
+    // 2. Disable using 'HA local command' origin 3 times with same id (expect disabled state).
+    // 3. Disable using 'DB connection' origin 1 time (expect disabled state).
+    // 4. Disable using 'HA remote command' origin 1 time (expect disabled state).
+    // 5. Enable using 'HA local command' origin (expect disabled state).
+    // 6. Enable using 'user command' origin 1 time (expect disabled state).
+    // 7. Enable using 'HA remote command' origin 1 time (expect disabled state).
+    // 8. Enable using 'DB connection' origin 1 time (expect enabled state).
+    // 9. Disable using 'user command' origin 1 time (expect disabled state).
+    // 10. Disable using 'HA local command' origin 3 times with different ids (expect disabled state).
+    // 11. Disable using 'DB connection' origin 1 time (expect disabled state).
+    // 12. Disable using 'HA remote command' origin 1 time (expect disabled state).
+    // 13. Enable using 'user command' origin 1 time (expect disabled state).
+    // 14. Enable using 'HA remote command' origin 1 time (expect disabled state).
+    // 15. Enable using 'DB connection' origin 1 time (expect disabled state).
+    // 16. Enable using 'HA local command' origin 3 times with different ids (expect enabled state).
+    // 17. Disable using 'user command' origin 1 time (expect disabled state).
+    // 18. Disable using 'HA local command' origin 3 times with different ids (expect disabled state).
+    // 19. Disable using 'DB connection' origin 1 time (expect disabled state).
+    // 20. Disable using 'HA remote command' origin 1 time (expect disabled state).
+    // 21. Enable using 'user command' origin 1 time (expect disabled state).
+    // 22. Enable using 'HA remote command' origin 1 time (expect disabled state).
+    // 23. Enable using 'DB connection' origin 1 time (expect disabled state).
+    // 24. Reset using 'HA local command' origin (expect enabled state).
+    // 25. Disable using 'HA local command' origin 3 times (expect disabled state).
+    // 26. Enable using 'HA local command' origin (expect enabled state).
+    void resetUsingHALocalCommandOriginTest();
 
     /// @brief This test verifies that reset works, so that internal state is reset after
     /// all managers are recreated.
-    /// 1. Disable using 'user command' origin 1 time (expect disabled state).
-    /// 2. Disable using 'HA command' origin 1 time (expect disabled state).
-    /// 3. Disable using 'DB connection' origin 3 time (expect disabled state).
-    /// 4. Reset using 'DB connection' origin (expect disabled state).
-    /// 5. Enable using 'user command' origin 1 time (expect disabled state).
-    /// 6. Enable using 'DB connection' origin 1 time (expect enabled state).
-    /// 7. Disable using 'DB connection' origin 3 times (expect disabled state).
-    /// 8. Reset using 'DB connection' origin (expect enabled state).
+    // 1. Disable using 'user command' origin 1 time (expect disabled state).
+    // 2. Disable using 'HA remote command' origin 3 times with same id (expect disabled state).
+    // 3. Disable using 'DB connection' origin 1 time (expect disabled state).
+    // 4. Disable using 'HA local command' origin 1 time (expect disabled state).
+    // 5. Enable using 'HA remote command' origin (expect disabled state).
+    // 6. Enable using 'user command' origin 1 time (expect disabled state).
+    // 7. Enable using 'HA local command' origin 1 time (expect disabled state).
+    // 8. Enable using 'DB connection' origin 1 time (expect enabled state).
+    // 9. Disable using 'user command' origin 1 time (expect disabled state).
+    // 10. Disable using 'HA remote command' origin 3 times with different ids (expect disabled state).
+    // 11. Disable using 'DB connection' origin 1 time (expect disabled state).
+    // 12. Disable using 'HA local command' origin 1 time (expect disabled state).
+    // 13. Enable using 'user command' origin 1 time (expect disabled state).
+    // 14. Enable using 'HA local command' origin 1 time (expect disabled state).
+    // 15. Enable using 'DB connection' origin 1 time (expect disabled state).
+    // 16. Enable using 'HA remote command' origin 3 times with different ids (expect enabled state).
+    // 17. Disable using 'user command' origin 1 time (expect disabled state).
+    // 18. Disable using 'HA remote command' origin 3 times with different ids (expect disabled state).
+    // 19. Disable using 'DB connection' origin 1 time (expect disabled state).
+    // 20. Disable using 'HA local command' origin 1 time (expect disabled state).
+    // 21. Enable using 'user command' origin 1 time (expect disabled state).
+    // 22. Enable using 'HA local command' origin 1 time (expect disabled state).
+    // 23. Enable using 'DB connection' origin 1 time (expect disabled state).
+    // 24. Reset using 'HA remote command' origin (expect enabled state).
+    // 25. Disable using 'HA remote command' origin 3 times (expect disabled state).
+    // 26. Enable using 'HA remote command' origin (expect enabled state).
+    void resetUsingHARemoteCommandOriginTest();
+
+    /// @brief This test verifies that reset works, so that internal state is reset after
+    /// all managers are recreated.
+    // 1. Disable using 'user command' origin 1 time (expect disabled state).
+    // 2. Disable using 'DB connection' origin 3 times with same id (expect disabled state).
+    // 3. Disable using 'HA remote command' origin 1 time (expect disabled state).
+    // 4. Disable using 'HA local command' origin 1 time (expect disabled state).
+    // 5. Enable using 'DB connection' origin (expect disabled state).
+    // 6. Enable using 'user command' origin 1 time (expect disabled state).
+    // 7. Enable using 'HA local command' origin 1 time (expect disabled state).
+    // 8. Enable using 'HA remote command' origin 1 time (expect enabled state).
+    // 9. Disable using 'user command' origin 1 time (expect disabled state).
+    // 10. Disable using 'DB connection' origin 3 times with different ids (expect disabled state).
+    // 11. Disable using 'HA remote command' origin 1 time (expect disabled state).
+    // 12. Disable using 'HA local command' origin 1 time (expect disabled state).
+    // 13. Enable using 'user command' origin 1 time (expect disabled state).
+    // 14. Enable using 'HA local command' origin 1 time (expect disabled state).
+    // 15. Enable using 'HA remote command' origin 1 time (expect disabled state).
+    // 16. Enable using 'DB connection' origin 3 times with different ids (expect enabled state).
+    // 17. Disable using 'user command' origin 1 time (expect disabled state).
+    // 18. Disable using 'DB connection' origin 3 times with different ids (expect disabled state).
+    // 19. Disable using 'HA remote command' origin 1 time (expect disabled state).
+    // 20. Disable using 'HA local command' origin 1 time (expect disabled state).
+    // 21. Enable using 'user command' origin 1 time (expect disabled state).
+    // 22. Enable using 'HA local command' origin 1 time (expect disabled state).
+    // 23. Enable using 'HA remote command' origin 1 time (expect disabled state).
+    // 24. Reset using 'DB connection' origin (expect enabled state).
+    // 25. Disable using 'DB connection' origin 3 times (expect disabled state).
+    // 26. Enable using 'DB connection' origin (expect enabled state).
     void resetUsingDBConnectionOriginTest();
 
     /// @brief This test verifies that it is possible to setup delayed execution of enableAll
@@ -150,6 +206,59 @@ public:
         io_service_->poll();
     }
 
+    /// @brief Check network state.
+    ///
+    /// @brief state The network state to check.
+    /// @brief user Flag which indicates if user command disabled the state.
+    /// @brief local The list of local IDs which disabled the state.
+    /// @brief remote The list of remote IDs which disabled the state.
+    /// @brief db The list of manager IDs which disabled the state because of a
+    /// db connection failure.
+    /// @brief global Flag which indicates if the state is disabled.
+    void checkNetworkState(const NetworkState& state,
+                           bool user,
+                           std::vector<uint32_t> local,
+                           std::vector<uint32_t> remote,
+                           std::vector<uint32_t> db,
+                           bool global) {
+        std::ostringstream data;
+        data << std::boolalpha;
+        data << "{ \"disabled-by-db-connection\": [ ";
+        bool not_first = false;
+        for (auto const value : db) {
+            if (not_first) {
+                data << ", ";
+            }
+            data << value;
+            not_first = true;
+        }
+        data << " ], \"disabled-by-local-command\": [ ";
+        not_first = false;
+        for (auto const value : local) {
+            if (not_first) {
+                data << ", ";
+            }
+            data << value;
+            not_first = true;
+        }
+        data << " ], \"disabled-by-remote-command\": [ ";
+        not_first = false;
+        for (auto const value : remote) {
+            if (not_first) {
+                data << ", ";
+            }
+            data << value;
+            not_first = true;
+        }
+        data << " ], \"disabled-by-user\": " << user
+             << ", \"globally-disabled\": " << global
+             << " }";
+        auto const& expected = data.str();
+        auto const& actual = state.toElement()->str();
+        EXPECT_EQ(expected, actual);
+        EXPECT_EQ(!global, state.isServiceEnabled());
+    }
+
     /// @brief IO service used during the tests.
     IOServicePtr io_service_;
 };
@@ -157,226 +266,202 @@ public:
 // This test verifies the default is enable state.
 void
 NetworkStateTest::defaultTest() {
-    NetworkState state4(NetworkState::DHCPv4);
-    EXPECT_TRUE(state4.isServiceEnabled());
-    NetworkState state6(NetworkState::DHCPv6);
-    EXPECT_TRUE(state6.isServiceEnabled());
+    NetworkState state;
+
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
-// This test verifies that it is possible to disable and then enable DHCPv4
+// This test verifies that it is possible to disable and then enable
 // service using 'user command' origin.
 void
-NetworkStateTest::disableEnableService4UsingUserCommandOriginTest() {
-    NetworkState state(NetworkState::DHCPv4);
+NetworkStateTest::disableEnableServiceUsingUserCommandOriginTest() {
+    NetworkState state;
 
     // Test that enable/disable using 'user command' origin works
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 
     // Test that using 'user command' origin does not use internal counter
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
-// This test verifies that it is possible to disable and then enable DHCPv4
-// service using 'HA command' origin.
+// This test verifies that it is possible to disable and then enable
+// service using 'HA local command' origin.
 void
-NetworkStateTest::disableEnableService4UsingHACommandOriginTest() {
-    NetworkState state(NetworkState::DHCPv4);
+NetworkStateTest::disableEnableServiceUsingHALocalCommandOriginTest() {
+    NetworkState state;
 
-    // Test that enable/disable using 'HA command' origin works
+    // Test that enable/disable using 'HA local command' origin works
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000 }, {}, {}, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 
-    // Test that using 'HA command' origin does not use internal counter
+    // Test that using 'HA local command' origin does not use internal counter
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000 }, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000 }, {}, {}, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
-}
+    checkNetworkState(state, false, {}, {}, {}, false);
 
-// This test verifies that it is possible to disable and then enable DHCPv4
-// service using 'DB connection' origin.
-void
-NetworkStateTest::disableEnableService4UsingDBConnectionOriginTest() {
-    NetworkState state(NetworkState::DHCPv4);
-
-    // Test that enable/disable using 'DB connection' origin works
-    state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
-
-    // Test that using 'DB connection' origin uses internal counter
-    state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
-    state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
-}
-
-// This test verifies that it is possible to disable and then enable DHCPv4
-// service using a combination of origins.
-// 1. Disable using 'user command' origin 2 times (expect disabled state).
-// 2. Disable using 'HA command' origin 2 times (expect disabled state).
-// 3. Disable using 'DB connection' origin 2 times (expect disabled state).
-// 4. Enable using 'user command' origin 1 time (expect disabled state).
-// 5. Enable using 'HA command' origin 1 time (expect disabled state).
-// 6. Enable using 'DB connection' origin 2 times (expect enabled state).
-void
-NetworkStateTest::disableEnableService4UsingMultipleOriginsTest() {
-    NetworkState state(NetworkState::DHCPv4);
-
-    // Test that a combination properly affects the state
-    state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    // Test that using 'HA local command' origin does consider id
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND + 1);
+    checkNetworkState(state, false, { 1000, 1001 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND + 2);
+    checkNetworkState(state, false, { 1000, 1001, 1002 }, {}, {}, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1001, 1002 }, {}, {}, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND + 1);
+    checkNetworkState(state, false, { 1002 }, {}, {}, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND + 2);
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
-// This test verifies that it is possible to disable and then enable DHCPv6
-// service using 'user command' origin.
+// This test verifies that it is possible to disable and then enable
+// service using 'HA remote command' origin.
 void
-NetworkStateTest::disableEnableService6UsingUserCommandOriginTest() {
-    NetworkState state(NetworkState::DHCPv6);
-
-    // Test that enable/disable using 'user command' origin works
-    state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
-
-    // Test that using 'user command' origin does not use internal counter
-    state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
-    state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+NetworkStateTest::disableEnableServiceUsingHARemoteCommandOriginTest() {
+    NetworkState state;
+
+    // Test that enable/disable using 'HA remote command' origin works
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test that using 'HA remote command' origin does not use internal counter
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, {}, false);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test that using 'HA remote command' origin does consider id
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND + 1);
+    checkNetworkState(state, false, {}, { 2000, 2001 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND + 2);
+    checkNetworkState(state, false, {}, { 2000, 2001, 2002 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2001, 2002 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND + 1);
+    checkNetworkState(state, false, {}, { 2002 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND + 2);
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
-// This test verifies that it is possible to disable and then enable DHCPv6
-// service using 'HA command' origin.
-void
-NetworkStateTest::disableEnableService6UsingHACommandOriginTest() {
-    NetworkState state(NetworkState::DHCPv6);
-
-    // Test that enable/disable using 'HA command' origin works
-    state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
-
-    // Test that using 'HA command' origin does not use internal counter
-    state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
-    state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
-}
-
-// This test verifies that it is possible to disable and then enable DHCPv6
+// This test verifies that it is possible to disable and then enable
 // service using 'DB connection' origin.
 void
-NetworkStateTest::disableEnableService6UsingDBConnectionOriginTest() {
-    NetworkState state(NetworkState::DHCPv6);
+NetworkStateTest::disableEnableServiceUsingDBConnectionOriginTest() {
+    NetworkState state;
 
     // Test that enable/disable using 'DB connection' origin works
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
     state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 
-    // Test that using 'DB connection' origin uses internal counter
+    // Test that using 'DB connection' origin does not use internal counter
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
     state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
     state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test that using 'DB connection' origin does consider id
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
+    state.disableService(NetworkState::DB_CONNECTION + 1);
+    checkNetworkState(state, false, {}, {}, { 3000, 3001 }, true);
+    state.disableService(NetworkState::DB_CONNECTION + 2);
+    checkNetworkState(state, false, {}, {}, { 3000, 3001, 3002 }, true);
     state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3001, 3002 }, true);
+    state.enableService(NetworkState::DB_CONNECTION + 1);
+    checkNetworkState(state, false, {}, {}, { 3002 }, true);
+    state.enableService(NetworkState::DB_CONNECTION + 2);
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
-// This test verifies that it is possible to disable and then enable DHCPv6
-// service using a combination of origins.
+/// @brief This test verifies that it is possible to disable and then enable
+/// service using a combination of origins.
 // 1. Disable using 'user command' origin 2 times (expect disabled state).
-// 2. Disable using 'HA command' origin 2 times (expect disabled state).
-// 3. Disable using 'DB connection' origin 2 times (expect disabled state).
-// 4. Enable using 'user command' origin 1 time (expect disabled state).
-// 5. Enable using 'HA command' origin 1 time (expect disabled state).
-// 6. Enable using 'DB connection' origin 2 times (expect enabled state).
+// 2. Disable using 'HA local command' origin 2 times (expect disabled state).
+// 3. Disable using 'HA local command' origin 1 time different id (expect disabled state).
+// 4. Disable using 'HA remote command' origin 2 times (expect disabled state).
+// 5. Disable using 'HA remote command' origin 1 time different id (expect disabled state).
+// 6. Disable using 'DB connection' origin 2 times (expect disabled state).
+// 7. Disable using 'DB connection' origin 1 time different id (expect disabled state).
+// 8. Enable using 'user command' origin 1 time (expect disabled state).
+// 9. Enable using 'HA local command' origin 1 time (expect disabled state).
+// 10. Enable using 'HA local command' origin 1 time different id (expect disabled state).
+// 11. Enable using 'HA remote command' origin 1 time (expect disabled state).
+// 12. Enable using 'HA remote command' origin 1 time different id (expect disabled state).
+// 13. Enable using 'DB connection' origin 1 times (expect disabled state).
+// 14. Enable using 'DB connection' origin 1 time different id (expect disabled state).
 void
-NetworkStateTest::disableEnableService6UsingMultipleOriginsTest() {
-    NetworkState state(NetworkState::DHCPv6);
+NetworkStateTest::disableEnableServiceUsingMultipleOriginsTest() {
+    NetworkState state;
 
     // Test that a combination properly affects the state
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND + 1);
+    checkNetworkState(state, true, { 1000, 1001 }, {}, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, { 1000, 1001 }, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, { 1000, 1001 }, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND + 1);
+    checkNetworkState(state, true, { 1000, 1001 }, { 2000, 2001 }, {}, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000, 1001 }, { 2000, 2001 }, { 3000 }, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000, 1001 }, { 2000, 2001 }, { 3000 }, true);
+    state.disableService(NetworkState::DB_CONNECTION + 1);
+    checkNetworkState(state, true, { 1000, 1001 }, { 2000, 2001 }, { 3000, 3001 }, true);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000, 1001 }, { 2000, 2001 }, { 3000, 3001 }, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1001 }, { 2000, 2001 }, { 3000, 3001 }, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND + 1);
+    checkNetworkState(state, false, {}, { 2000, 2001 }, { 3000, 3001 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2001 }, { 3000, 3001 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND + 1);
+    checkNetworkState(state, false, {}, {}, { 3000, 3001 }, true);
     state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3001 },true);
+    state.enableService(NetworkState::DB_CONNECTION + 1);
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
 // This test verifies that reset works, so that internal state is reset after
@@ -388,131 +473,388 @@ NetworkStateTest::disableEnableService6UsingMultipleOriginsTest() {
 // 5. Enable using 'HA command' origin 1 time (expect disabled state).
 // 6. Enable using 'DB connection' origin 1 time (expect enabled state).
 // 7. Disable using 'user command' origin 3 times (expect disabled state).
-// 8. Reset using 'user command' origin (expect enabled state).
+// 8. Enable using 'user command' origin (expect enabled state).
 void
 NetworkStateTest::resetUsingUserCommandOriginTest() {
-    NetworkState state(NetworkState::DHCPv4);
+    NetworkState state;
 
     // Test User COMMAND + HA COMMAND + DB CONNECTION origins
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, { 1000 }, { 2000 }, {}, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, { 2000 }, { 3000 }, true);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000 }, { 2000 }, { 3000 }, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
     state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 
     // Test User COMMAND origin only
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
 // This test verifies that reset works, so that internal state is reset after
 // all managers are recreated.
 // 1. Disable using 'user command' origin 1 time (expect disabled state).
-// 2. Disable using 'HA command' origin 3 times (expect disabled state).
+// 2. Disable using 'HA local command' origin 3 times with same id (expect disabled state).
 // 3. Disable using 'DB connection' origin 1 time (expect disabled state).
-// 4. Enable using 'HA command' origin (expect disabled state).
-// 5. Enable using 'user command' origin 1 time (expect disabled state).
-// 6. Enable using 'DB connection' origin 1 time (expect enabled state).
-// 7. Disable using 'HA command' origin 3 times (expect disabled state).
-// 8. Enable using 'HA command' origin (expect enabled state).
+// 4. Disable using 'HA remote command' origin 1 time (expect disabled state).
+// 5. Enable using 'HA local command' origin (expect disabled state).
+// 6. Enable using 'user command' origin 1 time (expect disabled state).
+// 7. Enable using 'HA remote command' origin 1 time (expect disabled state).
+// 8. Enable using 'DB connection' origin 1 time (expect enabled state).
+// 9. Disable using 'user command' origin 1 time (expect disabled state).
+// 10. Disable using 'HA local command' origin 3 times with different ids (expect disabled state).
+// 11. Disable using 'DB connection' origin 1 time (expect disabled state).
+// 12. Disable using 'HA remote command' origin 1 time (expect disabled state).
+// 13. Enable using 'user command' origin 1 time (expect disabled state).
+// 14. Enable using 'HA remote command' origin 1 time (expect disabled state).
+// 15. Enable using 'DB connection' origin 1 time (expect disabled state).
+// 16. Enable using 'HA local command' origin 3 times with different ids (expect enabled state).
+// 17. Disable using 'user command' origin 1 time (expect disabled state).
+// 18. Disable using 'HA local command' origin 3 times with different ids (expect disabled state).
+// 19. Disable using 'DB connection' origin 1 time (expect disabled state).
+// 20. Disable using 'HA remote command' origin 1 time (expect disabled state).
+// 21. Enable using 'user command' origin 1 time (expect disabled state).
+// 22. Enable using 'HA remote command' origin 1 time (expect disabled state).
+// 23. Enable using 'DB connection' origin 1 time (expect disabled state).
+// 24. Reset using 'HA local command' origin (expect enabled state).
+// 25. Disable using 'HA local command' origin 3 times (expect disabled state).
+// 26. Enable using 'HA local command' origin (expect enabled state).
 void
-NetworkStateTest::resetUsingHACommandOriginTest() {
-    NetworkState state(NetworkState::DHCPv4);
+NetworkStateTest::resetUsingHALocalCommandOriginTest() {
+    NetworkState state;
 
     // Test HA COMMAND + User COMMAND + DB CONNECTION origins
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, { 3000 }, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, { 1000 }, { 2000 }, { 3000 }, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, { 2000 }, { 3000 }, true);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
     state.enableService(NetworkState::DB_CONNECTION);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 
-    // Test HA COMMAND origin only
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
+    state.disableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND + 1);
+    checkNetworkState(state, true, { 1000, 1001 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND + 2);
+    checkNetworkState(state, true, { 1000, 1001, 1002 }, {}, {}, true);
+    state.disableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, { 1000, 1001, 1002 }, {}, { 3000 }, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, { 1000, 1001, 1002 }, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, false, { 1000, 1001, 1002 }, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, { 1000, 1001, 1002 }, {}, { 3000 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, false, { 1000, 1001, 1002 }, {}, {}, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, { 1001, 1002 }, {}, {}, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND + 1);
+    checkNetworkState(state, false, { 1002 }, {}, {}, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND + 2);
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
+    state.disableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND + 1);
+    checkNetworkState(state, true, { 1000, 1001 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND + 2);
+    checkNetworkState(state, true, { 1000, 1001, 1002 }, {}, {}, true);
+    state.disableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, { 1000, 1001, 1002 }, {}, { 3000 }, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, { 1000, 1001, 1002 }, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, false, { 1000, 1001, 1002 }, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, { 1000, 1001, 1002 }, {}, { 3000 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, false, { 1000, 1001, 1002 }, {}, {}, true);
+    state.resetForLocalCommands();
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test HA LOCAL COMMAND origin only
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, { 1000 }, {}, {}, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, { 1000 }, {}, {}, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
-// This test verifies that reset works, so that internal state is  reset after
+// This test verifies that reset works, so that internal state is reset after
 // all managers are recreated.
 // 1. Disable using 'user command' origin 1 time (expect disabled state).
-// 2. Disable using 'HA command' origin 1 time (expect disabled state).
-// 3. Disable using 'DB connection' origin 3 time (expect disabled state).
-// 4. Reset using 'DB connection' origin (expect disabled state).
-// 5. Enable using 'user command' origin 1 time (expect disabled state).
-// 6. Enable using 'DB connection' origin 1 time (expect enabled state).
-// 7. Disable using 'DB connection' origin 3 times (expect disabled state).
-// 8. Reset using 'DB connection' origin (expect enabled state).
+// 2. Disable using 'HA remote command' origin 3 times with same id (expect disabled state).
+// 3. Disable using 'DB connection' origin 1 time (expect disabled state).
+// 4. Disable using 'HA local command' origin 1 time (expect disabled state).
+// 5. Enable using 'HA remote command' origin (expect disabled state).
+// 6. Enable using 'user command' origin 1 time (expect disabled state).
+// 7. Enable using 'HA local command' origin 1 time (expect disabled state).
+// 8. Enable using 'DB connection' origin 1 time (expect enabled state).
+// 9. Disable using 'user command' origin 1 time (expect disabled state).
+// 10. Disable using 'HA remote command' origin 3 times with different ids (expect disabled state).
+// 11. Disable using 'DB connection' origin 1 time (expect disabled state).
+// 12. Disable using 'HA local command' origin 1 time (expect disabled state).
+// 13. Enable using 'user command' origin 1 time (expect disabled state).
+// 14. Enable using 'HA local command' origin 1 time (expect disabled state).
+// 15. Enable using 'DB connection' origin 1 time (expect disabled state).
+// 16. Enable using 'HA remote command' origin 3 times with different ids (expect enabled state).
+// 17. Disable using 'user command' origin 1 time (expect disabled state).
+// 18. Disable using 'HA remote command' origin 3 times with different ids (expect disabled state).
+// 19. Disable using 'DB connection' origin 1 time (expect disabled state).
+// 20. Disable using 'HA local command' origin 1 time (expect disabled state).
+// 21. Enable using 'user command' origin 1 time (expect disabled state).
+// 22. Enable using 'HA local command' origin 1 time (expect disabled state).
+// 23. Enable using 'DB connection' origin 1 time (expect disabled state).
+// 24. Reset using 'HA remote command' origin (expect enabled state).
+// 25. Disable using 'HA remote command' origin 3 times (expect disabled state).
+// 26. Enable using 'HA remote command' origin (expect enabled state).
 void
-NetworkStateTest::resetUsingDBConnectionOriginTest() {
-    NetworkState state(NetworkState::DHCPv4);
+NetworkStateTest::resetUsingHARemoteCommandOriginTest() {
+    NetworkState state;
 
-    // Test DB CONNECTION + User COMMAND + HA COMMAND origins
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
     state.disableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, {}, { 2000 }, { 3000 }, true);
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, { 1000 }, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, { 1000 }, {}, { 3000 }, true);
+    state.enableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, false, { 1000 }, {}, { 3000 }, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
+    state.disableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, true, {}, {}, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND + 1);
+    checkNetworkState(state, true, {}, { 2000, 2001 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND + 2);
+    checkNetworkState(state, true, {}, { 2000, 2001, 2002 }, {}, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, true, { 1000 }, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.enableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, false, { 1000 }, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, {}, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, false, {}, { 2000, 2001, 2002 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2001, 2002 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND + 1);
+    checkNetworkState(state, false, {}, { 2002 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND + 2);
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
+    state.disableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, true, {}, {}, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND + 1);
+    checkNetworkState(state, true, {}, { 2000, 2001 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND + 2);
+    checkNetworkState(state, true, {}, { 2000, 2001, 2002 }, {}, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, true, { 1000 }, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.enableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, false, { 1000 }, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, {}, { 2000, 2001, 2002 }, { 3000 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, false, {}, { 2000, 2001, 2002 }, {}, true);
+    state.resetForRemoteCommands();
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test HA REMOTE COMMAND origin only
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, {}, false);
+}
+
+/// @brief This test verifies that reset works, so that internal state is reset after
+/// all managers are recreated.
+// 1. Disable using 'user command' origin 1 time (expect disabled state).
+// 2. Disable using 'DB connection' origin 3 times with same id (expect disabled state).
+// 3. Disable using 'HA remote command' origin 1 time (expect disabled state).
+// 4. Disable using 'HA local command' origin 1 time (expect disabled state).
+// 5. Enable using 'DB connection' origin (expect disabled state).
+// 6. Enable using 'user command' origin 1 time (expect disabled state).
+// 7. Enable using 'HA local command' origin 1 time (expect disabled state).
+// 8. Enable using 'HA remote command' origin 1 time (expect enabled state).
+// 9. Disable using 'user command' origin 1 time (expect disabled state).
+// 10. Disable using 'DB connection' origin 3 times with different ids (expect disabled state).
+// 11. Disable using 'HA remote command' origin 1 time (expect disabled state).
+// 12. Disable using 'HA local command' origin 1 time (expect disabled state).
+// 13. Enable using 'user command' origin 1 time (expect disabled state).
+// 14. Enable using 'HA local command' origin 1 time (expect disabled state).
+// 15. Enable using 'HA remote command' origin 1 time (expect disabled state).
+// 16. Enable using 'DB connection' origin 3 times with different ids (expect enabled state).
+// 17. Disable using 'user command' origin 1 time (expect disabled state).
+// 18. Disable using 'DB connection' origin 3 times with different ids (expect disabled state).
+// 19. Disable using 'HA remote command' origin 1 time (expect disabled state).
+// 20. Disable using 'HA local command' origin 1 time (expect disabled state).
+// 21. Enable using 'user command' origin 1 time (expect disabled state).
+// 22. Enable using 'HA local command' origin 1 time (expect disabled state).
+// 23. Enable using 'HA remote command' origin 1 time (expect disabled state).
+// 24. Reset using 'DB connection' origin (expect enabled state).
+// 25. Disable using 'DB connection' origin 3 times (expect disabled state).
+// 26. Enable using 'DB connection' origin (expect enabled state).
+void
+NetworkStateTest::resetUsingDBConnectionOriginTest() {
+    NetworkState state;
+
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
+    state.disableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, true, {}, {}, {}, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.resetForDbConnection();
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, true, {}, {}, { 3000 }, true);
+    state.disableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, {}, {}, { 3000 }, true);
+    state.disableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, {}, {}, { 3000 }, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, { 3000 }, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, true, { 1000 }, { 2000 }, { 3000 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, { 1000 }, { 2000 }, {}, true);
     state.enableService(NetworkState::USER_COMMAND);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, { 1000 }, { 2000 }, {}, true);
     state.enableService(NetworkState::HA_LOCAL_COMMAND);
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, { 2000 }, {}, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
+    state.disableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, true, {}, {}, {}, true);
+    state.disableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, {}, {}, { 3000 }, true);
+    state.disableService(NetworkState::DB_CONNECTION + 1);
+    checkNetworkState(state, true, {}, {}, { 3000, 3001 }, true);
+    state.disableService(NetworkState::DB_CONNECTION + 2);
+    checkNetworkState(state, true, {}, {}, { 3000, 3001, 3002 }, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, true, { 1000 }, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.enableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, false, { 1000 }, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, { 3000, 3001, 3002 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, false, {}, {}, { 3001, 3002 }, true);
+    state.enableService(NetworkState::DB_CONNECTION + 1);
+    checkNetworkState(state, false, {}, {}, { 3002 }, true);
+    state.enableService(NetworkState::DB_CONNECTION + 2);
+    checkNetworkState(state, false, {}, {}, {}, false);
+
+    // Test HA COMMAND + User COMMAND + DB CONNECTION origins
+    state.disableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, true, {}, {}, {}, true);
+    state.disableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, true, {}, {}, { 3000 }, true);
+    state.disableService(NetworkState::DB_CONNECTION + 1);
+    checkNetworkState(state, true, {}, {}, { 3000, 3001 }, true);
+    state.disableService(NetworkState::DB_CONNECTION + 2);
+    checkNetworkState(state, true, {}, {}, { 3000, 3001, 3002 }, true);
+    state.disableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, true, {}, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.disableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, true, { 1000 }, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.enableService(NetworkState::USER_COMMAND);
+    checkNetworkState(state, false, { 1000 }, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.enableService(NetworkState::HA_LOCAL_COMMAND);
+    checkNetworkState(state, false, {}, { 2000 }, { 3000, 3001, 3002 }, true);
+    state.enableService(NetworkState::HA_REMOTE_COMMAND);
+    checkNetworkState(state, false, {}, {}, { 3000, 3001, 3002 }, true);
+    state.resetForDbConnection();
+    checkNetworkState(state, false, {}, {}, {}, false);
 
     // Test DB CONNECTION origin only
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
     state.disableService(NetworkState::DB_CONNECTION);
-    EXPECT_FALSE(state.isServiceEnabled());
-    state.resetForDbConnection();
-    EXPECT_TRUE(state.isServiceEnabled());
+    checkNetworkState(state, false, {}, {}, { 3000 }, true);
+    state.enableService(NetworkState::DB_CONNECTION);
+    checkNetworkState(state, false, {}, {}, {}, false);
 }
 
 // This test verifies that it is possible to setup delayed execution of enableAll
 // function.
 void
 NetworkStateTest::delayedEnableServiceTest() {
-    NetworkState state(NetworkState::DHCPv4);
+    NetworkState state;
     // Disable the service and then schedule enabling it in 1 second.
     state.disableService(NetworkState::USER_COMMAND);
     state.delayedEnableService(1, NetworkState::USER_COMMAND);
@@ -538,7 +880,7 @@ NetworkStateTest::delayedEnableServiceTest() {
 // scheduled for automatically enabling it.
 void
 NetworkStateTest::earlyEnableServiceTest() {
-    NetworkState state(NetworkState::DHCPv4);
+    NetworkState state;
     // Disable the service.
     state.disableService(NetworkState::USER_COMMAND);
     EXPECT_FALSE(state.isServiceEnabled());
@@ -555,7 +897,7 @@ NetworkStateTest::earlyEnableServiceTest() {
 // and that it results in only one timer being scheduled.
 void
 NetworkStateTest::multipleDelayedEnableServiceTest() {
-    NetworkState state(NetworkState::DHCPv4);
+    NetworkState state;
     // Disable the service and then schedule enabling it in 5 second.
     state.disableService(NetworkState::USER_COMMAND);
     // Schedule the first timer for 5 seconds.
@@ -577,7 +919,7 @@ NetworkStateTest::multipleDelayedEnableServiceTest() {
 // from different origins and that it results in each timer being scheduled.
 void
 NetworkStateTest::multipleDifferentOriginsDelayedEnableServiceTest() {
-    NetworkState state(NetworkState::DHCPv4);
+    NetworkState state;
     // Disable the service and then schedule enabling it in 5 second.
     state.disableService(NetworkState::HA_LOCAL_COMMAND);
     // Disable the service and then schedule enabling it in 2 second.
@@ -614,76 +956,49 @@ TEST_F(NetworkStateTest, defaultTestMultiThreading) {
     defaultTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService4UsingUserCommandOriginTest) {
-    disableEnableService4UsingUserCommandOriginTest();
-}
-
-TEST_F(NetworkStateTest, disableEnableService4UsingUserCommandOriginTestMultilThreading) {
-    MultiThreadingMgr::instance().setMode(true);
-    disableEnableService4UsingUserCommandOriginTest();
-}
-
-TEST_F(NetworkStateTest, disableEnableService4UsingHACommandOriginTest) {
-    disableEnableService4UsingHACommandOriginTest();
-}
-
-TEST_F(NetworkStateTest, disableEnableService4UsingHACommandOriginTestMultiThreading) {
-    MultiThreadingMgr::instance().setMode(true);
-    disableEnableService4UsingHACommandOriginTest();
-}
-
-TEST_F(NetworkStateTest, disableEnableService4UsingDBConnectionOriginTest) {
-    disableEnableService4UsingDBConnectionOriginTest();
-}
-
-TEST_F(NetworkStateTest, disableEnableService4UsingDBConnectionOriginTestMultiThreading) {
-    MultiThreadingMgr::instance().setMode(true);
-    disableEnableService4UsingDBConnectionOriginTest();
-}
-
-TEST_F(NetworkStateTest, disableEnableService4UsingMultipleOriginsTest) {
-    disableEnableService4UsingMultipleOriginsTest();
+TEST_F(NetworkStateTest, disableEnableServiceUsingUserCommandOriginTest) {
+    disableEnableServiceUsingUserCommandOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService4UsingMultipleOriginsTestMultiThreading) {
+TEST_F(NetworkStateTest, disableEnableServiceUsingUserCommandOriginTestMultilThreading) {
     MultiThreadingMgr::instance().setMode(true);
-    disableEnableService4UsingMultipleOriginsTest();
+    disableEnableServiceUsingUserCommandOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingUserCommandOriginTest) {
-    disableEnableService6UsingUserCommandOriginTest();
+TEST_F(NetworkStateTest, disableEnableServiceUsingHALocalCommandOriginTest) {
+    disableEnableServiceUsingHALocalCommandOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingUserCommandOriginTestMultiThreading) {
+TEST_F(NetworkStateTest, disableEnableServiceUsingHALocalCommandOriginTestMultiThreading) {
     MultiThreadingMgr::instance().setMode(true);
-    disableEnableService6UsingUserCommandOriginTest();
+    disableEnableServiceUsingHALocalCommandOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingHACommandOriginTest) {
-    disableEnableService6UsingHACommandOriginTest();
+TEST_F(NetworkStateTest, disableEnableServiceUsingHARemoteCommandOriginTest) {
+    disableEnableServiceUsingHARemoteCommandOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingHACommandOriginTestMultiThreading) {
+TEST_F(NetworkStateTest, disableEnableServiceUsingHARemoteCommandOriginTestMultiThreading) {
     MultiThreadingMgr::instance().setMode(true);
-    disableEnableService6UsingHACommandOriginTest();
+    disableEnableServiceUsingHARemoteCommandOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingDBConnectionOriginTest) {
-    disableEnableService6UsingDBConnectionOriginTest();
+TEST_F(NetworkStateTest, disableEnableServiceUsingDBConnectionOriginTest) {
+    disableEnableServiceUsingDBConnectionOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingDBConnectionOriginTestMultiThreading) {
+TEST_F(NetworkStateTest, disableEnableServiceUsingDBConnectionOriginTestMultiThreading) {
     MultiThreadingMgr::instance().setMode(true);
-    disableEnableService6UsingDBConnectionOriginTest();
+    disableEnableServiceUsingDBConnectionOriginTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingMultipleOriginsTest) {
-    disableEnableService6UsingMultipleOriginsTest();
+TEST_F(NetworkStateTest, disableEnableServiceUsingMultipleOriginsTest) {
+    disableEnableServiceUsingMultipleOriginsTest();
 }
 
-TEST_F(NetworkStateTest, disableEnableService6UsingMultipleOriginsTestMultiThreading) {
+TEST_F(NetworkStateTest, disableEnableServiceUsingMultipleOriginsTestMultiThreading) {
     MultiThreadingMgr::instance().setMode(true);
-    disableEnableService6UsingMultipleOriginsTest();
+    disableEnableServiceUsingMultipleOriginsTest();
 }
 
 TEST_F(NetworkStateTest, resetUsingUserCommandOriginTest) {
@@ -704,13 +1019,22 @@ TEST_F(NetworkStateTest, resetUsingDBConnectionOriginTestMultiThreading) {
     resetUsingDBConnectionOriginTest();
 }
 
-TEST_F(NetworkStateTest, resetUsingHACommandOriginTest) {
-    resetUsingHACommandOriginTest();
+TEST_F(NetworkStateTest, resetUsingHALocalCommandOriginTest) {
+    resetUsingHALocalCommandOriginTest();
+}
+
+TEST_F(NetworkStateTest, resetUsingHALocalCommandOriginTestMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    resetUsingHALocalCommandOriginTest();
+}
+
+TEST_F(NetworkStateTest, resetUsingHARemoteCommandOriginTest) {
+    resetUsingHARemoteCommandOriginTest();
 }
 
-TEST_F(NetworkStateTest, resetUsingHACommandOriginTestMultiThreading) {
+TEST_F(NetworkStateTest, resetUsingHARemoteCommandOriginTestMultiThreading) {
     MultiThreadingMgr::instance().setMode(true);
-    resetUsingHACommandOriginTest();
+    resetUsingHARemoteCommandOriginTest();
 }
 
 TEST_F(NetworkStateTest, delayedEnableServiceTest) {
index 84523d8b796e58b6319a9535ea4b47a36417d978..bbbf13a89f193e059d776e53e54c45db3e51442d 100644 (file)
@@ -320,12 +320,13 @@ std::pair<uint32_t, uint32_t>
 MySqlConnection::getVersion(const ParameterMap& parameters,
                             const IOServiceAccessorPtr& ac,
                             const DbCallback& cb,
-                            const string& timer_name) {
+                            const string& timer_name,
+                            unsigned int id) {
     // Get a connection.
     MySqlConnection conn(parameters, ac, cb);
 
     if (!timer_name.empty()) {
-        conn.makeReconnectCtl(timer_name);
+        conn.makeReconnectCtl(timer_name, id);
     }
 
     // Open the database.
index 10dc1dc1f4bdb5bec1e1a0f79f2d65fec7a8fe01..7800ac2d072d74896d3168a5a6aeab29311cce11 100644 (file)
@@ -271,6 +271,7 @@ public:
     /// @param ac An IOServiceAccessor object.
     /// @param cb The dbReconnect callback.
     /// @param timer_name The DB reconnect timer name.
+    /// @param id the ID of the manager.
     ///
     /// @return Version number as a pair of unsigned integers.  "first" is the
     ///         major version number, "second" the minor number.
@@ -281,7 +282,8 @@ public:
     getVersion(const ParameterMap& parameters,
                const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(),
                const DbCallback& cb = DbCallback(),
-               const std::string& timer_name = std::string());
+               const std::string& timer_name = std::string(),
+               unsigned int id = 0);
 
     /// @brief Retrieve schema version, validate it against the hardcoded
     ///     version, and attempt to initialize the schema if there is an
index e63a699a1a42caf0bbc641a67cf2329f490c0550..9afc56f880799fb6592d2953c59845ddbc143d2d 100644 (file)
@@ -147,12 +147,13 @@ std::pair<uint32_t, uint32_t>
 PgSqlConnection::getVersion(const ParameterMap& parameters,
                             const IOServiceAccessorPtr& ac,
                             const DbCallback& cb,
-                            const string& timer_name) {
+                            const string& timer_name,
+                            unsigned int id) {
     // Get a connection.
     PgSqlConnection conn(parameters, ac, cb);
 
     if (!timer_name.empty()) {
-        conn.makeReconnectCtl(timer_name);
+        conn.makeReconnectCtl(timer_name, id);
     }
 
     // Open the database.
index b3fbf5b38a3b79295341a5d7108f9759e4c5dc69..495478e7f3105b2e2623f886aba6a8313923fd81 100644 (file)
@@ -242,6 +242,7 @@ public:
     /// @param ac An IOServiceAccessor object.
     /// @param cb The dbReconnect callback.
     /// @param timer_name The DB reconnect timer name.
+    /// @param id the ID of the manager.
     ///
     /// @return Version number as a pair of unsigned integers.  "first" is the
     ///         major version number, "second" the minor number.
@@ -252,7 +253,8 @@ public:
     getVersion(const ParameterMap& parameters,
                const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(),
                const DbCallback& cb = DbCallback(),
-               const std::string& timer_name = std::string());
+               const std::string& timer_name = std::string(),
+               unsigned int id = 0);
 
     /// @brief Retrieve schema version, validate it against the hardcoded
     ///     version, and attempt to initialize the schema if there is an
index b9f4a328ea5511a7f7ded2555a1230533f243699..8143f61f74f7cdd44ded0fe9261e843074d83f47 100644 (file)
@@ -36,18 +36,25 @@ public:
     /// @param max_retries maximum number of reconnect attempts to make.
     /// @param retry_interval amount of time to between reconnect attempts.
     /// @param action which should be taken on connection loss.
+    /// @param id the ID of the manager.
     ReconnectCtl(const std::string& backend_type, const std::string& timer_name,
                  unsigned int max_retries, unsigned int retry_interval,
-                 OnFailAction action) :
+                 OnFailAction action, unsigned int id) :
           backend_type_(backend_type), timer_name_(timer_name),
           max_retries_(max_retries), retries_left_(max_retries),
-          retry_interval_(retry_interval), action_(action) {}
+          retry_interval_(retry_interval), action_(action), id_(id) {
+    }
 
     /// @brief Returns the type of the caller backend.
     std::string backendType() const {
         return (backend_type_);
     }
 
+    /// @brief Returns the ID of the manager.
+    unsigned int id() const {
+        return (id_);
+    }
+
     /// @brief Returns the associated timer name.
     ///
     /// @return the associated timer.
@@ -132,6 +139,9 @@ private:
 
     /// @brief Action to take on connection loss.
     OnFailAction action_;
+
+    /// @brief The ID of the manager.
+    unsigned int id_;
 };
 
 /// @brief Pointer to an instance of ReconnectCtl
index 8e107a71d550321b166d9c0310c9c0bbfb5f6b7e..0be7e5e4407148890799c54f1d71fab39e00c53e 100644 (file)
         "{",
         "    \"result\": <integer>,",
         "    \"arguments\": {",
-        "        \"pid\": <integer>,",
-        "        \"uptime\": <uptime in seconds>,",
-        "        \"reload\": <time since reload in seconds>,",
+        "        \"dhcp-state\": {",
+        "            \"disabled-by-db-connection\": [],",
+        "            \"disabled-by-local-command\": [],",
+        "            \"disabled-by-remote-command\": [],",
+        "            \"disabled-by-user\": false,",
+        "            \"globally-disabled\": false",
+        "        },",
         "        \"high-availability\": [",
         "            {",
         "                \"ha-mode\": <HA mode configured for this relationship>,",
         "            }",
         "        ],",
         "        \"multi-threading-enabled\": true,",
-        "        \"thread-pool-size\": 4,",
         "        \"packet-queue-size\": 64,",
         "        \"packet-queue-statistics\": [ 1.2, 2.3, 3.4 ],",
+        "        \"pid\": <integer>,",
+        "        \"reload\": <time since reload in seconds>,",
         "        \"sockets\": {",
         "            \"errors\": [ <error received during the last attempt to open all sockets> ],",
         "            \"status\": <ready, retrying, or failed>",
-        "        }",
+        "        },",
+        "        \"thread-pool-size\": 4,",
+        "        \"uptime\": <uptime in seconds>",
         "    }",
         "}"
     ],