summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2019-09-29 09:28:13 +0200
committerFrancis Dupont <fdupont@isc.org>2019-10-15 11:45:32 +0200
commit34ed1671950db527566de74f47c9b334f44688ab (patch)
tree8e61d98b6f1f8c546ca2d1761fab878c8085f283
parent[#934,!531] kea-centos-8 for virtualbox and lxc uploaded and available (diff)
downloadkea-34ed1671950db527566de74f47c9b334f44688ab.tar.xz
kea-34ed1671950db527566de74f47c9b334f44688ab.zip
[392-search-of-reservations-by-hostname] Checkpont: add new methods - tests to write
-rw-r--r--src/lib/dhcpsrv/base_host_data_source.h35
-rw-r--r--src/lib/dhcpsrv/cfg_hosts.cc158
-rw-r--r--src/lib/dhcpsrv/cfg_hosts.h116
-rw-r--r--src/lib/dhcpsrv/cql_host_data_source.cc239
-rw-r--r--src/lib/dhcpsrv/cql_host_data_source.h35
-rw-r--r--src/lib/dhcpsrv/host.h6
-rw-r--r--src/lib/dhcpsrv/host_container.h12
-rw-r--r--src/lib/dhcpsrv/host_mgr.cc36
-rw-r--r--src/lib/dhcpsrv/host_mgr.h35
-rw-r--r--src/lib/dhcpsrv/hosts_messages.cc20
-rw-r--r--src/lib/dhcpsrv/hosts_messages.h11
-rw-r--r--src/lib/dhcpsrv/hosts_messages.mes43
-rw-r--r--src/lib/dhcpsrv/mysql_host_data_source.cc150
-rw-r--r--src/lib/dhcpsrv/mysql_host_data_source.h35
-rw-r--r--src/lib/dhcpsrv/pgsql_host_data_source.cc135
-rw-r--r--src/lib/dhcpsrv/pgsql_host_data_source.h35
-rw-r--r--src/lib/dhcpsrv/tests/host_cache_unittest.cc14
-rw-r--r--src/lib/dhcpsrv/tests/host_unittest.cc10
-rw-r--r--src/lib/dhcpsrv/testutils/memory_host_data_source.cc40
-rw-r--r--src/lib/dhcpsrv/testutils/memory_host_data_source.h20
-rw-r--r--src/lib/dhcpsrv/writable_host_data_source.h35
21 files changed, 1212 insertions, 8 deletions
diff --git a/src/lib/dhcpsrv/base_host_data_source.h b/src/lib/dhcpsrv/base_host_data_source.h
index dae3977be2..cb59481140 100644
--- a/src/lib/dhcpsrv/base_host_data_source.h
+++ b/src/lib/dhcpsrv/base_host_data_source.h
@@ -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
diff --git a/src/lib/dhcpsrv/cfg_hosts.cc b/src/lib/dhcpsrv/cfg_hosts.cc
index 81051cb4e6..f93467665c 100644
--- a/src/lib/dhcpsrv/cfg_hosts.cc
+++ b/src/lib/dhcpsrv/cfg_hosts.cc
@@ -83,6 +83,64 @@ CfgHosts::getAll6(const SubnetID& subnet_id) {
}
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*/,
uint64_t lower_host_id,
@@ -275,6 +333,106 @@ CfgHosts::getAllInternal6(const SubnetID& subnet_id,
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,
uint64_t lower_host_id,
const HostPageSize& page_size,
diff --git a/src/lib/dhcpsrv/cfg_hosts.h b/src/lib/dhcpsrv/cfg_hosts.h
index 2f0fb862c8..54edd268e2 100644
--- a/src/lib/dhcpsrv/cfg_hosts.h
+++ b/src/lib/dhcpsrv/cfg_hosts.h
@@ -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
diff --git a/src/lib/dhcpsrv/cql_host_data_source.cc b/src/lib/dhcpsrv/cql_host_data_source.cc
index 34f6d3e272..085c9da46c 100644
--- a/src/lib/dhcpsrv/cql_host_data_source.cc
+++ b/src/lib/dhcpsrv/cql_host_data_source.cc
@@ -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).
@@ -3035,6 +3249,29 @@ CqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
}
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);
+
+ return (impl_->getAllbyHostname4(hostname, subnet_id));
+}
+
+ConstHostCollection
+CqlHostDataSource::getAllbyHostname6(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_GET_ALL);
+
+ return (impl_->getAllbyHostname6(hostname, subnet_id));
+}
+
+ConstHostCollection
CqlHostDataSource::getPage4(const SubnetID& subnet_id,
size_t& /*source_index*/,
uint64_t lower_host_id,
diff --git a/src/lib/dhcpsrv/cql_host_data_source.h b/src/lib/dhcpsrv/cql_host_data_source.h
index cac22825f5..c90e3b1f55 100644
--- a/src/lib/dhcpsrv/cql_host_data_source.h
+++ b/src/lib/dhcpsrv/cql_host_data_source.h
@@ -193,6 +193,41 @@ public:
virtual ConstHostCollection
getAll6(const SubnetID& subnet_id) const override;
+ /// @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 override;
+
+ /// @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 override;
+
+ /// @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 override;
+
/// @brief Returns range of hosts in a DHCPv4 subnet.
///
/// Not implemented.
diff --git a/src/lib/dhcpsrv/host.h b/src/lib/dhcpsrv/host.h
index 8c81ca8a5c..ad60da7c47 100644
--- a/src/lib/dhcpsrv/host.h
+++ b/src/lib/dhcpsrv/host.h
@@ -16,6 +16,7 @@
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/subnet_id.h>
#include <boost/shared_ptr.hpp>
+#include <boost/algorithm/string.hpp>
#include <list>
#include <map>
#include <string>
@@ -569,6 +570,11 @@ public:
return (hostname_);
}
+ /// @brief Returns reserved hostname in lower case.
+ std::string getLowerHostname() const {
+ return (boost::algorithm::to_lower_copy(hostname_));
+ }
+
/// @brief Adds new client class for DHCPv4.
///
/// @param class_name Class name.
diff --git a/src/lib/dhcpsrv/host_container.h b/src/lib/dhcpsrv/host_container.h
index ae21449c4e..55692cf25d 100644
--- a/src/lib/dhcpsrv/host_container.h
+++ b/src/lib/dhcpsrv/host_container.h
@@ -88,6 +88,13 @@ typedef boost::multi_index_container<
// Index using values returned by the @c Host::getHostId
boost::multi_index::const_mem_fun<Host, uint64_t,
&Host::getHostId>
+ >,
+
+ // Sixth index is used to search for the host using hostname
+ boost::multi_index::ordered_non_unique<
+ // Index using values returned by the @c Host::getLowerHostname
+ boost::multi_index::const_mem_fun<Host, std::string,
+ &Host::getLowerHostname>
>
>
> HostContainer;
@@ -141,6 +148,11 @@ typedef HostContainer::nth_index<4>::type HostContainerIndex4;
typedef std::pair<HostContainerIndex4::iterator,
HostContainerIndex4::iterator> HostContainerIndex4Range;
+/// @brief Sixth index type in the @c HostContainer.
+///
+/// This index allows for searching for @c Host objects using a hostname.
+typedef HostContainer::nth_index<5>::type HostContainerIndex5;
+
/// @brief Defines one entry for the Host Container for v6 hosts
///
/// It's essentially a pair of (IPv6 reservation, Host pointer).
diff --git a/src/lib/dhcpsrv/host_mgr.cc b/src/lib/dhcpsrv/host_mgr.cc
index 6903d9ce84..ebcab3bdc3 100644
--- a/src/lib/dhcpsrv/host_mgr.cc
+++ b/src/lib/dhcpsrv/host_mgr.cc
@@ -136,6 +136,42 @@ HostMgr::getAll6(const SubnetID& subnet_id) const {
}
ConstHostCollection
+HostMgr::getAllbyHostname(const std::string& hostname) const {
+ ConstHostCollection hosts = getCfgHosts()->getAllbyHostname(hostname);
+ for (auto source : alternate_sources_) {
+ ConstHostCollection hosts_plus = source->getAllbyHostname(hostname);
+ hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
+ }
+ return (hosts);
+}
+
+ConstHostCollection
+HostMgr::getAllbyHostname4(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ ConstHostCollection hosts = getCfgHosts()->getAllbyHostname4(hostname,
+ subnet_id);
+ for (auto source : alternate_sources_) {
+ ConstHostCollection hosts_plus = source->getAllbyHostname4(hostname,
+ subnet_id);
+ hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
+ }
+ return (hosts);
+}
+
+ConstHostCollection
+HostMgr::getAllbyHostname6(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ ConstHostCollection hosts = getCfgHosts()->getAllbyHostname6(hostname,
+ subnet_id);
+ for (auto source : alternate_sources_) {
+ ConstHostCollection hosts_plus = source->getAllbyHostname6(hostname,
+ subnet_id);
+ hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
+ }
+ return (hosts);
+}
+
+ConstHostCollection
HostMgr::getPage4(const SubnetID& subnet_id,
size_t& source_index,
uint64_t lower_host_id,
diff --git a/src/lib/dhcpsrv/host_mgr.h b/src/lib/dhcpsrv/host_mgr.h
index caedff49b6..357b156328 100644
--- a/src/lib/dhcpsrv/host_mgr.h
+++ b/src/lib/dhcpsrv/host_mgr.h
@@ -160,6 +160,41 @@ public:
virtual ConstHostCollection
getAll6(const SubnetID& subnet_id) 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 const @c Host objects.
+ virtual ConstHostCollection
+ getAllbyHostname(const std::string& hostname) 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 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 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 Returns range of hosts in a DHCPv4 subnet.
///
/// This method returns a page of @c Host objects representing
diff --git a/src/lib/dhcpsrv/hosts_messages.cc b/src/lib/dhcpsrv/hosts_messages.cc
index c210ee2c54..7fa76c6907 100644
--- a/src/lib/dhcpsrv/hosts_messages.cc
+++ b/src/lib/dhcpsrv/hosts_messages.cc
@@ -1,4 +1,4 @@
-// File created from ../../../src/lib/dhcpsrv/hosts_messages.mes on Fri Feb 08 2019 20:31
+// File created from ../../../src/lib/dhcpsrv/hosts_messages.mes on Sun Sep 29 2019 01:57
#include <cstddef>
#include <log/message_types.h>
@@ -21,6 +21,15 @@ extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS4_HOST = "HOSTS_CFG_GE
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6 = "HOSTS_CFG_GET_ALL_ADDRESS6";
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6_COUNT = "HOSTS_CFG_GET_ALL_ADDRESS6_COUNT";
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6_HOST = "HOSTS_CFG_GET_ALL_ADDRESS6_HOST";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME = "HOSTS_CFG_GET_ALL_HOSTNAME";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_COUNT = "HOSTS_CFG_GET_ALL_HOSTNAME_COUNT";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_HOST = "HOSTS_CFG_GET_ALL_HOSTNAME_HOST";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4 = "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_COUNT = "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_COUNT";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_HOST = "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_HOST";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6 = "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_COUNT = "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_COUNT";
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_HOST = "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_HOST";
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER = "HOSTS_CFG_GET_ALL_IDENTIFIER";
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT = "HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT";
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER_HOST = "HOSTS_CFG_GET_ALL_IDENTIFIER_HOST";
@@ -75,6 +84,15 @@ const char* values[] = {
"HOSTS_CFG_GET_ALL_ADDRESS6", "get all hosts with reservations for IPv6 address %1",
"HOSTS_CFG_GET_ALL_ADDRESS6_COUNT", "using address %1, found %2 host(s)",
"HOSTS_CFG_GET_ALL_ADDRESS6_HOST", "using address %1 found host: %2",
+ "HOSTS_CFG_GET_ALL_HOSTNAME", "get all hosts with reservations for hostname %1",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_COUNT", "using hostname %1, found %2 host(s)",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_HOST", "using hostname %1, found host: %2",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4", "get all hosts with reservations for hostname %1 and IPv4 subnet %2",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_COUNT", "using hostname %1 and IPv4 subnet %2, found %3 host(s)",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_HOST", "using hostname %1 and IPv4 subnet %2, found host: %3",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6", "get all hosts with reservations for hostname %1 and IPv6 subnet %2",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_COUNT", "using hostname %1 and IPv6 subnet %2, found %3 host(s)",
+ "HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_HOST", "using hostname %1 and IPv6 subnet %2, found host: %3",
"HOSTS_CFG_GET_ALL_IDENTIFIER", "get all hosts with reservations using identifier: %1",
"HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT", "using identifier %1, found %2 host(s)",
"HOSTS_CFG_GET_ALL_IDENTIFIER_HOST", "using identifier: %1, found host: %2",
diff --git a/src/lib/dhcpsrv/hosts_messages.h b/src/lib/dhcpsrv/hosts_messages.h
index 6a13da5754..5d636c3f73 100644
--- a/src/lib/dhcpsrv/hosts_messages.h
+++ b/src/lib/dhcpsrv/hosts_messages.h
@@ -1,4 +1,4 @@
-// File created from ../../../src/lib/dhcpsrv/hosts_messages.mes on Fri Feb 08 2019 20:31
+// File created from ../../../src/lib/dhcpsrv/hosts_messages.mes on Sun Sep 29 2019 01:57
#ifndef HOSTS_MESSAGES_H
#define HOSTS_MESSAGES_H
@@ -22,6 +22,15 @@ extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS4_HOST;
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6;
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6_COUNT;
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6_HOST;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_COUNT;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_HOST;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_COUNT;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_HOST;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_COUNT;
+extern const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_HOST;
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER;
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT;
extern const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER_HOST;
diff --git a/src/lib/dhcpsrv/hosts_messages.mes b/src/lib/dhcpsrv/hosts_messages.mes
index d6dc7542aa..a44d6ea725 100644
--- a/src/lib/dhcpsrv/hosts_messages.mes
+++ b/src/lib/dhcpsrv/hosts_messages.mes
@@ -73,6 +73,49 @@ This debug message is issued when found host with the reservation
for the specified IPv6 address. The arguments specify the IPv6 address
and the detailed description of the host found.
+% HOSTS_CFG_GET_ALL_HOSTNAME get all hosts with reservations for hostname %1
+This debug message is issued when starting to retrieve all hosts with
+the specific hostname. The argument specifies hostname.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_COUNT using hostname %1, found %2 host(s)
+This debug message include the details of the host found using the
+hostname. The arguments specify hostname and the number of hosts found
+respectively.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_HOST using hostname %1, found host: %2
+This debug message includes the details of the host found using the hostname.
+The arguments specify hostname and found host details respectively.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4 get all hosts with reservations for hostname %1 and IPv4 subnet %2
+This debug message is issued when starting to retrieve all hosts with
+the specific hostname connected to the specific DHCPv4 subnet. The argument
+specifies hostname and subnet id.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_COUNT using hostname %1 and IPv4 subnet %2, found %3 host(s)
+This debug message include the details of the host found using the
+hostname and the DHCPv4 subnet id. The arguments specify hostname,
+subnet id and the number of hosts found respectively.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_HOST using hostname %1 and IPv4 subnet %2, found host: %3
+This debug message includes the details of the host found using the
+hostname and the DHCPv4 subnet id. The arguments specify hostname,
+subnet id and found host details respectively.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6 get all hosts with reservations for hostname %1 and IPv6 subnet %2
+This debug message is issued when starting to retrieve all hosts with
+the specific hostname connected to the specific DHCPv6 subnet. The argument
+specifies hostname and subnet id.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_COUNT using hostname %1 and IPv6 subnet %2, found %3 host(s)
+This debug message include the details of the host found using the
+hostname and the DHCPv6 subnet id. The arguments specify hostname,
+subnet id and the number of hosts found respectively.
+
+% HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_HOST using hostname %1 and IPv6 subnet %2, found host: %3
+This debug message includes the details of the host found using the
+hostname and the DHCPv6 subnet id. The arguments specify hostname,
+subnet id and found host details respectively.
+
% HOSTS_CFG_GET_ALL_IDENTIFIER get all hosts with reservations using identifier: %1
This debug message is issued when starting to retrieve reservations for all hosts
identified by HW address or DUID. The argument holds both the identifier
diff --git a/src/lib/dhcpsrv/mysql_host_data_source.cc b/src/lib/dhcpsrv/mysql_host_data_source.cc
index 4eddbdc68d..3c0c2d7c38 100644
--- a/src/lib/dhcpsrv/mysql_host_data_source.cc
+++ b/src/lib/dhcpsrv/mysql_host_data_source.cc
@@ -1915,6 +1915,9 @@ public:
GET_HOST_SUBID6_ADDR, // Gets host by IPv6 SubnetID and IPv6 prefix
GET_HOST_SUBID4, // Get hosts by IPv4 SubnetID
GET_HOST_SUBID6, // Get hosts by IPv6 SubnetID
+ GET_HOST_HOSTNAME, // Get host by hostname
+ GET_HOST_HOSTNAME_SUBID4, // Get host by hostname and IPv4 SubnetID
+ GET_HOST_HOSTNAME_SUBID6, // Get host by hostname and IPv6 SubnetID
GET_HOST_SUBID4_PAGE, // Get hosts by IPv4 SubnetID beginning by HID
GET_HOST_SUBID6_PAGE, // Get hosts by IPv6 SubnetID beginning by HID
INSERT_HOST, // Insert new host to collection
@@ -2308,6 +2311,73 @@ TaggedStatementArray tagged_statements = { {
"WHERE h.dhcp6_subnet_id = ? "
"ORDER BY h.host_id, o.option_id, r.reservation_id"},
+ // Retrieves host information, IPv6 reservations and both DHCPv4 and
+ // DHCPv6 options associated with the host. The LEFT JOIN clause is used
+ // to retrieve information from 4 different tables using a single query.
+ // Hence, this query returns multiple rows for a single host.
+ {MySqlHostDataSourceImpl::GET_HOST_HOSTNAME,
+ "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
+ "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, "
+ "h.hostname, h.dhcp4_client_classes, h.dhcp6_client_classes, "
+ "h.user_context, "
+ "h.dhcp4_next_server, h.dhcp4_server_hostname, "
+ "h.dhcp4_boot_file_name, h.auth_key, "
+ "o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
+ "o4.persistent, o4.user_context, "
+ "o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
+ "o6.persistent, o6.user_context, "
+ "r.reservation_id, r.address, r.prefix_len, r.type, "
+ "r.dhcp6_iaid "
+ "FROM hosts AS h "
+ "LEFT JOIN dhcp4_options AS o4 "
+ "ON h.host_id = o4.host_id "
+ "LEFT JOIN dhcp6_options AS o6 "
+ "ON h.host_id = o6.host_id "
+ "LEFT JOIN ipv6_reservations AS r "
+ "ON h.host_id = r.host_id "
+ "WHERE h.hostname = ? "
+ "ORDER BY h.host_id, o4.option_id, o6.option_id, r.reservation_id"},
+
+ // Retrieves host information and DHCPv4 options using hostname and
+ // subnet identifier. Left joining the dhcp4_options table results in
+ // multiple rows being returned for the same host.
+ {MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4,
+ "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
+ "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
+ "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
+ "h.dhcp4_next_server, h.dhcp4_server_hostname, "
+ "h.dhcp4_boot_file_name, h.auth_key, "
+ "o.option_id, o.code, o.value, o.formatted_value, o.space, "
+ "o.persistent, o.user_context "
+ "FROM hosts AS h "
+ "LEFT JOIN dhcp4_options AS o "
+ "ON h.host_id = o.host_id "
+ "WHERE h.hostname = ? AND h.dhcp4_subnet_id = ? "
+ "ORDER BY h.host_id, o.option_id"},
+
+ // Retrieves host information, IPv6 reservations and DHCPv6 options
+ // using hostname and subnet identifier. The number of rows returned
+ // is a multiplication of number of IPv6 reservations and DHCPv6 options.
+ {MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6,
+ "SELECT h.host_id, h.dhcp_identifier, "
+ "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
+ "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
+ "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
+
+ "h.dhcp4_next_server, h.dhcp4_server_hostname, "
+ "h.dhcp4_boot_file_name, h.auth_key, "
+ "o.option_id, o.code, o.value, o.formatted_value, o.space, "
+ "o.persistent, o.user_context, "
+ "r.reservation_id, r.address, r.prefix_len, r.type, "
+ "r.dhcp6_iaid "
+ "FROM hosts AS h "
+ "LEFT JOIN dhcp6_options AS o "
+ "ON h.host_id = o.host_id "
+ "LEFT JOIN ipv6_reservations AS r "
+ "ON h.host_id = r.host_id "
+ "WHERE h.hostname = ? AND h.dhcp6_subnet_id = ? "
+ "ORDER BY h.host_id, o.option_id, r.reservation_id"},
+
// Retrieves host information along with the DHCPv4 options associated with
// it. Left joining the dhcp4_options table results in multiple rows being
// returned for the same host. Hosts are retrieved by IPv4 subnet id
@@ -2973,6 +3043,86 @@ MySqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
}
ConstHostCollection
+MySqlHostDataSource::getAllbyHostname(const std::string& hostname) const {
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[1];
+ memset(inbind, 0, sizeof(inbind));
+
+ // Hostname
+ char hostname_[HOSTNAME_MAX_LEN];
+ strncpy(hostname_, hostname.c_str(), HOSTNAME_MAX_LEN - 1);
+ unsigned long length = hostname.length();
+ inbind[0].buffer_type = MYSQL_TYPE_STRING;
+ inbind[0].buffer = reinterpret_cast<char*>(hostname_);
+ inbind[0].buffer_length = length;
+ inbind[0].length = &length;
+
+ ConstHostCollection result;
+ impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME,
+ inbind, impl_->host_ipv46_exchange_,
+ result, false);
+ return (result);
+}
+
+ConstHostCollection
+MySqlHostDataSource::getAllbyHostname4(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[2];
+ memset(inbind, 0, sizeof(inbind));
+
+ // Hostname
+ char hostname_[HOSTNAME_MAX_LEN];
+ strncpy(hostname_, hostname.c_str(), HOSTNAME_MAX_LEN - 1);
+ unsigned long length = hostname.length();
+ inbind[0].buffer_type = MYSQL_TYPE_STRING;
+ inbind[0].buffer = reinterpret_cast<char*>(hostname_);
+ inbind[0].buffer_length = length;
+ inbind[0].length = &length;
+
+ // Subnet ID
+ uint32_t subnet = subnet_id;
+ inbind[1].buffer_type = MYSQL_TYPE_LONG;
+ inbind[1].buffer = reinterpret_cast<char*>(&subnet);
+ inbind[1].is_unsigned = MLM_TRUE;
+
+ ConstHostCollection result;
+ impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4,
+ inbind, impl_->host_exchange_,
+ result, false);
+ return (result);
+}
+
+ConstHostCollection
+MySqlHostDataSource::getAllbyHostname6(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[2];
+ memset(inbind, 0, sizeof(inbind));
+
+ // Hostname
+ char hostname_[HOSTNAME_MAX_LEN];
+ strncpy(hostname_, hostname.c_str(), HOSTNAME_MAX_LEN - 1);
+ unsigned long length = hostname.length();
+ inbind[0].buffer_type = MYSQL_TYPE_STRING;
+ inbind[0].buffer = reinterpret_cast<char*>(hostname_);
+ inbind[0].buffer_length = length;
+ inbind[0].length = &length;
+
+ // Subnet ID
+ uint32_t subnet = subnet_id;
+ inbind[1].buffer_type = MYSQL_TYPE_LONG;
+ inbind[1].buffer = reinterpret_cast<char*>(&subnet);
+ inbind[1].is_unsigned = MLM_TRUE;
+
+ ConstHostCollection result;
+ impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4,
+ inbind, impl_->host_ipv6_exchange_,
+ result, false);
+ return (result);
+}
+
+ConstHostCollection
MySqlHostDataSource::getPage4(const SubnetID& subnet_id,
size_t& /*source_index*/,
uint64_t lower_host_id,
diff --git a/src/lib/dhcpsrv/mysql_host_data_source.h b/src/lib/dhcpsrv/mysql_host_data_source.h
index 6f1e3b5c67..759f3304fa 100644
--- a/src/lib/dhcpsrv/mysql_host_data_source.h
+++ b/src/lib/dhcpsrv/mysql_host_data_source.h
@@ -153,6 +153,41 @@ public:
virtual ConstHostCollection
getAll6(const SubnetID& subnet_id) 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 const @c Host objects.
+ virtual ConstHostCollection
+ getAllbyHostname(const std::string& hostname) 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 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 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 Returns range of hosts in a DHCPv4 subnet.
///
/// This method returns a page of @c Host objects which represent
diff --git a/src/lib/dhcpsrv/pgsql_host_data_source.cc b/src/lib/dhcpsrv/pgsql_host_data_source.cc
index e3a005df0f..7ea6f61e6b 100644
--- a/src/lib/dhcpsrv/pgsql_host_data_source.cc
+++ b/src/lib/dhcpsrv/pgsql_host_data_source.cc
@@ -1290,6 +1290,9 @@ public:
GET_HOST_SUBID6_ADDR, // Gets host by IPv6 SubnetID and IPv6 prefix
GET_HOST_SUBID4, // Gets hosts by IPv4 SubnetID
GET_HOST_SUBID6, // Gets hosts by IPv6 SubnetID
+ GET_HOST_HOSTNAME, // Gets hosts by hostname
+ GET_HOST_HOSTNAME_SUBID4, // Gets hosts by hostname and IPv4 SubnetID
+ GET_HOST_HOSTNAME_SUBID6, // Gets hosts by hostname and IPv6 SubnetID
GET_HOST_SUBID4_PAGE, // Gets hosts by IPv4 SubnetID beginning by HID
GET_HOST_SUBID6_PAGE, // Gets hosts by IPv6 SubnetID beginning by HID
INSERT_HOST, // Insert new host to collection
@@ -1694,6 +1697,81 @@ TaggedStatementArray tagged_statements = { {
"ORDER BY h.host_id, o.option_id, r.reservation_id"
},
+ // PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME
+ // Retrieves host information, IPv6 reservations and both DHCPv4 and
+ // DHCPv6 options associated with all hosts using the hostname.
+ // The LEFT JOIN clause is used to retrieve information from 4 different
+ // tables using a single query. Hence, this query returns multiple rows
+ // for a single host.
+ {1,
+ { OID_VARCHAR },
+ "get_host_hostname",
+ "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
+ " h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, "
+ " h.hostname, h.dhcp4_client_classes, h.dhcp6_client_classes, "
+ " h.user_context, "
+ " h.dhcp4_next_server, h.dhcp4_server_hostname, "
+ " h.dhcp4_boot_file_name, h.auth_key, "
+ " o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
+ " o4.persistent, o4.user_context, "
+ " o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
+ " o6.persistent, o6.user_context, "
+ " r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
+ "FROM hosts AS h "
+ "LEFT JOIN dhcp4_options AS o4 ON h.host_id = o4.host_id "
+ "LEFT JOIN dhcp6_options AS o6 ON h.host_id = o6.host_id "
+ "LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id "
+ "WHERE lower(h.hostname) = $1 "
+ "ORDER BY h.host_id, o4.option_id, o6.option_id, r.reservation_id"
+ },
+
+ // PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4
+ // Retrieves host information for all hosts with a hostname in a subnet,
+ // along with the DHCPv4 options associated with it. Left joining
+ // the dhcp4_options table results in multiple rows being returned for
+ // the same host.
+ {2,
+ { OID_VARCHAR, OID_INT8 },
+ "get_host_hostname_subid4",
+ "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
+ " h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
+ " h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
+ " h.dhcp4_next_server, h.dhcp4_server_hostname, "
+ " h.dhcp4_boot_file_name, h.auth_key, "
+ " o.option_id, o.code, o.value, o.formatted_value, o.space, "
+ " o.persistent, o.user_context "
+ "FROM hosts AS h "
+ "LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
+ "WHERE lower(h.hostname) = $1 AND h.dhcp4_subnet_id = $2 "
+ "ORDER BY h.host_id, o.option_id"
+ },
+
+ // PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6
+ // Retrieves host information, IPv6 reservations and DHCPv6 options
+ // associated with all hosts using the hostname and the IPv6 subnet id.
+ // This query returns host information for many hosts. However, multiple
+ // rows are returned due to left joining IPv6 reservations and DHCPv6
+ // options. The number of rows returned is multiplication of number of
+ // existing IPv6 reservations and DHCPv6 options for each host in a subnet.
+ {2,
+ { OID_VARCHAR, OID_INT8 },
+ "get_host_hostname_subid6",
+ "SELECT h.host_id, h.dhcp_identifier, "
+ " h.dhcp_identifier_type, h.dhcp4_subnet_id, "
+ " h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
+ " h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
+ " h.dhcp4_next_server, h.dhcp4_server_hostname, "
+ " h.dhcp4_boot_file_name, h.auth_key, "
+ " o.option_id, o.code, o.value, o.formatted_value, o.space, "
+ " o.persistent, o.user_context, "
+ " r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
+ "FROM hosts AS h "
+ "LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
+ "LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id "
+ "WHERE lower(h.hostname) = $1 AND h.dhcp6_subnet_id = $2 "
+ "ORDER BY h.host_id, o.option_id, r.reservation_id"
+ },
+
// PgSqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE
// Retrieves host information along with the DHCPv4 options associated with
// it. Left joining the dhcp4_options table results in multiple rows being
@@ -1761,7 +1839,7 @@ TaggedStatementArray tagged_statements = { {
"RETURNING host_id"
},
- //PgSqlHostDataSourceImpl::INSERT_V6_RESRV
+ // PgSqlHostDataSourceImpl::INSERT_V6_RESRV
// Inserts a single IPv6 reservation into 'reservations' table.
{5,
{ OID_VARCHAR, OID_INT2, OID_INT4, OID_INT4, OID_INT4 },
@@ -2237,6 +2315,61 @@ PgSqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
}
ConstHostCollection
+PgSqlHostDataSource::getAllbyHostname(const std::string& hostname) const {
+ // Set up the WHERE clause value
+ PsqlBindArrayPtr bind_array(new PsqlBindArray());
+
+ // Add the hostname.
+ bind_array->add(hostname);
+
+ ConstHostCollection result;
+ impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME,
+ bind_array, impl_->host_ipv46_exchange_,
+ result, false);
+ return (result);
+}
+
+ConstHostCollection
+PgSqlHostDataSource::getAllbyHostname4(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ // Set up the WHERE clause value
+ PsqlBindArrayPtr bind_array(new PsqlBindArray());
+
+ // Add the hostname.
+ bind_array->add(hostname);
+
+ // Add the subnet id.
+ bind_array->add(subnet_id);
+
+ ConstHostCollection result;
+ impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4,
+ bind_array, impl_->host_exchange_,
+ result, false);
+
+ return (result);
+}
+
+ConstHostCollection
+PgSqlHostDataSource::getAllbyHostname6(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ // Set up the WHERE clause value
+ PsqlBindArrayPtr bind_array(new PsqlBindArray());
+
+ // Add the hostname.
+ bind_array->add(hostname);
+
+ // Add the subnet id.
+ bind_array->add(subnet_id);
+
+ ConstHostCollection result;
+ impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6,
+ bind_array, impl_->host_ipv6_exchange_,
+ result, false);
+
+ return (result);
+}
+
+ConstHostCollection
PgSqlHostDataSource::getPage4(const SubnetID& subnet_id,
size_t& /*source_index*/,
uint64_t lower_host_id,
diff --git a/src/lib/dhcpsrv/pgsql_host_data_source.h b/src/lib/dhcpsrv/pgsql_host_data_source.h
index f3b1f55205..29711e13a6 100644
--- a/src/lib/dhcpsrv/pgsql_host_data_source.h
+++ b/src/lib/dhcpsrv/pgsql_host_data_source.h
@@ -182,6 +182,41 @@ public:
virtual ConstHostCollection
getAll6(const SubnetID& subnet_id) 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 const @c Host objects.
+ virtual ConstHostCollection
+ getAllbyHostname(const std::string& hostname) 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 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 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 Returns range of hosts in a DHCPv4 subnet.
///
/// This method implements paged browsing of host databases. The
diff --git a/src/lib/dhcpsrv/tests/host_cache_unittest.cc b/src/lib/dhcpsrv/tests/host_cache_unittest.cc
index d24f249d06..8e1b196136 100644
--- a/src/lib/dhcpsrv/tests/host_cache_unittest.cc
+++ b/src/lib/dhcpsrv/tests/host_cache_unittest.cc
@@ -611,6 +611,20 @@ public:
return (getCollection());
}
+ ConstHostCollection getAllbyHostname(const std::string&) const {
+ return (getCollection());
+ }
+
+ ConstHostCollection getAllbyHostname4(const std::string&,
+ const SubnetID&) const {
+ return (getCollection());
+ }
+
+ ConstHostCollection getAllbyHostname6(const std::string&,
+ const SubnetID&) const {
+ return (getCollection());
+ }
+
ConstHostCollection getPage4(const SubnetID&, size_t&, uint64_t,
const HostPageSize&) const {
return (getCollection());
diff --git a/src/lib/dhcpsrv/tests/host_unittest.cc b/src/lib/dhcpsrv/tests/host_unittest.cc
index fb7cac2746..3c4c448e69 100644
--- a/src/lib/dhcpsrv/tests/host_unittest.cc
+++ b/src/lib/dhcpsrv/tests/host_unittest.cc
@@ -665,19 +665,20 @@ TEST_F(HostTest, setValues) {
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
SubnetID(1), SubnetID(2),
IOAddress("192.0.2.3"),
- "some-host.example.org")));
+ "some-host.eXAMple.org")));
ASSERT_EQ(1, host->getIPv4SubnetID());
ASSERT_EQ(2, host->getIPv6SubnetID());
ASSERT_EQ("192.0.2.3", host->getIPv4Reservation().toText());
- ASSERT_EQ("some-host.example.org", host->getHostname());
+ ASSERT_EQ("some-host.eXAMple.org", host->getHostname());
+ ASSERT_EQ("some-host.example.org", host->getLowerHostname());
ASSERT_FALSE(host->getContext());
ASSERT_FALSE(host->getNegative());
host->setIPv4SubnetID(SubnetID(123));
host->setIPv6SubnetID(SubnetID(234));
host->setIPv4Reservation(IOAddress("10.0.0.1"));
- host->setHostname("other-host.example.org");
+ host->setHostname("other-host.eXAMple.org");
host->setNextServer(IOAddress("192.0.2.2"));
host->setServerHostname("server-hostname.example.org");
host->setBootFileName("bootfile.efi");
@@ -690,7 +691,8 @@ TEST_F(HostTest, setValues) {
EXPECT_EQ(123, host->getIPv4SubnetID());
EXPECT_EQ(234, host->getIPv6SubnetID());
EXPECT_EQ("10.0.0.1", host->getIPv4Reservation().toText());
- EXPECT_EQ("other-host.example.org", host->getHostname());
+ EXPECT_EQ("other-host.eXAMple.org", host->getHostname());
+ ASSERT_EQ("other-host.example.org", host->getLowerHostname());
EXPECT_EQ("192.0.2.2", host->getNextServer().toText());
EXPECT_EQ("server-hostname.example.org", host->getServerHostname());
EXPECT_EQ("bootfile.efi", host->getBootFileName());
diff --git a/src/lib/dhcpsrv/testutils/memory_host_data_source.cc b/src/lib/dhcpsrv/testutils/memory_host_data_source.cc
index ba9a6bfd63..094889ccd8 100644
--- a/src/lib/dhcpsrv/testutils/memory_host_data_source.cc
+++ b/src/lib/dhcpsrv/testutils/memory_host_data_source.cc
@@ -47,6 +47,46 @@ MemHostDataSource::getAll6(const SubnetID& subnet_id) const {
}
ConstHostCollection
+MemHostDataSource::getAllbyHostname(const std::string& hostname) const {
+ ConstHostCollection hosts;
+ for (auto h = store_.begin(); h != store_.end(); ++h) {
+ // Keep it when hostname matchs.
+ if ((*h)->getLowerHostname() == hostname) {
+ hosts.push_back(*h);
+ }
+ }
+ return (hosts);
+}
+
+ConstHostCollection
+MemHostDataSource::getAllbyHostname4(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ ConstHostCollection hosts;
+ for (auto h = store_.begin(); h != store_.end(); ++h) {
+ // Keep it when hostname and subnet_id match.
+ if (((*h)->getLowerHostname() == hostname) &&
+ ((*h)->getIPv4SubnetID() == subnet_id)) {
+ hosts.push_back(*h);
+ }
+ }
+ return (hosts);
+}
+
+ConstHostCollection
+MemHostDataSource::getAllbyHostname6(const std::string& hostname,
+ const SubnetID& subnet_id) const {
+ ConstHostCollection hosts;
+ for (auto h = store_.begin(); h != store_.end(); ++h) {
+ // Keep it when hostname and subnet_id match.
+ if (((*h)->getLowerHostname() == hostname) &&
+ ((*h)->getIPv6SubnetID() == subnet_id)) {
+ hosts.push_back(*h);
+ }
+ }
+ return (hosts);
+}
+
+ConstHostCollection
MemHostDataSource::getPage4(const SubnetID& subnet_id,
size_t& /*source_index*/,
uint64_t lower_host_id,
diff --git a/src/lib/dhcpsrv/testutils/memory_host_data_source.h b/src/lib/dhcpsrv/testutils/memory_host_data_source.h
index a1577a41c0..993ab26cdf 100644
--- a/src/lib/dhcpsrv/testutils/memory_host_data_source.h
+++ b/src/lib/dhcpsrv/testutils/memory_host_data_source.h
@@ -58,6 +58,26 @@ public:
virtual ConstHostCollection
getAll6(const SubnetID& subnet_id) const;
+ /// @brief Return all hosts with a hostname.
+ ///
+ /// @param hostname The lower case hostname.
+ virtual ConstHostCollection
+ getAllbyHostname(const std::string& hostname) const;
+
+ /// @brief Return all hosts with a hostname in a DHCPv4 subnet.
+ ///
+ /// @param hostname The lower case hostname.
+ /// @param subnet_id Subnet identifier.
+ virtual ConstHostCollection
+ getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const;
+
+ /// @brief Return all hosts with a hostname in a DHCPv6 subnet.
+ ///
+ /// @param hostname The lower case hostname.
+ /// @param subnet_id Subnet identifier.
+ virtual ConstHostCollection
+ getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const;
+
/// @brief Return range of hosts in a DHCPv4 subnet.
///
/// @param subnet_id Subnet identifier.
diff --git a/src/lib/dhcpsrv/writable_host_data_source.h b/src/lib/dhcpsrv/writable_host_data_source.h
index 38a3842517..1f68b79a47 100644
--- a/src/lib/dhcpsrv/writable_host_data_source.h
+++ b/src/lib/dhcpsrv/writable_host_data_source.h
@@ -57,6 +57,41 @@ public:
virtual HostCollection
getAll6(const SubnetID& subnet_id) = 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 @c Host objects.
+ virtual HostCollection
+ getAllbyHostname(const std::string& hostname) = 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 @c Host objects.
+ virtual HostCollection
+ getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) = 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 @c Host objects.
+ virtual HostCollection
+ getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) = 0;
+
/// @brief Returns range of hosts in a DHCPv4 subnet.
///
/// This method implements paged browsing of host databases. The