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) :
69 : io_service_(io_service), network_state_(network_state), config_(config),
70 server_type_(server_type), client_(), listener_(), communication_state_(),
71 query_filter_(config), mutex_(), pending_requests_(),
72 lease_update_backlog_(config->getDelayedUpdatesLimit()),
73 sync_complete_notified_(false) {
87 if (!
config_->getEnableMultiThreading()) {
93 config_->getHttpClientThreads(),
true));
96 if (
config_->getHttpDedicatedListener()) {
98 auto my_url =
config_->getThisServerConfig()->getUrl();
99 IOAddress server_address(IOAddress::IPV4_ZERO_ADDRESS());
103 server_address =
IOAddress(my_url.getStrippedHostname());
104 }
catch (
const std::exception& ex) {
106 <<
" is not a valid IP address");
110 uint32_t listener_threads =
config_->getHttpListenerThreads();
113 auto tls_context =
config_->getThisServerConfig()->getTlsContext();
117 listener_threads, tls_context));
119 if (
config_->getRestrictCommands()) {
121 CmdResponseCreator::command_accept_list_ =
124 CmdResponseCreator::command_accept_list_ =
145 StateModel::defineEvents();
159 StateModel::verifyEvents();
173 StateModel::defineStates();
412 }
else if (
config_->amAllowingCommRecovery()) {
471 if (maintenance ||
config_->getThisServerConfig()->isAutoFailover()) {
742 unsigned int dhcp_disable_timeout =
743 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
744 if (dhcp_disable_timeout == 0) {
745 ++dhcp_disable_timeout;
749 std::string status_message;
751 config_->getFailoverPeerConfig()->getName(),
752 dhcp_disable_timeout);
907 boost::to_upper(current_state_name);
908 boost::to_upper(new_state_name);
914 std::string partner_state_name =
getStateLabel(partner_state);
915 boost::to_upper(partner_state_name);
919 .arg(current_state_name)
921 .arg(partner_state_name);
926 .arg(current_state_name)
927 .arg(new_state_name);
948 .arg(new_state_name);
950 }
else if (!
config_->amSendingLeaseUpdates()) {
953 .arg(new_state_name);
960 .arg(new_state_name);
971 switch (
config_->getHAMode()) {
996 boost::to_upper(state_name);
1009 return (inScopeInternal(query4));
1014 return (inScopeInternal(query6));
1017template<
typename QueryPtrType>
1019HAService::inScopeInternal(QueryPtrType& query) {
1021 std::string scope_class;
1040 boost::to_upper(current_state_name);
1053 boost::to_upper(current_state_name);
1055 .arg(
config_->getThisServerName())
1056 .arg(current_state_name);
1057 network_state_->disableService(NetworkState::Origin::HA_COMMAND);
1059 }
else if (should_enable && !
network_state_->isServiceEnabled()) {
1061 boost::to_upper(current_state_name);
1063 .arg(
config_->getThisServerName())
1064 .arg(current_state_name);
1102 if (!should_terminate) {
1106 return (should_terminate);
1153 size_t sent_num = 0;
1156 for (
auto p = peers_configs.begin(); p != peers_configs.end(); ++p) {
1164 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
1169 for (
auto l = leases->begin(); l != leases->end(); ++l) {
1191 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
1197 for (
auto l = leases->begin(); l != leases->end(); ++l) {
1222 size_t sent_num = 0;
1225 for (
auto p = peers_configs.begin(); p != peers_configs.end(); ++p) {
1232 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
1237 for (
auto l = leases->begin(); l != leases->end(); ++l) {
1273template<
typename QueryPtrType>
1277 if (MultiThreadingMgr::instance().getMode()) {
1278 std::lock_guard<std::mutex> lock(mutex_);
1279 return (leaseUpdateCompleteInternal(query, parking_lot));
1281 return (leaseUpdateCompleteInternal(query, parking_lot));
1285template<
typename QueryPtrType>
1287HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
1289 auto it = pending_requests_.find(query);
1293 if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
1294 parking_lot->unpark(query);
1298 if (it != pending_requests_.end()) {
1299 pending_requests_.erase(it);
1306template<
typename QueryPtrType>
1309 if (MultiThreadingMgr::instance().getMode()) {
1310 std::lock_guard<std::mutex> lock(mutex_);
1311 updatePendingRequestInternal(query);
1313 updatePendingRequestInternal(query);
1317template<
typename QueryPtrType>
1319HAService::updatePendingRequestInternal(QueryPtrType& query) {
1320 if (pending_requests_.count(query) == 0) {
1321 pending_requests_[query] = 1;
1323 ++pending_requests_[query];
1327template<
typename QueryPtrType>
1335 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1337 config->addBasicAuthHttpHeader(request);
1338 request->setBodyAsJson(command);
1339 request->finalize();
1348 boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
1351 client_->asyncSendRequest(config->getUrl(), config->getTlsContext(),
1353 [
this, weak_query, parking_lot, config]
1354 (
const boost::system::error_code& ec,
1356 const std::string& error_str) {
1360 QueryPtrType query = weak_query.lock();
1362 isc_throw(Unexpected,
"query is null while receiving response from"
1363 " HA peer. This is programmatic error");
1372 bool lease_update_success =
true;
1375 if (ec || !error_str.empty()) {
1376 LOG_WARN(ha_logger, HA_LEASE_UPDATE_COMMUNICATIONS_FAILED)
1377 .arg(query->getLabel())
1378 .arg(config->getLogLabel())
1379 .arg(ec ? ec.message() : error_str);
1383 lease_update_success = false;
1390 auto args = verifyAsyncResponse(response, rcode);
1393 logFailedLeaseUpdates(query, args);
1395 } catch (
const std::exception& ex) {
1397 .arg(query->getLabel())
1398 .arg(config->getLogLabel())
1402 lease_update_success =
false;
1411 communication_state_->setPartnerState(
"unavailable");
1421 if (!lease_update_success) {
1422 parking_lot->drop(query);
1430 if (leaseUpdateComplete(query, parking_lot)) {
1436 runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
1440 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1441 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1442 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1449 if (config_->amWaitingBackupAck() || (config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1451 updatePendingRequest(query);
1458 if (!config_->amSendingLeaseUpdates()) {
1463 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1468 if (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP) {
1474 switch (getCurrState()) {
1489 if (!config_->amSendingLeaseUpdates()) {
1493 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1501HAService::logFailedLeaseUpdates(
const PktPtr& query,
1504 if (!args || (args->getType() != Element::map)) {
1514 auto failed_leases = args->get(param_name);
1517 if (failed_leases && (failed_leases->getType() == Element::list)) {
1519 for (
int i = 0; i < failed_leases->size(); ++i) {
1520 auto lease = failed_leases->get(i);
1521 if (lease->getType() == Element::map) {
1524 auto ip_address = lease->get(
"ip-address");
1527 auto lease_type = lease->get(
"type");
1530 auto error_message = lease->get(
"error-message");
1533 .arg(query->getLabel())
1534 .arg(lease_type && (lease_type->getType() == Element::string) ?
1535 lease_type->stringValue() :
"(unknown)")
1536 .arg(ip_address && (ip_address->getType() == Element::string) ?
1537 ip_address->stringValue() :
"(unknown)")
1538 .arg(error_message && (error_message->getType() == Element::string) ?
1539 error_message->stringValue() :
"(unknown)");
1553HAService::processStatusGet()
const {
1554 ElementPtr ha_servers = Element::createMap();
1559 role = config_->getThisServerConfig()->getRole();
1560 std::string role_txt = HAConfig::PeerConfig::roleToString(role);
1561 local->set(
"role", Element::create(role_txt));
1562 int state = getCurrState();
1568 local->set(
"state", Element::create(std::string()));
1570 std::set<std::string> scopes = query_filter_.getServedScopes();
1572 for (std::string scope : scopes) {
1573 list->add(Element::create(scope));
1575 local->set(
"scopes", list);
1576 ha_servers->set(
"local", local);
1580 if ((config_->getHAMode() == HAConfig::PASSIVE_BACKUP) ||
1581 (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP)) {
1582 return (ha_servers);
1586 ElementPtr remote = communication_state_->getReport();
1589 role = config_->getFailoverPeerConfig()->getRole();
1590 std::string role_txt = HAConfig::PeerConfig::roleToString(role);
1591 remote->set(
"role", Element::create(role_txt));
1594 remote->set(
"role", Element::create(std::string()));
1596 ha_servers->set(
"remote", remote);
1598 return (ha_servers);
1602HAService::processHeartbeat() {
1604 std::string state_label = getState(getCurrState())->getLabel();
1605 arguments->set(
"state", Element::create(state_label));
1608 arguments->set(
"date-time", Element::create(date_time));
1610 auto scopes = query_filter_.getServedScopes();
1611 ElementPtr scopes_list = Element::createList();
1612 for (
auto scope : scopes) {
1613 scopes_list->add(Element::create(scope));
1615 arguments->set(
"scopes", scopes_list);
1617 arguments->set(
"unsent-update-count",
1618 Element::create(
static_cast<int64_t
>(communication_state_->getUnsentUpdateCount())));
1625HAService::processHAReset() {
1635HAService::asyncSendHeartbeat() {
1645 bool sync_complete_notified = sync_complete_notified_;
1646 sync_complete_notified_ =
false;
1650 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1652 partner_config->addBasicAuthHttpHeader(request);
1653 request->setBodyAsJson(CommandCreator::createHeartbeat(server_type_));
1654 request->finalize();
1661 client_->asyncSendRequest(partner_config->getUrl(),
1662 partner_config->getTlsContext(),
1664 [
this, partner_config, sync_complete_notified]
1665 (
const boost::system::error_code& ec,
1667 const std::string& error_str) {
1675 bool heartbeat_success = true;
1678 if (ec || !error_str.empty()) {
1679 LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
1680 .arg(partner_config->getLogLabel())
1681 .arg(ec ? ec.message() : error_str);
1682 heartbeat_success = false;
1691 ConstElementPtr args = verifyAsyncResponse(response, rcode);
1692 if (!args || args->getType() != Element::map) {
1693 isc_throw(CtrlChannelError,
"returned arguments in the response"
1697 ConstElementPtr state = args->get(
"state");
1698 if (!state || state->getType() != Element::string) {
1699 isc_throw(CtrlChannelError,
"server state not returned in response"
1700 " to a ha-heartbeat command or it is not a string");
1704 communication_state_->setPartnerState(state->stringValue());
1706 ConstElementPtr date_time = args->get(
"date-time");
1707 if (!date_time || date_time->getType() != Element::string) {
1708 isc_throw(CtrlChannelError,
"date-time not returned in response"
1709 " to a ha-heartbeat command or it is not a string");
1712 communication_state_->setPartnerTime(date_time->stringValue());
1716 auto scopes = args->get(
"scopes");
1717 communication_state_->setPartnerScopes(scopes);
1732 auto unsent_update_count = args->get(
"unsent-update-count");
1733 if (unsent_update_count) {
1734 if (unsent_update_count->getType() != Element::integer) {
1735 isc_throw(CtrlChannelError,
"unsent-update-count returned in"
1736 " the ha-heartbeat response is not an integer");
1738 communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>
1739 (unsent_update_count->intValue()));
1742 } catch (
const std::exception& ex) {
1744 .arg(partner_config->getLogLabel())
1746 heartbeat_success =
false;
1752 if (heartbeat_success) {
1753 communication_state_->poke();
1758 communication_state_->setPartnerState(
"unavailable");
1760 if (communication_state_->isCommunicationInterrupted()) {
1762 .arg(partner_config->getName());
1770 if (sync_complete_notified && !heartbeat_success) {
1771 postNextEvent(HA_SYNCED_PARTNER_UNAVAILABLE_EVT);
1778 runModel(HA_HEARTBEAT_COMPLETE_EVT);
1781 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1782 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1783 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1788HAService::scheduleHeartbeat() {
1789 if (!communication_state_->isHeartbeatRunning()) {
1795HAService::startHeartbeat() {
1796 if (config_->getHeartbeatDelay() > 0) {
1797 communication_state_->startHeartbeat(config_->getHeartbeatDelay(),
1798 std::bind(&HAService::asyncSendHeartbeat,
1805 const std::string& server_name,
1806 const unsigned int max_period,
1812 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1815 remote_config->addBasicAuthHttpHeader(request);
1816 request->setBodyAsJson(CommandCreator::createDHCPDisable(max_period,
1818 request->finalize();
1826 remote_config->getTlsContext(),
1828 [
this, remote_config, post_request_action]
1829 (
const boost::system::error_code& ec,
1831 const std::string& error_str) {
1840 std::string error_message;
1843 if (ec || !error_str.empty()) {
1844 error_message = (ec ? ec.message() : error_str);
1845 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
1846 .arg(remote_config->getLogLabel())
1847 .arg(error_message);
1853 static_cast<void>(verifyAsyncResponse(response, rcode));
1855 } catch (
const std::exception& ex) {
1856 error_message = ex.what();
1858 .arg(remote_config->getLogLabel())
1859 .arg(error_message);
1865 if (!error_message.empty()) {
1866 communication_state_->setPartnerState(
"unavailable");
1870 if (post_request_action) {
1871 post_request_action(error_message.empty(),
1877 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1878 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1879 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1885 const std::string& server_name,
1891 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1893 remote_config->addBasicAuthHttpHeader(request);
1894 request->setBodyAsJson(CommandCreator::createDHCPEnable(server_type_));
1895 request->finalize();
1903 remote_config->getTlsContext(),
1905 [
this, remote_config, post_request_action]
1906 (
const boost::system::error_code& ec,
1908 const std::string& error_str) {
1917 std::string error_message;
1920 if (ec || !error_str.empty()) {
1921 error_message = (ec ? ec.message() : error_str);
1922 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
1923 .arg(remote_config->getLogLabel())
1924 .arg(error_message);
1930 static_cast<void>(verifyAsyncResponse(response, rcode));
1932 } catch (
const std::exception& ex) {
1933 error_message = ex.what();
1935 .arg(remote_config->getLogLabel())
1936 .arg(error_message);
1942 if (!error_message.empty()) {
1943 communication_state_->setPartnerState(
"unavailable");
1947 if (post_request_action) {
1948 post_request_action(error_message.empty(),
1954 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1955 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1956 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1961HAService::localDisableDHCPService() {
1962 network_state_->disableService(NetworkState::Origin::HA_COMMAND);
1966HAService::localEnableDHCPService() {
1967 network_state_->enableService(NetworkState::Origin::HA_COMMAND);
1971HAService::asyncSyncLeases() {
1975 unsigned int dhcp_disable_timeout =
1976 static_cast<unsigned int>(config_->getSyncTimeout() / 1000);
1977 if (dhcp_disable_timeout == 0) {
1979 dhcp_disable_timeout = 1;
1982 asyncSyncLeases(*client_, config_->getFailoverPeerConfig()->getName(),
1983 dhcp_disable_timeout,
LeasePtr(), null_action);
1988 const std::string& server_name,
1989 const unsigned int max_period,
1992 const bool dhcp_disabled) {
1998 asyncDisableDHCPService(http_client, server_name, max_period,
1999 [
this, &http_client, server_name, max_period, last_lease,
2000 post_sync_action, dhcp_disabled]
2001 (
const bool success,
const std::string& error_message,
const int) {
2008 asyncSyncLeasesInternal(http_client, server_name, max_period,
2009 last_lease, post_sync_action,
true);
2012 post_sync_action(success, error_message, dhcp_disabled);
2019 const std::string& server_name,
2020 const unsigned int max_period,
2023 const bool dhcp_disabled) {
2029 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2031 partner_config->addBasicAuthHttpHeader(request);
2033 request->setBodyAsJson(CommandCreator::createLease4GetPage(
2034 boost::dynamic_pointer_cast<Lease4>(last_lease), config_->getSyncPageLimit()));
2037 request->setBodyAsJson(CommandCreator::createLease6GetPage(
2038 boost::dynamic_pointer_cast<Lease6>(last_lease), config_->getSyncPageLimit()));
2040 request->finalize();
2048 partner_config->getTlsContext(),
2050 [
this, partner_config, post_sync_action, &http_client, server_name,
2051 max_period, dhcp_disabled]
2052 (
const boost::system::error_code& ec,
2054 const std::string& error_str) {
2058 LeasePtr last_lease;
2066 std::string error_message;
2069 if (ec || !error_str.empty()) {
2070 error_message = (ec ? ec.message() : error_str);
2071 LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
2072 .arg(partner_config->getLogLabel())
2073 .arg(error_message);
2079 ConstElementPtr args = verifyAsyncResponse(response, rcode);
2082 if (args && (args->getType() != Element::map)) {
2083 isc_throw(CtrlChannelError,
2084 "arguments in the received response must be a map");
2087 ConstElementPtr leases = args->get(
"leases");
2088 if (!leases || (leases->getType() != Element::list)) {
2089 isc_throw(CtrlChannelError,
2090 "server response does not contain leases argument or this"
2091 " argument is not a list");
2095 const auto& leases_element = leases->listValue();
2097 LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
2098 .arg(leases_element.size())
2101 for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
2104 if (server_type_ == HAServerType::DHCPv4) {
2105 Lease4Ptr lease = Lease4::fromElement(*l);
2108 Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
2109 if (!existing_lease) {
2111 LeaseMgrFactory::instance().addLease(lease);
2113 } else if (existing_lease->cltt_ < lease->cltt_) {
2119 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2120 LeaseMgrFactory::instance().updateLease4(lease);
2123 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
2124 .arg(lease->addr_.toText())
2125 .arg(lease->subnet_id_);
2131 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2132 (l + 1 == leases_element.end())) {
2133 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2137 Lease6Ptr lease = Lease6::fromElement(*l);
2140 Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
2142 if (!existing_lease) {
2144 LeaseMgrFactory::instance().addLease(lease);
2146 } else if (existing_lease->cltt_ < lease->cltt_) {
2152 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2153 LeaseMgrFactory::instance().updateLease6(lease);
2156 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
2157 .arg(lease->addr_.toText())
2158 .arg(lease->subnet_id_);
2164 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2165 (l + 1 == leases_element.end())) {
2166 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2170 } catch (const std::exception& ex) {
2171 LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
2177 } catch (
const std::exception& ex) {
2178 error_message = ex.what();
2180 .arg(partner_config->getLogLabel())
2181 .arg(error_message);
2187 if (!error_message.empty()) {
2188 communication_state_->setPartnerState(
"unavailable");
2190 }
else if (last_lease) {
2193 asyncSyncLeases(http_client, server_name, max_period, last_lease,
2194 post_sync_action, dhcp_disabled);
2199 if (post_sync_action) {
2200 post_sync_action(error_message.empty(),
2206 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2207 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2208 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2214HAService::processSynchronize(
const std::string& server_name,
2215 const unsigned int max_period) {
2216 std::string answer_message;
2217 int sync_status = synchronize(answer_message, server_name, max_period);
2222HAService::synchronize(std::string& status_message,
const std::string& server_name,
2223 const unsigned int max_period) {
2227 asyncSyncLeases(client, server_name, max_period,
Lease4Ptr(),
2228 [&](
const bool success,
const std::string& error_message,
2229 const bool dhcp_disabled) {
2234 status_message = error_message;
2240 if (dhcp_disabled) {
2245 asyncSyncCompleteNotify(client, server_name,
2246 [&](
const bool success,
2247 const std::string& error_message,
2253 asyncEnableDHCPService(client, server_name,
2254 [&](
const bool success,
2255 const std::string& error_message,
2260 if (!success && status_message.empty()) {
2261 status_message = error_message;
2273 if (!success && status_message.empty()) {
2274 status_message = error_message;
2286 asyncEnableDHCPService(client, server_name,
2287 [&](
const bool success,
2288 const std::string& error_message,
2290 if (!success && status_message.empty()) {
2291 status_message = error_message;
2323 if (!status_message.empty()) {
2324 postNextEvent(HA_SYNCING_FAILED_EVT);
2328 .arg(status_message);
2335 status_message =
"Lease database synchronization complete.";
2336 postNextEvent(HA_SYNCING_SUCCEEDED_EVT);
2346HAService::asyncSendLeaseUpdatesFromBacklog(
HttpClient& http_client,
2349 if (lease_update_backlog_.size() == 0) {
2357 Lease4Ptr lease = boost::dynamic_pointer_cast<Lease4>(lease_update_backlog_.pop(op_type));
2358 if (op_type == LeaseUpdateBacklog::ADD) {
2359 command = CommandCreator::createLease4Update(*lease);
2361 command = CommandCreator::createLease4Delete(*lease);
2365 command = CommandCreator::createLease6BulkApply(lease_update_backlog_);
2370 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2372 config->addBasicAuthHttpHeader(request);
2373 request->setBodyAsJson(command);
2374 request->finalize();
2382 [
this, &http_client, config, post_request_action]
2383 (
const boost::system::error_code& ec,
2385 const std::string& error_str) {
2388 std::string error_message;
2390 if (ec || !error_str.empty()) {
2391 error_message = (ec ? ec.message() : error_str);
2392 LOG_WARN(ha_logger, HA_LEASES_BACKLOG_COMMUNICATIONS_FAILED)
2393 .arg(config->getLogLabel())
2394 .arg(ec ? ec.message() : error_str);
2399 auto args = verifyAsyncResponse(response, rcode);
2400 } catch (
const std::exception& ex) {
2401 error_message = ex.what();
2403 .arg(config->getLogLabel())
2413 if (error_message.empty()) {
2414 asyncSendLeaseUpdatesFromBacklog(http_client, config, post_request_action);
2416 post_request_action(error_message.empty(), error_message, rcode);
2422HAService::sendLeaseUpdatesFromBacklog() {
2423 auto num_updates = lease_update_backlog_.size();
2424 if (num_updates == 0) {
2431 auto remote_config = config_->getFailoverPeerConfig();
2432 bool updates_successful =
true;
2436 .arg(remote_config->getName());
2438 asyncSendLeaseUpdatesFromBacklog(client, remote_config,
2439 [&](
const bool success,
const std::string&,
const int) {
2441 updates_successful = success;
2453 if (updates_successful) {
2455 .arg(remote_config->getName())
2456 .arg(stopwatch.logFormatLastDuration());
2459 return (updates_successful);
2466 ConstElementPtr command = CommandCreator::createHAReset(server_type_);
2470 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2472 config->addBasicAuthHttpHeader(request);
2473 request->setBodyAsJson(command);
2474 request->finalize();
2482 [
this, config, post_request_action]
2483 (
const boost::system::error_code& ec,
2485 const std::string& error_str) {
2488 std::string error_message;
2490 if (ec || !error_str.empty()) {
2491 error_message = (ec ? ec.message() : error_str);
2492 LOG_WARN(ha_logger, HA_RESET_COMMUNICATIONS_FAILED)
2493 .arg(config->getLogLabel())
2494 .arg(ec ? ec.message() : error_str);
2499 auto args = verifyAsyncResponse(response, rcode);
2500 } catch (
const std::exception& ex) {
2501 error_message = ex.what();
2503 .arg(config->getLogLabel())
2508 post_request_action(error_message.empty(), error_message, rcode);
2513HAService::sendHAReset() {
2516 auto remote_config = config_->getFailoverPeerConfig();
2517 bool reset_successful =
true;
2519 asyncSendHAReset(client, remote_config,
2520 [&](
const bool success,
const std::string&,
const int) {
2522 reset_successful = success;
2528 return (reset_successful);
2532HAService::processScopes(
const std::vector<std::string>& scopes) {
2534 query_filter_.serveScopes(scopes);
2535 adjustNetworkState();
2537 }
catch (
const std::exception& ex) {
2545HAService::processContinue() {
2553HAService::processMaintenanceNotify(
const bool cancel) {
2557 " maintenance for the server not in the"
2558 " in-maintenance state."));
2561 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
2562 verboseTransition(getPrevState());
2567 switch (getCurrState()) {
2577 return (
createAnswer(HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED,
2578 "Unable to transition the server from the "
2580 " in-maintenance state."));
2583 runModel(HA_MAINTENANCE_NOTIFY_EVT);
2589HAService::processMaintenanceStart() {
2590 switch (getCurrState()) {
2597 " partner-in-maintenance state."));
2607 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2609 remote_config->addBasicAuthHttpHeader(request);
2610 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(
false, server_type_));
2611 request->finalize();
2620 boost::system::error_code captured_ec;
2621 std::string captured_error_message;
2622 int captured_rcode = 0;
2626 remote_config->getTlsContext(),
2628 [
this, remote_config, &io_service, &captured_ec, &captured_error_message,
2630 (
const boost::system::error_code& ec,
2632 const std::string& error_str) {
2642 std::string error_message;
2645 if (ec || !error_str.empty()) {
2646 error_message = (ec ? ec.message() : error_str);
2647 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_COMMUNICATIONS_FAILED)
2648 .arg(remote_config->getLogLabel())
2649 .arg(error_message);
2655 static_cast<void>(verifyAsyncResponse(response, captured_rcode));
2657 } catch (
const std::exception& ex) {
2658 error_message = ex.what();
2660 .arg(remote_config->getLogLabel())
2661 .arg(error_message);
2667 if (!error_message.empty()) {
2668 communication_state_->setPartnerState(
"unavailable");
2672 captured_error_message = error_message;
2675 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2676 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2677 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2687 postNextEvent(HA_MAINTENANCE_START_EVT);
2691 "Server is now in the partner-down state as its"
2692 " partner appears to be offline for maintenance."));
2698 postNextEvent(HA_MAINTENANCE_START_EVT);
2706 " partner-in-maintenance state. The partner server responded"
2707 " with the following message to the ha-maintenance-notify"
2708 " command: " + captured_error_message +
"."));
2713 "Server is now in the partner-in-maintenance state"
2714 " and its partner is in-maintenance state. The partner"
2715 " can be now safely shut down."));
2719HAService::processMaintenanceCancel() {
2722 " request because the server is not in the"
2723 " partner-in-maintenance state."));
2731 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2733 remote_config->addBasicAuthHttpHeader(request);
2734 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(
true, server_type_));
2735 request->finalize();
2744 std::string error_message;
2748 remote_config->getTlsContext(),
2750 [
this, remote_config, &io_service, &error_message]
2751 (
const boost::system::error_code& ec,
2753 const std::string& error_str) {
2758 if (ec || !error_str.empty()) {
2759 error_message = (ec ? ec.message() : error_str);
2760 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_CANCEL_COMMUNICATIONS_FAILED)
2761 .arg(remote_config->getLogLabel())
2762 .arg(error_message);
2769 static_cast<void>(verifyAsyncResponse(response, rcode));
2771 } catch (
const std::exception& ex) {
2772 error_message = ex.what();
2774 .arg(remote_config->getLogLabel())
2775 .arg(error_message);
2781 if (!error_message.empty()) {
2782 communication_state_->setPartnerState(
"unavailable");
2786 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2787 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2788 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2797 if (!error_message.empty()) {
2799 "Unable to cancel maintenance. The partner server responded"
2800 " with the following message to the ha-maintenance-notify"
2801 " command: " + error_message +
"."));
2806 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
2807 verboseTransition(getPrevState());
2811 "Server maintenance successfully canceled."));
2816 const std::string& server_name,
2822 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2825 remote_config->addBasicAuthHttpHeader(request);
2826 request->setBodyAsJson(CommandCreator::createSyncCompleteNotify(server_type_));
2827 request->finalize();
2835 remote_config->getTlsContext(),
2837 [
this, remote_config, post_request_action]
2838 (
const boost::system::error_code& ec,
2840 const std::string& error_str) {
2849 std::string error_message;
2852 if (ec || !error_str.empty()) {
2853 error_message = (ec ? ec.message() : error_str);
2854 LOG_ERROR(ha_logger, HA_SYNC_COMPLETE_NOTIFY_COMMUNICATIONS_FAILED)
2855 .arg(remote_config->getLogLabel())
2856 .arg(error_message);
2862 static_cast<void>(verifyAsyncResponse(response, rcode));
2864 } catch (
const CommandUnsupportedError& ex) {
2867 }
catch (
const std::exception& ex) {
2868 error_message = ex.what();
2870 .arg(remote_config->getLogLabel())
2871 .arg(error_message);
2877 if (!error_message.empty()) {
2878 communication_state_->setPartnerState(
"unavailable");
2882 if (post_request_action) {
2883 post_request_action(error_message.empty(),
2889 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2890 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2891 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2896HAService::processSyncCompleteNotify() {
2898 sync_complete_notified_ =
true;
2900 localEnableDHCPService();
2903 "Server successfully notified about the synchronization completion."));
2912 boost::dynamic_pointer_cast<HttpResponseJson>(response);
2913 if (!json_response) {
2924 if (body->getType() != Element::list) {
2926 if (body->getType() == Element::map) {
2942 if (body->empty()) {
2951 std::ostringstream s;
2953 if (args && args->getType() == Element::string) {
2954 s << args->stringValue() <<
", ";
2957 s <<
"error code " << rcode;
2960 isc_throw(CommandUnsupportedError, s.str());
2970HAService::clientConnectHandler(
const boost::system::error_code& ec,
int tcp_native_fd) {
2974 if (client_->getThreadIOService()) {
2982 if ((!ec || (ec.value() == boost::asio::error::in_progress))
2983 && (tcp_native_fd >= 0)) {
2988 IfaceMgr::instance().addExternalSocket(tcp_native_fd,
2989 std::bind(&HAService::socketReadyHandler,
this, ph::_1)
3001HAService::socketReadyHandler(
int tcp_native_fd) {
3006 client_->closeIfOutOfBand(tcp_native_fd);
3010HAService::clientCloseHandler(
int tcp_native_fd) {
3011 if (tcp_native_fd >= 0) {
3012 IfaceMgr::instance().deleteExternalSocket(tcp_native_fd);
3017HAService::pendingRequestSize() {
3018 if (MultiThreadingMgr::instance().getMode()) {
3019 std::lock_guard<std::mutex> lock(mutex_);
3020 return (pending_requests_.size());
3022 return (pending_requests_.size());
3026template<
typename QueryPtrType>
3028HAService::getPendingRequest(
const QueryPtrType& query) {
3029 if (MultiThreadingMgr::instance().getMode()) {
3030 std::lock_guard<std::mutex> lock(mutex_);
3031 return (getPendingRequestInternal(query));
3033 return (getPendingRequestInternal(query));
3037template<
typename QueryPtrType>
3039HAService::getPendingRequestInternal(
const QueryPtrType& query) {
3040 if (pending_requests_.count(query) == 0) {
3043 return (pending_requests_[query]);
3048HAService::checkPermissionsClientAndListener() {
3056 client_->checkPermissions();
3060 listener_->checkPermissions();
3068 }
catch (
const std::exception& ex) {
3075HAService::startClientAndListener() {
3077 MultiThreadingMgr::instance().addCriticalSectionCallbacks(
"HA_MT",
3078 std::bind(&HAService::checkPermissionsClientAndListener,
this),
3079 std::bind(&HAService::pauseClientAndListener,
this),
3080 std::bind(&HAService::resumeClientAndListener,
this));
3092HAService::pauseClientAndListener() {
3103 }
catch (
const std::exception& ex) {
3110HAService::resumeClientAndListener() {
3119 listener_->resume();
3121 }
catch (std::exception& ex) {
3128HAService::stopClientAndListener() {
3130 MultiThreadingMgr::instance().removeCriticalSectionCallbacks(
"HA_MT");
3142template int HAService::getPendingRequest(
const Pkt4Ptr&);
3143template int HAService::getPendingRequest(
const Pkt6Ptr&);
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
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)
The IOService class is a wrapper for the ASIO io_service class.
void run()
Start the underlying event loop.
void stop()
Stop the underlying event loop.
A multi-threaded HTTP listener that can process API commands requests.
A standard control channel exception that is thrown if a function is there is a problem with one of t...
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 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.
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.
bool shouldTerminate() const
Indicates if the server should transition to the terminated state as a result of high clock skew.
void terminatedStateHandler()
Handler for "terminated" state.
dhcp::NetworkStatePtr network_state_
Pointer to the state of the DHCP service (enabled/disabled).
HAService(const asiolink::IOServicePtr &io_service, const dhcp::NetworkStatePtr &network_state, const HAConfigPtr &config, const HAServerType &server_type=HAServerType::DHCPv4)
Constructor.
void scheduleHeartbeat()
Schedules asynchronous heartbeat to a peer if it is not scheduled.
void passiveBackupStateHandler()
Handler for "passive-backup" state.
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 inMaintenanceStateHandler()
Handler for the "in-maintenance" state.
virtual void verifyEvents()
Verifies events used by the HA service.
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.
std::function< void(const bool, const std::string &, const int)> PostRequestCallback
Callback invoked when request was sent and a response received or an error occurred.
virtual void defineEvents()
Defines events used by the HA service.
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.
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.
void readyStateHandler()
Handler for "ready" state.
virtual void defineStates()
Defines states of the HA service.
void backupStateHandler()
Handler for the "backup" state.
void communicationRecoveryHandler()
Handler for the "communication-recovery" state.
bool isPartnerStateInvalid() const
Indicates if the partner's state is invalid.
int synchronize(std::string &status_message, const std::string &server_name, const unsigned int max_period)
Synchronizes lease database with a partner.
void normalStateHandler()
Handler for the "hot-standby" and "load-balancing" states.
void waitingStateHandler()
Handler for "waiting" state.
bool shouldSendLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be sent as result of leases allocation or release.
static const int HA_LEASE_UPDATES_COMPLETE_EVT
Finished lease updates commands.
void partnerDownStateHandler()
Handler for "partner-down" state.
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.
std::function< void(const bool, const std::string &, const bool)> PostSyncCallback
Callback invoked when lease database synchronization is complete.
void syncingStateHandler()
Handler for "syncing" state.
void partnerInMaintenanceStateHandler()
Handler for "partner-in-maintenance" state.
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.
void asyncSendRequest(const Url &url, const asiolink::TlsContextPtr &tls_context, const HttpRequestPtr &request, const HttpResponsePtr &response, const RequestHandler &request_callback, const RequestTimeout &request_timeout=RequestTimeout(10000), const ConnectHandler &connect_callback=ConnectHandler(), const HandshakeHandler &handshake_callback=HandshakeHandler(), const CloseHandler &close_callback=CloseHandler())
Queues new asynchronous HTTP request for a given URL.
This class parses and generates time values used in HTTP.
std::string rfc1123Format() const
Returns time value formatted as specified in RFC 1123.
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.
bool isModelPaused() const
Returns whether or not the model is paused.
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.
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.
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.
std::string logFormatLastDuration() const
Returns the last measured duration in the format directly usable in log messages.
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.
const int CONTROL_RESULT_COMMAND_UNSUPPORTED
Status code indicating that the specified command is not supported.
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
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.
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_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_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_SYNC_COMPLETE_NOTIFY_FAILED
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED
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.