Commit a88eb83e authored by Marcin Siodelski's avatar Marcin Siodelski

[5674] Use pausing capability of StateModel in HA library.

parent 2a727b6e
......@@ -35,7 +35,6 @@ libha_la_SOURCES += ha_log.cc ha_log.h
libha_la_SOURCES += ha_server_type.h
libha_la_SOURCES += ha_service.cc ha_service.h
libha_la_SOURCES += ha_service_states.cc ha_service_states.h
libha_la_SOURCES += ha_state_machine_control.cc ha_state_machine_control.h
libha_la_SOURCES += query_filter.cc query_filter.h
libha_la_SOURCES += version.cc
......
......@@ -10,6 +10,8 @@
#include <ha_service_states.h>
#include <sstream>
using namespace isc::util;
namespace isc {
namespace ha {
......@@ -78,7 +80,7 @@ HAConfig::PeerConfig::roleToString(const HAConfig::PeerConfig::Role& role) {
}
HAConfig::StateConfig::StateConfig(const int state)
: state_(state), pausing_(HAConfig::StateConfig::PAUSE_NEVER) {
: state_(state), pausing_(STATE_PAUSE_NEVER) {
}
void
......@@ -86,31 +88,31 @@ HAConfig::StateConfig::setPausing(const std::string& pausing) {
pausing_ = stringToPausing(pausing);
}
HAConfig::StateConfig::Pausing
StatePausing
HAConfig::StateConfig::stringToPausing(const std::string& pausing) {
if (pausing == "always") {
return (HAConfig::StateConfig::PAUSE_ALWAYS);
return (STATE_PAUSE_ALWAYS);
} else if (pausing == "never") {
return (HAConfig::StateConfig::PAUSE_NEVER);
return (STATE_PAUSE_NEVER);
} else if (pausing == "once") {
return (HAConfig::StateConfig::PAUSE_ONCE);
return (STATE_PAUSE_ONCE);
}
isc_throw(BadValue, "unsupported value " << pausing << " of 'pause' parameter");
}
std::string
HAConfig::StateConfig::pausingToString(const HAConfig::StateConfig::Pausing& pausing) {
HAConfig::StateConfig::pausingToString(const StatePausing& pausing) {
switch (pausing) {
case HAConfig::StateConfig::PAUSE_ALWAYS:
case STATE_PAUSE_ALWAYS:
return ("always");
case HAConfig::StateConfig::PAUSE_NEVER:
case STATE_PAUSE_NEVER:
return ("never");
case HAConfig::StateConfig::PAUSE_ONCE:
case STATE_PAUSE_ONCE:
return ("once");
default:
......
......@@ -9,6 +9,7 @@
#include <exceptions/exceptions.h>
#include <http/url.h>
#include <util/state_model.h>
#include <boost/shared_ptr.hpp>
#include <cstdint>
#include <map>
......@@ -165,18 +166,6 @@ public:
class StateConfig {
public:
/// @brief State machine pausing modes.
///
/// Supported modes are:
/// - always pause in the given state,
/// - never pause in the given state,
/// - pause upon first transition to the given state.
enum Pausing {
PAUSE_ALWAYS,
PAUSE_NEVER,
PAUSE_ONCE
};
/// @brief Constructor.
///
/// @param state state identifier.
......@@ -188,7 +177,7 @@ public:
}
/// @brief Returns pausing mode for the given state.
Pausing getPausing() const {
util::StatePausing getPausing() const {
return (pausing_);
}
......@@ -202,12 +191,12 @@ public:
///
/// @param pausing pausing mode in the textual form. Supported
/// values are: always, never, once.
static Pausing stringToPausing(const std::string& pausing);
static util::StatePausing stringToPausing(const std::string& pausing);
/// @brief Returns pausing mode in the textual form.
///
/// @param pausing pausing mode.
static std::string pausingToString(const Pausing& pausing);
static std::string pausingToString(const util::StatePausing& pausing);
private:
......@@ -215,7 +204,7 @@ public:
int state_;
/// @brief Pausing mode in the given state.
Pausing pausing_;
util::StatePausing pausing_;
};
/// @brief Pointer to the state configuration.
......
......@@ -45,7 +45,7 @@ HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& netw
const HAConfigPtr& config, const HAServerType& server_type)
: io_service_(io_service), network_state_(network_state), config_(config),
server_type_(server_type), client_(*io_service), communication_state_(),
query_filter_(config), state_machine_control_(config), pending_requests_() {
query_filter_(config), pending_requests_() {
if (server_type == HAServerType::DHCPv4) {
communication_state_.reset(new CommunicationState4(io_service_, config));
......@@ -55,7 +55,6 @@ HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& netw
}
startModel(HA_WAITING_ST);
state_machine_control_.notify(HA_WAITING_ST);
LOG_INFO(ha_logger, HA_SERVICE_STARTED)
.arg(HAConfig::HAModeToString(config->getHAMode()))
......@@ -87,28 +86,36 @@ HAService::defineStates() {
StateModel::defineStates();
defineState(HA_BACKUP_ST, stateToString(HA_BACKUP_ST),
boost::bind(&HAService::backupStateHandler, this));
boost::bind(&HAService::backupStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_BACKUP_ST)->getPausing());
defineState(HA_HOT_STANDBY_ST, stateToString(HA_HOT_STANDBY_ST),
boost::bind(&HAService::normalStateHandler, this));
boost::bind(&HAService::normalStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_HOT_STANDBY_ST)->getPausing());
defineState(HA_LOAD_BALANCING_ST, stateToString(HA_LOAD_BALANCING_ST),
boost::bind(&HAService::normalStateHandler, this));
boost::bind(&HAService::normalStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_LOAD_BALANCING_ST)->getPausing());
defineState(HA_PARTNER_DOWN_ST, stateToString(HA_PARTNER_DOWN_ST),
boost::bind(&HAService::partnerDownStateHandler, this));
boost::bind(&HAService::partnerDownStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_PARTNER_DOWN_ST)->getPausing());
defineState(HA_READY_ST, stateToString(HA_READY_ST),
boost::bind(&HAService::readyStateHandler, this));
boost::bind(&HAService::readyStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_READY_ST)->getPausing());
defineState(HA_SYNCING_ST, stateToString(HA_SYNCING_ST),
boost::bind(&HAService::syncingStateHandler, this));
boost::bind(&HAService::syncingStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_SYNCING_ST)->getPausing());
defineState(HA_TERMINATED_ST, stateToString(HA_TERMINATED_ST),
boost::bind(&HAService::terminatedStateHandler, this));
boost::bind(&HAService::terminatedStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_TERMINATED_ST)->getPausing());
defineState(HA_WAITING_ST, stateToString(HA_WAITING_ST),
boost::bind(&HAService::waitingStateHandler, this));
boost::bind(&HAService::waitingStateHandler, this),
config_->getStateMachineConfig()->getStateConfig(HA_WAITING_ST)->getPausing());
}
void
......@@ -135,7 +142,7 @@ HAService::normalStateHandler() {
scheduleHeartbeat();
if (state_machine_control_.amPaused()) {
if (isModelPaused()) {
postNextEvent(NOP_EVT);
return;
}
......@@ -190,7 +197,7 @@ HAService::partnerDownStateHandler() {
scheduleHeartbeat();
if (state_machine_control_.amPaused()) {
if (isModelPaused()) {
postNextEvent(NOP_EVT);
return;
}
......@@ -235,7 +242,7 @@ HAService::readyStateHandler() {
scheduleHeartbeat();
if (state_machine_control_.amPaused()) {
if (isModelPaused()) {
postNextEvent(NOP_EVT);
return;
}
......@@ -295,7 +302,7 @@ HAService::syncingStateHandler() {
adjustNetworkState();
}
if (state_machine_control_.amPaused()) {
if (isModelPaused()) {
postNextEvent(NOP_EVT);
return;
}
......@@ -389,7 +396,7 @@ HAService::waitingStateHandler() {
scheduleHeartbeat();
}
if (state_machine_control_.amPaused()) {
if (isModelPaused()) {
postNextEvent(NOP_EVT);
return;
}
......@@ -482,7 +489,6 @@ HAService::verboseTransition(const unsigned state) {
// Do the actual transition.
transition(state, getNextEvent());
state_machine_control_.notify(state);
// Inform the administrator whether or not lease updates are generated.
// Updates are never generated by a backup server so it doesn't make
......@@ -505,11 +511,24 @@ HAService::verboseTransition(const unsigned state) {
.arg(new_state_name);
}
}
// Inform the administrator if the state machine is paused.
if (isModelPaused()) {
std::string state_name = stateToString(state);
boost::to_upper(state_name);
LOG_INFO(ha_logger, HA_STATE_MACHINE_PAUSED)
.arg(state_name);
}
}
void
bool
HAService::unpause() {
state_machine_control_.unpause();
if (isModelPaused()) {
LOG_INFO(ha_logger, HA_STATE_MACHINE_CONTINUED);
unpauseModel();
return (true);
}
return (false);
}
void
......
......@@ -10,7 +10,6 @@
#include <communication_state.h>
#include <ha_config.h>
#include <ha_server_type.h>
#include <ha_state_machine_control.h>
#include <query_filter.h>
#include <asiolink/io_service.h>
#include <cc/data.h>
......@@ -247,12 +246,14 @@ protected:
public:
/// @brief Un-pauses the state machine.
/// @brief Unpauses the HA state machine with logging.
///
/// This is method is invoked when the server receives the 'ha-continue'
/// command which instructs the server to unblock the HA state machine
/// so as it may transition to a next state.
void unpause();
/// It un-pauses the state machine if it is paused and logs an informational
/// message. It doesn't log the message if the state machine is not paused.
///
/// @return true if the state machine was unpaused, false if the state
/// machine was not paused when this method was invoked.
bool unpause();
/// @brief Instructs the HA service to serve default scopes.
///
......@@ -643,9 +644,6 @@ protected:
/// @brief Selects queries to be processed/dropped.
QueryFilter query_filter_;
/// @brief Controls state machine pausing and unpausing.
HAStateMachineControl state_machine_control_;
/// @brief Map holding a number of scheduled requests for a given packet.
///
/// A single callout may send multiple requests at the same time, e.g.
......
// Copyright (C) 2018 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
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <ha_log.h>
#include <ha_service_states.h>
#include <ha_state_machine_control.h>
#include <boost/algorithm/string.hpp>
namespace isc {
namespace ha {
HAStateMachineControl::HAStateMachineControl(const HAConfigPtr& config)
: config_(config), paused_(false), visited_states_() {
}
void
HAStateMachineControl::notify(const int state) {
// Always get the configuration to verify that the state identifier is
// recognized.
HAConfig::StateConfigPtr state_config = config_->getStateMachineConfig()->
getStateConfig(state);
// Pause if we should always pause in this state or we should pause once
// and this is the first time we visit this state.
bool first_visit = (visited_states_.count(state) == 0);
// If this is the first time we're in this state, record it.
if (first_visit) {
visited_states_.insert(state);
}
// Only pause the state machine if it is not paused already.
if (!amPaused()) {
if ((state_config->getPausing() == HAConfig::StateConfig::PAUSE_ALWAYS) ||
((state_config->getPausing() == HAConfig::StateConfig::PAUSE_ONCE) &&
first_visit)) {
std::string state_name = stateToString(state);
boost::to_upper(state_name);
LOG_INFO(ha_logger, HA_STATE_MACHINE_PAUSED)
.arg(state_name);
paused_ = true;
}
}
}
void
HAStateMachineControl::unpause() {
if (amPaused()) {
LOG_INFO(ha_logger, HA_STATE_MACHINE_CONTINUED);
paused_ = false;
}
}
} // end of namespace isc::ha
} // end of namespace isc
// Copyright (C) 2018 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
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef HA_STATE_MACHINE_CONTROL_H
#define HA_STATE_MACHINE_CONTROL_H
#include <ha_config.h>
#include <boost/shared_ptr.hpp>
#include <set>
namespace isc {
namespace ha {
/// @brief Hold runtime information about HA state machine.
///
/// Currently, the only available runtime information is whether the
/// state machine is paused and if it should paused in certain states
/// upon next transition to these states. Note that the server may be
/// configured to only pause the state machine upon the first transition
/// to the certain states.
///
/// The @c HAService calls @c notify upon transition to the next state.
/// This class determines whether the state machine should be paused
/// in this state based on the provided configuration and the history
/// of already visited states. The @c amPaused method should be later
/// called in the state handlers to check if the state machine is
/// paused or running. In the former case, it should not transition to
/// any other state until the state machine is unpaused.
class HAStateMachineControl {
public:
/// @brief Constructor.
///
/// @param config HA hooks library configuration.
explicit HAStateMachineControl(const HAConfigPtr& config);
/// @brief Receives notification from the HA state handlers about
/// the current state.
///
/// This method pauses sets a flag to pause the HA state machine if
/// it should be paused in the given state. It also records that
/// state as "visited", so as it is possible to determine whether
/// the state machine should be paused the next time it transitions
/// to this state.
///
/// @param state current state of the state machine.
/// @throw BadValue if the state is not recognized.
void notify(int state);
/// @brief Informs whether the state machine is paused.
///
/// @return true if the state machine is paused, false otherwise.
bool amPaused() const {
return (paused_);
}
/// @brief Clears flag indicating that the state machine is paused.
void unpause();
private:
/// @brief HA configuration
HAConfigPtr config_;
/// @brief Boolean flag indicating if the state machine is paused.
bool paused_;
/// @brief Keeps track of visited states.
std::set<int> visited_states_;
};
/// @brief Shared pointer to the @c HAStateMachineControl.
typedef boost::shared_ptr<HAStateMachineControl> HAStateMachineControlPtr;
} // end of namespace isc::ha
} // end of namespace isc
#endif
......@@ -29,7 +29,6 @@ ha_unittests_SOURCES += communication_state_unittest.cc
ha_unittests_SOURCES += ha_config_unittest.cc
ha_unittests_SOURCES += ha_impl_unittest.cc
ha_unittests_SOURCES += ha_service_unittest.cc
ha_unittests_SOURCES += ha_state_machine_control_unittest.cc
ha_unittests_SOURCES += ha_test.cc ha_test.h
ha_unittests_SOURCES += query_filter_unittest.cc
ha_unittests_SOURCES += run_unittests.cc
......
......@@ -13,6 +13,7 @@
#include <cc/data.h>
#include <cc/dhcp_config_error.h>
#include <config/command_mgr.h>
#include <util/state_model.h>
#include <string>
using namespace isc;
......@@ -21,6 +22,7 @@ using namespace isc::data;
using namespace isc::ha;
using namespace isc::hooks;
using namespace isc::ha::test;
using namespace isc::util;
namespace {
......@@ -150,37 +152,37 @@ TEST_F(HAConfigTest, configureLoadBalancing) {
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_BACKUP_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_LOAD_BALANCING_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_PARTNER_DOWN_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_READY_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_ALWAYS, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_ALWAYS, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_SYNCING_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_TERMINATED_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_WAITING_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_ONCE, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_ONCE, state_cfg->getPausing());
}
// Verifies that load balancing configuration is parsed correctly.
......@@ -249,37 +251,37 @@ TEST_F(HAConfigTest, configureHotStandby) {
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_BACKUP_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_HOT_STANDBY_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_PARTNER_DOWN_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_READY_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_SYNCING_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_TERMINATED_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_WAITING_ST));
ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER, state_cfg->getPausing());
EXPECT_EQ(STATE_PAUSE_NEVER, state_cfg->getPausing());
}
// This server name must not be empty.
......@@ -985,22 +987,22 @@ TEST_F(HAConfigTest, HAModeToString) {
// Test that conversion of the 'pause' value works correctly.
TEST_F(HAConfigTest, stringToPausing) {
EXPECT_EQ(HAConfig::StateConfig::PAUSE_ALWAYS,
EXPECT_EQ(STATE_PAUSE_ALWAYS,
HAConfig::StateConfig::stringToPausing("always"));
EXPECT_EQ(HAConfig::StateConfig::PAUSE_NEVER,
EXPECT_EQ(STATE_PAUSE_NEVER,
HAConfig::StateConfig::stringToPausing("never"));
EXPECT_EQ(HAConfig::StateConfig::PAUSE_ONCE,
EXPECT_EQ(STATE_PAUSE_ONCE,
HAConfig::StateConfig::stringToPausing("once"));
}
// Test that pause parameter value is generated correctly.
TEST_F(HAConfigTest, pausingToString) {
EXPECT_EQ("always",
HAConfig::StateConfig::pausingToString(HAConfig::StateConfig::PAUSE_ALWAYS));
HAConfig::StateConfig::pausingToString(STATE_PAUSE_ALWAYS));
EXPECT_EQ("never",
HAConfig::StateConfig::pausingToString(HAConfig::StateConfig::PAUSE_NEVER));
HAConfig::StateConfig::pausingToString(STATE_PAUSE_NEVER));
EXPECT_EQ("once",
HAConfig::StateConfig::pausingToString(HAConfig::StateConfig::PAUSE_ONCE));
HAConfig::StateConfig::pausingToString(STATE_PAUSE_ONCE));
}
......
......@@ -3573,7 +3573,9 @@ TEST_F(HAServiceStateMachineTest, stateTransitionsLoadBalancingPause) {
FinalState(HA_LOAD_BALANCING_ST));
EXPECT_TRUE(state_->isHeartbeatRunning());
service_->unpause();
EXPECT_TRUE(service_->unpause());
// An additional attempt to unpause should return false.
EXPECT_FALSE(service_->unpause());
testTransition(MyState(HA_LOAD_BALANCING_ST), PartnerState(HA_TERMINATED_ST),
FinalState(HA_TERMINATED_ST));
......@@ -3587,7 +3589,7 @@ TEST_F(HAServiceStateMachineTest, stateTransitionsLoadBalancingPause) {
FinalState(HA_PARTNER_DOWN_ST));
EXPECT_TRUE(state_->isHeartbeatRunning());
service_->unpause();
EXPECT_TRUE(service_->unpause());
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_LOAD_BALANCING_ST),
FinalState(HA_WAITING_ST));
......@@ -3602,7 +3604,7 @@ TEST_F(HAServiceStateMachineTest, stateTransitionsLoadBalancingPause) {
FinalState(HA_READY_ST));
EXPECT_TRUE(state_->isHeartbeatRunning());
service_->unpause();
EXPECT_TRUE(service_->unpause());
testTransition(MyState(HA_READY_ST), PartnerState(HA_LOAD_BALANCING_ST),
FinalState(HA_LOAD_BALANCING_ST));
......@@ -3617,7 +3619,7 @@ TEST_F(HAServiceStateMachineTest, stateTransitionsLoadBalancingPause) {
FinalState(HA_WAITING_ST));
EXPECT_TRUE(state_->isHeartbeatRunning());
service_->unpause();
EXPECT_TRUE(service_->unpause());
testTransition(MyState(HA_WAITING_ST), PartnerState(HA_LOAD_BALANCING_ST),
FinalState(HA_SYNCING_ST));
......@@ -3671,7 +3673,7 @@ TEST_F(HAServiceStateMachineTest, syncingTransitionsLoadBalancingPause) {
EXPECT_NE(service_->getLastEvent(), HAService::HA_SYNCING_SUCCEEDED_EVT);
// Unpause the state machine.
service_->unpause();
EXPECT_TRUE(service_->unpause());
// Retry the test. It should now transition to the ready state.
testSyncingTransition(FinalState(HA_READY_ST));
......
// Copyright (C) 2018 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
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <ha_state_machine_control.h>
#include <ha_test.h>
#include <gtest/gtest.h>
using namespace isc::ha;
using namespace isc::ha::test;
namespace {
class HAStateMachineControlTest : public HATest {
public:
/// @brief Constructor.
HAStateMachineControlTest()
: HATest() {
}
};
// This test verifies that pausing HA state machine works as expected.
TEST_F(HAStateMachineControlTest, pause) {
HAConfigPtr config = createValidConfiguration();
// Always pause in the waiting state and pause on first transition to
// the ready state. Do not pause for other states.
config->getStateMachineConfig()->getStateConfig(HA_WAITING_ST)->setPausing("always");
config->getStateMachineConfig()->getStateConfig(HA_READY_ST)->setPausing("once");
// Initially we shouldn't be paused.