Skip to content

Commit d37e2a9

Browse files
HBASE-28973 Support client access to HBase servers using IP in IPV6 env
1 parent 16d629f commit d37e2a9

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

hbase-common/src/main/java/org/apache/hadoop/hbase/ServerName.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
package org.apache.hadoop.hbase;
1919

2020
import java.io.Serializable;
21+
import java.io.UnsupportedEncodingException;
22+
import java.net.URLDecoder;
23+
import java.net.URLEncoder;
2124
import java.util.ArrayList;
2225
import java.util.Iterator;
2326
import java.util.List;
@@ -62,6 +65,12 @@ public class ServerName implements Comparable<ServerName>, Serializable {
6265
*/
6366
private static final short VERSION = 0;
6467
static final byte[] VERSION_BYTES = Bytes.toBytes(VERSION);
68+
private static final String COLON_ENCODED_VALUE = "%3a";
69+
70+
public static final String COLON = ":";
71+
72+
// IPV6 address length separated by COLON(:), eg: "0:0:0:0:0:0:0:1".split(colon).length
73+
private static final int IPV6_SPLIT_COLON_LENGTH = 8;
6574

6675
/**
6776
* What to use if no startcode supplied.
@@ -424,7 +433,49 @@ public static ServerName parseVersionedServerName(final byte[] versionedBytes) {
424433
* @return A ServerName instance.
425434
*/
426435
public static ServerName parseServerName(final String str) {
427-
return SERVERNAME_PATTERN.matcher(str).matches() ? valueOf(str) : valueOf(str, NON_STARTCODE);
436+
ServerName sn =
437+
SERVERNAME_PATTERN.matcher(str).matches() ? valueOf(str) : valueOf(str, NON_STARTCODE);
438+
String hostname = sn.getHostname();
439+
// if IPV6 address is in encoded format, need to check and validate its address length
440+
// eg: if address is like "0%3a0%3a0%3a0%3a0%3a0%3a0%3a0%3a1,16020,1720673488765" decode to
441+
// "0:0:0:0:0:0:0:1,16020,1720673488765"
442+
if (isIpv6ServerName(hostname, COLON_ENCODED_VALUE)) {
443+
try {
444+
hostname = URLDecoder.decode(sn.getHostname(), "UTF8");
445+
return ServerName.valueOf(hostname, sn.getPort(), sn.getStartCode());
446+
} catch (UnsupportedEncodingException e) {
447+
throw new IllegalArgumentException("Exception occurred while decoding server name", e);
448+
}
449+
}
450+
return sn;
451+
}
452+
453+
/**
454+
* Verify the ServerAddress is in IPV6 format or not
455+
* @param serverAddress IP address
456+
* @param addressSeparator IPV6 address separator
457+
* @return true if server address is in IPV6 format
458+
*/
459+
public static boolean isIpv6ServerName(String serverAddress, String addressSeparator) {
460+
return serverAddress.contains(addressSeparator)
461+
&& serverAddress.split(addressSeparator).length == IPV6_SPLIT_COLON_LENGTH;
462+
}
463+
464+
/**
465+
* Encode the Server Address
466+
* @param str Either an instance of {@link #toString()} or a "'&lt;hostname&gt;' ':'
467+
* '&lt;port&gt;'".
468+
* @return ServerName instance
469+
*/
470+
public static ServerName getEncodedServerName(final String str) {
471+
ServerName sn =
472+
SERVERNAME_PATTERN.matcher(str).matches() ? valueOf(str) : valueOf(str, NON_STARTCODE);
473+
try {
474+
return ServerName.valueOf(URLEncoder.encode(sn.getHostname(), "UTF8"), sn.getPort(),
475+
sn.getStartCode());
476+
} catch (UnsupportedEncodingException e) {
477+
throw new IllegalArgumentException("Exception occurred while encoding server name", e);
478+
}
428479
}
429480

430481
/** Returns true if the String follows the pattern of {@link #toString()}, false otherwise. */

hbase-server/src/main/java/org/apache/hadoop/hbase/wal/AbstractFSWALProvider.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,13 @@ public static boolean validateWALFilename(String filename) {
291291
* @return the relative WAL directory name, e.g. <code>.logs/1.example.org,60030,12345</code> if
292292
* <code>serverName</code> passed is <code>1.example.org,60030,12345</code>
293293
*/
294-
public static String getWALDirectoryName(final String serverName) {
294+
public static String getWALDirectoryName(String serverName) {
295+
// If ServerName is IPV6 address, then need to encode server address
296+
if (ServerName.isIpv6ServerName(serverName, ServerName.COLON)) {
297+
serverName = ServerName.getEncodedServerName(serverName).getServerName();
298+
}
295299
StringBuilder dirName = new StringBuilder(HConstants.HREGION_LOGDIR_NAME);
296-
dirName.append("/");
300+
dirName.append(Path.SEPARATOR);
297301
dirName.append(serverName);
298302
return dirName.toString();
299303
}
@@ -305,9 +309,13 @@ public static String getWALDirectoryName(final String serverName) {
305309
* @param serverName Server name formatted as described in {@link ServerName}
306310
* @return the relative WAL directory name
307311
*/
308-
public static String getWALArchiveDirectoryName(Configuration conf, final String serverName) {
312+
public static String getWALArchiveDirectoryName(Configuration conf, String serverName) {
309313
StringBuilder dirName = new StringBuilder(HConstants.HREGION_OLDLOGDIR_NAME);
310314
if (conf.getBoolean(SEPARATE_OLDLOGDIR, DEFAULT_SEPARATE_OLDLOGDIR)) {
315+
// If ServerName is IPV6 address, then need to encode server address
316+
if (ServerName.isIpv6ServerName(serverName, ServerName.COLON)) {
317+
serverName = ServerName.getEncodedServerName(serverName).getServerName();
318+
}
311319
dirName.append(Path.SEPARATOR);
312320
dirName.append(serverName);
313321
}

0 commit comments

Comments
 (0)