From: Marcin Siodelski Date: Tue, 14 Jan 2020 10:20:33 +0000 (+0100) Subject: [#1024] Implemented state handlers X-Git-Tag: Kea-1.7.4~68 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22d64dbce65b0db4fc8fad97bad5db45ea0168fa;p=thirdparty%2Fkea.git [#1024] Implemented state handlers There are now new handlers for the maintained and partner-maintained state. --- diff --git a/src/hooks/dhcp/high_availability/ha_service.cc b/src/hooks/dhcp/high_availability/ha_service.cc index 3a1d64fc12..d02ccdfc25 100644 --- a/src/hooks/dhcp/high_availability/ha_service.cc +++ b/src/hooks/dhcp/high_availability/ha_service.cc @@ -203,6 +203,24 @@ HAService::normalStateHandler() { void HAService::maintainedStateHandler() { + // If we are transitioning from another state, we have to define new + // serving scopes appropriate for the new state. We don't do it if + // we remain in this state. + if (doOnEntry()) { + // In this state the server remains silent and waits for being + // shutdown. + query_filter_.serveNoScopes(); + adjustNetworkState(); + + // Log if the state machine is paused. + conditionalLogPausedState(); + } + + scheduleHeartbeat(); + + // We don't transition out of this state unless explicitly mandated + // by the administrator via a dedicated command which cancels + // the maintenance. postNextEvent(NOP_EVT); } @@ -265,7 +283,46 @@ HAService::partnerDownStateHandler() { void HAService::partnerMaintainedStateHandler() { - postNextEvent(NOP_EVT); + // If we are transitioning from another state, we have to define new + // serving scopes appropriate for the new state. We don't do it if + // we remain in this state. + if (doOnEntry()) { + // It may be administratively disabled to handle partner's scope + // in case of failure. If this is the case we'll just handle our + // default scope (or no scope at all). The user will need to + // manually enable this server to handle partner's scope. + if (config_->getThisServerConfig()->isAutoFailover()) { + query_filter_.serveFailoverScopes(); + } else { + query_filter_.serveDefaultScopes(); + } + adjustNetworkState(); + + // Log if the state machine is paused. + conditionalLogPausedState(); + } + + scheduleHeartbeat(); + + if (isModelPaused()) { + postNextEvent(NOP_EVT); + return; + } + + // Check if the clock skew is still acceptable. If not, transition to + // the terminated state. + if (shouldTerminate()) { + verboseTransition(HA_TERMINATED_ST); + return; + } + + switch (communication_state_->getPartnerState()) { + case HA_UNAVAILABLE_ST: + verboseTransition(HA_PARTNER_DOWN_ST); + + default: + postNextEvent(NOP_EVT); + } } void @@ -645,6 +702,7 @@ HAService::adjustNetworkState() { const bool should_enable = ((getCurrState() == HA_LOAD_BALANCING_ST) || (getCurrState() == HA_HOT_STANDBY_ST) || (getCurrState() == HA_PARTNER_DOWN_ST) || + (getCurrState() == HA_PARTNER_MAINTAINED_ST) || (getCurrState() == HA_TERMINATED_ST)); if (!should_enable && network_state_->isServiceEnabled()) { @@ -928,6 +986,7 @@ HAService::shouldSendLeaseUpdates(const HAConfig::PeerConfigPtr& peer_config) co switch (getCurrState()) { case HA_HOT_STANDBY_ST: case HA_LOAD_BALANCING_ST: + case HA_PARTNER_MAINTAINED_ST: return (true); default: diff --git a/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc b/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc index 6b67daa019..18c51441ed 100644 --- a/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc +++ b/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc @@ -4045,10 +4045,12 @@ TEST_F(HAServiceStateMachineTest, scopesServingLoadBalancing) { expectScopes(MyState(HA_LOAD_BALANCING_ST), { "server1" }, true); expectScopes(MyState(HA_TERMINATED_ST), { "server1" }, true); - // PARTNER DOWN: serving both scopes. + // PARTNER DOWN and PARTNER MAINTAINED: serving both scopes. expectScopes(MyState(HA_PARTNER_DOWN_ST), { "server1", "server2" }, true); + expectScopes(MyState(HA_PARTNER_MAINTAINED_ST), { "server1", "server2" }, true); - // READY & WAITING: serving no scopes. + // MAINTAINED, READY & WAITING: serving no scopes. + expectScopes(MyState(HA_MAINTAINED_ST), { }, false); expectScopes(MyState(HA_READY_ST), { }, false); expectScopes(MyState(HA_WAITING_ST), { }, false); } @@ -4064,11 +4066,13 @@ TEST_F(HAServiceStateMachineTest, scopesServingLoadBalancingNoFailover) { expectScopes(MyState(HA_LOAD_BALANCING_ST), { "server1" }, true); expectScopes(MyState(HA_TERMINATED_ST), { "server1" }, true); - // PARTNER DOWN: still serving my own scope because auto-failover - // is disabled. + // PARTNER MAINTAINED & PARTNER DOWN: still serving my own scope + // because auto-failover is disabled. expectScopes(MyState(HA_PARTNER_DOWN_ST), { "server1" }, true); + expectScopes(MyState(HA_PARTNER_MAINTAINED_ST), { "server1" }, true); - // READY & WAITING: serving no scopes. + // MAINTAINED, READY & WAITING: serving no scopes. + expectScopes(MyState(HA_MAINTAINED_ST), { }, false); expectScopes(MyState(HA_READY_ST), { }, false); expectScopes(MyState(HA_WAITING_ST), { }, false); } @@ -4082,7 +4086,9 @@ TEST_F(HAServiceStateMachineTest, shouldSendLeaseUpdatesLoadBalancing) { HAConfig::PeerConfigPtr peer_config = valid_config->getFailoverPeerConfig(); EXPECT_TRUE(expectLeaseUpdates(MyState(HA_LOAD_BALANCING_ST), peer_config)); + EXPECT_FALSE(expectLeaseUpdates(MyState(HA_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_PARTNER_DOWN_ST), peer_config)); + EXPECT_TRUE(expectLeaseUpdates(MyState(HA_PARTNER_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_READY_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_SYNCING_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_TERMINATED_ST), peer_config)); @@ -4100,7 +4106,9 @@ TEST_F(HAServiceStateMachineTest, shouldSendLeaseUpdatesDisabledLoadBalancing) { HAConfig::PeerConfigPtr peer_config = valid_config->getFailoverPeerConfig(); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_LOAD_BALANCING_ST), peer_config)); + EXPECT_FALSE(expectLeaseUpdates(MyState(HA_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_PARTNER_DOWN_ST), peer_config)); + EXPECT_FALSE(expectLeaseUpdates(MyState(HA_PARTNER_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_READY_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_SYNCING_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_TERMINATED_ST), peer_config)); @@ -4114,7 +4122,9 @@ TEST_F(HAServiceStateMachineTest, heartbeatLoadBalancing) { startService(valid_config); EXPECT_TRUE(expectHeartbeat(MyState(HA_LOAD_BALANCING_ST))); + EXPECT_TRUE(expectHeartbeat(MyState(HA_MAINTAINED_ST))); EXPECT_TRUE(expectHeartbeat(MyState(HA_PARTNER_DOWN_ST))); + EXPECT_TRUE(expectHeartbeat(MyState(HA_PARTNER_MAINTAINED_ST))); EXPECT_TRUE(expectHeartbeat(MyState(HA_READY_ST))); EXPECT_FALSE(expectHeartbeat(MyState(HA_TERMINATED_ST))); EXPECT_TRUE(expectHeartbeat(MyState(HA_WAITING_ST))); @@ -4519,10 +4529,12 @@ TEST_F(HAServiceStateMachineTest, scopesServingHotStandbyPrimary) { expectScopes(MyState(HA_HOT_STANDBY_ST), { "server1" }, true); expectScopes(MyState(HA_TERMINATED_ST), { "server1" }, true); - // PARTNER DOWN: still serving my own scope. + // PARTNER DOWN and PARTNER MAINTAINED: still serving my own scope. expectScopes(MyState(HA_PARTNER_DOWN_ST), { "server1" }, true); + expectScopes(MyState(HA_PARTNER_MAINTAINED_ST), { "server1" }, true); - // READY & WAITING: serving no scopes. + // MAINTAINED, READY & WAITING: serving no scopes. + expectScopes(MyState(HA_MAINTAINED_ST), { }, false); expectScopes(MyState(HA_READY_ST), { }, false); expectScopes(MyState(HA_WAITING_ST), { }, false); } @@ -4544,10 +4556,12 @@ TEST_F(HAServiceStateMachineTest, scopesServingHotStandbyPrimaryNoFailover) { expectScopes(MyState(HA_HOT_STANDBY_ST), { "server1" }, true); expectScopes(MyState(HA_TERMINATED_ST), { "server1" }, true); - // PARTNER DOWN: still serving my own scope. + // PARTNER MAINTAINED & PARTNER DOWN: still serving my own scope. expectScopes(MyState(HA_PARTNER_DOWN_ST), { "server1" }, true); + expectScopes(MyState(HA_PARTNER_MAINTAINED_ST), { "server1" }, true); - // READY & WAITING: serving no scopes. + // MAINTAINED, READY & WAITING: serving no scopes. + expectScopes(MyState(HA_MAINTAINED_ST), { }, false); expectScopes(MyState(HA_READY_ST), { }, false); expectScopes(MyState(HA_WAITING_ST), { }, false); } @@ -4567,7 +4581,9 @@ TEST_F(HAServiceStateMachineTest, shouldSendLeaseUpdatesHotStandbyPrimary) { HAConfig::PeerConfigPtr peer_config = valid_config->getFailoverPeerConfig(); EXPECT_TRUE(expectLeaseUpdates(MyState(HA_HOT_STANDBY_ST), peer_config)); + EXPECT_FALSE(expectLeaseUpdates(MyState(HA_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_PARTNER_DOWN_ST), peer_config)); + EXPECT_TRUE(expectLeaseUpdates(MyState(HA_PARTNER_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_READY_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_SYNCING_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_TERMINATED_ST), peer_config)); @@ -4576,7 +4592,7 @@ TEST_F(HAServiceStateMachineTest, shouldSendLeaseUpdatesHotStandbyPrimary) { // This test verifies if the server would send heartbeat to the partner // while being in various states. The HA configuration is hot standby. -TEST_F(HAServiceStateMachineTest, heartbeatHotstandby) { +TEST_F(HAServiceStateMachineTest, heartbeatHotStandby) { HAConfigPtr valid_config = createValidConfiguration(); // Turn it into hot-standby configuration. @@ -4586,7 +4602,9 @@ TEST_F(HAServiceStateMachineTest, heartbeatHotstandby) { startService(valid_config); EXPECT_TRUE(expectHeartbeat(MyState(HA_HOT_STANDBY_ST))); + EXPECT_TRUE(expectHeartbeat(MyState(HA_MAINTAINED_ST))); EXPECT_TRUE(expectHeartbeat(MyState(HA_PARTNER_DOWN_ST))); + EXPECT_TRUE(expectHeartbeat(MyState(HA_PARTNER_MAINTAINED_ST))); EXPECT_TRUE(expectHeartbeat(MyState(HA_READY_ST))); EXPECT_FALSE(expectHeartbeat(MyState(HA_TERMINATED_ST))); EXPECT_TRUE(expectHeartbeat(MyState(HA_WAITING_ST))); @@ -4613,10 +4631,12 @@ TEST_F(HAServiceStateMachineTest, scopesServingHotStandbyStandby) { // TERMINATED: serving no scopes because the primary is active. expectScopes(MyState(HA_TERMINATED_ST), { }, true); - // PARTNER DOWN: serving server1's scope. + // PARTNER MAINTAINED & PARTNER DOWN: serving server1's scope. expectScopes(MyState(HA_PARTNER_DOWN_ST), { "server1" }, true); + expectScopes(MyState(HA_PARTNER_MAINTAINED_ST), { "server1" }, true); - // READY & WAITING: serving no scopes. + // MAINTAINED, READY & WAITING: serving no scopes. + expectScopes(MyState(HA_MAINTAINED_ST), { }, false); expectScopes(MyState(HA_READY_ST), { }, false); expectScopes(MyState(HA_WAITING_ST), { }, false); } @@ -4644,11 +4664,13 @@ TEST_F(HAServiceStateMachineTest, scopesServingHotStandbyStandbyNoFailover) { // TERMINATED: serving no scopes because the primary is active. expectScopes(MyState(HA_TERMINATED_ST), { }, true); - // PARTNER DOWN: still serving no scopes because auto-failover is + // PARTNER MAINTAINED & PARTNER DOWN: still serving no scopes because auto-failover is // set to false. expectScopes(MyState(HA_PARTNER_DOWN_ST), { }, true); + expectScopes(MyState(HA_PARTNER_MAINTAINED_ST), { }, true); - // READY & WAITING: serving no scopes. + // MAINTAINED, READY & WAITING: serving no scopes. + expectScopes(MyState(HA_MAINTAINED_ST), { }, false); expectScopes(MyState(HA_READY_ST), { }, false); expectScopes(MyState(HA_WAITING_ST), { }, false); } @@ -4669,7 +4691,9 @@ TEST_F(HAServiceStateMachineTest, shouldSendLeaseUpdatesHotStandbyStandby) { HAConfig::PeerConfigPtr peer_config = valid_config->getFailoverPeerConfig(); EXPECT_TRUE(expectLeaseUpdates(MyState(HA_HOT_STANDBY_ST), peer_config)); + EXPECT_FALSE(expectLeaseUpdates(MyState(HA_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_PARTNER_DOWN_ST), peer_config)); + EXPECT_TRUE(expectLeaseUpdates(MyState(HA_PARTNER_MAINTAINED_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_READY_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_SYNCING_ST), peer_config)); EXPECT_FALSE(expectLeaseUpdates(MyState(HA_TERMINATED_ST), peer_config));