]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[392-search-of-reservations-by-hostname] Checkpont: add new methods - tests to write
authorFrancis Dupont <fdupont@isc.org>
Sun, 29 Sep 2019 07:28:13 +0000 (09:28 +0200)
committerFrancis Dupont <fdupont@isc.org>
Tue, 15 Oct 2019 09:45:32 +0000 (11:45 +0200)
21 files changed:
src/lib/dhcpsrv/base_host_data_source.h
src/lib/dhcpsrv/cfg_hosts.cc
src/lib/dhcpsrv/cfg_hosts.h
src/lib/dhcpsrv/cql_host_data_source.cc
src/lib/dhcpsrv/cql_host_data_source.h
src/lib/dhcpsrv/host.h
src/lib/dhcpsrv/host_container.h
src/lib/dhcpsrv/host_mgr.cc
src/lib/dhcpsrv/host_mgr.h
src/lib/dhcpsrv/hosts_messages.cc
src/lib/dhcpsrv/hosts_messages.h
src/lib/dhcpsrv/hosts_messages.mes
src/lib/dhcpsrv/mysql_host_data_source.cc
src/lib/dhcpsrv/mysql_host_data_source.h
src/lib/dhcpsrv/pgsql_host_data_source.cc
src/lib/dhcpsrv/pgsql_host_data_source.h
src/lib/dhcpsrv/tests/host_cache_unittest.cc
src/lib/dhcpsrv/tests/host_unittest.cc
src/lib/dhcpsrv/testutils/memory_host_data_source.cc
src/lib/dhcpsrv/testutils/memory_host_data_source.h
src/lib/dhcpsrv/writable_host_data_source.h

index dae3977be22469dc8c14ee4470c5a25eef2840dd..cb594811407f5afd08164370300fe3a59da7c5fd 100644 (file)
@@ -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
index 81051cb4e6f050d355a0a1d020856de154e61dc6..f93467665c269bc24f7e68de0b774b6af040aba5 100644 (file)
@@ -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,
index 2f0fb862c8218c537293202d21b2298d467f9159..54edd268e2374d4616341f8bddae25927cbd58e0 100644 (file)
@@ -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
index 34f6d3e2725c655bc82ce32215e62ccbb08acea6..085c9da46cbb0b3383bbad7add1a8fb3b0ed5fba 100644 (file)
@@ -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);
+
+    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*/,
index cac22825f5829d2877bc0811935091c30db04f57..c90e3b1f559698a07fa3913a4ed9d37065a01b36 100644 (file)
@@ -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.
index 8c81ca8a5c1abe7e3b6b68a48fb5a162592dc00f..ad60da7c4784683c3766354de78676c04cf53018 100644 (file)
@@ -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.
index ae21449c4e536963f96c80157eeec96bc2701b4a..55692cf25d3714840d214de6da2a70c5f8d4dc96 100644 (file)
@@ -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).
index 6903d9ce843c42c154cc283ec109e9dc4640c654..ebcab3bdc39aa8a523466748384924acb6a5a9b3 100644 (file)
@@ -135,6 +135,42 @@ HostMgr::getAll6(const SubnetID& subnet_id) const {
     return (hosts);
 }
 
+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,
index caedff49b6eaa2ab69acd5e6301fbc78938fab1d..357b156328ff046283859677c7f05adb518c8063 100644 (file)
@@ -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
index c210ee2c54e92c93bec33445efa7f57ac5e49cbc..7fa76c690764ba6247be5dbcb6cca74249403024 100644 (file)
@@ -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",
index 6a13da5754ad28cf41c6047db7a7030be4e2c5af..5d636c3f73dbafe473773eb48e149e4af2f4ced6 100644 (file)
@@ -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;
index d6dc7542aae375ae535ada4a05d39095987fe477..a44d6ea725bc919b89a68eb47510cac7874ad0d9 100644 (file)
@@ -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
index 4eddbdc68dd82ecffa024eed9da150407d3c2f0d..3c0c2d7c386a6088b0f44e562c9aff820bb9bcb2 100644 (file)
@@ -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
@@ -2972,6 +3042,86 @@ MySqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
     return (result);
 }
 
+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*/,
index 6f1e3b5c67a720ce42cdfa915f31fd208531ea11..759f3304fa8f0928ff032dc60c180e889d6bdb8c 100644 (file)
@@ -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
index e3a005df0fb03d48fa1421719482fb020daafb67..7ea6f61e6b8e0308e7d25515cb4c8daaeca351df 100644 (file)
@@ -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 },
@@ -2236,6 +2314,61 @@ PgSqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
     return (result);
 }
 
+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*/,
index f3b1f55205fd3bbeb82cbd6cc72e6b7e0a5e39cd..29711e13a62b0c25c7c6fa31b140c4b554811684 100644 (file)
@@ -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
index d24f249d06c3bd9659f2994737c30ed13b54f0f5..8e1b196136ba9dd05b8c04c8e666678eb4af8324 100644 (file)
@@ -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());
index fb7cac274600c4eab846a25cbe1e7314fc1d53dd..3c4c448e69310432f659c21866923887c66aba7b 100644 (file)
@@ -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());
index ba9a6bfd63face13ca83f0e8bd263cca63df23e7..094889ccd8f4687f298a02196ef0df5ed19e7004 100644 (file)
@@ -46,6 +46,46 @@ MemHostDataSource::getAll6(const SubnetID& subnet_id) const {
     return (hosts);
 }
 
+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*/,
index a1577a41c0ea2914a3b5d1546af3002710fe67f4..993ab26cdf3b926826d4d7547a39189d694ed6a8 100644 (file)
@@ -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.
index 38a3842517bf25d3dc3ab73b050d2f57bcc96f72..1f68b79a47521e30af01902b621e442153581743 100644 (file)
@@ -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