Commit 34ed1671 authored by Francis Dupont's avatar Francis Dupont

[392-search-of-reservations-by-hostname] Checkpont: add new methods - tests to write

parent 74dddcbf
......@@ -136,6 +136,41 @@ public:
virtual ConstHostCollection
getAll6(const SubnetID& subnet_id) const = 0;
/// @brief Return all hosts with a hostname.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname.
///
/// @param hostname The lower case hostname.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAllbyHostname(const std::string& hostname) const = 0;
/// @brief Return all hosts with a hostname in a DHCPv4 subnet.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname in a specified subnet.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const = 0;
/// @brief Return all hosts with a hostname in a DHCPv6 subnet.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname in a specified subnet.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const = 0;
/// @brief Returns range of hosts in a DHCPv4 subnet.
///
/// This method implements paged browsing of host databases. The
......
......@@ -82,6 +82,64 @@ CfgHosts::getAll6(const SubnetID& subnet_id) {
return (collection);
}
ConstHostCollection
CfgHosts::getAllbyHostname(const std::string& hostname) const {
// Do not issue logging message here because it will be logged by
// the getAllbyHostnameInternal method.
ConstHostCollection collection;
getAllbyHostnameInternal<ConstHostCollection>(hostname, collection);
return (collection);
}
HostCollection
CfgHosts::getAllbyHostname(const std::string& hostname) {
// Do not issue logging message here because it will be logged by
// the getAllbyHostnameInternal method.
HostCollection collection;
getAllbyHostnameInternal<HostCollection>(hostname, collection);
return (collection);
}
ConstHostCollection
CfgHosts::getAllbyHostname4(const std::string& hostname,
const SubnetID& subnet_id) const {
// Do not issue logging message here because it will be logged by
// the getAllbyHostnameInternal4 method.
ConstHostCollection collection;
getAllbyHostnameInternal4<ConstHostCollection>(hostname, subnet_id, collection);
return (collection);
}
HostCollection
CfgHosts::getAllbyHostname4(const std::string& hostname,
const SubnetID& subnet_id) {
// Do not issue logging message here because it will be logged by
// the getAllbyHostnameInternal4 method.
HostCollection collection;
getAllbyHostnameInternal4<HostCollection>(hostname, subnet_id, collection);
return (collection);
}
ConstHostCollection
CfgHosts::getAllbyHostname6(const std::string& hostname,
const SubnetID& subnet_id) const {
// Do not issue logging message here because it will be logged by
// the getAllbyHostnameInternal6 method.
ConstHostCollection collection;
getAllbyHostnameInternal6<ConstHostCollection>(hostname, subnet_id, collection);
return (collection);
}
HostCollection
CfgHosts::getAllbyHostname6(const std::string& hostname,
const SubnetID& subnet_id) {
// Do not issue logging message here because it will be logged by
// the getAllbyHostnameInternal6 method.
HostCollection collection;
getAllbyHostnameInternal6<HostCollection>(hostname, subnet_id, collection);
return (collection);
}
ConstHostCollection
CfgHosts::getPage4(const SubnetID& subnet_id,
size_t& /*source_index*/,
......@@ -273,6 +331,106 @@ CfgHosts::getAllInternal6(const SubnetID& subnet_id,
.arg(storage.size());
}
template<typename Storage>
void
CfgHosts::getAllbyHostnameInternal(const std::string& hostname,
Storage& storage) const {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_HOSTNAME)
.arg(hostname);
// Use try hostname.
const HostContainerIndex5& idx = hosts_.get<5>();
// Append each Host object to the storage.
for (HostContainerIndex5::iterator host = idx.lower_bound(hostname);
host != idx.upper_bound(hostname);
++host) {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
HOSTS_CFG_GET_ALL_HOSTNAME_HOST)
.arg(hostname)
.arg((*host)->toText());
storage.push_back(*host);
}
// Log how many hosts have been found.
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_HOSTNAME_COUNT)
.arg(hostname)
.arg(storage.size());
}
template<typename Storage>
void
CfgHosts::getAllbyHostnameInternal4(const std::string& hostname,
const SubnetID& subnet_id,
Storage& storage) const {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4)
.arg(hostname);
// Use try hostname.
const HostContainerIndex5& idx = hosts_.get<5>();
// Append each Host object to the storage.
for (HostContainerIndex5::iterator host = idx.lower_bound(hostname);
host != idx.upper_bound(hostname);
++host) {
if ((*host)->getIPv4SubnetID() != subnet_id) {
continue;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_HOST)
.arg(hostname)
.arg(subnet_id)
.arg((*host)->toText());
storage.push_back(*host);
}
// Log how many hosts have been found.
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_COUNT)
.arg(hostname)
.arg(subnet_id)
.arg(storage.size());
}
template<typename Storage>
void
CfgHosts::getAllbyHostnameInternal6(const std::string& hostname,
const SubnetID& subnet_id,
Storage& storage) const {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6)
.arg(hostname);
// Use try hostname.
const HostContainerIndex5& idx = hosts_.get<5>();
// Append each Host object to the storage.
for (HostContainerIndex5::iterator host = idx.lower_bound(hostname);
host != idx.upper_bound(hostname);
++host) {
if ((*host)->getIPv6SubnetID() != subnet_id) {
continue;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_HOST)
.arg(hostname)
.arg(subnet_id)
.arg((*host)->toText());
storage.push_back(*host);
}
// Log how many hosts have been found.
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_COUNT)
.arg(hostname)
.arg(subnet_id)
.arg(storage.size());
}
template<typename Storage>
void
CfgHosts::getPageInternal4(const SubnetID& subnet_id,
......
......@@ -119,6 +119,76 @@ public:
virtual HostCollection
getAll6(const SubnetID& subnet_id);
/// @brief Return all hosts with a hostname.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname.
///
/// @param hostname The lower case hostname.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAllbyHostname(const std::string& hostname) const;
/// @brief Return all hosts with a hostname.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname.
///
/// @param hostname The lower case hostname.
///
/// @return Collection of @c Host objects.
virtual HostCollection
getAllbyHostname(const std::string& hostname);
/// @brief Return all hosts with a hostname in a DHCPv4 subnet.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname in a specified subnet.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const;
/// @brief Return all hosts with a hostname in a DHCPv4 subnet.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname in a specified subnet.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
///
/// @return Collection of @c Host objects.
virtual HostCollection
getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id);
/// @brief Return all hosts with a hostname in a DHCPv6 subnet.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname in a specified subnet.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const;
/// @brief Return all hosts with a hostname in a DHCPv6 subnet.
///
/// This method returns all @c Host objects which represent reservations
/// using a specified hostname in a specified subnet.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
///
/// @return Collection of @c Host objects.
virtual HostCollection
getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id);
/// @brief Returns range of hosts in a DHCPv4 subnet.
///
/// This method returns a page of @c Host objects which represent
......@@ -476,6 +546,52 @@ private:
void getAllInternal6(const SubnetID& subnet_id,
Storage& storage) const;
/// @brief Return all hosts with a hostname.
///
/// This private method is called by the @c CfgHosts::getAllbyHostname
/// method which finds the @c Host objects in a specified subnet.
/// The retrieved objects are appended to the @c storage container.
///
/// @param hostname The lower case hostname.
/// @param [out] storage Container to which the retrieved objects are
/// appended.
/// @tparam One of the @c ConstHostCollection of @c HostCollection.
template<typename Storage>
void getAllbyHostnameInternal(const std::string& hostname,
Storage& storage) const;
/// @brief Return all hosts with a hostname and a DHCPv4 subnet.
///
/// This private method is called by the @c CfgHosts::getAllbyHostname4
/// method which finds the @c Host objects in a specified subnet.
/// The retrieved objects are appended to the @c storage container.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
/// @param [out] storage Container to which the retrieved objects are
/// appended.
/// @tparam One of the @c ConstHostCollection of @c HostCollection.
template<typename Storage>
void getAllbyHostnameInternal4(const std::string& hostname,
const SubnetID& subnet_id,
Storage& storage) const;
/// @brief Return all hosts with a hostname and a DHCPv6 subnet.
///
/// This private method is called by the @c CfgHosts::getAllbyHostname6
/// method which finds the @c Host objects in a specified subnet.
/// The retrieved objects are appended to the @c storage container.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
/// @param [out] storage Container to which the retrieved objects are
/// appended.
/// @tparam One of the @c ConstHostCollection of @c HostCollection.
template<typename Storage>
void getAllbyHostnameInternal6(const std::string& hostname,
const SubnetID& subnet_id,
Storage& storage) const;
/// @brief Returns a page of @c Host objects in a DHCPv4 subnet.
///
/// This private method is called by the @c CfgHosts::getPage4
......
......@@ -259,7 +259,7 @@ public:
// Inserts all parameters belonging to any reservation from a single host.
static constexpr StatementTag INSERT_HOST = "INSERT_HOST";
// Retrieves hosts information, IPv6 reservations and both IPv4 and IPv6
// Retrieves host information, IPv6 reservations and both IPv4 and IPv6
// options associated with it.
static constexpr StatementTag GET_HOST = "GET_HOST";
......@@ -314,6 +314,21 @@ public:
static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID =
"GET_HOST_BY_IPV6_SUBNET_ID";
// Retrieves host information, IPv6 reservations and both IPv4 and IPv6
// options associated with it using hostname.
static constexpr StatementTag GET_HOST_BY_HOST_NAME =
"GET_HOST_BY_HOST_NAME";
// Retrieves host information along with the IPv4 options associated
// with it using hostname and subnet identifier.
static constexpr StatementTag GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID =
"GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID";
// Retrieves host information; IPv6 reservations and IPv6 options
// associated with it using hostname and subnet identifier.
static constexpr StatementTag GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID =
"GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID";
// Retrieves host information along with the IPv4 options associated
// with it using a subnet identifier from first host (paging).
static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_LIMIT =
......@@ -469,6 +484,9 @@ constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_PREFIX;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_NAME;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_LIMIT;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_LIMIT;
constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_NEXT_KEY;
......@@ -901,6 +919,119 @@ StatementMap CqlHostExchange::tagged_statements_ = {
"ALLOW FILTERING "
}},
{GET_HOST_BY_HOST_NAME,
{GET_HOST_BY_HOST_NAME,
"SELECT "
"key, "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"host_ipv4_next_server, "
"host_ipv4_server_hostname, "
"host_ipv4_boot_file_name, "
"auth_key, "
"hostname, "
"user_context, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id, "
"option_user_context, "
"option_scope_id "
"FROM hosts "
"WHERE hostname = ? "
"ALLOW FILTERING "
}},
{GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID,
{GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID,
"SELECT "
"key, "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"host_ipv4_next_server, "
"host_ipv4_server_hostname, "
"host_ipv4_boot_file_name, "
"auth_key, "
"hostname, "
"user_context, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id, "
"option_user_context, "
"option_scope_id "
"FROM hosts "
"WHERE hostname = ? "
"AND host_ipv4_subnet_id = ? "
"ALLOW FILTERING "
}},
{GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID,
{GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID,
"SELECT "
"key, "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"host_ipv4_next_server, "
"host_ipv4_server_hostname, "
"host_ipv4_boot_file_name, "
"auth_key, "
"hostname, "
"user_context, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id, "
"option_user_context, "
"option_scope_id "
"FROM hosts "
"WHERE hostname = ? "
"AND host_ipv6_subnet_id = ? "
"ALLOW FILTERING "
}},
{GET_HOST_BY_IPV4_SUBNET_ID_LIMIT,
{GET_HOST_BY_IPV4_SUBNET_ID_LIMIT,
"SELECT "
......@@ -1914,6 +2045,32 @@ public:
/// @param subnet_id identifier of the subnet to which hosts belong
virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const;
/// @brief Implementation of @ref CqlHostDataSource::getAllbyHostname()
///
/// See @ref CqlHostDataSource::getAllbyHostname() for parameter details.
///
/// @param hostname The lower case hostname.
virtual ConstHostCollection
getAllbyHostname(const std::string& hostname) const;
/// @brief Implementation of @ref CqlHostDataSource::getAllbyHostname4()
///
/// See @ref CqlHostDataSource::getAllbyHostname4() for parameter details.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
virtual ConstHostCollection
getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const;
/// @brief Implementation of @ref CqlHostDataSource::getAllbyHostname6()
///
/// See @ref CqlHostDataSource::getAllbyHostname6() for parameter details.
///
/// @param hostname The lower case hostname.
/// @param subnet_id Subnet identifier.
virtual ConstHostCollection
getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const;
/// @brief Implementation of @ref CqlHostDataSource::getPage4()
///
/// See @ref CqlHostDataSource::getPage4() for parameter details.
......@@ -2449,6 +2606,63 @@ CqlHostDataSourceImpl::getAll6(const SubnetID& subnet_id) const {
return (result);
}
ConstHostCollection
CqlHostDataSourceImpl::getAllbyHostname(const std::string& hostname) const {
// Convert to CQL data types.
std::string hostname_ = hostname;
// Bind to array.
AnyArray where_values;
where_values.add(&hostname_);
// Run statement.
ConstHostCollection result =
getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_NAME,
where_values);
return (result);
}
ConstHostCollection
CqlHostDataSourceImpl::getAllbyHostname4(const std::string& hostname,
const SubnetID& subnet_id) const {
// Convert to CQL data types.
std::string hostname_ = hostname;
cass_int32_t host_ipv4_subnet_id = static_cast<cass_int32_t>(subnet_id);
// Bind to array.
AnyArray where_values;
where_values.add(&hostname_);
where_values.add(&host_ipv4_subnet_id);
// Run statement.
ConstHostCollection result =
getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID,
where_values);
return (result);
}
ConstHostCollection
CqlHostDataSourceImpl::getAllbyHostname6(const std::string& hostname,
const SubnetID& subnet_id) const {
// Convert to CQL data types.
std::string hostname_ = hostname;
cass_int32_t host_ipv6_subnet_id = static_cast<cass_int32_t>(subnet_id);
// Bind to array.
AnyArray where_values;
where_values.add(&hostname_);
where_values.add(&host_ipv6_subnet_id);
// Run statement.
ConstHostCollection result =
getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID,
where_values);
return (result);
}
// There are some problems implementing this for Cassandra.
// Attempts show the per page ordering does not work and
// it is not possible to order by TOKEN(host_id).
......@@ -3034,6 +3248,29 @@ CqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
return (impl_->getAll6(subnet_id));
}
ConstHostCollection
CqlHostDataSource::getAllbyHostname(const std::string& hostname) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_GET_ALL);
return (impl_->getAllbyHostname(hostname));
}
ConstHostCollection
CqlHostDataSource::getAllbyHostname4(const std::string& hostname,
const SubnetID& subnet_id) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_GET_ALL);