Commit 57653336 authored by Marcin Siodelski's avatar Marcin Siodelski

[#158,!136] Added ability to remove all hosts for subnet id.

parent 98b3e424
...@@ -600,6 +600,18 @@ CfgHosts::del(const SubnetID& /*subnet_id*/, const asiolink::IOAddress& /*addr*/ ...@@ -600,6 +600,18 @@ CfgHosts::del(const SubnetID& /*subnet_id*/, const asiolink::IOAddress& /*addr*/
return (false); return (false);
} }
size_t
CfgHosts::delAll4(const SubnetID& subnet_id) {
HostContainerIndex2& idx = hosts_.get<2>();
size_t erased = idx.erase(subnet_id);
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL_ALL_SUBNET4)
.arg(erased)
.arg(subnet_id);
return (erased);
}
bool bool
CfgHosts::del4(const SubnetID& /*subnet_id*/, CfgHosts::del4(const SubnetID& /*subnet_id*/,
const Host::IdentifierType& /*identifier_type*/, const Host::IdentifierType& /*identifier_type*/,
...@@ -610,6 +622,24 @@ CfgHosts::del4(const SubnetID& /*subnet_id*/, ...@@ -610,6 +622,24 @@ CfgHosts::del4(const SubnetID& /*subnet_id*/,
return (false); return (false);
} }
size_t
CfgHosts::delAll6(const SubnetID& subnet_id) {
// Delete IPv6 reservations.
HostContainer6Index2& idx6 = hosts6_.get<2>();
size_t erased_addresses = idx6.erase(subnet_id);
// Delete hosts.
HostContainerIndex3& idx = hosts_.get<3>();
size_t erased_hosts = idx.erase(subnet_id);
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL_ALL_SUBNET6)
.arg(erased_hosts)
.arg(erased_addresses)
.arg(subnet_id);
return (erased_hosts);
}
bool bool
CfgHosts::del6(const SubnetID& /*subnet_id*/, CfgHosts::del6(const SubnetID& /*subnet_id*/,
const Host::IdentifierType& /*identifier_type*/, const Host::IdentifierType& /*identifier_type*/,
......
...@@ -241,6 +241,13 @@ public: ...@@ -241,6 +241,13 @@ public:
/// @param addr specified address. /// @param addr specified address.
virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr); virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
/// @brief Attempts to delete all hosts for a given IPv4 subnet.
///
/// @param subnet_id Identifier of the subnet for which reservation should
/// be deleted.
/// @return Number of deleted hosts.
virtual size_t delAll4(const SubnetID& subnet_id);
/// @brief Attempts to delete a host by (subnet4-id, identifier, identifier-type) /// @brief Attempts to delete a host by (subnet4-id, identifier, identifier-type)
/// ///
/// This method supports v4 only. /// This method supports v4 only.
...@@ -256,6 +263,13 @@ public: ...@@ -256,6 +263,13 @@ public:
const Host::IdentifierType& identifier_type, const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len); const uint8_t* identifier_begin, const size_t identifier_len);
/// @brief Attempts to delete all hosts for a given IPv6 subnet.
///
/// @param subnet_id Identifier of the subnet for which reservation should
/// be deleted.
/// @return Number of deleted hosts.
virtual size_t delAll6(const SubnetID& subnet_id);
/// @brief Attempts to delete a host by (subnet6-id, identifier, identifier-type) /// @brief Attempts to delete a host by (subnet6-id, identifier, identifier-type)
/// ///
/// This method supports v6 only. /// This method supports v6 only.
......
...@@ -67,6 +67,20 @@ typedef boost::multi_index_container< ...@@ -67,6 +67,20 @@ typedef boost::multi_index_container<
// Index using values returned by the @c Host::getIPv4Reservation. // Index using values returned by the @c Host::getIPv4Reservation.
boost::multi_index::const_mem_fun<Host, const asiolink::IOAddress&, boost::multi_index::const_mem_fun<Host, const asiolink::IOAddress&,
&Host::getIPv4Reservation> &Host::getIPv4Reservation>
>,
// Third index is used to search for the host using IPv4 subnet id
boost::multi_index::ordered_non_unique<
// Index using values returned by the @c Host::getIPv4SubnetID
boost::multi_index::const_mem_fun<Host, SubnetID,
&Host::getIPv4SubnetID>
>,
// Forth index is used to search for the host using IPv6 subnet id
boost::multi_index::ordered_non_unique<
// Index using values returned by the @c Host::getIPv6SubnetID
boost::multi_index::const_mem_fun<Host, SubnetID,
&Host::getIPv6SubnetID>
> >
> >
> HostContainer; > HostContainer;
...@@ -91,6 +105,26 @@ typedef HostContainer::nth_index<1>::type HostContainerIndex1; ...@@ -91,6 +105,26 @@ typedef HostContainer::nth_index<1>::type HostContainerIndex1;
typedef std::pair<HostContainerIndex1::iterator, typedef std::pair<HostContainerIndex1::iterator,
HostContainerIndex1::iterator> HostContainerIndex1Range; HostContainerIndex1::iterator> HostContainerIndex1Range;
/// @brief Third index type in the @c HostContainer.
///
/// This index allows for searching for @c Host objects using a
/// IPv4 subnet id.
typedef HostContainer::nth_index<2>::type HostContainerIndex2;
/// @brief Results range returned using the @c HostContainerIndex2.
typedef std::pair<HostContainerIndex2::iterator,
HostContainerIndex2::iterator> HostContainerIndex2Range;
/// @brief Forth index type in the @c HostContainer.
///
/// This index allows for searching for @c Host objects using a
/// IPv6 subnet id.
typedef HostContainer::nth_index<3>::type HostContainerIndex3;
/// @brief Results range returned using the @c HostContainerIndex3.
typedef std::pair<HostContainerIndex3::iterator,
HostContainerIndex3::iterator> HostContainerIndex3Range;
/// @brief Defines one entry for the Host Container for v6 hosts /// @brief Defines one entry for the Host Container for v6 hosts
/// ///
/// It's essentially a pair of (IPv6 reservation, Host pointer). /// It's essentially a pair of (IPv6 reservation, Host pointer).
...@@ -167,6 +201,13 @@ typedef boost::multi_index_container< ...@@ -167,6 +201,13 @@ typedef boost::multi_index_container<
&HostResrv6Tuple::getKey &HostResrv6Tuple::getKey
> >
> >
>,
// Third index is used to search for the host using IPv6 subnet id
boost::multi_index::ordered_non_unique<
// Index using values returned by the @c Host::getIPv6SubnetID
boost::multi_index::member<HostResrv6Tuple, const SubnetID,
&HostResrv6Tuple::subnet_id_>
> >
> >
> HostContainer6; > HostContainer6;
...@@ -191,6 +232,16 @@ typedef HostContainer6::nth_index<1>::type HostContainer6Index1; ...@@ -191,6 +232,16 @@ typedef HostContainer6::nth_index<1>::type HostContainer6Index1;
typedef std::pair<HostContainer6Index1::iterator, typedef std::pair<HostContainer6Index1::iterator,
HostContainer6Index1::iterator> HostContainer6Index1Range; HostContainer6Index1::iterator> HostContainer6Index1Range;
/// @brief Third index type in the @c HostContainer6.
///
/// This index allows for searching for @c Host objects using a
/// IPv6 subnet id.
typedef HostContainer6::nth_index<2>::type HostContainer6Index2;
/// @brief Results range returned using the @c HostContainer6Index2.
typedef std::pair<HostContainer6Index2::iterator,
HostContainer6Index2::iterator> HostContainer6Index2Range;
}; // end of isc::dhcp namespace }; // end of isc::dhcp namespace
}; // end of isc namespace }; // end of isc namespace
......
...@@ -31,6 +31,18 @@ detected by the host manager. ...@@ -31,6 +31,18 @@ detected by the host manager.
This is a normal message being printed when the server closes host data This is a normal message being printed when the server closes host data
source connection. source connection.
% HOSTS_CFG_DEL_ALL_SUBNET4 deleted all %1 host(s) for subnet id %2
This debug message is issued when all IPv4 reservations are deleted for
the specified subnet. The first argument specifies how many reservations
have been deleted. The second argument is the subnet identifier.
% HOSTS_CFG_DEL_ALL_SUBNET6 deleted all %1 host(s) including %2 IPv6 reservation(s) for subnet id %3
This debug message is issued when all IPv6 reservations are deleted for
the specified subnet. The first argument specifies how many hosts
have been deleted. The second argument specifies how many IPv6
(addresses and prefixes) have been deleted. The third argument is the
subnet identifier.
% HOSTS_CFG_GET_ALL_ADDRESS4 get all hosts with reservations for IPv4 address %1 % HOSTS_CFG_GET_ALL_ADDRESS4 get all hosts with reservations for IPv4 address %1
This debug message is issued when starting to retrieve all hosts, holding the This debug message is issued when starting to retrieve all hosts, holding the
reservation for the specific IPv4 address, from the configuration. The reservation for the specific IPv4 address, from the configuration. The
......
...@@ -235,6 +235,54 @@ TEST_F(CfgHostsTest, getAll4ByAddress) { ...@@ -235,6 +235,54 @@ TEST_F(CfgHostsTest, getAll4ByAddress) {
EXPECT_EQ(25, *subnet_ids.rbegin()); EXPECT_EQ(25, *subnet_ids.rbegin());
} }
// This test checks that all reservations for the specified IPv4 subnet can
// be deleted.
TEST_F(CfgHostsTest, deleteAll4) {
CfgHosts cfg;
// Add hosts.
for (unsigned i = 0; i < 25; ++i) {
// Hosts will differ by hostname. It is easier than differentiating by
// IPv4 address because if they all have zero IPv4 address it is
// easier to retrieve all of them to check the host counts.
std::ostringstream s;
s << "hostname" << i;
// Add host identified by the HW address.
cfg.add(HostPtr(new Host(hwaddrs_[i]->toText(false),
"hw-address",
SubnetID(1 + i % 2), SUBNET_ID_UNUSED,
IOAddress::IPV4_ZERO_ADDRESS(),
"hostname")));
}
// Get all inserted hosts.
HostCollection hosts = cfg.getAll4(IOAddress::IPV4_ZERO_ADDRESS());
std::set<uint32_t> subnet_ids;
for (HostCollection::const_iterator host = hosts.begin(); host != hosts.end();
++host) {
subnet_ids.insert((*host)->getIPv4SubnetID());
}
// Make sure there are two unique subnets: 1 and 2.
ASSERT_EQ(2, subnet_ids.size());
EXPECT_EQ(1, *subnet_ids.begin());
EXPECT_EQ(2, *subnet_ids.rbegin());
// Delete all hosts for subnet id 2. There should be 12 of them.
EXPECT_EQ(12, cfg.delAll4(SubnetID(2)));
// Gather the host counts again.
subnet_ids.clear();
hosts = cfg.getAll4(IOAddress::IPV4_ZERO_ADDRESS());
for (HostCollection::const_iterator host = hosts.begin(); host != hosts.end();
++host) {
subnet_ids.insert((*host)->getIPv4SubnetID());
}
// We should only have hosts for one subnet and it should be the subnet
// with ID of 1.
ASSERT_EQ(1, subnet_ids.size());
EXPECT_EQ(1, *subnet_ids.begin());
}
// This test checks that the reservations can be retrieved for the particular // This test checks that the reservations can be retrieved for the particular
// host connected to the specific IPv4 subnet (by subnet id). // host connected to the specific IPv4 subnet (by subnet id).
TEST_F(CfgHostsTest, get4) { TEST_F(CfgHostsTest, get4) {
...@@ -409,6 +457,53 @@ TEST_F(CfgHostsTest, get6) { ...@@ -409,6 +457,53 @@ TEST_F(CfgHostsTest, get6) {
} }
} }
// This test checks that all reservations for the specified IPv6 subnet can
// be deleted.
TEST_F(CfgHostsTest, deleteAll6) {
CfgHosts cfg;
// Add hosts.
for (unsigned i = 0; i < 25; ++i) {
// Add host identified by HW address. The subnet for which we're
// adding the host has id of 1 for even values of i and 2 for
// odd values of i.
HostPtr host = HostPtr(new Host(hwaddrs_[i]->toText(false),
"hw-address",
SubnetID(10), SubnetID(1 + i % 2),
IOAddress("0.0.0.0")));
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
increase(IOAddress("2001:db8:1::1"),
i)));
cfg.add(host);
}
// Delete all hosts for subnet id. There should be 13 of them.
EXPECT_EQ(13, cfg.delAll6(SubnetID(1)));
for (unsigned i = 0; i < 25; ++i) {
// Calculate subnet id for the given i.
SubnetID subnet_id = 1 + i % 2;
// Try to retrieve host by HW address.
HostPtr host = cfg.get6(subnet_id, Host::IDENT_HWADDR,
&hwaddrs_[i]->hwaddr_[0],
hwaddrs_[i]->hwaddr_.size());
// The host should exist for subnet id of 2.
if (subnet_id == 2) {
ASSERT_TRUE(host);
EXPECT_EQ(subnet_id, host->getIPv6SubnetID());
IPv6ResrvRange reservations =
host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
ASSERT_EQ(1, std::distance(reservations.first, reservations.second));
EXPECT_EQ(increase(IOAddress("2001:db8:1::1"), i),
reservations.first->second.getPrefix());
} else {
// All hosts for subnet id 2 should be gone.
EXPECT_FALSE(host);
}
}
}
// This test checks that the DHCPv6 reservations can be unparsed // This test checks that the DHCPv6 reservations can be unparsed
TEST_F(CfgHostsTest, unparse6) { TEST_F(CfgHostsTest, unparse6) {
CfgMgr::instance().setFamily(AF_INET6); CfgMgr::instance().setFamily(AF_INET6);
......
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