HDFS-12910. Secure Datanode Starter should log the port when it fails to bind. Contributed by Stephen O'Donnell and Nanda kumar.
This commit is contained in:
parent
95d4ec7fc0
commit
e1cb278cd0
|
@ -32,6 +32,7 @@ import org.apache.hadoop.security.UserGroupInformation;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.net.BindException;
|
||||
|
||||
/**
|
||||
* Utility class to start a datanode in a secure cluster, first obtaining
|
||||
|
@ -102,7 +103,13 @@ public class SecureDataNodeStarter implements Daemon {
|
|||
|
||||
ServerSocket ss = (socketWriteTimeout > 0) ?
|
||||
ServerSocketChannel.open().socket() : new ServerSocket();
|
||||
try {
|
||||
ss.bind(streamingAddr, backlogLength);
|
||||
} catch (BindException e) {
|
||||
BindException newBe = appendMessageToBindException(e,
|
||||
streamingAddr.toString());
|
||||
throw newBe;
|
||||
}
|
||||
|
||||
// Check that we got the port we need
|
||||
if (ss.getLocalPort() != streamingAddr.getPort()) {
|
||||
|
@ -126,13 +133,20 @@ public class SecureDataNodeStarter implements Daemon {
|
|||
if (policy.isHttpEnabled()) {
|
||||
httpChannel = ServerSocketChannel.open();
|
||||
InetSocketAddress infoSocAddr = DataNode.getInfoAddr(conf);
|
||||
try {
|
||||
httpChannel.socket().bind(infoSocAddr);
|
||||
} catch (BindException e) {
|
||||
BindException newBe = appendMessageToBindException(e,
|
||||
infoSocAddr.toString());
|
||||
throw newBe;
|
||||
}
|
||||
InetSocketAddress localAddr = (InetSocketAddress) httpChannel.socket()
|
||||
.getLocalSocketAddress();
|
||||
|
||||
if (localAddr.getPort() != infoSocAddr.getPort()) {
|
||||
throw new RuntimeException("Unable to bind on specified info port in secure " +
|
||||
"context. Needed " + streamingAddr.getPort() + ", got " + ss.getLocalPort());
|
||||
throw new RuntimeException("Unable to bind on specified info port in " +
|
||||
"secure context. Needed " + infoSocAddr.getPort() + ", got " +
|
||||
ss.getLocalPort());
|
||||
}
|
||||
System.err.println("Successfully obtained privileged resources (streaming port = "
|
||||
+ ss + " ) (http listener port = " + localAddr.getPort() +")");
|
||||
|
@ -149,4 +163,11 @@ public class SecureDataNodeStarter implements Daemon {
|
|||
return new SecureResources(ss, httpChannel);
|
||||
}
|
||||
|
||||
private static BindException appendMessageToBindException(BindException e,
|
||||
String msg) {
|
||||
BindException newBe = new BindException(e.getMessage() + " " + msg);
|
||||
newBe.initCause(e.getCause());
|
||||
newBe.setStackTrace(e.getStackTrace());
|
||||
return newBe;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,14 @@ import org.apache.hadoop.hdfs.DFSConfigKeys;
|
|||
import org.apache.hadoop.hdfs.HdfsConfiguration;
|
||||
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
||||
import static org.apache.hadoop.security.SecurityUtilTestHelper.isExternalKdcRunning;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import java.net.BindException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
/**
|
||||
* This test starts a 1 NameNode 1 DataNode MiniDFSCluster with
|
||||
|
@ -48,16 +53,18 @@ import org.junit.Test;
|
|||
* dfs.datanode.keytab.file
|
||||
*/
|
||||
public class TestStartSecureDataNode {
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
final static private int NUM_OF_DATANODES = 1;
|
||||
|
||||
@Before
|
||||
public void testExternalKdcRunning() {
|
||||
private void testExternalKdcRunning() {
|
||||
// Tests are skipped if external KDC is not running.
|
||||
Assume.assumeTrue(isExternalKdcRunning());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecureNameNode() throws Exception {
|
||||
testExternalKdcRunning();
|
||||
MiniDFSCluster cluster = null;
|
||||
try {
|
||||
String nnPrincipal =
|
||||
|
@ -104,4 +111,55 @@ public class TestStartSecureDataNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test doesn't require KDC or other security settings as it expects
|
||||
* {@link java.net.BindException}. Testing is done with unprivileged port
|
||||
* for {@code dfs.datanode.address}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testStreamingAddrBindException() throws Exception {
|
||||
ServerSocket ss = new ServerSocket();
|
||||
try {
|
||||
ss.bind(new InetSocketAddress("localhost", 0));
|
||||
thrown.expect(BindException.class);
|
||||
thrown.expectMessage("localhost/127.0.0.1:" + ss.getLocalPort());
|
||||
|
||||
Configuration conf = new HdfsConfiguration();
|
||||
conf.set(DFSConfigKeys.DFS_DATANODE_ADDRESS_KEY,
|
||||
"localhost:" + ss.getLocalPort());
|
||||
SecureDataNodeStarter.getSecureResources(conf);
|
||||
} finally {
|
||||
ss.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test doesn't require KDC or other security settings as it expects
|
||||
* {@link java.net.BindException}. Testing is done with unprivileged port
|
||||
* for {@code dfs.datanode.http.address}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testWebServerAddrBindException() throws Exception {
|
||||
ServerSocket ss = new ServerSocket();
|
||||
try {
|
||||
ss.bind(new InetSocketAddress("localhost", 0));
|
||||
thrown.expect(BindException.class);
|
||||
thrown.expectMessage("localhost/127.0.0.1:" + ss.getLocalPort());
|
||||
|
||||
Configuration conf = new HdfsConfiguration();
|
||||
conf.set(DFSConfigKeys.DFS_DATANODE_ADDRESS_KEY,
|
||||
"localhost:" + NetUtils.getFreeSocketPort());
|
||||
conf.set(DFSConfigKeys.DFS_DATANODE_HTTP_ADDRESS_KEY,
|
||||
"localhost:" + ss.getLocalPort());
|
||||
|
||||
SecureDataNodeStarter.getSecureResources(conf);
|
||||
} finally {
|
||||
ss.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue