summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcin Siodelski <marcin@isc.org>2018-07-11 14:13:50 +0200
committerMarcin Siodelski <marcin@isc.org>2018-07-11 14:13:50 +0200
commit717006b2c0bbe1ca8d9151e1a0b8537d30c8f52f (patch)
treefa01495caac8c68a0a08411e126370c323fb28f8
parent[5674] Implemented HA pause for ordinary states. (diff)
downloadkea-717006b2c0bbe1ca8d9151e1a0b8537d30c8f52f.tar.xz
kea-717006b2c0bbe1ca8d9151e1a0b8537d30c8f52f.zip
[5674] State machine pausing in syncing state.
-rw-r--r--src/hooks/dhcp/high_availability/ha_service.cc6
-rw-r--r--src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc50
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) {