// 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':
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.
#ifdef HAVE_MYSQL
#include <mysql/testutils/mysql_schema.h>
+#include <hooks/dhcp/mysql_hb/mysql_host_data_source.h>
#endif
#ifdef HAVE_PGSQL
#include <pgsql/testutils/pgsql_schema.h>
+#include <hooks/dhcp/pgsql_hb/pgsql_host_data_source.h>
#endif
#include <boost/scoped_ptr.hpp>
// 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':
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.
#ifdef HAVE_MYSQL
#include <mysql/testutils/mysql_schema.h>
+#include <hooks/dhcp/mysql_hb/mysql_host_data_source.h>
#endif
#ifdef HAVE_PGSQL
#include <pgsql/testutils/pgsql_schema.h>
+#include <hooks/dhcp/pgsql_hb/pgsql_host_data_source.h>
#endif
#include <boost/pointer_cast.hpp>
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 << ")";
}
// 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);
/// @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);
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
/// @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);
}
};
}
// 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);
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
}
// 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);
/// @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);
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
/// @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);
}
};
}
// 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);
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
namespace isc {
namespace dhcp {
-map<string, HostDataSourceFactory::Factory> HostDataSourceFactory::map_;
+map<string, pair<HostDataSourceFactory::Factory, HostDataSourceFactory::DBVersion>> HostDataSourceFactory::map_;
void
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()) {
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<string, Factory>(db_type, factory));
+
+ static auto default_db_version = []() -> std::string {
+ return (std::string());
+ };
+
+ if (!db_version) {
+ db_version = default_db_version;
+ }
+
+ map_.insert(pair<string, pair<Factory, DBVersion>>(db_type, pair<Factory, DBVersion>(factory, db_version)));
// We are dealing here with static logger initialization fiasco.
// registerFactory may be called from constructors of static global
if (!txt.str().empty()) {
txt << " ";
}
- txt << x.first;
+ txt << x.second.second();
}
return (txt.str());
/// data source. In case of failure it must throw and not return null.
typedef std::function<HostDataSourcePtr (const db::DatabaseConnection::ParameterMap&)> Factory;
+ /// @brief Type of host mgr version
+ typedef std::function<std::string ()> DBVersion;
+
/// @brief Register a host data source factory
///
/// Associate the factory to a database type in the map.
/// @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
///
private:
/// @brief Factory map
- static std::map<std::string, Factory> map_;
+ static std::map<std::string, std::pair<Factory, DBVersion>> map_;
};
} // end of isc::dhcp namespace
namespace isc {
namespace dhcp {
-map<string, LeaseMgrFactory::Factory> LeaseMgrFactory::map_;
+map<string, pair<LeaseMgrFactory::Factory, LeaseMgrFactory::DBVersion>> LeaseMgrFactory::map_;
+
+/// @brief Initializer.
+MemfileLeaseMgrInit memfile_init;
TrackingLeaseMgrPtr&
LeaseMgrFactory::getLeaseMgrPtr() {
"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);
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]);
}
// Call the factory.
- getLeaseMgrPtr() = index->second(parameters);
+ getLeaseMgrPtr() = index->second.first(parameters);
// Check the factory did not return null.
if (!getLeaseMgrPtr()) {
.arg(getLeaseMgrPtr()->getType());
}
getLeaseMgrPtr().reset();
- LeaseMgrFactory::deregisterFactory("memfile", true);
}
void
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<string, Factory>(db_type, factory));
+
+ static auto default_db_version = []() -> std::string {
+ return (std::string());
+ };
+
+ if (!db_version) {
+ db_version = default_db_version;
+ }
+
+ map_.insert(pair<string, pair<Factory, DBVersion>>(db_type, pair<Factory, DBVersion>(factory, db_version)));
// We are dealing here with static logger initialization fiasco.
// registerFactory may be called from constructors of static global
if (!txt.str().empty()) {
txt << " ";
}
- txt << x.first;
+ txt << x.second.second();
}
return (txt.str());
/// In case of failure it must throw and not return null.
typedef std::function<TrackingLeaseMgrPtr (const db::DatabaseConnection::ParameterMap&)> Factory;
+ /// @brief Type of lease mgr version
+ typedef std::function<std::string ()> DBVersion;
+
/// @brief Register a lease mgr factory
///
/// Associate the factory to a database type in the map.
/// @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
///
static TrackingLeaseMgrPtr& getLeaseMgrPtr();
/// @brief Factory map
- static std::map<std::string, Factory> map_;
+ static std::map<std::string, std::pair<Factory, DBVersion>> map_;
};
} // end of isc::dhcp namespace
}
std::string
-Memfile_LeaseMgr::getDBVersion(Universe const& u) {
+Memfile_LeaseMgr::getDBVersionInternal(Universe const& u) {
std::stringstream tmp;
tmp << "Memfile backend ";
if (u == V4) {
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));
}
}
}
}
+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
#include <dhcp/hwaddr.h>
#include <dhcpsrv/csv_lease_file4.h>
#include <dhcpsrv/csv_lease_file6.h>
+#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/memfile_lease_limits.h>
#include <dhcpsrv/memfile_lease_storage.h>
#include <dhcpsrv/tracking_lease_mgr.h>
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.
///
/// @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
// @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
// @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
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"));
#include <asiolink/io_address.h>
#include <database/database_connection.h>
+#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/memfile_lease_mgr.h>
#include <dhcpsrv/tracking_lease_mgr.h>
// @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
// @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
}
// 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"));
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());
// DBVersion too.
EXPECT_EQ("Memfile backend " + s.str(),
- lease_mgr->getDBVersion(Memfile_LeaseMgr::V4));
+ lease_mgr->getDBVersionInternal(Memfile_LeaseMgr::V4));
}
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.