Skip to content

Commit fde6425

Browse files
committed
HADOOP-17843. Support IPv6 with IP for internal & external communication.
1 parent c0f0b33 commit fde6425

File tree

6 files changed

+63
-14
lines changed
  • hadoop-common-project/hadoop-common/src
  • hadoop-hdfs-project/hadoop-hdfs/src
  • hadoop-yarn-project/hadoop-yarn
    • hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp
    • hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy

6 files changed

+63
-14
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/NetUtils.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import javax.net.SocketFactory;
4747

4848
import org.apache.commons.lang3.StringUtils;
49+
import org.apache.commons.lang3.tuple.Pair;
4950
import org.apache.hadoop.security.AccessControlException;
5051
import org.apache.hadoop.thirdparty.com.google.common.cache.Cache;
5152
import org.apache.hadoop.thirdparty.com.google.common.cache.CacheBuilder;
@@ -1218,4 +1219,30 @@ public static InetAddress bindToLocalAddress(InetAddress localAddr, boolean
12181219
}
12191220
return null;
12201221
}
1222+
1223+
/**
1224+
* Parse the given address into IP & Port number pair.
1225+
* @param bindAddress IP Address to parse
1226+
* @return Pair of IP-Address & Port number.
1227+
*/
1228+
public static Pair<String, Integer> parseAddress2IpAndPort(
1229+
String bindAddress) {
1230+
String[] parts = org.apache.hadoop.util.StringUtils
1231+
.split(bindAddress, ':');
1232+
Pair <String, Integer> pair = null;
1233+
//If bind address is IPv6
1234+
if (parts.length > 2) {
1235+
String target = bindAddress;
1236+
int i = target.lastIndexOf(":");
1237+
String ipAddress = '['+target.substring(0, i)+']';
1238+
pair = Pair.of(ipAddress, Integer.parseInt(parts[parts.length-1]));
1239+
} else if (parts.length == 2) {
1240+
//Given address is IPv4 Address
1241+
pair = Pair.of(parts[0], Integer.parseInt(parts[1]));
1242+
} else {
1243+
//No port specified, consider port number as 0
1244+
pair = Pair.of(bindAddress, 0);
1245+
}
1246+
return pair;
1247+
}
12211248
}

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestNetUtils.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.concurrent.TimeUnit;
4040

4141
import org.apache.commons.lang3.StringUtils;
42+
import org.apache.commons.lang3.tuple.Pair;
4243
import org.apache.hadoop.conf.Configuration;
4344
import org.apache.hadoop.io.IOUtils;
4445
import org.apache.hadoop.security.KerberosAuthException;
@@ -854,4 +855,19 @@ public void testCreateSocketAddressWithIPV6() throws Throwable {
854855
assertEquals(ipv6Address, addr.getHostName());
855856
assertEquals(12345, addr.getPort());
856857
}
858+
859+
@Test
860+
public void testParseAddress2IpAndPort() {
861+
String ip = "10.10.10.10";
862+
Pair<String, Integer> pair = NetUtils.parseAddress2IpAndPort(ip);
863+
assertEquals(pair.getLeft(), ip);
864+
assertEquals(pair.getRight().longValue(), 0);
865+
pair = NetUtils.parseAddress2IpAndPort(ip+":8080");
866+
assertEquals(pair.getLeft(), ip);
867+
assertEquals(pair.getRight().longValue(), 8080);
868+
ip = "10:10:10:10:10:10:10:10";
869+
pair = NetUtils.parseAddress2IpAndPort(ip+":8080");
870+
assertEquals(pair.getLeft(), '['+ip+']');
871+
assertEquals(pair.getRight().longValue(), 8080);
872+
}
857873
}

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,10 @@ public static URI getInfoServer(InetSocketAddress namenodeAddr,
10301030
authority = substituteForWildcardAddress(authority,
10311031
namenodeAddr.getHostName());
10321032
}
1033+
if (!authority.startsWith("[")
1034+
&& StringUtils.countMatches(authority, ":") > 2) {
1035+
authority = NetUtils.normalizeV6Address(authority);
1036+
}
10331037
return URI.create(scheme + "://" + authority);
10341038
}
10351039

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,13 @@ public void testGetInfoServer() throws IOException, URISyntaxException {
513513
assertEquals(
514514
URI.create("http://localhost:" + DFS_NAMENODE_HTTP_PORT_DEFAULT),
515515
httpAddress);
516+
517+
//Verify IPv6 Address
518+
httpAddress = DFSUtil.getInfoServer(new InetSocketAddress(
519+
"::0", 8020), conf, "http");
520+
assertEquals(
521+
URI.create("http://[0:0:0:0:0:0:0:0]:" + DFS_NAMENODE_HTTP_PORT_DEFAULT),
522+
httpAddress);
516523
}
517524

