From: Francis Dupont Date: Wed, 5 Apr 2023 19:23:11 +0000 (+0200) Subject: [#2757] Rebased from #275[23] X-Git-Tag: Kea-2.3.8~101 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=acbfbe1498a374b17dccfd4ca40efbf0062f1bba;p=thirdparty%2Fkea.git [#2757] Rebased from #275[23] --- diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.cc b/src/lib/dhcpsrv/dhcpsrv_messages.cc index 40de1c65d9..7056296e94 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.cc +++ b/src/lib/dhcpsrv/dhcpsrv_messages.cc @@ -192,6 +192,9 @@ extern const isc::log::MessageID DHCPSRV_MYSQL_START_TRANSACTION = "DHCPSRV_MYSQ extern const isc::log::MessageID DHCPSRV_MYSQL_TLS_CIPHER = "DHCPSRV_MYSQL_TLS_CIPHER"; extern const isc::log::MessageID DHCPSRV_MYSQL_UPDATE_ADDR4 = "DHCPSRV_MYSQL_UPDATE_ADDR4"; extern const isc::log::MessageID DHCPSRV_MYSQL_UPDATE_ADDR6 = "DHCPSRV_MYSQL_UPDATE_ADDR6"; +extern const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4 = "DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4"; +extern const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_ERROR = "DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_ERROR"; +extern const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_PAGE = "DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_PAGE"; extern const isc::log::MessageID DHCPSRV_NOTYPE_DB = "DHCPSRV_NOTYPE_DB"; extern const isc::log::MessageID DHCPSRV_NO_SOCKETS_OPEN = "DHCPSRV_NO_SOCKETS_OPEN"; extern const isc::log::MessageID DHCPSRV_OPEN_SOCKET_FAIL = "DHCPSRV_OPEN_SOCKET_FAIL"; @@ -243,6 +246,9 @@ extern const isc::log::MessageID DHCPSRV_PGSQL_START_TRANSACTION = "DHCPSRV_PGSQ extern const isc::log::MessageID DHCPSRV_PGSQL_TLS_SUPPORT = "DHCPSRV_PGSQL_TLS_SUPPORT"; extern const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR4 = "DHCPSRV_PGSQL_UPDATE_ADDR4"; extern const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR6 = "DHCPSRV_PGSQL_UPDATE_ADDR6"; +extern const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4 = "DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4"; +extern const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR = "DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR"; +extern const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE = "DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE"; extern const isc::log::MessageID DHCPSRV_QUEUE_NCR = "DHCPSRV_QUEUE_NCR"; extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_FAILED = "DHCPSRV_QUEUE_NCR_FAILED"; extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_SKIP = "DHCPSRV_QUEUE_NCR_SKIP"; @@ -457,6 +463,9 @@ const char* values[] = { "DHCPSRV_MYSQL_TLS_CIPHER", "TLS cipher: %1", "DHCPSRV_MYSQL_UPDATE_ADDR4", "updating IPv4 lease for address %1", "DHCPSRV_MYSQL_UPDATE_ADDR6", "updating IPv6 lease for address %1, lease type %2", + "DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4", "upgrading IPv4 leases done in %1 pages with %2 updated leases", + "DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_ERROR", "upgrading extending info for IPv4 lease at %1 failed with %2", + "DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_PAGE", "upgrading IPv4 lease extended info at page %1 starting at %2 (updated %3)", "DHCPSRV_NOTYPE_DB", "no 'type' keyword to determine database backend: %1", "DHCPSRV_NO_SOCKETS_OPEN", "no interface configured to listen to DHCP traffic", "DHCPSRV_OPEN_SOCKET_FAIL", "failed to open socket: %1", @@ -508,6 +517,9 @@ const char* values[] = { "DHCPSRV_PGSQL_TLS_SUPPORT", "Attempt to configure TLS: %1", "DHCPSRV_PGSQL_UPDATE_ADDR4", "updating IPv4 lease for address %1", "DHCPSRV_PGSQL_UPDATE_ADDR6", "updating IPv6 lease for address %1, lease type %2", + "DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4", "upgrading IPv4 leases done in %1 pages with %2 updated leases", + "DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR", "upgrading extending info for IPv4 lease at %1 failed with %2", + "DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE", "upgrading IPv4 lease extended info at page %1 starting at %2 (updated %3)", "DHCPSRV_QUEUE_NCR", "%1: Name change request to %2 DNS entry queued: %3", "DHCPSRV_QUEUE_NCR_FAILED", "%1: queuing %2 name change request failed for lease %3: %4", "DHCPSRV_QUEUE_NCR_SKIP", "%1: skip queuing name change request for lease: %2", diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.h b/src/lib/dhcpsrv/dhcpsrv_messages.h index 3d2db5ba9d..39c56744b2 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.h +++ b/src/lib/dhcpsrv/dhcpsrv_messages.h @@ -193,6 +193,9 @@ extern const isc::log::MessageID DHCPSRV_MYSQL_START_TRANSACTION; extern const isc::log::MessageID DHCPSRV_MYSQL_TLS_CIPHER; extern const isc::log::MessageID DHCPSRV_MYSQL_UPDATE_ADDR4; extern const isc::log::MessageID DHCPSRV_MYSQL_UPDATE_ADDR6; +extern const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4; +extern const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_ERROR; +extern const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_PAGE; extern const isc::log::MessageID DHCPSRV_NOTYPE_DB; extern const isc::log::MessageID DHCPSRV_NO_SOCKETS_OPEN; extern const isc::log::MessageID DHCPSRV_OPEN_SOCKET_FAIL; @@ -244,6 +247,9 @@ extern const isc::log::MessageID DHCPSRV_PGSQL_START_TRANSACTION; extern const isc::log::MessageID DHCPSRV_PGSQL_TLS_SUPPORT; extern const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR4; extern const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR6; +extern const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4; +extern const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR; +extern const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE; extern const isc::log::MessageID DHCPSRV_QUEUE_NCR; extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_FAILED; extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_SKIP; diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index 1f3dc0737c..9037820ab9 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -976,6 +976,19 @@ lease from the MySQL database for the specified address. A debug message issued when the server is attempting to update IPv6 lease from the MySQL database for the specified address. +% DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4 upgrading IPv4 leases done in %1 pages with %2 updated leases +The server upgraded extended info. The number of pages and the final count of +updated leases are displayed. + +% DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_ERROR upgrading extending info for IPv4 lease at %1 failed with %2 +A debug message issued when the server failed to upgrade an extended info. +The address of the lease and the error message are displayed. + +% DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_PAGE upgrading IPv4 lease extended info at page %1 starting at %2 (updated %3) +A debug message issued when the server upgrades IPv4 lease extended info. +The page number and started address, and the count of already updated leases +are displayed. + % DHCPSRV_NOTYPE_DB no 'type' keyword to determine database backend: %1 This is an error message, logged when an attempt has been made to access a database backend, but where no 'type' keyword has been included in @@ -1221,6 +1234,19 @@ lease from the PostgreSQL database for the specified address. A debug message issued when the server is attempting to update IPv6 lease from the PostgreSQL database for the specified address. +% DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4 upgrading IPv4 leases done in %1 pages with %2 updated leases +The server upgraded extended info. The number of pages and the final count of +updated leases are displayed. + +% DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR upgrading extending info for IPv4 lease at %1 failed with %2 +A debug message issued when the server failed to upgrade an extended info. +The address of the lease and the error message are displayed. + +% DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE upgrading IPv4 lease extended info at page %1 starting at %2 (updated %3) +A debug message issued when the server upgrades IPv4 lease extended info. +The page number and started address, and the count of already updated leases +are displayed. + % DHCPSRV_QUEUE_NCR %1: Name change request to %2 DNS entry queued: %3 A debug message which is logged when the NameChangeRequest to add or remove a DNS entries for a particular lease has been queued. The first argument diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h index 94be5d6a30..fe42783cf9 100644 --- a/src/lib/dhcpsrv/lease_mgr.h +++ b/src/lib/dhcpsrv/lease_mgr.h @@ -960,6 +960,12 @@ public: /// @param filename File name to write leases. virtual void writeLeases6(const std::string& filename) = 0; + /// @brief Upgrade extended info (v4). + /// + /// @param page_size The page size used for retrieval. + /// @return The number of updates in the database. + virtual size_t upgradeExtendedInfo(const LeasePageSize& page_size) = 0; + /// @brief Returns the setting indicating if lease extended info tables /// are enabled. /// diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index b94c1593d8..5b5c7df041 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -3032,6 +3032,11 @@ Memfile_LeaseMgr::extractExtendedInfo4(bool update, bool current) { return (updated); } +size_t +Memfile_LeaseMgr::upgradeExtendedInfo(const LeasePageSize& /* page_size */) { + return (0); +} + size_t Memfile_LeaseMgr::buildExtendedInfoTables6Internal(bool update, bool current) { CfgConsistencyPtr cfg; diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 0a88b31b64..15c06f0314 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -1508,6 +1508,12 @@ public: /// @param filename File name to write leases. virtual void writeLeases6(const std::string& filename) override; + /// @brief Upgrade extended info (v4). + /// + /// @param page_size The page size used for retrieval. + /// @return Always return 0. + virtual size_t upgradeExtendedInfo(const LeasePageSize& page_size) override; + protected: /// Extended information / Bulk Lease Query shared interface. diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index f26c7cedf1..11df3850af 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -162,6 +162,15 @@ tagged_statements = { { "WHERE address > ? " "ORDER BY address " "LIMIT ?"}, + {MySqlLeaseMgr::GET_LEASE4_UCTX_PAGE, + "SELECT address, hwaddr, client_id, " + "valid_lifetime, expire, subnet_id, " + "fqdn_fwd, fqdn_rev, hostname, " + "state, user_context, relay_id, remote_id " + "FROM lease4 " + "WHERE address > ? AND user_context IS NOT NULL " + "ORDER BY address " + "LIMIT ?"}, {MySqlLeaseMgr::GET_LEASE4_SUBID, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " @@ -330,6 +339,17 @@ tagged_statements = { { "WHERE address > ? " "ORDER BY address " "LIMIT ?"}, + {MySqlLeaseMgr::GET_LEASE6_UCTX_PAGE, + "SELECT address, duid, valid_lifetime, " + "expire, subnet_id, pref_lifetime, " + "lease_type, iaid, prefix_len, " + "fqdn_fwd, fqdn_rev, hostname, " + "hwaddr, hwtype, hwaddr_source, " + "state, user_context " + "FROM lease6 " + "WHERE address > ? AND user_context IS NOT NULL " + "ORDER BY address " + "LIMIT ?"}, {MySqlLeaseMgr::GET_LEASE6_SUBID, "SELECT address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " @@ -3875,6 +3895,95 @@ MySqlLeaseMgr::getLeases4ByRemoteId(const OptionBuffer& remote_id, return (result); } +size_t +MySqlLeaseMgr::upgradeExtendedInfo(const LeasePageSize& page_size) { + auto check = CfgMgr::instance().getCurrentCfg()-> + getConsistency()->getExtendedInfoSanityCheck(); + + size_t pages = 0; + size_t updated = 0; + IOAddress start_addr = IOAddress::IPV4_ZERO_ADDRESS(); + for (;;) { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, + DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_PAGE) + .arg(pages) + .arg(start_addr.toText()) + .arg(updated); + + // Prepare WHERE clause. + MYSQL_BIND inbind[2]; + memset(inbind, 0, sizeof(inbind)); + + // Bind start address. + uint32_t start_addr_data = start_addr.toUint32(); + inbind[0].buffer_type = MYSQL_TYPE_LONG; + inbind[0].buffer = reinterpret_cast(&start_addr_data); + inbind[0].is_unsigned = MLM_TRUE; + + // Bind page size value. + uint32_t ps = static_cast(page_size.page_size_); + inbind[1].buffer_type = MYSQL_TYPE_LONG; + inbind[1].buffer = reinterpret_cast(&ps); + inbind[1].is_unsigned = MLM_TRUE; + + Lease4Collection leases; + + // Get a context. + { + MySqlLeaseContextAlloc get_context(*this); + MySqlLeaseContextPtr ctx = get_context.ctx_; + + getLeaseCollection(ctx, GET_LEASE4_UCTX_PAGE, inbind, leases); + } + + if (leases.empty()) { + // Done. + break; + } + + ++pages; + start_addr = leases.back()->addr_; + for (auto lease : leases) { + ConstElementPtr previous_user_context = lease->getContext(); + vector previous_relay_id = lease->relay_id_; + vector previous_remote_id = lease->remote_id_; + if (!previous_user_context && + previous_relay_id.empty() && + previous_remote_id.empty()) { + continue; + } + bool modified = upgradeLease4ExtendedInfo(lease, check); + try { + lease->relay_id_.clear(); + lease->remote_id_.clear(); + extractLease4ExtendedInfo(lease, false); + if (modified || + (previous_relay_id != lease->relay_id_) || + (previous_remote_id != lease->remote_id_)) { + updateLease4(lease); + ++updated; + } + } catch (const NoSuchLease&) { + // The lease was modified in parallel: + // as its extended info was processed just ignore. + continue; + } catch (const std::exception& ex) { + // Something when wrong, for instance extract failed. + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, + DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_ERROR) + .arg(lease->addr_.toText()) + .arg(ex.what()); + } + } + } + + LOG_INFO(dhcpsrv_logger, DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4) + .arg(pages) + .arg(updated); + + return (updated); +} + Lease6Collection MySqlLeaseMgr::getLeases6ByRelayId(const DUID& /* relay_id */, const IOAddress& /* link_addr */, diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h index 26a83fc675..ba9f677368 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.h +++ b/src/lib/dhcpsrv/mysql_lease_mgr.h @@ -702,6 +702,7 @@ public: GET_LEASE4_HWADDR, // Get lease4 by HW address GET_LEASE4_HWADDR_SUBID, // Get lease4 by HW address & subnet ID GET_LEASE4_PAGE, // Get page of leases beginning with an address + GET_LEASE4_UCTX_PAGE, // Get page of leases with user context GET_LEASE4_SUBID, // Get IPv4 leases by subnet ID GET_LEASE4_HOSTNAME, // Get IPv4 leases by hostname GET_LEASE4_EXPIRE, // Get lease4 by expiration. @@ -718,6 +719,7 @@ public: GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID GET_LEASE6_PAGE, // Get page of leases beginning with an address + GET_LEASE6_UCTX_PAGE, // Get page of leases with user context GET_LEASE6_SUBID, // Get IPv6 leases by subnet ID GET_LEASE6_DUID, // Get IPv6 leases by DUID GET_LEASE6_HOSTNAME, // Get IPv6 leases by hostname @@ -1119,6 +1121,12 @@ private: const asiolink::IOAddress& lower_bound_address, const LeasePageSize& page_size) override; + /// @brief Upgrade extended info (v4). + /// + /// @param page_size The page size used for retrieval. + /// @return The number of updates in the database. + virtual size_t upgradeExtendedInfo(const LeasePageSize& page_size) override; + /// @brief Build extended info v6 tables. /// /// @param update Update extended info in database. diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.cc b/src/lib/dhcpsrv/pgsql_lease_mgr.cc index 2f590f8396..dace3eff89 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.cc +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.cc @@ -134,6 +134,18 @@ PgSqlTaggedStatement tagged_statements[] = { "ORDER BY address " "LIMIT $2"}, + // GET_LEASE4_UCTX_PAGE + { 2, { OID_INT8, OID_INT8 }, + "get_lease4_uctx_page", + "SELECT address, hwaddr, client_id, " + "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " + "fqdn_fwd, fqdn_rev, hostname, " + "state, user_context, relay_id, remote_id " + "FROM lease4 " + "WHERE address > $1 AND user_context IS NOT NULL " + "ORDER BY address " + "LIMIT $2"}, + // GET_LEASE4_SUBID { 1, { OID_INT8 }, "get_lease4_subid", @@ -335,6 +347,19 @@ PgSqlTaggedStatement tagged_statements[] = { "ORDER BY address " "LIMIT $2"}, + // GET_LEASE6_UCTX_PAGE + { 2, { OID_VARCHAR, OID_INT8 }, + "get_lease6_uctx_page", + "SELECT address, duid, valid_lifetime, " + "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, " + "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " + "hwaddr, hwtype, hwaddr_source, " + "state, user_context " + "FROM lease6 " + "WHERE address > $1 AND user_context IS NOT NULL " + "ORDER BY address " + "LIMIT $2"}, + // GET_LEASE6_SUBID { 1, { OID_INT8 }, "get_lease6_subid", @@ -3010,6 +3035,91 @@ PgSqlLeaseMgr::getLeases4ByRemoteId(const OptionBuffer& remote_id, return (result); } +size_t +PgSqlLeaseMgr::upgradeExtendedInfo(const LeasePageSize& page_size) { + auto check = CfgMgr::instance().getCurrentCfg()-> + getConsistency()->getExtendedInfoSanityCheck(); + + size_t pages = 0; + size_t updated = 0; + IOAddress start_addr = IOAddress::IPV4_ZERO_ADDRESS(); + for (;;) { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, + DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE) + .arg(pages) + .arg(start_addr.toText()) + .arg(updated); + + // Prepare WHERE clause. + PsqlBindArray bind_array; + + // Bind start address. + uint32_t start_addr_data = start_addr.toUint32(); + bind_array.add(start_addr_data); + + // Bind page size value. + std::string page_size_data = + boost::lexical_cast(page_size.page_size_); + bind_array.add(page_size_data); + + Lease4Collection leases; + + // Get a context. + { + PgSqlLeaseContextAlloc get_context(*this); + PgSqlLeaseContextPtr ctx = get_context.ctx_; + + getLeaseCollection(ctx, GET_LEASE4_UCTX_PAGE, bind_array, leases); + } + + if (leases.empty()) { + // Done. + break; + } + + ++pages; + start_addr = leases.back()->addr_; + for (auto lease : leases) { + ConstElementPtr previous_user_context = lease->getContext(); + vector previous_relay_id = lease->relay_id_; + vector previous_remote_id = lease->remote_id_; + if (!previous_user_context && + previous_relay_id.empty() && + previous_remote_id.empty()) { + continue; + } + bool modified = upgradeLease4ExtendedInfo(lease, check); + try { + lease->relay_id_.clear(); + lease->remote_id_.clear(); + extractLease4ExtendedInfo(lease, false); + if (modified || + (previous_relay_id != lease->relay_id_) || + (previous_remote_id != lease->remote_id_)) { + updateLease4(lease); + ++updated; + } + } catch (const NoSuchLease&) { + // The lease was modified in parallel: + // as its extended info was processed just ignore. + continue; + } catch (const std::exception& ex) { + // Something when wrong, for instance extract failed. + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, + DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR) + .arg(lease->addr_.toText()) + .arg(ex.what()); + } + } + } + + LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4) + .arg(pages) + .arg(updated); + + return (updated); +} + Lease6Collection PgSqlLeaseMgr::getLeases6ByRelayId(const DUID& /* relay_id */, const IOAddress& /* link_addr */, diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.h b/src/lib/dhcpsrv/pgsql_lease_mgr.h index 9e4d7f126f..794555abaa 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.h +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.h @@ -678,6 +678,7 @@ public: GET_LEASE4_HWADDR, // Get lease4 by HW address GET_LEASE4_HWADDR_SUBID, // Get lease4 by HW address & subnet ID GET_LEASE4_PAGE, // Get page of leases beginning with an address + GET_LEASE4_UCTX_PAGE, // Get page of leases with user context GET_LEASE4_SUBID, // Get IPv4 leases by subnet ID GET_LEASE4_HOSTNAME, // Get IPv4 leases by hostname GET_LEASE4_EXPIRE, // Get lease4 by expiration. @@ -694,6 +695,7 @@ public: GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID GET_LEASE6_PAGE, // Get page of leases beginning with an address + GET_LEASE6_UCTX_PAGE, // Get page of leases with user context GET_LEASE6_SUBID, // Get IPv6 leases by subnet ID GET_LEASE6_DUID, // Get IPv6 leases by DUID GET_LEASE6_HOSTNAME, // Get IPv6 leases by hostname @@ -1073,6 +1075,12 @@ private: const asiolink::IOAddress& lower_bound_address, const LeasePageSize& page_size) override; + /// @brief Upgrade extended info (v4). + /// + /// @param page_size The page size used for retrieval. + /// @return The number of updates in the database. + virtual size_t upgradeExtendedInfo(const LeasePageSize& page_size) override; + /// @brief Build extended info v6 tables. /// /// @param update Update extended info in database. diff --git a/src/lib/dhcpsrv/tests/mysql_lease_extended_info_unittest.cc b/src/lib/dhcpsrv/tests/mysql_lease_extended_info_unittest.cc index ba34f0cadf..c06fd7f809 100644 --- a/src/lib/dhcpsrv/tests/mysql_lease_extended_info_unittest.cc +++ b/src/lib/dhcpsrv/tests/mysql_lease_extended_info_unittest.cc @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include #include @@ -122,6 +124,10 @@ public: /// @brief Test getLease4ByRemoteId. void testGetLeases4ByRemoteId(); + /// @brief Test upgradeExtendedInfo. + void testUpgradeExtendedInfo(const CfgConsistency::ExtendedInfoSanity& check, + const LeasePageSize& page_size); + /// @brief Lease manager. LeaseMgr* lease_mgr_; @@ -614,4 +620,349 @@ TEST_F(MySqlExtendedInfoTest, getLeases4ByRemoteIdMultiThreading) { testGetLeases4ByRemoteId(); } +void +MySqlExtendedInfoTest::testUpgradeExtendedInfo(const CfgConsistency::ExtendedInfoSanity& check, + const LeasePageSize& page_size) { + // Lease manager is created with empty tables. + initLease4(false); + + // Create leases. + IOAddress addr0(ADDRESS4[0]); + IOAddress addr1(ADDRESS4[1]); + IOAddress addr2(ADDRESS4[2]); + IOAddress addr3(ADDRESS4[3]); + IOAddress addr4(ADDRESS4[4]); + IOAddress addr5(ADDRESS4[5]); + IOAddress addr6(ADDRESS4[6]); + IOAddress addr7(ADDRESS4[7]); + IOAddress zero = IOAddress::IPV4_ZERO_ADDRESS(); + vector relay_id = { 0xaa, 0xbb, 0xcc }; + vector relay_id2 = { 0xdd, 0xee, 0xff }; + vector remote_id = { 1, 2, 3, 4 }; + vector remote_id2 = { 5, 6, 7, 8 }; + string user_context_txt = "{ \"ISC\": { \"relay-agent-info\": {"; + user_context_txt += " \"sub-options\": \"0204010203040C03AABBCC\","; + user_context_txt += " \"relay-id\": \"AABBCC\","; + user_context_txt += " \"remote-id\": \"01020304\" } } }"; + ElementPtr user_context; + ASSERT_NO_THROW(user_context = Element::fromJSON(user_context_txt)); + string user_context_txt_old = "{ \"ISC\": { \"relay-agent-info\":"; + user_context_txt_old += " \"0204010203040C03AABBCC\" } }"; + ElementPtr user_context_old; + ASSERT_NO_THROW(user_context_old = Element::fromJSON(user_context_txt_old)); + string user_context_list_txt = "{ \"ISC\": { \"relay-agent-info\": [ ] } }"; + ElementPtr user_context_list; + ASSERT_NO_THROW(user_context_list = Element::fromJSON(user_context_list_txt)); + string user_context_lower_txt = "{ \"isc\": { \"relay-agent-info\":"; + user_context_lower_txt += " \"0204010203040c03aabbcc\" } }"; + ElementPtr user_context_lower; + ASSERT_NO_THROW(user_context_lower = Element::fromJSON(user_context_lower_txt)); + string user_context_badsub_txt = "{ \"ISC\": { \"relay-agent-info\": {"; + user_context_badsub_txt += " \"sub-options\": \"foobar\","; + user_context_badsub_txt += " \"relay-id\": \"AABBCC\","; + user_context_badsub_txt += " \"remote-id\": \"01020304\" } } }"; + ElementPtr user_context_badsub; + ASSERT_NO_THROW(user_context_badsub = Element::fromJSON(user_context_badsub_txt)); + string user_context_extra_txt = "{ \"ISC\": { \"relay-agent-info\": {"; + user_context_extra_txt += " \"foo\": \"bar\", "; + user_context_extra_txt += " \"sub-options\": \"0204010203040C03AABBCC\","; + user_context_extra_txt += " \"relay-id\": \"AABBCC\","; + user_context_extra_txt += " \"remote-id\": \"01020304\" } } }"; + ElementPtr user_context_extra; + ASSERT_NO_THROW(user_context_extra = Element::fromJSON(user_context_extra_txt)); + + Lease4Ptr lease; + // lease0: addr0, ids, before: always not updated. + lease = leases4[0]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context); + lease->cltt_ = now_ - 500; + + // lease1: addr1, ids, after: always not updated. + lease = leases4[1]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context); + lease->cltt_ = now_ + 500; + + // lease2: addr2, no id, old user context: updated on check > NONE. + lease = leases4[2]; + ASSERT_TRUE(lease); + lease->setContext(user_context_old); + + // lease3: addr3, ids, lower case old user context: always updated. + lease = leases4[3]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_lower); + + // Lease4: addr4, ids, bad (list) user context: updated on check > NONE. + lease = leases4[4]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_list); + + // Lease5: addr5, other ids: always updated. + lease = leases4[5]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id2; + lease->remote_id_ = remote_id2; + lease->setContext(user_context); + + // Lease6: addr6, ids, bad sub-options: updated on check > FIX. + lease = leases4[6]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_badsub); + + // Lease7: addr7, ids, extra in ISC: updated on check > STRICT. + lease = leases4[7]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_extra); + + // Add leases. + for (size_t i = 0; i < leases4.size(); ++i) { + EXPECT_TRUE(lease_mgr_->addLease(leases4[i])); + } + + // Set extended info consistency. + CfgMgr::instance().getCurrentCfg()->getConsistency()-> + setExtendedInfoSanityCheck(check); + + size_t updated; + ASSERT_NO_THROW(updated = lease_mgr_->upgradeExtendedInfo(page_size)); + + // Verify result. + switch (check) { + case CfgConsistency::EXTENDED_INFO_CHECK_NONE: + // Updated leases: 3, 5. + EXPECT_EQ(updated, 2); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_FIX: + // Updated leases: 2, 3, 4, 5. + EXPECT_EQ(updated, 4); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_STRICT: + // Updated leases: 2, 3, 4, 5, 6. + EXPECT_EQ(updated, 5); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC: + default: + // Updated leases: 2, 3, 4, 5, 6, 7. + EXPECT_EQ(updated, 6); + break; + } + + // Verify stored leases. + Lease4Collection got; + // Use the page version as it returns leases in order. + EXPECT_NO_THROW(got = lease_mgr_->getLeases4(zero, LeasePageSize(100))); + ASSERT_EQ(leases4.size(), got.size()); + + // Check lease0. + lease = got[0]; + EXPECT_EQ(*lease, *leases4[0]); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + + // Check lease1. + lease = got[1]; + EXPECT_EQ(*lease, *leases4[1]); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + + // Check lease2. + lease = got[2]; + Lease4Ptr expected2(new Lease4(*leases4[2])); + if (check == CfgConsistency::EXTENDED_INFO_CHECK_NONE) { + EXPECT_EQ(*lease, *expected2); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } else { + expected2->setContext(user_context); + expected2->relay_id_ = relay_id; + expected2->remote_id_ = remote_id; + EXPECT_EQ(*lease, *expected2); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } + + // Check lease3. + lease = got[3]; + Lease4Ptr expected3(new Lease4(*leases4[3])); + expected3->relay_id_.clear(); + expected3->remote_id_.clear(); + EXPECT_EQ(*lease, *expected3); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + + // Check lease4. + lease = got[4]; + Lease4Ptr expected4(new Lease4(*leases4[4])); + if (check == CfgConsistency::EXTENDED_INFO_CHECK_NONE) { + EXPECT_EQ(*lease, *expected4); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } else { + expected4->relay_id_.clear(); + expected4->remote_id_.clear(); + expected4->setContext(ElementPtr()); + EXPECT_EQ(*lease, *expected4); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } + + // Check lease5. + lease = got[5]; + Lease4Ptr expected5(new Lease4(*leases4[5])); + expected5->relay_id_ = relay_id; + expected5->remote_id_ = remote_id; + EXPECT_EQ(*lease, *expected5); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + + // Check lease6. + lease = got[6]; + Lease4Ptr expected6(new Lease4(*leases4[6])); + if ((check != CfgConsistency::EXTENDED_INFO_CHECK_STRICT) && + (check != CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC)) { + EXPECT_EQ(*lease, *expected6); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } else { + expected6->relay_id_.clear(); + expected6->remote_id_.clear(); + expected6->setContext(ElementPtr()); + EXPECT_EQ(*lease, *expected6); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } + + // Check lease7. + lease = got[7]; + Lease4Ptr expected7(new Lease4(*leases4[7])); + if (check != CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC) { + EXPECT_EQ(*lease, *expected7); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } else { + expected7->relay_id_.clear(); + expected7->remote_id_.clear(); + expected7->setContext(ElementPtr()); + EXPECT_EQ(*lease, *expected7); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } + + // Verify getLeases4ByRelayId. + Lease4Collection by_relay_id; + EXPECT_NO_THROW(by_relay_id = + lease_mgr_->getLeases4ByRelayId(relay_id, + zero, + LeasePageSize(100))); + switch (check) { + case CfgConsistency::EXTENDED_INFO_CHECK_NONE: + // Got leases: 0, 1, 4, 5, 6, 7. + EXPECT_EQ(6, by_relay_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_FIX: + // Got leases: 0, 1, 2, 5, 6, 7. + EXPECT_EQ(6, by_relay_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_STRICT: + // Got leases: 0, 1, 2, 4, 7. + EXPECT_EQ(5, by_relay_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC: + default: + // Got leases: 0, 1, 2, 4. + EXPECT_EQ(4, by_relay_id.size()); + break; + } + + // Verify getLeases4ByRemoteId. + Lease4Collection by_remote_id; + EXPECT_NO_THROW(by_remote_id = + lease_mgr_->getLeases4ByRemoteId(remote_id, + zero, + LeasePageSize(100))); + switch (check) { + case CfgConsistency::EXTENDED_INFO_CHECK_NONE: + // Got leases: 0, 1, 4, 5, 6, 7. + EXPECT_EQ(6, by_remote_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_FIX: + // Got leases: 0, 1, 2, 5, 6, 7. + EXPECT_EQ(6, by_remote_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_STRICT: + // Got leases: 0, 1, 2, 4, 7. + EXPECT_EQ(5, by_remote_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC: + default: + // Got leases: 0, 1, 2, 4. + EXPECT_EQ(4, by_remote_id.size()); + break; + } + +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfoNone) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_NONE, + LeasePageSize(100)); +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfoFix) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(100)); +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfoStrict) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + LeasePageSize(100)); +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfoPedantic) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + LeasePageSize(100)); +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfo10) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(10)); +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfo5) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(5)); +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfo2) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(2)); +} + +TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfo1) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(1)); +} + } // namespace diff --git a/src/lib/dhcpsrv/tests/pgsql_lease_extended_info_unittest.cc b/src/lib/dhcpsrv/tests/pgsql_lease_extended_info_unittest.cc index 0f7d21c5a4..67aa319d13 100644 --- a/src/lib/dhcpsrv/tests/pgsql_lease_extended_info_unittest.cc +++ b/src/lib/dhcpsrv/tests/pgsql_lease_extended_info_unittest.cc @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include #include @@ -122,6 +124,10 @@ public: /// @brief Test getLease4ByRemoteId. void testGetLeases4ByRemoteId(); + /// @brief Test upgradeExtendedInfo. + void testUpgradeExtendedInfo(const CfgConsistency::ExtendedInfoSanity& check, + const LeasePageSize& page_size); + /// @brief Lease manager. LeaseMgr* lease_mgr_; @@ -614,4 +620,349 @@ TEST_F(PgSqlExtendedInfoTest, getLeases4ByRemoteIdMultiThreading) { testGetLeases4ByRemoteId(); } +void +PgSqlExtendedInfoTest::testUpgradeExtendedInfo(const CfgConsistency::ExtendedInfoSanity& check, + const LeasePageSize& page_size) { + // Lease manager is created with empty tables. + initLease4(false); + + // Create leases. + IOAddress addr0(ADDRESS4[0]); + IOAddress addr1(ADDRESS4[1]); + IOAddress addr2(ADDRESS4[2]); + IOAddress addr3(ADDRESS4[3]); + IOAddress addr4(ADDRESS4[4]); + IOAddress addr5(ADDRESS4[5]); + IOAddress addr6(ADDRESS4[6]); + IOAddress addr7(ADDRESS4[7]); + IOAddress zero = IOAddress::IPV4_ZERO_ADDRESS(); + vector relay_id = { 0xaa, 0xbb, 0xcc }; + vector relay_id2 = { 0xdd, 0xee, 0xff }; + vector remote_id = { 1, 2, 3, 4 }; + vector remote_id2 = { 5, 6, 7, 8 }; + string user_context_txt = "{ \"ISC\": { \"relay-agent-info\": {"; + user_context_txt += " \"sub-options\": \"0204010203040C03AABBCC\","; + user_context_txt += " \"relay-id\": \"AABBCC\","; + user_context_txt += " \"remote-id\": \"01020304\" } } }"; + ElementPtr user_context; + ASSERT_NO_THROW(user_context = Element::fromJSON(user_context_txt)); + string user_context_txt_old = "{ \"ISC\": { \"relay-agent-info\":"; + user_context_txt_old += " \"0204010203040C03AABBCC\" } }"; + ElementPtr user_context_old; + ASSERT_NO_THROW(user_context_old = Element::fromJSON(user_context_txt_old)); + string user_context_list_txt = "{ \"ISC\": { \"relay-agent-info\": [ ] } }"; + ElementPtr user_context_list; + ASSERT_NO_THROW(user_context_list = Element::fromJSON(user_context_list_txt)); + string user_context_lower_txt = "{ \"isc\": { \"relay-agent-info\":"; + user_context_lower_txt += " \"0204010203040c03aabbcc\" } }"; + ElementPtr user_context_lower; + ASSERT_NO_THROW(user_context_lower = Element::fromJSON(user_context_lower_txt)); + string user_context_badsub_txt = "{ \"ISC\": { \"relay-agent-info\": {"; + user_context_badsub_txt += " \"sub-options\": \"foobar\","; + user_context_badsub_txt += " \"relay-id\": \"AABBCC\","; + user_context_badsub_txt += " \"remote-id\": \"01020304\" } } }"; + ElementPtr user_context_badsub; + ASSERT_NO_THROW(user_context_badsub = Element::fromJSON(user_context_badsub_txt)); + string user_context_extra_txt = "{ \"ISC\": { \"relay-agent-info\": {"; + user_context_extra_txt += " \"foo\": \"bar\", "; + user_context_extra_txt += " \"sub-options\": \"0204010203040C03AABBCC\","; + user_context_extra_txt += " \"relay-id\": \"AABBCC\","; + user_context_extra_txt += " \"remote-id\": \"01020304\" } } }"; + ElementPtr user_context_extra; + ASSERT_NO_THROW(user_context_extra = Element::fromJSON(user_context_extra_txt)); + + Lease4Ptr lease; + // lease0: addr0, ids, before: always not updated. + lease = leases4[0]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context); + lease->cltt_ = now_ - 500; + + // lease1: addr1, ids, after: always not updated. + lease = leases4[1]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context); + lease->cltt_ = now_ + 500; + + // lease2: addr2, no id, old user context: updated on check > NONE. + lease = leases4[2]; + ASSERT_TRUE(lease); + lease->setContext(user_context_old); + + // lease3: addr3, ids, lower case old user context: always updated. + lease = leases4[3]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_lower); + + // Lease4: addr4, ids, bad (list) user context: updated on check > NONE. + lease = leases4[4]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_list); + + // Lease5: addr5, other ids: always updated. + lease = leases4[5]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id2; + lease->remote_id_ = remote_id2; + lease->setContext(user_context); + + // Lease6: addr6, ids, bad sub-options: updated on check > FIX. + lease = leases4[6]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_badsub); + + // Lease7: addr7, ids, extra in ISC: updated on check > STRICT. + lease = leases4[7]; + ASSERT_TRUE(lease); + lease->relay_id_ = relay_id; + lease->remote_id_ = remote_id; + lease->setContext(user_context_extra); + + // Add leases. + for (size_t i = 0; i < leases4.size(); ++i) { + EXPECT_TRUE(lease_mgr_->addLease(leases4[i])); + } + + // Set extended info consistency. + CfgMgr::instance().getCurrentCfg()->getConsistency()-> + setExtendedInfoSanityCheck(check); + + size_t updated; + ASSERT_NO_THROW(updated = lease_mgr_->upgradeExtendedInfo(page_size)); + + // Verify result. + switch (check) { + case CfgConsistency::EXTENDED_INFO_CHECK_NONE: + // Updated leases: 3, 5. + EXPECT_EQ(updated, 2); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_FIX: + // Updated leases: 2, 3, 4, 5. + EXPECT_EQ(updated, 4); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_STRICT: + // Updated leases: 2, 3, 4, 5, 6. + EXPECT_EQ(updated, 5); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC: + default: + // Updated leases: 2, 3, 4, 5, 6, 7. + EXPECT_EQ(updated, 6); + break; + } + + // Verify stored leases. + Lease4Collection got; + // Use the page version as it returns leases in order. + EXPECT_NO_THROW(got = lease_mgr_->getLeases4(zero, LeasePageSize(100))); + ASSERT_EQ(leases4.size(), got.size()); + + // Check lease0. + lease = got[0]; + EXPECT_EQ(*lease, *leases4[0]); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + + // Check lease1. + lease = got[1]; + EXPECT_EQ(*lease, *leases4[1]); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + + // Check lease2. + lease = got[2]; + Lease4Ptr expected2(new Lease4(*leases4[2])); + if (check == CfgConsistency::EXTENDED_INFO_CHECK_NONE) { + EXPECT_EQ(*lease, *expected2); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } else { + expected2->setContext(user_context); + expected2->relay_id_ = relay_id; + expected2->remote_id_ = remote_id; + EXPECT_EQ(*lease, *expected2); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } + + // Check lease3. + lease = got[3]; + Lease4Ptr expected3(new Lease4(*leases4[3])); + expected3->relay_id_.clear(); + expected3->remote_id_.clear(); + EXPECT_EQ(*lease, *expected3); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + + // Check lease4. + lease = got[4]; + Lease4Ptr expected4(new Lease4(*leases4[4])); + if (check == CfgConsistency::EXTENDED_INFO_CHECK_NONE) { + EXPECT_EQ(*lease, *expected4); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } else { + expected4->relay_id_.clear(); + expected4->remote_id_.clear(); + expected4->setContext(ElementPtr()); + EXPECT_EQ(*lease, *expected4); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } + + // Check lease5. + lease = got[5]; + Lease4Ptr expected5(new Lease4(*leases4[5])); + expected5->relay_id_ = relay_id; + expected5->remote_id_ = remote_id; + EXPECT_EQ(*lease, *expected5); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + + // Check lease6. + lease = got[6]; + Lease4Ptr expected6(new Lease4(*leases4[6])); + if ((check != CfgConsistency::EXTENDED_INFO_CHECK_STRICT) && + (check != CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC)) { + EXPECT_EQ(*lease, *expected6); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } else { + expected6->relay_id_.clear(); + expected6->remote_id_.clear(); + expected6->setContext(ElementPtr()); + EXPECT_EQ(*lease, *expected6); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } + + // Check lease7. + lease = got[7]; + Lease4Ptr expected7(new Lease4(*leases4[7])); + if (check != CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC) { + EXPECT_EQ(*lease, *expected7); + EXPECT_EQ(relay_id, lease->relay_id_); + EXPECT_EQ(remote_id, lease->remote_id_); + } else { + expected7->relay_id_.clear(); + expected7->remote_id_.clear(); + expected7->setContext(ElementPtr()); + EXPECT_EQ(*lease, *expected7); + EXPECT_TRUE(lease->relay_id_.empty()); + EXPECT_TRUE(lease->remote_id_.empty()); + } + + // Verify getLeases4ByRelayId. + Lease4Collection by_relay_id; + EXPECT_NO_THROW(by_relay_id = + lease_mgr_->getLeases4ByRelayId(relay_id, + zero, + LeasePageSize(100))); + switch (check) { + case CfgConsistency::EXTENDED_INFO_CHECK_NONE: + // Got leases: 0, 1, 4, 5, 6, 7. + EXPECT_EQ(6, by_relay_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_FIX: + // Got leases: 0, 1, 2, 5, 6, 7. + EXPECT_EQ(6, by_relay_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_STRICT: + // Got leases: 0, 1, 2, 4, 7. + EXPECT_EQ(5, by_relay_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC: + default: + // Got leases: 0, 1, 2, 4. + EXPECT_EQ(4, by_relay_id.size()); + break; + } + + // Verify getLeases4ByRemoteId. + Lease4Collection by_remote_id; + EXPECT_NO_THROW(by_remote_id = + lease_mgr_->getLeases4ByRemoteId(remote_id, + zero, + LeasePageSize(100))); + switch (check) { + case CfgConsistency::EXTENDED_INFO_CHECK_NONE: + // Got leases: 0, 1, 4, 5, 6, 7. + EXPECT_EQ(6, by_remote_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_FIX: + // Got leases: 0, 1, 2, 5, 6, 7. + EXPECT_EQ(6, by_remote_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_STRICT: + // Got leases: 0, 1, 2, 4, 7. + EXPECT_EQ(5, by_remote_id.size()); + break; + + case CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC: + default: + // Got leases: 0, 1, 2, 4. + EXPECT_EQ(4, by_remote_id.size()); + break; + } + +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfoNone) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_NONE, + LeasePageSize(100)); +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfoFix) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(100)); +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfoStrict) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + LeasePageSize(100)); +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfoPedantic) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + LeasePageSize(100)); +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfo10) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(10)); +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfo5) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(5)); +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfo2) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(2)); +} + +TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfo1) { + testUpgradeExtendedInfo(CfgConsistency::EXTENDED_INFO_CHECK_FIX, + LeasePageSize(1)); +} + } // namespace diff --git a/src/lib/dhcpsrv/testutils/concrete_lease_mgr.cc b/src/lib/dhcpsrv/testutils/concrete_lease_mgr.cc index d04fd34ccc..f89d883df0 100644 --- a/src/lib/dhcpsrv/testutils/concrete_lease_mgr.cc +++ b/src/lib/dhcpsrv/testutils/concrete_lease_mgr.cc @@ -291,6 +291,11 @@ ConcreteLeaseMgr::getLeases6ByLink(const IOAddress& /* link_addr */, isc_throw(NotImplemented, "ConcreteLeaseMgr::getLeases6ByLink not implemented"); } +size_t +ConcreteLeaseMgr::upgradeExtendedInfo(const LeasePageSize& /* page_size */) { + return (0); +} + size_t ConcreteLeaseMgr::buildExtendedInfoTables6(bool /* update */, bool /* current */) { diff --git a/src/lib/dhcpsrv/testutils/concrete_lease_mgr.h b/src/lib/dhcpsrv/testutils/concrete_lease_mgr.h index 3b97a492b3..14cab968e8 100644 --- a/src/lib/dhcpsrv/testutils/concrete_lease_mgr.h +++ b/src/lib/dhcpsrv/testutils/concrete_lease_mgr.h @@ -377,6 +377,10 @@ public: const asiolink::IOAddress& /* lower_bound_address */, const LeasePageSize& /* page_size */) override; + /// @brief Stub implementation. + virtual size_t + upgradeExtendedInfo(const LeasePageSize& /* page_size */) override; + /// @brief Stub implementation. virtual size_t buildExtendedInfoTables6(bool /* update */, bool /* current */) override;