You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by to...@apache.org on 2017/08/21 21:32:31 UTC

kudu git commit: KUDU-2032 (part 1): pass pre-resolution hostname into RPC proxies

Repository: kudu
Updated Branches:
  refs/heads/master 1d5606645 -> efb5395bd


KUDU-2032 (part 1): pass pre-resolution hostname into RPC proxies

This modifies the constructor of RPC proxies (generated and otherwise)
to take the remote hostname in addition to the existing resolved
Sockaddr parameter. The hostname is then passed into the ConnectionId
object, and plumbed through to the SASL client in place of the IP
address that was used previously.

The patch changes all of the construction sites of Proxy to fit the new
interface. In most of the test cases, we don't have real hostnames, so
we just use the dotted-decimal string form of the remote Sockaddr, which
matches the existing behavior.

In the real call sites, we have actual host names typically specified by
the user, and in those cases we'll need to pass those into the proxy. In
a few cases, they were conveniently available in the same function that
creates the proxy. In others, they are relatively far away, so this
patch just uses the dotted-decimal string and leaves TODOs.

In the case that Kerberos is not configured, this change should have no
effect since the hostname is ignored by SASL "plain". In the case that
Kerberos is configured with 'rdns=true', they also have no effect,
because the krb5 library will resolve and reverse the hostname from the
IP as it did before. In the case that 'rdns=false', this moves us one
step closer to fixing KUDU-2032 by getting a hostname into the SASL
library.

I verified that, if I set 'rdns = false' on a Kerberized client, I'm now
able to run  'kudu master status <host>' successfully where it would not
before. This tool uses a direct proxy instantiation where the hostname
was easy to plumb in. 'kudu table list <host>' still does not work because
it uses the client, which wasn't convenient to plumb quite yet.

Given that this makes incremental improvement towards fixing the issue
without any regression, and is already a fairly wide patch, I hope to
commit this and then address the remaining plumbing in a separate patch.

Change-Id: I96fb3c73382f0be6e30e29ae2e7176be42f3bb98
Reviewed-on: http://gerrit.cloudera.org:8080/7687
Tested-by: Kudu Jenkins
Reviewed-by: Alexey Serbin <as...@cloudera.com>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/efb5395b
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/efb5395b
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/efb5395b

Branch: refs/heads/master
Commit: efb5395bdf8b89077b403c8a01528e63b346c49a
Parents: 1d56066
Author: Todd Lipcon <to...@apache.org>
Authored: Tue Aug 15 18:20:48 2017 -0700
Committer: Todd Lipcon <to...@apache.org>
Committed: Mon Aug 21 21:26:55 2017 +0000

----------------------------------------------------------------------
 src/kudu/client/client-internal.cc              |  3 +-
 src/kudu/client/master_rpc.cc                   |  3 +-
 src/kudu/client/meta_cache.cc                   |  2 +-
 src/kudu/consensus/consensus_peers.cc           |  2 +-
 .../create-table-stress-test.cc                 |  4 +-
 .../exactly_once_writes-itest.cc                |  4 +-
 .../integration-tests/external_mini_cluster.cc  | 21 +++---
 .../integration-tests/internal_mini_cluster.cc  |  4 +-
 .../integration-tests/master-stress-test.cc     |  4 +-
 .../master_cert_authority-itest.cc              |  4 +-
 .../master_replication-itest.cc                 |  4 +-
 src/kudu/integration-tests/security-itest.cc    |  8 +--
 .../integration-tests/table_locations-itest.cc  |  4 +-
 .../ts_tablet_manager-itest.cc                  |  3 +-
 src/kudu/master/master-test.cc                  |  3 +-
 src/kudu/master/master.cc                       |  2 +-
 src/kudu/master/sys_catalog-test.cc             |  4 +-
 src/kudu/master/ts_descriptor.cc                | 17 +++--
 src/kudu/master/ts_descriptor.h                 |  4 +-
 src/kudu/rpc/connection.h                       | 15 ++--
 src/kudu/rpc/connection_id.cc                   | 25 +++++--
 src/kudu/rpc/connection_id.h                    | 10 ++-
 src/kudu/rpc/exactly_once_rpc-test.cc           |  3 +-
 src/kudu/rpc/mt-rpc-test.cc                     |  6 +-
 src/kudu/rpc/negotiation.cc                     |  9 +--
 src/kudu/rpc/protoc-gen-krpc.cc                 | 11 +--
 src/kudu/rpc/proxy.cc                           |  6 +-
 src/kudu/rpc/proxy.h                            |  5 +-
 src/kudu/rpc/reactor.cc                         |  5 +-
 src/kudu/rpc/rpc-bench.cc                       |  4 +-
 src/kudu/rpc/rpc-test.cc                        | 73 +++++++++++++-------
 src/kudu/rpc/rpc_stub-test.cc                   | 47 +++++++------
 src/kudu/tools/ksck_remote.cc                   |  8 ++-
 src/kudu/tools/tool_action_common.cc            |  2 +-
 src/kudu/tserver/heartbeater.cc                 |  2 +-
 src/kudu/tserver/tablet_copy_client.cc          |  2 +-
 src/kudu/tserver/tablet_copy_service-test.cc    |  4 +-
 src/kudu/tserver/tablet_server-test.cc          |  3 +-
 src/kudu/tserver/tablet_server_test_util.cc     | 11 +--
 src/kudu/util/net/net_util-test.cc              |  1 +
 src/kudu/util/net/sockaddr.cc                   |  4 +-
 src/kudu/util/net/sockaddr.h                    |  3 +
 42 files changed, 220 insertions(+), 139 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/client/client-internal.cc
----------------------------------------------------------------------
diff --git a/src/kudu/client/client-internal.cc b/src/kudu/client/client-internal.cc
index 5e84eca..ef98aaf 100644
--- a/src/kudu/client/client-internal.cc
+++ b/src/kudu/client/client-internal.cc
@@ -681,7 +681,8 @@ void KuduClient::Data::ConnectedToClusterCb(
 
     if (status.ok()) {
       leader_master_hostport_ = HostPort(leader_addr);
-      master_proxy_.reset(new MasterServiceProxy(messenger_, leader_addr));
+      // TODO(KUDU-2032): retain the original hostname passed by caller.
+      master_proxy_.reset(new MasterServiceProxy(messenger_, leader_addr, leader_addr.host()));
     }
   }
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/client/master_rpc.cc
----------------------------------------------------------------------
diff --git a/src/kudu/client/master_rpc.cc b/src/kudu/client/master_rpc.cc
index be597ae..cb2fc2c 100644
--- a/src/kudu/client/master_rpc.cc
+++ b/src/kudu/client/master_rpc.cc
@@ -121,7 +121,8 @@ ConnectToMasterRpc::~ConnectToMasterRpc() {
 }
 
 void ConnectToMasterRpc::SendRpc() {
-  MasterServiceProxy proxy(retrier().messenger(), addr_);
+  // TODO(KUDU-2032): retain the hostname for addr_
+  MasterServiceProxy proxy(retrier().messenger(), addr_, addr_.host());
   rpc::RpcController* controller = mutable_retrier()->mutable_controller();
   // TODO(todd): should this be setting an RPC call deadline based on 'deadline'?
   // it doesn't seem to be.

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/client/meta_cache.cc
----------------------------------------------------------------------
diff --git a/src/kudu/client/meta_cache.cc b/src/kudu/client/meta_cache.cc
index c77b335..1c9dd60 100644
--- a/src/kudu/client/meta_cache.cc
+++ b/src/kudu/client/meta_cache.cc
@@ -122,7 +122,7 @@ void RemoteTabletServer::DnsResolutionFinished(const HostPort& hp,
 
   {
     std::lock_guard<simple_spinlock> l(lock_);
-    proxy_.reset(new TabletServerServiceProxy(client->data_->messenger_, (*addrs)[0]));
+    proxy_.reset(new TabletServerServiceProxy(client->data_->messenger_, (*addrs)[0], hp.host()));
   }
   user_callback.Run(s);
 }

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/consensus/consensus_peers.cc
----------------------------------------------------------------------
diff --git a/src/kudu/consensus/consensus_peers.cc b/src/kudu/consensus/consensus_peers.cc
index 7e3b247..788b37d 100644
--- a/src/kudu/consensus/consensus_peers.cc
+++ b/src/kudu/consensus/consensus_peers.cc
@@ -527,7 +527,7 @@ Status CreateConsensusServiceProxyForHost(const shared_ptr<Messenger>& messenger
     << "resolves to " << addrs.size() << " different addresses. Using "
     << addrs[0].ToString();
   }
-  new_proxy->reset(new ConsensusServiceProxy(messenger, addrs[0]));
+  new_proxy->reset(new ConsensusServiceProxy(messenger, addrs[0], hostport.host()));
   return Status::OK();
 }
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/create-table-stress-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/create-table-stress-test.cc b/src/kudu/integration-tests/create-table-stress-test.cc
index 149d8f6..04c1199 100644
--- a/src/kudu/integration-tests/create-table-stress-test.cc
+++ b/src/kudu/integration-tests/create-table-stress-test.cc
@@ -120,8 +120,8 @@ class CreateTableStressTest : public KuduTest {
               .set_num_reactors(1)
               .set_max_negotiation_threads(1)
               .Build(&messenger_));
