Commit a3a40b9c authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3569] Implemented configuration for host data source.

parent e66caf26
......@@ -438,7 +438,11 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
parser = new StringParser(config_id,
globalContext()->string_values_);
} else if (config_id.compare("lease-database") == 0) {
parser = new DbAccessParser(config_id, *globalContext());
parser = new DbAccessParser(config_id, DbAccessParser::LEASE_DB,
*globalContext());
} else if (config_id.compare("hosts-database") == 0) {
parser = new DbAccessParser(config_id, DbAccessParser::HOSTS_DB,
*globalContext());
} else if (config_id.compare("hooks-libraries") == 0) {
parser = new HooksLibrariesParser(config_id);
} else if (config_id.compare("echo-client-id") == 0) {
......
......@@ -689,7 +689,11 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
parser = new StringParser(config_id,
globalContext()->string_values_);
} else if (config_id.compare("lease-database") == 0) {
parser = new DbAccessParser(config_id, *globalContext());
parser = new DbAccessParser(config_id, DbAccessParser::LEASE_DB,
*globalContext());
} else if (config_id.compare("hosts-database") == 0) {
parser = new DbAccessParser(config_id, DbAccessParser::HOSTS_DB,
*globalContext());
} else if (config_id.compare("hooks-libraries") == 0) {
parser = new HooksLibrariesParser(config_id);
} else if (config_id.compare("dhcp-ddns") == 0) {
......
......@@ -20,6 +20,7 @@
#include <dhcp/hwaddr.h>
#include <dhcpsrv/host.h>
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace dhcp {
......@@ -214,6 +215,9 @@ public:
virtual void rollback() {};
};
/// @brief HostDataSource pointer
typedef boost::shared_ptr<BaseHostDataSource> HostDataSourcePtr;
}
}
......
......@@ -207,6 +207,14 @@ public:
return (std::string("host_mgr"));
}
/// @brief Returns pointer to the host data source
///
/// May return NULL
/// @return pointer to the host data source (or NULL)
HostDataSourcePtr getHostDataSource() const {
return (alternate_source);
}
private:
/// @brief Private default constructor.
......@@ -215,7 +223,7 @@ private:
/// @brief Pointer to an alternate host data source.
///
/// If this pointer is NULL, the source is not in use.
static boost::shared_ptr<BaseHostDataSource> alternate_source;
HostDataSourcePtr alternate_source;
/// @brief Returns a pointer to the currently used instance of the
/// @c HostMgr.
......
......@@ -17,6 +17,7 @@
#include <dhcp/option.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/parsers/dbaccess_parser.h>
#include <boost/foreach.hpp>
......@@ -34,8 +35,9 @@ namespace dhcp {
// Factory function to build the parser
DbAccessParser::DbAccessParser(const std::string&, const ParserContext& ctx)
: values_(), ctx_(ctx)
DbAccessParser::DbAccessParser(const std::string&, DBType db_type,
const ParserContext& ctx)
: values_(), type_(db_type), ctx_(ctx)
{
}
......@@ -139,11 +141,29 @@ DbAccessParser::getDbAccessString() const {
// Commit the changes - reopen the database with the new parameters
void
DbAccessParser::commit() {
// Close current lease manager database.
LeaseMgrFactory::destroy();
// ... and open the new database using the access string.
LeaseMgrFactory::create(getDbAccessString());
switch (type_) {
case LEASE_DB:
{
// Close current lease manager database.
LeaseMgrFactory::destroy();
// ... and open the new database using the access string.
LeaseMgrFactory::create(getDbAccessString());
break;
}
case HOSTS_DB:
{
// Let's instantiate HostMgr with new parameters. Note that HostMgr's
// constructor will call HostDataSourceFactory::create() with appropriate
// parameters.
HostMgr::create(getDbAccessString());
break;
}
default:
isc_throw(BadValue, "Incorrect type specified in DbAccessParser: "
<< type_);
};
}
}; // namespace dhcp
......
......@@ -45,6 +45,13 @@ public:
/// depend on the database chosen.
class DbAccessParser: public DhcpConfigParser {
public:
/// @brief Specifies the database type
typedef enum {
LEASE_DB = 1,
HOSTS_DB = 2
} DBType;
/// @brief Keyword and associated value
typedef std::pair<std::string, std::string> StringPair;
......@@ -55,8 +62,10 @@ public:
///
/// @param param_name Name of the parameter under which the database
/// access details are held.
/// @param db_type Specifies database type (lease or hosts)
/// @param ctx Parser context.
DbAccessParser(const std::string& param_name, const ParserContext& ctx);
DbAccessParser(const std::string& param_name, DBType db_type,
const ParserContext& ctx);
/// The destructor.
virtual ~DbAccessParser()
......@@ -103,7 +112,14 @@ public:
/// destroying the parser after use.
static DhcpConfigParser* factory(const std::string& param_name,
const ParserContext& ctx) {
return (new DbAccessParser(param_name, ctx));
if (param_name == "lease-database") {
return (new DbAccessParser(param_name, DbAccessParser::LEASE_DB, ctx));
} else if (param_name == "hosts-database") {
return (new DbAccessParser(param_name, DbAccessParser::HOSTS_DB, ctx));
} else {
isc_throw(BadValue, "Unexpected parameter name (" << param_name
<< ") passed to DbAccessParser::factory");
}
}
protected:
......@@ -130,6 +146,8 @@ private:
std::map<std::string, std::string> values_; ///< Stored parameter values
DBType type_; ///< Database type (leases or hosts)
ParserContext ctx_; ///< Parser context
};
......
......@@ -17,6 +17,7 @@
#include <cc/command_interpreter.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/parsers/dbaccess_parser.h>
#include <dhcpsrv/host_mgr.h>
#include <log/logger_support.h>
#include <gtest/gtest.h>
......@@ -201,8 +202,9 @@ public:
/// @brief Constructor
///
/// @brief Keyword/value collection of ddatabase access parameters
TestDbAccessParser(const std::string& param_name, const ParserContext& ctx)
: DbAccessParser(param_name, ctx)
TestDbAccessParser(const std::string& param_name, DbAccessParser::DBType type,
const ParserContext& ctx)
: DbAccessParser(param_name, type, ctx)
{}
/// @brief Destructor
......@@ -243,7 +245,8 @@ TEST_F(DbAccessParserTest, validTypeMemfile) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
EXPECT_NO_THROW(parser.build(json_elements));
checkAccessString("Valid memfile", parser.getDbAccessParameters(), config);
}
......@@ -259,7 +262,8 @@ TEST_F(DbAccessParserTest, emptyKeyword) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
EXPECT_NO_THROW(parser.build(json_elements));
checkAccessString("Valid memfile", parser.getDbAccessParameters(), config);
}
......@@ -276,7 +280,8 @@ TEST_F(DbAccessParserTest, persistV4Memfile) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
EXPECT_NO_THROW(parser.build(json_elements));
checkAccessString("Valid memfile", parser.getDbAccessParameters(),
......@@ -295,7 +300,8 @@ TEST_F(DbAccessParserTest, persistV6Memfile) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V6));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V6));
EXPECT_NO_THROW(parser.build(json_elements));
checkAccessString("Valid memfile", parser.getDbAccessParameters(),
......@@ -314,7 +320,8 @@ TEST_F(DbAccessParserTest, validLFCInterval) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V6));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V6));
ASSERT_NO_THROW(parser.build(json_elements));
checkAccessString("Valid LFC Interval", parser.getDbAccessParameters(),
config, Option::V6);
......@@ -332,7 +339,8 @@ TEST_F(DbAccessParserTest, negativeLFCInterval) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V6));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V6));
EXPECT_THROW(parser.build(json_elements), BadValue);
}
......@@ -348,7 +356,8 @@ TEST_F(DbAccessParserTest, largeLFCInterval) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V6));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V6));
EXPECT_THROW(parser.build(json_elements), BadValue);
}
......@@ -365,7 +374,8 @@ TEST_F(DbAccessParserTest, validTypeMysql) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
EXPECT_NO_THROW(parser.build(json_elements));
checkAccessString("Valid mysql", parser.getDbAccessParameters(), config);
}
......@@ -382,7 +392,8 @@ TEST_F(DbAccessParserTest, missingTypeKeyword) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
EXPECT_THROW(parser.build(json_elements), TypeKeywordMissing);
}
......@@ -442,7 +453,8 @@ TEST_F(DbAccessParserTest, incrementalChanges) {
"name", "keatest",
NULL};
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
// First configuration string should cause a representation of that string
// to be held.
......@@ -506,7 +518,8 @@ TEST_F(DbAccessParserTest, getDbAccessString) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
EXPECT_NO_THROW(parser.build(json_elements));
// Get the database access string
......@@ -518,10 +531,10 @@ TEST_F(DbAccessParserTest, getDbAccessString) {
EXPECT_EQ(dbaccess, "name=keatest type=mysql universe=4");
}
// Check that the "commit" function actually opens the database. We will
// only do this for the "memfile" database, as that does not assume that the
// test has been built with MySQL support.
TEST_F(DbAccessParserTest, commit) {
// Check that the "commit" function actually opens the database, when type
// is set to LEASE_DB. We will only do this for the "memfile" database, as
// that does not assume that the test has been built with MySQL support.
TEST_F(DbAccessParserTest, commitLeaseDb) {
// Verify that no lease database is open
EXPECT_THROW({
......@@ -536,7 +549,8 @@ TEST_F(DbAccessParserTest, commit) {
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("lease-database", ParserContext(Option::V4));
TestDbAccessParser parser("lease-database", DbAccessParser::LEASE_DB,
ParserContext(Option::V4));
EXPECT_NO_THROW(parser.build(json_elements));
// Ensure that the access string is as expected.
......@@ -552,4 +566,46 @@ TEST_F(DbAccessParserTest, commit) {
EXPECT_EQ(std::string("memfile"), dbtype);
}
// Check that the "commit" function actually opens the database, when type
// is set to HOSTS_DB.
TEST_F(DbAccessParserTest, commitHostsDb) {
// Verify that no lease database is open
EXPECT_THROW({
LeaseMgr& manager = LeaseMgrFactory::instance();
manager.getType(); // Never executed but satisfies compiler
}, isc::dhcp::NoLeaseManager);
// Set up the parser to open the memfile database.
const char* config[] = {"type", "memfile", "persist", "false", NULL};
string json_config = toJson(config);
ConstElementPtr json_elements = Element::fromJSON(json_config);
EXPECT_TRUE(json_elements);
TestDbAccessParser parser("hosts-database", DbAccessParser::HOSTS_DB,
ParserContext(Option::V4));
EXPECT_NO_THROW(parser.build(json_elements));
// Ensure that the access string is as expected.
EXPECT_EQ("persist=false type=memfile universe=4",
parser.getDbAccessString());
// Destroy lease mgr (if there's any)
LeaseMgrFactory::destroy();
// Committal of the parser changes should not create LeaseMgr.
// It should create HostDataSource instead.
EXPECT_NO_THROW(parser.commit());
// Check that LeaseMgr was NOT created (it shouldn't, this is for HOSTS_DB.
EXPECT_THROW(LeaseMgrFactory::instance(), NoLeaseManager);
HostDataSourcePtr hds = HostMgr::instance().getHostDataSource();
/// @todo: Uncomment this once 3682 is merged. The whole unit-test
/// should create MySQL database and be ifdefed appropriately.
// ASSERT_TRUE(hds);
}
}; // Anonymous namespace
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment