27#include <boost/pointer_cast.hpp>
28#include <boost/make_shared.hpp>
29#include <boost/weak_ptr.hpp>
41namespace ph = std::placeholders;
48 CommandUnsupportedError(
const char* file,
size_t line,
const char* what) :
55 ConflictError(
const char* file,
size_t line,
const char* what) :
78 : id_(id), io_service_(io_service), network_state_(network_state), config_(config),
79 server_type_(server_type), client_(), listener_(), communication_state_(),
80 query_filter_(config), lease_sync_filter_(server_type, config), mutex_(),
81 pending_requests_(), lease_update_backlog_(config->getDelayedUpdatesLimit()),
82 sync_complete_notified_(false) {
96 if (!
config_->getEnableMultiThreading()) {
102 config_->getHttpClientThreads(),
true));
105 if (
config_->getHttpDedicatedListener()) {
107 auto my_url =
config_->getThisServerConfig()->getUrl();
112 server_address =
IOAddress(my_url.getStrippedHostname());
113 }
catch (
const std::exception& ex) {
115 <<
" is not a valid IP address");
119 uint32_t listener_threads =
config_->getHttpListenerThreads();
122 auto tls_context =
config_->getThisServerConfig()->getTlsContext();
126 listener_threads, tls_context));
128 if (
config_->getRestrictCommands()) {
141 .arg(
config_->getThisServerName())
154HAService::getCSCallbacksSetName()
const {
155 std::ostringstream s;
156 s <<
"HA_MT_" <<
id_;
161HAService::defineEvents() {
175HAService::verifyEvents() {
189HAService::defineStates() {
193 std::bind(&HAService::backupStateHandler,
this),
197 std::bind(&HAService::communicationRecoveryHandler,
this),
201 std::bind(&HAService::normalStateHandler,
this),
205 std::bind(&HAService::normalStateHandler,
this),
209 std::bind(&HAService::inMaintenanceStateHandler,
this),
213 std::bind(&HAService::partnerDownStateHandler,
this),
217 std::bind(&HAService::partnerInMaintenanceStateHandler,
this),
221 std::bind(&HAService::passiveBackupStateHandler,
this),
225 std::bind(&HAService::readyStateHandler,
this),
229 std::bind(&HAService::syncingStateHandler,
this),
233 std::bind(&HAService::terminatedStateHandler,
this),
237 std::bind(&HAService::waitingStateHandler,
this),
242HAService::backupStateHandler() {
257HAService::communicationRecoveryHandler() {
374HAService::normalStateHandler() {
429 }
else if (
config_->amAllowingCommRecovery()) {
449HAService::inMaintenanceStateHandler() {
463 .arg(
config_->getThisServerName());
475HAService::partnerDownStateHandler() {
489 if (maintenance ||
config_->getThisServerConfig()->isAutoFailover()) {
504 .arg(
config_->getThisServerName());
567HAService::partnerInMaintenanceStateHandler() {
580 .arg(
config_->getThisServerName());
607HAService::passiveBackupStateHandler() {
625HAService::readyStateHandler() {
705HAService::syncingStateHandler() {
765 unsigned int dhcp_disable_timeout =
766 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
767 if (dhcp_disable_timeout == 0) {
768 ++dhcp_disable_timeout;
772 std::string status_message;
774 config_->getFailoverPeerConfig(),
775 dhcp_disable_timeout);
795HAService::terminatedStateHandler() {
811 .arg(
config_->getThisServerName());
818HAService::waitingStateHandler() {
890 if (!partner_in_terminated.is_not_a_date_time() &&
893 .arg(
config_->getThisServerName())
906 .arg(
config_->getThisServerName());
944 boost::to_upper(current_state_name);
945 boost::to_upper(new_state_name);
951 std::string partner_state_name =
getStateLabel(partner_state);
952 boost::to_upper(partner_state_name);
956 .arg(
config_->getThisServerName())
957 .arg(current_state_name)
959 .arg(partner_state_name);
964 .arg(
config_->getThisServerName())
965 .arg(current_state_name)
966 .arg(new_state_name);
975 .arg(
config_->getThisServerName());
988 .arg(
config_->getThisServerName())
989 .arg(new_state_name);
991 }
else if (!
config_->amSendingLeaseUpdates()) {
994 .arg(
config_->getThisServerName())
995 .arg(new_state_name);
1002 .arg(
config_->getThisServerName())
1003 .arg(new_state_name);
1014 switch (
config_->getHAMode()) {
1028 .arg(
config_->getThisServerName());
1040 boost::to_upper(state_name);
1042 .arg(
config_->getThisServerName())
1059 return (inScopeInternal(query4));
1064 return (inScopeInternal(query6));
1067template<
typename QueryPtrType>
1069HAService::inScopeInternal(QueryPtrType& query) {
1071 std::string scope_class;
1090 boost::to_upper(current_state_name);
1103 boost::to_upper(current_state_name);
1105 .arg(
config_->getThisServerName())
1106 .arg(current_state_name);
1109 }
else if (should_enable && !
network_state_->isServiceEnabled()) {
1111 boost::to_upper(current_state_name);
1113 .arg(
config_->getThisServerName())
1114 .arg(current_state_name);
1152 if (!should_terminate) {
1159 return (should_terminate);
1173 .arg(
config_->getThisServerName());
1181 .arg(
config_->getThisServerName());
1189 .arg(
config_->getThisServerName());
1209 size_t sent_num = 0;
1212 for (
auto const& p : peers_configs) {
1220 for (
auto const& l : *deleted_leases) {
1223 if (l->state_ == Lease4::STATE_RELEASED) {
1231 for (
auto const& l : *leases) {
1253 for (
auto const& l : *deleted_leases) {
1256 if (l->state_ == Lease4::STATE_RELEASED) {
1266 for (
auto const& l : *leases) {
1287 leases->push_back(lease);
1302 size_t sent_num = 0;
1305 for (
auto const& p : peers_configs) {
1312 for (
auto const& l : *deleted_leases) {
1315 if (l->state_ == Lease4::STATE_RELEASED) {
1323 for (
auto const& l : *leases) {
1359template<
typename QueryPtrType>
1364 std::lock_guard<std::mutex> lock(mutex_);
1365 return (leaseUpdateCompleteInternal(query, parking_lot));
1367 return (leaseUpdateCompleteInternal(query, parking_lot));
1371template<
typename QueryPtrType>
1373HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
1375 auto it = pending_requests_.find(query);
1379 if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
1381 parking_lot->unpark(query);
1386 if (it != pending_requests_.end()) {
1387 pending_requests_.erase(it);
1394template<
typename QueryPtrType>
1398 std::lock_guard<std::mutex> lock(mutex_);
1399 updatePendingRequestInternal(query);
1401 updatePendingRequestInternal(query);
1405template<
typename QueryPtrType>
1407HAService::updatePendingRequestInternal(QueryPtrType& query) {
1408 if (pending_requests_.count(query) == 0) {
1409 pending_requests_[query] = 1;
1411 ++pending_requests_[query];
1415template<
typename QueryPtrType>
1425 config->addBasicAuthHttpHeader(request);
1426 request->setBodyAsJson(command);
1427 request->finalize();
1436 boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
1439 client_->asyncSendRequest(config->getUrl(), config->getTlsContext(),
1441 [
this, weak_query, parking_lot, config]
1442 (
const boost::system::error_code& ec,
1444 const std::string& error_str) {
1448 QueryPtrType query = weak_query.lock();
1450 isc_throw(Unexpected,
"query is null while receiving response from"
1451 " HA peer. This is programmatic error");
1462 bool lease_update_success =
true;
1463 bool lease_update_conflict =
false;
1466 if (ec || !error_str.empty()) {
1468 .arg(
config_->getThisServerName())
1469 .arg(query->getLabel())
1470 .arg(config->getLogLabel())
1471 .arg(ec ? ec.message() : error_str);
1475 lease_update_success =
false;
1486 }
catch (
const ConflictError& ex) {
1488 lease_update_conflict =
true;
1489 lease_update_success =
false;
1493 .arg(
config_->getThisServerName())
1494 .arg(query->getLabel())
1495 .arg(config->getLogLabel())
1498 }
catch (
const std::exception& ex) {
1501 .arg(
config_->getThisServerName())
1502 .arg(query->getLabel())
1503 .arg(config->getLogLabel())
1507 lease_update_success =
false;
1516 if (!lease_update_success) {
1519 if (!lease_update_conflict) {
1538 if (!lease_update_success) {
1540 parking_lot->drop(query);
1570 updatePendingRequest(query);
1577 if (!config_->amSendingLeaseUpdates()) {
1582 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1587 if (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP) {
1593 switch (getCurrState()) {
1608 if (!config_->amSendingLeaseUpdates()) {
1612 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1620HAService::logFailedLeaseUpdates(
const PktPtr& query,
1633 auto failed_leases = args->get(param_name);
1636 if (failed_leases && (failed_leases->getType() ==
Element::list)) {
1638 for (
int i = 0; i < failed_leases->size(); ++i) {
1639 auto lease = failed_leases->get(i);
1643 auto ip_address = lease->get(
"ip-address");
1646 auto lease_type = lease->get(
"type");
1649 auto error_message = lease->get(
"error-message");
1652 .arg(query->getLabel())
1654 lease_type->stringValue() :
"(unknown)")
1656 ip_address->stringValue() :
"(unknown)")
1658 error_message->stringValue() :
"(unknown)");
1672HAService::processStatusGet()
const {
1678 role = config_->getThisServerConfig()->getRole();
1679 std::string role_txt = HAConfig::PeerConfig::roleToString(role);
1681 int state = getCurrState();
1689 std::set<std::string> scopes = query_filter_.getServedScopes();
1691 for (
auto const& scope : scopes) {
1694 local->set(
"scopes", list);
1695 local->set(
"server-name",
Element::create(config_->getThisServerName()));
1696 ha_servers->set(
"local", local);
1700 if ((config_->getHAMode() == HAConfig::PASSIVE_BACKUP) ||
1701 (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP)) {
1702 return (ha_servers);
1706 ElementPtr remote = communication_state_->getReport();
1709 role = config_->getFailoverPeerConfig()->getRole();
1710 role_txt = HAConfig::PeerConfig::roleToString(role);
1716 remote->set(
"server-name",
Element::create(config_->getFailoverPeerConfig()->getName()));
1717 ha_servers->set(
"remote", remote);
1719 return (ha_servers);
1723HAService::processHeartbeat() {
1725 std::string state_label = getState(getCurrState())->getLabel();
1731 auto scopes = query_filter_.getServedScopes();
1733 for (
auto const& scope : scopes) {
1736 arguments->set(
"scopes", scopes_list);
1738 arguments->set(
"unsent-update-count",
1739 Element::create(
static_cast<int64_t
>(communication_state_->getUnsentUpdateCount())));
1746HAService::processHAReset() {
1756HAService::asyncSendHeartbeat() {
1766 bool sync_complete_notified = sync_complete_notified_;
1767 sync_complete_notified_ =
false;
1773 partner_config->addBasicAuthHttpHeader(request);
1774 request->setBodyAsJson(CommandCreator::createHeartbeat(config_->getThisServerName(),
1776 request->finalize();
1783 client_->asyncSendRequest(partner_config->getUrl(),
1784 partner_config->getTlsContext(),
1786 [
this, partner_config, sync_complete_notified]
1787 (
const boost::system::error_code& ec,
1789 const std::string& error_str) {
1797 bool heartbeat_success = true;
1800 if (ec || !error_str.empty()) {
1801 LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
1802 .arg(config_->getThisServerName())
1803 .arg(partner_config->getLogLabel())
1804 .arg(ec ? ec.message() : error_str);
1805 heartbeat_success = false;
1814 ConstElementPtr args = verifyAsyncResponse(response, rcode);
1815 if (!args || args->getType() != Element::map) {
1816 isc_throw(CtrlChannelError,
"returned arguments in the response"
1820 ConstElementPtr state = args->get(
"state");
1821 if (!state || state->getType() != Element::string) {
1822 isc_throw(CtrlChannelError,
"server state not returned in response"
1823 " to a ha-heartbeat command or it is not a string");
1827 communication_state_->setPartnerState(state->stringValue());
1829 ConstElementPtr date_time = args->get(
"date-time");
1830 if (!date_time || date_time->getType() != Element::string) {
1831 isc_throw(CtrlChannelError,
"date-time not returned in response"
1832 " to a ha-heartbeat command or it is not a string");
1835 communication_state_->setPartnerTime(date_time->stringValue());
1839 auto scopes = args->get(
"scopes");
1840 communication_state_->setPartnerScopes(scopes);
1855 auto unsent_update_count = args->get(
"unsent-update-count");
1856 if (unsent_update_count) {
1857 if (unsent_update_count->getType() != Element::integer) {
1858 isc_throw(CtrlChannelError,
"unsent-update-count returned in"
1859 " the ha-heartbeat response is not an integer");
1861 communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>
1862 (unsent_update_count->intValue()));
1865 } catch (
const std::exception& ex) {
1867 .arg(config_->getThisServerName())
1868 .arg(partner_config->getLogLabel())
1870 heartbeat_success =
false;
1876 if (heartbeat_success) {
1877 communication_state_->poke();
1882 communication_state_->setPartnerUnavailable();
1884 if (communication_state_->isCommunicationInterrupted()) {
1885 LOG_WARN(ha_logger, HA_COMMUNICATION_INTERRUPTED)
1886 .arg(config_->getThisServerName())
1887 .arg(partner_config->getName());
1895 if (sync_complete_notified && !heartbeat_success) {
1896 postNextEvent(HA_SYNCED_PARTNER_UNAVAILABLE_EVT);
1903 runModel(HA_HEARTBEAT_COMPLETE_EVT);
1906 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1907 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1908 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1913HAService::scheduleHeartbeat() {
1914 if (!communication_state_->isHeartbeatRunning()) {
1920HAService::startHeartbeat() {
1921 if (config_->getHeartbeatDelay() > 0) {
1922 communication_state_->startHeartbeat(config_->getHeartbeatDelay(),
1923 std::bind(&HAService::asyncSendHeartbeat,
1931 const unsigned int max_period,
1932 PostRequestCallback post_request_action) {
1938 remote_config->addBasicAuthHttpHeader(request);
1939 request->setBodyAsJson(CommandCreator::createDHCPDisable(getRemoteOrigin(),
1942 request->finalize();
1949 http_client.asyncSendRequest(remote_config->getUrl(),
1950 remote_config->getTlsContext(),
1952 [
this, remote_config, post_request_action]
1953 (
const boost::system::error_code& ec,
1955 const std::string& error_str) {
1964 std::string error_message;
1967 if (ec || !error_str.empty()) {
1968 error_message = (ec ? ec.message() : error_str);
1969 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
1970 .arg(config_->getThisServerName())
1971 .arg(remote_config->getLogLabel())
1972 .arg(error_message);
1978 static_cast<void>(verifyAsyncResponse(response, rcode));
1980 } catch (
const std::exception& ex) {
1981 error_message = ex.what();
1983 .arg(config_->getThisServerName())
1984 .arg(remote_config->getLogLabel())
1985 .arg(error_message);
1991 if (!error_message.empty()) {
1992 communication_state_->setPartnerUnavailable();
1996 if (post_request_action) {
1997 post_request_action(error_message.empty(),
2003 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2004 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2005 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2012 PostRequestCallback post_request_action) {
2017 remote_config->addBasicAuthHttpHeader(request);
2018 request->setBodyAsJson(CommandCreator::createDHCPEnable(getRemoteOrigin(),
2020 request->finalize();
2027 http_client.asyncSendRequest(remote_config->getUrl(),
2028 remote_config->getTlsContext(),
2030 [
this, remote_config, post_request_action]
2031 (
const boost::system::error_code& ec,
2033 const std::string& error_str) {
2042 std::string error_message;
2045 if (ec || !error_str.empty()) {
2046 error_message = (ec ? ec.message() : error_str);
2047 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
2048 .arg(config_->getThisServerName())
2049 .arg(remote_config->getLogLabel())
2050 .arg(error_message);
2056 static_cast<void>(verifyAsyncResponse(response, rcode));
2058 } catch (
const std::exception& ex) {
2059 error_message = ex.what();
2061 .arg(config_->getThisServerName())
2062 .arg(remote_config->getLogLabel())
2063 .arg(error_message);
2069 if (!error_message.empty()) {
2070 communication_state_->setPartnerUnavailable();
2074 if (post_request_action) {
2075 post_request_action(error_message.empty(),
2081 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2082 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2083 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2088HAService::localDisableDHCPService() {
2089 network_state_->disableService(getLocalOrigin());
2093HAService::localEnableDHCPService() {
2094 network_state_->enableService(getLocalOrigin());
2098HAService::asyncSyncLeases() {
2099 PostSyncCallback null_action;
2102 unsigned int dhcp_disable_timeout =
2103 static_cast<unsigned int>(config_->getSyncTimeout() / 1000);
2104 if (dhcp_disable_timeout == 0) {
2106 dhcp_disable_timeout = 1;
2109 lease_sync_filter_.apply();
2110 asyncSyncLeases(*client_, config_->getFailoverPeerConfig(),
2111 dhcp_disable_timeout,
LeasePtr(), null_action);
2117 const unsigned int max_period,
2119 PostSyncCallback post_sync_action,
2120 const bool dhcp_disabled) {
2126 asyncDisableDHCPService(http_client, remote_config, max_period,
2127 [
this, &http_client, remote_config, max_period, last_lease,
2128 post_sync_action, dhcp_disabled]
2129 (
const bool success,
const std::string& error_message,
const int) {
2136 asyncSyncLeasesInternal(http_client, remote_config, max_period,
2137 last_lease, post_sync_action,
true);
2140 post_sync_action(success, error_message, dhcp_disabled);
2148 const unsigned int max_period,
2150 PostSyncCallback post_sync_action,
2151 const bool dhcp_disabled) {
2156 remote_config->addBasicAuthHttpHeader(request);
2157 if (server_type_ == HAServerType::DHCPv4) {
2158 request->setBodyAsJson(CommandCreator::createLease4GetPage(
2159 boost::dynamic_pointer_cast<Lease4>(last_lease), config_->getSyncPageLimit()));
2162 request->setBodyAsJson(CommandCreator::createLease6GetPage(
2163 boost::dynamic_pointer_cast<Lease6>(last_lease), config_->getSyncPageLimit()));
2165 request->finalize();
2172 http_client.asyncSendRequest(remote_config->getUrl(),
2173 remote_config->getTlsContext(),
2175 [
this, remote_config, post_sync_action, &http_client, max_period, dhcp_disabled]
2176 (
const boost::system::error_code& ec,
2178 const std::string& error_str) {
2182 LeasePtr last_lease;
2190 std::string error_message;
2193 if (ec || !error_str.empty()) {
2194 error_message = (ec ? ec.message() : error_str);
2195 LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
2196 .arg(config_->getThisServerName())
2197 .arg(remote_config->getLogLabel())
2198 .arg(error_message);
2204 ConstElementPtr args = verifyAsyncResponse(response, rcode);
2207 if (args && (args->getType() != Element::map)) {
2208 isc_throw(CtrlChannelError,
2209 "arguments in the received response must be a map");
2212 ConstElementPtr leases = args->get(
"leases");
2213 if (!leases || (leases->getType() != Element::list)) {
2214 isc_throw(CtrlChannelError,
2215 "server response does not contain leases argument or this"
2216 " argument is not a list");
2220 auto const& leases_element = leases->listValue();
2222 LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
2223 .arg(config_->getThisServerName())
2224 .arg(leases_element.size())
2225 .arg(remote_config->getLogLabel());
2228 uint64_t applied_lease_count = 0;
2229 for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
2232 if (server_type_ == HAServerType::DHCPv4) {
2233 Lease4Ptr lease = Lease4::fromElement(*l);
2238 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2239 (l + 1 == leases_element.end())) {
2240 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2243 if (!lease_sync_filter_.shouldSync(lease)) {
2248 Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
2249 if (!existing_lease) {
2251 LeaseMgrFactory::instance().addLease(lease);
2252 ++applied_lease_count;
2254 } else if (existing_lease->cltt_ < lease->cltt_) {
2260 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2261 LeaseMgrFactory::instance().updateLease4(lease);
2262 ++applied_lease_count;
2265 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
2266 .arg(config_->getThisServerName())
2267 .arg(lease->addr_.toText())
2268 .arg(lease->subnet_id_);
2272 Lease6Ptr lease = Lease6::fromElement(*l);
2277 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2278 (l + 1 == leases_element.end())) {
2279 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2282 if (!lease_sync_filter_.shouldSync(lease)) {
2287 Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
2289 if (!existing_lease) {
2291 LeaseMgrFactory::instance().addLease(lease);
2292 ++applied_lease_count;
2294 } else if (existing_lease->cltt_ < lease->cltt_) {
2300 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2301 LeaseMgrFactory::instance().updateLease6(lease);
2302 ++applied_lease_count;
2305 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
2306 .arg(config_->getThisServerName())
2307 .arg(lease->addr_.toText())
2308 .arg(lease->subnet_id_);
2312 } catch (const std::exception& ex) {
2313 LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
2314 .arg(config_->getThisServerName())
2320 LOG_INFO(ha_logger, HA_LEASES_SYNC_APPLIED_LEASES)
2321 .arg(config_->getThisServerName())
2322 .arg(applied_lease_count);
2324 } catch (
const std::exception& ex) {
2325 error_message = ex.what();
2327 .arg(config_->getThisServerName())
2328 .arg(remote_config->getLogLabel())
2329 .arg(error_message);
2335 if (!error_message.empty()) {
2336 communication_state_->setPartnerUnavailable();
2338 }
else if (last_lease) {
2341 asyncSyncLeases(http_client, remote_config, max_period, last_lease,
2342 post_sync_action, dhcp_disabled);
2347 if (post_sync_action) {
2348 post_sync_action(error_message.empty(),
2354 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2355 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2356 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2362HAService::processSynchronize(
const std::string& server_name,
2363 const unsigned int max_period) {
2366 remote_config = config_->getPeerConfig(server_name);
2367 }
catch (
const std::exception& ex) {
2371 if (remote_config->getName() == config_->getThisServerName()) {
2373 +
"' points to local server but should point to a partner"));
2375 std::string answer_message;
2376 int sync_status = synchronize(answer_message, remote_config, max_period);
2381HAService::synchronize(std::string& status_message,
2383 const unsigned int max_period) {
2384 lease_sync_filter_.apply();
2389 asyncSyncLeases(client, remote_config, max_period,
Lease4Ptr(),
2390 [&](
const bool success,
const std::string& error_message,
2391 const bool dhcp_disabled) {
2396 status_message = error_message;
2402 if (dhcp_disabled) {
2407 asyncSyncCompleteNotify(client, remote_config,
2408 [&](
const bool success,
2409 const std::string& error_message,
2415 asyncEnableDHCPService(client, remote_config,
2416 [&](
const bool success,
2417 const std::string& error_message,
2422 if (!success && status_message.empty()) {
2423 status_message = error_message;
2435 if (!success && status_message.empty()) {
2436 status_message = error_message;
2448 asyncEnableDHCPService(client, remote_config,
2449 [&](
const bool success,
2450 const std::string& error_message,
2452 if (!success && status_message.empty()) {
2453 status_message = error_message;
2472 .arg(config_->getThisServerName())
2473 .arg(remote_config->getLogLabel());
2487 io_service->stopAndPoll();
2491 if (!status_message.empty()) {
2492 postNextEvent(HA_SYNCING_FAILED_EVT);
2495 .arg(config_->getThisServerName())
2496 .arg(remote_config->getLogLabel())
2497 .arg(status_message);
2504 status_message =
"Lease database synchronization complete.";
2505 postNextEvent(HA_SYNCING_SUCCEEDED_EVT);
2508 .arg(config_->getThisServerName())
2509 .arg(remote_config->getLogLabel())
2510 .arg(stopwatch.logFormatLastDuration());
2516HAService::asyncSendLeaseUpdatesFromBacklog(
HttpClient& http_client,
2518 PostRequestCallback post_request_action) {
2519 if (lease_update_backlog_.size() == 0) {
2525 if (server_type_ == HAServerType::DHCPv4) {
2527 Lease4Ptr lease = boost::dynamic_pointer_cast<Lease4>(lease_update_backlog_.pop(op_type));
2528 if (op_type == LeaseUpdateBacklog::ADD) {
2529 command = CommandCreator::createLease4Update(*lease);
2531 command = CommandCreator::createLease4Delete(*lease);
2535 command = CommandCreator::createLease6BulkApply(lease_update_backlog_);
2542 config->addBasicAuthHttpHeader(request);
2543 request->setBodyAsJson(command);
2544 request->finalize();
2550 http_client.asyncSendRequest(config->getUrl(), config->getTlsContext(),
2552 [
this, &http_client, config, post_request_action]
2553 (
const boost::system::error_code& ec,
2555 const std::string& error_str) {
2558 std::string error_message;
2560 if (ec || !error_str.empty()) {
2561 error_message = (ec ? ec.message() : error_str);
2562 LOG_WARN(ha_logger, HA_LEASES_BACKLOG_COMMUNICATIONS_FAILED)
2563 .arg(config_->getThisServerName())
2564 .arg(config->getLogLabel())
2565 .arg(ec ? ec.message() : error_str);
2570 auto args = verifyAsyncResponse(response, rcode);
2571 } catch (
const std::exception& ex) {
2572 error_message = ex.what();
2574 .arg(config_->getThisServerName())
2575 .arg(config->getLogLabel())
2585 if (error_message.empty()) {
2586 asyncSendLeaseUpdatesFromBacklog(http_client, config, post_request_action);
2588 post_request_action(error_message.empty(), error_message, rcode);
2594HAService::sendLeaseUpdatesFromBacklog() {
2595 auto num_updates = lease_update_backlog_.size();
2596 if (num_updates == 0) {
2598 .arg(config_->getThisServerName());
2604 auto remote_config = config_->getFailoverPeerConfig();
2605 bool updates_successful =
true;
2608 .arg(config_->getThisServerName())
2610 .arg(remote_config->getName());
2612 asyncSendLeaseUpdatesFromBacklog(client, remote_config,
2613 [&](
const bool success,
const std::string&,
const int) {
2615 updates_successful = success;
2629 io_service->stopAndPoll();
2631 if (updates_successful) {
2633 .arg(config_->getThisServerName())
2634 .arg(remote_config->getName())
2635 .arg(stopwatch.logFormatLastDuration());
2638 return (updates_successful);
2644 PostRequestCallback post_request_action) {
2645 ConstElementPtr command = CommandCreator::createHAReset(config_->getThisServerName(),
2652 config->addBasicAuthHttpHeader(request);
2653 request->setBodyAsJson(command);
2654 request->finalize();
2660 http_client.asyncSendRequest(config->getUrl(), config->getTlsContext(),
2662 [
this, config, post_request_action]
2663 (
const boost::system::error_code& ec,
2665 const std::string& error_str) {
2668 std::string error_message;
2670 if (ec || !error_str.empty()) {
2671 error_message = (ec ? ec.message() : error_str);
2672 LOG_WARN(ha_logger, HA_RESET_COMMUNICATIONS_FAILED)
2673 .arg(config_->getThisServerName())
2674 .arg(config->getLogLabel())
2675 .arg(ec ? ec.message() : error_str);
2680 auto args = verifyAsyncResponse(response, rcode);
2681 } catch (
const std::exception& ex) {
2682 error_message = ex.what();
2684 .arg(config_->getThisServerName())
2685 .arg(config->getLogLabel())
2690 post_request_action(error_message.empty(), error_message, rcode);
2695HAService::sendHAReset() {
2698 auto remote_config = config_->getFailoverPeerConfig();
2699 bool reset_successful =
true;
2701 asyncSendHAReset(client, remote_config,
2702 [&](
const bool success,
const std::string&,
const int) {
2704 reset_successful = success;
2712 io_service->stopAndPoll();
2714 return (reset_successful);
2718HAService::processScopes(
const std::vector<std::string>& scopes) {
2720 query_filter_.serveScopes(scopes);
2721 adjustNetworkState();
2723 }
catch (
const std::exception& ex) {
2731HAService::processContinue() {
2739HAService::processMaintenanceNotify(
const bool cancel) {
2743 " maintenance for the server not in the"
2744 " in-maintenance state."));
2747 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
2748 verboseTransition(getPrevState());
2753 switch (getCurrState()) {
2763 return (
createAnswer(HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED,
2764 "Unable to transition the server from the "
2766 " in-maintenance state."));
2769 runModel(HA_MAINTENANCE_NOTIFY_EVT);
2775HAService::processMaintenanceStart() {
2776 switch (getCurrState()) {
2783 " partner-in-maintenance state."));
2795 remote_config->addBasicAuthHttpHeader(request);
2796 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(config_->getThisServerName(),
2797 false, server_type_));
2798 request->finalize();
2807 boost::system::error_code captured_ec;
2808 std::string captured_error_message;
2809 int captured_rcode = 0;
2812 client.asyncSendRequest(remote_config->getUrl(),
2813 remote_config->getTlsContext(),
2815 [
this, remote_config, &io_service, &captured_ec, &captured_error_message,
2817 (
const boost::system::error_code& ec,
2819 const std::string& error_str) {
2829 std::string error_message;
2832 if (ec || !error_str.empty()) {
2833 error_message = (ec ? ec.message() : error_str);
2834 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_COMMUNICATIONS_FAILED)
2835 .arg(config_->getThisServerName())
2836 .arg(remote_config->getLogLabel())
2837 .arg(error_message);
2843 static_cast<void>(verifyAsyncResponse(response, captured_rcode));
2845 } catch (
const std::exception& ex) {
2846 error_message = ex.what();
2848 .arg(config_->getThisServerName())
2849 .arg(remote_config->getLogLabel())
2850 .arg(error_message);
2856 if (!error_message.empty()) {
2857 communication_state_->setPartnerUnavailable();
2861 captured_error_message = error_message;
2864 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2865 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2866 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2875 io_service->stopAndPoll();
2880 postNextEvent(HA_MAINTENANCE_START_EVT);
2881 verboseTransition(HA_PARTNER_DOWN_ST);
2884 "Server is now in the partner-down state as its"
2885 " partner appears to be offline for maintenance."));
2891 postNextEvent(HA_MAINTENANCE_START_EVT);
2892 verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST);
2899 " partner-in-maintenance state. The partner server responded"
2900 " with the following message to the ha-maintenance-notify"
2901 " command: " + captured_error_message +
"."));
2906 "Server is now in the partner-in-maintenance state"
2907 " and its partner is in-maintenance state. The partner"
2908 " can be now safely shut down."));
2912HAService::processMaintenanceCancel() {
2915 " request because the server is not in the"
2916 " partner-in-maintenance state."));
2926 remote_config->addBasicAuthHttpHeader(request);
2927 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(config_->getThisServerName(),
2928 true, server_type_));
2929 request->finalize();
2938 std::string error_message;
2941 client.asyncSendRequest(remote_config->getUrl(),
2942 remote_config->getTlsContext(),
2944 [
this, remote_config, &io_service, &error_message]
2945 (
const boost::system::error_code& ec,
2947 const std::string& error_str) {
2952 if (ec || !error_str.empty()) {
2953 error_message = (ec ? ec.message() : error_str);
2954 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_CANCEL_COMMUNICATIONS_FAILED)
2955 .arg(config_->getThisServerName())
2956 .arg(remote_config->getLogLabel())
2957 .arg(error_message);
2964 static_cast<void>(verifyAsyncResponse(response, rcode));
2966 } catch (
const std::exception& ex) {
2967 error_message = ex.what();
2969 .arg(config_->getThisServerName())
2970 .arg(remote_config->getLogLabel())
2971 .arg(error_message);
2977 if (!error_message.empty()) {
2978 communication_state_->setPartnerUnavailable();
2982 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2983 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2984 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2993 io_service->stopAndPoll();
2997 if (!error_message.empty()) {
2999 "Unable to cancel maintenance. The partner server responded"
3000 " with the following message to the ha-maintenance-notify"
3001 " command: " + error_message +
"."));
3006 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
3007 verboseTransition(getPrevState());
3011 "Server maintenance successfully canceled."));
3017 PostRequestCallback post_request_action) {
3023 remote_config->addBasicAuthHttpHeader(request);
3024 request->setBodyAsJson(CommandCreator::createSyncCompleteNotify(getRemoteOrigin(),
3025 config_->getThisServerName(),
3027 request->finalize();
3034 http_client.asyncSendRequest(remote_config->getUrl(),
3035 remote_config->getTlsContext(),
3037 [
this, remote_config, post_request_action]
3038 (
const boost::system::error_code& ec,
3040 const std::string& error_str) {
3049 std::string error_message;
3052 if (ec || !error_str.empty()) {
3053 error_message = (ec ? ec.message() : error_str);
3054 LOG_ERROR(ha_logger, HA_SYNC_COMPLETE_NOTIFY_COMMUNICATIONS_FAILED)
3055 .arg(config_->getThisServerName())
3056 .arg(remote_config->getLogLabel())
3057 .arg(error_message);
3063 static_cast<void>(verifyAsyncResponse(response, rcode));
3065 } catch (
const CommandUnsupportedError& ex) {
3068 }
catch (
const std::exception& ex) {
3069 error_message = ex.what();
3071 .arg(config_->getThisServerName())
3072 .arg(remote_config->getLogLabel())
3073 .arg(error_message);
3079 if (!error_message.empty()) {
3080 communication_state_->setPartnerUnavailable();
3084 if (post_request_action) {
3085 post_request_action(error_message.empty(),
3091 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
3092 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
3093 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
3098HAService::processSyncCompleteNotify(
const unsigned int origin_id) {
3100 sync_complete_notified_ =
true;
3108 network_state_->disableService(getLocalOrigin());
3113 network_state_->enableService(origin_id);
3115 "Server successfully notified about the synchronization completion."));
3124 boost::dynamic_pointer_cast<HttpResponseJson>(response);
3125 if (!json_response) {
3154 if (body->empty()) {
3165 std::ostringstream s;
3174 s << args->stringValue() <<
" (";
3177 s <<
"error code " << rcode <<
")";
3182 isc_throw(CommandUnsupportedError, s.str());
3190 auto failed_leases = args->get(
"failed-leases");
3191 if (!failed_leases || (failed_leases->getType() !=
Element::list)) {
3195 auto conflict =
false;
3197 for (
auto i = 0; i < failed_leases->size(); ++i) {
3198 auto lease = failed_leases->get(i);
3202 auto result = lease->get(
"result");
3206 auto error_message = lease->get(
"error-message");
3209 if (error_message && error_message->getType()) {
3210 s << error_message->stringValue() <<
" (";
3212 s <<
"error code " << result->intValue() <<
")";
3220 conflict_error_message = error_message;
3226 if (conflict_error_message &&
3228 s << conflict_error_message->stringValue() <<
" (";
3242HAService::clientConnectHandler(
const boost::system::error_code& ec,
int tcp_native_fd) {
3246 if (client_->getThreadIOService()) {
3254 if ((!ec || (ec.value() == boost::asio::error::in_progress))
3255 && (tcp_native_fd >= 0)) {
3261 std::bind(&HAService::socketReadyHandler,
this, ph::_1)
3273HAService::socketReadyHandler(
int tcp_native_fd) {
3278 client_->closeIfOutOfBand(tcp_native_fd);
3282HAService::clientCloseHandler(
int tcp_native_fd) {
3283 if (tcp_native_fd >= 0) {
3289HAService::pendingRequestSize() {
3291 std::lock_guard<std::mutex> lock(mutex_);
3292 return (pending_requests_.size());
3294 return (pending_requests_.size());
3298template<
typename QueryPtrType>
3300HAService::getPendingRequest(
const QueryPtrType& query) {
3302 std::lock_guard<std::mutex> lock(mutex_);
3303 return (getPendingRequestInternal(query));
3305 return (getPendingRequestInternal(query));
3309template<
typename QueryPtrType>
3311HAService::getPendingRequestInternal(
const QueryPtrType& query) {
3312 if (pending_requests_.count(query) == 0) {
3315 return (pending_requests_[query]);
3320HAService::checkPermissionsClientAndListener() {
3328 client_->checkPermissions();
3332 listener_->checkPermissions();
3336 .arg(config_->getThisServerName())
3341 }
catch (
const std::exception& ex) {
3343 .arg(config_->getThisServerName())
3349HAService::startClientAndListener() {
3352 std::bind(&HAService::checkPermissionsClientAndListener,
this),
3353 std::bind(&HAService::pauseClientAndListener,
this),
3354 std::bind(&HAService::resumeClientAndListener,
this));
3366HAService::pauseClientAndListener() {
3377 }
catch (
const std::exception& ex) {
3384HAService::resumeClientAndListener() {
3393 listener_->resume();
3395 }
catch (std::exception& ex) {
3397 .arg(config_->getThisServerName())
3403HAService::stopClientAndListener() {
3417template int HAService::getPendingRequest(
const Pkt4Ptr&);
3418template int HAService::getPendingRequest(
const Pkt6Ptr&);
Exception thrown when a worker thread is trying to stop or pause the respective thread pool (which wo...
A generic exception that is thrown when an unexpected error condition occurs.
The IOAddress class represents an IP addresses (version agnostic)
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
The IOService class is a wrapper for the ASIO io_service class.
A multi-threaded HTTP listener that can process API commands requests.
static std::unordered_set< std::string > command_accept_list_
The server command accept list.
A standard control channel exception that is thrown if a function is there is a problem with one of t...
static ElementPtr create(const Position &pos=ZERO_POSITION())
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
static data::ConstElementPtr createLease4Delete(const dhcp::Lease4 &lease4)
Creates lease4-del command.
static std::unordered_set< std::string > ha_commands4_
List of commands used by the High Availability in v4.
static data::ConstElementPtr createLease4Update(const dhcp::Lease4 &lease4)
Creates lease4-update command.
static data::ConstElementPtr createLease6BulkApply(const dhcp::Lease6CollectionPtr &leases, const dhcp::Lease6CollectionPtr &deleted_leases)
Creates lease6-bulk-apply command.
static std::unordered_set< std::string > ha_commands6_
List of commands used by the High Availability in v6.
Holds communication state between DHCPv4 servers.
Holds communication state between DHCPv6 servers.
Role
Server's role in the High Availability setup.
static std::string roleToString(const HAConfig::PeerConfig::Role &role)
Returns role name.
std::map< std::string, PeerConfigPtr > PeerConfigMap
Map of the servers' configurations.
static std::string HAModeToString(const HAMode &ha_mode)
Returns HA mode name.
boost::shared_ptr< PeerConfig > PeerConfigPtr
Pointer to the server's configuration.
static const int HA_MAINTENANCE_START_EVT
ha-maintenance-start command received.
bool inScope(dhcp::Pkt4Ptr &query4)
Checks if the DHCPv4 query should be processed by this server.
void adjustNetworkState()
Enables or disables network state depending on the served scopes.
void stopClientAndListener()
Stop the client and(or) listener instances.
int getNormalState() const
Returns normal operation state for the current configuration.
bool shouldQueueLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be queued.
static const int HA_HEARTBEAT_COMPLETE_EVT
Finished heartbeat command.
bool clientConnectHandler(const boost::system::error_code &ec, int tcp_native_fd)
HttpClient connect callback handler.
bool isMaintenanceCanceled() const
Convenience method checking if the current state is a result of canceling the maintenance.
void asyncSendLeaseUpdate(const QueryPtrType &query, const HAConfig::PeerConfigPtr &config, const data::ConstElementPtr &command, const hooks::ParkingLotHandlePtr &parking_lot)
Asynchronously sends lease update to the peer.
void verboseTransition(const unsigned state)
Transitions to a desired state and logs it.
bool sendLeaseUpdatesFromBacklog()
Attempts to send all lease updates from the backlog synchronously.
config::CmdHttpListenerPtr listener_
HTTP listener instance used to receive and respond to HA commands and lease updates.
void clientCloseHandler(int tcp_native_fd)
HttpClient close callback handler.
bool leaseUpdateComplete(QueryPtrType &query, const hooks::ParkingLotHandlePtr &parking_lot)
Handle last pending request for this query.
HAConfigPtr config_
Pointer to the HA hooks library configuration.
unsigned int id_
Unique service id.
bool shouldTerminate() const
Indicates if the server should transition to the terminated state.
dhcp::NetworkStatePtr network_state_
Pointer to the state of the DHCP service (enabled/disabled).
void scheduleHeartbeat()
Schedules asynchronous heartbeat to a peer if it is not scheduled.
QueryFilter query_filter_
Selects queries to be processed/dropped.
static const int HA_MAINTENANCE_NOTIFY_EVT
ha-maintenance-notify command received.
static const int HA_SYNCED_PARTNER_UNAVAILABLE_EVT
The heartbeat command failed after receiving ha-sync-complete-notify command from the partner.
void conditionalLogPausedState() const
Logs if the server is paused in the current state.
bool unpause()
Unpauses the HA state machine with logging.
static const int HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED
Control result returned in response to ha-maintenance-notify.
void serveDefaultScopes()
Instructs the HA service to serve default scopes.
size_t asyncSendLeaseUpdates(const dhcp::Pkt4Ptr &query, const dhcp::Lease4CollectionPtr &leases, const dhcp::Lease4CollectionPtr &deleted_leases, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules asynchronous IPv4 leases updates.
static const int HA_SYNCING_SUCCEEDED_EVT
Lease database synchronization succeeded.
bool sendHAReset()
Sends ha-reset command to partner synchronously.
asiolink::IOServicePtr io_service_
Pointer to the IO service object shared between this hooks library and the DHCP server.
CommunicationStatePtr communication_state_
Holds communication state with a peer.
void logFailedLeaseUpdates(const dhcp::PktPtr &query, const data::ConstElementPtr &args) const
Log failed lease updates.
bool clientHandshakeHandler(const boost::system::error_code &)
HttpClient handshake callback handler.
LeaseUpdateBacklog lease_update_backlog_
Backlog of DHCP lease updates.
virtual ~HAService()
Destructor.
static const int HA_SYNCING_FAILED_EVT
Lease database synchronization failed.
static const int HA_MAINTENANCE_CANCEL_EVT
ha-maintenance-cancel command received.
size_t asyncSendSingleLeaseUpdate(const dhcp::Pkt4Ptr &query, const dhcp::Lease4Ptr &lease, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules an asynchronous IPv4 lease update.
bool isPartnerStateInvalid() const
Indicates if the partner's state is invalid.
data::ConstElementPtr verifyAsyncResponse(const http::HttpResponsePtr &response, int &rcode)
Checks if the response is valid or contains an error.
int synchronize(std::string &status_message, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period)
Synchronizes lease database with a partner.
bool shouldSendLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be sent as result of leases allocation or release.
void serveFailoverScopes()
Instructs the HA service to serve failover scopes.
static const int HA_LEASE_UPDATES_COMPLETE_EVT
Finished lease updates commands.
HAService(const unsigned int id, const asiolink::IOServicePtr &io_service, const dhcp::NetworkStatePtr &network_state, const HAConfigPtr &config, const HAServerType &server_type=HAServerType::DHCPv4)
Constructor.
http::HttpClientPtr client_
HTTP client instance used to send HA commands and lease updates.
void updatePendingRequest(QueryPtrType &query)
Update pending request counter for this query.
bool shouldPartnerDown() const
Indicates if the server should transition to the partner down state.
static const int HA_WAITING_TO_TERMINATED_ST_DELAY_MINUTES
A delay in minutes to transition from the waiting to terminated state when the partner remains in ter...
bool push(const OpType op_type, const dhcp::LeasePtr &lease)
Appends lease update to the queue.
OpType
Type of the lease update (operation type).
void clear()
Removes all lease updates from the queue.
bool wasOverflown()
Checks if the queue was overflown.
bool inScope(const dhcp::Pkt4Ptr &query4, std::string &scope_class) const
Checks if this server should process the DHCPv4 query.
void serveFailoverScopes()
Enable scopes required in failover case.
void serveDefaultScopes()
Serve default scopes for the given HA mode.
void serveNoScopes()
Disables all scopes.
This class parses and generates time values used in HTTP.
std::string rfc1123Format() const
Returns time value formatted as specified in RFC 1123.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
const EventPtr & getEvent(unsigned int value)
Fetches the event referred to by value.
std::string getStateLabel(const int state) const
Fetches the label associated with an state value.
void unpauseModel()
Unpauses state model.
virtual void runModel(unsigned int event)
Processes events through the state model.
bool isModelPaused() const
Returns whether or not the model is paused.
virtual void defineEvents()
Populates the set of events.
void postNextEvent(unsigned int event)
Sets the next event to the given event value.
void defineState(unsigned int value, const std::string &label, StateHandler handler, const StatePausing &state_pausing=STATE_PAUSE_NEVER)
Adds an state value and associated label to the set of states.
bool doOnExit()
Checks if on exit flag is true.
unsigned int getNextEvent() const
Fetches the model's next event.
void defineEvent(unsigned int value, const std::string &label)
Adds an event value and associated label to the set of events.
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
virtual void verifyEvents()
Validates the contents of the set of events.
bool doOnEntry()
Checks if on entry flag is true.
static const int NOP_EVT
Signifies that no event has occurred.
void startModel(const int start_state)
Begins execution of the model.
virtual void defineStates()
Populates the set of states.
unsigned int getLastEvent() const
Fetches the model's last event.
unsigned int getCurrState() const
Fetches the model's current state.
Utility class to measure code execution times.
void stop()
Stops the stopwatch.
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
An abstract API for lease database.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
const char * CONTROL_TEXT
String used for storing textual description ("text")
constexpr long TIMEOUT_DEFAULT_HTTP_CLIENT_REQUEST
Timeout for the HTTP clients awaiting a response to a request.
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_CONFLICT
Status code indicating that the command was unsuccessful due to a conflict between the command argume...
const int CONTROL_RESULT_COMMAND_UNSUPPORTED
Status code indicating that the specified command is not supported.
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
const char * CONTROL_RESULT
String used for result, i.e. integer status ("result")
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
std::string ClientClass
Defines a single class name.
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
boost::shared_ptr< NetworkState > NetworkStatePtr
Pointer to the NetworkState object.
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID HA_INVALID_PARTNER_STATE_LOAD_BALANCING
const isc::log::MessageID HA_RESUME_CLIENT_LISTENER_FAILED
const isc::log::MessageID HA_LOCAL_DHCP_ENABLE
const isc::log::MessageID HA_LEASES_BACKLOG_NOTHING_TO_SEND
const isc::log::MessageID HA_LEASES_BACKLOG_FAILED
const isc::log::MessageID HA_SYNC_FAILED
const isc::log::MessageID HA_TERMINATED_RESTART_PARTNER
const int HA_PASSIVE_BACKUP_ST
In passive-backup state with a single active server and backup servers.
const int HA_HOT_STANDBY_ST
Hot standby state.
const isc::log::MessageID HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY
const isc::log::MessageID HA_LEASES_BACKLOG_SUCCESS
const int HA_COMMUNICATION_RECOVERY_ST
Communication recovery state.
const isc::log::MessageID HA_LEASE_UPDATE_COMMUNICATIONS_FAILED
const isc::log::MessageID HA_STATE_MACHINE_CONTINUED
isc::log::Logger ha_logger("ha-hooks")
const isc::log::MessageID HA_LEASES_SYNC_FAILED
const isc::log::MessageID HA_SYNC_SUCCESSFUL
const int HA_UNAVAILABLE_ST
Special state indicating that this server is unable to communicate with the partner.
const isc::log::MessageID HA_CONFIG_LEASE_UPDATES_DISABLED_REMINDER
const isc::log::MessageID HA_SERVICE_STARTED
const int HA_TERMINATED_ST
HA service terminated state.
const int HA_IN_MAINTENANCE_ST
In maintenance state.
const int HA_LOAD_BALANCING_ST
Load balancing state.
const isc::log::MessageID HA_DHCP_ENABLE_FAILED
const isc::log::MessageID HA_LEASE_UPDATE_DELETE_FAILED_ON_PEER
const isc::log::MessageID HA_LEASES_BACKLOG_START
const isc::log::MessageID HA_SYNC_START
const isc::log::MessageID HA_HEARTBEAT_FAILED
const int HA_PARTNER_DOWN_ST
Partner down state.
const isc::log::MessageID HA_LEASE_UPDATES_ENABLED
const isc::log::MessageID HA_INVALID_PARTNER_STATE_HOT_STANDBY
const isc::log::MessageID HA_STATE_MACHINE_PAUSED
const isc::log::MessageID HA_TERMINATED
const isc::log::MessageID HA_DHCP_DISABLE_FAILED
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
const isc::log::MessageID HA_MAINTENANCE_STARTED_IN_PARTNER_DOWN
const int HA_PARTNER_IN_MAINTENANCE_ST
Partner in-maintenance state.
const isc::log::MessageID HA_MAINTENANCE_NOTIFY_FAILED
const int HA_WAITING_ST
Server waiting state, i.e. waiting for another server to be ready.
HAServerType
Lists possible server types for which HA service is created.
const int HA_BACKUP_ST
Backup state.
const isc::log::MessageID HA_PAUSE_CLIENT_LISTENER_ILLEGAL
const isc::log::MessageID HA_PAUSE_CLIENT_LISTENER_FAILED
const isc::log::MessageID HA_MAINTENANCE_SHUTDOWN_SAFE
const isc::log::MessageID HA_MAINTENANCE_NOTIFY_CANCEL_FAILED
const isc::log::MessageID HA_LEASE_UPDATE_CONFLICT
const isc::log::MessageID HA_LEASE_UPDATES_DISABLED
const isc::log::MessageID HA_LOCAL_DHCP_DISABLE
const int HA_SYNCING_ST
Synchronizing database state.
const isc::log::MessageID HA_RESET_FAILED
const isc::log::MessageID HA_STATE_TRANSITION
const isc::log::MessageID HA_CONFIG_LEASE_SYNCING_DISABLED_REMINDER
std::string stateToString(int state)
Returns state name.
const int HA_READY_ST
Server ready state, i.e. synchronized database, can enable DHCP service.
const isc::log::MessageID HA_TERMINATED_PARTNER_DID_NOT_RESTART
const isc::log::MessageID HA_SYNC_COMPLETE_NOTIFY_FAILED
const isc::log::MessageID HA_MAINTENANCE_STARTED
const isc::log::MessageID HA_LEASE_UPDATE_CREATE_UPDATE_FAILED_ON_PEER
const isc::log::MessageID HA_LEASE_UPDATE_FAILED
const isc::log::MessageID HA_STATE_TRANSITION_PASSIVE_BACKUP
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
boost::shared_ptr< PostHttpRequestJson > PostHttpRequestJsonPtr
Pointer to PostHttpRequestJson.
boost::shared_ptr< HttpResponseJson > HttpResponseJsonPtr
Pointer to the HttpResponseJson object.
boost::shared_ptr< HttpResponse > HttpResponsePtr
Pointer to the HttpResponse object.
Defines the logger used by the top-level component of kea-lfc.
HTTP request/response timeout value.
static const HttpVersion & HTTP_11()
HTTP version 1.1.