package tachyon.util;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;
import org.apache.log4j.Logger;
import tachyon.Constants;
/**
* Common network utilities shared by all components in Tachyon.
*/
public class NetworkUtils {
private static final Logger LOG = Logger.getLogger(Constants.LOGGER_TYPE);
/**
* @return the local host name, which is not based on a loopback ip address.
*/
public static String getLocalHostName() {
try {
return InetAddress.getByName(getLocalIpAddress()).getCanonicalHostName();
} catch (UnknownHostException e) {
LOG.error(e);
CommonUtils.runtimeException(e);
}
return null;
}
/**
* @return the local ip address, which is not a loopback address.
*/
public static String getLocalIpAddress() {
try {
InetAddress address = InetAddress.getLocalHost();
System.out.println("address " + address.toString() + " " + address.isLoopbackAddress() + " "
+ address.getHostAddress() + " " + address.getHostName());
if (address.isLoopbackAddress()) {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface ni = networkInterfaces.nextElement();
Enumeration<InetAddress> addresses = ni.getInetAddresses();
while (addresses.hasMoreElements()) {
address = addresses.nextElement();
if (!address.isLinkLocalAddress() && !address.isLoopbackAddress()
&& (address instanceof Inet4Address)) {
return address.getHostAddress();
}
}
}
LOG.warn("Your hostname, " + InetAddress.getLocalHost().getHostName() + " resolves to"
+ " a loopback address: " + address.getHostAddress() + ", but we couldn't find any"
+ " external IP address!");
}
return address.getHostAddress();
} catch (IOException e) {
LOG.error(e);
CommonUtils.runtimeException(e);
}
return null;
}
/**
* Replace and resolve the hostname in a given address or path string.
*
* @param addr
* an address or path string, e.g., "hdfs://host:port/dir", "file:///dir", "/dir".
* @return an address or path string with hostname resolved, or the original path intact if
* no hostname is embedded, or null if the given path is null or empty.
* @throws UnknownHostException
* if the hostname cannot be resolved.
*/
public static String replaceHostName(String addr) throws UnknownHostException {
if (addr == null || addr.isEmpty()) {
return null;
}
if (addr.contains("://")) {
int idx = addr.indexOf("://");
String prefix = addr.substring(0, idx + 3);
String rest = addr.substring(idx + 3);
if (rest.contains(":")) {
// case host:port/dir or host:port or host:port/
int idx2 = rest.indexOf(":");
String hostname = rest.substring(0, idx2);
hostname = resolveHostName(hostname);
String suffix = rest.substring(idx2);
return prefix + hostname + suffix;
} else if (rest.contains(Constants.PATH_SEPARATOR)) {
// case host/dir or /dir or host/
int idx2 = rest.indexOf(Constants.PATH_SEPARATOR);
if (idx2 > 0) {
String hostname = rest.substring(0, idx2);
hostname = resolveHostName(hostname);
String suffix = rest.substring(idx2);
return prefix + hostname + suffix;
}
} else {
// case host is rest of the path
return prefix + resolveHostName(rest);
}
}
return addr;
}
/**
* Resolve a given hostname by a canonical hostname. When a hostname alias (e.g., those
* specified in /etc/hosts) is given, the alias may not be resolvable on other hosts in a
* cluster unless the same alias is defined there. In this situation, loadufs would break.
*
* @param hostname
* the input hostname, which could be an alias.
* @return the canonical form of the hostname, or null if it is null or empty.
* @throws UnknownHostException
* if the given hostname cannot be resolved.
*/
public static String resolveHostName(String hostname) throws UnknownHostException {
if (hostname == null || hostname.isEmpty()) {
return null;
}
return InetAddress.getByName(hostname).getCanonicalHostName();
}
}