31#include <boost/make_shared.hpp>
32#include <boost/pointer_cast.hpp>
33#include <boost/weak_ptr.hpp>
45namespace ph = std::placeholders;
50class CommandUnsupportedError :
public CtrlChannelError {
52 CommandUnsupportedError(
const char* file,
size_t line,
const char* what) :
53 CtrlChannelError(file, line, what) {}
57class ConflictError :
public CtrlChannelError {
59 ConflictError(
const char* file,
size_t line,
const char* what) :
60 CtrlChannelError(file, line, what) {}
100 if (!
config_->getEnableMultiThreading()) {
106 config_->getHttpClientThreads(),
true));
109 if (
config_->getHttpDedicatedListener()) {
111 auto my_url =
config_->getThisServerConfig()->getUrl();
116 server_address =
IOAddress(my_url.getStrippedHostname());
117 }
catch (
const std::exception& ex) {
119 <<
" is not a valid IP address");
123 uint32_t listener_threads =
config_->getHttpListenerThreads();
126 auto tls_context =
config_->getThisServerConfig()->getTlsContext();
130 config_->getThisServerConfig()->getBasicAuthConfig();
133 std::unordered_set<std::string> command_accept_list;
134 if (
config_->getRestrictCommands()) {
148 command_accept_list));
153 .arg(
config_->getThisServerName())
166HAService::getCSCallbacksSetName()
const {
167 std::ostringstream s;
168 s <<
"HA_MT_" <<
id_;
205 std::bind(&HAService::backupStateHandler,
this),
209 std::bind(&HAService::communicationRecoveryHandler,
this),
213 std::bind(&HAService::normalStateHandler,
this),
217 std::bind(&HAService::normalStateHandler,
this),
221 std::bind(&HAService::inMaintenanceStateHandler,
this),
225 std::bind(&HAService::partnerDownStateHandler,
this),
229 std::bind(&HAService::partnerInMaintenanceStateHandler,
this),
233 std::bind(&HAService::passiveBackupStateHandler,
this),
237 std::bind(&HAService::readyStateHandler,
this),
241 std::bind(&HAService::syncingStateHandler,
this),
245 std::bind(&HAService::terminatedStateHandler,
this),
249 std::bind(&HAService::waitingStateHandler,
this),
254HAService::backupStateHandler() {
269HAService::communicationRecoveryHandler() {
386HAService::normalStateHandler() {
441 }
else if (
config_->amAllowingCommRecovery()) {
461HAService::inMaintenanceStateHandler() {
475 .arg(
config_->getThisServerName());
487HAService::partnerDownStateHandler() {
501 if (maintenance ||
config_->getThisServerConfig()->isAutoFailover()) {
516 .arg(
config_->getThisServerName());
579HAService::partnerInMaintenanceStateHandler() {
592 .arg(
config_->getThisServerName());
619HAService::passiveBackupStateHandler() {
637HAService::readyStateHandler() {
717HAService::syncingStateHandler() {
777 unsigned int dhcp_disable_timeout =
778 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
779 if (dhcp_disable_timeout == 0) {
780 ++dhcp_disable_timeout;
784 std::string status_message;
786 config_->getFailoverPeerConfig(),
787 dhcp_disable_timeout);
807HAService::terminatedStateHandler() {
823 .arg(
config_->getThisServerName());
830HAService::waitingStateHandler() {
902 if (!partner_in_terminated.is_not_a_date_time() &&
905 .arg(
config_->getThisServerName())
918 .arg(
config_->getThisServerName());
956 boost::to_upper(current_state_name);
957 boost::to_upper(new_state_name);
963 std::string partner_state_name =
getStateLabel(partner_state);
964 boost::to_upper(partner_state_name);
968 .arg(
config_->getThisServerName())
969 .arg(current_state_name)
971 .arg(partner_state_name);
976 .arg(
config_->getThisServerName())
977 .arg(current_state_name)
978 .arg(new_state_name);
987 .arg(
config_->getThisServerName());
1000 .arg(
config_->getThisServerName())
1001 .arg(new_state_name);
1003 }
else if (!
config_->amSendingLeaseUpdates()) {
1006 .arg(
config_->getThisServerName())
1007 .arg(new_state_name);
1014 .arg(
config_->getThisServerName())
1015 .arg(new_state_name);
1026 switch (
config_->getHAMode()) {
1040 .arg(
config_->getThisServerName());
1052 boost::to_upper(state_name);
1054 .arg(
config_->getThisServerName())
1071 return (inScopeInternal(query4));
1076 return (inScopeInternal(query6));
1079template<
typename QueryPtrType>
1081HAService::inScopeInternal(QueryPtrType& query) {
1083 std::string scope_class;
1101 return (shouldReclaimInternal(lease4));
1106 return (shouldReclaimInternal(lease6));
1109template<
typename LeasePtrType>
1111HAService::shouldReclaimInternal(
const LeasePtrType& lease)
const {
1118 boost::to_upper(current_state_name);
1131 boost::to_upper(current_state_name);
1133 .arg(
config_->getThisServerName())
1134 .arg(current_state_name);
1137 }
else if (should_enable && !
network_state_->isServiceEnabled()) {
1139 boost::to_upper(current_state_name);
1141 .arg(
config_->getThisServerName())
1142 .arg(current_state_name);
1180 if (!should_terminate) {
1187 return (should_terminate);
1201 .arg(
config_->getThisServerName());
1209 .arg(
config_->getThisServerName());
1217 .arg(
config_->getThisServerName());
1237 size_t sent_num = 0;
1240 for (
auto const& p : peers_configs) {
1248 for (
auto const& l : *deleted_leases) {
1259 for (
auto const& l : *leases) {
1281 for (
auto const& l : *deleted_leases) {
1294 for (
auto const& l : *leases) {
1315 leases->push_back(lease);
1330 size_t sent_num = 0;
1333 for (
auto const& p : peers_configs) {
1340 for (
auto const& l : *deleted_leases) {
1351 for (
auto const& l : *leases) {
1387template<
typename QueryPtrType>
1392 std::lock_guard<std::mutex> lock(mutex_);
1393 return (leaseUpdateCompleteInternal(query, parking_lot));
1395 return (leaseUpdateCompleteInternal(query, parking_lot));
1399template<
typename QueryPtrType>
1401HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
1403 auto it = pending_requests_.find(query);
1407 if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
1409 parking_lot->unpark(query);
1414 if (it != pending_requests_.end()) {
1415 pending_requests_.erase(it);
1422template<
typename QueryPtrType>
1426 std::lock_guard<std::mutex> lock(mutex_);
1427 updatePendingRequestInternal(query);
1429 updatePendingRequestInternal(query);
1433template<
typename QueryPtrType>
1435HAService::updatePendingRequestInternal(QueryPtrType& query) {
1436 if (pending_requests_.count(query) == 0) {
1437 pending_requests_[query] = 1;
1439 ++pending_requests_[query];
1443template<
typename QueryPtrType>
1453 config->addBasicAuthHttpHeader(request);
1454 request->setBodyAsJson(command);
1455 request->finalize();
1464 boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
1469 [
this, weak_query, parking_lot,
config]
1470 (
const boost::system::error_code& ec,
1472 const std::string& error_str) {
1476 QueryPtrType query_ptr = weak_query.lock();
1478 isc_throw(Unexpected,
"query is null while receiving response from"
1479 " HA peer. This is programmatic error");
1490 bool lease_update_success =
true;
1491 bool lease_update_conflict =
false;
1494 if (ec || !error_str.empty()) {
1495 LOG_WARN(ha_logger, HA_LEASE_UPDATE_COMMUNICATIONS_FAILED)
1496 .arg(config_->getThisServerName())
1497 .arg(query_ptr->getLabel())
1498 .arg(config->getLogLabel())
1499 .arg(ec ? ec.message() : error_str);
1503 lease_update_success = false;
1509 auto args = verifyAsyncResponse(http_response, rcode);
1512 logFailedLeaseUpdates(query_ptr, args);
1514 } catch (
const ConflictError& ex) {
1516 lease_update_conflict =
true;
1517 lease_update_success =
false;
1521 .arg(
config_->getThisServerName())
1522 .arg(query_ptr->getLabel())
1523 .arg(
config->getLogLabel())
1526 }
catch (
const std::exception& ex) {
1529 .arg(
config_->getThisServerName())
1530 .arg(query_ptr->getLabel())
1531 .arg(
config->getLogLabel())
1535 lease_update_success =
false;
1544 if (!lease_update_success) {
1547 if (!lease_update_conflict) {
1550 communication_state_->setPartnerUnavailable();
1555 communication_state_->reportSuccessfulLeaseUpdate(query_ptr);
1562 if (config_->amWaitingBackupAck() || (
config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1566 if (!lease_update_success) {
1568 parking_lot->drop(query_ptr);
1577 if (leaseUpdateComplete(query_ptr, parking_lot)) {
1583 runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
1587 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1588 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1589 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1596 if (config_->amWaitingBackupAck() || (
config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1598 updatePendingRequest(query);
1605 if (!
config_->amSendingLeaseUpdates()) {
1636 if (!
config_->amSendingLeaseUpdates()) {
1657 auto log_proc = [query, args](
const std::string& param_name,
const log::MessageID& mesid) {
1659 auto failed_leases = args->get(param_name);
1662 if (failed_leases && (failed_leases->getType() ==
Element::list)) {
1664 for (
unsigned i = 0; i < failed_leases->size(); ++i) {
1665 auto lease = failed_leases->get(i);
1669 auto ip_address = lease->get(
"ip-address");
1672 auto lease_type = lease->get(
"type");
1675 auto error_message = lease->get(
"error-message");
1678 .arg(query->getLabel())
1680 lease_type->stringValue() :
"(unknown)")
1682 ip_address->stringValue() :
"(unknown)")
1684 error_message->stringValue() :
"(unknown)");
1704 role =
config_->getThisServerConfig()->getRole();
1715 std::set<std::string> scopes =
query_filter_.getServedScopes();
1717 for (
auto const& scope : scopes) {
1720 local->set(
"scopes", list);
1723 if (my_time.is_not_a_date_time()) {
1728 ha_servers->set(
"local", local);
1734 return (ha_servers);
1741 role =
config_->getFailoverPeerConfig()->getRole();
1749 ha_servers->set(
"remote", remote);
1751 return (ha_servers);
1765 for (
auto const& scope : scopes) {
1768 arguments->set(
"scopes", scopes_list);
1770 arguments->set(
"unsent-update-count",
1805 partner_config->addBasicAuthHttpHeader(request);
1808 request->finalize();
1815 client_->asyncSendRequest(partner_config->getUrl(),
1816 partner_config->getTlsContext(),
1818 [
this, partner_config, sync_complete_notified]
1819 (
const boost::system::error_code& ec,
1821 const std::string& error_str) {
1829 bool heartbeat_success = true;
1832 if (ec || !error_str.empty()) {
1833 LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
1834 .arg(config_->getThisServerName())
1835 .arg(partner_config->getLogLabel())
1836 .arg(ec ? ec.message() : error_str);
1837 heartbeat_success = false;
1846 ConstElementPtr args = verifyAsyncResponse(http_response, rcode);
1847 if (!args || args->getType() != Element::map) {
1848 isc_throw(CtrlChannelError,
"returned arguments in the response"
1852 ConstElementPtr state = args->get(
"state");
1853 if (!state || state->getType() != Element::string) {
1854 isc_throw(CtrlChannelError,
"server state not returned in response"
1855 " to a ha-heartbeat command or it is not a string");
1859 communication_state_->setPartnerState(state->stringValue());
1861 ConstElementPtr date_time = args->get(
"date-time");
1862 if (!date_time || date_time->getType() != Element::string) {
1863 isc_throw(CtrlChannelError,
"date-time not returned in response"
1864 " to a ha-heartbeat command or it is not a string");
1867 communication_state_->setPartnerTime(date_time->stringValue());
1871 auto scopes = args->get(
"scopes");
1872 communication_state_->setPartnerScopes(scopes);
1887 auto unsent_update_count = args->get(
"unsent-update-count");
1888 if (unsent_update_count) {
1889 if (unsent_update_count->getType() != Element::integer) {
1890 isc_throw(CtrlChannelError,
"unsent-update-count returned in"
1891 " the ha-heartbeat response is not an integer");
1893 communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>
1894 (unsent_update_count->intValue()));
1897 } catch (
const std::exception& ex) {
1899 .arg(
config_->getThisServerName())
1900 .arg(partner_config->getLogLabel())
1902 heartbeat_success =
false;
1908 if (heartbeat_success) {
1909 communication_state_->poke();
1914 communication_state_->setPartnerUnavailable();
1916 if (communication_state_->isCommunicationInterrupted()) {
1917 LOG_WARN(ha_logger, HA_COMMUNICATION_INTERRUPTED)
1918 .arg(config_->getThisServerName())
1919 .arg(partner_config->getName());
1927 if (sync_complete_notified && !heartbeat_success) {
1928 postNextEvent(HA_SYNCED_PARTNER_UNAVAILABLE_EVT);
1935 runModel(HA_HEARTBEAT_COMPLETE_EVT);
1938 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1939 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1940 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1953 if (
config_->getHeartbeatDelay() > 0) {
1963 const unsigned int max_period,
1970 remote_config->addBasicAuthHttpHeader(request);
1974 request->finalize();
1982 remote_config->getTlsContext(),
1984 [
this, remote_config, post_request_action]
1985 (
const boost::system::error_code& ec,
1987 const std::string& error_str) {
1996 std::string error_message;
1999 if (ec || !error_str.empty()) {
2000 error_message = (ec ? ec.message() : error_str);
2001 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
2002 .arg(config_->getThisServerName())
2003 .arg(remote_config->getLogLabel())
2004 .arg(error_message);
2010 static_cast<void>(verifyAsyncResponse(http_response, rcode));
2012 } catch (
const std::exception& ex) {
2013 error_message = ex.what();
2015 .arg(
config_->getThisServerName())
2016 .arg(remote_config->getLogLabel())
2017 .arg(error_message);
2023 if (!error_message.empty()) {
2024 communication_state_->setPartnerUnavailable();
2028 if (post_request_action) {
2029 post_request_action(error_message.empty(),
2035 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2036 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2037 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2049 remote_config->addBasicAuthHttpHeader(request);
2052 request->finalize();
2060 remote_config->getTlsContext(),
2062 [
this, remote_config, post_request_action]
2063 (
const boost::system::error_code& ec,
2065 const std::string& error_str) {
2074 std::string error_message;
2077 if (ec || !error_str.empty()) {
2078 error_message = (ec ? ec.message() : error_str);
2079 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
2080 .arg(config_->getThisServerName())
2081 .arg(remote_config->getLogLabel())
2082 .arg(error_message);
2088 static_cast<void>(verifyAsyncResponse(http_response, rcode));
2090 } catch (
const std::exception& ex) {
2091 error_message = ex.what();
2093 .arg(
config_->getThisServerName())
2094 .arg(remote_config->getLogLabel())
2095 .arg(error_message);
2101 if (!error_message.empty()) {
2102 communication_state_->setPartnerUnavailable();
2106 if (post_request_action) {
2107 post_request_action(error_message.empty(),
2113 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2114 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2115 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2134 unsigned int dhcp_disable_timeout =
2135 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
2136 if (dhcp_disable_timeout == 0) {
2138 dhcp_disable_timeout = 1;
2143 dhcp_disable_timeout,
LeasePtr(), null_action);
2149 const unsigned int max_period,
2152 const bool dhcp_disabled) {
2159 [
this, &http_client, remote_config, max_period, last_lease,
2160 post_sync_action, dhcp_disabled]
2161 (
const bool success,
const std::string& error_message,
const int) {
2169 last_lease, post_sync_action,
true);
2172 post_sync_action(success, error_message, dhcp_disabled);
2180 const unsigned int max_period,
2183 const bool dhcp_disabled) {
2188 remote_config->addBasicAuthHttpHeader(request);
2191 boost::dynamic_pointer_cast<Lease4>(last_lease),
config_->getSyncPageLimit()));
2195 boost::dynamic_pointer_cast<Lease6>(last_lease),
config_->getSyncPageLimit()));
2197 request->finalize();
2205 remote_config->getTlsContext(),
2207 [
this, remote_config, post_sync_action, &http_client, max_period, dhcp_disabled]
2208 (
const boost::system::error_code& ec,
2210 const std::string& error_str) {
2214 LeasePtr last_lease_in_callback;
2222 std::string error_message;
2225 if (ec || !error_str.empty()) {
2226 error_message = (ec ? ec.message() : error_str);
2227 LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
2228 .arg(config_->getThisServerName())
2229 .arg(remote_config->getLogLabel())
2230 .arg(error_message);
2236 ConstElementPtr args = verifyAsyncResponse(http_response, rcode);
2239 if (args && (args->getType() != Element::map)) {
2240 isc_throw(CtrlChannelError,
2241 "arguments in the received response must be a map");
2244 ConstElementPtr leases = args->get(
"leases");
2245 if (!leases || (leases->getType() != Element::list)) {
2246 isc_throw(CtrlChannelError,
2247 "server response does not contain leases argument or this"
2248 " argument is not a list");
2252 auto const& leases_element = leases->listValue();
2254 LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
2255 .arg(config_->getThisServerName())
2256 .arg(leases_element.size())
2257 .arg(remote_config->getLogLabel());
2260 uint64_t applied_lease_count = 0;
2261 for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
2264 if (server_type_ == HAServerType::DHCPv4) {
2265 Lease4Ptr lease = Lease4::fromElement(*l);
2270 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2271 (l + 1 == leases_element.end())) {
2272 last_lease_in_callback = boost::dynamic_pointer_cast<Lease>(lease);
2275 if (!lease_sync_filter_.shouldSync(lease)) {
2280 Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
2281 if (!existing_lease) {
2283 LeaseMgrFactory::instance().addLease(lease);
2284 ++applied_lease_count;
2285 LeaseMgr::updateStatsOnAdd(lease);
2286 } else if (existing_lease->cltt_ < lease->cltt_) {
2292 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2293 LeaseMgrFactory::instance().updateLease4(lease);
2294 ++applied_lease_count;
2295 LeaseMgr::updateStatsOnUpdate(existing_lease, lease);
2297 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
2298 .arg(config_->getThisServerName())
2299 .arg(lease->addr_.toText())
2300 .arg(lease->subnet_id_);
2304 Lease6Ptr lease = Lease6::fromElement(*l);
2309 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2310 (l + 1 == leases_element.end())) {
2311 last_lease_in_callback = boost::dynamic_pointer_cast<Lease>(lease);
2314 if (!lease_sync_filter_.shouldSync(lease)) {
2319 Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
2321 if (!existing_lease) {
2323 LeaseMgrFactory::instance().addLease(lease);
2324 ++applied_lease_count;
2325 LeaseMgr::updateStatsOnAdd(lease);
2326 } else if (existing_lease->cltt_ < lease->cltt_) {
2332 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2333 LeaseMgrFactory::instance().updateLease6(lease);
2334 ++applied_lease_count;
2335 LeaseMgr::updateStatsOnUpdate(existing_lease, lease);
2337 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
2338 .arg(config_->getThisServerName())
2339 .arg(lease->addr_.toText())
2340 .arg(lease->subnet_id_);
2344 } catch (const std::exception& ex) {
2345 LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
2346 .arg(config_->getThisServerName())
2352 LOG_INFO(ha_logger, HA_LEASES_SYNC_APPLIED_LEASES)
2353 .arg(config_->getThisServerName())
2354 .arg(applied_lease_count);
2356 } catch (
const std::exception& ex) {
2357 error_message = ex.what();
2359 .arg(
config_->getThisServerName())
2360 .arg(remote_config->getLogLabel())
2361 .arg(error_message);
2367 if (!error_message.empty()) {
2368 communication_state_->setPartnerUnavailable();
2370 }
else if (last_lease_in_callback) {
2373 asyncSyncLeases(http_client, remote_config, max_period, last_lease_in_callback,
2374 post_sync_action, dhcp_disabled);
2379 if (post_sync_action) {
2380 post_sync_action(error_message.empty(),
2386 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2387 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2388 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2395 const unsigned int max_period) {
2398 remote_config =
config_->getPeerConfig(server_name);
2399 }
catch (
const std::exception& ex) {
2403 if (remote_config->getName() ==
config_->getThisServerName()) {
2405 +
"' points to local server but should point to a partner"));
2407 std::string answer_message;
2408 int sync_status =
synchronize(answer_message, remote_config, max_period);
2415 const unsigned int max_period) {
2422 [&](
const bool success,
const std::string& error_message,
2423 const bool dhcp_disabled) {
2428 status_message = error_message;
2434 if (dhcp_disabled) {
2440 [&](
const bool success_complete_notify,
2441 const std::string& error_message_complete_notify,
2448 [&](
const bool success_enable_dhcp,
2449 const std::string& error_message_enable_dhcp,
2454 if (!success_enable_dhcp && status_message.empty()) {
2455 status_message = error_message_enable_dhcp;
2467 if (!success_complete_notify && status_message.empty()) {
2468 status_message = error_message_complete_notify;
2481 [&](
const bool success_enable_dhcp,
2482 const std::string& error_message_enable_dhcp,
2484 if (!success_enable_dhcp && status_message.empty()) {
2485 status_message = error_message_enable_dhcp;
2504 .arg(
config_->getThisServerName())
2505 .arg(remote_config->getLogLabel());
2519 io_service->stopAndPoll();
2523 if (!status_message.empty()) {
2527 .arg(
config_->getThisServerName())
2528 .arg(remote_config->getLogLabel())
2529 .arg(status_message);
2536 status_message =
"Lease database synchronization complete.";
2540 .arg(
config_->getThisServerName())
2541 .arg(remote_config->getLogLabel())
2574 config->addBasicAuthHttpHeader(request);
2575 request->setBodyAsJson(command);
2576 request->finalize();
2584 [
this, &http_client,
config, post_request_action]
2585 (
const boost::system::error_code& ec,
2587 const std::string& error_str) {
2590 std::string error_message;
2592 if (ec || !error_str.empty()) {
2593 error_message = (ec ? ec.message() : error_str);
2594 LOG_WARN(ha_logger, HA_LEASES_BACKLOG_COMMUNICATIONS_FAILED)
2595 .arg(config_->getThisServerName())
2596 .arg(config->getLogLabel())
2597 .arg(ec ? ec.message() : error_str);
2602 auto args = verifyAsyncResponse(http_response, rcode);
2603 } catch (
const std::exception& ex) {
2604 error_message = ex.what();
2606 .arg(
config_->getThisServerName())
2607 .arg(
config->getLogLabel())
2617 if (error_message.empty()) {
2618 asyncSendLeaseUpdatesFromBacklog(http_client, config, post_request_action);
2620 post_request_action(error_message.empty(), error_message, rcode);
2628 if (num_updates == 0) {
2630 .arg(
config_->getThisServerName());
2636 auto remote_config =
config_->getFailoverPeerConfig();
2637 bool updates_successful =
true;
2640 .arg(
config_->getThisServerName())
2642 .arg(remote_config->getName());
2645 [&](
const bool success,
const std::string&,
const int) {
2647 updates_successful = success;
2661 io_service->stopAndPoll();
2663 if (updates_successful) {
2665 .arg(
config_->getThisServerName())
2666 .arg(remote_config->getName())
2667 .arg(stopwatch.logFormatLastDuration());
2670 return (updates_successful);
2684 config->addBasicAuthHttpHeader(request);
2685 request->setBodyAsJson(command);
2686 request->finalize();
2694 [
this,
config, post_request_action]
2695 (
const boost::system::error_code& ec,
2697 const std::string& error_str) {
2700 std::string error_message;
2702 if (ec || !error_str.empty()) {
2703 error_message = (ec ? ec.message() : error_str);
2704 LOG_WARN(ha_logger, HA_RESET_COMMUNICATIONS_FAILED)
2705 .arg(config_->getThisServerName())
2706 .arg(config->getLogLabel())
2707 .arg(ec ? ec.message() : error_str);
2712 auto args = verifyAsyncResponse(http_response, rcode);
2713 } catch (
const std::exception& ex) {
2714 error_message = ex.what();
2716 .arg(
config_->getThisServerName())
2717 .arg(
config->getLogLabel())
2722 post_request_action(error_message.empty(), error_message, rcode);
2730 auto remote_config =
config_->getFailoverPeerConfig();
2731 bool reset_successful =
true;
2734 [&](
const bool success,
const std::string&,
const int) {
2736 reset_successful = success;
2744 io_service->stopAndPoll();
2746 return (reset_successful);
2755 }
catch (
const std::exception& ex) {
2775 " maintenance for the server not in the"
2776 " in-maintenance state."));
2814 "Unable to transition the server from the "
2816 " in-maintenance state."));
2833 " partner-in-maintenance state."));
2845 remote_config->addBasicAuthHttpHeader(request);
2848 request->finalize();
2857 boost::system::error_code captured_ec;
2858 std::string captured_error_message;
2859 int captured_rcode = 0;
2863 remote_config->getTlsContext(),
2865 [
this, remote_config, &io_service, &captured_ec, &captured_error_message,
2867 (
const boost::system::error_code& ec,
2869 const std::string& error_str) {
2879 std::string error_message;
2882 if (ec || !error_str.empty()) {
2883 error_message = (ec ? ec.message() : error_str);
2884 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_COMMUNICATIONS_FAILED)
2885 .arg(config_->getThisServerName())
2886 .arg(remote_config->getLogLabel())
2887 .arg(error_message);
2893 static_cast<void>(verifyAsyncResponse(http_response, captured_rcode));
2895 } catch (
const std::exception& ex) {
2896 error_message = ex.what();
2898 .arg(
config_->getThisServerName())
2899 .arg(remote_config->getLogLabel())
2900 .arg(error_message);
2906 if (!error_message.empty()) {
2907 communication_state_->setPartnerUnavailable();
2911 captured_error_message = error_message;
2914 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2915 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2916 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2925 io_service->stopAndPoll();
2930 postNextEvent(HA_MAINTENANCE_START_EVT);
2931 verboseTransition(HA_PARTNER_DOWN_ST);
2934 "Server is now in the partner-down state as its"
2935 " partner appears to be offline for maintenance."));
2941 postNextEvent(HA_MAINTENANCE_START_EVT);
2942 verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST);
2949 " partner-in-maintenance state. The partner server responded"
2950 " with the following message to the ha-maintenance-notify"
2951 " command: " + captured_error_message +
"."));
2956 "Server is now in the partner-in-maintenance state"
2957 " and its partner is in-maintenance state. The partner"
2958 " can be now safely shut down."));
2965 " request because the server is not in the"
2966 " partner-in-maintenance state."));
2980 remote_config->addBasicAuthHttpHeader(request);
2985 request->finalize();
2994 std::string error_message;
2998 remote_config->getTlsContext(),
3000 [
this, remote_config, &io_service, &error_message]
3001 (
const boost::system::error_code& ec,
3003 const std::string& error_str) {
3008 if (ec || !error_str.empty()) {
3009 error_message = (ec ? ec.message() : error_str);
3010 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_CANCEL_COMMUNICATIONS_FAILED)
3011 .arg(config_->getThisServerName())
3012 .arg(remote_config->getLogLabel())
3013 .arg(error_message);
3020 ConstElementPtr args = verifyAsyncResponse(http_response, rcode);
3025 communication_state_->setPartnerUnavailable();
3029 if (args && args->getType() == Element::map) {
3031 ConstElementPtr state = args->get(
"state");
3033 if (state->getType() != Element::string) {
3034 isc_throw(CtrlChannelError,
"server state not returned in response"
3035 " to a ha-heartbeat command or it is not a string");
3037 communication_state_->setPartnerState(state->stringValue());
3040 } catch (
const std::exception& ex) {
3041 error_message = ex.what();
3043 .arg(
config_->getThisServerName())
3044 .arg(remote_config->getLogLabel())
3045 .arg(error_message);
3051 if (!error_message.empty()) {
3052 communication_state_->setPartnerUnavailable();
3056 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
3057 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
3058 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
3067 io_service->stopAndPoll();
3071 if (!error_message.empty()) {
3073 "Unable to cancel maintenance. The partner server responded"
3074 " with the following message to the ha-maintenance-notify"
3075 " command: " + error_message +
"."));
3081 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
3082 verboseTransition(next_state);
3086 "Server maintenance successfully canceled."));
3098 remote_config->addBasicAuthHttpHeader(request);
3102 request->finalize();
3110 remote_config->getTlsContext(),
3112 [
this, remote_config, post_request_action]
3113 (
const boost::system::error_code& ec,
3115 const std::string& error_str) {
3124 std::string error_message;
3127 if (ec || !error_str.empty()) {
3128 error_message = (ec ? ec.message() : error_str);
3129 LOG_ERROR(ha_logger, HA_SYNC_COMPLETE_NOTIFY_COMMUNICATIONS_FAILED)
3130 .arg(config_->getThisServerName())
3131 .arg(remote_config->getLogLabel())
3132 .arg(error_message);
3138 static_cast<void>(verifyAsyncResponse(http_response, rcode));
3140 } catch (
const CommandUnsupportedError& ex) {
3143 }
catch (
const std::exception& ex) {
3144 error_message = ex.what();
3146 .arg(
config_->getThisServerName())
3147 .arg(remote_config->getLogLabel())
3148 .arg(error_message);
3154 if (!error_message.empty()) {
3155 communication_state_->setPartnerUnavailable();
3159 if (post_request_action) {
3160 post_request_action(error_message.empty(),
3166 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
3167 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
3168 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
3190 "Server successfully notified about the synchronization completion."));
3199 boost::dynamic_pointer_cast<HttpResponseJson>(response);
3200 if (!json_response) {
3229 if (body->empty()) {
3240 std::ostringstream s;
3249 s << args->stringValue() <<
" (";
3252 s <<
"error code " << rcode <<
")";
3257 isc_throw(CommandUnsupportedError, s.str());
3265 auto failed_leases = args->get(
"failed-leases");
3266 if (!failed_leases || (failed_leases->getType() !=
Element::list)) {
3270 auto conflict =
false;
3272 for (
unsigned i = 0; i < failed_leases->size(); ++i) {
3273 auto lease = failed_leases->get(i);
3277 auto result = lease->get(
"result");
3281 auto error_message = lease->get(
"error-message");
3284 if (error_message && error_message->getType()) {
3285 s << error_message->stringValue() <<
" (";
3287 s <<
"error code " << result->intValue() <<
")";
3295 conflict_error_message = error_message;
3301 if (conflict_error_message &&
3303 s << conflict_error_message->stringValue() <<
" (";
3321 if (
client_->getThreadIOService()) {
3329 if ((!ec || (ec.value() == boost::asio::error::in_progress))
3330 && (tcp_native_fd >= 0)) {
3353 client_->closeIfOutOfBand(tcp_native_fd);
3358 if ((tcp_native_fd >= 0) &&
3367 std::lock_guard<std::mutex> lock(mutex_);
3368 return (pending_requests_.size());
3370 return (pending_requests_.size());
3374template<
typename QueryPtrType>
3378 std::lock_guard<std::mutex> lock(mutex_);
3379 return (getPendingRequestInternal(query));
3381 return (getPendingRequestInternal(query));
3385template<
typename QueryPtrType>
3387HAService::getPendingRequestInternal(
const QueryPtrType& query) {
3388 if (pending_requests_.count(query) == 0) {
3391 return (pending_requests_[query]);
3412 .arg(
config_->getThisServerName())
3417 }
catch (
const std::exception& ex) {
3419 .arg(
config_->getThisServerName())
3453 }
catch (
const std::exception& ex) {
3455 .arg(
config_->getThisServerName())
3472 }
catch (std::exception& ex) {
3474 .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.
static std::string roleToString(const HAConfig::PeerConfig::Role &role)
Returns role name.
Role
Server's role in the High Availability setup.
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.