From 5e84997f2ffdbcf5f849d70c30ddbe2db4039ca4 Mon Sep 17 00:00:00 2001 From: maoling Date: Fri, 12 Oct 2018 17:15:41 +0800 Subject: [PATCH] HBASE-13468 hbase.zookeeper.quorum supports ipv6 address Signed-off-by: tedyu --- hbase-common/pom.xml | 5 +++ .../hadoop/hbase/zookeeper/ZKConfig.java | 31 +++++++++++++++++-- hbase-shaded/pom.xml | 4 +++ .../hbase/zookeeper/TestZKMainServer.java | 27 ++++++++++++++++ pom.xml | 6 ++++ 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/hbase-common/pom.xml b/hbase-common/pom.xml index 0aaccb89e39..7d7deefbf46 100644 --- a/hbase-common/pom.xml +++ b/hbase-common/pom.xml @@ -211,6 +211,11 @@ commons-io compile + + commons-validator + commons-validator + compile + com.google.protobuf protobuf-java diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKConfig.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKConfig.java index f324ec68cf5..98827772040 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKConfig.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKConfig.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.Map.Entry; import java.util.Properties; +import org.apache.commons.validator.routines.InetAddressValidator; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.util.StringUtils; @@ -146,12 +147,36 @@ public final class ZKConfig { public static String buildZKQuorumServerString(String[] serverHosts, String clientPort) { StringBuilder quorumStringBuilder = new StringBuilder(); String serverHost; + InetAddressValidator validator = new InetAddressValidator(); for (int i = 0; i < serverHosts.length; ++i) { - if (serverHosts[i].contains(":")) { - serverHost = serverHosts[i]; // just use the port specified from the input + if (serverHosts[i].startsWith("[")) { + int index = serverHosts[i].indexOf("]"); + if (index < 0) { + throw new IllegalArgumentException(serverHosts[i] + + " starts with '[' but has no matching ']:'"); + } + if (index + 2 == serverHosts[i].length()) { + throw new IllegalArgumentException(serverHosts[i] + + " doesn't have a port after colon"); + } + //check the IPv6 address e.g. [2001:db8::1] + String serverHostWithoutBracket = serverHosts[i].substring(1, index); + if (!validator.isValidInet6Address(serverHostWithoutBracket)) { + throw new IllegalArgumentException(serverHosts[i] + + " is not a valid IPv6 address"); + } + serverHost = serverHosts[i]; + if ((index + 1 == serverHosts[i].length())) { + serverHost = serverHosts[i] + ":" + clientPort; + } } else { - serverHost = serverHosts[i] + ":" + clientPort; + if (serverHosts[i].contains(":")) { + serverHost = serverHosts[i]; // just use the port specified from the input + } else { + serverHost = serverHosts[i] + ":" + clientPort; + } } + if (i > 0) { quorumStringBuilder.append(','); } diff --git a/hbase-shaded/pom.xml b/hbase-shaded/pom.xml index 29ecc1e4fe9..92170c818fc 100644 --- a/hbase-shaded/pom.xml +++ b/hbase-shaded/pom.xml @@ -338,6 +338,10 @@ + + org.apache.commons.validator + ${shaded.prefix}.org.apache.commons.validator + org.apache.commons.beanutils ${shaded.prefix}.org.apache.commons.beanutils diff --git a/hbase-zookeeper/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKMainServer.java b/hbase-zookeeper/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKMainServer.java index d1c18d3548e..5680c78df23 100644 --- a/hbase-zookeeper/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKMainServer.java +++ b/hbase-zookeeper/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKMainServer.java @@ -28,6 +28,7 @@ import org.apache.hadoop.hbase.HBaseZKTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.testclassification.SmallTests; import org.apache.hadoop.hbase.testclassification.ZKTests; +import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -121,5 +122,31 @@ public class TestZKMainServer { c.set("hbase.zookeeper.quorum", "example1.com:5678,example2.com:9012,example3.com"); ensemble = parser.parse(c); assertEquals(ensemble, "example1.com:5678,example2.com:9012,example3.com:" + port); + + // multiple servers(IPv6) with its own port + c.set("hbase.zookeeper.quorum", "[2001:db8:1::242:ac11:2]:2181," + + "[2001:db8:1::242:ac11:3]:5678"); + ensemble = parser.parse(c); + assertEquals("[2001:db8:1::242:ac11:2]:2181," + + "[2001:db8:1::242:ac11:3]:5678", ensemble); + + // some servers(IPv6) without its own port, which will be assigned the default client port + c.set("hbase.zookeeper.quorum", "[1001:db8:1::242:ac11:8], [2001:db8:1::242:df23:2]:9876," + + "[2001:db8:1::242:ac11:3]:5678"); + ensemble = parser.parse(c); + assertEquals("[1001:db8:1::242:ac11:8]:1234, [2001:db8:1::242:df23:2]:9876," + + "[2001:db8:1::242:ac11:3]:5678", ensemble); + + //a bad case + try { + // some servers(IPv6) with an invaild Ipv6 address in it + c.set("hbase.zookeeper.quorum", "[1001:db8:1::242:ac11:8], [2001:db8:1::242:df23:2]:9876," + + "[1001:db8:1::242:ac11:8:89:67]:5678"); + ensemble = parser.parse(c); + Assert.fail("IPv6 address should be 8 groups."); + } catch (IllegalArgumentException e) { + //expected + } + } } diff --git a/pom.xml b/pom.xml index da6de1d039d..3ace2e0cad0 100755 --- a/pom.xml +++ b/pom.xml @@ -1466,6 +1466,7 @@ 0.5.0 1.7.7 1.10 + 1.6 2.5 3.6 @@ -1919,6 +1920,11 @@ commons-codec ${commons-codec.version} + + commons-validator + commons-validator + ${commons-validator.version} + commons-io commons-io