28#include <boost/pointer_cast.hpp>
29#include <boost/make_shared.hpp>
30#include <boost/weak_ptr.hpp>
42namespace ph = std::placeholders;
49 CommandUnsupportedError(
const char* file,
size_t line,
const char* what) :
56 ConflictError(
const char* file,
size_t line,
const char* what) :
79 : id_(id), io_service_(io_service), network_state_(network_state), config_(config),
80 server_type_(server_type), client_(), listener_(), communication_state_(),
81 query_filter_(config), lease_sync_filter_(server_type, config), mutex_(),
82 pending_requests_(), lease_update_backlog_(config->getDelayedUpdatesLimit()),
83 sync_complete_notified_(false) {
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 listener_threads, tls_context));
129 if (
config_->getRestrictCommands()) {
142 .arg(
config_->getThisServerName())
155HAService::getCSCallbacksSetName()
const {
156 std::ostringstream s;
157 s <<
"HA_MT_" <<
id_;
162HAService::defineEvents() {
176HAService::verifyEvents() {
190HAService::defineStates() {
194 std::bind(&HAService::backupStateHandler,
this),
198 std::bind(&HAService::communicationRecoveryHandler,
this),
202 std::bind(&HAService::normalStateHandler,
this),
206 std::bind(&HAService::normalStateHandler,
this),
210 std::bind(&HAService::inMaintenanceStateHandler,
this),
214 std::bind(&HAService::partnerDownStateHandler,
this),
218 std::bind(&HAService::partnerInMaintenanceStateHandler,
this),
222 std::bind(&HAService::passiveBackupStateHandler,
this),
226 std::bind(&HAService::readyStateHandler,
this),
230 std::bind(&HAService::syncingStateHandler,
this),
234 std::bind(&HAService::terminatedStateHandler,
this),
238 std::bind(&HAService::waitingStateHandler,
this),
243HAService::backupStateHandler() {
258HAService::communicationRecoveryHandler() {
375HAService::normalStateHandler() {
430 }
else if (
config_->amAllowingCommRecovery()) {
450HAService::inMaintenanceStateHandler() {
464 .arg(
config_->getThisServerName());
476HAService::partnerDownStateHandler() {
490 if (maintenance ||
config_->getThisServerConfig()->isAutoFailover()) {
505 .arg(
config_->getThisServerName());
568HAService::partnerInMaintenanceStateHandler() {
581 .arg(
config_->getThisServerName());
608HAService::passiveBackupStateHandler() {
626HAService::readyStateHandler() {
706HAService::syncingStateHandler() {
766 unsigned int dhcp_disable_timeout =
767 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
768 if (dhcp_disable_timeout == 0) {
769 ++dhcp_disable_timeout;
773 std::string status_message;
775 config_->getFailoverPeerConfig(),
776 dhcp_disable_timeout);
796HAService::terminatedStateHandler() {
812 .arg(
config_->getThisServerName());
819HAService::waitingStateHandler() {
891 if (!partner_in_terminated.is_not_a_date_time() &&
894 .arg(
config_->getThisServerName())
907 .arg(
config_->getThisServerName());
945 boost::to_upper(current_state_name);
946 boost::to_upper(new_state_name);
952 std::string partner_state_name =
getStateLabel(partner_state);
953 boost::to_upper(partner_state_name);
957 .arg(
config_->getThisServerName())
958 .arg(current_state_name)
960 .arg(partner_state_name);
965 .arg(
config_->getThisServerName())
966 .arg(current_state_name)
967 .arg(new_state_name);
976 .arg(
config_->getThisServerName());
989 .arg(
config_->getThisServerName())
990 .arg(new_state_name);
992 }
else if (!
config_->amSendingLeaseUpdates()) {
995 .arg(
config_->getThisServerName())
996 .arg(new_state_name);
1003 .arg(
config_->getThisServerName())
1004 .arg(new_state_name);
1015 switch (
config_->getHAMode()) {
1029 .arg(
config_->getThisServerName());
1041 boost::to_upper(state_name);
1043 .arg(
config_->getThisServerName())
1060 return (inScopeInternal(query4));
1065 return (inScopeInternal(query6));
1068template<
typename QueryPtrType>
1070HAService::inScopeInternal(QueryPtrType& query) {
1072 std::string scope_class;
1091 boost::to_upper(current_state_name);
1104 boost::to_upper(current_state_name);
1106 .arg(
config_->getThisServerName())
1107 .arg(current_state_name);
1110 }
else if (should_enable && !
network_state_->isServiceEnabled()) {
1112 boost::to_upper(current_state_name);
1114 .arg(
config_->getThisServerName())
1115 .arg(current_state_name);
1153 if (!should_terminate) {
1160 return (should_terminate);
1174 .arg(
config_->getThisServerName());
1182 .arg(
config_->getThisServerName());
1190 .arg(
config_->getThisServerName());
1210 size_t sent_num = 0;
1213 for (
auto const& p : peers_configs) {
1221 for (
auto const& l : *deleted_leases) {
1224 if (l->state_ == Lease4::STATE_RELEASED) {
1232 for (
auto const& l : *leases) {
1254 for (
auto const& l : *deleted_leases) {
1257 if (l->state_ == Lease4::STATE_RELEASED) {
1267 for (
auto const& l : *leases) {
1288 leases->push_back(lease);
1303 size_t sent_num = 0;
1306 for (
auto const& p : peers_configs) {
1313 for (
auto const& l : *deleted_leases) {
1316 if (l->state_ == Lease4::STATE_RELEASED) {
1324 for (
auto const& l : *leases) {
1360template<
typename QueryPtrType>
1365 std::lock_guard<std::mutex> lock(mutex_);
1366 return (leaseUpdateCompleteInternal(query, parking_lot));
1368 return (leaseUpdateCompleteInternal(query, parking_lot));
1372template<
typename QueryPtrType>
1374HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
1376 auto it = pending_requests_.find(query);
1380 if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
1382 parking_lot->unpark(query);
1387 if (it != pending_requests_.end()) {
1388 pending_requests_.erase(it);
1395template<
typename QueryPtrType>
1399 std::lock_guard<std::mutex> lock(mutex_);
1400 updatePendingRequestInternal(query);
1402 updatePendingRequestInternal(query);
1406template<
typename QueryPtrType>
1408HAService::updatePendingRequestInternal(QueryPtrType& query) {
1409 if (pending_requests_.count(query) == 0) {
1410 pending_requests_[query] = 1;
1412 ++pending_requests_[query];
1416template<
typename QueryPtrType>
1426 config->addBasicAuthHttpHeader(request);
1427 request->setBodyAsJson(command);
1428 request->finalize();
1437 boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
1440 client_->asyncSendRequest(config->getUrl(), config->getTlsContext(),
1442 [
this, weak_query, parking_lot, config]
1443 (
const boost::system::error_code& ec,
1445 const std::string& error_str) {
1449 QueryPtrType query = weak_query.lock();
1451 isc_throw(Unexpected,
"query is null while receiving response from"
1452 " HA peer. This is programmatic error");
1463 bool lease_update_success =
true;
1464 bool lease_update_conflict =
false;
1467 if (ec || !error_str.empty()) {
1468 LOG_WARN(ha_logger, HA_LEASE_UPDATE_COMMUNICATIONS_FAILED)
1469 .arg(config_->getThisServerName())
1470 .arg(query->getLabel())
1471 .arg(config->getLogLabel())
1472 .arg(ec ? ec.message() : error_str);
1476 lease_update_success = false;
1482 auto args = verifyAsyncResponse(response, rcode);
1485 logFailedLeaseUpdates(query, args);
1487 } catch (
const ConflictError& ex) {
1489 lease_update_conflict =
true;
1490 lease_update_success =
false;
1494 .arg(
config_->getThisServerName())
1495 .arg(query->getLabel())
1496 .arg(config->getLogLabel())
1499 }
catch (
const std::exception& ex) {
1502 .arg(
config_->getThisServerName())
1503 .arg(query->getLabel())
1504 .arg(config->getLogLabel())
1508 lease_update_success =
false;
1517 if (!lease_update_success) {
1520 if (!lease_update_conflict) {
1523 communication_state_->setPartnerUnavailable();
1528 communication_state_->reportSuccessfulLeaseUpdate(query);
1535 if (config_->amWaitingBackupAck() || (config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1539 if (!lease_update_success) {
1541 parking_lot->drop(query);
1550 if (leaseUpdateComplete(query, parking_lot)) {
1556 runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
1560 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1561 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1562 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1569 if (config_->amWaitingBackupAck() || (config->getRole() != HAConfig::PeerConfig::BACKUP)) {
1571 updatePendingRequest(query);
1578 if (!config_->amSendingLeaseUpdates()) {
1583 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1588 if (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP) {
1594 switch (getCurrState()) {
1609 if (!config_->amSendingLeaseUpdates()) {
1613 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
1621HAService::logFailedLeaseUpdates(
const PktPtr& query,
1634 auto failed_leases = args->get(param_name);
1637 if (failed_leases && (failed_leases->getType() ==
Element::list)) {
1639 for (
int i = 0; i < failed_leases->size(); ++i) {
1640 auto lease = failed_leases->get(i);
1644 auto ip_address = lease->get(
"ip-address");
1647 auto lease_type = lease->get(
"type");
1650 auto error_message = lease->get(
"error-message");
1653 .arg(query->getLabel())
1655 lease_type->stringValue() :
"(unknown)")
1657 ip_address->stringValue() :
"(unknown)")
1659 error_message->stringValue() :
"(unknown)");
1673HAService::processStatusGet()
const {
1679 role = config_->getThisServerConfig()->getRole();
1680 std::string role_txt = HAConfig::PeerConfig::roleToString(role);
1682 int state = getCurrState();
1690 std::set<std::string> scopes = query_filter_.getServedScopes();
1692 for (
auto const& scope : scopes) {
1695 local->set(
"scopes", list);
1696 local->set(
"server-name",
Element::create(config_->getThisServerName()));
1697 auto const my_time(communication_state_->getMyTimeAtSkew());
1698 if (my_time.is_not_a_date_time()) {
1703 ha_servers->set(
"local", local);
1707 if ((config_->getHAMode() == HAConfig::PASSIVE_BACKUP) ||
1708 (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP)) {
1709 return (ha_servers);
1713 ElementPtr remote = communication_state_->getReport();
1716 role = config_->getFailoverPeerConfig()->getRole();
1717 role_txt = HAConfig::PeerConfig::roleToString(role);
1723 remote->set(
"server-name",
Element::create(config_->getFailoverPeerConfig()->getName()));
1724 ha_servers->set(
"remote", remote);
1726 return (ha_servers);
1730HAService::processHeartbeat() {
1732 std::string state_label = getState(getCurrState())->getLabel();
1738 auto scopes = query_filter_.getServedScopes();
1740 for (
auto const& scope : scopes) {
1743 arguments->set(
"scopes", scopes_list);
1745 arguments->set(
"unsent-update-count",
1746 Element::create(
static_cast<int64_t
>(communication_state_->getUnsentUpdateCount())));
1753HAService::processHAReset() {
1763HAService::asyncSendHeartbeat() {
1773 bool sync_complete_notified = sync_complete_notified_;
1774 sync_complete_notified_ =
false;
1780 partner_config->addBasicAuthHttpHeader(request);
1781 request->setBodyAsJson(CommandCreator::createHeartbeat(config_->getThisServerName(),
1783 request->finalize();
1790 client_->asyncSendRequest(partner_config->getUrl(),
1791 partner_config->getTlsContext(),
1793 [
this, partner_config, sync_complete_notified]
1794 (
const boost::system::error_code& ec,
1796 const std::string& error_str) {
1804 bool heartbeat_success = true;
1807 if (ec || !error_str.empty()) {
1808 LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
1809 .arg(config_->getThisServerName())
1810 .arg(partner_config->getLogLabel())
1811 .arg(ec ? ec.message() : error_str);
1812 heartbeat_success = false;
1821 ConstElementPtr args = verifyAsyncResponse(response, rcode);
1822 if (!args || args->getType() != Element::map) {
1823 isc_throw(CtrlChannelError,
"returned arguments in the response"
1827 ConstElementPtr state = args->get(
"state");
1828 if (!state || state->getType() != Element::string) {
1829 isc_throw(CtrlChannelError,
"server state not returned in response"
1830 " to a ha-heartbeat command or it is not a string");
1834 communication_state_->setPartnerState(state->stringValue());
1836 ConstElementPtr date_time = args->get(
"date-time");
1837 if (!date_time || date_time->getType() != Element::string) {
1838 isc_throw(CtrlChannelError,
"date-time not returned in response"
1839 " to a ha-heartbeat command or it is not a string");
1842 communication_state_->setPartnerTime(date_time->stringValue());
1846 auto scopes = args->get(
"scopes");
1847 communication_state_->setPartnerScopes(scopes);
1862 auto unsent_update_count = args->get(
"unsent-update-count");
1863 if (unsent_update_count) {
1864 if (unsent_update_count->getType() != Element::integer) {
1865 isc_throw(CtrlChannelError,
"unsent-update-count returned in"
1866 " the ha-heartbeat response is not an integer");
1868 communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>
1869 (unsent_update_count->intValue()));
1872 } catch (
const std::exception& ex) {
1874 .arg(config_->getThisServerName())
1875 .arg(partner_config->getLogLabel())
1877 heartbeat_success =
false;
1883 if (heartbeat_success) {
1884 communication_state_->poke();
1889 communication_state_->setPartnerUnavailable();
1891 if (communication_state_->isCommunicationInterrupted()) {
1892 LOG_WARN(ha_logger, HA_COMMUNICATION_INTERRUPTED)
1893 .arg(config_->getThisServerName())
1894 .arg(partner_config->getName());
1902 if (sync_complete_notified && !heartbeat_success) {
1903 postNextEvent(HA_SYNCED_PARTNER_UNAVAILABLE_EVT);
1910 runModel(HA_HEARTBEAT_COMPLETE_EVT);
1913 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
1914 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
1915 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
1920HAService::scheduleHeartbeat() {
1921 if (!communication_state_->isHeartbeatRunning()) {
1927HAService::startHeartbeat() {
1928 if (config_->getHeartbeatDelay() > 0) {
1929 communication_state_->startHeartbeat(config_->getHeartbeatDelay(),
1930 std::bind(&HAService::asyncSendHeartbeat,
1938 const unsigned int max_period,
1945 remote_config->addBasicAuthHttpHeader(request);
1946 request->setBodyAsJson(CommandCreator::createDHCPDisable(getRemoteOrigin(),
1949 request->finalize();
1957 remote_config->getTlsContext(),
1959 [
this, remote_config, post_request_action]
1960 (
const boost::system::error_code& ec,
1962 const std::string& error_str) {
1971 std::string error_message;
1974 if (ec || !error_str.empty()) {
1975 error_message = (ec ? ec.message() : error_str);
1976 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
1977 .arg(config_->getThisServerName())
1978 .arg(remote_config->getLogLabel())
1979 .arg(error_message);
1985 static_cast<void>(verifyAsyncResponse(response, rcode));
1987 } catch (
const std::exception& ex) {
1988 error_message = ex.what();
1990 .arg(config_->getThisServerName())
1991 .arg(remote_config->getLogLabel())
1992 .arg(error_message);
1998 if (!error_message.empty()) {
1999 communication_state_->setPartnerUnavailable();
2003 if (post_request_action) {
2004 post_request_action(error_message.empty(),
2010 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2011 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2012 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2024 remote_config->addBasicAuthHttpHeader(request);
2025 request->setBodyAsJson(CommandCreator::createDHCPEnable(getRemoteOrigin(),
2027 request->finalize();
2035 remote_config->getTlsContext(),
2037 [
this, remote_config, post_request_action]
2038 (
const boost::system::error_code& ec,
2040 const std::string& error_str) {
2049 std::string error_message;
2052 if (ec || !error_str.empty()) {
2053 error_message = (ec ? ec.message() : error_str);
2054 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
2055 .arg(config_->getThisServerName())
2056 .arg(remote_config->getLogLabel())
2057 .arg(error_message);
2063 static_cast<void>(verifyAsyncResponse(response, rcode));
2065 } catch (
const std::exception& ex) {
2066 error_message = ex.what();
2068 .arg(config_->getThisServerName())
2069 .arg(remote_config->getLogLabel())
2070 .arg(error_message);
2076 if (!error_message.empty()) {
2077 communication_state_->setPartnerUnavailable();
2081 if (post_request_action) {
2082 post_request_action(error_message.empty(),
2088 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2089 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2090 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2095HAService::localDisableDHCPService() {
2096 network_state_->disableService(getLocalOrigin());
2100HAService::localEnableDHCPService() {
2101 network_state_->enableService(getLocalOrigin());
2105HAService::asyncSyncLeases() {
2109 unsigned int dhcp_disable_timeout =
2110 static_cast<unsigned int>(config_->getSyncTimeout() / 1000);
2111 if (dhcp_disable_timeout == 0) {
2113 dhcp_disable_timeout = 1;
2116 lease_sync_filter_.apply();
2117 asyncSyncLeases(*client_, config_->getFailoverPeerConfig(),
2118 dhcp_disable_timeout,
LeasePtr(), null_action);
2124 const unsigned int max_period,
2127 const bool dhcp_disabled) {
2133 asyncDisableDHCPService(http_client, remote_config, max_period,
2134 [
this, &http_client, remote_config, max_period, last_lease,
2135 post_sync_action, dhcp_disabled]
2136 (
const bool success,
const std::string& error_message,
const int) {
2143 asyncSyncLeasesInternal(http_client, remote_config, max_period,
2144 last_lease, post_sync_action,
true);
2147 post_sync_action(success, error_message, dhcp_disabled);
2155 const unsigned int max_period,
2158 const bool dhcp_disabled) {
2163 remote_config->addBasicAuthHttpHeader(request);
2164 if (server_type_ == HAServerType::DHCPv4) {
2165 request->setBodyAsJson(CommandCreator::createLease4GetPage(
2166 boost::dynamic_pointer_cast<Lease4>(last_lease), config_->getSyncPageLimit()));
2169 request->setBodyAsJson(CommandCreator::createLease6GetPage(
2170 boost::dynamic_pointer_cast<Lease6>(last_lease), config_->getSyncPageLimit()));
2172 request->finalize();
2180 remote_config->getTlsContext(),
2182 [
this, remote_config, post_sync_action, &http_client, max_period, dhcp_disabled]
2183 (
const boost::system::error_code& ec,
2185 const std::string& error_str) {
2189 LeasePtr last_lease;
2197 std::string error_message;
2200 if (ec || !error_str.empty()) {
2201 error_message = (ec ? ec.message() : error_str);
2202 LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
2203 .arg(config_->getThisServerName())
2204 .arg(remote_config->getLogLabel())
2205 .arg(error_message);
2211 ConstElementPtr args = verifyAsyncResponse(response, rcode);
2214 if (args && (args->getType() != Element::map)) {
2215 isc_throw(CtrlChannelError,
2216 "arguments in the received response must be a map");
2219 ConstElementPtr leases = args->get(
"leases");
2220 if (!leases || (leases->getType() != Element::list)) {
2221 isc_throw(CtrlChannelError,
2222 "server response does not contain leases argument or this"
2223 " argument is not a list");
2227 auto const& leases_element = leases->listValue();
2229 LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
2230 .arg(config_->getThisServerName())
2231 .arg(leases_element.size())
2232 .arg(remote_config->getLogLabel());
2235 uint64_t applied_lease_count = 0;
2236 for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
2239 if (server_type_ == HAServerType::DHCPv4) {
2240 Lease4Ptr lease = Lease4::fromElement(*l);
2245 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2246 (l + 1 == leases_element.end())) {
2247 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2250 if (!lease_sync_filter_.shouldSync(lease)) {
2255 Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
2256 if (!existing_lease) {
2258 LeaseMgrFactory::instance().addLease(lease);
2259 ++applied_lease_count;
2261 } else if (existing_lease->cltt_ < lease->cltt_) {
2267 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2268 LeaseMgrFactory::instance().updateLease4(lease);
2269 ++applied_lease_count;
2272 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
2273 .arg(config_->getThisServerName())
2274 .arg(lease->addr_.toText())
2275 .arg(lease->subnet_id_);
2279 Lease6Ptr lease = Lease6::fromElement(*l);
2284 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
2285 (l + 1 == leases_element.end())) {
2286 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
2289 if (!lease_sync_filter_.shouldSync(lease)) {
2294 Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
2296 if (!existing_lease) {
2298 LeaseMgrFactory::instance().addLease(lease);
2299 ++applied_lease_count;
2301 } else if (existing_lease->cltt_ < lease->cltt_) {
2307 Lease::syncCurrentExpirationTime(*existing_lease, *lease);
2308 LeaseMgrFactory::instance().updateLease6(lease);
2309 ++applied_lease_count;
2312 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
2313 .arg(config_->getThisServerName())
2314 .arg(lease->addr_.toText())
2315 .arg(lease->subnet_id_);
2319 } catch (const std::exception& ex) {
2320 LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
2321 .arg(config_->getThisServerName())
2327 LOG_INFO(ha_logger, HA_LEASES_SYNC_APPLIED_LEASES)
2328 .arg(config_->getThisServerName())
2329 .arg(applied_lease_count);
2331 } catch (
const std::exception& ex) {
2332 error_message = ex.what();
2334 .arg(config_->getThisServerName())
2335 .arg(remote_config->getLogLabel())
2336 .arg(error_message);
2342 if (!error_message.empty()) {
2343 communication_state_->setPartnerUnavailable();
2345 }
else if (last_lease) {
2348 asyncSyncLeases(http_client, remote_config, max_period, last_lease,
2349 post_sync_action, dhcp_disabled);
2354 if (post_sync_action) {
2355 post_sync_action(error_message.empty(),
2361 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2362 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2363 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2369HAService::processSynchronize(
const std::string& server_name,
2370 const unsigned int max_period) {
2373 remote_config = config_->getPeerConfig(server_name);
2374 }
catch (
const std::exception& ex) {
2378 if (remote_config->getName() == config_->getThisServerName()) {
2380 +
"' points to local server but should point to a partner"));
2382 std::string answer_message;
2383 int sync_status = synchronize(answer_message, remote_config, max_period);
2388HAService::synchronize(std::string& status_message,
2390 const unsigned int max_period) {
2391 lease_sync_filter_.apply();
2396 asyncSyncLeases(client, remote_config, max_period,
Lease4Ptr(),
2397 [&](
const bool success,
const std::string& error_message,
2398 const bool dhcp_disabled) {
2403 status_message = error_message;
2409 if (dhcp_disabled) {
2414 asyncSyncCompleteNotify(client, remote_config,
2415 [&](
const bool success,
2416 const std::string& error_message,
2422 asyncEnableDHCPService(client, remote_config,
2423 [&](
const bool success,
2424 const std::string& error_message,
2429 if (!success && status_message.empty()) {
2430 status_message = error_message;
2442 if (!success && status_message.empty()) {
2443 status_message = error_message;
2455 asyncEnableDHCPService(client, remote_config,
2456 [&](
const bool success,
2457 const std::string& error_message,
2459 if (!success && status_message.empty()) {
2460 status_message = error_message;
2479 .arg(config_->getThisServerName())
2480 .arg(remote_config->getLogLabel());
2494 io_service->stopAndPoll();
2498 if (!status_message.empty()) {
2499 postNextEvent(HA_SYNCING_FAILED_EVT);
2502 .arg(config_->getThisServerName())
2503 .arg(remote_config->getLogLabel())
2504 .arg(status_message);
2511 status_message =
"Lease database synchronization complete.";
2512 postNextEvent(HA_SYNCING_SUCCEEDED_EVT);
2515 .arg(config_->getThisServerName())
2516 .arg(remote_config->getLogLabel())
2523HAService::asyncSendLeaseUpdatesFromBacklog(
HttpClient& http_client,
2526 if (lease_update_backlog_.size() == 0) {
2532 if (server_type_ == HAServerType::DHCPv4) {
2534 Lease4Ptr lease = boost::dynamic_pointer_cast<Lease4>(lease_update_backlog_.pop(op_type));
2535 if (op_type == LeaseUpdateBacklog::ADD) {
2536 command = CommandCreator::createLease4Update(*lease);
2538 command = CommandCreator::createLease4Delete(*lease);
2542 command = CommandCreator::createLease6BulkApply(lease_update_backlog_);
2549 config->addBasicAuthHttpHeader(request);
2550 request->setBodyAsJson(command);
2551 request->finalize();
2559 [
this, &http_client, config, post_request_action]
2560 (
const boost::system::error_code& ec,
2562 const std::string& error_str) {
2565 std::string error_message;
2567 if (ec || !error_str.empty()) {
2568 error_message = (ec ? ec.message() : error_str);
2569 LOG_WARN(ha_logger, HA_LEASES_BACKLOG_COMMUNICATIONS_FAILED)
2570 .arg(config_->getThisServerName())
2571 .arg(config->getLogLabel())
2572 .arg(ec ? ec.message() : error_str);
2577 auto args = verifyAsyncResponse(response, rcode);
2578 } catch (
const std::exception& ex) {
2579 error_message = ex.what();
2581 .arg(config_->getThisServerName())
2582 .arg(config->getLogLabel())
2592 if (error_message.empty()) {
2593 asyncSendLeaseUpdatesFromBacklog(http_client, config, post_request_action);
2595 post_request_action(error_message.empty(), error_message, rcode);
2601HAService::sendLeaseUpdatesFromBacklog() {
2602 auto num_updates = lease_update_backlog_.size();
2603 if (num_updates == 0) {
2605 .arg(config_->getThisServerName());
2611 auto remote_config = config_->getFailoverPeerConfig();
2612 bool updates_successful =
true;
2615 .arg(config_->getThisServerName())
2617 .arg(remote_config->getName());
2619 asyncSendLeaseUpdatesFromBacklog(client, remote_config,
2620 [&](
const bool success,
const std::string&,
const int) {
2622 updates_successful = success;
2636 io_service->stopAndPoll();
2638 if (updates_successful) {
2640 .arg(config_->getThisServerName())
2641 .arg(remote_config->getName())
2642 .arg(stopwatch.logFormatLastDuration());
2645 return (updates_successful);
2652 ConstElementPtr command = CommandCreator::createHAReset(config_->getThisServerName(),
2659 config->addBasicAuthHttpHeader(request);
2660 request->setBodyAsJson(command);
2661 request->finalize();
2669 [
this, config, post_request_action]
2670 (
const boost::system::error_code& ec,
2672 const std::string& error_str) {
2675 std::string error_message;
2677 if (ec || !error_str.empty()) {
2678 error_message = (ec ? ec.message() : error_str);
2679 LOG_WARN(ha_logger, HA_RESET_COMMUNICATIONS_FAILED)
2680 .arg(config_->getThisServerName())
2681 .arg(config->getLogLabel())
2682 .arg(ec ? ec.message() : error_str);
2687 auto args = verifyAsyncResponse(response, rcode);
2688 } catch (
const std::exception& ex) {
2689 error_message = ex.what();
2691 .arg(config_->getThisServerName())
2692 .arg(config->getLogLabel())
2697 post_request_action(error_message.empty(), error_message, rcode);
2702HAService::sendHAReset() {
2705 auto remote_config = config_->getFailoverPeerConfig();
2706 bool reset_successful =
true;
2708 asyncSendHAReset(client, remote_config,
2709 [&](
const bool success,
const std::string&,
const int) {
2711 reset_successful = success;
2719 io_service->stopAndPoll();
2721 return (reset_successful);
2725HAService::processScopes(
const std::vector<std::string>& scopes) {
2727 query_filter_.serveScopes(scopes);
2728 adjustNetworkState();
2730 }
catch (
const std::exception& ex) {
2738HAService::processContinue() {
2746HAService::processMaintenanceNotify(
const bool cancel,
const std::string& state) {
2750 " maintenance for the server not in the"
2751 " in-maintenance state."));
2755 communication_state_->setPartnerState(state);
2760 communication_state_->setPartnerUnavailable();
2762 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
2772 std::string state_label = getState(getCurrState())->getLabel();
2778 switch (getCurrState()) {
2788 return (
createAnswer(HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED,
2789 "Unable to transition the server from the "
2791 " in-maintenance state."));
2794 runModel(HA_MAINTENANCE_NOTIFY_EVT);
2800HAService::processMaintenanceStart() {
2801 switch (getCurrState()) {
2808 " partner-in-maintenance state."));
2820 remote_config->addBasicAuthHttpHeader(request);
2821 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(config_->getThisServerName(),
2822 false, getCurrState(), server_type_));
2823 request->finalize();
2832 boost::system::error_code captured_ec;
2833 std::string captured_error_message;
2834 int captured_rcode = 0;
2838 remote_config->getTlsContext(),
2840 [
this, remote_config, &io_service, &captured_ec, &captured_error_message,
2842 (
const boost::system::error_code& ec,
2844 const std::string& error_str) {
2854 std::string error_message;
2857 if (ec || !error_str.empty()) {
2858 error_message = (ec ? ec.message() : error_str);
2859 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_COMMUNICATIONS_FAILED)
2860 .arg(config_->getThisServerName())
2861 .arg(remote_config->getLogLabel())
2862 .arg(error_message);
2868 static_cast<void>(verifyAsyncResponse(response, captured_rcode));
2870 } catch (
const std::exception& ex) {
2871 error_message = ex.what();
2873 .arg(config_->getThisServerName())
2874 .arg(remote_config->getLogLabel())
2875 .arg(error_message);
2881 if (!error_message.empty()) {
2882 communication_state_->setPartnerUnavailable();
2886 captured_error_message = error_message;
2889 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
2890 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
2891 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
2900 io_service->stopAndPoll();
2905 postNextEvent(HA_MAINTENANCE_START_EVT);
2906 verboseTransition(HA_PARTNER_DOWN_ST);
2909 "Server is now in the partner-down state as its"
2910 " partner appears to be offline for maintenance."));
2916 postNextEvent(HA_MAINTENANCE_START_EVT);
2917 verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST);
2924 " partner-in-maintenance state. The partner server responded"
2925 " with the following message to the ha-maintenance-notify"
2926 " command: " + captured_error_message +
"."));
2931 "Server is now in the partner-in-maintenance state"
2932 " and its partner is in-maintenance state. The partner"
2933 " can be now safely shut down."));
2937HAService::processMaintenanceCancel() {
2940 " request because the server is not in the"
2941 " partner-in-maintenance state."));
2955 remote_config->addBasicAuthHttpHeader(request);
2956 request->setBodyAsJson(CommandCreator::createMaintenanceNotify(config_->getThisServerName(),
2960 request->finalize();
2969 std::string error_message;
2973 remote_config->getTlsContext(),
2975 [
this, remote_config, &io_service, &error_message]
2976 (
const boost::system::error_code& ec,
2978 const std::string& error_str) {
2983 if (ec || !error_str.empty()) {
2984 error_message = (ec ? ec.message() : error_str);
2985 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_CANCEL_COMMUNICATIONS_FAILED)
2986 .arg(config_->getThisServerName())
2987 .arg(remote_config->getLogLabel())
2988 .arg(error_message);
2995 ConstElementPtr args = verifyAsyncResponse(response, rcode);
3000 communication_state_->setPartnerUnavailable();
3004 if (args && args->getType() == Element::map) {
3006 ConstElementPtr state = args->get(
"state");
3008 if (state->getType() != Element::string) {
3009 isc_throw(CtrlChannelError,
"server state not returned in response"
3010 " to a ha-heartbeat command or it is not a string");
3012 communication_state_->setPartnerState(state->stringValue());
3015 } catch (
const std::exception& ex) {
3016 error_message = ex.what();
3018 .arg(config_->getThisServerName())
3019 .arg(remote_config->getLogLabel())
3020 .arg(error_message);
3026 if (!error_message.empty()) {
3027 communication_state_->setPartnerUnavailable();
3031 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
3032 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
3033 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
3042 io_service->stopAndPoll();
3046 if (!error_message.empty()) {
3048 "Unable to cancel maintenance. The partner server responded"
3049 " with the following message to the ha-maintenance-notify"
3050 " command: " + error_message +
"."));
3056 postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
3057 verboseTransition(next_state);
3061 "Server maintenance successfully canceled."));
3073 remote_config->addBasicAuthHttpHeader(request);
3074 request->setBodyAsJson(CommandCreator::createSyncCompleteNotify(getRemoteOrigin(),
3075 config_->getThisServerName(),
3077 request->finalize();
3085 remote_config->getTlsContext(),
3087 [
this, remote_config, post_request_action]
3088 (
const boost::system::error_code& ec,
3090 const std::string& error_str) {
3099 std::string error_message;
3102 if (ec || !error_str.empty()) {
3103 error_message = (ec ? ec.message() : error_str);
3104 LOG_ERROR(ha_logger, HA_SYNC_COMPLETE_NOTIFY_COMMUNICATIONS_FAILED)
3105 .arg(config_->getThisServerName())
3106 .arg(remote_config->getLogLabel())
3107 .arg(error_message);
3113 static_cast<void>(verifyAsyncResponse(response, rcode));
3115 } catch (
const CommandUnsupportedError& ex) {
3118 }
catch (
const std::exception& ex) {
3119 error_message = ex.what();
3121 .arg(config_->getThisServerName())
3122 .arg(remote_config->getLogLabel())
3123 .arg(error_message);
3129 if (!error_message.empty()) {
3130 communication_state_->setPartnerUnavailable();
3134 if (post_request_action) {
3135 post_request_action(error_message.empty(),
3141 std::bind(&HAService::clientConnectHandler,
this, ph::_1, ph::_2),
3142 std::bind(&HAService::clientHandshakeHandler,
this, ph::_1),
3143 std::bind(&HAService::clientCloseHandler,
this, ph::_1)
3148HAService::processSyncCompleteNotify(
const unsigned int origin_id) {
3150 sync_complete_notified_ =
true;
3158 network_state_->disableService(getLocalOrigin());
3163 network_state_->enableService(origin_id);
3165 "Server successfully notified about the synchronization completion."));
3174 boost::dynamic_pointer_cast<HttpResponseJson>(response);
3175 if (!json_response) {
3204 if (body->empty()) {
3215 std::ostringstream s;
3224 s << args->stringValue() <<
" (";
3227 s <<
"error code " << rcode <<
")";
3232 isc_throw(CommandUnsupportedError, s.str());
3240 auto failed_leases = args->get(
"failed-leases");
3241 if (!failed_leases || (failed_leases->getType() !=
Element::list)) {
3245 auto conflict =
false;
3247 for (
auto i = 0; i < failed_leases->size(); ++i) {
3248 auto lease = failed_leases->get(i);
3252 auto result = lease->get(
"result");
3256 auto error_message = lease->get(
"error-message");
3259 if (error_message && error_message->getType()) {
3260 s << error_message->stringValue() <<
" (";
3262 s <<
"error code " << result->intValue() <<
")";
3270 conflict_error_message = error_message;
3276 if (conflict_error_message &&
3278 s << conflict_error_message->stringValue() <<
" (";
3292HAService::clientConnectHandler(
const boost::system::error_code& ec,
int tcp_native_fd) {
3296 if (client_->getThreadIOService()) {
3304 if ((!ec || (ec.value() == boost::asio::error::in_progress))
3305 && (tcp_native_fd >= 0)) {
3311 std::bind(&HAService::socketReadyHandler,
this, ph::_1)
3323HAService::socketReadyHandler(
int tcp_native_fd) {
3328 client_->closeIfOutOfBand(tcp_native_fd);
3332HAService::clientCloseHandler(
int tcp_native_fd) {
3333 if (tcp_native_fd >= 0) {
3339HAService::pendingRequestSize() {
3341 std::lock_guard<std::mutex> lock(mutex_);
3342 return (pending_requests_.size());
3344 return (pending_requests_.size());
3348template<
typename QueryPtrType>
3350HAService::getPendingRequest(
const QueryPtrType& query) {
3352 std::lock_guard<std::mutex> lock(mutex_);
3353 return (getPendingRequestInternal(query));
3355 return (getPendingRequestInternal(query));
3359template<
typename QueryPtrType>
3361HAService::getPendingRequestInternal(
const QueryPtrType& query) {
3362 if (pending_requests_.count(query) == 0) {
3365 return (pending_requests_[query]);
3370HAService::checkPermissionsClientAndListener() {
3378 client_->checkPermissions();
3382 listener_->checkPermissions();
3386 .arg(config_->getThisServerName())
3391 }
catch (
const std::exception& ex) {
3393 .arg(config_->getThisServerName())
3399HAService::startClientAndListener() {
3402 std::bind(&HAService::checkPermissionsClientAndListener,
this),
3403 std::bind(&HAService::pauseClientAndListener,
this),
3404 std::bind(&HAService::resumeClientAndListener,
this));
3416HAService::pauseClientAndListener() {
3427 }
catch (
const std::exception& ex) {
3434HAService::resumeClientAndListener() {
3443 listener_->resume();
3445 }
catch (std::exception& ex) {
3447 .arg(config_->getThisServerName())
3453HAService::stopClientAndListener() {
3467template int HAService::getPendingRequest(
const Pkt4Ptr&);
3468template int HAService::getPendingRequest(
const Pkt6Ptr&);
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Exception thrown when a worker thread is trying to stop or pause the respective thread pool (which wo...
A generic exception that is thrown when an unexpected error condition occurs.
The IOAddress class represents an IP addresses (version agnostic)
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
The IOService class is a wrapper for the ASIO io_service class.
A multi-threaded HTTP listener that can process API commands requests.
static std::unordered_set< std::string > command_accept_list_
The server command accept list.
A standard control channel exception that is thrown if a function is there is a problem with one of t...
static ElementPtr create(const Position &pos=ZERO_POSITION())
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
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 std::unordered_set< std::string > ha_commands4_
List of commands used by the High Availability in v4.
static data::ConstElementPtr createLease4Update(const dhcp::Lease4 &lease4)
Creates lease4-update command.
static data::ConstElementPtr createLease6BulkApply(const dhcp::Lease6CollectionPtr &leases, const dhcp::Lease6CollectionPtr &deleted_leases)
Creates lease6-bulk-apply command.
static std::unordered_set< std::string > ha_commands6_
List of commands used by the High Availability in v6.
Holds communication state between DHCPv4 servers.
Holds communication state between DHCPv6 servers.
Role
Server's role in the High Availability setup.
static std::string roleToString(const HAConfig::PeerConfig::Role &role)
Returns role name.
std::map< std::string, PeerConfigPtr > PeerConfigMap
Map of the servers' configurations.
boost::shared_ptr< PeerConfig > PeerConfigPtr
Pointer to the server's configuration.
static std::string HAModeToString(const HAMode &ha_mode)
Returns HA mode name.
static const int HA_MAINTENANCE_START_EVT
ha-maintenance-start command received.
bool inScope(dhcp::Pkt4Ptr &query4)
Checks if the DHCPv4 query should be processed by this server.
void adjustNetworkState()
Enables or disables network state depending on the served scopes.
void stopClientAndListener()
Stop the client and(or) listener instances.
int getNormalState() const
Returns normal operation state for the current configuration.
bool shouldQueueLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be queued.
static const int HA_HEARTBEAT_COMPLETE_EVT
Finished heartbeat command.
bool isMaintenanceCanceled() const
Convenience method checking if the current state is a result of canceling the maintenance.
void asyncSendLeaseUpdate(const QueryPtrType &query, const HAConfig::PeerConfigPtr &config, const data::ConstElementPtr &command, const hooks::ParkingLotHandlePtr &parking_lot)
Asynchronously sends lease update to the peer.
void verboseTransition(const unsigned state)
Transitions to a desired state and logs it.
bool sendLeaseUpdatesFromBacklog()
Attempts to send all lease updates from the backlog synchronously.
config::CmdHttpListenerPtr listener_
HTTP listener instance used to receive and respond to HA commands and lease updates.
bool leaseUpdateComplete(QueryPtrType &query, const hooks::ParkingLotHandlePtr &parking_lot)
Handle last pending request for this query.
HAConfigPtr config_
Pointer to the HA hooks library configuration.
unsigned int id_
Unique service id.
bool shouldTerminate() const
Indicates if the server should transition to the terminated state.
dhcp::NetworkStatePtr network_state_
Pointer to the state of the DHCP service (enabled/disabled).
void scheduleHeartbeat()
Schedules asynchronous heartbeat to a peer if it is not scheduled.
std::function< void(const bool, const std::string &, const bool)> PostSyncCallback
Callback invoked when lease database synchronization is complete.
QueryFilter query_filter_
Selects queries to be processed/dropped.
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.
static const int HA_MAINTENANCE_NOTIFY_EVT
ha-maintenance-notify command received.
static const int HA_SYNCED_PARTNER_UNAVAILABLE_EVT
The heartbeat command failed after receiving ha-sync-complete-notify command from the partner.
void conditionalLogPausedState() const
Logs if the server is paused in the current state.
bool unpause()
Unpauses the HA state machine with logging.
static const int HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED
Control result returned in response to ha-maintenance-notify.
void serveDefaultScopes()
Instructs the HA service to serve default scopes.
size_t asyncSendLeaseUpdates(const dhcp::Pkt4Ptr &query, const dhcp::Lease4CollectionPtr &leases, const dhcp::Lease4CollectionPtr &deleted_leases, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules asynchronous IPv4 leases updates.
static const int HA_SYNCING_SUCCEEDED_EVT
Lease database synchronization succeeded.
bool sendHAReset()
Sends ha-reset command to partner synchronously.
asiolink::IOServicePtr io_service_
Pointer to the IO service object shared between this hooks library and the DHCP server.
CommunicationStatePtr communication_state_
Holds communication state with a peer.
LeaseUpdateBacklog lease_update_backlog_
Backlog of DHCP lease updates.
virtual ~HAService()
Destructor.
static const int HA_SYNCING_FAILED_EVT
Lease database synchronization failed.
static const int HA_MAINTENANCE_CANCEL_EVT
ha-maintenance-cancel command received.
size_t asyncSendSingleLeaseUpdate(const dhcp::Pkt4Ptr &query, const dhcp::Lease4Ptr &lease, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules an asynchronous IPv4 lease update.
bool isPartnerStateInvalid() const
Indicates if the partner's state is invalid.
int synchronize(std::string &status_message, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period)
Synchronizes lease database with a partner.
bool shouldSendLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be sent as result of leases allocation or release.
void serveFailoverScopes()
Instructs the HA service to serve failover scopes.
static const int HA_LEASE_UPDATES_COMPLETE_EVT
Finished lease updates commands.
HAService(const unsigned int id, const asiolink::IOServicePtr &io_service, const dhcp::NetworkStatePtr &network_state, const HAConfigPtr &config, const HAServerType &server_type=HAServerType::DHCPv4)
Constructor.
http::HttpClientPtr client_
HTTP client instance used to send HA commands and lease updates.
void updatePendingRequest(QueryPtrType &query)
Update pending request counter for this query.
bool shouldPartnerDown() const
Indicates if the server should transition to the partner down state.
static const int HA_WAITING_TO_TERMINATED_ST_DELAY_MINUTES
A delay in minutes to transition from the waiting to terminated state when the partner remains in ter...
bool push(const OpType op_type, const dhcp::LeasePtr &lease)
Appends lease update to the queue.
OpType
Type of the lease update (operation type).
void clear()
Removes all lease updates from the queue.
bool wasOverflown()
Checks if the queue was overflown.
bool inScope(const dhcp::Pkt4Ptr &query4, std::string &scope_class) const
Checks if this server should process the DHCPv4 query.
void serveFailoverScopes()
Enable scopes required in failover case.
void serveDefaultScopes()
Serve default scopes for the given HA mode.
void serveNoScopes()
Disables all scopes.
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.
const EventPtr & getEvent(unsigned int value)
Fetches the event referred to by value.
std::string getStateLabel(const int state) const
Fetches the label associated with an state value.
void unpauseModel()
Unpauses state model.
bool isModelPaused() const
Returns whether or not the model is paused.
virtual void defineEvents()
Populates the set of events.
void postNextEvent(unsigned int event)
Sets the next event to the given event value.
void defineState(unsigned int value, const std::string &label, StateHandler handler, const StatePausing &state_pausing=STATE_PAUSE_NEVER)
Adds an state value and associated label to the set of states.
bool doOnExit()
Checks if on exit flag is true.
unsigned int getNextEvent() const
Fetches the model's next event.
void defineEvent(unsigned int value, const std::string &label)
Adds an event value and associated label to the set of events.
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
virtual void verifyEvents()
Validates the contents of the set of events.
bool doOnEntry()
Checks if on entry flag is true.
static const int NOP_EVT
Signifies that no event has occurred.
void startModel(const int start_state)
Begins execution of the model.
virtual void defineStates()
Populates the set of states.
unsigned int getLastEvent() const
Fetches the model's last event.
unsigned int getCurrState() const
Fetches the model's current state.
Utility class to measure code execution times.
void stop()
Stops the stopwatch.
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< 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< 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.
HTTP request/response timeout value.
static const HttpVersion & HTTP_11()
HTTP version 1.1.