28#include <boost/pointer_cast.hpp> 
   29#include <boost/make_shared.hpp> 
   30#include <boost/weak_ptr.hpp> 
   42namespace ph = std::placeholders;
 
   47class CommandUnsupportedError : 
public CtrlChannelError {
 
   49    CommandUnsupportedError(
const char* file, 
size_t line, 
const char* what) :
 
   50        CtrlChannelError(file, line, what) {}
 
   54class ConflictError : 
public CtrlChannelError {
 
   56    ConflictError(
const char* file, 
size_t line, 
const char* what) :
 
   57        CtrlChannelError(file, line, what) {}
 
   97    if (!
config_->getEnableMultiThreading()) {
 
  103                      config_->getHttpClientThreads(), 
true));
 
  106        if (
config_->getHttpDedicatedListener()) {
 
  108            auto my_url = 
config_->getThisServerConfig()->getUrl();
 
  113                server_address = 
IOAddress(my_url.getStrippedHostname());
 
  114            } 
catch (
const std::exception& ex) {
 
  116                          << 
" is not a valid IP address");
 
  120            uint32_t listener_threads = 
config_->getHttpListenerThreads();
 
  123            auto tls_context = 
config_->getThisServerConfig()->getTlsContext();
 
  127                                                listener_threads, tls_context));
 
  129            if (
config_->getRestrictCommands()) {
 
  142        .arg(
config_->getThisServerName())
 
 
  155HAService::getCSCallbacksSetName()
 const {
 
  156    std::ostringstream s;
 
  157    s << 
"HA_MT_" << 
id_;
 
  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;
 
 1090    return (shouldReclaimInternal(lease4));
 
 
 1095    return (shouldReclaimInternal(lease6));
 
 
 1098template<
typename LeasePtrType>
 
 1100HAService::shouldReclaimInternal(
const LeasePtrType& lease)
 const {
 
 
 1107    boost::to_upper(current_state_name);
 
 1120        boost::to_upper(current_state_name);
 
 1122            .arg(
config_->getThisServerName())
 
 1123            .arg(current_state_name);
 
 1126    } 
else if (should_enable && !
network_state_->isServiceEnabled()) {
 
 1128        boost::to_upper(current_state_name);
 
 1130            .arg(
config_->getThisServerName())
 
 1131            .arg(current_state_name);
 
 
 1169    if (!should_terminate) {
 
 1176    return (should_terminate);
 
 
 1190                    .arg(
config_->getThisServerName());
 
 1198                    .arg(
config_->getThisServerName());
 
 1206                    .arg(
config_->getThisServerName());
 
 
 1226    size_t sent_num = 0;
 
 1229    for (
auto const& p : peers_configs) {
 
 1237            for (
auto const& l : *deleted_leases) {
 
 1248            for (
auto const& l : *leases) {
 
 1270        for (
auto const& l : *deleted_leases) {
 
 1283        for (
auto const& l : *leases) {
 
 
 1304    leases->push_back(lease);
 
 
 1319    size_t sent_num = 0;
 
 1322    for (
auto const& p : peers_configs) {
 
 1329            for (
auto const& l : *deleted_leases) {
 
 1340            for (
auto const& l : *leases) {
 
 
 1376template<
typename QueryPtrType>
 
 1381        std::lock_guard<std::mutex> lock(mutex_);
 
 1382        return (leaseUpdateCompleteInternal(query, parking_lot));
 
 1384        return (leaseUpdateCompleteInternal(query, parking_lot));
 
 
 1388template<
typename QueryPtrType>
 
 1390HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
 
 1392    auto it = pending_requests_.find(query);
 
 1396    if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
 
 1398            parking_lot->unpark(query);
 
 1403        if (it != pending_requests_.end()) {
 
 1404            pending_requests_.erase(it);
 
 1411template<
typename QueryPtrType>
 
 1415        std::lock_guard<std::mutex> lock(mutex_);
 
 1416        updatePendingRequestInternal(query);
 
 1418        updatePendingRequestInternal(query);
 
 
 1422template<
typename QueryPtrType>
 
 1424HAService::updatePendingRequestInternal(QueryPtrType& query) {
 
 1425    if (pending_requests_.count(query) == 0) {
 
 1426        pending_requests_[query] = 1;
 
 1428        ++pending_requests_[query];
 
 1432template<
typename QueryPtrType>
 
 1442    config->addBasicAuthHttpHeader(request);
 
 1443    request->setBodyAsJson(command);
 
 1444    request->finalize();
 
 1453    boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
 
 1458        [
this, weak_query, parking_lot, 
config]
 
 1459            (
const boost::system::error_code& ec,
 
 1461             const std::string& error_str) {
 
 1465            QueryPtrType query = weak_query.lock();
 
 1467                isc_throw(Unexpected, 
"query is null while receiving response from" 
 1468                          " HA peer. This is programmatic error");
 
 1479            bool lease_update_success = 
true;
 
 1480            bool lease_update_conflict = 
false;
 
 1483            if (ec || !error_str.empty()) {
 
 1484                LOG_WARN(ha_logger, HA_LEASE_UPDATE_COMMUNICATIONS_FAILED)
 
 1485                    .arg(config_->getThisServerName())
 
 1486                    .arg(query->getLabel())
 
 1487                    .arg(config->getLogLabel())
 
 1488                    .arg(ec ? ec.message() : error_str);
 
 1492                lease_update_success = false;
 
 1498                    auto args = verifyAsyncResponse(response, rcode);
 
 1501                    logFailedLeaseUpdates(query, args);
 
 1503                } catch (
const ConflictError& ex) {
 
 1505                    lease_update_conflict = 
true;
 
 1506                    lease_update_success = 
false;
 
 1510                        .arg(
config_->getThisServerName())
 
 1511                        .arg(query->getLabel())
 
 1512                        .arg(
config->getLogLabel())
 
 1515                } 
catch (
const std::exception& ex) {
 
 1518                        .arg(
config_->getThisServerName())
 
 1519                        .arg(query->getLabel())
 
 1520                        .arg(
config->getLogLabel())
 
 1524                    lease_update_success = 
false;
 
 1533                if (!lease_update_success) {
 
 1536                    if (!lease_update_conflict) {
 
 1539                        communication_state_->setPartnerUnavailable();
 
 1544                    communication_state_->reportSuccessfulLeaseUpdate(query);
 
 1551            if (config_->amWaitingBackupAck() || (
config->getRole() != HAConfig::PeerConfig::BACKUP)) {
 
 1555                if (!lease_update_success) {
 
 1557                        parking_lot->drop(query);
 
 1566            if (leaseUpdateComplete(query, parking_lot)) {
 
 1572                runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
 
 1576        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 1577        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 1578        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 1585    if (config_->amWaitingBackupAck() || (
config->getRole() != HAConfig::PeerConfig::BACKUP)) {
 
 1587        updatePendingRequest(query);
 
 
 1594    if (!
config_->amSendingLeaseUpdates()) {
 
 
 1625    if (!
config_->amSendingLeaseUpdates()) {
 
 
 1650        auto failed_leases = args->get(param_name);
 
 1653        if (failed_leases && (failed_leases->getType() == 
Element::list)) {
 
 1655            for (
unsigned i = 0; i < failed_leases->size(); ++i) {
 
 1656                auto lease = failed_leases->get(i);
 
 1660                    auto ip_address = lease->get(
"ip-address");
 
 1663                    auto lease_type = lease->get(
"type");
 
 1666                    auto error_message = lease->get(
"error-message");
 
 1669                        .arg(query->getLabel())
 
 1671                             lease_type->stringValue() : 
"(unknown)")
 
 1673                             ip_address->stringValue() : 
"(unknown)")
 
 1675                             error_message->stringValue() : 
"(unknown)");
 
 
 1695    role = 
config_->getThisServerConfig()->getRole();
 
 1706    std::set<std::string> scopes = 
query_filter_.getServedScopes();
 
 1708    for (
auto const& scope : scopes) {
 
 1711    local->set(
"scopes", list);
 
 1714    if (my_time.is_not_a_date_time()) {
 
 1719    ha_servers->set(
"local", local);
 
 1725        return (ha_servers);
 
 1732        role = 
config_->getFailoverPeerConfig()->getRole();
 
 1740    ha_servers->set(
"remote", remote);
 
 1742    return (ha_servers);
 
 
 1756    for (
auto const& scope : scopes) {
 
 1759    arguments->set(
"scopes", scopes_list);
 
 1761    arguments->set(
"unsent-update-count",
 
 
 1796    partner_config->addBasicAuthHttpHeader(request);
 
 1799    request->finalize();
 
 1806    client_->asyncSendRequest(partner_config->getUrl(),
 
 1807                              partner_config->getTlsContext(),
 
 1809        [
this, partner_config, sync_complete_notified]
 
 1810            (
const boost::system::error_code& ec,
 
 1812             const std::string& error_str) {
 
 1820            bool heartbeat_success = true;
 
 1823            if (ec || !error_str.empty()) {
 
 1824                LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
 
 1825                    .arg(config_->getThisServerName())
 
 1826                    .arg(partner_config->getLogLabel())
 
 1827                    .arg(ec ? ec.message() : error_str);
 
 1828                heartbeat_success = false;
 
 1837                    ConstElementPtr args = verifyAsyncResponse(response, rcode);
 
 1838                    if (!args || args->getType() != Element::map) {
 
 1839                        isc_throw(CtrlChannelError, 
"returned arguments in the response" 
 1843                    ConstElementPtr state = args->get(
"state");
 
 1844                    if (!state || state->getType() != Element::string) {
 
 1845                        isc_throw(CtrlChannelError, 
"server state not returned in response" 
 1846                                  " to a ha-heartbeat command or it is not a string");
 
 1850                    communication_state_->setPartnerState(state->stringValue());
 
 1852                    ConstElementPtr date_time = args->get(
"date-time");
 
 1853                    if (!date_time || date_time->getType() != Element::string) {
 
 1854                        isc_throw(CtrlChannelError, 
"date-time not returned in response" 
 1855                                  " to a ha-heartbeat command or it is not a string");
 
 1858                    communication_state_->setPartnerTime(date_time->stringValue());
 
 1862                        auto scopes = args->get(
"scopes");
 
 1863                        communication_state_->setPartnerScopes(scopes);
 
 1878                    auto unsent_update_count = args->get(
"unsent-update-count");
 
 1879                    if (unsent_update_count) {
 
 1880                        if (unsent_update_count->getType() != Element::integer) {
 
 1881                            isc_throw(CtrlChannelError, 
"unsent-update-count returned in" 
 1882                                      " the ha-heartbeat response is not an integer");
 
 1884                        communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>
 
 1885                                                                          (unsent_update_count->intValue()));
 
 1888                } catch (
const std::exception& ex) {
 
 1890                        .arg(
config_->getThisServerName())
 
 1891                        .arg(partner_config->getLogLabel())
 
 1893                    heartbeat_success = 
false;
 
 1899            if (heartbeat_success) {
 
 1900                communication_state_->poke();
 
 1905                communication_state_->setPartnerUnavailable();
 
 1907                if (communication_state_->isCommunicationInterrupted()) {
 
 1908                    LOG_WARN(ha_logger, HA_COMMUNICATION_INTERRUPTED)
 
 1909                        .arg(config_->getThisServerName())
 
 1910                        .arg(partner_config->getName());
 
 1918            if (sync_complete_notified && !heartbeat_success) {
 
 1919                postNextEvent(HA_SYNCED_PARTNER_UNAVAILABLE_EVT);
 
 1926            runModel(HA_HEARTBEAT_COMPLETE_EVT);
 
 1929        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 1930        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 1931        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 
 1944    if (
config_->getHeartbeatDelay() > 0) {
 
 
 1954                                   const unsigned int max_period,
 
 1961    remote_config->addBasicAuthHttpHeader(request);
 
 1965    request->finalize();
 
 1973                                 remote_config->getTlsContext(),
 
 1975        [
this, remote_config, post_request_action]
 
 1976            (
const boost::system::error_code& ec,
 
 1978             const std::string& error_str) {
 
 1987             std::string error_message;
 
 1990             if (ec || !error_str.empty()) {
 
 1991                 error_message = (ec ? ec.message() : error_str);
 
 1992                 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
 
 1993                     .arg(config_->getThisServerName())
 
 1994                     .arg(remote_config->getLogLabel())
 
 1995                     .arg(error_message);
 
 2001                     static_cast<void>(verifyAsyncResponse(response, rcode));
 
 2003                 } catch (
const std::exception& ex) {
 
 2004                     error_message = ex.what();
 
 2006                         .arg(
config_->getThisServerName())
 
 2007                         .arg(remote_config->getLogLabel())
 
 2008                         .arg(error_message);
 
 2014             if (!error_message.empty()) {
 
 2015                 communication_state_->setPartnerUnavailable();
 
 2019             if (post_request_action) {
 
 2020                 post_request_action(error_message.empty(),
 
 2026        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 2027        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 2028        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 
 2040    remote_config->addBasicAuthHttpHeader(request);
 
 2043    request->finalize();
 
 2051                                 remote_config->getTlsContext(),
 
 2053        [
this, remote_config, post_request_action]
 
 2054            (
const boost::system::error_code& ec,
 
 2056             const std::string& error_str) {
 
 2065             std::string error_message;
 
 2068             if (ec || !error_str.empty()) {
 
 2069                 error_message = (ec ? ec.message() : error_str);
 
 2070                 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
 
 2071                     .arg(config_->getThisServerName())
 
 2072                     .arg(remote_config->getLogLabel())
 
 2073                     .arg(error_message);
 
 2079                     static_cast<void>(verifyAsyncResponse(response, rcode));
 
 2081                 } catch (
const std::exception& ex) {
 
 2082                     error_message = ex.what();
 
 2084                         .arg(
config_->getThisServerName())
 
 2085                         .arg(remote_config->getLogLabel())
 
 2086                         .arg(error_message);
 
 2092             if (!error_message.empty()) {
 
 2093                 communication_state_->setPartnerUnavailable();
 
 2097             if (post_request_action) {
 
 2098                 post_request_action(error_message.empty(),
 
 2104        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 2105        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 2106        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 
 2125    unsigned int dhcp_disable_timeout =
 
 2126        static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
 
 2127    if (dhcp_disable_timeout == 0) {
 
 2129        dhcp_disable_timeout = 1;
 
 2134                    dhcp_disable_timeout, 
LeasePtr(), null_action);
 
 
 2140                           const unsigned int max_period,
 
 2143                           const bool dhcp_disabled) {
 
 2150                            [
this, &http_client, remote_config, max_period, last_lease,
 
 2151                             post_sync_action, dhcp_disabled]
 
 2152                            (
const bool success, 
const std::string& error_message, 
const int) {
 
 2160                                    last_lease, post_sync_action, 
true);
 
 2163            post_sync_action(success, error_message, dhcp_disabled);
 
 
 2171                                   const unsigned int max_period,
 
 2174                                   const bool dhcp_disabled) {
 
 2179    remote_config->addBasicAuthHttpHeader(request);
 
 2182            boost::dynamic_pointer_cast<Lease4>(last_lease), 
config_->getSyncPageLimit()));
 
 2186            boost::dynamic_pointer_cast<Lease6>(last_lease), 
config_->getSyncPageLimit()));
 
 2188    request->finalize();
 
 2196                                 remote_config->getTlsContext(),
 
 2198        [
this, remote_config, post_sync_action, &http_client, max_period, dhcp_disabled]
 
 2199            (
const boost::system::error_code& ec,
 
 2201             const std::string& error_str) {
 
 2205             LeasePtr last_lease;
 
 2213            std::string error_message;
 
 2216            if (ec || !error_str.empty()) {
 
 2217                error_message = (ec ? ec.message() : error_str);
 
 2218                LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
 
 2219                    .arg(config_->getThisServerName())
 
 2220                    .arg(remote_config->getLogLabel())
 
 2221                    .arg(error_message);
 
 2227                    ConstElementPtr args = verifyAsyncResponse(response, rcode);
 
 2230                    if (args && (args->getType() != Element::map)) {
 
 2231                        isc_throw(CtrlChannelError,
 
 2232                                  "arguments in the received response must be a map");
 
 2235                    ConstElementPtr leases = args->get(
"leases");
 
 2236                    if (!leases || (leases->getType() != Element::list)) {
 
 2237                        isc_throw(CtrlChannelError,
 
 2238                                  "server response does not contain leases argument or this" 
 2239                                  " argument is not a list");
 
 2243                    auto const& leases_element = leases->listValue();
 
 2245                    LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
 
 2246                        .arg(config_->getThisServerName())
 
 2247                        .arg(leases_element.size())
 
 2248                        .arg(remote_config->getLogLabel());
 
 2251                    uint64_t applied_lease_count = 0;
 
 2252                    for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
 
 2255                            if (server_type_ == HAServerType::DHCPv4) {
 
 2256                                Lease4Ptr lease = Lease4::fromElement(*l);
 
 2261                                if ((leases_element.size() >= config_->getSyncPageLimit()) &&
 
 2262                                    (l + 1 == leases_element.end())) {
 
 2263                                    last_lease = boost::dynamic_pointer_cast<Lease>(lease);
 
 2266                                if (!lease_sync_filter_.shouldSync(lease)) {
 
 2271                                Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
 
 2272                                if (!existing_lease) {
 
 2274                                    LeaseMgrFactory::instance().addLease(lease);
 
 2275                                    ++applied_lease_count;
 
 2277                                } else if (existing_lease->cltt_ < lease->cltt_) {
 
 2283                                    Lease::syncCurrentExpirationTime(*existing_lease, *lease);
 
 2284                                    LeaseMgrFactory::instance().updateLease4(lease);
 
 2285                                    ++applied_lease_count;
 
 2288                                    LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
 
 2289                                        .arg(config_->getThisServerName())
 
 2290                                        .arg(lease->addr_.toText())
 
 2291                                        .arg(lease->subnet_id_);
 
 2295                                Lease6Ptr lease = Lease6::fromElement(*l);
 
 2300                                if ((leases_element.size() >= config_->getSyncPageLimit()) &&
 
 2301                                    (l + 1 == leases_element.end())) {
 
 2302                                    last_lease = boost::dynamic_pointer_cast<Lease>(lease);
 
 2305                                if (!lease_sync_filter_.shouldSync(lease)) {
 
 2310                                Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
 
 2312                                if (!existing_lease) {
 
 2314                                    LeaseMgrFactory::instance().addLease(lease);
 
 2315                                    ++applied_lease_count;
 
 2317                                } else if (existing_lease->cltt_ < lease->cltt_) {
 
 2323                                    Lease::syncCurrentExpirationTime(*existing_lease, *lease);
 
 2324                                    LeaseMgrFactory::instance().updateLease6(lease);
 
 2325                                    ++applied_lease_count;
 
 2328                                    LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
 
 2329                                        .arg(config_->getThisServerName())
 
 2330                                        .arg(lease->addr_.toText())
 
 2331                                        .arg(lease->subnet_id_);
 
 2335                        } catch (const std::exception& ex) {
 
 2336                            LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
 
 2337                                .arg(config_->getThisServerName())
 
 2343                    LOG_INFO(ha_logger, HA_LEASES_SYNC_APPLIED_LEASES)
 
 2344                        .arg(config_->getThisServerName())
 
 2345                        .arg(applied_lease_count);
 
 2347                } catch (
const std::exception& ex) {
 
 2348                    error_message = ex.what();
 
 2350                        .arg(
config_->getThisServerName())
 
 2351                        .arg(remote_config->getLogLabel())
 
 2352                        .arg(error_message);
 
 2358             if (!error_message.empty()) {
 
 2359                 communication_state_->setPartnerUnavailable();
 
 2361             } 
else if (last_lease) {
 
 2364                 asyncSyncLeases(http_client, remote_config, max_period, last_lease,
 
 2365                                 post_sync_action, dhcp_disabled);
 
 2370            if (post_sync_action) {
 
 2371                post_sync_action(error_message.empty(),
 
 2377        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 2378        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 2379        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 
 2386                              const unsigned int max_period) {
 
 2389        remote_config = 
config_->getPeerConfig(server_name);
 
 2390    } 
catch (
const std::exception& ex) {
 
 2394    if (remote_config->getName() == 
config_->getThisServerName()) {
 
 2396            + 
"' points to local server but should point to a partner"));
 
 2398    std::string answer_message;
 
 2399    int sync_status = 
synchronize(answer_message, remote_config, max_period);
 
 
 2406                       const unsigned int max_period) {
 
 2413                    [&](
const bool success, 
const std::string& error_message,
 
 2414                        const bool dhcp_disabled) {
 
 2419            status_message = error_message;
 
 2425        if (dhcp_disabled) {
 
 2431                                        [&](
const bool success,
 
 2432                                            const std::string& error_message,
 
 2439                                               [&](
const bool success,
 
 2440                                                   const std::string& error_message,
 
 2445                            if (!success && status_message.empty()) {
 
 2446                                status_message = error_message;
 
 2458                        if (!success && status_message.empty()) {
 
 2459                            status_message = error_message;
 
 2472                                       [&](
const bool success,
 
 2473                                           const std::string& error_message,
 
 2475                    if (!success && status_message.empty()) {
 
 2476                        status_message = error_message;
 
 2495        .arg(
config_->getThisServerName())
 
 2496        .arg(remote_config->getLogLabel());
 
 2510    io_service->stopAndPoll();
 
 2514    if (!status_message.empty()) {
 
 2518            .arg(
config_->getThisServerName())
 
 2519            .arg(remote_config->getLogLabel())
 
 2520            .arg(status_message);
 
 2527    status_message = 
"Lease database synchronization complete.";
 
 2531        .arg(
config_->getThisServerName())
 
 2532        .arg(remote_config->getLogLabel())
 
 
 2565    config->addBasicAuthHttpHeader(request);
 
 2566    request->setBodyAsJson(command);
 
 2567    request->finalize();
 
 2575        [
this, &http_client, 
config, post_request_action]
 
 2576            (
const boost::system::error_code& ec,
 
 2578             const std::string& error_str) {
 
 2581             std::string error_message;
 
 2583             if (ec || !error_str.empty()) {
 
 2584                 error_message = (ec ? ec.message() : error_str);
 
 2585                 LOG_WARN(ha_logger, HA_LEASES_BACKLOG_COMMUNICATIONS_FAILED)
 
 2586                     .arg(config_->getThisServerName())
 
 2587                     .arg(config->getLogLabel())
 
 2588                     .arg(ec ? ec.message() : error_str);
 
 2593                    auto args = verifyAsyncResponse(response, rcode);
 
 2594                 } catch (
const std::exception& ex) {
 
 2595                     error_message = ex.what();
 
 2597                         .arg(
config_->getThisServerName())
 
 2598                         .arg(
config->getLogLabel())
 
 2608             if (error_message.empty()) {
 
 2609                 asyncSendLeaseUpdatesFromBacklog(http_client, config, post_request_action);
 
 2611                 post_request_action(error_message.empty(), error_message, rcode);
 
 
 2619    if (num_updates == 0) {
 
 2621            .arg(
config_->getThisServerName());
 
 2627    auto remote_config = 
config_->getFailoverPeerConfig();
 
 2628    bool updates_successful = 
true;
 
 2631        .arg(
config_->getThisServerName())
 
 2633        .arg(remote_config->getName());
 
 2636                                     [&](
const bool success, 
const std::string&, 
const int) {
 
 2638        updates_successful = success;
 
 2652    io_service->stopAndPoll();
 
 2654    if (updates_successful) {
 
 2656            .arg(
config_->getThisServerName())
 
 2657            .arg(remote_config->getName())
 
 2658            .arg(stopwatch.logFormatLastDuration());
 
 2661    return (updates_successful);
 
 
 2675    config->addBasicAuthHttpHeader(request);
 
 2676    request->setBodyAsJson(command);
 
 2677    request->finalize();
 
 2685        [
this, 
config, post_request_action]
 
 2686            (
const boost::system::error_code& ec,
 
 2688             const std::string& error_str) {
 
 2691             std::string error_message;
 
 2693             if (ec || !error_str.empty()) {
 
 2694                 error_message = (ec ? ec.message() : error_str);
 
 2695                 LOG_WARN(ha_logger, HA_RESET_COMMUNICATIONS_FAILED)
 
 2696                     .arg(config_->getThisServerName())
 
 2697                     .arg(config->getLogLabel())
 
 2698                     .arg(ec ? ec.message() : error_str);
 
 2703                    auto args = verifyAsyncResponse(response, rcode);
 
 2704                 } catch (
const std::exception& ex) {
 
 2705                     error_message = ex.what();
 
 2707                         .arg(
config_->getThisServerName())
 
 2708                         .arg(
config->getLogLabel())
 
 2713             post_request_action(error_message.empty(), error_message, rcode);
 
 
 2721    auto remote_config = 
config_->getFailoverPeerConfig();
 
 2722    bool reset_successful = 
true;
 
 2725                     [&](
const bool success, 
const std::string&, 
const int) {
 
 2727        reset_successful = success;
 
 2735    io_service->stopAndPoll();
 
 2737    return (reset_successful);
 
 
 2746    } 
catch (
const std::exception& ex) {
 
 
 2766                                 " maintenance for the server not in the" 
 2767                                 " in-maintenance state."));
 
 2805                             "Unable to transition the server from the " 
 2807                             " in-maintenance state."));
 
 
 2824                             " partner-in-maintenance state."));
 
 2836    remote_config->addBasicAuthHttpHeader(request);
 
 2839    request->finalize();
 
 2848    boost::system::error_code captured_ec;
 
 2849    std::string captured_error_message;
 
 2850    int captured_rcode = 0;
 
 2854                            remote_config->getTlsContext(),
 
 2856        [
this, remote_config, &io_service, &captured_ec, &captured_error_message,
 
 2858            (
const boost::system::error_code& ec,
 
 2860             const std::string& error_str) {
 
 2870             std::string error_message;
 
 2873             if (ec || !error_str.empty()) {
 
 2874                 error_message = (ec ? ec.message() : error_str);
 
 2875                 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_COMMUNICATIONS_FAILED)
 
 2876                     .arg(config_->getThisServerName())
 
 2877                     .arg(remote_config->getLogLabel())
 
 2878                     .arg(error_message);
 
 2884                     static_cast<void>(verifyAsyncResponse(response, captured_rcode));
 
 2886                 } catch (
const std::exception& ex) {
 
 2887                     error_message = ex.what();
 
 2889                         .arg(
config_->getThisServerName())
 
 2890                         .arg(remote_config->getLogLabel())
 
 2891                         .arg(error_message);
 
 2897             if (!error_message.empty()) {
 
 2898                 communication_state_->setPartnerUnavailable();
 
 2902             captured_error_message = error_message;
 
 2905        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 2906        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 2907        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 2916    io_service->stopAndPoll();
 
 2921        postNextEvent(HA_MAINTENANCE_START_EVT);
 
 2922        verboseTransition(HA_PARTNER_DOWN_ST);
 
 2925                             "Server is now in the partner-down state as its" 
 2926                             " partner appears to be offline for maintenance."));
 
 2932        postNextEvent(HA_MAINTENANCE_START_EVT);
 
 2933        verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST);
 
 2940                             " partner-in-maintenance state. The partner server responded" 
 2941                             " with the following message to the ha-maintenance-notify" 
 2942                             " command: " + captured_error_message + 
"."));
 
 2947                         "Server is now in the partner-in-maintenance state" 
 2948                         " and its partner is in-maintenance state. The partner" 
 2949                         " can be now safely shut down."));
 
 
 2956                             " request because the server is not in the" 
 2957                             " partner-in-maintenance state."));
 
 2971    remote_config->addBasicAuthHttpHeader(request);
 
 2976    request->finalize();
 
 2985    std::string error_message;
 
 2989                            remote_config->getTlsContext(),
 
 2991        [
this, remote_config, &io_service, &error_message]
 
 2992            (
const boost::system::error_code& ec,
 
 2994             const std::string& error_str) {
 
 2999             if (ec || !error_str.empty()) {
 
 3000                 error_message = (ec ? ec.message() : error_str);
 
 3001                 LOG_ERROR(ha_logger, HA_MAINTENANCE_NOTIFY_CANCEL_COMMUNICATIONS_FAILED)
 
 3002                     .arg(config_->getThisServerName())
 
 3003                     .arg(remote_config->getLogLabel())
 
 3004                     .arg(error_message);
 
 3011                     ConstElementPtr args = verifyAsyncResponse(response, rcode);
 
 3016                     communication_state_->setPartnerUnavailable();
 
 3020                     if (args && args->getType() == Element::map) {
 
 3022                         ConstElementPtr state = args->get(
"state");
 
 3024                             if (state->getType() != Element::string) {
 
 3025                                 isc_throw(CtrlChannelError, 
"server state not returned in response" 
 3026                                           " to a ha-heartbeat command or it is not a string");
 
 3028                             communication_state_->setPartnerState(state->stringValue());
 
 3031                 } catch (
const std::exception& ex) {
 
 3032                     error_message = ex.what();
 
 3034                         .arg(
config_->getThisServerName())
 
 3035                         .arg(remote_config->getLogLabel())
 
 3036                         .arg(error_message);
 
 3042             if (!error_message.empty()) {
 
 3043                 communication_state_->setPartnerUnavailable();
 
 3047        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 3048        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 3049        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 3058    io_service->stopAndPoll();
 
 3062    if (!error_message.empty()) {
 
 3064                             "Unable to cancel maintenance. The partner server responded" 
 3065                             " with the following message to the ha-maintenance-notify" 
 3066                             " command: " + error_message + 
"."));
 
 3072    postNextEvent(HA_MAINTENANCE_CANCEL_EVT);
 
 3073    verboseTransition(next_state);
 
 3077                         "Server maintenance successfully canceled."));
 
 
 3089    remote_config->addBasicAuthHttpHeader(request);
 
 3093    request->finalize();
 
 3101                                 remote_config->getTlsContext(),
 
 3103        [
this, remote_config, post_request_action]
 
 3104            (
const boost::system::error_code& ec,
 
 3106             const std::string& error_str) {
 
 3115             std::string error_message;
 
 3118             if (ec || !error_str.empty()) {
 
 3119                 error_message = (ec ? ec.message() : error_str);
 
 3120                 LOG_ERROR(ha_logger, HA_SYNC_COMPLETE_NOTIFY_COMMUNICATIONS_FAILED)
 
 3121                     .arg(config_->getThisServerName())
 
 3122                     .arg(remote_config->getLogLabel())
 
 3123                     .arg(error_message);
 
 3129                     static_cast<void>(verifyAsyncResponse(response, rcode));
 
 3131                 } catch (
const CommandUnsupportedError& ex) {
 
 3134                 } 
catch (
const std::exception& ex) {
 
 3135                     error_message = ex.what();
 
 3137                         .arg(
config_->getThisServerName())
 
 3138                         .arg(remote_config->getLogLabel())
 
 3139                         .arg(error_message);
 
 3145             if (!error_message.empty()) {
 
 3146                 communication_state_->setPartnerUnavailable();
 
 3150             if (post_request_action) {
 
 3151                 post_request_action(error_message.empty(),
 
 3157        std::bind(&HAService::clientConnectHandler, 
this, ph::_1, ph::_2),
 
 3158        std::bind(&HAService::clientHandshakeHandler, 
this, ph::_1),
 
 3159        std::bind(&HAService::clientCloseHandler, 
this, ph::_1)
 
 
 3181                         "Server successfully notified about the synchronization completion."));
 
 
 3190        boost::dynamic_pointer_cast<HttpResponseJson>(response);
 
 3191    if (!json_response) {
 
 3220    if (body->empty()) {
 
 3231    std::ostringstream s;
 
 3240            s << args->stringValue() << 
" (";
 
 3243        s << 
"error code " << rcode << 
")";
 
 3248        isc_throw(CommandUnsupportedError, s.str());
 
 3256            auto failed_leases = args->get(
"failed-leases");
 
 3257            if (!failed_leases || (failed_leases->getType() != 
Element::list)) {
 
 3261            auto conflict = 
false;
 
 3263            for (
unsigned i = 0; i < failed_leases->size(); ++i) {
 
 3264                auto lease = failed_leases->get(i);
 
 3268                auto result = lease->get(
"result");
 
 3272                auto error_message = lease->get(
"error-message");
 
 3275                    if (error_message && error_message->getType()) {
 
 3276                        s << error_message->stringValue() << 
" (";
 
 3278                    s << 
"error code " << result->intValue() << 
")";
 
 3286                    conflict_error_message = error_message;
 
 3292                if (conflict_error_message &&
 
 3294                    s << conflict_error_message->stringValue() << 
" (";
 
 
 3312    if (
client_->getThreadIOService()) {
 
 3320    if ((!ec || (ec.value() == boost::asio::error::in_progress))
 
 3321        && (tcp_native_fd >= 0)) {
 
 
 3344    client_->closeIfOutOfBand(tcp_native_fd);
 
 
 3349    if (tcp_native_fd >= 0) {
 
 
 3357        std::lock_guard<std::mutex> lock(mutex_);
 
 3358        return (pending_requests_.size());
 
 3360        return (pending_requests_.size());
 
 
 3364template<
typename QueryPtrType>
 
 3368        std::lock_guard<std::mutex> lock(mutex_);
 
 3369        return (getPendingRequestInternal(query));
 
 3371        return (getPendingRequestInternal(query));
 
 
 3375template<
typename QueryPtrType>
 
 3377HAService::getPendingRequestInternal(
const QueryPtrType& query) {
 
 3378    if (pending_requests_.count(query) == 0) {
 
 3381        return (pending_requests_[query]);
 
 3402            .arg(
config_->getThisServerName())
 
 3407    } 
catch (
const std::exception& ex) {
 
 3409            .arg(
config_->getThisServerName())
 
 
 3443    } 
catch (
const std::exception& ex) {
 
 
 3461    } 
catch (std::exception& ex) {
 
 3463            .arg(
config_->getThisServerName())
 
 
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.
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.
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...
void deleteExternalSocket(int socketfd)
Deletes external socket.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
static data::ConstElementPtr createLease4Delete(const dhcp::Lease4 &lease4)
Creates lease4-del command.
static data::ConstElementPtr createHeartbeat(const std::string &server_name, const HAServerType &server_type)
Creates ha-heartbeat command for DHCP server.
static std::unordered_set< std::string > ha_commands4_
List of commands used by the High Availability in v4.
static data::ConstElementPtr createLease4Update(const dhcp::Lease4 &lease4)
Creates lease4-update command.
static data::ConstElementPtr createSyncCompleteNotify(const unsigned int origin_id, const std::string &server_name, const HAServerType &server_type)
Creates ha-sync-complete-notify command.
static data::ConstElementPtr createLease6BulkApply(const dhcp::Lease6CollectionPtr &leases, const dhcp::Lease6CollectionPtr &deleted_leases)
Creates lease6-bulk-apply command.
static data::ConstElementPtr createLease6GetPage(const dhcp::Lease6Ptr &lease6, const uint32_t limit)
Creates lease6-get-page command.
static data::ConstElementPtr createDHCPDisable(const unsigned int origin_id, const unsigned int max_period, const HAServerType &server_type)
Creates dhcp-disable command for DHCP server.
static data::ConstElementPtr createDHCPEnable(const unsigned int origin_id, const HAServerType &server_type)
Creates dhcp-enable command for DHCP server.
static data::ConstElementPtr createMaintenanceNotify(const std::string &server_name, const bool cancel, const int state, const HAServerType &server_type)
Creates ha-maintenance-notify command.
static std::unordered_set< std::string > ha_commands6_
List of commands used by the High Availability in v6.
static data::ConstElementPtr createHAReset(const std::string &server_name, const HAServerType &server_type)
Creates ha-reset command.
static data::ConstElementPtr createLease4GetPage(const dhcp::Lease4Ptr &lease4, const uint32_t limit)
Creates lease4-get-page command.
Holds communication state between DHCPv4 servers.
Holds communication state between DHCPv6 servers.
Role
Server's role in the High Availability setup.
static std::string roleToString(const HAConfig::PeerConfig::Role &role)
Returns role name.
std::map< std::string, PeerConfigPtr > PeerConfigMap
Map of the servers' configurations.
static std::string HAModeToString(const HAMode &ha_mode)
Returns HA mode name.
boost::shared_ptr< PeerConfig > PeerConfigPtr
Pointer to the server's configuration.
static const int HA_MAINTENANCE_START_EVT
ha-maintenance-start command received.
bool inScope(dhcp::Pkt4Ptr &query4)
Checks if the DHCPv4 query should be processed by this server.
void adjustNetworkState()
Enables or disables network state depending on the served scopes.
void stopClientAndListener()
Stop the client and(or) listener instances.
int getNormalState() const
Returns normal operation state for the current configuration.
bool shouldQueueLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be queued.
static const int HA_HEARTBEAT_COMPLETE_EVT
Finished heartbeat command.
void asyncSendHAReset(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Sends ha-reset command to partner asynchronously.
bool clientConnectHandler(const boost::system::error_code &ec, int tcp_native_fd)
HttpClient connect callback handler.
void asyncSyncLeases()
Asynchronously reads leases from a peer and updates local lease database.
bool isMaintenanceCanceled() const
Convenience method checking if the current state is a result of canceling the maintenance.
data::ConstElementPtr processMaintenanceCancel()
Processes ha-maintenance-cancel command and returns a response.
void checkPermissionsClientAndListener()
Check client and(or) listener current thread permissions to perform thread pool state transition.
bool shouldReclaim(const dhcp::Lease4Ptr &lease4) const
Checks if the lease should be reclaimed by this server.
void asyncSendLeaseUpdate(const QueryPtrType &query, const HAConfig::PeerConfigPtr &config, const data::ConstElementPtr &command, const hooks::ParkingLotHandlePtr &parking_lot)
Asynchronously sends lease update to the peer.
void verboseTransition(const unsigned state)
Transitions to a desired state and logs it.
bool sendLeaseUpdatesFromBacklog()
Attempts to send all lease updates from the backlog synchronously.
config::CmdHttpListenerPtr listener_
HTTP listener instance used to receive and respond to HA commands and lease updates.
void clientCloseHandler(int tcp_native_fd)
HttpClient close callback handler.
bool leaseUpdateComplete(QueryPtrType &query, const hooks::ParkingLotHandlePtr &parking_lot)
Handle last pending request for this query.
HAConfigPtr config_
Pointer to the HA hooks library configuration.
data::ConstElementPtr processMaintenanceStart()
Processes ha-maintenance-start command and returns a response.
unsigned int id_
Unique service id.
HAServerType server_type_
DHCP server type.
bool sync_complete_notified_
An indicator that a partner sent ha-sync-complete-notify command.
bool shouldTerminate() const
Indicates if the server should transition to the terminated state.
data::ConstElementPtr processScopes(const std::vector< std::string > &scopes)
Processes ha-scopes command and returns a response.
dhcp::NetworkStatePtr network_state_
Pointer to the state of the DHCP service (enabled/disabled).
data::ConstElementPtr processSynchronize(const std::string &server_name, const unsigned int max_period)
Processes ha-sync command and returns a response.
void scheduleHeartbeat()
Schedules asynchronous heartbeat to a peer if it is not scheduled.
void asyncSyncCompleteNotify(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Schedules asynchronous "ha-sync-complete-notify" command to the specified server.
QueryFilter query_filter_
Selects queries to be processed/dropped.
static const int HA_MAINTENANCE_NOTIFY_EVT
ha-maintenance-notify command received.
static const int HA_SYNCED_PARTNER_UNAVAILABLE_EVT
The heartbeat command failed after receiving ha-sync-complete-notify command from the partner.
data::ConstElementPtr processMaintenanceNotify(const bool cancel, const std::string &state)
Processes ha-maintenance-notify command and returns a response.
void conditionalLogPausedState() const
Logs if the server is paused in the current state.
bool unpause()
Unpauses the HA state machine with logging.
static const int HA_CONTROL_RESULT_MAINTENANCE_NOT_ALLOWED
Control result returned in response to ha-maintenance-notify.
void serveDefaultScopes()
Instructs the HA service to serve default scopes.
size_t asyncSendLeaseUpdates(const dhcp::Pkt4Ptr &query, const dhcp::Lease4CollectionPtr &leases, const dhcp::Lease4CollectionPtr &deleted_leases, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules asynchronous IPv4 leases updates.
size_t pendingRequestSize()
Get the number of entries in the pending request map.
static const int HA_SYNCING_SUCCEEDED_EVT
Lease database synchronization succeeded.
bool sendHAReset()
Sends ha-reset command to partner synchronously.
std::function< void(const bool, const std::string &, const int)> PostRequestCallback
Callback invoked when request was sent and a response received or an error occurred.
asiolink::IOServicePtr io_service_
Pointer to the IO service object shared between this hooks library and the DHCP server.
void localDisableDHCPService()
Disables local DHCP service.
CommunicationStatePtr communication_state_
Holds communication state with a peer.
void logFailedLeaseUpdates(const dhcp::PktPtr &query, const data::ConstElementPtr &args) const
Log failed lease updates.
LeaseUpdateBacklog lease_update_backlog_
Backlog of DHCP lease updates.
virtual ~HAService()
Destructor.
static const int HA_SYNCING_FAILED_EVT
Lease database synchronization failed.
static const int HA_MAINTENANCE_CANCEL_EVT
ha-maintenance-cancel command received.
void asyncSendLeaseUpdatesFromBacklog(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Sends lease updates from backlog to partner asynchronously.
data::ConstElementPtr processHeartbeat()
Processes ha-heartbeat command and returns a response.
void asyncSyncLeasesInternal(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period, const dhcp::LeasePtr &last_lease, PostSyncCallback post_sync_action, const bool dhcp_disabled)
Implements fetching one page of leases during synchronization.
data::ConstElementPtr processHAReset()
Processes ha-reset command and returns a response.
size_t asyncSendSingleLeaseUpdate(const dhcp::Pkt4Ptr &query, const dhcp::Lease4Ptr &lease, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules an asynchronous IPv4 lease update.
void asyncSendHeartbeat()
Starts asynchronous heartbeat to a peer.
bool isPartnerStateInvalid() const
Indicates if the partner's state is invalid.
void startClientAndListener()
Start the client and(or) listener instances.
data::ConstElementPtr verifyAsyncResponse(const http::HttpResponsePtr &response, int &rcode)
Checks if the response is valid or contains an error.
void resumeClientAndListener()
Resumes client and(or) listener thread pool operations.
data::ConstElementPtr processStatusGet() const
Processes status-get command and returns a response.
int getPendingRequest(const QueryPtrType &query)
Get the number of scheduled requests for a given query.
LeaseSyncFilter lease_sync_filter_
Lease synchronization filter used in hub-and-spoke model.
int synchronize(std::string &status_message, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period)
Synchronizes lease database with a partner.
bool shouldSendLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be sent as result of leases allocation or release.
void serveFailoverScopes()
Instructs the HA service to serve failover scopes.
void localEnableDHCPService()
Enables local DHCP service.
static const int HA_LEASE_UPDATES_COMPLETE_EVT
Finished lease updates commands.
HAService(const unsigned int id, const asiolink::IOServicePtr &io_service, const dhcp::NetworkStatePtr &network_state, const HAConfigPtr &config, const HAServerType &server_type=HAServerType::DHCPv4)
Constructor.
void socketReadyHandler(int tcp_native_fd)
IfaceMgr external socket ready callback handler.
http::HttpClientPtr client_
HTTP client instance used to send HA commands and lease updates.
void updatePendingRequest(QueryPtrType &query)
Update pending request counter for this query.
bool shouldPartnerDown() const
Indicates if the server should transition to the partner down state.
void startHeartbeat()
Unconditionally starts one heartbeat to a peer.
data::ConstElementPtr processSyncCompleteNotify(const unsigned int origin_id)
Process ha-sync-complete-notify command and returns a response.
data::ConstElementPtr processContinue()
Processes ha-continue command and returns a response.
void asyncDisableDHCPService(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, const unsigned int max_period, PostRequestCallback post_request_action)
Schedules asynchronous "dhcp-disable" command to the specified server.
void pauseClientAndListener()
Pauses client and(or) listener thread pool operations.
std::function< void(const bool, const std::string &, const bool)> PostSyncCallback
Callback invoked when lease database synchronization is complete.
static const int HA_WAITING_TO_TERMINATED_ST_DELAY_MINUTES
A delay in minutes to transition from the waiting to terminated state when the partner remains in ter...
void asyncEnableDHCPService(http::HttpClient &http_client, const HAConfig::PeerConfigPtr &remote_config, PostRequestCallback post_request_action)
Schedules asynchronous "dhcp-enable" command to the specified server.
OpType
Type of the lease update (operation type).
bool inScope(const dhcp::Pkt4Ptr &query4, std::string &scope_class) const
Checks if this server should process the DHCPv4 query.
void stop()
Halts client-side IO activity.
void asyncSendRequest(const Url &url, const asiolink::TlsContextPtr &tls_context, const HttpRequestPtr &request, const HttpResponsePtr &response, const RequestHandler &request_callback, const RequestTimeout &request_timeout=RequestTimeout(10000), const ConnectHandler &connect_callback=ConnectHandler(), const HandshakeHandler &handshake_callback=HandshakeHandler(), const CloseHandler &close_callback=CloseHandler())
Queues new asynchronous HTTP request for a given URL.
This class parses and generates time values used in HTTP.
std::string rfc1123Format() const
Returns time value formatted as specified in RFC 1123.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
void removeCriticalSectionCallbacks(const std::string &name)
Removes the set of callbacks associated with a given name from the list of CriticalSection callbacks.
void addCriticalSectionCallbacks(const std::string &name, const CSCallbackSet::Callback &check_cb, const CSCallbackSet::Callback &entry_cb, const CSCallbackSet::Callback &exit_cb)
Adds a set of callbacks to the list of CriticalSection callbacks.
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.
virtual void runModel(unsigned int event)
Processes events through the 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.
const StatePtr getState(unsigned int value)
Fetches the state referred to by value.
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 getPrevState() const
Fetches the model's previous state.
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< 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< 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 const 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.