28#include <boost/pointer_cast.hpp>
29#include <boost/make_shared.hpp>
30#include <boost/weak_ptr.hpp>
42namespace ph = std::placeholders;
47class CommandUnsupportedError :
public CtrlChannelError {
49 CommandUnsupportedError(
const char* file,
size_t line,
const char* what) :
50 CtrlChannelError(file, line, what) {}
54class ConflictError :
public CtrlChannelError {
56 ConflictError(
const char* file,
size_t line,
const char* what) :
57 CtrlChannelError(file, line, what) {}
97 if (!
config_->getEnableMultiThreading()) {
103 config_->getHttpClientThreads(),
true));
106 if (
config_->getHttpDedicatedListener()) {
108 auto my_url =
config_->getThisServerConfig()->getUrl();
113 server_address =
IOAddress(my_url.getStrippedHostname());
114 }
catch (
const std::exception& ex) {
116 <<
" is not a valid IP address");
120 uint32_t listener_threads =
config_->getHttpListenerThreads();
123 auto tls_context =
config_->getThisServerConfig()->getTlsContext();
127 config_->getThisServerConfig()->getBasicAuthConfig();
130 std::unordered_set<std::string> command_accept_list;
131 if (
config_->getRestrictCommands()) {
145 command_accept_list));
150 .arg(
config_->getThisServerName())
163HAService::getCSCallbacksSetName()
const {
164 std::ostringstream s;
165 s <<
"HA_MT_" <<
id_;
202 std::bind(&HAService::backupStateHandler,
this),
206 std::bind(&HAService::communicationRecoveryHandler,
this),
210 std::bind(&HAService::normalStateHandler,
this),
214 std::bind(&HAService::normalStateHandler,
this),
218 std::bind(&HAService::inMaintenanceStateHandler,
this),
222 std::bind(&HAService::partnerDownStateHandler,
this),
226 std::bind(&HAService::partnerInMaintenanceStateHandler,
this),
230 std::bind(&HAService::passiveBackupStateHandler,
this),
234 std::bind(&HAService::readyStateHandler,
this),
238 std::bind(&HAService::syncingStateHandler,
this),
242 std::bind(&HAService::terminatedStateHandler,
this),
246 std::bind(&HAService::waitingStateHandler,
this),
251HAService::backupStateHandler() {
266HAService::communicationRecoveryHandler() {
383HAService::normalStateHandler() {
438 }
else if (
config_->amAllowingCommRecovery()) {
458HAService::inMaintenanceStateHandler() {
472 .arg(
config_->getThisServerName());
484HAService::partnerDownStateHandler() {
498 if (maintenance ||
config_->getThisServerConfig()->isAutoFailover()) {
513 .arg(
config_->getThisServerName());
576HAService::partnerInMaintenanceStateHandler() {
589 .arg(
config_->getThisServerName());
616HAService::passiveBackupStateHandler() {
634HAService::readyStateHandler() {
714HAService::syncingStateHandler() {
774 unsigned int dhcp_disable_timeout =
775 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
776 if (dhcp_disable_timeout == 0) {
777 ++dhcp_disable_timeout;
781 std::string status_message;
783 config_->getFailoverPeerConfig(),
784 dhcp_disable_timeout);
804HAService::terminatedStateHandler() {
820 .arg(
config_->getThisServerName());
827HAService::waitingStateHandler() {
899 if (!partner_in_terminated.is_not_a_date_time() &&
902 .arg(
config_->getThisServerName())
915 .arg(
config_->getThisServerName());
953 boost::to_upper(current_state_name);
954 boost::to_upper(new_state_name);
960 std::string partner_state_name =
getStateLabel(partner_state);
961 boost::to_upper(partner_state_name);
965 .arg(
config_->getThisServerName())
966 .arg(current_state_name)
968 .arg(partner_state_name);
973 .arg(
config_->getThisServerName())
974 .arg(current_state_name)
975 .arg(new_state_name);
984 .arg(
config_->getThisServerName());
997 .arg(
config_->getThisServerName())
998 .arg(new_state_name);
1000 }
else if (!
config_->amSendingLeaseUpdates()) {
1003 .arg(
config_->getThisServerName())
1004 .arg(new_state_name);
1011 .arg(
config_->getThisServerName())
1012 .arg(new_state_name);
1023 switch (
config_->getHAMode()) {
1037 .arg(
config_->getThisServerName());
1049 boost::to_upper(state_name);
1051 .arg(
config_->getThisServerName())
1068 return (inScopeInternal(query4));
1073 return (inScopeInternal(query6));
1076template<
typename QueryPtrType>
1078HAService::inScopeInternal(QueryPtrType& query) {
1080 std::string scope_class;
1098 return (shouldReclaimInternal(lease4));
1103 return (shouldReclaimInternal(lease6));
1106template<
typename LeasePtrType>
1108HAService::shouldReclaimInternal(
const LeasePtrType& lease)
const {
1115 boost::to_upper(current_state_name);
1128 boost::to_upper(current_state_name);
1130 .arg(
config_->getThisServerName())
1131 .arg(current_state_name);
1134 }
else if (should_enable && !
network_state_->isServiceEnabled()) {
1136 boost::to_upper(current_state_name);
1138 .arg(
config_->getThisServerName())
1139 .arg(current_state_name);
1177 if (!should_terminate) {
1184 return (should_terminate);
1198 .arg(
config_->getThisServerName());
1206 .arg(
config_->getThisServerName());
1214 .arg(
config_->getThisServerName());
1234 size_t sent_num = 0;
1237 for (
auto const& p : peers_configs) {
1245 for (
auto const& l : *deleted_leases) {
1256 for (
auto const& l : *leases) {
1278 for (
auto const& l : *deleted_leases) {
1291 for (
auto const& l : *leases) {
1312 leases->push_back(lease);
1327 size_t sent_num = 0;
1330 for (
auto const& p : peers_configs) {
1337 for (
auto const& l : *deleted_leases) {
1348 for (
auto const& l : *leases) {
1384template<
typename QueryPtrType>
1389 std::lock_guard<std::mutex> lock(mutex_);
1390 return (leaseUpdateCompleteInternal(query, parking_lot));
1392 return (leaseUpdateCompleteInternal(query, parking_lot));
1396template<
typename QueryPtrType>
1398HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
1400 auto it = pending_requests_.find(query);
1404 if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
1406 parking_lot->unpark(query);
1411 if (it != pending_requests_.end()) {
1412 pending_requests_.erase(it);
1419template<
typename QueryPtrType>
1423 std::lock_guard<std::mutex> lock(mutex_);
1424 updatePendingRequestInternal(query);
1426 updatePendingRequestInternal(query);
1430template<
typename QueryPtrType>
1432HAService::updatePendingRequestInternal(QueryPtrType& query) {
1433 if (pending_requests_.count(query) == 0) {
1434 pending_requests_[query] = 1;
1436 ++pending_requests_[query];
1440template<
typename QueryPtrType>
1450 config->addBasicAuthHttpHeader(request);
1451 request->setBodyAsJson(command);
1452 request->finalize();
1461 boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
1466 [
this, weak_query, parking_lot,
config]
1467 (
const boost::system::error_code& ec,
1469 const std::string& error_str) {
1473 QueryPtrType query_ptr = weak_query.lock();
1475 isc_throw(Unexpected,
"query is null while receiving response from"
1476 " HA peer. This is programmatic error");
1487 bool lease_update_success =
true;
1488 bool lease_update_conflict =
false;
1491 if (ec || !error_str.empty()) {
1492 LOG_WARN(ha_logger, HA_LEASE_UPDATE_COMMUNICATIONS_FAILED)
1493 .arg(config_->getThisServerName())
1494 .arg(query_ptr->getLabel())
1495 .arg(config->getLogLabel())
1496 .arg(ec ? ec.message() : error_str);
1500 lease_update_success = false;
1506 auto args = verifyAsyncResponse(http_response, rcode);
1509 logFailedLeaseUpdates(query_ptr, args);
1511 } catch (
const ConflictError& ex) {
1513 lease_update_conflict =
true;
1514 lease_update_success =
false;
1518 .arg(
config_->getThisServerName())
1519 .arg(query_ptr->getLabel())
1520 .arg(
config->getLogLabel())
1523 }
catch (
const std::exception& ex) {
1526 .arg(
config_->getThisServerName())
1527 .arg(query_ptr->getLabel())
1528 .arg(
config->getLogLabel())
1532 lease_update_success =
false;
1541 if (!lease_update_success) {
1544 if (!lease_update_conflict) {
1547 communication_state_->setPartnerUnavailable();
1552 communication_state_->reportSuccessfulLeaseUpdate(query_ptr);
1559 if (config_->amWaitingBackupAck() || (
config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1563 if (!lease_update_success) {
1565 parking_lot->drop(query_ptr);
1574 if (leaseUpdateComplete(query_ptr, parking_lot)) {
1580 runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
1584 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1585 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1586 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1593 if (config_->amWaitingBackupAck() || (
config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1595 updatePendingRequest(query);
1602 if (!
config_->amSendingLeaseUpdates()) {
1633 if (!
config_->amSendingLeaseUpdates()) {
1654 auto log_proc = [query, args](
const std::string& param_name,
const log::MessageID& mesid) {
1656 auto failed_leases = args->get(param_name);
1659 if (failed_leases && (failed_leases->getType() ==
Element::list)) {
1661 for (
unsigned i = 0; i < failed_leases->size(); ++i) {
1662 auto lease = failed_leases->get(i);
1666 auto ip_address = lease->get(
"ip-address");
1669 auto lease_type = lease->get(
"type");
1672 auto error_message = lease->get(
"error-message");
1675 .arg(query->getLabel())
1677 lease_type->stringValue() :
"(unknown)")
1679 ip_address->stringValue() :
"(unknown)")
1681 error_message->stringValue() :
"(unknown)");
1701 role =
config_->getThisServerConfig()->getRole();
1712 std::set<std::string> scopes =
query_filter_.getServedScopes();
1714 for (
auto const& scope : scopes) {
1717 local->set(
"scopes", list);
1720 if (my_time.is_not_a_date_time()) {
1725 ha_servers->set(
"local", local);
1731 return (ha_servers);
1738 role =
config_->getFailoverPeerConfig()->getRole();
1746 ha_servers->set(
"remote", remote);
1748 return (ha_servers);
1762 for (
auto const& scope : scopes) {
1765 arguments->set(
"scopes", scopes_list);
1767 arguments->set(
"unsent-update-count",
1802 partner_config->addBasicAuthHttpHeader(request);
1805 request->finalize();
1812 client_->asyncSendRequest(partner_config->getUrl(),
1813 partner_config->getTlsContext(),
1815 [
this, partner_config, sync_complete_notified]
1816 (
const boost::system::error_code& ec,
1818 const std::string& error_str) {
1826 bool heartbeat_success = true;
1829 if (ec || !error_str.empty()) {
1830 LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
1831 .arg(config_->getThisServerName())
1832 .arg(partner_config->getLogLabel())
1833 .arg(ec ? ec.message() : error_str);
1834 heartbeat_success = false;
1843 ConstElementPtr args = verifyAsyncResponse(http_response, rcode);
1844 if (!args || args->getType() != Element::map) {
1845 isc_throw(CtrlChannelError,
"returned arguments in the response"
1849 ConstElementPtr state = args->get(
"state");
1850 if (!state || state->getType() != Element::string) {
1851 isc_throw(CtrlChannelError,
"server state not returned in response"
1852 " to a ha-heartbeat command or it is not a string");
1856 communication_state_->setPartnerState(state->stringValue());
1858 ConstElementPtr date_time = args->get(
"date-time");
1859 if (!date_time || date_time->getType() != Element::string) {
1860 isc_throw(CtrlChannelError,
"date-time not returned in response"
1861 " to a ha-heartbeat command or it is not a string");
1864 communication_state_->setPartnerTime(date_time->stringValue());
1868 auto scopes = args->get(
"scopes");
1869 communication_state_->setPartnerScopes(scopes);
1884 auto unsent_update_count = args->get(
"unsent-update-count");
1885 if (unsent_update_count) {
1886 if (unsent_update_count->getType() != Element::integer) {
1887 isc_throw(CtrlChannelError,
"unsent-update-count returned in"
1888 " the ha-heartbeat response is not an integer");
1890 communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>
1891 (unsent_update_count->intValue()));
1894 } catch (
const std::exception& ex) {
1896 .arg(
config_->getThisServerName())
1897 .arg(partner_config->getLogLabel())
1899 heartbeat_success =
false;
1905 if (heartbeat_success) {
1906 communication_state_->poke();
1911 communication_state_->setPartnerUnavailable();
1913 if (communication_state_->isCommunicationInterrupted()) {
1914 LOG_WARN(ha_logger, HA_COMMUNICATION_INTERRUPTED)
1915 .arg(config_->getThisServerName())
1916 .arg(partner_config->getName());
1924 if (sync_complete_notified && !heartbeat_success) {
1925 postNextEvent(HA_SYNCED_PARTNER_UNAVAILABLE_EVT);
1932 runModel(HA_HEARTBEAT_COMPLETE_EVT);
1935 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1936 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1937 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1950 if (
config_->getHeartbeatDelay() > 0) {
1960 const unsigned int max_period,
1967 remote_config->addBasicAuthHttpHeader(request);
1971 request->finalize();
1979 remote_config->getTlsContext(),
1981 [
this, remote_config, post_request_action]
1982 (
const boost::system::error_code& ec,
1984 const std::string& error_str) {
1993 std::string error_message;
1996 if (ec || !error_str.empty()) {
1997 error_message = (ec ? ec.message() : error_str);
1998 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
1999 .arg(config_->getThisServerName())
2000 .arg(remote_config->getLogLabel())
2001 .arg(error_message);
2007 static_cast<void>(verifyAsyncResponse(http_response, rcode));
2009 } catch (
const std::exception& ex) {
2010 error_message = ex.what();
2012 .arg(
config_->getThisServerName())
2013 .arg(remote_config->getLogLabel())
2014 .arg(error_message);
2020 if (!error_message.empty()) {
2021 communication_state_->setPartnerUnavailable();
2025 if (post_request_action) {
2026 post_request_action(error_message.empty(),
2032 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2033 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2034 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2046 remote_config->addBasicAuthHttpHeader(request);
2049 request->finalize();
2057 remote_config->getTlsContext(),
2059 [
this, remote_config, post_request_action]
2060 (
const boost::system::error_code& ec,
2062 const std::string& error_str) {
2071 std::string error_message;
2074 if (ec || !error_str.empty()) {
2075 error_message = (ec ? ec.message() : error_str);
2076 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
2077 .arg(config_->getThisServerName())
2078 .arg(remote_config->getLogLabel())
2079 .arg(error_message);
2085 static_cast<void>(verifyAsyncResponse(http_response, rcode));
2087 } catch (
const std::exception& ex) {
2088 error_message = ex.what();
2090 .arg(
config_->getThisServerName())
2091 .arg(remote_config->getLogLabel())
2092 .arg(error_message);
2098 if (!error_message.empty()) {
2099 communication_state_->setPartnerUnavailable();
2103 if (post_request_action) {
2104 post_request_action(error_message.empty(),
2110 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2111 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2112 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2131 unsigned int dhcp_disable_timeout =
2132 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
2133 if (dhcp_disable_timeout == 0) {
2135 dhcp_disable_timeout = 1;
2140 dhcp_disable_timeout,
LeasePtr(), null_action);
2146 const unsigned int max_period,
2149 const bool dhcp_disabled) {
2156 [
this, &http_client, remote_config, max_period, last_lease,
2157 post_sync_action, dhcp_disabled]
2158 (
const bool success,
const std::string& error_message,
const int) {
2166 last_lease, post_sync_action,
true);
2169 post_sync_action(success, error_message, dhcp_disabled);
2177 const unsigned int max_period,
2180 const bool dhcp_disabled) {
2185 remote_config->addBasicAuthHttpHeader(request);
2188 boost::dynamic_pointer_cast<Lease4>(last_lease),
config_->getSyncPageLimit()));
2192 boost::dynamic_pointer_cast<Lease6>(last_lease),
config_->getSyncPageLimit()));
2194 request->finalize();
2202 remote_config->getTlsContext(),
2204 [
this, remote_config, post_sync_action, &http_client, max_period, dhcp_disabled]
2205 (
const boost::system::error_code& ec,
2207 const std::string& error_str) {
2211 LeasePtr last_lease_in_callback;
2219 std::string error_message;
2222 if (ec || !error_str.empty()) {
2223 error_message = (ec ? ec.message() : error_str);
2224 LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
2225 .arg(config_->getThisServerName())
2226 .arg(remote_config->getLogLabel())
2227 .arg(error_message);
2233 ConstElementPtr args = verifyAsyncResponse(http_response, rcode);
2236 if (args && (args->getType() != Element::map)) {
2237 isc_throw(CtrlChannelError,
2238 "arguments in the received response must be a map");
2241 ConstElementPtr leases = args->get(
"leases");
2242 if (!leases || (leases->getType() != Element::list)) {
2243 isc_throw(CtrlChannelError,
2244 "server response does not contain leases argument or this"
2245 " argument is not a list");
2249 auto const& leases_element = leases->listValue();
2251 LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
2252 .arg(config_->getThisServerName())
2253 .arg(leases_element.size())
2254 .arg(remote_config->getLogLabel());
2257 uint64_t applied_lease_count = 0;
2258 for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
2261 if (server_type_ == HAServerType::DHCPv4) {
2262 Lease4Ptr lease = Lease4::fromElement(*l);
2267 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2268 (l + 1 == leases_element.end())) {
2269 last_lease_in_callback = boost::dynamic_pointer_cast<Lease>(lease);
2272 if (!lease_sync_filter_.shouldSync(lease)) {
2277 Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
2278 if (!existing_lease) {
2280 LeaseMgrFactory::instance().addLease(lease);
2281 ++applied_lease_count;
2282 LeaseMgr::updateStatsOnAdd(lease);
2283 } else if (existing_lease->cltt_ < lease->cltt_) {
2289 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2290 LeaseMgrFactory::instance().updateLease4(lease);
2291 ++applied_lease_count;
2292 LeaseMgr::updateStatsOnUpdate(existing_lease, lease);
2294 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
2295 .arg(config_->getThisServerName())
2296 .arg(lease->addr_.toText())
2297 .arg(lease->subnet_id_);
2301 Lease6Ptr lease = Lease6::fromElement(*l);
2306 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2307 (l + 1 == leases_element.end())) {
2308 last_lease_in_callback = boost::dynamic_pointer_cast<Lease>(lease);
2311 if (!lease_sync_filter_.shouldSync(lease)) {
2316 Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
2318 if (!existing_lease) {
2320 LeaseMgrFactory::instance().addLease(lease);
2321 ++applied_lease_count;
2322 LeaseMgr::updateStatsOnAdd(lease);
2323 } else if (existing_lease->cltt_ < lease->cltt_) {
2329 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2330 LeaseMgrFactory::instance().updateLease6(lease);
2331 ++applied_lease_count;
2332 LeaseMgr::updateStatsOnUpdate(existing_lease, lease);
2334 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
2335 .arg(config_->getThisServerName())
2336 .arg(lease->addr_.toText())
2337 .arg(lease->subnet_id_);
2341 } catch (const std::exception& ex) {
2342 LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
2343 .arg(config_->getThisServerName())
2349 LOG_INFO(ha_logger, HA_LEASES_SYNC_APPLIED_LEASES)
2350 .arg(config_->getThisServerName())
2351 .arg(applied_lease_count);
2353 } catch (
const std::exception& ex) {
2354 error_message = ex.what();
2356 .arg(
config_->getThisServerName())
2357 .arg(remote_config->getLogLabel())
2358 .arg(error_message);
2364 if (!error_message.empty()) {
2365 communication_state_->setPartnerUnavailable();
2367 }
else if (last_lease_in_callback) {
2370 asyncSyncLeases(http_client, remote_config, max_period, last_lease_in_callback,
2371 post_sync_action, dhcp_disabled);
2376 if (post_sync_action) {
2377 post_sync_action(error_message.empty(),
2383 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2384 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2385 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2392 const unsigned int max_period) {
2395 remote_config =
config_->getPeerConfig(server_name);
2396 }
catch (
const std::exception& ex) {
2400 if (remote_config->getName() ==
config_->getThisServerName()) {
2402 +
"' points to local server but should point to a partner"));
2404 std::string answer_message;
2405 int sync_status =
synchronize(answer_message, remote_config, max_period);
2412 const unsigned int max_period) {
2419 [&](
const bool success,
const std::string& error_message,
2420 const bool dhcp_disabled) {
2425 status_message = error_message;
2431 if (dhcp_disabled) {
2437 [&](
const bool success_complete_notify,
2438 const std::string& error_message_complete_notify,
2445 [&](
const bool success_enable_dhcp,
2446 const std::string& error_message_enable_dhcp,
2451 if (!success_enable_dhcp && status_message.empty()) {
2452 status_message = error_message_enable_dhcp;
2464 if (!success_complete_notify && status_message.empty()) {
2465 status_message = error_message_complete_notify;
2478 [&](
const bool success_enable_dhcp,
2479 const std::string& error_message_enable_dhcp,
2481 if (!success_enable_dhcp && status_message.empty()) {
2482 status_message = error_message_enable_dhcp;
2501 .arg(
config_->getThisServerName())
2502 .arg(remote_config->getLogLabel());
2516 io_service->stopAndPoll();
2520 if (!status_message.empty()) {
2524 .arg(
config_->getThisServerName())
2525 .arg(remote_config->getLogLabel())
2526 .arg(status_message);
2533 status_message =
"Lease database synchronization complete.";
2537 .arg(
config_->getThisServerName())
2538 .arg(remote_config->getLogLabel())
2571 config->addBasicAuthHttpHeader(request);
2572 request->setBodyAsJson(command);
2573 request->finalize();
2581 [
this, &http_client,
config, post_request_action]
2582 (
const boost::system::error_code& ec,
2584 const std::string& error_str) {
2587 std::string error_message;
2589 if (ec || !error_str.empty()) {
2590 error_message = (ec ? ec.message() : error_str);
2591 LOG_WARN(ha_logger, HA_LEASES_BACKLOG_COMMUNICATIONS_FAILED)
2592 .arg(config_->getThisServerName())
2593 .arg(config->getLogLabel())
2594 .arg(ec ? ec.message() : error_str);
2599 auto args = verifyAsyncResponse(http_response, rcode);
2600 } catch (
const std::exception& ex) {
2601 error_message = ex.what();
2603 .arg(
config_->getThisServerName())
2604 .arg(
config->getLogLabel())
2614 if (error_message.empty()) {
2615 asyncSendLeaseUpdatesFromBacklog(http_client, config, post_request_action);
2617 post_request_action(error_message.empty(), error_message, rcode);
2625 if (num_updates == 0) {
2627 .arg(
config_->getThisServerName());
2633 auto remote_config =
config_->getFailoverPeerConfig();
2634 bool updates_successful =
true;
2637 .arg(
config_->getThisServerName())
2639 .arg(remote_config->getName());
2642 [&](
const bool success,
const std::string&,
const int) {
2644 updates_successful = success;
2658 io_service->stopAndPoll();
2660 if (updates_successful) {
2662 .arg(
config_->getThisServerName())
2663 .arg(remote_config->getName())
2664 .arg(stopwatch.logFormatLastDuration());
2667 return (updates_successful);
2681 config->addBasicAuthHttpHeader(request);
2682 request->setBodyAsJson(command);
2683 request->finalize();
2691 [
this,
config, post_request_action]
2692 (
const boost::system::error_code& ec,
2694 const std::string& error_str) {
2697 std::string error_message;
2699 if (ec || !error_str.empty()) {
2700 error_message = (ec ? ec.message() : error_str);
2701 LOG_WARN(ha_logger, HA_RESET_COMMUNICATIONS_FAILED)
2702 .arg(config_->getThisServerName())
2703 .arg(config->getLogLabel())
2704 .arg(ec ? ec.message() : error_str);
2709 auto args = verifyAsyncResponse(http_response, rcode);
2710 } catch (
const std::exception& ex) {
2711 error_message = ex.what();
2713 .arg(
config_->getThisServerName())
2714 .arg(
config->getLogLabel())
2719 post_request_action(error_message.empty(), error_message, rcode);
2727 auto remote_config =
config_->getFailoverPeerConfig();
2728 bool reset_successful =
true;
2731 [&](
const bool success,
const std::string&,
const int) {
2733 reset_successful = success;
2741 io_service->stopAndPoll();
2743 return (reset_successful);
2752 }
catch (
const std::exception& ex) {
2772 " maintenance for the server not in the"
2773 " in-maintenance state."));
2811 "Unable to transition the server from the "
2813 " in-maintenance state."));
2830 " partner-in-maintenance state."));
2842 remote_config->addBasicAuthHttpHeader(request);
2845 request->finalize();
2854 boost::system::error_code captured_ec;
2855 std::string captured_error_message;
2856 int captured_rcode = 0;
2860 remote_config->getTlsContext(),
2862 [
this, remote_config, &io_service, &captured_ec, &captured_error_message,
2864 (
const boost::system::error_code& ec,
2866 const std::string& error_str) {
2876 std::string error_message;
2879 if (ec || !error_str.empty()) {
2880 error_message = (ec ? ec.message() : error_str);
2881 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_COMMUNICATIONS_FAILED)
2882 .arg(config_->getThisServerName())
2883 .arg(remote_config->getLogLabel())
2884 .arg(error_message);
2890 static_cast<void>(verifyAsyncResponse(http_response, captured_rcode));
2892 } catch (
const std::exception& ex) {
2893 error_message = ex.what();
2895 .arg(
config_->getThisServerName())
2896 .arg(remote_config->getLogLabel())
2897 .arg(error_message);
2903 if (!error_message.empty()) {
2904 communication_state_->setPartnerUnavailable();
2908 captured_error_message = error_message;
2911 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2912 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2913 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2922 io_service->stopAndPoll();
2927 postNextEvent(HA_MAINTENANCE_START_EVT);
2928 verboseTransition(HA_PARTNER_DOWN_ST);
2931 "Server is now in the partner-down state as its"
2932 " partner appears to be offline for maintenance."));
2938 postNextEvent(HA_MAINTENANCE_START_EVT);
2939 verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST);
2946 " partner-in-maintenance state. The partner server responded"
2947 " with the following message to the ha-maintenance-notify"
2948 " command: " + captured_error_message +
"."));
2953 "Server is now in the partner-in-maintenance state"
2954 " and its partner is in-maintenance state. The partner"
2955 " can be now safely shut down."));
2962 " request because the server is not in the"
2963 " partner-in-maintenance state."));
2977 remote_config->addBasicAuthHttpHeader(request);
2982 request->finalize();
2991 std::string error_message;
2995 remote_config->getTlsContext(),
2997 [
this, remote_config, &io_service, &error_message]
2998 (
const boost::system::error_code& ec,
3000 const std::string& error_str) {
3005 if (ec || !error_str.empty()) {
3006 error_message = (ec ? ec.message() : error_str);
3007 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_CANCEL_COMMUNICATIONS_FAILED)
3008 .arg(config_->getThisServerName())
3009 .arg(remote_config->getLogLabel())
3010 .arg(error_message);
3017 ConstElementPtr args = verifyAsyncResponse(http_response, rcode);
3022 communication_state_->setPartnerUnavailable();
3026 if (args && args->getType() == Element::map) {
3028 ConstElementPtr state = args->get(
"state");
3030 if (state->getType() != Element::string) {
3031 isc_throw(CtrlChannelError,
"server state not returned in response"
3032 " to a ha-heartbeat command or it is not a string");
3034 communication_state_->setPartnerState(state->stringValue());
3037 } catch (
const std::exception& ex) {
3038 error_message = ex.what();
3040 .arg(
config_->getThisServerName())
3041 .arg(remote_config->getLogLabel())
3042 .arg(error_message);
3048 if (!error_message.empty()) {
3049 communication_state_->setPartnerUnavailable();
3053 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
3054 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
3055 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
3064 io_service->stopAndPoll();
3068 if (!error_message.empty()) {
3070 "Unable to cancel maintenance. The partner server responded"
3071 " with the following message to the ha-maintenance-notify"
3072 " command: " + error_message +
"."));
3078 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
3079 verboseTransition(next_state);
3083 "Server maintenance successfully canceled."));
3095 remote_config->addBasicAuthHttpHeader(request);
3099 request->finalize();
3107 remote_config->getTlsContext(),
3109 [
this, remote_config, post_request_action]
3110 (
const boost::system::error_code& ec,
3112 const std::string& error_str) {
3121 std::string error_message;
3124 if (ec || !error_str.empty()) {
3125 error_message = (ec ? ec.message() : error_str);
3126 LOG_ERROR(ha_logger, HA_SYNC_COMPLETE_NOTIFY_COMMUNICATIONS_FAILED)
3127 .arg(config_->getThisServerName())
3128 .arg(remote_config->getLogLabel())
3129 .arg(error_message);
3135 static_cast<void>(verifyAsyncResponse(http_response, rcode));
3137 } catch (
const CommandUnsupportedError& ex) {
3140 }
catch (
const std::exception& ex) {
3141 error_message = ex.what();
3143 .arg(
config_->getThisServerName())
3144 .arg(remote_config->getLogLabel())
3145 .arg(error_message);
3151 if (!error_message.empty()) {
3152 communication_state_->setPartnerUnavailable();
3156 if (post_request_action) {
3157 post_request_action(error_message.empty(),
3163 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
3164 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
3165 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
3187 "Server successfully notified about the synchronization completion."));
3196 boost::dynamic_pointer_cast<HttpResponseJson>(response);
3197 if (!json_response) {
3226 if (body->empty()) {
3237 std::ostringstream s;
3246 s << args->stringValue() <<
" (";
3249 s <<
"error code " << rcode <<
")";
3254 isc_throw(CommandUnsupportedError, s.str());
3262 auto failed_leases = args->get(
"failed-leases");
3263 if (!failed_leases || (failed_leases->getType() !=
Element::list)) {
3267 auto conflict =
false;
3269 for (
unsigned i = 0; i < failed_leases->size(); ++i) {
3270 auto lease = failed_leases->get(i);
3274 auto result = lease->get(
"result");
3278 auto error_message = lease->get(
"error-message");
3281 if (error_message && error_message->getType()) {
3282 s << error_message->stringValue() <<
" (";
3284 s <<
"error code " << result->intValue() <<
")";
3292 conflict_error_message = error_message;
3298 if (conflict_error_message &&
3300 s << conflict_error_message->stringValue() <<
" (";
3318 if (
client_->getThreadIOService()) {
3326 if ((!ec || (ec.value() == boost::asio::error::in_progress))
3327 && (tcp_native_fd >= 0)) {
3350 client_->closeIfOutOfBand(tcp_native_fd);
3355 if ((tcp_native_fd >= 0) &&
3364 std::lock_guard<std::mutex> lock(mutex_);
3365 return (pending_requests_.size());
3367 return (pending_requests_.size());
3371template<
typename QueryPtrType>
3375 std::lock_guard<std::mutex> lock(mutex_);
3376 return (getPendingRequestInternal(query));
3378 return (getPendingRequestInternal(query));
3382template<
typename QueryPtrType>
3384HAService::getPendingRequestInternal(
const QueryPtrType& query) {
3385 if (pending_requests_.count(query) == 0) {
3388 return (pending_requests_[query]);
3409 .arg(
config_->getThisServerName())
3414 }
catch (
const std::exception& ex) {
3416 .arg(
config_->getThisServerName())
3450 }
catch (
const std::exception& ex) {
3452 .arg(
config_->getThisServerName())
3469 }
catch (std::exception& ex) {
3471 .arg(
config_->getThisServerName())
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
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).
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
The IOService class is a wrapper for the ASIO io_context class.
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...
void deleteExternalSocket(int socketfd)
Deletes external socket.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
static data::ConstElementPtr createLease4Delete(const dhcp::Lease4 &lease4)
Creates lease4-del command.
static data::ConstElementPtr createHeartbeat(const std::string &server_name, const HAServerType &server_type)
Creates ha-heartbeat command for DHCP server.
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 createSyncCompleteNotify(const unsigned int origin_id, const std::string &server_name, const HAServerType &server_type)
Creates ha-sync-complete-notify command.
static data::ConstElementPtr createLease6BulkApply(const dhcp::Lease6CollectionPtr &leases, const dhcp::Lease6CollectionPtr &deleted_leases)
Creates lease6-bulk-apply command.
static data::ConstElementPtr createLease6GetPage(const dhcp::Lease6Ptr &lease6, const uint32_t limit)
Creates lease6-get-page command.
static data::ConstElementPtr createDHCPDisable(const unsigned int origin_id, const unsigned int max_period, const HAServerType &server_type)
Creates dhcp-disable command for DHCP server.
static data::ConstElementPtr createDHCPEnable(const unsigned int origin_id, const HAServerType &server_type)
Creates dhcp-enable command for DHCP server.
static data::ConstElementPtr createMaintenanceNotify(const std::string &server_name, const bool cancel, const int state, const HAServerType &server_type)
Creates ha-maintenance-notify command.
static std::unordered_set< std::string > ha_commands6_
List of commands used by the High Availability in v6.
static data::ConstElementPtr createHAReset(const std::string &server_name, const HAServerType &server_type)
Creates ha-reset command.
static data::ConstElementPtr createLease4GetPage(const dhcp::Lease4Ptr &lease4, const uint32_t limit)
Creates lease4-get-page command.
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.
void asyncSendHAReset(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Sends ha-reset command to partner asynchronously.
bool clientConnectHandler(const boost::system::error_code &ec, int tcp_native_fd)
HttpClient connect callback handler.
void asyncSyncLeases()
Asynchronously reads leases from a peer and updates local lease database.
bool isMaintenanceCanceled() const
Convenience method checking if the current state is a result of canceling the maintenance.
data::ConstElementPtr processMaintenanceCancel()
Processes ha-maintenance-cancel command and returns a response.
void checkPermissionsClientAndListener()
Check client and(or) listener current thread permissions to perform thread pool state transition.
bool shouldReclaim(const dhcp::Lease4Ptr &lease4) const
Checks if the lease should be reclaimed by this server.
void asyncSendLeaseUpdate(const QueryPtrType &query, const HAConfig::PeerConfigPtr &config, const data::ConstElementPtr &command, const hooks::ParkingLotHandlePtr &parking_lot)
Asynchronously sends lease update to the peer.
void verboseTransition(const unsigned state)
Transitions to a desired state and logs it.
bool sendLeaseUpdatesFromBacklog()
Attempts to send all lease updates from the backlog synchronously.
config::CmdHttpListenerPtr listener_
HTTP listener instance used to receive and respond to HA commands and lease updates.
void clientCloseHandler(int tcp_native_fd)
HttpClient close callback handler.
bool leaseUpdateComplete(QueryPtrType &query, const hooks::ParkingLotHandlePtr &parking_lot)
Handle last pending request for this query.
HAConfigPtr config_
Pointer to the HA hooks library configuration.
data::ConstElementPtr processMaintenanceStart()
Processes ha-maintenance-start command and returns a response.
unsigned int id_
Unique service id.
HAServerType server_type_
DHCP server type.
bool sync_complete_notified_
An indicator that a partner sent ha-sync-complete-notify command.
bool shouldTerminate() const
Indicates if the server should transition to the terminated state.
data::ConstElementPtr processScopes(const std::vector< std::string > &scopes)
Processes ha-scopes command and returns a response.
dhcp::NetworkStatePtr network_state_
Pointer to the state of the DHCP service (enabled/disabled).
data::ConstElementPtr processSynchronize(const std::string &server_name, const unsigned int max_period)
Processes ha-sync command and returns a response.
void scheduleHeartbeat()
Schedules asynchronous heartbeat to a peer if it is not scheduled.
void asyncSyncCompleteNotify(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Schedules asynchronous "ha-sync-complete-notify" command to the specified server.
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.
data::ConstElementPtr processMaintenanceNotify(const bool cancel, const std::string &state)
Processes ha-maintenance-notify command and returns a response.
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.
size_t pendingRequestSize()
Get the number of entries in the pending request map.
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.
asiolink::IOServicePtr io_service_
Pointer to the IO service object shared between this hooks library and the DHCP server.
void localDisableDHCPService()
Disables local DHCP service.
CommunicationStatePtr communication_state_
Holds communication state with a peer.
void logFailedLeaseUpdates(const dhcp::PktPtr &query, const data::ConstElementPtr &args) const
Log failed lease updates.
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 asyncSendLeaseUpdatesFromBacklog(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Sends lease updates from backlog to partner asynchronously.
data::ConstElementPtr processHeartbeat()
Processes ha-heartbeat command and returns a response.
void asyncSyncLeasesInternal(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period, const dhcp::LeasePtr &last_lease, PostSyncCallback post_sync_action, const bool dhcp_disabled)
Implements fetching one page of leases during synchronization.
data::ConstElementPtr processHAReset()
Processes ha-reset command and returns a response.
size_t asyncSendSingleLeaseUpdate(const dhcp::Pkt4Ptr &query, const dhcp::Lease4Ptr &lease, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules an asynchronous IPv4 lease update.
void asyncSendHeartbeat()
Starts asynchronous heartbeat to a peer.
bool isPartnerStateInvalid() const
Indicates if the partner's state is invalid.
void startClientAndListener()
Start the client and(or) listener instances.
data::ConstElementPtr verifyAsyncResponse(const http::HttpResponsePtr &response, int &rcode)
Checks if the response is valid or contains an error.
void resumeClientAndListener()
Resumes client and(or) listener thread pool operations.
data::ConstElementPtr processStatusGet() const
Processes status-get command and returns a response.
int getPendingRequest(const QueryPtrType &query)
Get the number of scheduled requests for a given query.
LeaseSyncFilter lease_sync_filter_
Lease synchronization filter used in hub-and-spoke model.
int synchronize(std::string &status_message, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period)
Synchronizes lease database with a partner.
bool shouldSendLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be sent as result of leases allocation or release.
void serveFailoverScopes()
Instructs the HA service to serve failover scopes.
void localEnableDHCPService()
Enables local DHCP service.
static const int HA_LEASE_UPDATES_COMPLETE_EVT
Finished lease updates commands.
HAService(const unsigned int id, const asiolink::IOServicePtr &io_service, const dhcp::NetworkStatePtr &network_state, const HAConfigPtr &config, const HAServerType &server_type=HAServerType::DHCPv4)
Constructor.
void socketReadyHandler(int tcp_native_fd)
IfaceMgr external socket ready callback handler.
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.
void startHeartbeat()
Unconditionally starts one heartbeat to a peer.
data::ConstElementPtr processSyncCompleteNotify(const unsigned int origin_id)
Process ha-sync-complete-notify command and returns a response.
data::ConstElementPtr processContinue()
Processes ha-continue command and returns a response.
void asyncDisableDHCPService(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period, PostRequestCallback post_request_action)
Schedules asynchronous "dhcp-disable" command to the specified server.
void pauseClientAndListener()
Pauses client and(or) listener thread pool operations.
std::function< void(const bool, const std::string &, const bool)> PostSyncCallback
Callback invoked when lease database synchronization is complete.
static const int HA_WAITING_TO_TERMINATED_ST_DELAY_MINUTES
A delay in minutes to transition from the waiting to terminated state when the partner remains in ter...
void asyncEnableDHCPService(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Schedules asynchronous "dhcp-enable" command to the specified server.
OpType
Type of the lease update (operation type).
bool inScope(const dhcp::Pkt4Ptr &query4, std::string &scope_class) const
Checks if this server should process the DHCPv4 query.
void stop()
Halts client-side IO activity.
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.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
void removeCriticalSectionCallbacks(const std::string &name)
Removes the set of callbacks associated with a given name from the list of CriticalSection callbacks.
void addCriticalSectionCallbacks(const std::string &name, const CSCallbackSet::Callback &check_cb, const CSCallbackSet::Callback &entry_cb, const CSCallbackSet::Callback &exit_cb)
Adds a set of callbacks to the list of CriticalSection callbacks.
std::string getStateLabel(const int state) const
Fetches the label associated with an state value.
void unpauseModel()
Unpauses state model.
int getLastEvent() const
Fetches the model's last event.
bool isModelPaused() const
Returns whether or not the model is paused.
virtual void defineEvents()
Populates the set of events.
bool doOnExit()
Checks if on exit flag is true.
void defineEvent(int value, const std::string &label)
Adds an event value and associated label to the set of events.
virtual void verifyEvents()
Validates the contents of the set of events.
bool doOnEntry()
Checks if on entry flag is true.
static const int NOP_EVT
Signifies that no event has occurred.
int getCurrState() const
Fetches the model's current state.
void defineState(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.
void startModel(const int start_state)
Begins execution of the model.
const EventPtr & getEvent(int value)
Fetches the event referred to by value.
virtual void defineStates()
Populates the set of states.
virtual void runModel(int event)
Processes events through the state model.
void transition(int state, int event)
Sets up the model to transition into given state with a given event.
int getNextEvent() const
Fetches the model's next event.
int getPrevState() const
Fetches the model's previous state.
const StatePtr getState(int value)
Fetches the state referred to by value.
void postNextEvent(int event)
Sets the next event to the given event value.
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").
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
Parses a standard config/command level answer and returns arguments or text status code.
constexpr long TIMEOUT_DEFAULT_HTTP_CLIENT_REQUEST
Timeout for the HTTP clients awaiting a response to a request.
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_CONFLICT
Status code indicating that the command was unsuccessful due to a conflict between the command argume...
const int CONTROL_RESULT_COMMAND_UNSUPPORTED
Status code indicating that the specified command is not supported.
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< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
boost::shared_ptr< NetworkState > NetworkStatePtr
Pointer to the NetworkState object.
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID HA_INVALID_PARTNER_STATE_LOAD_BALANCING
const isc::log::MessageID HA_RESUME_CLIENT_LISTENER_FAILED
const isc::log::MessageID HA_LOCAL_DHCP_ENABLE
const isc::log::MessageID HA_LEASES_BACKLOG_NOTHING_TO_SEND
const isc::log::MessageID HA_LEASES_BACKLOG_FAILED
const isc::log::MessageID HA_SYNC_FAILED
const isc::log::MessageID HA_TERMINATED_RESTART_PARTNER
const int HA_PASSIVE_BACKUP_ST
In passive-backup state with a single active server and backup servers.
const int HA_HOT_STANDBY_ST
Hot standby state.
const isc::log::MessageID HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY
const isc::log::MessageID HA_LEASES_BACKLOG_SUCCESS
const int HA_COMMUNICATION_RECOVERY_ST
Communication recovery state.
const isc::log::MessageID HA_STATE_MACHINE_CONTINUED
isc::log::Logger ha_logger("ha-hooks")
const isc::log::MessageID HA_LEASES_SYNC_FAILED
const isc::log::MessageID HA_SYNC_SUCCESSFUL
const int HA_UNAVAILABLE_ST
Special state indicating that this server is unable to communicate with the partner.
const isc::log::MessageID HA_CONFIG_LEASE_UPDATES_DISABLED_REMINDER
const isc::log::MessageID HA_SERVICE_STARTED
const int HA_TERMINATED_ST
HA service terminated state.
const int HA_IN_MAINTENANCE_ST
In maintenance state.
const int HA_LOAD_BALANCING_ST
Load balancing state.
const isc::log::MessageID HA_DHCP_ENABLE_FAILED
const isc::log::MessageID HA_LEASE_UPDATE_DELETE_FAILED_ON_PEER
const isc::log::MessageID HA_LEASES_BACKLOG_START
const isc::log::MessageID HA_SYNC_START
const isc::log::MessageID HA_HEARTBEAT_FAILED
const int HA_PARTNER_DOWN_ST
Partner down state.
const isc::log::MessageID HA_LEASE_UPDATES_ENABLED
const isc::log::MessageID HA_INVALID_PARTNER_STATE_HOT_STANDBY
const isc::log::MessageID HA_STATE_MACHINE_PAUSED
const isc::log::MessageID HA_TERMINATED
const isc::log::MessageID HA_DHCP_DISABLE_FAILED
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
const isc::log::MessageID HA_MAINTENANCE_STARTED_IN_PARTNER_DOWN
const int HA_PARTNER_IN_MAINTENANCE_ST
Partner in-maintenance state.
const isc::log::MessageID HA_MAINTENANCE_NOTIFY_FAILED
const int HA_WAITING_ST
Server waiting state, i.e. waiting for another server to be ready.
HAServerType
Lists possible server types for which HA service is created.
const int HA_BACKUP_ST
Backup state.
const isc::log::MessageID HA_PAUSE_CLIENT_LISTENER_ILLEGAL
const isc::log::MessageID HA_PAUSE_CLIENT_LISTENER_FAILED
const isc::log::MessageID HA_MAINTENANCE_SHUTDOWN_SAFE
const isc::log::MessageID HA_MAINTENANCE_NOTIFY_CANCEL_FAILED
const isc::log::MessageID HA_LEASE_UPDATE_CONFLICT
const isc::log::MessageID HA_LEASE_UPDATES_DISABLED
const isc::log::MessageID HA_LOCAL_DHCP_DISABLE
const int HA_SYNCING_ST
Synchronizing database state.
const isc::log::MessageID HA_RESET_FAILED
const isc::log::MessageID HA_STATE_TRANSITION
const isc::log::MessageID HA_CONFIG_LEASE_SYNCING_DISABLED_REMINDER
std::string stateToString(int state)
Returns state name.
const int HA_READY_ST
Server ready state, i.e. synchronized database, can enable DHCP service.
const isc::log::MessageID HA_TERMINATED_PARTNER_DID_NOT_RESTART
const isc::log::MessageID HA_SYNC_COMPLETE_NOTIFY_FAILED
const isc::log::MessageID HA_MAINTENANCE_STARTED
const isc::log::MessageID HA_LEASE_UPDATE_CREATE_UPDATE_FAILED_ON_PEER
const isc::log::MessageID HA_LEASE_UPDATE_FAILED
const isc::log::MessageID HA_STATE_TRANSITION_PASSIVE_BACKUP
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
boost::shared_ptr< PostHttpRequestJson > PostHttpRequestJsonPtr
Pointer to PostHttpRequestJson.
boost::shared_ptr< HttpAuthConfig > HttpAuthConfigPtr
Type of shared pointers to HTTP authentication configuration.
boost::shared_ptr< HttpResponseJson > HttpResponseJsonPtr
Pointer to the HttpResponseJson object.
boost::shared_ptr< HttpResponse > HttpResponsePtr
Pointer to the HttpResponse object.
std::string ptimeToText(boost::posix_time::ptime t, size_t fsecs_precision=MAX_FSECS_PRECISION)
Converts ptime structure to text.
Defines the logger used by the top-level component of kea-lfc.
static constexpr uint32_t STATE_RELEASED
Released lease held in the database for lease affinity.
HTTP request/response timeout value.
static const HttpVersion & HTTP_11()
HTTP version 1.1.