diff --git a/hudi-common/src/main/java/org/apache/hudi/common/util/NetworkUtils.java b/hudi-common/src/main/java/org/apache/hudi/common/util/NetworkUtils.java index 29c42e3ea..329c1090e 100644 --- a/hudi-common/src/main/java/org/apache/hudi/common/util/NetworkUtils.java +++ b/hudi-common/src/main/java/org/apache/hudi/common/util/NetworkUtils.java @@ -22,11 +22,14 @@ import org.apache.hudi.exception.HoodieException; import java.io.IOException; import java.net.DatagramSocket; +import java.net.Inet4Address; import java.net.InetAddress; -import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; -import java.util.Enumeration; +import java.net.UnknownHostException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; /** * A utility class for network. @@ -34,28 +37,51 @@ import java.util.Enumeration; public class NetworkUtils { public static synchronized String getHostname() { - try { - Enumeration networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces(); - while (networkInterfaceEnumeration.hasMoreElements()) { - for (InterfaceAddress interfaceAddress : networkInterfaceEnumeration.nextElement().getInterfaceAddresses()) { - InetAddress address = interfaceAddress.getAddress(); - if (!address.isLinkLocalAddress() && !address.isLoopbackAddress() && !address.isAnyLocalAddress()) { - return address.getHostAddress(); - } - } - } - } catch (SocketException e) { - throw new HoodieException("Unable to find server port", e); - } - - // fallback + InetAddress localAddress; try (DatagramSocket s = new DatagramSocket()) { // see https://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java // for details. s.connect(InetAddress.getByName("8.8.8.8"), 10002); - return s.getLocalAddress().getHostAddress(); + localAddress = s.getLocalAddress(); + if (validAddress(localAddress)) { + return localAddress.getHostAddress(); + } } catch (IOException e) { throw new HoodieException("Unable to find server port", e); } + + // fallback + try { + List activeNetworkIFs = Collections.list(NetworkInterface.getNetworkInterfaces()); + // On unix-like system, getNetworkInterfaces returns ifs in reverse order + // compared to ifconfig output order, + // pick ip address following system output order. + Collections.reverse(activeNetworkIFs); + for (NetworkInterface ni : activeNetworkIFs) { + List addresses = Collections.list(ni.getInetAddresses()).stream() + .filter(NetworkUtils::validAddress) + .collect(Collectors.toList()); + if (addresses.size() > 0) { + // IPv4 has higher priority + InetAddress address = addresses.stream() + .filter(addr -> addr instanceof Inet4Address).findAny() + .orElse(addresses.get(0)); + try { + // Inet6Address.toHostName may add interface at the end if it knows about it + return InetAddress.getByAddress(address.getAddress()).getHostAddress(); + } catch (UnknownHostException e) { + throw new HoodieException("Unable to fetch raw IP address for: " + address); + } + } + } + + return localAddress.getHostAddress(); + } catch (SocketException e) { + throw new HoodieException("Unable to find server port", e); + } + } + + private static boolean validAddress(InetAddress address) { + return !(address.isLinkLocalAddress() || address.isLoopbackAddress() || address.isAnyLocalAddress()); } }