HBASE-14734 Prevent BindException when setting up MiniKdc.
Port for kdc service gets selected in the constructor, but we bind to it later in MiniKdc.start()-->MiniKdc.initKDCServer() --> KdcServer.start(). In meantime, some other service can capture the port which results in BindException. The solution here is to catch the exception and retry. Testing methodology: - Used python and intellij. - breakpoint on kdc.start(1), in catch block(2) and just after catch block(3). - used python to bind to the selected port on breakpoint 1 --> run the program --> stops at breakpoint 2 (catch block) - On breakpoint 1 and after 2 failures, close the port --> run the program --> skips catch block and goes to breakpoint 3. Change-Id: I4e06e69819d1ec9a0a7fa471bf017f3a72c75cb3
This commit is contained in:
parent
6a4c292a90
commit
593fb75083
|
@ -26,6 +26,7 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.BindException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
|
@ -40,6 +41,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
@ -48,6 +50,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
@ -102,6 +105,7 @@ import org.apache.hadoop.hbase.regionserver.RegionServerServices;
|
|||
import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;
|
||||
import org.apache.hadoop.hbase.regionserver.wal.MetricsWAL;
|
||||
import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
|
||||
import org.apache.hadoop.hbase.security.HBaseKerberosUtils;
|
||||
import org.apache.hadoop.hbase.security.User;
|
||||
import org.apache.hadoop.hbase.security.visibility.VisibilityLabelsCache;
|
||||
import org.apache.hadoop.hbase.tool.Canary;
|
||||
|
@ -128,6 +132,7 @@ import org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream;
|
|||
import org.apache.hadoop.mapred.JobConf;
|
||||
import org.apache.hadoop.mapred.MiniMRCluster;
|
||||
import org.apache.hadoop.mapred.TaskLog;
|
||||
import org.apache.hadoop.minikdc.MiniKdc;
|
||||
import org.apache.zookeeper.WatchedEvent;
|
||||
import org.apache.zookeeper.ZooKeeper;
|
||||
import org.apache.zookeeper.ZooKeeper.States;
|
||||
|
@ -4049,4 +4054,39 @@ public class HBaseTestingUtility extends HBaseCommonTestingUtility {
|
|||
int o = outputRowString.indexOf(HConstants.DELIMITER);
|
||||
return inputRowString.substring(0, i).equals(outputRowString.substring(0, o));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up {@link MiniKdc} for testing security.
|
||||
* Uses {@link HBaseKerberosUtils} to set the given keytab file as
|
||||
* {@link HBaseKerberosUtils#KRB_KEYTAB_FILE}.
|
||||
*/
|
||||
public MiniKdc setupMiniKdc(File keytabFile) throws Exception {
|
||||
Properties conf = MiniKdc.createConf();
|
||||
conf.put(MiniKdc.DEBUG, true);
|
||||
MiniKdc kdc = null;
|
||||
File dir = null;
|
||||
// There is time lag between selecting a port and trying to bind with it. It's possible that
|
||||
// another service captures the port in between which'll result in BindException.
|
||||
boolean bindException;
|
||||
int numTries = 0;
|
||||
do {
|
||||
try {
|
||||
bindException = false;
|
||||
dir = new File(getDataTestDir("kdc").toUri().getPath());
|
||||
kdc = new MiniKdc(conf, dir);
|
||||
kdc.start();
|
||||
} catch (BindException e) {
|
||||
FileUtils.deleteDirectory(dir); // clean directory
|
||||
numTries++;
|
||||
if (numTries == 3) {
|
||||
LOG.error("Failed setting up MiniKDC. Tried " + numTries + " times.");
|
||||
throw e;
|
||||
}
|
||||
LOG.error("BindException encountered when setting up MiniKdc. Trying again.");
|
||||
bindException = true;
|
||||
}
|
||||
} while (bindException);
|
||||
HBaseKerberosUtils.setKeytabFileForTesting(keytabFile.getAbsolutePath());
|
||||
return kdc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import java.net.URI;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -179,10 +178,7 @@ public class TestSaslFanOutOneBlockAsyncDFSOutput {
|
|||
public static void setUpBeforeClass() throws Exception {
|
||||
EVENT_LOOP_GROUP = new NioEventLoopGroup();
|
||||
TEST_UTIL.getConfiguration().setInt(DFS_CLIENT_SOCKET_TIMEOUT_KEY, READ_TIMEOUT_MS);
|
||||
Properties conf = MiniKdc.createConf();
|
||||
conf.put(MiniKdc.DEBUG, true);
|
||||
KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
|
||||
KDC.start();
|
||||
KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||
USERNAME = UserGroupInformation.getLoginUser().getShortUserName();
|
||||
PRINCIPAL = USERNAME + "/" + HOST;
|
||||
HTTP_PRINCIPAL = "HTTP/" + HOST;
|
||||
|
@ -190,7 +186,6 @@ public class TestSaslFanOutOneBlockAsyncDFSOutput {
|
|||
|
||||
setUpKeyProvider(TEST_UTIL.getConfiguration());
|
||||
setHdfsSecuredConfiguration(TEST_UTIL.getConfiguration());
|
||||
HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
|
||||
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
||||
HBaseKerberosUtils.setSecuredConfiguration(TEST_UTIL.getConfiguration());
|
||||
UserGroupInformation.setConfiguration(TEST_UTIL.getConfiguration());
|
||||
|
|
|
@ -37,7 +37,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.security.sasl.SaslException;
|
||||
|
||||
|
@ -106,13 +105,9 @@ public class TestSecureIPC {
|
|||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
Properties conf = MiniKdc.createConf();
|
||||
conf.put(MiniKdc.DEBUG, true);
|
||||
KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
|
||||
KDC.start();
|
||||
KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||
PRINCIPAL = "hbase/" + HOST;
|
||||
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL);
|
||||
HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
|
||||
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||
|
@ -56,13 +55,9 @@ public class TestUsersOperationsWithSecureHadoop {
|
|||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
Properties conf = MiniKdc.createConf();
|
||||
conf.put(MiniKdc.DEBUG, true);
|
||||
KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
|
||||
KDC.start();
|
||||
KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||
PRINCIPAL = "hbase/" + HOST;
|
||||
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL);
|
||||
HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
|
||||
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* The class for set up a security cluster with kerberos, hdfs, hbase.
|
||||
|
@ -85,19 +84,16 @@ public class SecureTestCluster {
|
|||
*/
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
Properties conf = MiniKdc.createConf();
|
||||
conf.put(MiniKdc.DEBUG, true);
|
||||
KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
|
||||
KDC.start();
|
||||
KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||
USERNAME = UserGroupInformation.getLoginUser().getShortUserName();
|
||||
PRINCIPAL = USERNAME + "/" + HOST;
|
||||
HTTP_PRINCIPAL = "HTTP/" + HOST;
|
||||
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL, HTTP_PRINCIPAL);
|
||||
TEST_UTIL.startMiniZKCluster();
|
||||
|
||||
HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
|
||||
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
||||
HBaseKerberosUtils.setSecuredConfiguration(TEST_UTIL.getConfiguration());
|
||||
|
||||
setHdfsSecuredConfiguration(TEST_UTIL.getConfiguration());
|
||||
UserGroupInformation.setConfiguration(TEST_UTIL.getConfiguration());
|
||||
TEST_UTIL.getConfiguration().setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
|
||||
|
|
Loading…
Reference in New Issue