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
23c5ea39bd
commit
e7e660d5b2
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.net.BindException;
|
||||||
import java.net.DatagramSocket;
|
import java.net.DatagramSocket;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
|
@ -36,12 +37,14 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.lang.RandomStringUtils;
|
import org.apache.commons.lang.RandomStringUtils;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -94,6 +97,7 @@ import org.apache.hadoop.hbase.regionserver.RegionServerServices;
|
||||||
import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;
|
import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;
|
||||||
import org.apache.hadoop.hbase.regionserver.wal.MetricsWAL;
|
import org.apache.hadoop.hbase.regionserver.wal.MetricsWAL;
|
||||||
import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
|
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.User;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityLabelsCache;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityLabelsCache;
|
||||||
import org.apache.hadoop.hbase.tool.Canary;
|
import org.apache.hadoop.hbase.tool.Canary;
|
||||||
|
@ -121,6 +125,7 @@ import org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream;
|
||||||
import org.apache.hadoop.mapred.JobConf;
|
import org.apache.hadoop.mapred.JobConf;
|
||||||
import org.apache.hadoop.mapred.MiniMRCluster;
|
import org.apache.hadoop.mapred.MiniMRCluster;
|
||||||
import org.apache.hadoop.mapred.TaskLog;
|
import org.apache.hadoop.mapred.TaskLog;
|
||||||
|
import org.apache.hadoop.minikdc.MiniKdc;
|
||||||
import org.apache.zookeeper.KeeperException;
|
import org.apache.zookeeper.KeeperException;
|
||||||
import org.apache.zookeeper.KeeperException.NodeExistsException;
|
import org.apache.zookeeper.KeeperException.NodeExistsException;
|
||||||
import org.apache.zookeeper.WatchedEvent;
|
import org.apache.zookeeper.WatchedEvent;
|
||||||
|
@ -4214,4 +4219,40 @@ public class HBaseTestingUtility extends HBaseCommonTestingUtility {
|
||||||
}
|
}
|
||||||
return supportedAlgos.toArray(new Algorithm[supportedAlgos.size()]);
|
return supportedAlgos.toArray(new Algorithm[supportedAlgos.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,13 +141,9 @@ public abstract class AbstractTestSecureIPC {
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUp() throws Exception {
|
public static void setUp() throws Exception {
|
||||||
Properties conf = MiniKdc.createConf();
|
KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||||
conf.put(MiniKdc.DEBUG, true);
|
|
||||||
KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
|
|
||||||
KDC.start();
|
|
||||||
PRINCIPAL = "hbase/" + HOST;
|
PRINCIPAL = "hbase/" + HOST;
|
||||||
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL);
|
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL);
|
||||||
HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
|
|
||||||
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
|
@ -55,13 +54,9 @@ public class TestUsersOperationsWithSecureHadoop {
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUp() throws Exception {
|
public static void setUp() throws Exception {
|
||||||
Properties conf = MiniKdc.createConf();
|
KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||||
conf.put(MiniKdc.DEBUG, true);
|
|
||||||
KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
|
|
||||||
KDC.start();
|
|
||||||
PRINCIPAL = "hbase/" + HOST;
|
PRINCIPAL = "hbase/" + HOST;
|
||||||
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL);
|
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL);
|
||||||
HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
|
|
||||||
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class for set up a security cluster with kerberos, hdfs, hbase.
|
* The class for set up a security cluster with kerberos, hdfs, hbase.
|
||||||
|
@ -85,19 +84,16 @@ public class SecureTestCluster {
|
||||||
*/
|
*/
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUp() throws Exception {
|
public static void setUp() throws Exception {
|
||||||
Properties conf = MiniKdc.createConf();
|
KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||||
conf.put(MiniKdc.DEBUG, true);
|
|
||||||
KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
|
|
||||||
KDC.start();
|
|
||||||
USERNAME = UserGroupInformation.getLoginUser().getShortUserName();
|
USERNAME = UserGroupInformation.getLoginUser().getShortUserName();
|
||||||
PRINCIPAL = USERNAME + "/" + HOST;
|
PRINCIPAL = USERNAME + "/" + HOST;
|
||||||
HTTP_PRINCIPAL = "HTTP/" + HOST;
|
HTTP_PRINCIPAL = "HTTP/" + HOST;
|
||||||
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL, HTTP_PRINCIPAL);
|
KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL, HTTP_PRINCIPAL);
|
||||||
TEST_UTIL.startMiniZKCluster();
|
TEST_UTIL.startMiniZKCluster();
|
||||||
|
|
||||||
HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
|
|
||||||
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
|
||||||
HBaseKerberosUtils.setSecuredConfiguration(TEST_UTIL.getConfiguration());
|
HBaseKerberosUtils.setSecuredConfiguration(TEST_UTIL.getConfiguration());
|
||||||
|
|
||||||
setHdfsSecuredConfiguration(TEST_UTIL.getConfiguration());
|
setHdfsSecuredConfiguration(TEST_UTIL.getConfiguration());
|
||||||
UserGroupInformation.setConfiguration(TEST_UTIL.getConfiguration());
|
UserGroupInformation.setConfiguration(TEST_UTIL.getConfiguration());
|
||||||
TEST_UTIL.getConfiguration().setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
|
TEST_UTIL.getConfiguration().setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
|
||||||
|
|
Loading…
Reference in New Issue