Commit 52dad7c3 authored by Marcin Siodelski's avatar Marcin Siodelski

[#93,!56] Updated MySQL config backend to manage global parameters.

parent 7c1a92b0
This diff is collapsed.
......@@ -118,53 +118,53 @@ public:
/// @brief Retrieves single option by code and space.
///
/// @param selector Server selector.
/// @param server_selector Server selector.
/// @return Pointer to the retrieved option descriptor or null if
/// no option was found.
virtual OptionDescriptorPtr
getOption4(const db::ServerSelector& selector, const uint16_t code,
getOption4(const db::ServerSelector& server_selector, const uint16_t code,
const std::string& space) const;
/// @brief Retrieves all global options.
///
/// @param selector Server selector.
/// @param server_selector Server selector.
/// @return Collection of global options or empty collection if no
/// option found.
virtual OptionContainer
getAllOptions4(const db::ServerSelector& selector) const;
getAllOptions4(const db::ServerSelector& server_selector) const;
/// @brief Retrieves option modified after specified time.
///
/// @param selector Server selector.
/// @param server_selector Server selector.
/// @param modification_time Lower bound option modification time.
/// @return Collection of global options or empty collection if no
/// option found.
virtual OptionContainer
getModifiedOptions4(const db::ServerSelector& selector,
getModifiedOptions4(const db::ServerSelector& server_selector,
const boost::posix_time::ptime& modification_time) const;
/// @brief Retrieves global string parameter value.
/// @brief Retrieves global parameter value.
///
/// @param server_selector Server selector.
/// @param name Name of the global parameter to be retrieved.
/// @return Value of the global string parameter.
virtual util::OptionalValue<std::string>
getGlobalStringParameter4(const db::ServerSelector& server_selector,
const std::string& name) const;
/// @return Value of the global parameter.
virtual data::StampedValuePtr
getGlobalParameter4(const db::ServerSelector& server_selector,
const std::string& name) const;
/// @brief Retrieves global number parameter.
/// @brief Retrieves all global parameters.
///
/// @param server_selector Server selector.
/// @param name Name of the parameter to be retrieved.
virtual util::OptionalValue<int64_t>
getGlobalNumberParameter4(const db::ServerSelector& server_selector,
const std::string& name) const;
virtual data::StampedValueCollection
getAllGlobalParameters4(const db::ServerSelector& server_selector) const;
/// @brief Retrieves all global parameters as strings.
/// @brief Retrieves global parameters modified after specified time.
///
/// @param server_selector Server selector.
virtual std::map<std::string, std::string>
getAllGlobalParameters4(const db::ServerSelector& server_selector) const;
/// @param modification_time Lower bound modification time.
/// @return Collection of modified global parameters.
virtual data::StampedValueCollection
getModifiedGlobalParameters4(const db::ServerSelector& server_selector,
const boost::posix_time::ptime& modification_time) const;
/// @brief Creates or updates a subnet.
///
......@@ -200,12 +200,12 @@ public:
/// @brief Creates or updates shared network level option.
///
/// @param selector Server selector.
/// @param server_selector Server selector.
/// @param shared_network_name Name of a shared network to which option
/// belongs.
/// @param option Option to be added or updated.
virtual void
createUpdateOption4(const db::ServerSelector& selector,
createUpdateOption4(const db::ServerSelector& server_selector,
const std::string& shared_network_name,
const OptionDescriptorPtr& option);
......@@ -233,25 +233,14 @@ public:
const asiolink::IOAddress& pool_end_address,
const OptionDescriptorPtr& option);
/// @brief Creates or updates global string parameter.
/// @brief Creates or updates global parameter.
///
/// @param server_selector Server selector.
/// @param name Name of the global parameter.
/// @param value Value of the global parameter.
virtual void
createUpdateGlobalParameter4(const db::ServerSelector& server_selector,
const std::string& name,
const std::string& value);
/// @brief Creates or updates global number parameter.
///
/// @param server_selector Server selector.
/// @param name Name of the global parameter.
/// @param value Value of the global parameter.
virtual void
createUpdateGlobalParameter4(const db::ServerSelector& server_selector,
const std::string& name,
const int64_t value);
const data::StampedValuePtr& value);
/// @brief Deletes subnet by prefix.
///
......@@ -322,13 +311,13 @@ public:
/// @brief Deletes shared network level option.
///
/// @param selector Server selector.
/// @param server_selector Server selector.
/// @param shared_network_name Name of the shared network which deleted
/// option belongs to
/// @param code Code of the deleted option.
/// @param space Option space of the deleted option.
virtual uint64_t
deleteOption4(const db::ServerSelector& selector,
deleteOption4(const db::ServerSelector& server_selector,
const std::string& shared_network_name,
const uint16_t code,
const std::string& space);
......
......@@ -302,6 +302,99 @@ public:
boost::shared_ptr<ConfigBackendDHCPv4> cbptr_;
};
// This test verifies that the global parameter can be added, updated and
// deleted.
TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteGlobalParameter4) {
StampedValuePtr server_tag = StampedValue::create("server-tag", "whale");
// Explicitly set modification time to make sure that the time
// returned from the database is correct.
server_tag->setModificationTime(timestamps_["yesterday"]);
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
server_tag);
// Verify returned parameter and the modification time.
StampedValuePtr returned_server_tag =
cbptr_->getGlobalParameter4(ServerSelector::UNASSIGNED(), "server-tag");
ASSERT_TRUE(returned_server_tag);
EXPECT_EQ("server-tag", returned_server_tag->getName());
EXPECT_EQ("whale", returned_server_tag->getValue());
EXPECT_TRUE(returned_server_tag->getModificationTime() ==
server_tag->getModificationTime());
// Check that the parameter is udpated when it already exists in
// the database.
server_tag = StampedValue::create("server-tag", "fish");
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
server_tag);
returned_server_tag = cbptr_->getGlobalParameter4(ServerSelector::UNASSIGNED(),
"server-tag");
ASSERT_TRUE(returned_server_tag);
EXPECT_EQ("server-tag", returned_server_tag->getName());
EXPECT_EQ("fish", returned_server_tag->getValue());
EXPECT_TRUE(returned_server_tag->getModificationTime() ==
server_tag->getModificationTime());
// Delete parameter and make sure it is gone.
cbptr_->deleteGlobalParameter4(ServerSelector::UNASSIGNED(), "server-tag");
returned_server_tag = cbptr_->getGlobalParameter4(ServerSelector::UNASSIGNED(),
"server-tag");
EXPECT_FALSE(returned_server_tag);
}
// This test verifies that all global parameters can be retrieved and deleted.
TEST_F(MySqlConfigBackendDHCPv4Test, getAllGlobalParameters4) {
// Create 3 parameters and put them into the database.
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
StampedValue::create("name1", "value1"));
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
StampedValue::create("name2", 65));
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
StampedValue::create("name3", "value3"));
// Fetch all parameters.
auto parameters = cbptr_->getAllGlobalParameters4(ServerSelector::UNASSIGNED());
ASSERT_EQ(3, parameters.size());
// Verify their values.
EXPECT_EQ("value1", parameters[0]->getValue());
EXPECT_EQ(65, parameters[1]->getSignedIntegerValue());
EXPECT_EQ("value3", parameters[2]->getValue());
// Delete all parameters and make sure they are gone.
cbptr_->deleteAllGlobalParameters4(ServerSelector::UNASSIGNED());
parameters = cbptr_->getAllGlobalParameters4(ServerSelector::UNASSIGNED());
EXPECT_TRUE(parameters.empty());
}
// This test verifies that modified global parameters can be retrieved.
TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedGlobalParameters4) {
// Create 3 global parameters and assign modification times:
// "yesterday", "today" and "tomorrow" respectively.
StampedValuePtr value = StampedValue::create("name1", "value1");
value->setModificationTime(timestamps_["yesterday"]);
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
value);
value = StampedValue::create("name2", 65);
value->setModificationTime(timestamps_["today"]);
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
value);
value = StampedValue::create("name3", "value3");
value->setModificationTime(timestamps_["tomorrow"]);
cbptr_->createUpdateGlobalParameter4(ServerSelector::UNASSIGNED(),
value);
// Get parameters modified after "today".
auto parameters = cbptr_->getModifiedGlobalParameters4(ServerSelector::UNASSIGNED(),
timestamps_["today"]);
// It should be the one modified "tomorrow".
ASSERT_EQ(1, parameters.size());
ASSERT_TRUE(parameters[0]);
EXPECT_EQ("value3", parameters[0]->getValue());
}
// Test that subnet can be inserted, fetched, updated and then fetched again.
TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4) {
// Insert new subnet.
......
......@@ -11,12 +11,15 @@
namespace isc {
namespace data {
StampedValue::StampedValue(const std::string& value)
: StampedElement(), value_(value) {
StampedValue::StampedValue(const std::string& name,
const std::string& value)
: StampedElement(), name_(name), value_(value) {
}
StampedValue::StampedValue(const int64_t value)
: StampedElement(), value_() {
StampedValue::StampedValue(const std::string& name,
const int64_t value)
: StampedElement(), name_(name), value_() {
try {
value_ = boost::lexical_cast<std::string>(value);
} catch (...) {
......@@ -25,6 +28,19 @@ StampedValue::StampedValue(const int64_t value)
}
}
StampedValuePtr
StampedValue::create(const std::string& name,
const std::string& value) {
return (StampedValuePtr(new StampedValue(name, value)));
}
StampedValuePtr
StampedValue::create(const std::string& name,
const int64_t value) {
return (StampedValuePtr(new StampedValue(name, value)));
}
int64_t
StampedValue::getSignedIntegerValue() const {
if (!value_.empty()) {
......
......@@ -15,6 +15,14 @@
namespace isc {
namespace data {
class StampedValue;
/// @brief Pointer to the stamped value.
typedef boost::shared_ptr<StampedValue> StampedValuePtr;
/// @brief Collection of pointers to values.
typedef std::vector<StampedValuePtr> StampedValueCollection;
/// @brief This class represents string or signed integer configuration
/// element associated with the modification timestamp.
///
......@@ -33,17 +41,38 @@ public:
///
/// Creates stamped value from a string.
///
/// @param name Name of the value.
/// @param value Value to be set.
explicit StampedValue(const std::string& value);
StampedValue(const std::string& name, const std::string& value);
/// @brief Constructor.
///
/// Creates stamped value from the signed integer.
///
/// @param name Name of the value.
/// @param value Value to be set.
explicit StampedValue(const int64_t value);
explicit StampedValue(const std::string& name, const int64_t value);
/// @brief Convenience function creating shared pointer to the object.
///
/// @param name Name of the value.
/// @param value String value to be encapsulated by this object.
static StampedValuePtr create(const std::string& name,
const std::string& value);
/// @brief Convenience function creating shared Pointer to the object.
///
/// @param name Name of the value.
/// @param value Integer value to be encapsulated by this object.
static StampedValuePtr create(const std::string& name,
const int64_t value);
/// @brief Returns value as string.
/// @brief Returns value name.
std::string getName() const {
return (name_);
}
/// @Brief Returns value as string.
std::string getValue() const {
return (value_);
}
......@@ -55,6 +84,9 @@ public:
private:
/// @brief Name of the value.
std::string name_;
/// @brief Holds value as a string.
std::string value_;
};
......
......@@ -19,7 +19,8 @@ namespace {
// Tests that stamped value from string can be created.
TEST(StampedValueTest, createFromString) {
boost::scoped_ptr<StampedValue> value;
ASSERT_NO_THROW(value.reset(new StampedValue("foo")));
ASSERT_NO_THROW(value.reset(new StampedValue("bar", "foo")));
EXPECT_EQ("bar", value->getName());
EXPECT_EQ("foo", value->getValue());
EXPECT_THROW(value->getSignedIntegerValue(), BadValue);
}
......@@ -27,7 +28,8 @@ TEST(StampedValueTest, createFromString) {
// Tests that stamped value from integer can be created.
TEST(StampedValueTest, createFromInteger) {
boost::scoped_ptr<StampedValue> value;
ASSERT_NO_THROW(value.reset(new StampedValue(5)));
ASSERT_NO_THROW(value.reset(new StampedValue("bar", 5)));
EXPECT_EQ("bar", value->getName());
EXPECT_EQ("5", value->getValue());
int64_t signed_integer;
ASSERT_NO_THROW(signed_integer = value->getSignedIntegerValue());
......
......@@ -12,7 +12,6 @@
#include <database/backend_selector.h>
#include <database/db_exceptions.h>
#include <database/server_selector.h>
#include <util/optional_value.h>
#include <functional>
#include <list>
#include <string>
......@@ -147,87 +146,6 @@ protected:
}
}
/// @brief Retrieve a single value encapsulated in the @c OptionalValue
/// template.
///
/// This is common method for retrieving a single configuration property
/// from the databases. The property is encapsulated in the @c OptionalValue
/// class. The value is set to "unspecified" if it is null in the database.
/// The following is the example implementation of the method retrieving
/// global conifguration value:
///
/// @code
/// OptionalValue<std::string>
/// getGlobalParameter4(const std::string& parameter_name,
/// const BackendSelector& backend_selector,
/// const ServerSelector& server_selector) const {
/// std::string parameter;
/// getOptionalPropertyConst<std::string, const std::string&>
/// (&ConfigBackendDHCPv4::getGlobalParameter4, backend_selector,
/// server_selector, parameter, parameter_name);
/// return (parameter);
/// }
/// @endcode
///
/// where @c ConfigBackendDHCPv4::getGlobalParameter has the following signature:
///
/// @code
/// std::string getGlobalParameter4(const ServerSelector&, const std::string&) const;
/// @endcode
///
///
/// @tparam PropertyType Type of the object returned by the backend call.
/// @tparam FnPtrArgs Parameter pack holding argument types of the backend
/// method to be invoked.
/// @tparam Args Parameter pack holding types of the arguments provided
/// in the call to this method.
///
/// @param MethodPointer Pointer to the backend method to be called.
/// @param backend_selector Backend selector.
/// @param server_selector Server selector.
/// @param [out] property Reference to the shared pointer where retrieved
/// property should be assigned.
/// @param input Values to be used as input to the backend call.
///
/// @throw db::NoSuchDatabase if no database matching the given selector
/// was found.
template<typename PropertyType, typename... FnPtrArgs, typename... Args>
void getOptionalPropertyConst(util::OptionalValue<PropertyType>
(ConfigBackendType::*MethodPointer)
(const db::ServerSelector&, FnPtrArgs...) const,
const db::BackendSelector& backend_selector,
const db::ServerSelector& server_selector,
util::OptionalValue<PropertyType>& property,
Args... input) const {
// If no particular backend is selected, call each backend and return
// the first non-null (non zero) value.
if (backend_selector.amUnspecified()) {
for (auto backend : backends_) {
property = ((*backend).*MethodPointer)(server_selector, input...);
if (property.isSpecified()) {
break;
}
}
} else {
// Backend selected, find the one that matches selection.
auto backends = selectBackends(backend_selector);
if (!backends.empty()) {
for (auto backend : backends) {
property = ((*backend).*MethodPointer)(server_selector, input...);
if (property.isSpecified()) {
break;
}
}
} else {
isc_throw(db::NoSuchDatabase, "no such database found for selector: "
<< backend_selector.toText());
}
}
}
/// @brief Retrieve multiple configuration properties from the pool.
///
/// This is a common method for retrieving multiple configuration properties
......
......@@ -7,6 +7,7 @@
#ifndef CONFIG_BACKEND_DHCP4_H
#define CONFIG_BACKEND_DHCP4_H
#include <cc/stamped_value.h>
#include <config_backend/base_config_backend.h>
#include <database/server_selector.h>
#include <dhcp/option.h>
......@@ -14,9 +15,7 @@
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/shared_network.h>
#include <dhcpsrv/subnet.h>
#include <util/optional_value.h>
#include <boost/date_time/posix_time/ptime.hpp>
#include <map>
#include <string>
namespace isc {
......@@ -120,20 +119,20 @@ public:
/// @brief Retrieves single option by code and space.
///
/// @param selector Server selector.
/// @param server_selector Server selector.
/// @return Pointer to the retrieved option descriptor or null if
/// no option was found.
virtual OptionDescriptorPtr
getOption4(const db::ServerSelector& selector, const uint16_t code,
getOption4(const db::ServerSelector& server_selector, const uint16_t code,
const std::string& space) const = 0;
/// @brief Retrieves all global options.
///
/// @param selector Server selector.
/// @param server_selector Server selector.
/// @return Collection of global options or empty collection if no
/// option found.
virtual OptionContainer
getAllOptions4(const db::ServerSelector& selector) const = 0;
getAllOptions4(const db::ServerSelector& server_selector) const = 0;
/// @brief Retrieves option modified after specified time.
///
......@@ -145,28 +144,27 @@ public:
getModifiedOptions4(const db::ServerSelector& selector,
const boost::posix_time::ptime& modification_time) const = 0;
/// @brief Retrieves global string parameter value.
/// @brief Retrieves global parameter value.
///
/// @param server_selector Server selector.
/// @param name Name of the global parameter to be retrieved.
/// @return Value of the global string parameter.
virtual util::OptionalValue<std::string>
getGlobalStringParameter4(const db::ServerSelector& server_selector,
const std::string& name) const = 0;
/// @return Value of the global parameter or null if parameter doesn't
/// exist.
virtual data::StampedValuePtr
getGlobalParameter4(const db::ServerSelector& selector,
const std::string& name) const = 0;
/// @brief Retrieves global number parameter.
///
/// @param server_selector Server selector.
/// @param name Name of the parameter to be retrieved.
virtual util::OptionalValue<int64_t>
getGlobalNumberParameter4(const db::ServerSelector& server_selector,
const std::string& name) const = 0;
/// @return Collection of global parameters.
virtual data::StampedValueCollection
getAllGlobalParameters4(const db::ServerSelector& selector) const = 0;
/// @brief Retrieves all global parameters as strings.
/// @brief Retrieves global parameters modified after specified time.
///
/// @param server_selector Server selector.
virtual std::map<std::string, std::string>
getAllGlobalParameters4(const db::ServerSelector& server_selector) const = 0;
/// @param selector Server selector.
/// @return Collection of modified global parameters.
virtual data::StampedValueCollection
getModifiedGlobalParameters4(const db::ServerSelector& selector,
const boost::posix_time::ptime& modification_time) const = 0;
/// @brief Creates or updates a subnet.
///
......@@ -235,26 +233,14 @@ public:
const asiolink::IOAddress& pool_end_address,
const OptionDescriptorPtr& option) = 0;
/// @brief Creates or updates global string parameter.
/// @brief Creates or updates global parameter.
///
/// @param server_selector Server selector.
/// @param name Name of the global parameter.
/// @param value Value of the global parameter.
virtual void
createUpdateGlobalParameter4(const db::ServerSelector& server_selector,
const std::string& name,
const std::string& value) = 0;
const data::StampedValuePtr& value) = 0;
/// @brief Creates or updates global number parameter.
///
/// @param server_selector Server selector.
/// @param name Name of the global parameter.
/// @param value Value of the global parameter.
virtual void
createUpdateGlobalParameter4(const db::ServerSelector& server_selector,
const std::string& name,
const int64_t value) = 0;
/// @brief Deletes subnet by prefix.
///
/// @param server_selector Server selector.
......
......@@ -8,8 +8,8 @@
#include <dhcpsrv/config_backend_pool_dhcp4.h>
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::db;
using namespace isc::util;
namespace isc {
namespace dhcp {
......@@ -156,38 +156,39 @@ ConfigBackendPoolDHCPv4::getModifiedOptions4(const BackendSelector& backend_sele
return (options);
}
util::OptionalValue<std::string>
ConfigBackendPoolDHCPv4::getGlobalStringParameter4(const BackendSelector& backend_selector,
const ServerSelector& server_selector,
const std::string& name) const {
OptionalValue<std::string> parameter;
getOptionalPropertyConst<std::string, const std::string&>
(&ConfigBackendDHCPv4::getGlobalStringParameter4, backend_selector,
server_selector, parameter, name);
return (parameter);
}
util::OptionalValue<int64_t>
ConfigBackendPoolDHCPv4::getGlobalNumberParameter4(const BackendSelector& backend_selector,
const ServerSelector& server_selector,
const std::string& name) const {
OptionalValue<int64_t> parameter;
getOptionalPropertyConst<int64_t, const std::string&>
(&ConfigBackendDHCPv4::getGlobalNumberParameter4, backend_selector,
server_selector, parameter, name);
return (parameter);
StampedValuePtr
ConfigBackendPoolDHCPv4::getGlobalParameter4(const BackendSelector& backend_selector,
const ServerSelector& server_selector,
const std::string& name) const {
StampedValuePtr parameter;
getPropertyPtrConst<StampedValuePtr, const std::string&>
(&ConfigBackendDHCPv4::getGlobalParameter4, backend_selector,
server_selector, parameter, name);
return (parameter);
}
std::map<std::string, std::string>
StampedValueCollection
ConfigBackendPoolDHCPv4::getAllGlobalParameters4(const BackendSelector& backend_selector,
const ServerSelector& server_selector) const {
std::map<std::string, std::string> parameters;
getAllPropertiesConst<std::map<std::string, std::string> >
StampedValueCollection parameters;
getAllPropertiesConst<StampedValueCollection>
(&ConfigBackendDHCPv4::getAllGlobalParameters4, backend_selector,
server_selector, parameters);
return (parameters);
}
StampedValueCollection
ConfigBackendPoolDHCPv4::
getModifiedGlobalParameters4(const db::BackendSelector& backend_selector,
const db::ServerSelector& server_selector,
const boost::posix_time::ptime& modification_time) const {
StampedValueCollection parameters;
getMultiplePropertiesConst<StampedValueCollection, const boost::posix_time::ptime&>
(&ConfigBackendDHCPv4::getModifiedGlobalParameters4, backend_selector,
server_selector, parameters, modification_time);
return (parameters);
}
void
ConfigBackendPoolDHCPv4::createUpdateSubnet4(const BackendSelector& backend_selector,
const ServerSelector& server_selector,
......@@ -260,23 +261,12 @@ ConfigBackendPoolDHCPv4::createUpdateOption4(const BackendSelector& backend_sele
void
ConfigBackendPoolDHCPv4::createUpdateGlobalParameter4(const BackendSelector& backend_selector,
const ServerSelector& server_selector,
const std::string& name,
const std::string& value) {
createUpdateDeleteProperty<void, const std::string&, const std::string&>
const StampedValuePtr& value) {
createUpdateDeleteProperty<void, const StampedValuePtr&>
(&ConfigBackendDHCPv4::createUpdateGlobalParameter4, backend_selector,
server_selector, name, value);
server_selector, value);
}
void
ConfigBackendPoolDHCPv4::createUpdateGlobalParameter4(const BackendSelector& backend_selector,
const ServerSelector& server_selector,
const std::string& name,
const int64_t value) {
createUpdateDeleteProperty<void, const std::string&, int64_t>
(&ConfigBackendDHCPv4::createUpdateGlobalParameter4, backend_selector,
server_selector, name, value);
}
uint64_t