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
CfgHosts::del4(const SubnetID& /*subnet_id*/,
const Host::IdentifierType& /*identifier_type*/,
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
CfgHosts::del6(const SubnetID& /*subnet_id*/,
const Host::IdentifierType& /*identifier_type*/,
/// @param addr specified address.
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)
///
/// This method supports v4 only.
const Host::IdentifierType& identifier_type,
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)
///
/// This method supports v6 only.
// Index using values returned by the @c Host::getIPv4Reservation.
boost::multi_index::const_mem_fun<Host, const asiolink::IOAddress&,
&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;
typedef std::pair<HostContainerIndex1::iterator,
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
///
/// It's essentially a pair of (IPv6 reservation, Host pointer).
&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;
typedef std::pair<HostContainer6Index1::iterator,
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 namespace
This is a normal message being printed when the server closes host data
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
This debug message is issued when starting to retrieve all hosts, holding the
reservation for the specific IPv4 address, from the configuration. The
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
// host connected to the specific IPv4 subnet (by subnet id).
TEST_F(CfgHostsTest, get4) {
}
}
+// 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
TEST_F(CfgHostsTest, unparse6) {
CfgMgr::instance().setFamily(AF_INET6);