diff --git a/hbase-common/src/main/resources/hbase-default.xml b/hbase-common/src/main/resources/hbase-default.xml
index 70c638b9134..0ea9cc759bc 100644
--- a/hbase-common/src/main/resources/hbase-default.xml
+++ b/hbase-common/src/main/resources/hbase-default.xml
@@ -988,6 +988,15 @@ possible configurations would overwhelm and obscure the important.
When set to a non-empty value, this represents the (external facing) hostname for the underlying server.
See https://issues.apache.org/jira/browse/HBASE-12954 for details.
+
+ hbase.regionserver.hostname.disable.master.reversedns
+ false
+ This config is for experts: don't set its value unless you really know what you are doing.
+ When set to true, regionserver will use the current node hostname for the servername and HMaster will
+ skip reverse DNS lookup and use the hostname sent by regionserver instead. Note that this config and
+ hbase.regionserver.hostname are mutually exclusive. See https://issues.apache.org/jira/browse/HBASE-18226
+ for more details.
+
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
index 61e89333d7a..f0537e0f15b 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
@@ -450,6 +450,11 @@ public class HRegionServer extends HasThread implements
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
protected final static String MASTER_HOSTNAME_KEY = "hbase.master.hostname";
+ // HBASE-18226: This config and hbase.regionserver.hostname are mutually exclusive.
+ // Exception will be thrown if both are used.
+ final static String RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY =
+ "hbase.regionserver.hostname.disable.master.reversedns";
+
/**
* This servers startcode.
*/
@@ -577,6 +582,16 @@ public class HRegionServer extends HasThread implements
useThisHostnameInstead = conf.get(MASTER_HOSTNAME_KEY);
} else {
useThisHostnameInstead = conf.get(RS_HOSTNAME_KEY);
+ if (conf.getBoolean(RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, false)) {
+ if (shouldUseThisHostnameInstead()) {
+ String msg = RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY + " and " + RS_HOSTNAME_KEY +
+ " are mutually exclusive. Do not set " + RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY +
+ " to true while " + RS_HOSTNAME_KEY + " is used";
+ throw new IOException(msg);
+ } else {
+ useThisHostnameInstead = rpcServices.isa.getHostName();
+ }
+ }
}
String hostName = shouldUseThisHostnameInstead() ? useThisHostnameInstead :
rpcServices.isa.getHostName();
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerHostname.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerHostname.java
index 63e33d4819f..679595ae6ef 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerHostname.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerHostname.java
@@ -28,6 +28,8 @@ import java.util.Locale;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
@@ -42,13 +44,14 @@ import org.junit.experimental.categories.Category;
@Category({RegionServerTests.class, MediumTests.class})
public class TestRegionServerHostname {
private static final Log LOG = LogFactory.getLog(TestRegionServerHostname.class);
- private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
@Test (timeout=30000)
public void testInvalidRegionServerHostnameAbortsServer() throws Exception {
final int NUM_MASTERS = 1;
final int NUM_RS = 1;
String invalidHostname = "hostAddr.invalid";
+ Configuration conf = HBaseConfiguration.create();
+ HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(conf);
TEST_UTIL.getConfiguration().set(HRegionServer.RS_HOSTNAME_KEY, invalidHostname);
try {
TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS);
@@ -70,7 +73,8 @@ public class TestRegionServerHostname {
final int NUM_MASTERS = 1;
final int NUM_RS = 1;
Enumeration netInterfaceList = NetworkInterface.getNetworkInterfaces();
-
+ Configuration conf = HBaseConfiguration.create();
+ HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(conf);
while (netInterfaceList.hasMoreElements()) {
NetworkInterface ni = netInterfaceList.nextElement();
Enumeration addrList = ni.getInetAddresses();
@@ -82,7 +86,7 @@ public class TestRegionServerHostname {
}
String hostName = addr.getHostName();
LOG.info("Found " + hostName + " on " + ni);
-
+
TEST_UTIL.getConfiguration().set(HRegionServer.MASTER_HOSTNAME_KEY, hostName);
TEST_UTIL.getConfiguration().set(HRegionServer.RS_HOSTNAME_KEY, hostName);
TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS);
@@ -102,4 +106,64 @@ public class TestRegionServerHostname {
}
}
}
+
+ @Test(timeout=30000)
+ public void testConflictRegionServerHostnameConfigurationsAbortServer() throws Exception {
+ final int NUM_MASTERS = 1;
+ final int NUM_RS = 1;
+ Enumeration netInterfaceList = NetworkInterface.getNetworkInterfaces();
+ Configuration conf = HBaseConfiguration.create();
+ HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(conf);
+ while (netInterfaceList.hasMoreElements()) {
+ NetworkInterface ni = netInterfaceList.nextElement();
+ Enumeration addrList = ni.getInetAddresses();
+ // iterate through host addresses and use each as hostname
+ while (addrList.hasMoreElements()) {
+ InetAddress addr = addrList.nextElement();
+ if (addr.isLoopbackAddress() || addr.isLinkLocalAddress() || addr.isMulticastAddress()) {
+ continue;
+ }
+ String hostName = addr.getHostName();
+ LOG.info("Found " + hostName + " on " + ni);
+
+ TEST_UTIL.getConfiguration().set(HRegionServer.MASTER_HOSTNAME_KEY, hostName);
+ // "hbase.regionserver.hostname" and "hbase.regionserver.hostname.disable.master.reversedns"
+ // are mutually exclusive. Exception should be thrown if both are used.
+ TEST_UTIL.getConfiguration().set(HRegionServer.RS_HOSTNAME_KEY, hostName);
+ TEST_UTIL.getConfiguration().setBoolean(HRegionServer.RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true);
+ try {
+ TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS);
+ } catch (Exception e) {
+ Throwable t1 = e.getCause();
+ Throwable t2 = t1.getCause();
+ assertTrue(t1.getMessage()+" - "+t2.getMessage(), t2.getMessage().contains(
+ HRegionServer.RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY + " and " + HRegionServer.RS_HOSTNAME_KEY +
+ " are mutually exclusive"));
+ return;
+ } finally {
+ TEST_UTIL.shutdownMiniCluster();
+ }
+ assertTrue("Failed to validate against conflict hostname configurations", false);
+ }
+ }
+ }
+
+ @Test(timeout=30000)
+ public void testRegionServerHostnameReportedToMaster() throws Exception {
+ final int NUM_MASTERS = 1;
+ final int NUM_RS = 1;
+ Configuration conf = HBaseConfiguration.create();
+ HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(conf);
+ TEST_UTIL.getConfiguration().setBoolean(HRegionServer.RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true);
+ TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS);
+ try {
+ ZooKeeperWatcher zkw = TEST_UTIL.getZooKeeperWatcher();
+ List servers = ZKUtil.listChildrenNoWatch(zkw, zkw.znodePaths.rsZNode);
+ // there would be NUM_RS+1 children - one for the master
+ assertTrue(servers.size() == NUM_RS+1);
+ zkw.close();
+ } finally {
+ TEST_UTIL.shutdownMiniCluster();
+ }
+ }
}