001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertNull; 023import static org.junit.Assert.assertTrue; 024 025import java.net.InetAddress; 026import java.net.NetworkInterface; 027import java.util.ArrayList; 028import java.util.Enumeration; 029import java.util.List; 030import java.util.Locale; 031import org.apache.hadoop.conf.Configuration; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HBaseConfiguration; 034import org.apache.hadoop.hbase.HBaseTestingUtil; 035import org.apache.hadoop.hbase.StartTestingClusterOption; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.apache.hadoop.hbase.testclassification.RegionServerTests; 038import org.apache.hadoop.hbase.util.DNS; 039import org.apache.hadoop.hbase.zookeeper.ZKUtil; 040import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 041import org.junit.After; 042import org.junit.Before; 043import org.junit.ClassRule; 044import org.junit.Test; 045import org.junit.experimental.categories.Category; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049/** 050 * Tests for the hostname specification by region server 051 */ 052@Category({ RegionServerTests.class, MediumTests.class }) 053public class TestRegionServerHostname { 054 055 @ClassRule 056 public static final HBaseClassTestRule CLASS_RULE = 057 HBaseClassTestRule.forClass(TestRegionServerHostname.class); 058 059 private static final Logger LOG = LoggerFactory.getLogger(TestRegionServerHostname.class); 060 061 private HBaseTestingUtil TEST_UTIL; 062 063 private static final int NUM_MASTERS = 1; 064 private static final int NUM_RS = 1; 065 066 @Before 067 public void setup() { 068 Configuration conf = HBaseConfiguration.create(); 069 TEST_UTIL = new HBaseTestingUtil(conf); 070 } 071 072 @After 073 public void teardown() throws Exception { 074 TEST_UTIL.shutdownMiniCluster(); 075 } 076 077 @Test 078 public void testInvalidRegionServerHostnameAbortsServer() throws Exception { 079 String invalidHostname = "hostAddr.invalid"; 080 TEST_UTIL.getConfiguration().set(DNS.UNSAFE_RS_HOSTNAME_KEY, invalidHostname); 081 HRegionServer hrs = null; 082 try { 083 hrs = new HRegionServer(TEST_UTIL.getConfiguration()); 084 } catch (IllegalArgumentException iae) { 085 assertTrue(iae.getMessage(), iae.getMessage().contains("Failed resolve of " + invalidHostname) 086 || iae.getMessage().contains("Problem binding to " + invalidHostname)); 087 } 088 assertNull("Failed to validate against invalid hostname", hrs); 089 } 090 091 @Test 092 public void testRegionServerHostname() throws Exception { 093 for (NetworkInterface ni : getValidNetworkInterfaces()) { 094 Enumeration<InetAddress> addrList = ni.getInetAddresses(); 095 // iterate through host addresses and use each as hostname 096 while (addrList.hasMoreElements()) { 097 InetAddress addr = addrList.nextElement(); 098 if ( 099 addr.isLoopbackAddress() || addr.isLinkLocalAddress() || addr.isMulticastAddress() 100 || !addr.isSiteLocalAddress() 101 ) { 102 continue; 103 } 104 String hostName = addr.getHostName(); 105 LOG.info("Found " + hostName + " on " + ni + ", addr=" + addr); 106 107 TEST_UTIL.getConfiguration().set(DNS.MASTER_HOSTNAME_KEY, hostName); 108 TEST_UTIL.getConfiguration().set(DNS.UNSAFE_RS_HOSTNAME_KEY, hostName); 109 StartTestingClusterOption option = StartTestingClusterOption.builder() 110 .numMasters(NUM_MASTERS).numRegionServers(NUM_RS).numDataNodes(NUM_RS).build(); 111 TEST_UTIL.startMiniCluster(option); 112 try { 113 ZKWatcher zkw = TEST_UTIL.getZooKeeperWatcher(); 114 List<String> servers = ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode); 115 assertEquals(NUM_RS, servers.size()); 116 for (String server : servers) { 117 assertTrue("From zookeeper: " + server + " hostname: " + hostName, 118 server.startsWith(hostName.toLowerCase(Locale.ROOT) + ",")); 119 } 120 zkw.close(); 121 } finally { 122 TEST_UTIL.shutdownMiniCluster(); 123 } 124 } 125 } 126 } 127 128 @Test 129 public void testDeprecatedConfigs() throws Exception { 130 Configuration conf = TEST_UTIL.getConfiguration(); 131 new HRegionServer(conf); 132 conf.setBoolean(HRegionServer.RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, false); 133 assertFalse( 134 conf.getBoolean(HRegionServer.UNSAFE_RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true)); 135 conf.setBoolean(HRegionServer.RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true); 136 assertTrue( 137 conf.getBoolean(HRegionServer.UNSAFE_RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, false)); 138 conf.setBoolean(HRegionServer.UNSAFE_RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true); 139 assertTrue(conf.getBoolean(HRegionServer.RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, false)); 140 conf.setBoolean(HRegionServer.UNSAFE_RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, false); 141 assertFalse(conf.getBoolean(HRegionServer.RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true)); 142 143 conf.setBoolean(DNS.RS_HOSTNAME_KEY, false); 144 assertFalse(conf.getBoolean(DNS.UNSAFE_RS_HOSTNAME_KEY, true)); 145 conf.setBoolean(DNS.RS_HOSTNAME_KEY, true); 146 assertTrue(conf.getBoolean(DNS.UNSAFE_RS_HOSTNAME_KEY, false)); 147 conf.setBoolean(DNS.UNSAFE_RS_HOSTNAME_KEY, true); 148 assertTrue(conf.getBoolean(DNS.RS_HOSTNAME_KEY, false)); 149 conf.setBoolean(DNS.UNSAFE_RS_HOSTNAME_KEY, false); 150 assertFalse(conf.getBoolean(DNS.RS_HOSTNAME_KEY, true)); 151 } 152 153 @Test 154 public void testConflictRegionServerHostnameConfigurationsAbortServer() throws Exception { 155 Enumeration<NetworkInterface> netInterfaceList = NetworkInterface.getNetworkInterfaces(); 156 while (netInterfaceList.hasMoreElements()) { 157 NetworkInterface ni = netInterfaceList.nextElement(); 158 Enumeration<InetAddress> addrList = ni.getInetAddresses(); 159 // iterate through host addresses and use each as hostname 160 while (addrList.hasMoreElements()) { 161 InetAddress addr = addrList.nextElement(); 162 if (addr.isLoopbackAddress() || addr.isLinkLocalAddress() || addr.isMulticastAddress()) { 163 continue; 164 } 165 String hostName = addr.getHostName(); 166 LOG.info("Found " + hostName + " on " + ni); 167 168 TEST_UTIL.getConfiguration().set(DNS.MASTER_HOSTNAME_KEY, hostName); 169 // "hbase.unsafe.regionserver.hostname" and 170 // "hbase.unsafe.regionserver.hostname.disable.master.reversedns" 171 // are mutually exclusive. Exception should be thrown if both are used. 172 TEST_UTIL.getConfiguration().set(DNS.UNSAFE_RS_HOSTNAME_KEY, hostName); 173 TEST_UTIL.getConfiguration() 174 .setBoolean(HRegionServer.UNSAFE_RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true); 175 try { 176 StartTestingClusterOption option = StartTestingClusterOption.builder() 177 .numMasters(NUM_MASTERS).numRegionServers(NUM_RS).numDataNodes(NUM_RS).build(); 178 TEST_UTIL.startMiniCluster(option); 179 } catch (Exception e) { 180 Throwable t1 = e.getCause(); 181 Throwable t2 = t1.getCause(); 182 assertTrue(t1.getMessage() + " - " + t2.getMessage(), 183 t2.getMessage().contains(HRegionServer.UNSAFE_RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY 184 + " and " + DNS.UNSAFE_RS_HOSTNAME_KEY + " are mutually exclusive")); 185 return; 186 } finally { 187 TEST_UTIL.shutdownMiniCluster(); 188 } 189 assertTrue("Failed to validate against conflict hostname configurations", false); 190 } 191 } 192 } 193 194 @Test 195 public void testRegionServerHostnameReportedToMaster() throws Exception { 196 TEST_UTIL.getConfiguration() 197 .setBoolean(HRegionServer.UNSAFE_RS_HOSTNAME_DISABLE_MASTER_REVERSEDNS_KEY, true); 198 StartTestingClusterOption option = StartTestingClusterOption.builder().numMasters(NUM_MASTERS) 199 .numRegionServers(NUM_RS).numDataNodes(NUM_RS).build(); 200 TEST_UTIL.startMiniCluster(option); 201 int expectedRS = NUM_RS; 202 try (ZKWatcher zkw = TEST_UTIL.getZooKeeperWatcher()) { 203 List<String> servers = ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode); 204 assertEquals(expectedRS, servers.size()); 205 } 206 } 207 208 private boolean ignoreNetworkInterface(NetworkInterface networkInterface) throws Exception { 209 return networkInterface == null || networkInterface.isLoopback() || networkInterface.isVirtual() 210 || !networkInterface.isUp(); 211 } 212 213 private List<NetworkInterface> getValidNetworkInterfaces() throws Exception { 214 List<NetworkInterface> validNetworkInterfaces = new ArrayList<>(); 215 Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); 216 while (interfaces.hasMoreElements()) { 217 NetworkInterface networkInterface = interfaces.nextElement(); 218 if (ignoreNetworkInterface(networkInterface)) { 219 continue; 220 } 221 validNetworkInterfaces.add(networkInterface); 222 } 223 return validNetworkInterfaces; 224 } 225}