27 #include <boost/pointer_cast.hpp>
28 #include <boost/make_shared.hpp>
29 #include <boost/weak_ptr.hpp>
41 namespace 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) :
64 const int HAService::HA_HEARTBEAT_COMPLETE_EVT;
65 const int HAService::HA_LEASE_UPDATES_COMPLETE_EVT;
66 const int HAService::HA_SYNCING_FAILED_EVT;
67 const int HAService::HA_SYNCING_SUCCEEDED_EVT;
68 const int HAService::HA_MAINTENANCE_NOTIFY_EVT;
69 const int HAService::HA_MAINTENANCE_START_EVT;
70 const int HAService::HA_MAINTENANCE_CANCEL_EVT;
71 const int HAService::HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED;
72 const int HAService::HA_SYNCED_PARTNER_UNAVAILABLE_EVT;
76 : io_service_(io_service), network_state_(network_state), config_(config),
77 server_type_(server_type), client_(), listener_(), communication_state_(),
78 query_filter_(config), mutex_(), pending_requests_(),
79 lease_update_backlog_(config->getDelayedUpdatesLimit()),
80 sync_complete_notified_(false) {
94 if (!
config_->getEnableMultiThreading()) {
100 config_->getHttpClientThreads(),
true));
103 if (
config_->getHttpDedicatedListener()) {
105 auto my_url =
config_->getThisServerConfig()->getUrl();
106 IOAddress server_address(IOAddress::IPV4_ZERO_ADDRESS());
110 server_address =
IOAddress(my_url.getStrippedHostname());
111 }
catch (
const std::exception& ex) {
113 <<
" is not a valid IP address");
117 uint32_t listener_threads =
config_->getHttpListenerThreads();
120 auto tls_context =
config_->getThisServerConfig()->getTlsContext();
124 listener_threads, tls_context));
126 if (
config_->getRestrictCommands()) {
128 CmdResponseCreator::command_accept_list_ =
131 CmdResponseCreator::command_accept_list_ =
152 StateModel::defineEvents();
166 StateModel::verifyEvents();
180 StateModel::defineStates();
419 }
else if (
config_->amAllowingCommRecovery()) {
478 if (maintenance ||
config_->getThisServerConfig()->isAutoFailover()) {
752 unsigned int dhcp_disable_timeout =
753 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
754 if (dhcp_disable_timeout == 0) {
755 ++dhcp_disable_timeout;
759 std::string status_message;
761 config_->getFailoverPeerConfig()->getName(),
762 dhcp_disable_timeout);
919 boost::to_upper(current_state_name);
920 boost::to_upper(new_state_name);
926 std::string partner_state_name =
getStateLabel(partner_state);
927 boost::to_upper(partner_state_name);
931 .arg(current_state_name)
933 .arg(partner_state_name);
938 .arg(current_state_name)
939 .arg(new_state_name);
960 .arg(new_state_name);
962 }
else if (!
config_->amSendingLeaseUpdates()) {
965 .arg(new_state_name);
972 .arg(new_state_name);
983 switch (
config_->getHAMode()) {
1008 boost::to_upper(state_name);
1021 return (inScopeInternal(query4));
1026 return (inScopeInternal(query6));
1029 template<
typename QueryPtrType>
1031 HAService::inScopeInternal(QueryPtrType& query) {
1033 std::string scope_class;
1052 boost::to_upper(current_state_name);
1065 boost::to_upper(current_state_name);
1067 .arg(
config_->getThisServerName())
1068 .arg(current_state_name);
1069 network_state_->disableService(NetworkState::Origin::HA_COMMAND);
1071 }
else if (should_enable && !
network_state_->isServiceEnabled()) {
1073 boost::to_upper(current_state_name);
1075 .arg(
config_->getThisServerName())
1076 .arg(current_state_name);
1114 if (!should_terminate) {
1121 return (should_terminate);
1168 size_t sent_num = 0;
1171 for (
auto p = peers_configs.begin(); p != peers_configs.end(); ++p) {
1179 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
1184 for (
auto l = leases->begin(); l != leases->end(); ++l) {
1206 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
1212 for (
auto l = leases->begin(); l != leases->end(); ++l) {
1237 size_t sent_num = 0;
1240 for (
auto p = peers_configs.begin(); p != peers_configs.end(); ++p) {
1247 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
1252 for (
auto l = leases->begin(); l != leases->end(); ++l) {
1288 template<
typename QueryPtrType>
1292 if (MultiThreadingMgr::instance().getMode()) {
1293 std::lock_guard<std::mutex> lock(mutex_);
1294 return (leaseUpdateCompleteInternal(query, parking_lot));
1296 return (leaseUpdateCompleteInternal(query, parking_lot));
1300 template<
typename QueryPtrType>
1302 HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
1304 auto it = pending_requests_.find(query);
1308 if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
1309 parking_lot->unpark(query);
1313 if (it != pending_requests_.end()) {
1314 pending_requests_.erase(it);
1321 template<
typename QueryPtrType>
1324 if (MultiThreadingMgr::instance().getMode()) {
1325 std::lock_guard<std::mutex> lock(mutex_);
1326 updatePendingRequestInternal(query);
1328 updatePendingRequestInternal(query);
1332 template<
typename QueryPtrType>
1334 HAService::updatePendingRequestInternal(QueryPtrType& query) {
1335 if (pending_requests_.count(query) == 0) {
1336 pending_requests_[query] = 1;
1338 ++pending_requests_[query];
1342 template<
typename QueryPtrType>
1350 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1352 config->addBasicAuthHttpHeader(request);
1353 request->setBodyAsJson(command);
1354 request->finalize();
1363 boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
1366 client_->asyncSendRequest(config->getUrl(), config->getTlsContext(),
1368 [
this, weak_query, parking_lot, config]
1369 (
const boost::system::error_code& ec,
1371 const std::string& error_str) {
1375 QueryPtrType query = weak_query.lock();
1377 isc_throw(Unexpected,
"query is null while receiving response from"
1378 " HA peer. This is programmatic error");
1389 bool lease_update_success =
true;
1390 bool lease_update_conflict =
false;
1393 if (ec || !error_str.empty()) {
1394 LOG_WARN(ha_logger, HA_LEASE_UPDATE_COMMUNICATIONS_FAILED)
1395 .arg(query->getLabel())
1396 .arg(config->getLogLabel())
1397 .arg(ec ? ec.message() : error_str);
1401 lease_update_success = false;
1407 auto args = verifyAsyncResponse(response, rcode);
1410 logFailedLeaseUpdates(query, args);
1412 } catch (
const ConflictError& ex) {
1414 lease_update_conflict =
true;
1415 lease_update_success =
false;
1419 .arg(query->getLabel())
1420 .arg(config->getLogLabel())
1423 }
catch (
const std::exception& ex) {
1426 .arg(query->getLabel())
1427 .arg(config->getLogLabel())
1431 lease_update_success =
false;
1440 if (!lease_update_success) {
1443 if (!lease_update_conflict) {
1446 communication_state_->setPartnerUnavailable();
1451 communication_state_->reportSuccessfulLeaseUpdate(query);
1462 if (!lease_update_success) {
1463 parking_lot->drop(query);
1471 if (leaseUpdateComplete(query, parking_lot)) {
1477 runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
1481 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1482 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1483 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1490 if (config_->amWaitingBackupAck() || (config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1492 updatePendingRequest(query);
1499 if (!config_->amSendingLeaseUpdates()) {
1504 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1509 if (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP) {
1515 switch (getCurrState()) {
1530 if (!config_->amSendingLeaseUpdates()) {
1534 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1542 HAService::logFailedLeaseUpdates(
const PktPtr& query,
1545 if (!args || (args->getType() != Element::map)) {
1555 auto failed_leases = args->get(param_name);
1558 if (failed_leases && (failed_leases->getType() == Element::list)) {
1560 for (
int i = 0; i < failed_leases->size(); ++i) {
1561 auto lease = failed_leases->get(i);
1562 if (lease->getType() == Element::map) {
1565 auto ip_address = lease->get(
"ip-address");
1568 auto lease_type = lease->get(
"type");
1571 auto error_message = lease->get(
"error-message");
1574 .arg(query->getLabel())
1575 .arg(lease_type && (lease_type->getType() == Element::string) ?
1576 lease_type->stringValue() :
"(unknown)")
1577 .arg(ip_address && (ip_address->getType() == Element::string) ?
1578 ip_address->stringValue() :
"(unknown)")
1579 .arg(error_message && (error_message->getType() == Element::string) ?
1580 error_message->stringValue() :
"(unknown)");
1594 HAService::processStatusGet()
const {
1595 ElementPtr ha_servers = Element::createMap();
1600 role = config_->getThisServerConfig()->getRole();
1601 std::string role_txt = HAConfig::PeerConfig::roleToString(role);
1602 local->set(
"role", Element::create(role_txt));
1603 int state = getCurrState();
1609 local->set(
"state", Element::create(std::string()));
1611 std::set<std::string> scopes = query_filter_.getServedScopes();
1613 for (std::string scope : scopes) {
1614 list->add(Element::create(scope));
1616 local->set(
"scopes", list);
1617 ha_servers->set(
"local", local);
1621 if ((config_->getHAMode() == HAConfig::PASSIVE_BACKUP) ||
1622 (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP)) {
1623 return (ha_servers);
1627 ElementPtr remote = communication_state_->getReport();
1630 role = config_->getFailoverPeerConfig()->getRole();
1631 std::string role_txt = HAConfig::PeerConfig::roleToString(role);
1632 remote->set(
"role", Element::create(role_txt));
1635 remote->set(
"role", Element::create(std::string()));
1637 ha_servers->set(
"remote", remote);
1639 return (ha_servers);
1643 HAService::processHeartbeat() {
1645 std::string state_label = getState(getCurrState())->getLabel();
1646 arguments->set(
"state", Element::create(state_label));
1649 arguments->set(
"date-time", Element::create(date_time));
1651 auto scopes = query_filter_.getServedScopes();
1652 ElementPtr scopes_list = Element::createList();
1653 for (
auto scope : scopes) {
1654 scopes_list->add(Element::create(scope));
1656 arguments->set(
"scopes", scopes_list);
1658 arguments->set(
"unsent-update-count",
1659 Element::create(
static_cast<int64_t
>(communication_state_->getUnsentUpdateCount())));
1666 HAService::processHAReset() {
1676 HAService::asyncSendHeartbeat() {
1686 bool sync_complete_notified = sync_complete_notified_;
1687 sync_complete_notified_ =
false;
1691 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1693 partner_config->addBasicAuthHttpHeader(request);
1694 request->setBodyAsJson(CommandCreator::createHeartbeat(server_type_));
1695 request->finalize();
1702 client_->asyncSendRequest(partner_config->getUrl(),
1703 partner_config->getTlsContext(),
1705 [
this, partner_config, sync_complete_notified]
1706 (
const boost::system::error_code& ec,
1708 const std::string& error_str) {
1716 bool heartbeat_success = true;
1719 if (ec || !error_str.empty()) {
1720 LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
1721 .arg(partner_config->getLogLabel())
1722 .arg(ec ? ec.message() : error_str);
1723 heartbeat_success = false;
1732 ConstElementPtr args = verifyAsyncResponse(response, rcode);
1733 if (!args || args->getType() != Element::map) {
1734 isc_throw(CtrlChannelError,
"returned arguments in the response"
1738 ConstElementPtr state = args->get(
"state");
1739 if (!state || state->getType() != Element::string) {
1740 isc_throw(CtrlChannelError,
"server state not returned in response"
1741 " to a ha-heartbeat command or it is not a string");
1745 communication_state_->setPartnerState(state->stringValue());
1747 ConstElementPtr date_time = args->get(
"date-time");
1748 if (!date_time || date_time->getType() != Element::string) {
1749 isc_throw(CtrlChannelError,
"date-time not returned in response"
1750 " to a ha-heartbeat command or it is not a string");
1753 communication_state_->setPartnerTime(date_time->stringValue());
1757 auto scopes = args->get(
"scopes");
1758 communication_state_->setPartnerScopes(scopes);
1773 auto unsent_update_count = args->get(
"unsent-update-count");
1774 if (unsent_update_count) {
1775 if (unsent_update_count->getType() != Element::integer) {
1776 isc_throw(CtrlChannelError,
"unsent-update-count returned in"
1777 " the ha-heartbeat response is not an integer");
1779 communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>
1780 (unsent_update_count->intValue()));
1783 } catch (
const std::exception& ex) {
1785 .arg(partner_config->getLogLabel())
1787 heartbeat_success =
false;
1793 if (heartbeat_success) {
1794 communication_state_->poke();
1799 communication_state_->setPartnerUnavailable();
1801 if (communication_state_->isCommunicationInterrupted()) {
1803 .arg(partner_config->getName());
1811 if (sync_complete_notified && !heartbeat_success) {
1812 postNextEvent(HA_SYNCED_PARTNER_UNAVAILABLE_EVT);
1819 runModel(HA_HEARTBEAT_COMPLETE_EVT);
1822 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1823 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1824 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1829 HAService::scheduleHeartbeat() {
1830 if (!communication_state_->isHeartbeatRunning()) {
1836 HAService::startHeartbeat() {
1837 if (config_->getHeartbeatDelay() > 0) {
1838 communication_state_->startHeartbeat(config_->getHeartbeatDelay(),
1839 std::bind(&HAService::asyncSendHeartbeat,
1846 const std::string& server_name,
1847 const unsigned int max_period,
1853 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1856 remote_config->addBasicAuthHttpHeader(request);
1857 request->setBodyAsJson(CommandCreator::createDHCPDisable(max_period,
1859 request->finalize();
1867 remote_config->getTlsContext(),
1869 [
this, remote_config, post_request_action]
1870 (
const boost::system::error_code& ec,
1872 const std::string& error_str) {
1881 std::string error_message;
1884 if (ec || !error_str.empty()) {
1885 error_message = (ec ? ec.message() : error_str);
1886 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
1887 .arg(remote_config->getLogLabel())
1888 .arg(error_message);
1894 static_cast<void>(verifyAsyncResponse(response, rcode));
1896 } catch (
const std::exception& ex) {
1897 error_message = ex.what();
1899 .arg(remote_config->getLogLabel())
1900 .arg(error_message);
1906 if (!error_message.empty()) {
1907 communication_state_->setPartnerUnavailable();
1911 if (post_request_action) {
1912 post_request_action(error_message.empty(),
1918 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1919 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1920 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1926 const std::string& server_name,
1932 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
1934 remote_config->addBasicAuthHttpHeader(request);
1935 request->setBodyAsJson(CommandCreator::createDHCPEnable(server_type_));
1936 request->finalize();
1944 remote_config->getTlsContext(),
1946 [
this, remote_config, post_request_action]
1947 (
const boost::system::error_code& ec,
1949 const std::string& error_str) {
1958 std::string error_message;
1961 if (ec || !error_str.empty()) {
1962 error_message = (ec ? ec.message() : error_str);
1963 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
1964 .arg(remote_config->getLogLabel())
1965 .arg(error_message);
1971 static_cast<void>(verifyAsyncResponse(response, rcode));
1973 } catch (
const std::exception& ex) {
1974 error_message = ex.what();
1976 .arg(remote_config->getLogLabel())
1977 .arg(error_message);
1983 if (!error_message.empty()) {
1984 communication_state_->setPartnerUnavailable();
1988 if (post_request_action) {
1989 post_request_action(error_message.empty(),
1995 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1996 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1997 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2002 HAService::localDisableDHCPService() {
2003 network_state_->disableService(NetworkState::Origin::HA_COMMAND);
2007 HAService::localEnableDHCPService() {
2008 network_state_->enableService(NetworkState::Origin::HA_COMMAND);
2012 HAService::asyncSyncLeases() {
2016 unsigned int dhcp_disable_timeout =
2017 static_cast<unsigned int>(config_->getSyncTimeout() / 1000);
2018 if (dhcp_disable_timeout == 0) {
2020 dhcp_disable_timeout = 1;
2023 asyncSyncLeases(*client_, config_->getFailoverPeerConfig()->getName(),
2024 dhcp_disable_timeout,
LeasePtr(), null_action);
2029 const std::string& server_name,
2030 const unsigned int max_period,
2033 const bool dhcp_disabled) {
2039 asyncDisableDHCPService(http_client, server_name, max_period,
2040 [
this, &http_client, server_name, max_period, last_lease,
2041 post_sync_action, dhcp_disabled]
2042 (
const bool success,
const std::string& error_message,
const int) {
2049 asyncSyncLeasesInternal(http_client, server_name, max_period,
2050 last_lease, post_sync_action,
true);
2053 post_sync_action(success, error_message, dhcp_disabled);
2060 const std::string& server_name,
2061 const unsigned int max_period,
2064 const bool dhcp_disabled) {
2070 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2072 partner_config->addBasicAuthHttpHeader(request);
2074 request->setBodyAsJson(CommandCreator::createLease4GetPage(
2075 boost::dynamic_pointer_cast<Lease4>(last_lease), config_->getSyncPageLimit()));
2078 request->setBodyAsJson(CommandCreator::createLease6GetPage(
2079 boost::dynamic_pointer_cast<Lease6>(last_lease), config_->getSyncPageLimit()));
2081 request->finalize();
2089 partner_config->getTlsContext(),
2091 [
this, partner_config, post_sync_action, &http_client, server_name,
2092 max_period, dhcp_disabled]
2093 (
const boost::system::error_code& ec,
2095 const std::string& error_str) {
2099 LeasePtr last_lease;
2107 std::string error_message;
2110 if (ec || !error_str.empty()) {
2111 error_message = (ec ? ec.message() : error_str);
2112 LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
2113 .arg(partner_config->getLogLabel())
2114 .arg(error_message);
2120 ConstElementPtr args = verifyAsyncResponse(response, rcode);
2123 if (args && (args->getType() != Element::map)) {
2124 isc_throw(CtrlChannelError,
2125 "arguments in the received response must be a map");
2128 ConstElementPtr leases = args->get(
"leases");
2129 if (!leases || (leases->getType() != Element::list)) {
2130 isc_throw(CtrlChannelError,
2131 "server response does not contain leases argument or this"
2132 " argument is not a list");
2136 const auto& leases_element = leases->listValue();
2138 LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
2139 .arg(leases_element.size())
2142 for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
2145 if (server_type_ == HAServerType::DHCPv4) {
2146 Lease4Ptr lease = Lease4::fromElement(*l);
2149 Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
2150 if (!existing_lease) {
2152 LeaseMgrFactory::instance().addLease(lease);
2154 } else if (existing_lease->cltt_ < lease->cltt_) {
2160 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2161 LeaseMgrFactory::instance().updateLease4(lease);
2164 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
2165 .arg(lease->addr_.toText())
2166 .arg(lease->subnet_id_);
2172 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2173 (l + 1 == leases_element.end())) {
2174 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2178 Lease6Ptr lease = Lease6::fromElement(*l);
2181 Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
2183 if (!existing_lease) {
2185 LeaseMgrFactory::instance().addLease(lease);
2187 } else if (existing_lease->cltt_ < lease->cltt_) {
2193 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2194 LeaseMgrFactory::instance().updateLease6(lease);
2197 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
2198 .arg(lease->addr_.toText())
2199 .arg(lease->subnet_id_);
2205 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2206 (l + 1 == leases_element.end())) {
2207 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2211 } catch (const std::exception& ex) {
2212 LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
2218 } catch (
const std::exception& ex) {
2219 error_message = ex.what();
2221 .arg(partner_config->getLogLabel())
2222 .arg(error_message);
2228 if (!error_message.empty()) {
2229 communication_state_->setPartnerUnavailable();
2231 }
else if (last_lease) {
2234 asyncSyncLeases(http_client, server_name, max_period, last_lease,
2235 post_sync_action, dhcp_disabled);
2240 if (post_sync_action) {
2241 post_sync_action(error_message.empty(),
2247 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2248 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2249 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2255 HAService::processSynchronize(
const std::string& server_name,
2256 const unsigned int max_period) {
2257 std::string answer_message;
2258 int sync_status = synchronize(answer_message, server_name, max_period);
2263 HAService::synchronize(std::string& status_message,
const std::string& server_name,
2264 const unsigned int max_period) {
2268 asyncSyncLeases(client, server_name, max_period,
Lease4Ptr(),
2269 [&](
const bool success,
const std::string& error_message,
2270 const bool dhcp_disabled) {
2275 status_message = error_message;
2281 if (dhcp_disabled) {
2286 asyncSyncCompleteNotify(client, server_name,
2287 [&](
const bool success,
2288 const std::string& error_message,
2294 asyncEnableDHCPService(client, server_name,
2295 [&](
const bool success,
2296 const std::string& error_message,
2301 if (!success && status_message.empty()) {
2302 status_message = error_message;
2314 if (!success && status_message.empty()) {
2315 status_message = error_message;
2327 asyncEnableDHCPService(client, server_name,
2328 [&](
const bool success,
2329 const std::string& error_message,
2331 if (!success && status_message.empty()) {
2332 status_message = error_message;
2364 if (!status_message.empty()) {
2365 postNextEvent(HA_SYNCING_FAILED_EVT);
2369 .arg(status_message);
2376 status_message =
"Lease database synchronization complete.";
2377 postNextEvent(HA_SYNCING_SUCCEEDED_EVT);
2387 HAService::asyncSendLeaseUpdatesFromBacklog(
HttpClient& http_client,
2390 if (lease_update_backlog_.size() == 0) {
2398 Lease4Ptr lease = boost::dynamic_pointer_cast<Lease4>(lease_update_backlog_.pop(op_type));
2399 if (op_type == LeaseUpdateBacklog::ADD) {
2400 command = CommandCreator::createLease4Update(*lease);
2402 command = CommandCreator::createLease4Delete(*lease);
2406 command = CommandCreator::createLease6BulkApply(lease_update_backlog_);
2411 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2413 config->addBasicAuthHttpHeader(request);
2414 request->setBodyAsJson(command);
2415 request->finalize();
2423 [
this, &http_client, config, post_request_action]
2424 (
const boost::system::error_code& ec,
2426 const std::string& error_str) {
2429 std::string error_message;
2431 if (ec || !error_str.empty()) {
2432 error_message = (ec ? ec.message() : error_str);
2433 LOG_WARN(ha_logger, HA_LEASES_BACKLOG_COMMUNICATIONS_FAILED)
2434 .arg(config->getLogLabel())
2435 .arg(ec ? ec.message() : error_str);
2440 auto args = verifyAsyncResponse(response, rcode);
2441 } catch (
const std::exception& ex) {
2442 error_message = ex.what();
2444 .arg(config->getLogLabel())
2454 if (error_message.empty()) {
2455 asyncSendLeaseUpdatesFromBacklog(http_client, config, post_request_action);
2457 post_request_action(error_message.empty(), error_message, rcode);
2463 HAService::sendLeaseUpdatesFromBacklog() {
2464 auto num_updates = lease_update_backlog_.size();
2465 if (num_updates == 0) {
2472 auto remote_config = config_->getFailoverPeerConfig();
2473 bool updates_successful =
true;
2477 .arg(remote_config->getName());
2479 asyncSendLeaseUpdatesFromBacklog(client, remote_config,
2480 [&](
const bool success,
const std::string&,
const int) {
2482 updates_successful = success;
2494 if (updates_successful) {
2496 .arg(remote_config->getName())
2497 .arg(stopwatch.logFormatLastDuration());
2500 return (updates_successful);
2507 ConstElementPtr command = CommandCreator::createHAReset(server_type_);
2511 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2513 config->addBasicAuthHttpHeader(request);
2514 request->setBodyAsJson(command);
2515 request->finalize();
2523 [
this, config, post_request_action]
2524 (
const boost::system::error_code& ec,
2526 const std::string& error_str) {
2529 std::string error_message;
2531 if (ec || !error_str.empty()) {
2532 error_message = (ec ? ec.message() : error_str);
2533 LOG_WARN(ha_logger, HA_RESET_COMMUNICATIONS_FAILED)
2534 .arg(config->getLogLabel())
2535 .arg(ec ? ec.message() : error_str);
2540 auto args = verifyAsyncResponse(response, rcode);
2541 } catch (
const std::exception& ex) {
2542 error_message = ex.what();
2544 .arg(config->getLogLabel())
2549 post_request_action(error_message.empty(), error_message, rcode);
2554 HAService::sendHAReset() {
2557 auto remote_config = config_->getFailoverPeerConfig();
2558 bool reset_successful =
true;
2560 asyncSendHAReset(client, remote_config,
2561 [&](
const bool success,
const std::string&,
const int) {
2563 reset_successful = success;
2569 return (reset_successful);
2573 HAService::processScopes(
const std::vector<std::string>& scopes) {
2575 query_filter_.serveScopes(scopes);
2576 adjustNetworkState();
2578 }
catch (
const std::exception& ex) {
2586 HAService::processContinue() {
2594 HAService::processMaintenanceNotify(
const bool cancel) {
2598 " maintenance for the server not in the"
2599 " in-maintenance state."));
2602 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
2603 verboseTransition(getPrevState());
2608 switch (getCurrState()) {
2618 return (
createAnswer(HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED,
2619 "Unable to transition the server from the "
2621 " in-maintenance state."));
2624 runModel(HA_MAINTENANCE_NOTIFY_EVT);
2630 HAService::processMaintenanceStart() {
2631 switch (getCurrState()) {
2638 " partner-in-maintenance state."));
2648 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2650 remote_config->addBasicAuthHttpHeader(request);
2651 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(
false, server_type_));
2652 request->finalize();
2661 boost::system::error_code captured_ec;
2662 std::string captured_error_message;
2663 int captured_rcode = 0;
2667 remote_config->getTlsContext(),
2669 [
this, remote_config, &io_service, &captured_ec, &captured_error_message,
2671 (
const boost::system::error_code& ec,
2673 const std::string& error_str) {
2683 std::string error_message;
2686 if (ec || !error_str.empty()) {
2687 error_message = (ec ? ec.message() : error_str);
2688 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_COMMUNICATIONS_FAILED)
2689 .arg(remote_config->getLogLabel())
2690 .arg(error_message);
2696 static_cast<void>(verifyAsyncResponse(response, captured_rcode));
2698 } catch (
const std::exception& ex) {
2699 error_message = ex.what();
2701 .arg(remote_config->getLogLabel())
2702 .arg(error_message);
2708 if (!error_message.empty()) {
2709 communication_state_->setPartnerUnavailable();
2713 captured_error_message = error_message;
2716 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2717 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2718 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2728 postNextEvent(HA_MAINTENANCE_START_EVT);
2732 "Server is now in the partner-down state as its"
2733 " partner appears to be offline for maintenance."));
2739 postNextEvent(HA_MAINTENANCE_START_EVT);
2747 " partner-in-maintenance state. The partner server responded"
2748 " with the following message to the ha-maintenance-notify"
2749 " command: " + captured_error_message +
"."));
2754 "Server is now in the partner-in-maintenance state"
2755 " and its partner is in-maintenance state. The partner"
2756 " can be now safely shut down."));
2760 HAService::processMaintenanceCancel() {
2763 " request because the server is not in the"
2764 " partner-in-maintenance state."));
2772 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2774 remote_config->addBasicAuthHttpHeader(request);
2775 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(
true, server_type_));
2776 request->finalize();
2785 std::string error_message;
2789 remote_config->getTlsContext(),
2791 [
this, remote_config, &io_service, &error_message]
2792 (
const boost::system::error_code& ec,
2794 const std::string& error_str) {
2799 if (ec || !error_str.empty()) {
2800 error_message = (ec ? ec.message() : error_str);
2801 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_CANCEL_COMMUNICATIONS_FAILED)
2802 .arg(remote_config->getLogLabel())
2803 .arg(error_message);
2810 static_cast<void>(verifyAsyncResponse(response, rcode));
2812 } catch (
const std::exception& ex) {
2813 error_message = ex.what();
2815 .arg(remote_config->getLogLabel())
2816 .arg(error_message);
2822 if (!error_message.empty()) {
2823 communication_state_->setPartnerUnavailable();
2827 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2828 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2829 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2838 if (!error_message.empty()) {
2840 "Unable to cancel maintenance. The partner server responded"
2841 " with the following message to the ha-maintenance-notify"
2842 " command: " + error_message +
"."));
2847 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
2848 verboseTransition(getPrevState());
2852 "Server maintenance successfully canceled."));
2857 const std::string& server_name,
2863 (HttpRequest::Method::HTTP_POST,
"/", HttpVersion::HTTP_11(),
2866 remote_config->addBasicAuthHttpHeader(request);
2867 request->setBodyAsJson(CommandCreator::createSyncCompleteNotify(server_type_));
2868 request->finalize();
2876 remote_config->getTlsContext(),
2878 [
this, remote_config, post_request_action]
2879 (
const boost::system::error_code& ec,
2881 const std::string& error_str) {
2890 std::string error_message;
2893 if (ec || !error_str.empty()) {
2894 error_message = (ec ? ec.message() : error_str);
2895 LOG_ERROR(ha_logger, HA_SYNC_COMPLETE_NOTIFY_COMMUNICATIONS_FAILED)
2896 .arg(remote_config->getLogLabel())
2897 .arg(error_message);
2903 static_cast<void>(verifyAsyncResponse(response, rcode));
2905 } catch (
const CommandUnsupportedError& ex) {
2908 }
catch (
const std::exception& ex) {
2909 error_message = ex.what();
2911 .arg(remote_config->getLogLabel())
2912 .arg(error_message);
2918 if (!error_message.empty()) {
2919 communication_state_->setPartnerUnavailable();
2923 if (post_request_action) {
2924 post_request_action(error_message.empty(),
2930 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2931 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2932 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2937 HAService::processSyncCompleteNotify() {
2939 sync_complete_notified_ =
true;
2941 localEnableDHCPService();
2944 "Server successfully notified about the synchronization completion."));
2953 boost::dynamic_pointer_cast<HttpResponseJson>(response);
2954 if (!json_response) {
2965 if (body->getType() != Element::list) {
2967 if (body->getType() == Element::map) {
2983 if (body->empty()) {
2994 std::ostringstream s;
3002 if (args && args->getType() == Element::string) {
3003 s << args->stringValue() <<
" (";
3006 s <<
"error code " << rcode <<
")";
3011 isc_throw(CommandUnsupportedError, s.str());
3018 if (args && (args->getType() == Element::map)) {
3019 auto failed_leases = args->get(
"failed-leases");
3020 if (!failed_leases || (failed_leases->getType() != Element::list)) {
3024 auto conflict =
false;
3026 for (
auto i = 0; i < failed_leases->size(); ++i) {
3027 auto lease = failed_leases->get(i);
3028 if (!lease || lease->getType() != Element::map) {
3031 auto result = lease->get(
"result");
3032 if (!result || result->getType() != Element::integer) {
3035 auto error_message = lease->get(
"error-message");
3038 if (error_message && error_message->getType()) {
3039 s << error_message->stringValue() <<
" (";
3041 s <<
"error code " << result->intValue() <<
")";
3049 conflict_error_message = error_message;
3055 if (conflict_error_message &&
3056 (conflict_error_message->getType() == Element::string)) {
3057 s << conflict_error_message->stringValue() <<
" (";
3071 HAService::clientConnectHandler(
const boost::system::error_code& ec,
int tcp_native_fd) {
3075 if (client_->getThreadIOService()) {
3083 if ((!ec || (ec.value() == boost::asio::error::in_progress))
3084 && (tcp_native_fd >= 0)) {
3089 IfaceMgr::instance().addExternalSocket(tcp_native_fd,
3090 std::bind(&HAService::socketReadyHandler,
this, ph::_1)
3102 HAService::socketReadyHandler(
int tcp_native_fd) {
3107 client_->closeIfOutOfBand(tcp_native_fd);
3111 HAService::clientCloseHandler(
int tcp_native_fd) {
3112 if (tcp_native_fd >= 0) {
3113 IfaceMgr::instance().deleteExternalSocket(tcp_native_fd);
3118 HAService::pendingRequestSize() {
3119 if (MultiThreadingMgr::instance().getMode()) {
3120 std::lock_guard<std::mutex> lock(mutex_);
3121 return (pending_requests_.size());
3123 return (pending_requests_.size());
3127 template<
typename QueryPtrType>
3129 HAService::getPendingRequest(
const QueryPtrType& query) {
3130 if (MultiThreadingMgr::instance().getMode()) {
3131 std::lock_guard<std::mutex> lock(mutex_);
3132 return (getPendingRequestInternal(query));
3134 return (getPendingRequestInternal(query));
3138 template<
typename QueryPtrType>
3140 HAService::getPendingRequestInternal(
const QueryPtrType& query) {
3141 if (pending_requests_.count(query) == 0) {
3144 return (pending_requests_[query]);
3149 HAService::checkPermissionsClientAndListener() {
3157 client_->checkPermissions();
3161 listener_->checkPermissions();
3169 }
catch (
const std::exception& ex) {
3176 HAService::startClientAndListener() {
3178 MultiThreadingMgr::instance().addCriticalSectionCallbacks(
"HA_MT",
3179 std::bind(&HAService::checkPermissionsClientAndListener,
this),
3180 std::bind(&HAService::pauseClientAndListener,
this),
3181 std::bind(&HAService::resumeClientAndListener,
this));
3193 HAService::pauseClientAndListener() {
3204 }
catch (
const std::exception& ex) {
3211 HAService::resumeClientAndListener() {
3220 listener_->resume();
3222 }
catch (std::exception& ex) {
3229 HAService::stopClientAndListener() {
3231 MultiThreadingMgr::instance().removeCriticalSectionCallbacks(
"HA_MT");
3243 template int HAService::getPendingRequest(
const Pkt4Ptr&);
3244 template 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.
void terminatedStateHandler()
Handler for "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.
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.
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_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 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_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_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.