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 ...@@ -35,7 +35,6 @@ libha_la_SOURCES += ha_log.cc ha_log.h
libha_la_SOURCES += ha_server_type.h libha_la_SOURCES += ha_server_type.h
libha_la_SOURCES += ha_service.cc ha_service.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_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 += query_filter.cc query_filter.h
libha_la_SOURCES += version.cc libha_la_SOURCES += version.cc
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <ha_service_states.h> #include <ha_service_states.h>
#include <sstream> #include <sstream>
using namespace isc::util;
namespace isc { namespace isc {
namespace ha { namespace ha {
...@@ -78,7 +80,7 @@ HAConfig::PeerConfig::roleToString(const HAConfig::PeerConfig::Role& role) { ...@@ -78,7 +80,7 @@ HAConfig::PeerConfig::roleToString(const HAConfig::PeerConfig::Role& role) {
} }
HAConfig::StateConfig::StateConfig(const int state) HAConfig::StateConfig::StateConfig(const int state)
: state_(state), pausing_(HAConfig::StateConfig::PAUSE_NEVER) { : state_(state), pausing_(STATE_PAUSE_NEVER) {
} }
void void
...@@ -86,31 +88,31 @@ HAConfig::StateConfig::setPausing(const std::string& pausing) { ...@@ -86,31 +88,31 @@ HAConfig::StateConfig::setPausing(const std::string& pausing) {
pausing_ = stringToPausing(pausing); pausing_ = stringToPausing(pausing);
} }
HAConfig::StateConfig::Pausing StatePausing
HAConfig::StateConfig::stringToPausing(const std::string& pausing) { HAConfig::StateConfig::stringToPausing(const std::string& pausing) {
if (pausing == "always") { if (pausing == "always") {
return (HAConfig::StateConfig::PAUSE_ALWAYS); return (STATE_PAUSE_ALWAYS);
} else if (pausing == "never") { } else if (pausing == "never") {
return (HAConfig::StateConfig::PAUSE_NEVER); return (STATE_PAUSE_NEVER);
} else if (pausing == "once") { } else if (pausing == "once") {
return (HAConfig::StateConfig::PAUSE_ONCE); return (STATE_PAUSE_ONCE);
} }
isc_throw(BadValue, "unsupported value " << pausing << " of 'pause' parameter"); isc_throw(BadValue, "unsupported value " << pausing << " of 'pause' parameter");
} }
std::string std::string
HAConfig::StateConfig::pausingToString(const HAConfig::StateConfig::Pausing& pausing) { HAConfig::StateConfig::pausingToString(const StatePausing& pausing) {
switch (pausing) { switch (pausing) {
case HAConfig::StateConfig::PAUSE_ALWAYS: case STATE_PAUSE_ALWAYS:
return ("always"); return ("always");
case HAConfig::StateConfig::PAUSE_NEVER: case STATE_PAUSE_NEVER:
return ("never"); return ("never");
case HAConfig::StateConfig::PAUSE_ONCE: case STATE_PAUSE_ONCE:
return ("once"); return ("once");
default: default:
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <http/url.h> #include <http/url.h>
#include <util/state_model.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <cstdint> #include <cstdint>
#include <map> #include <map>
...@@ -165,18 +166,6 @@ public: ...@@ -165,18 +166,6 @@ public:
class StateConfig { class StateConfig {
public: 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. /// @brief Constructor.
/// ///
/// @param state state identifier. /// @param state state identifier.
...@@ -188,7 +177,7 @@ public: ...@@ -188,7 +177,7 @@ public:
} }
/// @brief Returns pausing mode for the given state. /// @brief Returns pausing mode for the given state.
Pausing getPausing() const { util::StatePausing getPausing() const {
return (pausing_); return (pausing_);
} }
...@@ -202,12 +191,12 @@ public: ...@@ -202,12 +191,12 @@ public:
/// ///
/// @param pausing pausing mode in the textual form. Supported /// @param pausing pausing mode in the textual form. Supported
/// values are: always, never, once. /// 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. /// @brief Returns pausing mode in the textual form.
/// ///
/// @param pausing pausing mode. /// @param pausing pausing mode.
static std::string pausingToString(const Pausing& pausing); static std::string pausingToString(const util::StatePausing& pausing);
private: private:
...@@ -215,7 +204,7 @@ public: ...@@ -215,7 +204,7 @@ public:
int state_; int state_;
/// @brief Pausing mode in the given state. /// @brief Pausing mode in the given state.
Pausing pausing_; util::StatePausing pausing_;
}; };
/// @brief Pointer to the state configuration. /// @brief Pointer to the state configuration.
......
...@@ -45,7 +45,7 @@ HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& netw ...@@ -45,7 +45,7 @@ HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& netw
const HAConfigPtr& config, const HAServerType& server_type) const HAConfigPtr& config, const HAServerType& server_type)
: io_service_(io_service), network_state_(network_state), config_(config), : io_service_(io_service), network_state_(network_state), config_(config),
server_type_(server_type), client_(*io_service), communication_state_(), 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) { if (server_type == HAServerType::DHCPv4) {
communication_state_.reset(new CommunicationState4(io_service_, config)); communication_state_.reset(new CommunicationState4(io_service_, config));
...@@ -55,7 +55,6 @@ HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& netw ...@@ -55,7 +55,6 @@ HAService::HAService(const IOServicePtr& io_service, const NetworkStatePtr& netw
} }
startModel(HA_WAITING_ST); startModel(HA_WAITING_ST);
state_machine_control_.notify(HA_WAITING_ST);
LOG_INFO(ha_logger, HA_SERVICE_STARTED) LOG_INFO(ha_logger, HA_SERVICE_STARTED)
.arg(HAConfig::HAModeToString(config->getHAMode())) .arg(HAConfig::HAModeToString(config->getHAMode()))
...@@ -87,28 +86,36 @@ HAService::defineStates() { ...@@ -87,28 +86,36 @@ HAService::defineStates() {
StateModel::defineStates(); StateModel::defineStates();
defineState(HA_BACKUP_ST, stateToString(HA_BACKUP_ST), 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), 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), 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), 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), 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), 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), 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), 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 void
...@@ -135,7 +142,7 @@ HAService::normalStateHandler() { ...@@ -135,7 +142,7 @@ HAService::normalStateHandler() {
scheduleHeartbeat(); scheduleHeartbeat();
if (state_machine_control_.amPaused()) { if (isModelPaused()) {
postNextEvent(NOP_EVT); postNextEvent(NOP_EVT);
return; return;
} }
...@@ -190,7 +197,7 @@ HAService::partnerDownStateHandler() { ...@@ -190,7 +197,7 @@ HAService::partnerDownStateHandler() {
scheduleHeartbeat(); scheduleHeartbeat();
if (state_machine_control_.amPaused()) { if (isModelPaused()) {
postNextEvent(NOP_EVT); postNextEvent(NOP_EVT);
return; return;
} }
...@@ -235,7 +242,7 @@ HAService::readyStateHandler() { ...@@ -235,7 +242,7 @@ HAService::readyStateHandler() {
scheduleHeartbeat(); scheduleHeartbeat();
if (state_machine_control_.amPaused()) { if (isModelPaused()) {
postNextEvent(NOP_EVT); postNextEvent(NOP_EVT);
return; return;
} }
...@@ -295,7 +302,7 @@ HAService::syncingStateHandler() { ...@@ -295,7 +302,7 @@ HAService::syncingStateHandler() {
adjustNetworkState(); adjustNetworkState();
} }
if (state_machine_control_.amPaused()) { if (isModelPaused()) {
postNextEvent(NOP_EVT); postNextEvent(NOP_EVT);
return; return;
} }
...@@ -389,7 +396,7 @@ HAService::waitingStateHandler() { ...@@ -389,7 +396,7 @@ HAService::waitingStateHandler() {
scheduleHeartbeat(); scheduleHeartbeat();
} }
if (state_machine_control_.amPaused()) { if (isModelPaused()) {
postNextEvent(NOP_EVT); postNextEvent(NOP_EVT);
return; return;
} }
...@@ -482,7 +489,6 @@ HAService::verboseTransition(const unsigned state) { ...@@ -482,7 +489,6 @@ HAService::verboseTransition(const unsigned state) {
// Do the actual transition. // Do the actual transition.
transition(state, getNextEvent()); transition(state, getNextEvent());
state_machine_control_.notify(state);
// Inform the administrator whether or not lease updates are generated. // Inform the administrator whether or not lease updates are generated.
// Updates are never generated by a backup server so it doesn't make // Updates are never generated by a backup server so it doesn't make
...@@ -505,11 +511,24 @@ HAService::verboseTransition(const unsigned state) { ...@@ -505,11 +511,24 @@ HAService::verboseTransition(const unsigned state) {
.arg(new_state_name); .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() { HAService::unpause() {
state_machine_control_.unpause(); if (isModelPaused()) {
LOG_INFO(ha_logger, HA_STATE_MACHINE_CONTINUED);
unpauseModel();
return (true);
}
return (false);
} }
void void
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <communication_state.h> #include <communication_state.h>
#include <ha_config.h> #include <ha_config.h>
#include <ha_server_type.h> #include <ha_server_type.h>
#include <ha_state_machine_control.h>
#include <query_filter.h> #include <query_filter.h>
#include <asiolink/io_service.h> #include <asiolink/io_service.h>
#include <cc/data.h> #include <cc/data.h>
...@@ -247,12 +246,14 @@ protected: ...@@ -247,12 +246,14 @@ protected:
public: 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' /// It un-pauses the state machine if it is paused and logs an informational
/// command which instructs the server to unblock the HA state machine /// message. It doesn't log the message if the state machine is not paused.
/// so as it may transition to a next state. ///
void unpause(); /// @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. /// @brief Instructs the HA service to serve default scopes.
/// ///
...@@ -643,9 +644,6 @@ protected: ...@@ -643,9 +644,6 @@ protected:
/// @brief Selects queries to be processed/dropped. /// @brief Selects queries to be processed/dropped.
QueryFilter query_filter_; 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. /// @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. /// 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 ...@@ -29,7 +29,6 @@ ha_unittests_SOURCES += communication_state_unittest.cc
ha_unittests_SOURCES += ha_config_unittest.cc ha_unittests_SOURCES += ha_config_unittest.cc
ha_unittests_SOURCES += ha_impl_unittest.cc ha_unittests_SOURCES += ha_impl_unittest.cc
ha_unittests_SOURCES += ha_service_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 += ha_test.cc ha_test.h
ha_unittests_SOURCES += query_filter_unittest.cc ha_unittests_SOURCES += query_filter_unittest.cc
ha_unittests_SOURCES += run_unittests.cc ha_unittests_SOURCES += run_unittests.cc
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <cc/data.h> #include <cc/data.h>
#include <cc/dhcp_config_error.h> #include <cc/dhcp_config_error.h>
#include <config/command_mgr.h> #include <config/command_mgr.h>
#include <util/state_model.h>
#include <string> #include <string>
using namespace isc; using namespace isc;
...@@ -21,6 +22,7 @@ using namespace isc::data; ...@@ -21,6 +22,7 @@ using namespace isc::data;
using namespace isc::ha; using namespace isc::ha;
using namespace isc::hooks; using namespace isc::hooks;
using namespace isc::ha::test; using namespace isc::ha::test;
using namespace isc::util;
namespace { namespace {
...@@ -150,37 +152,37 @@ TEST_F(HAConfigTest, configureLoadBalancing) { ...@@ -150,37 +152,37 @@ TEST_F(HAConfigTest, configureLoadBalancing) {
ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()-> ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_BACKUP_ST)); getStateConfig(HA_BACKUP_ST));
ASSERT_TRUE(state_cfg); 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()-> ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_LOAD_BALANCING_ST)); getStateConfig(HA_LOAD_BALANCING_ST));
ASSERT_TRUE(state_cfg); 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()-> ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_PARTNER_DOWN_ST)); getStateConfig(HA_PARTNER_DOWN_ST));
ASSERT_TRUE(state_cfg); 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()-> ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_READY_ST)); getStateConfig(HA_READY_ST));
ASSERT_TRUE(state_cfg); 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()-> ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_SYNCING_ST)); getStateConfig(HA_SYNCING_ST));
ASSERT_TRUE(state_cfg); 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()-> ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_TERMINATED_ST)); getStateConfig(HA_TERMINATED_ST));
ASSERT_TRUE(state_cfg); 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()-> ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()->
getStateConfig(HA_WAITING_ST)); getStateConfig(HA_WAITING_ST));
ASSERT_TRUE(state_cfg); ASSERT_TRUE(state_cfg);
EXPECT_EQ(HAConfig::StateConfig::PAUSE_ONCE, state_cfg->getPausing());