Commit 9b2b59ba authored by Marcin Siodelski's avatar Marcin Siodelski

[3561] Implemented basic host manager gathering hosts from the config.

parent 9a10722e
......@@ -64,6 +64,7 @@ libkea_dhcpsrv_la_SOURCES += dhcp_config_parser.h
libkea_dhcpsrv_la_SOURCES += dhcp_parsers.cc dhcp_parsers.h
libkea_dhcpsrv_la_SOURCES += host.cc host.h
libkea_dhcpsrv_la_SOURCES += host_container.h
libkea_dhcpsrv_la_SOURCES += host_mgr.cc host_mgr.h
libkea_dhcpsrv_la_SOURCES += host_reservation_parser.cc host_reservation_parser.h
libkea_dhcpsrv_la_SOURCES += key_from_key.h
libkea_dhcpsrv_la_SOURCES += lease.cc lease.h
......@@ -87,6 +88,7 @@ libkea_dhcpsrv_la_SOURCES += subnet_id.h
libkea_dhcpsrv_la_SOURCES += subnet_selector.h
libkea_dhcpsrv_la_SOURCES += triplet.h
libkea_dhcpsrv_la_SOURCES += utils.h
libkea_dhcpsrv_la_SOURCES += writable_host_data_source.h
nodist_libkea_dhcpsrv_la_SOURCES = dhcpsrv_messages.h dhcpsrv_messages.cc
......
......@@ -76,22 +76,6 @@ public:
virtual ConstHostCollection
getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const = 0;
/// @brief Non-const version of the @c getAll const method.
///
/// Specifying both hardware address and DUID is allowed for this method
/// and results in returning all objects that are associated with hardware
/// address OR duid. For example: if one host is associated with the
/// specified hardware address and another host is associated with the
/// specified DUID, two hosts will be returned.
///
/// @param hwaddr HW address of the client or NULL if no HW address
/// available.
/// @param duid client id or NULL if not available, e.g. DHCPv4 client case.
///
/// @return Collection of non-const @c Host objects.
virtual HostCollection
getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) = 0;
/// @brief Returns a collection of hosts using the specified IPv4 address.
///
/// This method may return multiple @c Host objects if they are connected
......@@ -103,17 +87,6 @@ public:
virtual ConstHostCollection
getAll4(const asiolink::IOAddress& address) const = 0;
/// @brief Returns a collection of hosts using the specified IPv4 address.
///
/// This method may return multiple @c Host objects if they are connected
/// to different subnets.
///
/// @param address IPv4 address for which the @c Host object is searched.
///
/// @return Collection of @c Host objects.
virtual HostCollection
getAll4(const asiolink::IOAddress& address) = 0;
/// @brief Returns a host connected to the IPv4 subnet.
///
/// Implementations of this method should guard against the case when
......@@ -132,24 +105,6 @@ public:
get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
const DuidPtr& duid = DuidPtr()) const = 0;
/// @brief Returns a host connected to the IPv4 subnet.
///
/// Implementations of this method should guard against the case when
/// mutliple instances of the @c Host are present, e.g. when two
/// @c Host objects are found, one for the DUID, another one for the
/// HW address. In such case, an implementation of this method
/// should throw an exception.
///
/// @param subnet_id Subnet identifier.
/// @param hwaddr HW address of the client or NULL if no HW address
/// available.
/// @param duid client id or NULL if not available.
///
/// @return Non-const @c Host object using a specified HW address or DUID.
virtual HostPtr
get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
const DuidPtr& duid = DuidPtr()) = 0;
/// @brief Returns a host connected to the IPv6 subnet.
///
/// Implementations of this method should guard against the case when
......@@ -168,23 +123,6 @@ public:
get6(const SubnetID& subnet_id, const DuidPtr& duid,
const HWAddrPtr& hwaddr = HWAddrPtr()) const = 0;
/// @brief Returns a host connected to the IPv6 subnet.
///
/// Implementations of this method should guard against the case when
/// mutliple instances of the @c Host are present, e.g. when two
/// @c Host objects are found, one for the DUID, another one for the
/// HW address. In such case, an implementation of this method
/// should throw an exception.
///
/// @param subnet_id Subnet identifier.
/// @param hwaddr HW address of the client or NULL if no HW address
/// available.
/// @param duid DUID or NULL if not available.
///
/// @return Non-const @c Host object using a specified HW address or DUID.
virtual HostPtr
get6(const SubnetID& subnet_id, const DuidPtr& duid,
const HWAddrPtr& hwaddr = HWAddrPtr()) = 0;
/// @brief Returns a host using the specified IPv6 prefix.
///
......@@ -195,15 +133,6 @@ public:
virtual ConstHostPtr
get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const = 0;
/// @brief Returns a host using the specified IPv6 prefix.
///
/// @param prefix IPv6 prefix for which the @c Host object is searched.
/// @param prefix_len IPv6 prefix length.
///
/// @return Non-const @c Host object using a specified HW address or DUID.
virtual HostPtr
get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) = 0;
/// @brief Adds a new host to the collection.
///
/// The implementations of this method should guard against duplicate
......
......@@ -165,12 +165,17 @@ CfgHosts::add(const HostPtr& host) {
isc_throw(BadValue, "specified host object must not be NULL when it"
" is added to the configuration");
}
/// @todo This may need further sanity checks. For example, a duplicate
/// should be rejected.
// At least one subnet ID must be non-zero
if (host->getIPv4SubnetID() == 0 && host->getIPv6SubnetID() == 0) {
isc_throw(BadValue, "must not use both IPv4 and IPv6 subnet ids of"
" 0 when adding new host reservation");
}
/// @todo This may need further sanity checks.
HWAddrPtr hwaddr = host->getHWAddress();
DuidPtr duid = host->getDuid();
// Check for duplicates for the specified IPv4 subnet.
if (get4(host->getIPv4SubnetID(), hwaddr, duid)) {
if ((host->getIPv4SubnetID() > 0) &&
get4(host->getIPv4SubnetID(), hwaddr, duid)) {
isc_throw(DuplicateHost, "failed to add new host using the HW"
" address '" << (hwaddr ? hwaddr->toText(false) : "(null)")
<< " and DUID '" << (duid ? duid->toText() : "(null)")
......@@ -178,7 +183,8 @@ CfgHosts::add(const HostPtr& host) {
<< "' as this host has already been added");
// Checek for duplicates for the specified IPv6 subnet.
} else if (get6(host->getIPv6SubnetID(), duid, hwaddr)) {
} else if (host->getIPv6SubnetID() &&
get6(host->getIPv6SubnetID(), duid, hwaddr)) {
isc_throw(DuplicateHost, "failed to add new host using the HW"
" address '" << (hwaddr ? hwaddr->toText(false) : "(null)")
<< " and DUID '" << (duid ? duid->toText() : "(null)")
......
......@@ -18,10 +18,10 @@
#include <asiolink/io_address.h>
#include <dhcp/duid.h>
#include <dhcp/hwaddr.h>
#include <dhcpsrv/base_host_data_source.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/host_container.h>
#include <dhcpsrv/subnet_id.h>
#include <dhcpsrv/writable_host_data_source.h>
#include <boost/shared_ptr.hpp>
#include <vector>
......@@ -42,7 +42,7 @@ namespace dhcp {
/// when the new configuration is applied for the server. The reservations
/// are retrieved by the @c HostMgr class when the server is allocating or
/// renewing an address or prefix for the particular client.
class CfgHosts : public BaseHostDataSource {
class CfgHosts : public WritableHostDataSource {
public:
/// @brief Return all hosts for the specified HW address or DUID.
......
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <dhcpsrv/cfg_hosts.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/host_mgr.h>
namespace {
/// @brief Convenience function returning a pointer to the hosts configuration.
///
/// This function is called by the @c HostMgr methods requiring access to the
/// host reservations specified in the DHCP server configuration.
///
/// @return A pointer to the const hosts reservation configuration.
isc::dhcp::ConstCfgHostsPtr getCfgHosts() {
return (isc::dhcp::CfgMgr::instance().getCurrentCfg()->getCfgHosts());
}
} // end of anonymous namespace
namespace isc {
namespace dhcp {
using namespace isc::asiolink;
boost::scoped_ptr<HostMgr>&
HostMgr::getHostMgrPtr() {
static boost::scoped_ptr<HostMgr> host_mgr_ptr;
return (host_mgr_ptr);
}
void
HostMgr::create(const std::string&) {
getHostMgrPtr().reset(new HostMgr());
}
HostMgr&
HostMgr::instance() {
boost::scoped_ptr<HostMgr>& host_mgr_ptr = getHostMgrPtr();
if (!host_mgr_ptr) {
create();
}
return (*host_mgr_ptr);
}
ConstHostCollection
HostMgr::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) const {
return (getCfgHosts()->getAll(hwaddr, duid));
}
ConstHostCollection
HostMgr::getAll4(const IOAddress& address) const {
return (getCfgHosts()->getAll4(address));
}
ConstHostPtr
HostMgr::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
const DuidPtr& duid) const {
return (getCfgHosts()->get4(subnet_id, hwaddr, duid));
}
ConstHostPtr
HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid,
const HWAddrPtr& hwaddr) const {
return (getCfgHosts()->get6(subnet_id, duid, hwaddr));
}
ConstHostPtr
HostMgr::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
return (getCfgHosts()->get6(prefix, prefix_len));
}
void
HostMgr::add(const HostPtr&) {
isc_throw(isc::NotImplemented, "HostMgr::add is not implemented");
}
} // end of isc::dhcp namespace
} // end of isc namespace
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef HOST_MGR_H
#define HOST_MGR_H
#include <boost/scoped_ptr.hpp>
namespace isc {
namespace dhcp {
/// @brief Host Manager.
///
/// This is a singleton class which provides access to multiple sources of
/// information about static host reservations. These sources are also referred
/// to as host data sources. Each source derives (directly or indirectly) from
/// the @c BaseHostDataSource.
///
/// The @c HostMgr is a central point for providing information about the host
/// reservations. Internally, it relays the queries (calls to the appropriate
/// methods declared in the @c BaseHostDataSource) to the data sources it is
/// connected to. The @c HostMgr is always connected to the server's
/// configuration, accessible through the @c CfgHosts object in the @c CfgMgr.
/// The @c CfgHosts object holds all reservations specified in the DHCP server
/// configuration file. If a particular reservation is not found in the
/// @c CfgHosts object, the @c HostMgr will try to find it using the alternate
/// host data storage. The alternate host data storage is usually a database
/// (e.g. SQL database), accessible through a dedicated host data source
/// object (a.k.a. database backend). This datasource is responsible for
/// managing the connection with the database and forming appropriate queries
/// to retrieve (or update) the information about the reservations.
///
/// The use of the alternate host data source is optional and usually requires
/// additional configuration to be specified by the server administrator.
/// For example, for the SQL database the user's credentials, database address,
/// and database name are required. The @c HostMgr passes these parameters
/// to an appropriate datasource which is responsible for opening a connection
/// and maintaing it.
///
/// It is possible to switch to a different alternate data source or disable
/// the use of the alternate datasource, e.g. as a result of server's
/// reconfiguration. However, the use of the primary host data source (i.e.
/// reservations specified in the configuration file) can't be disabled.
///
/// @todo Implement alternate host data sources: MySQL, PostgreSQL, etc.
class HostMgr : public BaseHostDataSource {
public:
/// @brief Creates new instance of the @c HostMgr.
///
/// If an instance of the @c HostMgr already exists, it will be replaced
/// by the new instance. Thus, any instances of the alternate host data
/// sources will be dropped.
///
/// @param access Host data source access parameters for the alternate
/// host data source. It holds "keyword=value" pairs, separated by spaces.
/// The supported values are specific to the alternate data source in use.
/// However, the "type" parameter is common and it specifies which data
/// source is to be used.
static void create(const std::string& access = "");
/// @brief Returns a sole instance of the @c HostMgr.
///
/// This method should be used to retrieve an instance of the @c HostMgr
/// to be used to gather/manage host reservations. It returns an instance
/// of the @c HostMgr created by the @c create method. If such instance
/// doesn't exist yet, it is created using the @c create method with the
/// default c
static HostMgr& instance();
/// @brief Returns all hosts for the specified HW address or DUID.
///
/// This method returns all @c Host objects representing reservations for
/// the specified HW address or DUID as documented in the
/// @c BaseHostDataSource::getAll.
///
/// It retrieves reservations from both primary and alternate host data
/// source as a single collection of @c Host objects. Note that this
/// collection may contain duplicates. It is the caller's responsibility
/// to check for duplicates.
///
/// @param hwaddr HW address of the client or NULL if no HW address
/// available.
/// @param duid client id or NULL of not available.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const;
/// @brief Returns a collection of hosts using the specified IPv4 address.
///
/// This method may return multiple @c Host objects if they are connected to
/// different subnets.
///
/// @param address IPv4 address for which the @c Host object is searched.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAll4(const asiolink::IOAddress& address) const;
/// @brief Returns a host connected to the IPv4 subnet.
///
/// This method returns a single reservation for the particular host
/// (identified by the HW address or DUID) as documented in the
/// @c BaseHostDataSource::get4.
///
/// @param subnet_id Subnet identifier.
/// @param hwaddr HW address of the client or NULL if no HW address
/// available.
/// @param duid client id or NULL if not available.
///
/// @return Const @c Host object using a specified HW address or DUID.
virtual ConstHostPtr
get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
const DuidPtr& duid = DuidPtr()) const;
/// @brief Returns a host connected to the IPv6 subnet.
///
/// This method returns a host connected to the IPv6 subnet and identified
/// by the HW address or DUID, as described in the
/// @c BaseHostDataSource::get6.
///
/// @param subnet_id Subnet identifier.
/// @param hwaddr HW address of the client or NULL if no HW address
/// available.
/// @param duid DUID or NULL if not available.
///
/// @return Const @c Host object using a specified HW address or DUID.
virtual ConstHostPtr
get6(const SubnetID& subnet_id, const DuidPtr& duid,
const HWAddrPtr& hwaddr = HWAddrPtr()) const;
/// @brief Returns a host using the specified IPv6 prefix.
///
/// This method returns a host using specified IPv6 prefix, as described
/// in the @c BaseHostDataSource::get6.
///
/// @param prefix IPv6 prefix for which the @c Host object is searched.
/// @param prefix_len IPv6 prefix length.
///
/// @return Const @c Host object using a specified HW address or DUID.
virtual ConstHostPtr
get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
/// @brief Adds a new host to the alternate data source.
///
/// This method will throw an exception if no alternate data source is
/// in use.
///
/// @param Pointer to the new @c Host object being added.
virtual void add(const HostPtr& host);
private:
/// @brief Returns a pointer to the currently used instance of the
/// @c HostMgr.
static boost::scoped_ptr<HostMgr>& getHostMgrPtr();
};
}
}
#endif // HOST_MGR_H
......@@ -68,6 +68,7 @@ libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc
libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc
libdhcpsrv_unittests_SOURCES += daemon_unittest.cc
libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += host_unittest.cc
libdhcpsrv_unittests_SOURCES += host_reservation_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_file_io.cc lease_file_io.h
......
......@@ -99,11 +99,11 @@ TEST_F(CfgHostsTest, getAllNonRepeatingHosts) {
for (int i = 0; i < 25; ++i) {
cfg.add(HostPtr(new Host(hwaddrs_[i]->toText(false),
"hw-address",
SubnetID(i % 10), SubnetID(i % 5),
SubnetID(i % 10 + 1), SubnetID(i % 5 + 1),
IOAddress("192.0.2.5"))));
cfg.add(HostPtr(new Host(duids_[i]->toText(), "duid",
SubnetID(i % 5), SubnetID(i % 10),
SubnetID(i % 5 + 1), SubnetID(i % 10 + 1),
IOAddress("192.0.2.10"))));
}
......@@ -115,14 +115,14 @@ TEST_F(CfgHostsTest, getAllNonRepeatingHosts) {
// points to a host for which the reservation hasn't been added.
HostCollection hosts = cfg.getAll(hwaddrs_[i], duids_[i + 25]);
ASSERT_EQ(1, hosts.size());
EXPECT_EQ(i % 10, hosts[0]->getIPv4SubnetID());
EXPECT_EQ(i % 10 + 1, hosts[0]->getIPv4SubnetID());
EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
// Get host identified by DUID. The HW address is non-null but it
// points to a host for which the reservation hasn't been added.
hosts = cfg.getAll(hwaddrs_[i + 25], duids_[i]);
ASSERT_EQ(1, hosts.size());
EXPECT_EQ(i % 5, hosts[0]->getIPv4SubnetID());
EXPECT_EQ(i % 5 + 1, hosts[0]->getIPv4SubnetID());
EXPECT_EQ("192.0.2.10", hosts[0]->getIPv4Reservation().toText());
}
......@@ -292,6 +292,15 @@ TEST_F(CfgHostsTest, get6) {
EXPECT_THROW(cfg.get6(SubnetID(1), duids_[0], hwaddrs_[0]), DuplicateHost);
}
TEST_F(CfgHostsTest, zeroSubnetIDs) {
CfgHosts cfg;
ASSERT_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
"hw-address",
SubnetID(0), SubnetID(0),
IOAddress("10.0.0.1")))),
isc::BadValue);
}
// This test verifies that it is not possible to add the same Host to the
// same IPv4 subnet twice.
TEST_F(CfgHostsTest, duplicatesSubnet4HWAddr) {
......@@ -299,21 +308,21 @@ TEST_F(CfgHostsTest, duplicatesSubnet4HWAddr) {
// Add a host.
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
"hw-address",
SubnetID(10), SubnetID(1),
SubnetID(10), SubnetID(0),
IOAddress("10.0.0.1")))));
// Try to add the host with the same HW address to the same subnet. The fact
// that the IP address is different here shouldn't really matter.
EXPECT_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
"hw-address",
SubnetID(10), SubnetID(12),
SubnetID(10), SubnetID(0),
IOAddress("10.0.0.10")))),
isc::dhcp::DuplicateHost);
// Now try to add it to a different subnet. It should go through.
EXPECT_NO_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
"hw-address",
SubnetID(11), SubnetID(12),
SubnetID(11), SubnetID(0),
IOAddress("10.0.0.10")))));
}
......@@ -324,21 +333,21 @@ TEST_F(CfgHostsTest, duplicatesSubnet4DUID) {
// Add a host.
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
"duid",
SubnetID(10), SubnetID(1),
SubnetID(10), SubnetID(0),
IOAddress("10.0.0.1")))));
// Try to add the host with the same DUID to the same subnet. The fact
// that the IP address is different here shouldn't really matter.
EXPECT_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
"duid",
SubnetID(10), SubnetID(12),
SubnetID(10), SubnetID(0),
IOAddress("10.0.0.10")))),
isc::dhcp::DuplicateHost);
// Now try to add it to a different subnet. It should go through.
EXPECT_NO_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
"duid",
SubnetID(11), SubnetID(12),
SubnetID(11), SubnetID(0),
IOAddress("10.0.0.10")))));
}
......@@ -349,21 +358,21 @@ TEST_F(CfgHostsTest, duplicatesSubnet6HWAddr) {
// Add a host.
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
"hw-address",
SubnetID(10), SubnetID(1),
SubnetID(0), SubnetID(1),
IOAddress("0.0.0.0")))));
// Try to add the host with the same HW address to the same subnet. The fact
// that the IP address is different here shouldn't really matter.
EXPECT_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
"hw-address",
SubnetID(11), SubnetID(1),
SubnetID(0), SubnetID(1),
IOAddress("0.0.0.0")))),
isc::dhcp::DuplicateHost);
// Now try to add it to a different subnet. It should go through.
EXPECT_NO_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
"hw-address",
SubnetID(11), SubnetID(2),
SubnetID(0), SubnetID(2),
IOAddress("0.0.0.0")))));
}
......@@ -374,21 +383,21 @@ TEST_F(CfgHostsTest, duplicatesSubnet6DUID) {
// Add a host.
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
"duid",
SubnetID(10), SubnetID(1),
SubnetID(0), SubnetID(1),
IOAddress("0.0.0.0")))));
// Try to add the host with the same DUID to the same subnet. The fact
// that the IP address is different here shouldn't really matter.
EXPECT_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
"duid",
SubnetID(11), SubnetID(1),
SubnetID(0), SubnetID(1),
IOAddress("0.0.0.0")))),
isc::dhcp::DuplicateHost);
// Now try to add it to a different subnet. It should go through.
EXPECT_NO_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
"duid",
SubnetID(11), SubnetID(2),
SubnetID(0), SubnetID(2),
IOAddress("0.0.0.0")))));
}
......
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <dhcp/duid.h>
#include <dhcp/hwaddr.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/host_mgr.h>
#include <gtest/gtest.h>
#include <vector>
using namespace isc;
using namespace isc::dhcp;
using namespace isc::asiolink;
namespace {
/// @brief Test fixture class for @c HostMgr class.
class HostMgrTest : public ::testing::Test {
protected:
/// @brief Prepares the class for a test.
///
/// This method crates a handful of unique HW address and DUID objects
/// for use in unit tests. These objects are held in the @c hwaddrs_ and
/// @c duids_ members respectively.
///
/// This method also resets the @c CfgMgr configuration and re-creates
/// the @c HostMgr object.
virtual void SetUp();
/// @brief Convenience method returning a pointer to the @c CfgHosts object
/// in the @c CfgMgr.
CfgHostsPtr getCfgHosts() const;
/// @brief HW addresses to be used by the tests.
std::vector<HWAddrPtr> hwaddrs_;
/// @brief DUIDs to be used by the tests.