From eb0c304edf52d2ced987cd5a3752aca5cf29d24d Mon Sep 17 00:00:00 2001 From: Razvan Becheriu Date: Tue, 17 Sep 2024 23:43:15 +0300 Subject: [PATCH] [#3536] implement getDBVersion --- src/bin/dhcp4/main.cc | 6 +-- src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 2 + src/bin/dhcp6/main.cc | 6 +-- src/bin/dhcp6/tests/dhcp6_srv_unittest.cc | 2 + src/bin/lfc/lfc_controller.cc | 4 +- src/hooks/dhcp/mysql_hb/mysql_hb_callouts.cc | 5 +- .../dhcp/mysql_hb/mysql_host_data_source.cc | 9 ++++ .../dhcp/mysql_hb/mysql_host_data_source.h | 9 +++- src/hooks/dhcp/mysql_lb/mysql_lb_callouts.cc | 3 +- src/hooks/dhcp/mysql_lb/mysql_lease_mgr.h | 4 +- src/hooks/dhcp/pgsql_hb/pgsql_hb_callouts.cc | 5 +- .../dhcp/pgsql_hb/pgsql_host_data_source.cc | 9 ++++ .../dhcp/pgsql_hb/pgsql_host_data_source.h | 9 +++- src/hooks/dhcp/pgsql_lb/pgsql_lb_callouts.cc | 3 +- src/hooks/dhcp/pgsql_lb/pgsql_lease_mgr.h | 4 +- src/lib/dhcpsrv/host_data_source_factory.cc | 23 ++++++--- src/lib/dhcpsrv/host_data_source_factory.h | 10 +++- src/lib/dhcpsrv/lease_mgr_factory.cc | 35 ++++++++------ src/lib/dhcpsrv/lease_mgr_factory.h | 9 +++- src/lib/dhcpsrv/memfile_lease_mgr.cc | 13 +++-- src/lib/dhcpsrv/memfile_lease_mgr.h | 27 ++++++++++- .../host_data_source_factory_unittest.cc | 16 ++++++- .../tests/lease_mgr_factory_unittest.cc | 47 +++++++++++++++++-- .../tests/memfile_lease_mgr_unittest.cc | 4 +- 24 files changed, 208 insertions(+), 56 deletions(-) diff --git a/src/bin/dhcp4/main.cc b/src/bin/dhcp4/main.cc index 7979a04666..7538b78f55 100644 --- a/src/bin/dhcp4/main.cc +++ b/src/bin/dhcp4/main.cc @@ -83,6 +83,9 @@ main(int argc, char* argv[]) { // The standard config file std::string config_file(""); + // This is the DHCPv4 server + CfgMgr::instance().setFamily(AF_INET); + while ((ch = getopt(argc, argv, "dvVWc:p:P:t:T:")) != -1) { switch (ch) { case 'd': @@ -162,9 +165,6 @@ main(int argc, char* argv[]) { usage(); } - // This is the DHCPv4 server - CfgMgr::instance().setFamily(AF_INET); - if (check_mode) { try { // We need to initialize logging, in case any error messages are to be printed. diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index 907e2ba5bc..2a2c2b111e 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -38,10 +38,12 @@ #ifdef HAVE_MYSQL #include +#include #endif #ifdef HAVE_PGSQL #include +#include #endif #include diff --git a/src/bin/dhcp6/main.cc b/src/bin/dhcp6/main.cc index fcfff7df53..c2402ccec7 100644 --- a/src/bin/dhcp6/main.cc +++ b/src/bin/dhcp6/main.cc @@ -83,6 +83,9 @@ main(int argc, char* argv[]) { // The standard config file std::string config_file(""); + // This is the DHCPv6 server + CfgMgr::instance().setFamily(AF_INET6); + while ((ch = getopt(argc, argv, "dvVWc:p:P:t:T:")) != -1) { switch (ch) { case 'd': @@ -162,9 +165,6 @@ main(int argc, char* argv[]) { usage(); } - // This is the DHCPv6 server - CfgMgr::instance().setFamily(AF_INET6); - if (check_mode) { try { // We need to initialize logging, in case any error messages are to be printed. diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc index b547b7082a..fc7fb7c1da 100644 --- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc @@ -39,10 +39,12 @@ #ifdef HAVE_MYSQL #include +#include #endif #ifdef HAVE_PGSQL #include +#include #endif #include diff --git a/src/bin/lfc/lfc_controller.cc b/src/bin/lfc/lfc_controller.cc index 2a03e05d13..10d7a80cb5 100644 --- a/src/bin/lfc/lfc_controller.cc +++ b/src/bin/lfc/lfc_controller.cc @@ -324,9 +324,9 @@ LFCController::getVersion(const bool extended) const{ if (extended) { std::string db_version; if (protocol_version_ == 4) { - db_version = Memfile_LeaseMgr::getDBVersion(Memfile_LeaseMgr::V4); + db_version = Memfile_LeaseMgr::getDBVersionInternal(Memfile_LeaseMgr::V4); } else if (protocol_version_ == 6) { - db_version = Memfile_LeaseMgr::getDBVersion(Memfile_LeaseMgr::V6); + db_version = Memfile_LeaseMgr::getDBVersionInternal(Memfile_LeaseMgr::V6); } version_stream << " (" << EXTENDED_VERSION << ")"; diff --git a/src/hooks/dhcp/mysql_hb/mysql_hb_callouts.cc b/src/hooks/dhcp/mysql_hb/mysql_hb_callouts.cc index 0d0394f82b..72394b19df 100644 --- a/src/hooks/dhcp/mysql_hb/mysql_hb_callouts.cc +++ b/src/hooks/dhcp/mysql_hb/mysql_hb_callouts.cc @@ -52,7 +52,8 @@ int load(LibraryHandle& /* handle */) { } // Register MySQL HB factories with Host Managers - isc::dhcp::HostDataSourceFactory::registerFactory("mysql", MySqlHostDataSource::factory, true); + HostDataSourceFactory::registerFactory("mysql", MySqlHostDataSource::factory, true, + MySqlHostDataSource::getDBVersion); LOG_INFO(mysql_hb_logger, MYSQL_HB_INIT_OK); return (0); @@ -63,7 +64,7 @@ int load(LibraryHandle& /* handle */) { /// @return 0 if deregistration was successful, 1 otherwise int unload() { // Unregister the factories and remove MySQL backends - isc::dhcp::HostDataSourceFactory::deregisterFactory("mysql", true); + HostDataSourceFactory::deregisterFactory("mysql", true); LOG_INFO(mysql_hb_logger, MYSQL_HB_DEINIT_OK); return (0); diff --git a/src/hooks/dhcp/mysql_hb/mysql_host_data_source.cc b/src/hooks/dhcp/mysql_hb/mysql_host_data_source.cc index 3740044a62..ac04d1fe21 100644 --- a/src/hooks/dhcp/mysql_hb/mysql_host_data_source.cc +++ b/src/hooks/dhcp/mysql_hb/mysql_host_data_source.cc @@ -4217,5 +4217,14 @@ MySqlHostDataSource::factory(const isc::db::DatabaseConnection::ParameterMap& pa return (HostDataSourcePtr(new MySqlHostDataSource(parameters))); } +std::string +MySqlHostDataSource::getDBVersion() { + std::stringstream tmp; + tmp << "MySQL backend " << MYSQL_SCHEMA_VERSION_MAJOR; + tmp << "." << MYSQL_SCHEMA_VERSION_MINOR; + tmp << ", library " << mysql_get_client_info(); + return (tmp.str()); +} + } // namespace dhcp } // namespace isc diff --git a/src/hooks/dhcp/mysql_hb/mysql_host_data_source.h b/src/hooks/dhcp/mysql_hb/mysql_host_data_source.h index 28f92c4b24..f32ed52d84 100644 --- a/src/hooks/dhcp/mysql_hb/mysql_host_data_source.h +++ b/src/hooks/dhcp/mysql_hb/mysql_host_data_source.h @@ -540,17 +540,22 @@ public: /// @return The MySQL Host Manager. static HostDataSourcePtr factory(const isc::db::DatabaseConnection::ParameterMap& parameters); + + /// @brief Local version of getDBVersion() class method + static std::string getDBVersion(); }; +/// @brief Initialization structure used to register and deregister MySQL Host Mgr. struct MySqlHostDataSourceInit { // Constructor registers MySqlHostDataSourceInit() { - isc::dhcp::HostDataSourceFactory::registerFactory("mysql", MySqlHostDataSource::factory, true); + HostDataSourceFactory::registerFactory("mysql", MySqlHostDataSource::factory, true, + MySqlHostDataSource::getDBVersion); } // Destructor deregisters ~MySqlHostDataSourceInit() { - isc::dhcp::HostDataSourceFactory::deregisterFactory("mysql", true); + HostDataSourceFactory::deregisterFactory("mysql", true); } }; diff --git a/src/hooks/dhcp/mysql_lb/mysql_lb_callouts.cc b/src/hooks/dhcp/mysql_lb/mysql_lb_callouts.cc index 0d74d995a3..97808d0206 100644 --- a/src/hooks/dhcp/mysql_lb/mysql_lb_callouts.cc +++ b/src/hooks/dhcp/mysql_lb/mysql_lb_callouts.cc @@ -52,7 +52,8 @@ int load(LibraryHandle& /* handle */) { } // Register MySQL LB factories with Lease Managers - LeaseMgrFactory::registerFactory("mysql", MySqlLeaseMgr::factory, true); + LeaseMgrFactory::registerFactory("mysql", MySqlLeaseMgr::factory, true, + MySqlLeaseMgr::getDBVersion); LOG_INFO(mysql_lb_logger, MYSQL_LB_INIT_OK); return (0); diff --git a/src/hooks/dhcp/mysql_lb/mysql_lease_mgr.h b/src/hooks/dhcp/mysql_lb/mysql_lease_mgr.h index 1b44891ec6..29791f188a 100644 --- a/src/hooks/dhcp/mysql_lb/mysql_lease_mgr.h +++ b/src/hooks/dhcp/mysql_lb/mysql_lease_mgr.h @@ -1309,10 +1309,12 @@ public: factory(const isc::db::DatabaseConnection::ParameterMap& parameters); }; +/// @brief Initialization structure used to register and deregister MySQL Lease Mgr. struct MySqlLeaseMgrInit { // Constructor registers MySqlLeaseMgrInit() { - LeaseMgrFactory::registerFactory("mysql", MySqlLeaseMgr::factory, true); + LeaseMgrFactory::registerFactory("mysql", MySqlLeaseMgr::factory, true, + MySqlLeaseMgr::getDBVersion); } // Destructor deregisters diff --git a/src/hooks/dhcp/pgsql_hb/pgsql_hb_callouts.cc b/src/hooks/dhcp/pgsql_hb/pgsql_hb_callouts.cc index 02158af4f9..8aa31e7b0a 100644 --- a/src/hooks/dhcp/pgsql_hb/pgsql_hb_callouts.cc +++ b/src/hooks/dhcp/pgsql_hb/pgsql_hb_callouts.cc @@ -52,7 +52,8 @@ int load(LibraryHandle& /* handle */) { } // Register PgSQL HB factories with Host Managers - isc::dhcp::HostDataSourceFactory::registerFactory("postgresql", PgSqlHostDataSource::factory, true); + HostDataSourceFactory::registerFactory("postgresql", PgSqlHostDataSource::factory, true, + PgSqlHostDataSource::getDBVersion); LOG_INFO(pgsql_hb_logger, PGSQL_HB_INIT_OK); return (0); @@ -63,7 +64,7 @@ int load(LibraryHandle& /* handle */) { /// @return 0 if deregistration was successful, 1 otherwise int unload() { // Unregister the factories and remove PgSQL backends - isc::dhcp::HostDataSourceFactory::deregisterFactory("postgresql", true); + HostDataSourceFactory::deregisterFactory("postgresql", true); LOG_INFO(pgsql_hb_logger, PGSQL_HB_DEINIT_OK); return (0); diff --git a/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.cc b/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.cc index 4604d8f9ae..efdf1eef50 100644 --- a/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.cc +++ b/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.cc @@ -3382,5 +3382,14 @@ PgSqlHostDataSource::factory(const isc::db::DatabaseConnection::ParameterMap& pa return (HostDataSourcePtr(new PgSqlHostDataSource(parameters))); } +std::string +PgSqlHostDataSource::getDBVersion() { + std::stringstream tmp; + tmp << "PostgreSQL backend " << PGSQL_SCHEMA_VERSION_MAJOR; + tmp << "." << PGSQL_SCHEMA_VERSION_MINOR; + tmp << ", library " << PQlibVersion(); + return (tmp.str()); +} + } // namespace dhcp } // namespace isc diff --git a/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.h b/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.h index a17306c6ca..5ce41bf31f 100644 --- a/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.h +++ b/src/hooks/dhcp/pgsql_hb/pgsql_host_data_source.h @@ -592,17 +592,22 @@ public: /// @return The PostgreSQL Host Manager. static HostDataSourcePtr factory(const isc::db::DatabaseConnection::ParameterMap& parameters); + + /// @brief Local version of getDBVersion() class method + static std::string getDBVersion(); }; +/// @brief Initialization structure used to register and deregister PostgreSQL Host Mgr. struct PgSqlHostDataSourceInit { // Constructor registers PgSqlHostDataSourceInit() { - isc::dhcp::HostDataSourceFactory::registerFactory("postgresql", PgSqlHostDataSource::factory, true); + HostDataSourceFactory::registerFactory("postgresql", PgSqlHostDataSource::factory, true, + PgSqlHostDataSource::getDBVersion); } // Destructor deregisters ~PgSqlHostDataSourceInit() { - isc::dhcp::HostDataSourceFactory::deregisterFactory("postgresql", true); + HostDataSourceFactory::deregisterFactory("postgresql", true); } }; diff --git a/src/hooks/dhcp/pgsql_lb/pgsql_lb_callouts.cc b/src/hooks/dhcp/pgsql_lb/pgsql_lb_callouts.cc index f1c3d2c5fd..7d299e698e 100644 --- a/src/hooks/dhcp/pgsql_lb/pgsql_lb_callouts.cc +++ b/src/hooks/dhcp/pgsql_lb/pgsql_lb_callouts.cc @@ -52,7 +52,8 @@ int load(LibraryHandle& /* handle */) { } // Register PgSQL LB factories with Lease Managers - LeaseMgrFactory::registerFactory("postgresql", PgSqlLeaseMgr::factory, true); + LeaseMgrFactory::registerFactory("postgresql", PgSqlLeaseMgr::factory, true, + PgSqlLeaseMgr::getDBVersion); LOG_INFO(pgsql_lb_logger, PGSQL_LB_INIT_OK); return (0); diff --git a/src/hooks/dhcp/pgsql_lb/pgsql_lease_mgr.h b/src/hooks/dhcp/pgsql_lb/pgsql_lease_mgr.h index adb8fe6bf7..1004c45a15 100644 --- a/src/hooks/dhcp/pgsql_lb/pgsql_lease_mgr.h +++ b/src/hooks/dhcp/pgsql_lb/pgsql_lease_mgr.h @@ -1268,10 +1268,12 @@ public: factory(const isc::db::DatabaseConnection::ParameterMap& parameters); }; +/// @brief Initialization structure used to register and deregister PostgreSQL Lease Mgr. struct PgSqlLeaseMgrInit { // Constructor registers PgSqlLeaseMgrInit() { - LeaseMgrFactory::registerFactory("postgresql", PgSqlLeaseMgr::factory, true); + LeaseMgrFactory::registerFactory("postgresql", PgSqlLeaseMgr::factory, true, + PgSqlLeaseMgr::getDBVersion); } // Destructor deregisters diff --git a/src/lib/dhcpsrv/host_data_source_factory.cc b/src/lib/dhcpsrv/host_data_source_factory.cc index 0a7c21b902..ca73372928 100644 --- a/src/lib/dhcpsrv/host_data_source_factory.cc +++ b/src/lib/dhcpsrv/host_data_source_factory.cc @@ -26,7 +26,7 @@ using namespace std; namespace isc { namespace dhcp { -map HostDataSourceFactory::map_; +map> HostDataSourceFactory::map_; void HostDataSourceFactory::add(HostDataSourceList& sources, @@ -51,14 +51,15 @@ HostDataSourceFactory::add(HostDataSourceList& sources, string with = (db_type == "postgresql" ? "pgsql" : db_type); isc_throw(InvalidType, "The type of host backend: '" << db_type << "' is not compiled in. Did you forget to use --with-" - << with << " during compilation?"); + << with << " during compilation or to load libdhcp_" + << with << "_hb hook library?"); } isc_throw(InvalidType, "The type of host backend: '" << db_type << "' is not supported"); } // Call the factory and push the pointer on sources. - sources.push_back(index->second(parameters)); + sources.push_back(index->second.first(parameters)); // Check the factory did not return null. if (!sources.back()) { @@ -114,11 +115,21 @@ HostDataSourceFactory::del(HostDataSourceList& sources, bool HostDataSourceFactory::registerFactory(const string& db_type, const Factory& factory, - bool no_log) { + bool no_log, + DBVersion db_version) { if (map_.count(db_type)) { return (false); } - map_.insert(pair(db_type, factory)); + + static auto default_db_version = []() -> std::string { + return (std::string()); + }; + + if (!db_version) { + db_version = default_db_version; + } + + map_.insert(pair>(db_type, pair(factory, db_version))); // We are dealing here with static logger initialization fiasco. // registerFactory may be called from constructors of static global @@ -176,7 +187,7 @@ HostDataSourceFactory::getDBVersions() { if (!txt.str().empty()) { txt << " "; } - txt << x.first; + txt << x.second.second(); } return (txt.str()); diff --git a/src/lib/dhcpsrv/host_data_source_factory.h b/src/lib/dhcpsrv/host_data_source_factory.h index 857c2b987b..22609421e2 100644 --- a/src/lib/dhcpsrv/host_data_source_factory.h +++ b/src/lib/dhcpsrv/host_data_source_factory.h @@ -99,6 +99,9 @@ public: /// data source. In case of failure it must throw and not return null. typedef std::function Factory; + /// @brief Type of host mgr version + typedef std::function DBVersion; + /// @brief Register a host data source factory /// /// Associate the factory to a database type in the map. @@ -108,10 +111,13 @@ public: /// @param db_type database type /// @param factory host data source factory /// @param no_log do not log (default false) + /// @param db_version host mgr version /// @return true if the factory was successfully added to the map, false /// if it already exists. static bool registerFactory(const std::string& db_type, - const Factory& factory, bool no_log = false); + const Factory& factory, + bool no_log = false, + DBVersion db_version = DBVersion()); /// @brief Deregister a host data source factory /// @@ -143,7 +149,7 @@ public: private: /// @brief Factory map - static std::map map_; + static std::map> map_; }; } // end of isc::dhcp namespace diff --git a/src/lib/dhcpsrv/lease_mgr_factory.cc b/src/lib/dhcpsrv/lease_mgr_factory.cc index b28afc7d44..fe6a3a9498 100644 --- a/src/lib/dhcpsrv/lease_mgr_factory.cc +++ b/src/lib/dhcpsrv/lease_mgr_factory.cc @@ -24,7 +24,10 @@ using namespace std; namespace isc { namespace dhcp { -map LeaseMgrFactory::map_; +map> LeaseMgrFactory::map_; + +/// @brief Initializer. +MemfileLeaseMgrInit memfile_init; TrackingLeaseMgrPtr& LeaseMgrFactory::getLeaseMgrPtr() { @@ -48,14 +51,6 @@ LeaseMgrFactory::create(const std::string& dbaccess) { "contain the 'type' keyword"); } - // Factory method - auto memfile_factory = [](const DatabaseConnection::ParameterMap& parameters) -> TrackingLeaseMgrPtr { - LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_DB) - .arg(DatabaseConnection::redactedAccessString(parameters)); - return (TrackingLeaseMgrPtr(new Memfile_LeaseMgr(parameters))); - }; - LeaseMgrFactory::registerFactory("memfile", memfile_factory, true); - string db_type = it->second; auto index = map_.find(db_type); @@ -67,7 +62,8 @@ LeaseMgrFactory::create(const std::string& dbaccess) { isc_throw(InvalidType, "The Kea server has not been compiled with " "support for database type: " << db_type << ". Did you forget to use --with-" - << with << " during compilation?"); + << with << " during compilation or to load libdhcp_" + << with << "_lb hook library?"); } // Get here on no match LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg(parameters[type]); @@ -76,7 +72,7 @@ LeaseMgrFactory::create(const std::string& dbaccess) { } // Call the factory. - getLeaseMgrPtr() = index->second(parameters); + getLeaseMgrPtr() = index->second.first(parameters); // Check the factory did not return null. if (!getLeaseMgrPtr()) { @@ -94,7 +90,6 @@ LeaseMgrFactory::destroy() { .arg(getLeaseMgrPtr()->getType()); } getLeaseMgrPtr().reset(); - LeaseMgrFactory::deregisterFactory("memfile", true); } void @@ -133,11 +128,21 @@ LeaseMgrFactory::instance() { bool LeaseMgrFactory::registerFactory(const string& db_type, const Factory& factory, - bool no_log) { + bool no_log, + DBVersion db_version) { if (map_.count(db_type)) { return (false); } - map_.insert(pair(db_type, factory)); + + static auto default_db_version = []() -> std::string { + return (std::string()); + }; + + if (!db_version) { + db_version = default_db_version; + } + + map_.insert(pair>(db_type, pair(factory, db_version))); // We are dealing here with static logger initialization fiasco. // registerFactory may be called from constructors of static global @@ -195,7 +200,7 @@ LeaseMgrFactory::getDBVersions() { if (!txt.str().empty()) { txt << " "; } - txt << x.first; + txt << x.second.second(); } return (txt.str()); diff --git a/src/lib/dhcpsrv/lease_mgr_factory.h b/src/lib/dhcpsrv/lease_mgr_factory.h index c4e8299426..fdf6934e21 100644 --- a/src/lib/dhcpsrv/lease_mgr_factory.h +++ b/src/lib/dhcpsrv/lease_mgr_factory.h @@ -108,6 +108,9 @@ public: /// In case of failure it must throw and not return null. typedef std::function Factory; + /// @brief Type of lease mgr version + typedef std::function DBVersion; + /// @brief Register a lease mgr factory /// /// Associate the factory to a database type in the map. @@ -117,11 +120,13 @@ public: /// @param db_type database type /// @param factory lease mgr factory /// @param no_log do not log (default false) + /// @param db_version lease mgr version /// @return true if the factory was successfully added to the map, false /// if it already exists. static bool registerFactory(const std::string& db_type, const Factory& factory, - bool no_log = false); + bool no_log = false, + DBVersion db_version = DBVersion()); /// @brief Deregister a lease mgr factory /// @@ -160,7 +165,7 @@ private: static TrackingLeaseMgrPtr& getLeaseMgrPtr(); /// @brief Factory map - static std::map map_; + static std::map> map_; }; } // end of isc::dhcp namespace diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 6119999c62..83542dc0ca 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -1030,7 +1030,7 @@ Memfile_LeaseMgr::~Memfile_LeaseMgr() { } std::string -Memfile_LeaseMgr::getDBVersion(Universe const& u) { +Memfile_LeaseMgr::getDBVersionInternal(Universe const& u) { std::stringstream tmp; tmp << "Memfile backend "; if (u == V4) { @@ -1045,9 +1045,9 @@ std::string Memfile_LeaseMgr::getDBVersion() { uint16_t family = CfgMgr::instance().getFamily(); if (family == AF_INET6) { - return (Memfile_LeaseMgr::getDBVersion(Memfile_LeaseMgr::V6)); + return (Memfile_LeaseMgr::getDBVersionInternal(Memfile_LeaseMgr::V6)); } else { - return (Memfile_LeaseMgr::getDBVersion(Memfile_LeaseMgr::V4)); + return (Memfile_LeaseMgr::getDBVersionInternal(Memfile_LeaseMgr::V4)); } } @@ -3459,5 +3459,12 @@ Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) { } } +TrackingLeaseMgrPtr +Memfile_LeaseMgr::factory(const isc::db::DatabaseConnection::ParameterMap& parameters) { + LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_DB) + .arg(DatabaseConnection::redactedAccessString(parameters)); + return (TrackingLeaseMgrPtr(new Memfile_LeaseMgr(parameters))); +} + } // namespace dhcp } // namespace isc diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 71229e7466..c283e6296c 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -159,7 +160,7 @@ public: static std::string getDBVersion(); /// @brief Local version of getDBVersion() class method - static std::string getDBVersion(Universe const& u); + static std::string getDBVersionInternal(Universe const& u); /// @brief Adds an IPv4 lease. /// @@ -1562,6 +1563,30 @@ private: /// @param filename File name to write leases. /// Must be called from a thread-safe context. virtual void writeLeases6Internal(const std::string& filename); + +public: + /// @brief Factory class method. + /// + /// @param parameters A data structure relating keywords and values + /// concerned with the database. + /// + /// @return The Memfile Lease Manager. + static TrackingLeaseMgrPtr + factory(const isc::db::DatabaseConnection::ParameterMap& parameters); +}; + +/// @brief Initialization structure used to register and deregister Memfile Lease Mgr. +struct MemfileLeaseMgrInit { + // Constructor registers + MemfileLeaseMgrInit() { + LeaseMgrFactory::registerFactory("memfile", Memfile_LeaseMgr::factory, true, + Memfile_LeaseMgr::getDBVersion); + } + + // Destructor deregisters + ~MemfileLeaseMgrInit() { + LeaseMgrFactory::deregisterFactory("memfile", true); + } }; } // namespace dhcp diff --git a/src/lib/dhcpsrv/tests/host_data_source_factory_unittest.cc b/src/lib/dhcpsrv/tests/host_data_source_factory_unittest.cc index 22d65d4c58..8de96723bf 100644 --- a/src/lib/dhcpsrv/tests/host_data_source_factory_unittest.cc +++ b/src/lib/dhcpsrv/tests/host_data_source_factory_unittest.cc @@ -25,7 +25,10 @@ namespace { // @brief Register memFactory bool registerFactory() { - return (HostDataSourceFactory::registerFactory("mem", memFactory)); + static auto db_version = []() -> std::string { + return (std::string("version 1")); + }; + return (HostDataSourceFactory::registerFactory("mem", memFactory, false, db_version)); } // @brief Derive mem1 class @@ -63,7 +66,10 @@ mem2Factory(const DatabaseConnection::ParameterMap&) { // @brief Register mem2Factory bool registerFactory2() { - return (HostDataSourceFactory::registerFactory("mem2", mem2Factory)); + static auto db_version = []() -> std::string { + return (std::string("version 2")); + }; + return (HostDataSourceFactory::registerFactory("mem2", mem2Factory, false, db_version)); } // @brief Factory function returning 0 @@ -187,6 +193,12 @@ TEST_F(HostDataSourceFactoryTest, multiple) { EXPECT_TRUE(registerFactory2()); EXPECT_NO_THROW(HostDataSourceFactory::add(sources_, "type=mem2")); + EXPECT_EQ("version 2", HostDataSourceFactory::getDBVersions()); + + EXPECT_TRUE(registerFactory()); + + EXPECT_EQ("version 1 version 2", HostDataSourceFactory::getDBVersions()); + // Delete them EXPECT_TRUE(HostDataSourceFactory::del(sources_, "mem1")); EXPECT_TRUE(HostDataSourceFactory::del(sources_, "mem2")); diff --git a/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc index f4741512f6..74e95b7dd9 100644 --- a/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc +++ b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,10 @@ memFactory(const DatabaseConnection::ParameterMap& parameters) { // @brief Register memFactory bool registerFactory() { - return (LeaseMgrFactory::registerFactory("mem", memFactory)); + static auto db_version = []() -> std::string { + return (std::string("version 1")); + }; + return (LeaseMgrFactory::registerFactory("mem", memFactory, false, db_version)); } // @brief Derive mem1 class @@ -86,7 +90,10 @@ mem2Factory(const DatabaseConnection::ParameterMap& parameters) { // @brief Register mem2Factory bool registerFactory2() { - return (LeaseMgrFactory::registerFactory("mem2", mem2Factory)); + static auto db_version = []() -> std::string { + return (std::string("version 2")); + }; + return (LeaseMgrFactory::registerFactory("mem2", mem2Factory, false, db_version)); } // @brief Factory function returning 0 @@ -198,7 +205,8 @@ TEST_F(LeaseMgrFactoryTest, destroy) { } // Verify create and destroy class method on multiple backends -TEST_F(LeaseMgrFactoryTest, multiple) { +TEST_F(LeaseMgrFactoryTest, multipleV4) { + CfgMgr::instance().setFamily(AF_INET); // Add foo twice EXPECT_TRUE(registerFactory1()); EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem1 persist=false universe=4")); @@ -212,6 +220,39 @@ TEST_F(LeaseMgrFactoryTest, multiple) { EXPECT_TRUE(LeaseMgrFactory::haveInstance()); EXPECT_EQ(LeaseMgrFactory::instance().getType(), "mem2"); + EXPECT_EQ("version 2 Memfile backend 3.0", LeaseMgrFactory::getDBVersions()); + + EXPECT_TRUE(registerFactory()); + + EXPECT_EQ("version 1 version 2 Memfile backend 3.0", LeaseMgrFactory::getDBVersions()); + + // Delete them + EXPECT_NO_THROW(LeaseMgrFactory::destroy()); + EXPECT_FALSE(LeaseMgrFactory::haveInstance()); +} + +// Verify create and destroy class method on multiple backends +TEST_F(LeaseMgrFactoryTest, multipleV6) { + CfgMgr::instance().setFamily(AF_INET6); + // Add foo twice + EXPECT_TRUE(registerFactory1()); + EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem1 persist=false universe=4")); + EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem1 persist=false universe=6")); + EXPECT_TRUE(LeaseMgrFactory::haveInstance()); + EXPECT_EQ(LeaseMgrFactory::instance().getType(), "mem1"); + + // Add mem2 once + EXPECT_TRUE(registerFactory2()); + EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem2 persist=false universe=6")); + EXPECT_TRUE(LeaseMgrFactory::haveInstance()); + EXPECT_EQ(LeaseMgrFactory::instance().getType(), "mem2"); + + EXPECT_EQ("version 2 Memfile backend 5.0", LeaseMgrFactory::getDBVersions()); + + EXPECT_TRUE(registerFactory()); + + EXPECT_EQ("version 1 version 2 Memfile backend 5.0", LeaseMgrFactory::getDBVersions()); + // Delete them EXPECT_NO_THROW(LeaseMgrFactory::destroy()); EXPECT_FALSE(LeaseMgrFactory::haveInstance()); diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc index 9edf637dce..f22b5cdee0 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc @@ -2378,7 +2378,7 @@ TEST_F(MemfileLeaseMgrTest, checkVersion4) { // DBVersion too. EXPECT_EQ("Memfile backend " + s.str(), - lease_mgr->getDBVersion(Memfile_LeaseMgr::V4)); + lease_mgr->getDBVersionInternal(Memfile_LeaseMgr::V4)); } TEST_F(MemfileLeaseMgrTest, checkVersion6) { @@ -2403,7 +2403,7 @@ TEST_F(MemfileLeaseMgrTest, checkVersion6) { // DBVersion too. EXPECT_EQ("Memfile backend " + s.str(), - lease_mgr->getDBVersion(Memfile_LeaseMgr::V6)); + lease_mgr->getDBVersionInternal(Memfile_LeaseMgr::V6)); } /// @brief Checks that complex user context can be read in v4.