-    master_proxy_.reset(new MasterServiceProxy(messenger_,
-                                               cluster_->mini_master()->bound_rpc_addr()));
+    const auto& addr = cluster_->mini_master()->bound_rpc_addr();
+    master_proxy_.reset(new MasterServiceProxy(messenger_, addr, addr.host()));
     ASSERT_OK(CreateTabletServerMap(master_proxy_, messenger_, &ts_map_));
   }
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/exactly_once_writes-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/exactly_once_writes-itest.cc b/src/kudu/integration-tests/exactly_once_writes-itest.cc
index 3f120a0..8a57675 100644
--- a/src/kudu/integration-tests/exactly_once_writes-itest.cc
+++ b/src/kudu/integration-tests/exactly_once_writes-itest.cc
@@ -113,8 +113,8 @@ void ExactlyOnceSemanticsITest::WriteRowsAndCollectResponses(int thread_idx,
   rpc::MessengerBuilder bld("Client");
   ASSERT_OK(bld.Build(&client_messenger));
 
-  std::unique_ptr<TabletServerServiceProxy> proxy(new TabletServerServiceProxy(client_messenger,
-                                                                               address));
+  std::unique_ptr<TabletServerServiceProxy> proxy(new TabletServerServiceProxy(
+      client_messenger, address, address.host()));
   for (int i = 0; i < num_batches; i++) {
     // Wait for all of the other writer threads to finish their attempts of the prior
     // batch before continuing on to the next one. This has two important effects:

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/external_mini_cluster.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/external_mini_cluster.cc b/src/kudu/integration-tests/external_mini_cluster.cc
index 6091ffd..fd1b8cc 100644
--- a/src/kudu/integration-tests/external_mini_cluster.cc
+++ b/src/kudu/integration-tests/external_mini_cluster.cc
@@ -487,7 +487,7 @@ void ExternalMiniCluster::AssertNoCrashes() {
 Status ExternalMiniCluster::WaitForTabletsRunning(ExternalTabletServer* ts,
                                                   int min_tablet_count,
                                                   const MonoDelta& timeout) {
-  TabletServerServiceProxy proxy(messenger_, ts->bound_rpc_addr());
+  TabletServerServiceProxy proxy(messenger_, ts->bound_rpc_addr(), ts->bound_rpc_addr().host());
   ListTabletsRequestPB req;
   ListTabletsResponsePB resp;
 
@@ -612,8 +612,8 @@ std::shared_ptr<MasterServiceProxy> ExternalMiniCluster::master_proxy() const {
 
 std::shared_ptr<MasterServiceProxy> ExternalMiniCluster::master_proxy(int idx) const {
   CHECK_LT(idx, masters_.size());
-  return std::make_shared<MasterServiceProxy>(
-      messenger_, CHECK_NOTNULL(master(idx))->bound_rpc_addr());
+  const auto& addr = CHECK_NOTNULL(master(idx))->bound_rpc_addr();
+  return std::make_shared<MasterServiceProxy>(messenger_, addr, addr.host());
 }
 
 Status ExternalMiniCluster::CreateClient(client::KuduClientBuilder* builder,
@@ -634,7 +634,8 @@ Status ExternalMiniCluster::CreateClient(client::KuduClientBuilder* builder,
 Status ExternalMiniCluster::SetFlag(ExternalDaemon* daemon,
                                     const string& flag,
                                     const string& value) {
-  server::GenericServiceProxy proxy(messenger_, daemon->bound_rpc_addr());
+  const auto& addr = daemon->bound_rpc_addr();
+  server::GenericServiceProxy proxy(messenger_, addr, addr.host());
 
   rpc::RpcController controller;
   controller.set_timeout(MonoDelta::FromSeconds(30));
@@ -973,10 +974,11 @@ Status ExternalDaemon::DeleteFromDisk() const {
 
 void ExternalDaemon::FlushCoverage() {
 #ifndef COVERAGE_BUILD
-  return;
+  return; // NOLINT(*)
 #else
   LOG(INFO) << "Attempting to flush coverage for " << exe_ << " pid " << process_->pid();
-  server::GenericServiceProxy proxy(messenger_, bound_rpc_addr());
+  server::GenericServiceProxy proxy(
+      messenger_, bound_rpc_addr(), bound_rpc_addr().host());
 
   server::FlushCoverageRequestPB req;
   server::FlushCoverageResponsePB resp;
@@ -995,7 +997,8 @@ void ExternalDaemon::CheckForLeaks() {
 #if defined(__has_feature)
 #  if __has_feature(address_sanitizer)
   LOG(INFO) << "Attempting to check leaks for " << exe_ << " pid " << process_->pid();
-  server::GenericServiceProxy proxy(messenger_, bound_rpc_addr());
+  server::GenericServiceProxy proxy(messenger_, bound_rpc_addr(), bound_rpc_addr().host());
+
   server::CheckLeaksRequestPB req;
   server::CheckLeaksResponsePB resp;
   rpc::RpcController rpc;
@@ -1162,8 +1165,8 @@ Status ExternalMaster::Restart() {
 }
 
 Status ExternalMaster::WaitForCatalogManager() {
-  unique_ptr<MasterServiceProxy> proxy(
-      new MasterServiceProxy(messenger_, bound_rpc_addr()));
+  unique_ptr<MasterServiceProxy> proxy(new MasterServiceProxy(
+      messenger_, bound_rpc_addr(), bound_rpc_addr().host()));
   Stopwatch sw;
   sw.start();
   while (sw.elapsed().wall_seconds() < kMasterCatalogManagerTimeoutSeconds) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/internal_mini_cluster.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/internal_mini_cluster.cc b/src/kudu/integration-tests/internal_mini_cluster.cc
index 41ae76e..5fbc9c3 100644
--- a/src/kudu/integration-tests/internal_mini_cluster.cc
+++ b/src/kudu/integration-tests/internal_mini_cluster.cc
@@ -368,8 +368,8 @@ std::shared_ptr<MasterServiceProxy> InternalMiniCluster::master_proxy() const {
 }
 
 std::shared_ptr<MasterServiceProxy> InternalMiniCluster::master_proxy(int idx) const {
-  return std::make_shared<MasterServiceProxy>(
-      messenger_, CHECK_NOTNULL(mini_master(idx))->bound_rpc_addr());
+  const auto& addr = CHECK_NOTNULL(mini_master(idx))->bound_rpc_addr();
+  return std::make_shared<MasterServiceProxy>(messenger_, addr, addr.host());
 }
 
 } // namespace kudu

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/master-stress-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/master-stress-test.cc b/src/kudu/integration-tests/master-stress-test.cc
index 788a376..3a8e3d9 100644
--- a/src/kudu/integration-tests/master-stress-test.cc
+++ b/src/kudu/integration-tests/master-stress-test.cc
@@ -255,8 +255,8 @@ class MasterStressTest : public KuduTest {
 
   Status WaitForMasterUpAndRunning(const shared_ptr<Messenger>& messenger,
                                    ExternalMaster* master) {
-    unique_ptr<MasterServiceProxy> proxy(
-        new MasterServiceProxy(messenger, master->bound_rpc_addr()));
+    const auto& addr = master->bound_rpc_addr();
+    unique_ptr<MasterServiceProxy> proxy(new MasterServiceProxy(messenger, addr, addr.host()));
     while (true) {
       ListTablesRequestPB req;
       ListTablesResponsePB resp;

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/master_cert_authority-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/master_cert_authority-itest.cc b/src/kudu/integration-tests/master_cert_authority-itest.cc
index 24c6be2..0e55b49 100644
--- a/src/kudu/integration-tests/master_cert_authority-itest.cc
+++ b/src/kudu/integration-tests/master_cert_authority-itest.cc
@@ -126,7 +126,7 @@ class MasterCertAuthorityTest : public KuduTest {
       if (!m->is_started()) {
         continue;
       }
-      MasterServiceProxy proxy(messenger_, m->bound_rpc_addr());
+      MasterServiceProxy proxy(messenger_, m->bound_rpc_addr(), m->bound_rpc_addr().host());
 
       // All masters (including followers) should accept the heartbeat.
       ASSERT_OK(proxy.TSHeartbeat(req, &resp, &rpc));
@@ -156,7 +156,7 @@ class MasterCertAuthorityTest : public KuduTest {
       if (!m->is_started()) {
         continue;
       }
-      MasterServiceProxy proxy(messenger_, m->bound_rpc_addr());
+      MasterServiceProxy proxy(messenger_, m->bound_rpc_addr(), m->bound_rpc_addr().host());
 
       // All masters (including followers) should accept the heartbeat.
       RETURN_NOT_OK(proxy.TSHeartbeat(req, &resp, &rpc));

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/master_replication-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/master_replication-itest.cc b/src/kudu/integration-tests/master_replication-itest.cc
index b9f61a8..b7bdde2 100644
--- a/src/kudu/integration-tests/master_replication-itest.cc
+++ b/src/kudu/integration-tests/master_replication-itest.cc
@@ -257,8 +257,8 @@ TEST_F(MasterReplicationTest, TestHeartbeatAcceptedByAnyMaster) {
     req.mutable_common()->CopyFrom(common);
     req.mutable_registration()->CopyFrom(fake_reg);
 
-    MasterServiceProxy proxy(messenger,
-                             cluster_->mini_master(i)->bound_rpc_addr());
+    const auto& addr = cluster_->mini_master(i)->bound_rpc_addr();
+    MasterServiceProxy proxy(messenger, addr, addr.host());
 
     // All masters (including followers) should accept the heartbeat.
     ASSERT_OK(proxy.TSHeartbeat(req, &resp, &rpc));

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/security-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/security-itest.cc b/src/kudu/integration-tests/security-itest.cc
index d8d5cc0..dcca26c 100644
--- a/src/kudu/integration-tests/security-itest.cc
+++ b/src/kudu/integration-tests/security-itest.cc
@@ -89,8 +89,8 @@ class SecurityITest : public KuduTest {
     // Make a new messenger so that we don't reuse any cached connections from
     // the minicluster startup sequence.
     auto messenger = NewMessengerOrDie();
-    server::GenericServiceProxy proxy(
-        messenger, cluster_->tablet_server(0)->bound_rpc_addr());
+    const auto& addr = cluster_->tablet_server(0)->bound_rpc_addr();
+    server::GenericServiceProxy proxy(messenger, addr, addr.host());
 
     rpc::RpcController controller;
     controller.set_timeout(MonoDelta::FromSeconds(30));
@@ -108,8 +108,8 @@ class SecurityITest : public KuduTest {
     // Make a new messenger so that we don't reuse any cached connections from
     // the minicluster startup sequence.
     auto messenger = NewMessengerOrDie();
-    master::MasterServiceProxy proxy(
-        messenger, cluster_->master(0)->bound_rpc_addr());
+    const auto& addr = cluster_->master(0)->bound_rpc_addr();
+    master::MasterServiceProxy proxy(messenger, addr, addr.host());
 
     rpc::RpcController rpc;
     master::TSHeartbeatRequestPB req;

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/table_locations-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/table_locations-itest.cc b/src/kudu/integration-tests/table_locations-itest.cc
index 9c04b6e..f956318 100644
--- a/src/kudu/integration-tests/table_locations-itest.cc
+++ b/src/kudu/integration-tests/table_locations-itest.cc
@@ -73,8 +73,8 @@ class TableLocationsTest : public KuduTest {
     // Create a client proxy to the master.
     MessengerBuilder bld("Client");
     ASSERT_OK(bld.Build(&client_messenger_));
-    proxy_.reset(new MasterServiceProxy(client_messenger_,
-                                        cluster_->mini_master()->bound_rpc_addr()));
+    const auto& addr = cluster_->mini_master()->bound_rpc_addr();
+    proxy_.reset(new MasterServiceProxy(client_messenger_, addr, addr.host()));
   }
 
   void TearDown() override {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/integration-tests/ts_tablet_manager-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/ts_tablet_manager-itest.cc b/src/kudu/integration-tests/ts_tablet_manager-itest.cc
index 5832c15..5d8354d 100644
--- a/src/kudu/integration-tests/ts_tablet_manager-itest.cc
+++ b/src/kudu/integration-tests/ts_tablet_manager-itest.cc
@@ -141,8 +141,9 @@ TEST_F(TsTabletManagerITest, TestReportNewLeaderOnLeaderChange) {
   ASSERT_OK(client_->OpenTable(kTableName, &table));
 
   // Build a TServerDetails map so we can check for convergence.
+  const auto& addr = cluster_->mini_master()->bound_rpc_addr();
   shared_ptr<MasterServiceProxy> master_proxy(
-      new MasterServiceProxy(client_messenger_, cluster_->mini_master()->bound_rpc_addr()));
+      new MasterServiceProxy(client_messenger_, addr, addr.host()));
 
   itest::TabletServerMap ts_map;
   ASSERT_OK(CreateTabletServerMap(master_proxy, client_messenger_, &ts_map));

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/master/master-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/master-test.cc b/src/kudu/master/master-test.cc
index bff0544..81fd195 100644
--- a/src/kudu/master/master-test.cc
+++ b/src/kudu/master/master-test.cc
@@ -113,7 +113,8 @@ class MasterTest : public KuduTest {
     // Create a client proxy to it.
     MessengerBuilder bld("Client");
     ASSERT_OK(bld.Build(&client_messenger_));
-    proxy_.reset(new MasterServiceProxy(client_messenger_, mini_master_->bound_rpc_addr()));
+    proxy_.reset(new MasterServiceProxy(client_messenger_, mini_master_->bound_rpc_addr(),
+                                        mini_master_->bound_rpc_addr().host()));
   }
 
   virtual void TearDown() OVERRIDE {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/master/master.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/master.cc b/src/kudu/master/master.cc
index d249959..1a06973 100644
--- a/src/kudu/master/master.cc
+++ b/src/kudu/master/master.cc
@@ -276,7 +276,7 @@ Status GetMasterEntryForHost(const shared_ptr<rpc::Messenger>& messenger,
                              ServerEntryPB* e) {
   Sockaddr sockaddr;
   RETURN_NOT_OK(SockaddrFromHostPort(hostport, &sockaddr));
-  MasterServiceProxy proxy(messenger, sockaddr);
+  MasterServiceProxy proxy(messenger, sockaddr, hostport.host());
   GetMasterRegistrationRequestPB req;
   GetMasterRegistrationResponsePB resp;
   rpc::RpcController controller;

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/master/sys_catalog-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/sys_catalog-test.cc b/src/kudu/master/sys_catalog-test.cc
index 340fcb1..e969b25 100644
--- a/src/kudu/master/sys_catalog-test.cc
+++ b/src/kudu/master/sys_catalog-test.cc
@@ -76,7 +76,9 @@ class SysCatalogTest : public KuduTest {
     // Create a client proxy to it.
     MessengerBuilder bld("Client");
     ASSERT_OK(bld.Build(&client_messenger_));
-    proxy_.reset(new MasterServiceProxy(client_messenger_, mini_master_->bound_rpc_addr()));
+    proxy_.reset(new MasterServiceProxy(
+        client_messenger_, mini_master_->bound_rpc_addr(),
+        mini_master_->bound_rpc_addr().host()));
   }
 
   virtual void TearDown() OVERRIDE {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/master/ts_descriptor.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/ts_descriptor.cc b/src/kudu/master/ts_descriptor.cc
index e119c7b..01193d3 100644
--- a/src/kudu/master/ts_descriptor.cc
+++ b/src/kudu/master/ts_descriptor.cc
@@ -202,7 +202,7 @@ void TSDescriptor::GetNodeInstancePB(NodeInstancePB* instance_pb) const {
   instance_pb->set_instance_seqno(latest_seqno_);
 }
 
-Status TSDescriptor::ResolveSockaddr(Sockaddr* addr) const {
+Status TSDescriptor::ResolveSockaddr(Sockaddr* addr, string* host) const {
   vector<HostPort> hostports;
   {
     std::lock_guard<simple_spinlock> l(lock_);
@@ -222,7 +222,7 @@ Status TSDescriptor::ResolveSockaddr(Sockaddr* addr) const {
     }
   }
 
-  if (addrs.size() == 0) {
+  if (addrs.empty()) {
     return Status::NetworkError("Unable to find the TS address: ",
                                 SecureDebugString(*registration_));
   }
@@ -233,6 +233,7 @@ Status TSDescriptor::ResolveSockaddr(Sockaddr* addr) const {
                   << addrs[0].ToString();
   }
   *addr = addrs[0];
+  *host = last_hostport.host();
   return Status::OK();
 }
 
@@ -247,11 +248,13 @@ Status TSDescriptor::GetTSAdminProxy(const shared_ptr<rpc::Messenger>& messenger
   }
 
   Sockaddr addr;
-  RETURN_NOT_OK(ResolveSockaddr(&addr));
+  string host;
+  RETURN_NOT_OK(ResolveSockaddr(&addr, &host));
 
   std::lock_guard<simple_spinlock> l(lock_);
   if (!ts_admin_proxy_) {
-    ts_admin_proxy_.reset(new tserver::TabletServerAdminServiceProxy(messenger, addr));
+    ts_admin_proxy_.reset(new tserver::TabletServerAdminServiceProxy(
+        messenger, addr, std::move(host)));
   }
   *proxy = ts_admin_proxy_;
   return Status::OK();
@@ -268,11 +271,13 @@ Status TSDescriptor::GetConsensusProxy(const shared_ptr<rpc::Messenger>& messeng
   }
 
   Sockaddr addr;
-  RETURN_NOT_OK(ResolveSockaddr(&addr));
+  string host;
+  RETURN_NOT_OK(ResolveSockaddr(&addr, &host));
 
   std::lock_guard<simple_spinlock> l(lock_);
   if (!consensus_proxy_) {
-    consensus_proxy_.reset(new consensus::ConsensusServiceProxy(messenger, addr));
+    consensus_proxy_.reset(new consensus::ConsensusServiceProxy(
+        messenger, addr, std::move(host)));
   }
   *proxy = consensus_proxy_;
   return Status::OK();

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/master/ts_descriptor.h
----------------------------------------------------------------------
diff --git a/src/kudu/master/ts_descriptor.h b/src/kudu/master/ts_descriptor.h
index 0d7c073..55cb275 100644
--- a/src/kudu/master/ts_descriptor.h
+++ b/src/kudu/master/ts_descriptor.h
@@ -129,7 +129,9 @@ class TSDescriptor {
   explicit TSDescriptor(std::string perm_id);
 
   // Uses DNS to resolve registered hosts to a single Sockaddr.
-  Status ResolveSockaddr(Sockaddr* addr) const;
+  // Returns the resolved address as well as the hostname associated with it
+  // in 'addr' and 'host'.
+  Status ResolveSockaddr(Sockaddr* addr, std::string* host) const;
 
   void DecayRecentReplicaCreationsUnlocked();
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/connection.h
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/connection.h b/src/kudu/rpc/connection.h
index 9413b4b..4d00316 100644
--- a/src/kudu/rpc/connection.h
+++ b/src/kudu/rpc/connection.h
@@ -136,15 +136,17 @@ class Connection : public RefCountedThreadSafe<Connection> {
   const Sockaddr &remote() const { return remote_; }
 
   // Set the user credentials for an outbound connection.
-  void set_local_user_credentials(UserCredentials creds) {
+  void set_outbound_connection_id(ConnectionId conn_id) {
     DCHECK_EQ(direction_, CLIENT);
-    local_user_credentials_ = std::move(creds);
+    DCHECK(!outbound_connection_id_);
+    outbound_connection_id_ = std::move(conn_id);
   }
 
   // Get the user credentials which will be used to log in.
-  const UserCredentials& local_user_credentials() const {
+  const ConnectionId& outbound_connection_id() const {
     DCHECK_EQ(direction_, CLIENT);
-    return local_user_credentials_;
+    DCHECK(outbound_connection_id_);
+    return *outbound_connection_id_;
   }
 
   // Credentials policy to start connection negotiation.
@@ -338,8 +340,9 @@ class Connection : public RefCountedThreadSafe<Connection> {
   // The socket we're communicating on.
   std::unique_ptr<Socket> socket_;
 
-  // The credentials of the user operating on this connection (if a client user).
-  UserCredentials local_user_credentials_;
+  // The ConnectionId that serves as a key into the client connection map
+  // within this reactor. Only set in the case of outbound connections.
+  boost::optional<ConnectionId> outbound_connection_id_;
 
   // The authenticated remote user (if this is an inbound connection on the server).
   RemoteUser remote_user_;

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/connection_id.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/connection_id.cc b/src/kudu/rpc/connection_id.cc
index 1d3076d..ffd2b6b 100644
--- a/src/kudu/rpc/connection_id.cc
+++ b/src/kudu/rpc/connection_id.cc
@@ -31,9 +31,13 @@ namespace rpc {
 
 ConnectionId::ConnectionId() {}
 
-ConnectionId::ConnectionId(const Sockaddr& remote, UserCredentials user_credentials) {
-  remote_ = remote;
-  user_credentials_ = std::move(user_credentials);
+ConnectionId::ConnectionId(const Sockaddr& remote,
+                           std::string hostname,
+                           UserCredentials user_credentials)
+    : remote_(remote),
+      hostname_(std::move(hostname)),
+      user_credentials_(std::move(user_credentials)) {
+  CHECK(!hostname_.empty());
 }
 
 void ConnectionId::set_user_credentials(UserCredentials user_credentials) {
@@ -41,21 +45,30 @@ void ConnectionId::set_user_credentials(UserCredentials user_credentials) {
 }
 
 string ConnectionId::ToString() const {
+  string remote;
+  if (hostname_ != remote_.host()) {
+    remote = strings::Substitute("$0 ($1)", remote_.ToString(), hostname_);
+  } else {
+    remote = remote_.ToString();
+  }
+
   return strings::Substitute("{remote=$0, user_credentials=$1}",
-                             remote_.ToString(),
+                             remote,
                              user_credentials_.ToString());
 }
 
 size_t ConnectionId::HashCode() const {
   size_t seed = 0;
   boost::hash_combine(seed, remote_.HashCode());
+  boost::hash_combine(seed, hostname_);
   boost::hash_combine(seed, user_credentials_.HashCode());
   return seed;
 }
 
 bool ConnectionId::Equals(const ConnectionId& other) const {
-  return (remote() == other.remote()
-       && user_credentials().Equals(other.user_credentials()));
+  return remote() == other.remote() &&
+      hostname_ == other.hostname_ &&
+      user_credentials().Equals(other.user_credentials());
 }
 
 size_t ConnectionIdHash::operator() (const ConnectionId& conn_id) const {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/connection_id.h
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/connection_id.h b/src/kudu/rpc/connection_id.h
index 1e2ba68..67a4786 100644
--- a/src/kudu/rpc/connection_id.h
+++ b/src/kudu/rpc/connection_id.h
@@ -36,11 +36,15 @@ class ConnectionId {
   ConnectionId(const ConnectionId& other) = default;
 
   // Convenience constructor.
-  ConnectionId(const Sockaddr& remote, UserCredentials user_credentials);
+  ConnectionId(const Sockaddr& remote,
+               std::string hostname,
+               UserCredentials user_credentials);
 
   // The remote address.
   const Sockaddr& remote() const { return remote_; }
 
+  const std::string& hostname() const { return hostname_; }
+
   // The credentials of the user associated with this connection, if any.
   void set_user_credentials(UserCredentials user_credentials);
 
@@ -59,6 +63,10 @@ class ConnectionId {
   // Remember to update HashCode() and Equals() when new fields are added.
   Sockaddr remote_;
 
+  // The original host name before it was resolved to 'remote_'.
+  // This must be retained since it is used to compute Kerberos Service Principal Names (SPNs).
+  std::string hostname_;
+
   UserCredentials user_credentials_;
 };
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/exactly_once_rpc-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/exactly_once_rpc-test.cc b/src/kudu/rpc/exactly_once_rpc-test.cc
index edf3767..a368483 100644
--- a/src/kudu/rpc/exactly_once_rpc-test.cc
+++ b/src/kudu/rpc/exactly_once_rpc-test.cc
@@ -203,7 +203,8 @@ class ExactlyOnceRpcTest : public RpcTestBase {
     // Set up server.
     StartTestServerWithGeneratedCode(&server_addr_);
     client_messenger_ = CreateMessenger("Client");
-    proxy_.reset(new CalculatorServiceProxy(client_messenger_, server_addr_));
+    proxy_.reset(new CalculatorServiceProxy(
+        client_messenger_, server_addr_, server_addr_.host()));
     test_picker_.reset(new TestServerPicker(proxy_.get()));
     request_tracker_.reset(new RequestTracker(kClientId));
     attempt_nos_ = 0;

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/mt-rpc-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/mt-rpc-test.cc b/src/kudu/rpc/mt-rpc-test.cc
index 65121e5..8f67038 100644
--- a/src/kudu/rpc/mt-rpc-test.cc
+++ b/src/kudu/rpc/mt-rpc-test.cc
@@ -68,7 +68,8 @@ class MultiThreadedRpcTest : public RpcTestBase {
                   Status* result, CountDownLatch* latch) {
     LOG(INFO) << "Connecting to " << server_addr.ToString();
     shared_ptr<Messenger> client_messenger(CreateMessenger("ClientSC"));
-    Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+    Proxy p(client_messenger, server_addr, server_addr.host(),
+            GenericCalculatorService::static_service_name());
     *result = DoTestSyncCall(p, method_name);
     latch->CountDown();
   }
@@ -84,7 +85,8 @@ class MultiThreadedRpcTest : public RpcTestBase {
       Sockaddr server_addr, const char* method_name, Status* last_result,
       const shared_ptr<Messenger>& messenger) {
     LOG(INFO) << "Connecting to " << server_addr.ToString();
-    Proxy p(messenger, server_addr, GenericCalculatorService::static_service_name());
+    Proxy p(messenger, server_addr, server_addr.host(),
+            GenericCalculatorService::static_service_name());
 
     int i = 0;
     while (true) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/negotiation.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/negotiation.cc b/src/kudu/rpc/negotiation.cc
index 8578e37..646df54 100644
--- a/src/kudu/rpc/negotiation.cc
+++ b/src/kudu/rpc/negotiation.cc
@@ -177,11 +177,7 @@ static Status DoClientNegotiation(Connection* conn,
                                        authn_token,
                                        encryption);
 
-  // Note that the fqdn is an IP address here: we've already lost whatever DNS
-  // name the client was attempting to use. Unless krb5 is configured with 'rdns
-  // = false', it will automatically take care of reversing this address to its
-  // canonical hostname to determine the expected server principal.
-  client_negotiation.set_server_fqdn(conn->remote().host());
+  client_negotiation.set_server_fqdn(conn->outbound_connection_id().hostname());
 
   if (authentication != RpcAuthentication::DISABLED) {
     Status s = client_negotiation.EnableGSSAPI();
@@ -210,7 +206,8 @@ static Status DoClientNegotiation(Connection* conn,
   }
 
   if (authentication != RpcAuthentication::REQUIRED) {
-    RETURN_NOT_OK(client_negotiation.EnablePlain(conn->local_user_credentials().real_user(), ""));
+    const auto& creds = conn->outbound_connection_id().user_credentials();
+    RETURN_NOT_OK(client_negotiation.EnablePlain(creds.real_user(), ""));
   }
 
   client_negotiation.set_deadline(deadline);

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/protoc-gen-krpc.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/protoc-gen-krpc.cc b/src/kudu/rpc/protoc-gen-krpc.cc
index 9ce166e..ff0287f 100644
--- a/src/kudu/rpc/protoc-gen-krpc.cc
+++ b/src/kudu/rpc/protoc-gen-krpc.cc
@@ -583,8 +583,9 @@ class CodeGenerator : public ::google::protobuf::compiler::CodeGenerator {
       Print(printer, *subs,
         "class $service_name$Proxy : public ::kudu::rpc::Proxy {\n"
         " public:\n"
-        "  $service_name$Proxy(const std::shared_ptr< ::kudu::rpc::Messenger>\n"
-        "                &messenger, const ::kudu::Sockaddr &sockaddr);\n"
+        "  $service_name$Proxy(std::shared_ptr<::kudu::rpc::Messenger>\n"
+        "                messenger, const ::kudu::Sockaddr &sockaddr,"
+        "                std::string hostname);\n"
         "  ~$service_name$Proxy();\n"
         "\n"
         );
@@ -645,9 +646,9 @@ class CodeGenerator : public ::google::protobuf::compiler::CodeGenerator {
       subs->PushService(service);
       Print(printer, *subs,
         "$service_name$Proxy::$service_name$Proxy(\n"
-        "   const std::shared_ptr< ::kudu::rpc::Messenger> &messenger,\n"
-        "   const ::kudu::Sockaddr &remote)\n"
-        "  : Proxy(messenger, remote, \"$full_service_name$\") {\n"
+        "   std::shared_ptr< ::kudu::rpc::Messenger> messenger,\n"
+        "   const ::kudu::Sockaddr &remote, std::string hostname)\n"
+        "  : Proxy(std::move(messenger), remote, std::move(hostname), \"$full_service_name$\") {\n"
         "}\n"
         "\n"
         "$service_name$Proxy::~$service_name$Proxy() {\n"

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/proxy.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/proxy.cc b/src/kudu/rpc/proxy.cc
index 84c9ba8..87a1e48 100644
--- a/src/kudu/rpc/proxy.cc
+++ b/src/kudu/rpc/proxy.cc
@@ -45,7 +45,9 @@ namespace kudu {
 namespace rpc {
 
 Proxy::Proxy(std::shared_ptr<Messenger> messenger,
-             const Sockaddr& remote, string service_name)
+             const Sockaddr& remote,
+             string hostname,
+             string service_name)
     : service_name_(std::move(service_name)),
       messenger_(std::move(messenger)),
       is_started_(false) {
@@ -63,7 +65,7 @@ Proxy::Proxy(std::shared_ptr<Messenger> messenger,
 
   UserCredentials creds;
   creds.set_real_user(std::move(real_user));
-  conn_id_ = ConnectionId(remote, std::move(creds));
+  conn_id_ = ConnectionId(remote, std::move(hostname), std::move(creds));
 }
 
 Proxy::~Proxy() {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/proxy.h
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/proxy.h b/src/kudu/rpc/proxy.h
index 50640e2..92b3079 100644
--- a/src/kudu/rpc/proxy.h
+++ b/src/kudu/rpc/proxy.h
@@ -57,8 +57,11 @@ class UserCredentials;
 // After initialization, multiple threads may make calls using the same proxy object.
 class Proxy {
  public:
-  Proxy(std::shared_ptr<Messenger> messenger, const Sockaddr& remote,
+  Proxy(std::shared_ptr<Messenger> messenger,
+        const Sockaddr& remote,
+        std::string hostname,
         std::string service_name);
+
   ~Proxy();
 
   // Call a remote method asynchronously.

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/reactor.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/reactor.cc b/src/kudu/rpc/reactor.cc
index ee6f105..b9ecb67 100644
--- a/src/kudu/rpc/reactor.cc
+++ b/src/kudu/rpc/reactor.cc
@@ -467,7 +467,7 @@ Status ReactorThread::FindOrStartConnection(const ConnectionId& conn_id,
   // Register the new connection in our map.
   *conn = new Connection(
       this, conn_id.remote(), std::move(new_socket), Connection::CLIENT, cred_policy);
-  (*conn)->set_local_user_credentials(conn_id.user_credentials());
+  (*conn)->set_outbound_connection_id(conn_id);
 
   // Kick off blocking client connection negotiation.
   Status s = StartConnectionNegotiation(*conn);
@@ -565,8 +565,7 @@ void ReactorThread::DestroyConnection(Connection *conn,
 
   // Unlink connection from lists.
   if (conn->direction() == Connection::CLIENT) {
-    ConnectionId conn_id(conn->remote(), conn->local_user_credentials());
-    const auto range = client_conns_.equal_range(conn_id);
+    const auto range = client_conns_.equal_range(conn->outbound_connection_id());
     CHECK(range.first != range.second) << "Couldn't find connection " << conn->ToString();
     // The client_conns_ container is a multi-map.
     for (auto it = range.first; it != range.second;) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/rpc-bench.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/rpc-bench.cc b/src/kudu/rpc/rpc-bench.cc
index 5d0dc1d..78fd11b 100644
--- a/src/kudu/rpc/rpc-bench.cc
+++ b/src/kudu/rpc/rpc-bench.cc
@@ -144,7 +144,7 @@ class ClientThread {
   void Run() {
     shared_ptr<Messenger> client_messenger = bench_->CreateMessenger("Client");
 
-    CalculatorServiceProxy p(client_messenger, bench_->server_addr_);
+    CalculatorServiceProxy p(client_messenger, bench_->server_addr_, "localhost");
 
     AddRequestPB req;
     AddResponsePB resp;
@@ -197,7 +197,7 @@ class ClientAsyncWorkload {
       messenger_(std::move(messenger)),
       request_count_(0) {
     controller_.set_timeout(MonoDelta::FromSeconds(10));
-    proxy_.reset(new CalculatorServiceProxy(messenger_, bench_->server_addr_));
+    proxy_.reset(new CalculatorServiceProxy(messenger_, bench_->server_addr_, "localhost"));
   }
 
   void CallOneRpc() {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/rpc-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/rpc-test.cc b/src/kudu/rpc/rpc-test.cc
index 12ef436..a367976 100644
--- a/src/kudu/rpc/rpc-test.cc
+++ b/src/kudu/rpc/rpc-test.cc
@@ -158,7 +158,8 @@ TEST_P(TestRpc, TestNegotiationDeadlock) {
   Sockaddr server_addr;
   StartTestServerWithCustomMessenger(&server_addr, messenger, enable_ssl);
 
-  Proxy p(messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
   ASSERT_OK(DoTestSyncCall(p, GenericCalculatorService::kAddMethodName));
 }
 
@@ -172,7 +173,8 @@ TEST_P(TestRpc, TestCall) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
   ASSERT_STR_CONTAINS(p.ToString(), strings::Substitute("kudu.rpc.GenericCalculatorService@"
                                                             "{remote=$0, user_credentials=",
                                                         server_addr.ToString()));
@@ -198,7 +200,8 @@ TEST_P(TestRpc, TestCallWithChainCert) {
   // Set up client.
   SCOPED_TRACE(strings::Substitute("Connecting to $0", server_addr.ToString()));
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
   ASSERT_STR_CONTAINS(p.ToString(), strings::Substitute("kudu.rpc.GenericCalculatorService@"
                                                             "{remote=$0, user_credentials=",
                                                         server_addr.ToString()));
@@ -227,7 +230,8 @@ TEST_P(TestRpc, TestCallWithPasswordProtectedKey) {
   // Set up client.
   SCOPED_TRACE(strings::Substitute("Connecting to $0", server_addr.ToString()));
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
   ASSERT_STR_CONTAINS(p.ToString(), strings::Substitute("kudu.rpc.GenericCalculatorService@"
                                                             "{remote=$0, user_credentials=",
                                                         server_addr.ToString()));
@@ -262,7 +266,8 @@ TEST_P(TestRpc, TestCallToBadServer) {
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, GetParam()));
   Sockaddr addr;
   addr.set_port(0);
-  Proxy p(client_messenger, addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, addr, addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Loop a few calls to make sure that we properly set up and tear down
   // the connections.
@@ -283,7 +288,8 @@ TEST_P(TestRpc, TestInvalidMethodCall) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Call the method which fails.
   Status s = DoTestSyncCall(p, "ThisMethodDoesNotExist");
@@ -301,7 +307,7 @@ TEST_P(TestRpc, TestWrongService) {
 
   // Set up client with the wrong service name.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, "WrongServiceName");
+  Proxy p(client_messenger, server_addr, "localhost", "WrongServiceName");
 
   // Call the method which fails.
   Status s = DoTestSyncCall(p, "ThisMethodDoesNotExist");
@@ -336,7 +342,8 @@ TEST_P(TestRpc, TestHighFDs) {
   bool enable_ssl = GetParam();
   StartTestServer(&server_addr, enable_ssl);
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
   ASSERT_OK(DoTestSyncCall(p, GenericCalculatorService::kAddMethodName));
 }
 
@@ -355,7 +362,8 @@ TEST_P(TestRpc, TestConnectionKeepalive) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   ASSERT_OK(DoTestSyncCall(p, GenericCalculatorService::kAddMethodName));
 
@@ -402,7 +410,8 @@ TEST_P(TestRpc, TestReopenOutboundConnections) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Verify the initial counters.
   ReactorMetrics metrics;
@@ -443,7 +452,8 @@ TEST_P(TestRpc, TestCredentialsPolicy) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Verify the initial counters.
   ReactorMetrics metrics;
@@ -511,7 +521,8 @@ TEST_P(TestRpc, TestCallLongerThanKeepalive) {
 
   // Set up client.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Make a call which sleeps longer than the keepalive.
   RpcController controller;
@@ -532,7 +543,8 @@ TEST_P(TestRpc, TestRpcSidecar) {
 
   // Set up client.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, GetParam()));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Test a zero-length sidecar
   DoTestSidecar(p, 0, 0);
@@ -571,7 +583,8 @@ TEST_P(TestRpc, TestRpcSidecarLimits) {
 
     // Set up client.
     shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, GetParam()));
-    Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+    Proxy p(client_messenger, server_addr, server_addr.host(),
+            GenericCalculatorService::static_service_name());
 
     RpcController controller;
     string s(FLAGS_rpc_max_message_size + 1, 'a');
@@ -602,7 +615,8 @@ TEST_P(TestRpc, TestCallTimeout) {
   bool enable_ssl = GetParam();
   StartTestServer(&server_addr, enable_ssl);
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Test a very short timeout - we expect this will time out while the
   // call is still trying to connect, or in the send queue. This was triggering ASAN failures
@@ -630,7 +644,8 @@ TEST_P(TestRpc, TestCallTimeoutDoesntAffectNegotiation) {
   bool enable_ssl = GetParam();
   StartTestServer(&server_addr, enable_ssl);
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   FLAGS_rpc_negotiation_inject_delay_ms = 500;
   ASSERT_NO_FATAL_FAILURE(DoTestExpectTimeout(p, MonoDelta::FromMilliseconds(50)));
@@ -673,7 +688,8 @@ TEST_F(TestRpc, TestNegotiationTimeout) {
 
   // Set up client.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client"));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   bool is_negotiation_error = false;
   ASSERT_NO_FATAL_FAILURE(DoTestExpectTimeout(
@@ -694,7 +710,8 @@ TEST_F(TestRpc, TestServerShutsDown) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client"));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   // Send a call.
   AddRequestPB req;
@@ -778,7 +795,8 @@ TEST_P(TestRpc, TestRpcHandlerLatencyMetric) {
 
   // Set up client.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, CalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          CalculatorService::static_service_name());
 
   RpcController controller;
   SleepRequestPB req;
@@ -826,7 +844,7 @@ TEST_P(TestRpc, TestRpcCallbackDestroysMessenger) {
   RpcController controller;
   controller.set_timeout(MonoDelta::FromMilliseconds(1));
   {
-    Proxy p(client_messenger, bad_addr, "xxx");
+    Proxy p(client_messenger, bad_addr, "xxx-host", "xxx-service");
     p.AsyncRequest("my-fake-method", req, &resp, &controller,
                    boost::bind(&DestroyMessengerCallback, &client_messenger, &latch));
   }
@@ -845,7 +863,8 @@ TEST_P(TestRpc, TestRpcContextClientDeadline) {
 
   // Set up client.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, CalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          CalculatorService::static_service_name());
 
   SleepRequestPB req;
   req.set_sleep_micros(sleep_micros);
@@ -871,7 +890,8 @@ TEST_P(TestRpc, TestApplicationFeatureFlag) {
 
   // Set up client.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, CalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          CalculatorService::static_service_name());
 
   { // Supported flag
     AddRequestPB req;
@@ -912,7 +932,8 @@ TEST_P(TestRpc, TestApplicationFeatureFlagUnsupportedServer) {
 
   // Set up client.
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, CalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          CalculatorService::static_service_name());
 
   { // Required flag
     AddRequestPB req;
@@ -947,7 +968,8 @@ TEST_P(TestRpc, TestCancellation) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   for (int i = OutboundCall::READY; i <= OutboundCall::FINISHED_SUCCESS; ++i) {
     FLAGS_rpc_inject_cancellation_state = i;
@@ -1009,7 +1031,8 @@ TEST_P(TestRpc, TestCancellationAsync) {
   // Set up client.
   LOG(INFO) << "Connecting to " << server_addr.ToString();
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
-  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  Proxy p(client_messenger, server_addr, server_addr.host(),
+          GenericCalculatorService::static_service_name());
 
   RpcController controller;
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/rpc/rpc_stub-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/rpc_stub-test.cc b/src/kudu/rpc/rpc_stub-test.cc
index 4adc8b1..2b787db 100644
--- a/src/kudu/rpc/rpc_stub-test.cc
+++ b/src/kudu/rpc/rpc_stub-test.cc
@@ -91,7 +91,7 @@ class RpcStubTest : public RpcTestBase {
   }
  protected:
   void SendSimpleCall() {
-    CalculatorServiceProxy p(client_messenger_, server_addr_);
+    CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
     RpcController controller;
     AddRequestPB req;
@@ -115,7 +115,7 @@ TEST_F(RpcStubTest, TestSimpleCall) {
 // reads and then makes a number of calls.
 TEST_F(RpcStubTest, TestShortRecvs) {
   FLAGS_socket_inject_short_recvs = true;
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   for (int i = 0; i < 100; i++) {
     NO_FATALS(SendSimpleCall());
@@ -133,7 +133,7 @@ TEST_F(RpcStubTest, TestBigCallData) {
   string data;
   data.resize(kMessageSize);
 
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   EchoRequestPB req;
   req.set_data(data);
@@ -158,7 +158,7 @@ TEST_F(RpcStubTest, TestBigCallData) {
 }
 
 TEST_F(RpcStubTest, TestRespondDeferred) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   RpcController controller;
   SleepRequestPB req;
@@ -170,7 +170,7 @@ TEST_F(RpcStubTest, TestRespondDeferred) {
 
 // Test that the default user credentials are propagated to the server.
 TEST_F(RpcStubTest, TestDefaultCredentialsPropagated) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   string expected;
   ASSERT_OK(GetLoggedInUser(&expected));
@@ -186,7 +186,7 @@ TEST_F(RpcStubTest, TestDefaultCredentialsPropagated) {
 // Test that the user can specify other credentials.
 TEST_F(RpcStubTest, TestCustomCredentialsPropagated) {
   const char* const kFakeUserName = "some fake user";
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   UserCredentials creds;
   creds.set_real_user(kFakeUserName);
@@ -203,7 +203,7 @@ TEST_F(RpcStubTest, TestCustomCredentialsPropagated) {
 TEST_F(RpcStubTest, TestAuthorization) {
   // First test calling WhoAmI() as user "alice", who is disallowed.
   {
-    CalculatorServiceProxy p(client_messenger_, server_addr_);
+    CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
     UserCredentials creds;
     creds.set_real_user("alice");
     p.set_user_credentials(creds);
@@ -220,7 +220,7 @@ TEST_F(RpcStubTest, TestAuthorization) {
 
   // Try some calls as "bob".
   {
-    CalculatorServiceProxy p(client_messenger_, server_addr_);
+    CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
     UserCredentials creds;
     creds.set_real_user("bob");
     p.set_user_credentials(creds);
@@ -248,7 +248,7 @@ TEST_F(RpcStubTest, TestAuthorization) {
 
 // Test that the user's remote address is accessible to the server.
 TEST_F(RpcStubTest, TestRemoteAddress) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   RpcController controller;
   WhoAmIRequestPB req;
@@ -264,7 +264,8 @@ TEST_F(RpcStubTest, TestRemoteAddress) {
 // Test sending a PB parameter with a missing field, where the client
 // thinks it has sent a full PB. (eg due to version mismatch)
 TEST_F(RpcStubTest, TestCallWithInvalidParam) {
-  Proxy p(client_messenger_, server_addr_, CalculatorService::static_service_name());
+  Proxy p(client_messenger_, server_addr_, server_addr_.host(),
+          CalculatorService::static_service_name());
 
   rpc_test::AddRequestPartialPB req;
   req.set_x(rand());
@@ -289,7 +290,7 @@ static void DoIncrement(Atomic32* count) {
 // This also ensures that the async callback is only called once
 // (regression test for a previously-encountered bug).
 TEST_F(RpcStubTest, TestCallWithMissingPBFieldClientSide) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   RpcController controller;
   AddRequestPB req;
@@ -309,7 +310,7 @@ TEST_F(RpcStubTest, TestCallWithMissingPBFieldClientSide) {
 }
 
 TEST_F(RpcStubTest, TestResponseWithMissingField) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   RpcController rpc;
   TestInvalidResponseRequestPB req;
@@ -324,7 +325,7 @@ TEST_F(RpcStubTest, TestResponseWithMissingField) {
 // configured RPC message size. The server should send the response, but the client
 // will reject it.
 TEST_F(RpcStubTest, TestResponseLargerThanFrameSize) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   RpcController rpc;
   TestInvalidResponseRequestPB req;
@@ -336,7 +337,8 @@ TEST_F(RpcStubTest, TestResponseLargerThanFrameSize) {
 
 // Test sending a call which isn't implemented by the server.
 TEST_F(RpcStubTest, TestCallMissingMethod) {
-  Proxy p(client_messenger_, server_addr_, CalculatorService::static_service_name());
+  Proxy p(client_messenger_, server_addr_, server_addr_.host(),
+          CalculatorService::static_service_name());
 
   Status s = DoTestSyncCall(p, "DoesNotExist");
   ASSERT_TRUE(s.IsRemoteError()) << "Bad status: " << s.ToString();
@@ -344,7 +346,7 @@ TEST_F(RpcStubTest, TestCallMissingMethod) {
 }
 
 TEST_F(RpcStubTest, TestApplicationError) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   RpcController controller;
   SleepRequestPB req;
@@ -408,7 +410,7 @@ TEST_F(RpcStubTest, TestRpcPanic) {
     CHECK_OK(env_->DeleteRecursively(test_dir_));
 
     // Make an RPC which causes the server to abort.
-    CalculatorServiceProxy p(client_messenger_, server_addr_);
+    CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
     RpcController controller;
     PanicRequestPB req;
     PanicResponsePB resp;
@@ -426,7 +428,7 @@ struct AsyncSleep {
 };
 
 TEST_F(RpcStubTest, TestDontHandleTimedOutCalls) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
   vector<AsyncSleep*> sleeps;
   ElementDeleter d(&sleeps);
 
@@ -490,7 +492,8 @@ TEST_F(RpcStubTest, TestEarliestDeadlineFirstQueue) {
   for (int thread_id = 0; thread_id < num_client_threads; thread_id++) {
     threads.emplace_back([&, thread_id] {
         Random rng(thread_id);
-        CalculatorServiceProxy p(client_messenger_, server_addr_);
+        CalculatorServiceProxy p(
+            client_messenger_, server_addr_, server_addr_.host());
         while (!done.load()) {
           // Set a deadline in the future. We'll keep using this same deadline
           // on each of our retries.
@@ -548,7 +551,7 @@ TEST_F(RpcStubTest, TestEarliestDeadlineFirstQueue) {
 }
 
 TEST_F(RpcStubTest, TestDumpCallsInFlight) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
   AsyncSleep sleep;
   sleep.req.set_sleep_micros(100 * 1000); // 100ms
   p.SleepAsync(sleep.req, &sleep.resp, &sleep.rpc,
@@ -592,7 +595,7 @@ TEST_F(RpcStubTest, TestDumpCallsInFlight) {
 }
 
 TEST_F(RpcStubTest, TestDumpSampledCalls) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   // Issue two calls that fall into different latency buckets.
   AsyncSleep sleeps[2];
@@ -649,7 +652,7 @@ void MyTestCallback(CountDownLatch* latch, scoped_refptr<RefCountedTest> my_refp
 // is held. This is important when the callback holds a refcounted ptr,
 // since we expect to be able to release that pointer when the call is done.
 TEST_F(RpcStubTest, TestCallbackClearedAfterRunning) {
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   CountDownLatch latch(1);
   scoped_refptr<RefCountedTest> my_refptr(new RefCountedTest);
@@ -678,7 +681,7 @@ TEST_F(RpcStubTest, DontTimeOutWhenReactorIsBlocked) {
       << "This test requires only a single reactor. Otherwise the injected sleep might "
       << "be scheduled on a different reactor than the RPC call.";
 
-  CalculatorServiceProxy p(client_messenger_, server_addr_);
+  CalculatorServiceProxy p(client_messenger_, server_addr_, server_addr_.host());
 
   // Schedule a 1-second sleep on the reactor thread.
   //

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/tools/ksck_remote.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/ksck_remote.cc b/src/kudu/tools/ksck_remote.cc
index 2268cb0..34dc0f5 100644
--- a/src/kudu/tools/ksck_remote.cc
+++ b/src/kudu/tools/ksck_remote.cc
@@ -85,9 +85,11 @@ Status RemoteKsckTabletServer::Init() {
   RETURN_NOT_OK(ParseAddressList(
       host_port_.ToString(),
       tserver::TabletServer::kDefaultPort, &addresses));
-  generic_proxy_.reset(new server::GenericServiceProxy(messenger_, addresses[0]));
-  ts_proxy_.reset(new tserver::TabletServerServiceProxy(messenger_, addresses[0]));
-  consensus_proxy_.reset(new consensus::ConsensusServiceProxy(messenger_, addresses[0]));
+  const auto& addr = addresses[0];
+  const auto& host = host_port_.host();
+  generic_proxy_.reset(new server::GenericServiceProxy(messenger_, addr, host));
+  ts_proxy_.reset(new tserver::TabletServerServiceProxy(messenger_, addr, host));
+  consensus_proxy_.reset(new consensus::ConsensusServiceProxy(messenger_, addr, host));
   return Status::OK();
 }
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/tools/tool_action_common.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_common.cc b/src/kudu/tools/tool_action_common.cc
index 0a4a037..5e5639d 100644
--- a/src/kudu/tools/tool_action_common.cc
+++ b/src/kudu/tools/tool_action_common.cc
@@ -264,7 +264,7 @@ Status BuildProxy(const string& address,
   vector<Sockaddr> resolved;
   RETURN_NOT_OK(hp.ResolveAddresses(&resolved));
 
-  proxy->reset(new ProxyClass(messenger, resolved[0]));
+  proxy->reset(new ProxyClass(messenger, resolved[0], hp.host()));
   return Status::OK();
 }
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/tserver/heartbeater.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/heartbeater.cc b/src/kudu/tserver/heartbeater.cc
index baa81c2..fe548fe 100644
--- a/src/kudu/tserver/heartbeater.cc
+++ b/src/kudu/tserver/heartbeater.cc
@@ -107,7 +107,7 @@ Status MasterServiceProxyForHostPort(const HostPort& hostport,
                  << "resolves to " << addrs.size() << " different addresses. Using "
                  << addrs[0].ToString();
   }
-  proxy->reset(new MasterServiceProxy(messenger, addrs[0]));
+  proxy->reset(new MasterServiceProxy(messenger, addrs[0], hostport.host()));
   return Status::OK();
 }
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/tserver/tablet_copy_client.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_copy_client.cc b/src/kudu/tserver/tablet_copy_client.cc
index 7418477..672840e 100644
--- a/src/kudu/tserver/tablet_copy_client.cc
+++ b/src/kudu/tserver/tablet_copy_client.cc
@@ -181,7 +181,7 @@ Status TabletCopyClient::Start(const HostPort& copy_source_addr,
                         << " from remote peer at address " << copy_source_addr.ToString();
 
   // Set up an RPC proxy for the TabletCopyService.
-  proxy_.reset(new TabletCopyServiceProxy(messenger_, addr));
+  proxy_.reset(new TabletCopyServiceProxy(messenger_, addr, copy_source_addr.host()));
 
   BeginTabletCopySessionRequestPB req;
   req.set_requestor_uuid(fs_manager_->uuid());

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/tserver/tablet_copy_service-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_copy_service-test.cc b/src/kudu/tserver/tablet_copy_service-test.cc
index 442210f..f469212 100644
--- a/src/kudu/tserver/tablet_copy_service-test.cc
+++ b/src/kudu/tserver/tablet_copy_service-test.cc
@@ -88,7 +88,9 @@ class TabletCopyServiceTest : public TabletCopyTest {
   void SetUp() OVERRIDE {
     TabletCopyTest::SetUp();
     tablet_copy_proxy_.reset(
-        new TabletCopyServiceProxy(client_messenger_, mini_server_->bound_rpc_addr()));
+        new TabletCopyServiceProxy(
+            client_messenger_, mini_server_->bound_rpc_addr(),
+            mini_server_->bound_rpc_addr().host()));
   }
 
   Status DoBeginTabletCopySession(const string& tablet_id,

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/tserver/tablet_server-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_server-test.cc b/src/kudu/tserver/tablet_server-test.cc
index 34a4ab1..da58e59 100644
--- a/src/kudu/tserver/tablet_server-test.cc
+++ b/src/kudu/tserver/tablet_server-test.cc
@@ -170,7 +170,8 @@ TEST_F(TabletServerTest, TestServerClock) {
 
 TEST_F(TabletServerTest, TestSetFlags) {
   server::GenericServiceProxy proxy(
-      client_messenger_, mini_server_->bound_rpc_addr());
+      client_messenger_, mini_server_->bound_rpc_addr(),
+      mini_server_->bound_rpc_addr().host());
 
   server::SetFlagRequestPB req;
   server::SetFlagResponsePB resp;

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/tserver/tablet_server_test_util.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_server_test_util.cc b/src/kudu/tserver/tablet_server_test_util.cc
index 52b3891..1b884be 100644
--- a/src/kudu/tserver/tablet_server_test_util.cc
+++ b/src/kudu/tserver/tablet_server_test_util.cc
@@ -17,6 +17,8 @@
 
 #include "kudu/tserver/tablet_server_test_util.h"
 
+#include <string>
+
 #include "kudu/consensus/consensus.proxy.h"
 #include "kudu/server/server_base.proxy.h"
 #include "kudu/tserver/tserver_admin.proxy.h"
@@ -35,10 +37,11 @@ void CreateTsClientProxies(const Sockaddr& addr,
                            gscoped_ptr<TabletServerAdminServiceProxy>* admin_proxy,
                            gscoped_ptr<ConsensusServiceProxy>* consensus_proxy,
                            gscoped_ptr<server::GenericServiceProxy>* generic_proxy) {
-  proxy->reset(new TabletServerServiceProxy(messenger, addr));
-  admin_proxy->reset(new TabletServerAdminServiceProxy(messenger, addr));
-  consensus_proxy->reset(new ConsensusServiceProxy(messenger, addr));
-  generic_proxy->reset(new server::GenericServiceProxy(messenger, addr));
+  const auto& host = addr.host();
+  proxy->reset(new TabletServerServiceProxy(messenger, addr, host));
+  admin_proxy->reset(new TabletServerAdminServiceProxy(messenger, addr, host));
+  consensus_proxy->reset(new ConsensusServiceProxy(messenger, addr, host));
+  generic_proxy->reset(new server::GenericServiceProxy(messenger, addr, host));
 }
 
 } // namespace tserver

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/util/net/net_util-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/net/net_util-test.cc b/src/kudu/util/net/net_util-test.cc
index 1717d04..202ec6b 100644
--- a/src/kudu/util/net/net_util-test.cc
+++ b/src/kudu/util/net/net_util-test.cc
@@ -60,6 +60,7 @@ TEST(SockaddrTest, Test) {
   Sockaddr addr;
   ASSERT_OK(addr.ParseString("1.1.1.1:12345", 12345));
   ASSERT_EQ(12345, addr.port());
+  ASSERT_EQ("1.1.1.1", addr.host());
 }
 
 TEST_F(NetUtilTest, TestParseAddresses) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/util/net/sockaddr.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/net/sockaddr.cc b/src/kudu/util/net/sockaddr.cc
index 428d4bd..3b99490 100644
--- a/src/kudu/util/net/sockaddr.cc
+++ b/src/kudu/util/net/sockaddr.cc
@@ -100,9 +100,7 @@ const struct sockaddr_in& Sockaddr::addr() const {
 }
 
 std::string Sockaddr::ToString() const {
-  char str[INET_ADDRSTRLEN];
-  ::inet_ntop(AF_INET, &addr_.sin_addr, str, INET_ADDRSTRLEN);
-  return StringPrintf("%s:%d", str, port());
+  return Substitute("$0:$1", host(), port());
 }
 
 bool Sockaddr::IsWildcard() const {

http://git-wip-us.apache.org/repos/asf/kudu/blob/efb5395b/src/kudu/util/net/sockaddr.h
----------------------------------------------------------------------
diff --git a/src/kudu/util/net/sockaddr.h b/src/kudu/util/net/sockaddr.h
index 3253b39..dffd151 100644
--- a/src/kudu/util/net/sockaddr.h
+++ b/src/kudu/util/net/sockaddr.h
@@ -56,11 +56,14 @@ class Sockaddr {
 
   uint32_t HashCode() const;
 
+  // Returns the dotted-decimal string '1.2.3.4' of the host component of this address.
   std::string host() const;
 
   void set_port(int port);
   int port() const;
   const struct sockaddr_in& addr() const;
+
+  // Returns the stringified address in '1.2.3.4:<port>' format.
   std::string ToString() const;
 
   // Returns true if the address is 0.0.0.0