]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5674] State machine pausing in syncing state.
authorMarcin Siodelski <marcin@isc.org>
Wed, 11 Jul 2018 12:13:50 +0000 (14:13 +0200)
committerMarcin Siodelski <marcin@isc.org>
Wed, 11 Jul 2018 12:13:50 +0000 (14:13 +0200)
src/hooks/dhcp/high_availability/ha_service.cc
src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc

index cb18d91230102195ca5e88da217a4cb0678e4587..e917e130173640c1e6025a7773f1d34c765685fa 100644 (file)
@@ -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
index 8151ec6bbff0152d92255940ac997761099d638a..1fcfaa630ba5d17adb5f771e1fdac366cb3030f0 100644 (file)
@@ -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) {