From: Tomek Mrugalski Date: Tue, 24 Nov 2015 20:42:19 +0000 (+0100) Subject: [3569] Implemented configuration for host data source. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e851537ed3b7664843d4452ffc358c2a9f8497d;p=thirdparty%2Fkea.git [3569] Implemented configuration for host data source. --- diff --git a/src/bin/dhcp4/json_config_parser.cc b/src/bin/dhcp4/json_config_parser.cc index d9c381e33c..65ce90a31c 100644 --- a/src/bin/dhcp4/json_config_parser.cc +++ b/src/bin/dhcp4/json_config_parser.cc @@ -439,7 +439,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) { diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index fe0af18311..1e203323e3 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -688,7 +688,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) { diff --git a/src/lib/dhcpsrv/base_host_data_source.h b/src/lib/dhcpsrv/base_host_data_source.h index aae1676e3c..b566134703 100644 --- a/src/lib/dhcpsrv/base_host_data_source.h +++ b/src/lib/dhcpsrv/base_host_data_source.h @@ -20,6 +20,7 @@ #include #include #include +#include namespace isc { namespace dhcp { @@ -182,6 +183,9 @@ public: }; +/// @brief HostDataSource pointer +typedef boost::shared_ptr HostDataSourcePtr; + } } diff --git a/src/lib/dhcpsrv/host_mgr.h b/src/lib/dhcpsrv/host_mgr.h index 55a4f4c05e..193e8441fa 100644 --- a/src/lib/dhcpsrv/host_mgr.h +++ b/src/lib/dhcpsrv/host_mgr.h @@ -198,6 +198,14 @@ public: /// @param host Pointer to the new @c Host object being added. virtual void add(const HostPtr& host); + /// @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. @@ -206,7 +214,7 @@ private: /// @brief Pointer to an alternate host data source. /// /// If this pointer is NULL, the source is not in use. - boost::scoped_ptr alternate_source; + HostDataSourcePtr alternate_source; /// @brief Returns a pointer to the currently used instance of the /// @c HostMgr. diff --git a/src/lib/dhcpsrv/parsers/dbaccess_parser.cc b/src/lib/dhcpsrv/parsers/dbaccess_parser.cc index e848109228..b46a6887f1 100644 --- a/src/lib/dhcpsrv/parsers/dbaccess_parser.cc +++ b/src/lib/dhcpsrv/parsers/dbaccess_parser.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -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 diff --git a/src/lib/dhcpsrv/parsers/dbaccess_parser.h b/src/lib/dhcpsrv/parsers/dbaccess_parser.h index 797dd5d888..652730bf3c 100644 --- a/src/lib/dhcpsrv/parsers/dbaccess_parser.h +++ b/src/lib/dhcpsrv/parsers/dbaccess_parser.h @@ -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 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 values_; ///< Stored parameter values + DBType type_; ///< Database type (leases or hosts) + ParserContext ctx_; ///< Parser context }; diff --git a/src/lib/dhcpsrv/tests/dbaccess_parser_unittest.cc b/src/lib/dhcpsrv/tests/dbaccess_parser_unittest.cc index e7450aa259..59c9ca6428 100644 --- a/src/lib/dhcpsrv/tests/dbaccess_parser_unittest.cc +++ b/src/lib/dhcpsrv/tests/dbaccess_parser_unittest.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -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