Commit c98545fa authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[5305] Implemented CfgSharedNetworks class.

parent c9094a92
......@@ -102,8 +102,7 @@ libkea_dhcpsrv_la_SOURCES += cfg_host_operations.cc cfg_host_operations.h
libkea_dhcpsrv_la_SOURCES += cfg_option.cc cfg_option.h
libkea_dhcpsrv_la_SOURCES += cfg_option_def.cc cfg_option_def.h
libkea_dhcpsrv_la_SOURCES += cfg_rsoo.cc cfg_rsoo.h
libkea_dhcpsrv_la_SOURCES += cfg_shared_networks4.cc cfg_shared_networks4.h
libkea_dhcpsrv_la_SOURCES += cfg_shared_networks6.h
libkea_dhcpsrv_la_SOURCES += cfg_shared_networks.h
libkea_dhcpsrv_la_SOURCES += cfg_subnets4.cc cfg_subnets4.h
libkea_dhcpsrv_la_SOURCES += cfg_subnets6.cc cfg_subnets6.h
libkea_dhcpsrv_la_SOURCES += cfg_mac_source.cc cfg_mac_source.h
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CFG_SHARED_NETWORKS_H
#define CFG_SHARED_NETWORKS_H
#include <cc/cfg_to_element.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/shared_network.h>
#include <boost/shared_ptr.hpp>
#include <string>
namespace isc {
namespace dhcp {
/// @brief This class holds configuration of shared networks.
///
/// This is a generic class implementing basic functions such as shared network
/// addition, removal and retrieval. It also dumps configuration in the JSON
/// format.
///
/// There are specializations of this class implemented as
/// @ref CfgSharedNetworks4 and @ref CfgSharedNetworks6 for IPv4 and IPv6 cases
/// repspectively.
///
/// @tparam Type of the pointer to a shared network, i.e. @ref SharedNetwork4Ptr
/// or @ref SharedNetwork6Ptr.
template<typename SharedNetworkPtrType>
class CfgSharedNetworks : public data::CfgToElement {
public:
/// @brief Adds new shared network to the configuration.
///
/// @param network Pointer to a network
///
/// @throw isc::BadValue when name is a duplicate of existing network's
/// name.
void add(const SharedNetworkPtrType& network) {
if (getByName(network->getName())) {
isc_throw(BadValue, "duplicate network '" << network->getName() <<
"' found in the configuration");
}
networks_.push_back(network);
}
/// @brief Deletes shared network from the configuration.
///
/// @param name Name of the network to be deleted.
///
/// @throw isc::BadValue if the network can't be found.
void del(const std::string& name) {
auto& index = networks_.template get<SharedNetworkNameIndexTag>();
auto shared_network = index.find(name);
if (shared_network != index.end()) {
index.erase(shared_network);
} else {
isc_throw(BadValue, "unable to delete non-existing network '"
<< name << "' from shared networks configuration");
}
}
/// @brief Retrieves shared network by name.
///
/// @param name Name of the network to be retrieved.
///
/// @return Pointer to the shared network or null pointer if the network
/// is not found.
SharedNetworkPtrType getByName(const std::string& name) const {
const auto& index = networks_.template get<SharedNetworkNameIndexTag>();
auto shared_network = index.find(name);
if (shared_network != index.cend()) {
return (*shared_network);
}
return (SharedNetworkPtrType());
}
/// @brief Unparses shared networks configuration.
///
/// @return Element object representing a list of shared networks held
/// within configuration. The networks are sorted by their names.
virtual data::ElementPtr toElement() const {
data::ElementPtr list = data::Element::createList();
// Insert shared networks sorted by their names into the list.
const auto& index = networks_.template get<SharedNetworkNameIndexTag>();
for (auto shared_network = index.begin(); shared_network != index.end();
++shared_network) {
list->add((*shared_network)->toElement());
}
return (list);
}
protected:
/// @brief Multi index container holding shared networks.
SharedNetworkCollection<typename SharedNetworkPtrType::element_type>
networks_;
};
/// @brief Represents configuration of IPv4 shared networks.
class CfgSharedNetworks4 : public CfgSharedNetworks<SharedNetwork4Ptr> {
};
/// @brief Pointer to the configuration of IPv4 shared networks.
typedef boost::shared_ptr<CfgSharedNetworks4> CfgSharedNetworks4Ptr;
/// @brief Represents configuration of IPv6 shared networks.
class CfgSharedNetworks6 : public CfgSharedNetworks<SharedNetwork6Ptr> {
};
/// @brief Pointer to the configuration of IPv6 shared networks.
typedef boost::shared_ptr<CfgSharedNetworks6> CfgSharedNetworks6Ptr;
} // end of namespace isc::dhcp
} // end of namespace isc
#endif // CFG_SHARED_NETWORKS_H
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <dhcpsrv/cfg_shared_networks4.h>
namespace isc {
namespace dhcp {
void
CfgSharedNetworks4::add(const SharedNetwork4Ptr& network) {
}
} // end of namespace isc::dhcp
} // end of namespace isc
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CFG_SHARED_NETWORKS4_H
#define CFG_SHARED_NETWORKS4_H
#include <cc/cfg_to_element.h>
#include <dhcpsrv/shared_network.h>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace dhcp {
class CfgSharedNetworks4 : public data::CfgToElement {
public:
void add(const SharedNetwork4Ptr& shared_network);
};
typedef boost::shared_ptr<CfgSharedNetworks4> CfgSharedNetworks4Ptr;
} // end of namespace isc::dhcp
} // end of namespace isc
#endif // CFG_SHARED_NETWORKS4_H
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CFG_SHARED_NETWORKS6_H
#define CFG_SHARED_NETWORKS6_H
#include <cc/cfg_to_element.h>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace dhcp {
class CfgSharedNetworks6 : public data::CfgToElement {
public:
};
typedef boost::shared_ptr<CfgSharedNetworks6> CfgSharedNetworks6Ptr;
} // end of namespace isc::dhcp
} // end of namespace isc
#endif // CFG_SHARED_NETWORKS6_H
......@@ -13,6 +13,11 @@
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/subnet_id.h>
#include <boost/enable_shared_from_this.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
......@@ -256,6 +261,39 @@ protected:
};
/// @brief A tag for accessing random access index.
struct SharedNetworkRandomAccessIndexTag { };
/// @brief A tag for accessing index by shared network name.
struct SharedNetworkNameIndexTag { };
/// @brief Multi index container holding shared networks.
///
/// This is multi index container can hold pointers to @ref SharedNetwork4
/// or @ref SharedNetwork6 objects. It provides indexes for shared network
/// lookups using properties such as shared network's name.
///
/// @tparam SharedNetworkType Type of the shared network: @ref SharedNetwork4
/// or @ref SharedNetwork6.
template<typename SharedNetworkType>
using SharedNetworkCollection = boost::multi_index_container<
// Multi index container holds pointers to the shared networks.
boost::shared_ptr<SharedNetworkType>,
boost::multi_index::indexed_by<
// First is the random access index allowing for accessing objects
// just like we'd do with vector.
boost::multi_index::random_access<
boost::multi_index::tag<SharedNetworkRandomAccessIndexTag>
>,
// Second index allows for access by shared network's name.
boost::multi_index::ordered_unique<
boost::multi_index::tag<SharedNetworkNameIndexTag>,
boost::multi_index::const_mem_fun<SharedNetwork, std::string,
&SharedNetwork::getName>
>
>
>;
/// @brief Shared network holding IPv4 subnets.
///
/// Specialization of the @ref SharedNetwork class for IPv4 subnets.
......@@ -335,12 +373,14 @@ private:
/// @brief Collection of IPv4 subnets within shared network.
Subnet4Collection subnets_;
};
/// @brief Pointer to @ref SharedNetwork4 object.
typedef boost::shared_ptr<SharedNetwork4> SharedNetwork4Ptr;
/// @brief A collection of @ref SharedNetwork4 objects.
typedef SharedNetworkCollection<SharedNetwork4> SharedNetwork4Collection;
/// @brief Shared network holding IPv6 subnets.
///
/// Specialization of the @ref SharedNetwork class for IPv6 subnets.
......@@ -425,6 +465,9 @@ private:
/// @brief Pointer to @ref SharedNetwork6 object.
typedef boost::shared_ptr<SharedNetwork6> SharedNetwork6Ptr;
/// @brief A collection of @ref SharedNetwork6 objects.
typedef SharedNetworkCollection<SharedNetwork6> SharedNetwork6Collection;
} // end of namespace isc::dhcp
} // end of namespace isc
......
......@@ -74,6 +74,8 @@ libdhcpsrv_unittests_SOURCES += cfg_mac_source_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_option_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_option_def_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_rsoo_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_shared_networks4_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_shared_networks6_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_subnets4_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_subnets6_unittest.cc
libdhcpsrv_unittests_SOURCES += cfgmgr_unittest.cc
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/cfg_shared_networks.h>
#include <testutils/test_to_element.h>
#include <gtest/gtest.h>
using namespace isc;
using namespace isc::dhcp;
namespace {
// This test verifies that shared networks can be added to the configruation
// and retrieved by name.
TEST(CfgSharedNetworks4Test, getByName) {
SharedNetwork4Ptr network1(new SharedNetwork4("frog"));
SharedNetwork4Ptr network2(new SharedNetwork4("dog"));
CfgSharedNetworks4 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
SharedNetwork4Ptr returned_network1 = cfg.getByName("frog");
ASSERT_TRUE(returned_network1);
SharedNetwork4Ptr returned_network2 = cfg.getByName("dog");
ASSERT_TRUE(returned_network2);
}
// This test verifies that it is possible to delete a network.
TEST(CfgSharedNetworks4Test, deleteByName) {
SharedNetwork4Ptr network1(new SharedNetwork4("frog"));
SharedNetwork4Ptr network2(new SharedNetwork4("dog"));
// Add two networks to the configuration.
CfgSharedNetworks4 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
// Try to delete non-existing network. This should throw.
ASSERT_THROW(cfg.del("lion"), BadValue);
// Delete network #1.
ASSERT_NO_THROW(cfg.del(network1->getName()));
ASSERT_FALSE(cfg.getByName(network1->getName()));
ASSERT_TRUE(cfg.getByName(network2->getName()));
// Delete network #2.
ASSERT_NO_THROW(cfg.del(network2->getName()));
ASSERT_FALSE(cfg.getByName(network1->getName()));
ASSERT_FALSE(cfg.getByName(network2->getName()));
}
// This test verifies that shared networks must have unique names.
TEST(CfgSharedNetworks4Test, duplicateName) {
SharedNetwork4Ptr network1(new SharedNetwork4("frog"));
SharedNetwork4Ptr network2(new SharedNetwork4("frog"));
CfgSharedNetworks4 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_THROW(cfg.add(network2), BadValue);
}
// This test verifies that unparsing shared networks returns valid structure.
TEST(CfgSharedNetworks4Test, unparse) {
SharedNetwork4Ptr network1(new SharedNetwork4("frog"));
SharedNetwork4Ptr network2(new SharedNetwork4("dog"));
network1->setIface("eth0");
network2->setIface("eth1");
CfgSharedNetworks4 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
std::string expected =
"[\n"
" {\n"
" \"interface\": \"eth1\",\n"
" \"name\": \"dog\",\n"
" \"option-data\": [ ],\n"
" \"subnet4\": [ ]\n"
" },\n"
" {\n"
" \"interface\": \"eth0\",\n"
" \"name\": \"frog\",\n"
" \"option-data\": [ ],\n"
" \"subnet4\": [ ]\n"
" }\n"
"]\n";
test::runToElementTest<CfgSharedNetworks4>(expected, cfg);
}
} // end of anonymous namespace
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/cfg_shared_networks.h>
#include <testutils/test_to_element.h>
#include <gtest/gtest.h>
using namespace isc;
using namespace isc::dhcp;
namespace {
// This test verifies that shared networks can be added to the configruation
// and retrieved by name.
TEST(CfgSharedNetworks6Test, getByName) {
SharedNetwork6Ptr network1(new SharedNetwork6("frog"));
SharedNetwork6Ptr network2(new SharedNetwork6("dog"));
CfgSharedNetworks6 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
SharedNetwork6Ptr returned_network1 = cfg.getByName("frog");
ASSERT_TRUE(returned_network1);
SharedNetwork6Ptr returned_network2 = cfg.getByName("dog");
ASSERT_TRUE(returned_network2);
}
// This test verifies that it is possible to delete a network.
TEST(CfgSharedNetworks6Test, deleteByName) {
SharedNetwork6Ptr network1(new SharedNetwork6("frog"));
SharedNetwork6Ptr network2(new SharedNetwork6("dog"));
// Add two networks to the configuration.
CfgSharedNetworks6 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
// Try to delete non-existing network. This should throw.
ASSERT_THROW(cfg.del("lion"), BadValue);
// Delete network #1.
ASSERT_NO_THROW(cfg.del(network1->getName()));
ASSERT_FALSE(cfg.getByName(network1->getName()));
ASSERT_TRUE(cfg.getByName(network2->getName()));
// Delete network #2.
ASSERT_NO_THROW(cfg.del(network2->getName()));
ASSERT_FALSE(cfg.getByName(network1->getName()));
ASSERT_FALSE(cfg.getByName(network2->getName()));
}
// This test verifies that shared networks must have unique names.
TEST(CfgSharedNetworks6Test, duplicateName) {
SharedNetwork6Ptr network1(new SharedNetwork6("frog"));
SharedNetwork6Ptr network2(new SharedNetwork6("frog"));
CfgSharedNetworks6 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_THROW(cfg.add(network2), BadValue);
}
// This test verifies that unparsing shared networks returns valid structure.
TEST(CfgSharedNetworks6Test, unparse) {
SharedNetwork6Ptr network1(new SharedNetwork6("frog"));
SharedNetwork6Ptr network2(new SharedNetwork6("dog"));
network1->setIface("eth0");
network2->setIface("eth1");
CfgSharedNetworks6 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
std::string expected =
"[\n"
" {\n"
" \"interface\": \"eth1\",\n"
" \"name\": \"dog\",\n"
" \"option-data\": [ ],\n"
" \"subnet6\": [ ]\n"
" },\n"
" {\n"
" \"interface\": \"eth0\",\n"
" \"name\": \"frog\",\n"
" \"option-data\": [ ],\n"
" \"subnet6\": [ ]\n"
" }\n"
"]\n";
test::runToElementTest<CfgSharedNetworks6>(expected, cfg);
}
} // end of 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