Commit 194f7617 authored by Marcin Siodelski's avatar Marcin Siodelski

[#99,!176] Implemented test config backend for DHCPv4.

parent 7fbbfde2
......@@ -8,6 +8,10 @@
#define STAMPED_VALUE_H
#include <cc/stamped_element.h>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/shared_ptr.hpp>
#include <cstdint>
#include <string>
......@@ -20,9 +24,6 @@ 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.
///
......@@ -91,8 +92,43 @@ private:
std::string value_;
};
/// @brief Pointer to the stamped value.
typedef boost::shared_ptr<StampedValue> StampedValuePtr;
/// @name Definition of the multi index container for @c StampedValue.
///
//@{
/// @brief Tag for the index for access by value name.
struct StampedValueNameIndexTag { };
/// @brief Tag for the index for access by modification time.
struct StampedValueModificationTimeIndexTag { };
/// @brief Multi index container for @c StampedValue.
typedef boost::multi_index_container<
StampedValuePtr,
boost::multi_index::indexed_by<
// Index used to access value by name.
boost::multi_index::hashed_non_unique<
boost::multi_index::tag<StampedValueNameIndexTag>,
boost::multi_index::const_mem_fun<
StampedValue,
std::string,
&StampedValue::getName
>
>,
// Index used to access value by modification time.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<StampedValueModificationTimeIndexTag>,
boost::multi_index::const_mem_fun<
StampedElement,
boost::posix_time::ptime,
&StampedElement::getModificationTime
>
>
>
> StampedValueCollection;
//@}
} // end of namespace isc::data
} // end of namespace isc
......
......@@ -15,6 +15,7 @@
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/shared_ptr.hpp>
......@@ -811,6 +812,16 @@ typedef boost::multi_index_container<
std::string,
&OptionDefinition::getName
>
>,
// Start definition of index #3
boost::multi_index::ordered_non_unique<
// Use option definition modification time as the index key.
// This value is returned by the StampedElement::getModificationTime
boost::multi_index::const_mem_fun<
data::StampedElement,
boost::posix_time::ptime,
&data::StampedElement::getModificationTime
>
>
>
> OptionDefContainer;
......
......@@ -15,6 +15,7 @@
#include <dhcpsrv/key_from_key.h>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/member.hpp>
......@@ -198,6 +199,15 @@ typedef boost::multi_index_container<
bool,
&OptionDescriptor::persistent_
>
>,
// Start definition of index #3.
// Use StampedElement::getModificationTime as a key.
boost::multi_index::ordered_non_unique<
boost::multi_index::const_mem_fun<
data::StampedElement,
boost::posix_time::ptime,
&data::StampedElement::getModificationTime
>
>
>
> OptionContainer;
......@@ -404,6 +414,31 @@ public:
return (*od_itr);
}
/// @brief Deletes option for the specified key and option code.
///
/// The key should be a string, in which case it specifies an option space
/// name, or an uint32_t value, in which case it specifies a vendor
/// identifier.
///
/// @param key Option space name or vendor identifier.
/// @param option_code Code of the option to be returned.
/// @tparam Selector one of: @c std::string or @c uint32_t
///
/// @return Number of deleted options.
template<typename Selector>
size_t del(const Selector& key, const uint16_t option_code) {
// Check for presence of options.
OptionContainerPtr options = getAll(key);
if (!options || options->empty()) {
// There are no options, so there is nothing to do.
return (0);
}
// Some options present, locate the one we are interested in.
auto& idx = options->get<1>();
return (idx.erase(option_code));
}
/// @brief Returns a list of configured option space names.
///
/// The returned option space names exclude vendor option spaces,
......
......@@ -34,6 +34,10 @@ struct SharedNetworkNameIndexTag { };
/// @brief A tag for accessing index by server identifier.
struct SharedNetworkServerIdIndexTag { };
/// @brief Tag for the index for searching by shared network modification
/// time.
struct SharedNetworkModificationTimeIndexTag { };
/// @brief Shared network holding IPv4 subnets.
///
/// Specialization of the @ref Network4 class for IPv4 shared networks.
......@@ -188,8 +192,14 @@ typedef boost::multi_index_container<
boost::multi_index::tag<SharedNetworkServerIdIndexTag>,
boost::multi_index::const_mem_fun<Network4, asiolink::IOAddress,
&Network4::getServerId>
>,
// Fourth index allows for searching using subnet modification time.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<SharedNetworkModificationTimeIndexTag>,
boost::multi_index::const_mem_fun<data::StampedElement,
boost::posix_time::ptime,
&data::StampedElement::getModificationTime>
>
>
> SharedNetwork4Collection;
......@@ -340,6 +350,13 @@ typedef boost::multi_index_container<
boost::multi_index::tag<SharedNetworkNameIndexTag>,
boost::multi_index::const_mem_fun<SharedNetwork6, std::string,
&SharedNetwork6::getName>
>,
// Third index allows for searching using subnet modification time.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<SharedNetworkModificationTimeIndexTag>,
boost::multi_index::const_mem_fun<data::StampedElement,
boost::posix_time::ptime,
&data::StampedElement::getModificationTime>
>
>
> SharedNetwork6Collection;
......
......@@ -744,6 +744,9 @@ struct SubnetPrefixIndexTag { };
/// @brief Tag for the index for searching by server identifier.
struct SubnetServerIdIndexTag { };
/// @brief Tag for the index for searching by subnet modification time.
struct SubnetModificationTimeIndexTag { };
/// @brief A collection of @c Subnet4 objects
///
/// This container provides a set of indexes which can be used to retrieve
......@@ -788,11 +791,19 @@ typedef boost::multi_index_container<
boost::multi_index::const_mem_fun<Subnet, std::string, &Subnet::toText>
>,
// Fourth index allows for searching using an output from getServerId
// Fourth index allows for searching using an output from getServerId.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<SubnetServerIdIndexTag>,
boost::multi_index::const_mem_fun<Network4, asiolink::IOAddress,
&Network4::getServerId>
>,
// Fifth index allows for searching using subnet modification time.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<SubnetModificationTimeIndexTag>,
boost::multi_index::const_mem_fun<data::StampedElement,
boost::posix_time::ptime,
&data::StampedElement::getModificationTime>
>
>
> Subnet4Collection;
......@@ -838,6 +849,13 @@ typedef boost::multi_index_container<
boost::multi_index::ordered_unique<
boost::multi_index::tag<SubnetPrefixIndexTag>,
boost::multi_index::const_mem_fun<Subnet, std::string, &Subnet::toText>
>,
// Fourth index allows for searching using subnet modification time.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<SubnetModificationTimeIndexTag>,
boost::multi_index::const_mem_fun<data::StampedElement,
boost::posix_time::ptime,
&data::StampedElement::getModificationTime>
>
>
> Subnet6Collection;
......
......@@ -9,13 +9,15 @@
#include <database/database_connection.h>
#include <test_config_backend_dhcp4.h>
using namespace isc::data;
namespace isc {
namespace dhcp {
namespace test {
bool
TestConfigBackendDHCPv4::registerBackendType(ConfigBackendDHCPv4Mgr& mgr,
const std::string& db_type) {
const std::string& db_type) {
return(mgr.registerBackendFactory(db_type,
[](const db::DatabaseConnection::ParameterMap& params)
-> dhcp::ConfigBackendDHCPv4Ptr {
......@@ -26,54 +28,82 @@ TestConfigBackendDHCPv4::registerBackendType(ConfigBackendDHCPv4Mgr& mgr,
void
TestConfigBackendDHCPv4::unregisterBackendType(ConfigBackendDHCPv4Mgr& mgr,
const std::string& db_type) {
const std::string& db_type) {
mgr.unregisterBackendFactory(db_type);
}
Subnet4Ptr
TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& /* server_selector */,
const std::string& /* subnet_prefix */) const{
return (Subnet4Ptr());
const std::string& subnet_prefix) const{
const auto& index = subnets_.get<SubnetPrefixIndexTag>();
auto subnet_it = index.find(subnet_prefix);
return ((subnet_it != index.cend()) ? (*subnet_it) : Subnet4Ptr());
}
Subnet4Ptr
TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& /* server_selector */,
const SubnetID& /* subnet_id */) const {
return (Subnet4Ptr());
const SubnetID& subnet_id) const {
const auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
auto subnet_it = index.find(subnet_id);
return ((subnet_it != index.cend()) ? (*subnet_it) : Subnet4Ptr());
}
Subnet4Collection
TestConfigBackendDHCPv4::getAllSubnets4(const db::ServerSelector& /* server_selector */) const {
return(subnets_);
return (subnets_);
}
Subnet4Collection
TestConfigBackendDHCPv4::getModifiedSubnets4(const db::ServerSelector& /* server_selector */,
const boost::posix_time::ptime& /* modification_time */) const {
return(subnets_);
const boost::posix_time::ptime& modification_time) const {
const auto& index = subnets_.get<SubnetModificationTimeIndexTag>();
Subnet4Collection subnets;
auto lb = index.lower_bound(modification_time);
for (auto subnet = lb; subnet != index.end(); ++subnet) {
subnets.push_back(*subnet);
}
return (subnets);
}
SharedNetwork4Ptr
TestConfigBackendDHCPv4::getSharedNetwork4(const db::ServerSelector& /* server_selector */,
const std::string& /* name */) const {
return(SharedNetwork4Ptr());
const std::string& name) const {
const auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
auto network_it = index.find(name);
return ((network_it != index.cend()) ? (*network_it) : SharedNetwork4Ptr());
}
SharedNetwork4Collection
TestConfigBackendDHCPv4::getAllSharedNetworks4(const db::ServerSelector& /* server_selector */) const{
return(shared_networks_);
return (shared_networks_);
}
SharedNetwork4Collection
TestConfigBackendDHCPv4::getModifiedSharedNetworks4(const db::ServerSelector& /* server_selector */,
const boost::posix_time::ptime& /* modification_time */) const {
return(shared_networks_);
const boost::posix_time::ptime& modification_time) const {
const auto& index = shared_networks_.get<SharedNetworkModificationTimeIndexTag>();
SharedNetwork4Collection shared_networks;
auto lb = index.lower_bound(modification_time);
for (auto shared_network = lb; shared_network != index.end(); ++shared_network) {
shared_networks.push_back(*shared_network);
}
return (shared_networks);
}
OptionDefinitionPtr
TestConfigBackendDHCPv4::getOptionDef4(const db::ServerSelector& /* server_selector */,
const uint16_t /* code */,
const std::string& /* space */) const {
const uint16_t code,
const std::string& space) const {
const auto& index = option_defs_.get<1>();
auto option_def_it_pair = index.equal_range(code);
for (auto option_def_it = option_def_it_pair.first;
option_def_it != option_def_it_pair.second;
++option_def_it) {
if ((*option_def_it)->getOptionSpaceName() == space) {
return (*option_def_it);
}
}
return (OptionDefinitionPtr());
}
......@@ -84,14 +114,30 @@ TestConfigBackendDHCPv4::getAllOptionDefs4(const db::ServerSelector& /* server_s
OptionDefContainer
TestConfigBackendDHCPv4::getModifiedOptionDefs4(const db::ServerSelector& /* server_selector */,
const boost::posix_time::ptime& /* modification_time */) const {
return (option_defs_);
const boost::posix_time::ptime& modification_time) const {
const auto& index = option_defs_.get<3>();
OptionDefContainer option_defs;
auto lb = index.lower_bound(modification_time);
for (auto option_def = lb; option_def != index.end(); ++option_def) {
option_defs.push_back(*option_def);
}
return (option_defs);
}
OptionDescriptorPtr
TestConfigBackendDHCPv4::getOption4(const db::ServerSelector& /* server_selector */,
const uint16_t /* code */,
const std::string& /* space */) const {
const uint16_t code,
const std::string& space) const {
const auto& index = options_.get<1>();
auto option_it_pair = index.equal_range(code);
for (auto option_it = option_it_pair.first; option_it != option_it_pair.second;
++option_it) {
if (option_it->space_name_ == space) {
return (OptionDescriptorPtr(new OptionDescriptor(*option_it)));
}
}
return (OptionDescriptorPtr());
}
......@@ -102,153 +148,306 @@ TestConfigBackendDHCPv4::getAllOptions4(const db::ServerSelector& /* server_sele
OptionContainer
TestConfigBackendDHCPv4::getModifiedOptions4(const db::ServerSelector& /* server_selector */,
const boost::posix_time::ptime& /* modification_time */) const {
return (options_);
const boost::posix_time::ptime& modification_time) const {
const auto& index = options_.get<3>();
OptionContainer options;
auto lb = index.lower_bound(modification_time);
for (auto option = lb; option != index.end(); ++option) {
options.push_back(*option);
}
return (options);
}
data::StampedValuePtr
StampedValuePtr
TestConfigBackendDHCPv4::getGlobalParameter4(const db::ServerSelector& /* server_selector */,
const std::string& /* name */) const {
return(data::StampedValuePtr());
const std::string& name) const {
const auto& index = globals_.get<StampedValueNameIndexTag>();
auto global_it = index.find(name);
return ((global_it != index.cend()) ? (*global_it) : StampedValuePtr());
}
data::StampedValueCollection
StampedValueCollection
TestConfigBackendDHCPv4::getAllGlobalParameters4(const db::ServerSelector& /* server_selector */) const {
return (globals_);
}
data::StampedValueCollection
StampedValueCollection
TestConfigBackendDHCPv4::getModifiedGlobalParameters4(const db::ServerSelector& /* server_selector */,
const boost::posix_time::ptime& /* modification_time */) const {
return (globals_);
const boost::posix_time::ptime& modification_time) const {
const auto& index = globals_.get<StampedValueModificationTimeIndexTag>();
StampedValueCollection globals;
auto lb = index.lower_bound(modification_time);
for (auto global = lb; global != index.end(); ++global) {
globals.insert(*global);
}
return (globals);
}
void
TestConfigBackendDHCPv4::createUpdateSubnet4(const db::ServerSelector& /* server_selector */,
const Subnet4Ptr& /* subnet */) {
const Subnet4Ptr& subnet) {
auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
auto subnet_it = index.find(subnet->getID());
if (subnet_it != index.cend()) {
index.replace(subnet_it, subnet);
} else {
index.insert(subnet);
}
}
void
TestConfigBackendDHCPv4::createUpdateSharedNetwork4(const db::ServerSelector& /* server_selector */,
const SharedNetwork4Ptr& /* shared_network */) {
const SharedNetwork4Ptr& shared_network) {
auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
auto network_it = index.find(shared_network->getName());
if (network_it != index.cend()) {
index.replace(network_it, shared_network);
} else {
index.insert(shared_network);
}
}
void
TestConfigBackendDHCPv4::createUpdateOptionDef4(const db::ServerSelector& /* server_selector */,
const OptionDefinitionPtr& /* option_def */) {
const OptionDefinitionPtr& option_def) {
auto& index = option_defs_.get<1>();
auto option_def_it = index.find(option_def->getCode());
if (option_def_it != index.cend()) {
index.replace(option_def_it, option_def);
} else {
index.insert(option_def);
}
}
void
TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& /* server_selector */,
const OptionDescriptorPtr& /* option */) {
const OptionDescriptorPtr& option) {
auto& index = options_.get<1>();
auto option_it = index.find(option->option_->getType());
if (option_it != index.end()) {
index.replace(option_it, *option);
} else {
index.insert(*option);
}
}
void
TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& /* server_selector */,
const std::string& /* shared_network_name */,
const OptionDescriptorPtr& /* option */) {
const std::string& shared_network_name,
const OptionDescriptorPtr& option) {
auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
auto network_it = index.find(shared_network_name);
if (network_it != index.end()) {
auto shared_network = *network_it;
shared_network->getCfgOption()->del(option->space_name_, option->option_->getType());
shared_network->getCfgOption()->add(*option, option->space_name_);
} else {
isc_throw(BadValue, "attempted to create or update option in a non existing "
"shared network " << shared_network_name);
}
}
void
TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& /* server_selector */,
const SubnetID& /* subnet_id */,
const OptionDescriptorPtr& /* option */) {
const SubnetID& subnet_id,
const OptionDescriptorPtr& option) {
auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
auto subnet_it = index.find(subnet_id);
if (subnet_it != index.cend()) {
auto subnet = *subnet_it;
subnet->getCfgOption()->del(option->space_name_, option->option_->getType());
subnet->getCfgOption()->add(*option, option->space_name_);
} else {
isc_throw(BadValue, "attempted to create or update option in a non existing "
"subnet ID " << subnet_id);
}
}
void
TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& /* server_selector */,
const asiolink::IOAddress& /* pool_start_address */,
const asiolink::IOAddress& /* pool_end_address */,
const OptionDescriptorPtr& /* option */) {
const asiolink::IOAddress& pool_start_address,
const asiolink::IOAddress& pool_end_address,
const OptionDescriptorPtr& option) {
for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ++subnet) {
auto pool = (*subnet)->getPool(Lease::TYPE_V4, pool_start_address);
if (pool) {
pool->getCfgOption()->del(option->space_name_, option->option_->getType());
pool->getCfgOption()->add(*option, option->space_name_);
return;
}
}
isc_throw(BadValue, "attempted to create or update option in a non existing "
"pool " << pool_start_address << " - " << pool_end_address);
}
void
TestConfigBackendDHCPv4::createUpdateGlobalParameter4(const db::ServerSelector& /* server_selector */,
const data::StampedValuePtr& /* value */) {
const data::StampedValuePtr& value) {
auto& index = globals_.get<StampedValueNameIndexTag>();
auto global_it = index.find(value->getName());
if (global_it != index.end()) {
index.replace(global_it, value);
} else {
index.insert(value);
}
}
uint64_t
TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& /* server_selector */,
const std::string& /* subnet_prefix */) {
return (0);
const std::string& subnet_prefix) {
auto& index = subnets_.get<SubnetPrefixIndexTag>();
return (index.erase(subnet_prefix));
}
uint64_t
TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& /* server_selector */,
const SubnetID& /* subnet_id */) {
return (0);
const SubnetID& subnet_id) {
auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
return (index.erase(subnet_id));
}
uint64_t
TestConfigBackendDHCPv4::deleteAllSubnets4(const db::ServerSelector& /* server_selector */) {
return (0);
auto subnets_size = subnets_.size();
subnets_.clear();
return (subnets_size);
}
uint64_t
TestConfigBackendDHCPv4::deleteSharedNetwork4(const db::ServerSelector& /* server_selector */,
const std::string& /* name */) {
return (0);
const std::string& name) {
auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
return (index.erase(name));
}
uint64_t
TestConfigBackendDHCPv4::deleteAllSharedNetworks4(const db::ServerSelector& /* server_selector */) {
return (0);
auto shared_networks_size = shared_networks_.size();
shared_networks_.clear();
return (shared_networks_size);
}
uint64_t
TestConfigBackendDHCPv4::deleteOptionDef4(const db::ServerSelector& /* server_selector */,
const uint16_t /* code */,
const std::string& /* space */) {
return (0);
const uint16_t code,
const std::string& space) {
uint64_t erased = 0;
for (auto option_def_it = option_defs_.begin(); option_def_it != option_defs_.end();
++option_def_it) {
if (((*option_def_it)->getCode() == code) &&
((*option_def_it)->getOptionSpaceName() == space)) {
option_def_it = option_defs_.erase(option_def_it);
++erased;
}
}
return (erased);
}
uint64_t
TestConfigBackendDHCPv4::deleteAllOptionDefs4(const db::ServerSelector& /* server_selector */) {
return (0);
auto option_defs_size = option_defs_.size();
option_defs_.clear();
return (option_defs_size);
}
uint64_t
TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& /* server_selector */,
const uint16_t /* code */,
const std::string& /* space */) {
return (0);
const uint16_t code,
const std::string& space) {
uint64_t erased = 0;
for (auto option_it = options_.begin(); option_it != options_.end();
++option_it) {
if ((option_it->option_->getType() == code) &&
(option_it->space_name_ == space)) {
option_it = options_.erase(option_it);
++erased;
}
}
return (erased);
}
uint64_t
TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& /* server_selector */,
const std::string& /* shared_network_name */,
const uint16_t /* code */,
const std::string& /* space */) {
return (0);
const std::string& shared_network_name,
const uint16_t code,
const std::string& space) {
auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
auto network_it = index.find(shared_network_name);
if (network_it != index.end()) {
auto shared_network = *network_it;
return (shared_network->getCfgOption()->del(space, code));
} else {
isc_throw(BadValue, "attempted to delete an option in a non existing "
"shared network " << shared_network_name);
}
}
uint64_t
TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& /* server_selector */,
const SubnetID& /* subnet_id */,
const uint16_t /* code */,
const std::string& /* space */) {
return (0);
const SubnetID& subnet_id,
const uint16_t code,
const std::string& space) {
auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
auto subnet_it = index.find(subnet_id);
if (subnet_it != index.cend()) {
auto subnet = *subnet_it;
return (subnet->getCfgOption()->del(space, code));
} else {
isc_throw(BadValue, "attempted to delete an option in a non existing "
"subnet ID " << subnet_id);
}
}
uint64_t
TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& /* server_selector */,
const asiolink::IOAddress& /* pool_start_address */,
const asiolink::IOAddress& /* pool_end_address */,
const uint16_t /* code */,
const std::string& /* space */) {