diff options
author | Marcin Siodelski <marcin@isc.org> | 2018-07-11 14:13:50 +0200 |
---|---|---|
committer | Marcin Siodelski <marcin@isc.org> | 2018-07-11 14:13:50 +0200 |
commit | 717006b2c0bbe1ca8d9151e1a0b8537d30c8f52f (patch) | |
tree | fa01495caac8c68a0a08411e126370c323fb28f8 | |
parent | [5674] Implemented HA pause for ordinary states. (diff) | |
download | kea-717006b2c0bbe1ca8d9151e1a0b8537d30c8f52f.tar.xz kea-717006b2c0bbe1ca8d9151e1a0b8537d30c8f52f.zip |
[5674] State machine pausing in syncing state.
-rw-r--r-- | src/hooks/dhcp/high_availability/ha_service.cc | 6 | ||||
-rw-r--r-- | src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc | 50 |
2 files changed, 56 insertions, 0 deletions
diff --git a/src/hooks/dhcp/high_availability/ha_service.cc b/src/hooks/dhcp/high_availability/ha_service.cc index cb18d91230..e917e13017 100644 --- a/src/hooks/dhcp/high_availability/ha_service.cc +++ b/src/hooks/dhcp/high_availability/ha_service.cc @@ -296,6 +296,12 @@ HAService::syncingStateHandler() { if (doOnEntry()) { query_filter_.serveNoScopes(); adjustNetworkState(); + state_machine_control_.notify(getCurrState()); + } + + if (state_machine_control_.amPaused()) { + postNextEvent(NOP_EVT); + return; } // Check if the clock skew is still acceptable. If not, transition to 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 8151ec6bbf..1fcfaa630b 100644 --- a/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc +++ b/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc @@ -3555,6 +3555,7 @@ TEST_F(HAServiceStateMachineTest, stateTransitionsLoadBalancingPause) { HAConfigPtr valid_config = createValidConfiguration(); auto state_configs = valid_config->getStateMachineConfig(); + // Set state machine pausing in all states. for (auto cfg = state_configs.begin(); cfg != state_configs.end(); ++cfg) { cfg->second->setPausing("always"); } @@ -3612,6 +3613,55 @@ TEST_F(HAServiceStateMachineTest, stateTransitionsLoadBalancingPause) { } } +// This test verifies that the HA state machine can be paused in the syncing +// state. +TEST_F(HAServiceStateMachineTest, syncingTransitionsLoadBalancingPause) { + HAConfigPtr valid_config = createValidConfiguration(); + + // Pause state machine in syncing state. + auto state_config = valid_config->getStateConfig(HA_SYNCING_ST); + state_config->setPausing("always"); + + startService(valid_config); + waitForEvent(HAService::HA_HEARTBEAT_COMPLETE_EVT); + + // The syncing state handler doesn't start synchronization until it + // detects that the partner is online. It may remember that from the + // previous heartbeat attempts. If the partner appears to be unavailable + // it will continue heartbeats before it synchronizes. This prevents the + // server from making endless attempts to synchronize without any chance + // to succeed. We verify that the server is not trying to synchronize + // by checking that the last event is not the one associated with the + // synchronization attempt. + ASSERT_NE(service_->getLastEvent(), HAService::HA_SYNCING_FAILED_EVT); + ASSERT_NE(service_->getLastEvent(), HAService::HA_SYNCING_SUCCEEDED_EVT); + + // Startup the partner. + partner_->enableRespondLeaseFetching(); + partner_->startup(); + + // We haven't been running heartbeats so we have to manually set the + // partner's state to something other than 'unavailable'. + state_->setPartnerState("ready"); + + // Run the syncing state handler. + testSyncingTransition(FinalState(HA_SYNCING_ST)); + + // We should see no synchronization attempts because the server is paused + // in this state. + EXPECT_NE(service_->getLastEvent(), HAService::HA_SYNCING_FAILED_EVT); + EXPECT_NE(service_->getLastEvent(), HAService::HA_SYNCING_SUCCEEDED_EVT); + + // Unpause the state machine. + service_->unpause(); + + // Retry the test. It should now transition to the ready state. + testSyncingTransition(FinalState(HA_READY_ST)); + + // This time the server should have synchronized. + EXPECT_EQ(HAService::HA_SYNCING_SUCCEEDED_EVT, service_->getLastEvent()); +} + // This test verifies that the server takes ownership of the given scopes // and whether the DHCP service is disabled or enabled in certain states. TEST_F(HAServiceStateMachineTest, scopesServingLoadBalancing) { |