Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion utils/src/main/java/com/cloud/utils/net/NetUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ public static String getDefaultHostIp() {
return null;
}

if (nic == null) {
LOGGER.warn("Unable to find a network interface named [{}], cannot determine the default host IP.", pubNic);
return null;
}

String[] info = null;
try {
info = NetUtils.getNetworkParams(nic);
Expand Down Expand Up @@ -295,6 +300,11 @@ public static List<String> getAllDefaultNicIps() {
return addrs;
}

if (nic == null) {
LOGGER.warn("Unable to find a network interface named [{}], no default NIC IPs will be returned.", pubNic);
return addrs;
}

for (InterfaceAddress address : nic.getInterfaceAddresses()) {
addrs.add(address.getAddress().getHostAddress().split("%")[0]);
}
Expand All @@ -306,7 +316,25 @@ public static String getDefaultEthDevice() {
final String defDev = Script.runSimpleBashScript("/sbin/route -n get default 2> /dev/null | grep interface | awk '{print $2}'");
return defDev;
}
return Script.runSimpleBashScript("ip route show default 0.0.0.0/0 | head -1 | awk '{print $5}'");
final String defaultIp4Device = getDefaultEthDevice(false);
if (defaultIp4Device != null) {
return defaultIp4Device;
}
LOGGER.debug("No IPv4 default route found, falling back to the IPv6 default route to determine the default network device.");
return getDefaultEthDevice(true);
}

/**
* Returns the name of the network device used by the IPv4 or IPv6 default route, or null when there is no such
* default route.
*
* An IPv4 default route is not a requirement, a host can be IPv6-only or have IPv4 connectivity without a default
* route, therefore both address families are looked up separately.
*/
protected static String getDefaultEthDevice(final boolean ipv6) {
final String command = String.format("ip -%d route show default | awk '{for (i = 1; i < NF; i++) if ($i == \"dev\") {print $(i + 1); exit}}'",
ipv6 ? 6 : 4);
return Script.runSimpleBashScript(command);
}

public static String getLocalIPString() {
Expand Down
38 changes: 38 additions & 0 deletions utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@
import java.util.TreeSet;
import java.util.stream.Collectors;

import org.apache.commons.lang3.SystemUtils;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;

import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils.SupersetOrSubset;
import com.cloud.utils.script.Script;
import com.googlecode.ipv6.IPv6Address;
import com.googlecode.ipv6.IPv6Network;

Expand Down Expand Up @@ -748,6 +751,41 @@ public void testAllIpsOfDefaultNic() {
}
}

@Test
public void testAllIpsOfDefaultNicWhenDeviceDoesNotExist() {
try (MockedStatic<Script> scriptMocked = Mockito.mockStatic(Script.class)) {
scriptMocked.when(() -> Script.runSimpleBashScript(Mockito.anyString())).thenReturn("nonexistent0");
Assert.assertTrue(NetUtils.getAllDefaultNicIps().isEmpty());
}
}

@Test
public void testAllIpsOfDefaultNicWithoutDefaultRoute() {
try (MockedStatic<Script> scriptMocked = Mockito.mockStatic(Script.class)) {
scriptMocked.when(() -> Script.runSimpleBashScript(Mockito.anyString())).thenReturn(null);
Assert.assertTrue(NetUtils.getAllDefaultNicIps().isEmpty());
}
}

@Test
public void testGetDefaultEthDeviceFallsBackToIpv6() {
Assume.assumeFalse(SystemUtils.IS_OS_MAC);
try (MockedStatic<Script> scriptMocked = Mockito.mockStatic(Script.class)) {
scriptMocked.when(() -> Script.runSimpleBashScript(Mockito.contains("ip -4"))).thenReturn(null);
scriptMocked.when(() -> Script.runSimpleBashScript(Mockito.contains("ip -6"))).thenReturn("eth0");
Assert.assertEquals("eth0", NetUtils.getDefaultEthDevice());
}
}

@Test
public void testGetDefaultEthDevicePrefersIpv4() {
Assume.assumeFalse(SystemUtils.IS_OS_MAC);
try (MockedStatic<Script> scriptMocked = Mockito.mockStatic(Script.class)) {
scriptMocked.when(() -> Script.runSimpleBashScript(Mockito.contains("ip -4"))).thenReturn("eth0");
Assert.assertEquals("eth0", NetUtils.getDefaultEthDevice());
}
}

@Test
public void testIsIPv6EUI64() {
assertTrue(NetUtils.isIPv6EUI64("fe80::5054:8fff:fe9f:af61"));
Expand Down
Loading