518525
@Test

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@
3232

3333
import javax.servlet.http.HttpServlet;
3434

35-
import org.apache.commons.lang3.StringUtils;
35+
import org.apache.commons.lang3.tuple.Pair;
3636
import org.apache.hadoop.classification.InterfaceAudience;
3737
import org.apache.hadoop.conf.Configuration;
3838
import org.apache.hadoop.conf.Configuration.IntegerRanges;
3939
import org.apache.hadoop.http.HttpConfig.Policy;
4040
import org.apache.hadoop.http.HttpServer2;
41+
import org.apache.hadoop.net.NetUtils;
4142
import org.apache.hadoop.security.UserGroupInformation;
4243
import org.apache.hadoop.security.authorize.AccessControlList;
4344
import org.apache.hadoop.security.http.RestCsrfPreventionFilter;
@@ -118,12 +119,8 @@ static class ServletStruct {
118119
}
119120

120121
public Builder<T> at(String bindAddress) {
121-
String[] parts = StringUtils.split(bindAddress, ':');
122-
if (parts.length == 2) {
123-
int port = Integer.parseInt(parts[1]);
124-
return at(parts[0], port, port == 0);
125-
}
126-
return at(bindAddress, 0, true);
122+
Pair<String, Integer> pair = NetUtils.parseAddress2IpAndPort(bindAddress);
123+
return at(pair.getLeft(), pair.getRight(), pair.getRight() == 0);
127124
}
128125

129126
public Builder<T> at(int port) {

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxy.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@
2222
import java.net.URI;
2323

2424
import com.google.common.net.HostAndPort;
25+
import org.apache.commons.lang3.tuple.Pair;
2526
import org.apache.hadoop.conf.Configuration;
2627
import org.apache.hadoop.http.HttpServer2;
28+
import org.apache.hadoop.net.NetUtils;
2729
import org.apache.hadoop.security.authorize.AccessControlList;
2830
import org.apache.hadoop.service.AbstractService;
29-
import org.apache.hadoop.util.StringUtils;
3031
import org.apache.hadoop.yarn.conf.YarnConfiguration;
3132
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
3233
import org.apache.hadoop.yarn.webapp.util.WebAppUtils;
@@ -79,12 +80,9 @@ protected void serviceInit(Configuration conf) throws Exception {
7980
" is not set so the proxy will not run.");
8081
}
8182

82-
String[] parts = StringUtils.split(bindAddress, ':');
83-
port = 0;
84-
if (parts.length == 2) {
85-
bindAddress = parts[0];
86-
port = Integer.parseInt(parts[1]);
87-
}
83+
Pair<String, Integer> pair = NetUtils.parseAddress2IpAndPort(bindAddress);
84+
bindAddress = pair.getLeft();
85+
port = pair.getRight();
8886

8987
String bindHost = conf.getTrimmed(YarnConfiguration.PROXY_BIND_HOST, null);
9088
if (bindHost != null) {

0 commit comments

Comments
 (0)