Skip to content

Commit ab914bf

Browse files
Do live host vddk support check during import operation
1 parent 90ddb19 commit ab914bf

File tree

6 files changed

+92
-62
lines changed

6 files changed

+92
-62
lines changed

core/src/main/java/com/cloud/agent/api/CheckConvertInstanceCommand.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
public class CheckConvertInstanceCommand extends Command {
2020
boolean checkWindowsGuestConversionSupport = false;
21+
boolean useVddk = false;
22+
String vddkLibDir;
2123

2224
public CheckConvertInstanceCommand() {
2325
}
@@ -26,6 +28,11 @@ public CheckConvertInstanceCommand(boolean checkWindowsGuestConversionSupport) {
2628
this.checkWindowsGuestConversionSupport = checkWindowsGuestConversionSupport;
2729
}
2830

31+
public CheckConvertInstanceCommand(boolean checkWindowsGuestConversionSupport, boolean useVddk) {
32+
this.checkWindowsGuestConversionSupport = checkWindowsGuestConversionSupport;
33+
this.useVddk = useVddk;
34+
}
35+
2936
@Override
3037
public boolean executeInSequence() {
3138
return false;
@@ -34,4 +41,20 @@ public boolean executeInSequence() {
3441
public boolean getCheckWindowsGuestConversionSupport() {
3542
return checkWindowsGuestConversionSupport;
3643
}
44+
45+
public boolean isUseVddk() {
46+
return useVddk;
47+
}
48+
49+
public void setUseVddk(boolean useVddk) {
50+
this.useVddk = useVddk;
51+
}
52+
53+
public String getVddkLibDir() {
54+
return vddkLibDir;
55+
}
56+
57+
public void setVddkLibDir(String vddkLibDir) {
58+
this.vddkLibDir = vddkLibDir;
59+
}
3760
}

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6003,7 +6003,18 @@ public boolean hostSupportsInstanceConversion() {
60036003
}
60046004

60056005
public boolean hostSupportsVddk() {
6006-
return hostSupportsInstanceConversion() && isVddkLibDirValid(vddkLibDir) && StringUtils.isNotBlank(vddkVersion);
6006+
return hostSupportsVddk(null);
6007+
}
6008+
6009+
public boolean hostSupportsVddk(String overriddenVddkLibDir) {
6010+
String effectiveVddkLibDir = StringUtils.trimToNull(overriddenVddkLibDir);
6011+
if (StringUtils.isBlank(effectiveVddkLibDir)) {
6012+
effectiveVddkLibDir = StringUtils.trimToNull(vddkLibDir);
6013+
}
6014+
if (StringUtils.isBlank(effectiveVddkLibDir) || !isVddkLibDirValid(effectiveVddkLibDir)) {
6015+
effectiveVddkLibDir = detectVddkLibDir();
6016+
}
6017+
return hostSupportsInstanceConversion() && isVddkLibDirValid(effectiveVddkLibDir) && StringUtils.isNotBlank(detectVddkVersion());
60076018
}
60086019

60096020
protected boolean isVddkLibDirValid(String path) {

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckConvertInstanceCommandWrapper.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,15 @@ public class LibvirtCheckConvertInstanceCommandWrapper extends CommandWrapper<Ch
3030

3131
@Override
3232
public Answer execute(CheckConvertInstanceCommand cmd, LibvirtComputingResource serverResource) {
33-
if (!serverResource.hostSupportsInstanceConversion()) {
33+
if (cmd.isUseVddk()) {
34+
if (!serverResource.hostSupportsVddk(cmd.getVddkLibDir())) {
35+
String msg = String.format("Cannot convert the instance from VMware using VDDK on host %s. " +
36+
"Please make sure virt-v2v%s, nbdkit-vddk and a valid VDDK library directory are available on the host.",
37+
serverResource.getPrivateIp(), serverResource.isUbuntuOrDebianHost() ? ", nbdkit" : "");
38+
logger.info(msg);
39+
return new CheckConvertInstanceAnswer(cmd, false, msg);
40+
}
41+
} else if (!serverResource.hostSupportsInstanceConversion()) {
3442
String msg = String.format("Cannot convert the instance from VMware as the virt-v2v binary is not found on host %s. " +
3543
"Please install virt-v2v%s on the host before attempting the instance conversion.", serverResource.getPrivateIp(), serverResource.isUbuntuOrDebianHost()? ", nbdkit" : "");
3644
logger.info(msg);

plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckConvertInstanceCommandWrapperTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,41 @@ public void setUp() {
5252

5353
@Test
5454
public void testCheckInstanceCommand_success() {
55+
Mockito.when(checkConvertInstanceCommandMock.isUseVddk()).thenReturn(false);
5556
Mockito.when(libvirtComputingResourceMock.hostSupportsInstanceConversion()).thenReturn(true);
5657
Answer answer = checkConvertInstanceCommandWrapper.execute(checkConvertInstanceCommandMock, libvirtComputingResourceMock);
5758
assertTrue(answer.getResult());
5859
}
5960

6061
@Test
6162
public void testCheckInstanceCommand_failure() {
63+
Mockito.when(checkConvertInstanceCommandMock.isUseVddk()).thenReturn(false);
6264
Mockito.when(libvirtComputingResourceMock.hostSupportsInstanceConversion()).thenReturn(false);
6365
Answer answer = checkConvertInstanceCommandWrapper.execute(checkConvertInstanceCommandMock, libvirtComputingResourceMock);
6466
assertFalse(answer.getResult());
6567
assertTrue(StringUtils.isNotBlank(answer.getDetails()));
6668
}
69+
70+
@Test
71+
public void testCheckInstanceCommand_vddkSuccess() {
72+
Mockito.when(checkConvertInstanceCommandMock.isUseVddk()).thenReturn(true);
73+
Mockito.when(checkConvertInstanceCommandMock.getVddkLibDir()).thenReturn("/opt/vmware-vddk/vmware-vix-disklib-distrib");
74+
Mockito.when(libvirtComputingResourceMock.hostSupportsVddk("/opt/vmware-vddk/vmware-vix-disklib-distrib")).thenReturn(true);
75+
76+
Answer answer = checkConvertInstanceCommandWrapper.execute(checkConvertInstanceCommandMock, libvirtComputingResourceMock);
77+
78+
assertTrue(answer.getResult());
79+
}
80+
81+
@Test
82+
public void testCheckInstanceCommand_vddkFailure() {
83+
Mockito.when(checkConvertInstanceCommandMock.isUseVddk()).thenReturn(true);
84+
Mockito.when(checkConvertInstanceCommandMock.getVddkLibDir()).thenReturn("/opt/vmware-vddk/vmware-vix-disklib-distrib");
85+
Mockito.when(libvirtComputingResourceMock.hostSupportsVddk("/opt/vmware-vddk/vmware-vix-disklib-distrib")).thenReturn(false);
86+
87+
Answer answer = checkConvertInstanceCommandWrapper.execute(checkConvertInstanceCommandMock, libvirtComputingResourceMock);
88+
89+
assertFalse(answer.getResult());
90+
assertTrue(StringUtils.isNotBlank(answer.getDetails()));
91+
}
6792
}

server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,8 +1701,8 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
17011701
: selectKVMHostForImportingInCluster(destinationCluster, importInstanceHostId);
17021702

17031703
boolean isOvfExportSupported = false;
1704+
CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false, useVddk, details);
17041705
if (!useVddk) {
1705-
CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false);
17061706
isOvfExportSupported = conversionSupportAnswer.isOvfExportSupported();
17071707
}
17081708
logger.debug("The host {} is selected to execute the conversion of the " +
@@ -1726,7 +1726,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
17261726

17271727
boolean isWindowsVm = sourceVMwareInstance.getOperatingSystem().toLowerCase().contains("windows");
17281728
if (isWindowsVm) {
1729-
checkConversionSupportOnHost(convertHost, sourceVMName, true);
1729+
checkConversionSupportOnHost(convertHost, sourceVMName, true, useVddk, details);
17301730
}
17311731

17321732
checkNetworkingBeforeConvertingVmwareInstance(zone, owner, displayName, hostName, sourceVMwareInstance, nicNetworkMap, nicIpAddressMap, forced);
@@ -2027,13 +2027,6 @@ HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long conv
20272027
err = String.format(
20282028
"Cannot perform the conversion on the host %s as it is not in the same zone as the destination cluster",
20292029
selectedHost);
2030-
} else if (useVddk) {
2031-
hostDao.loadDetails(selectedHost);
2032-
if (StringUtils.isBlank(selectedHost.getDetail(Host.HOST_VDDK_SUPPORT))) {
2033-
err = String.format(
2034-
"Cannot use VDDK-based conversion on host %s as the '%s' is not there on the host",
2035-
selectedHost, Host.HOST_VDDK_SUPPORT);
2036-
}
20372030
}
20382031
if (err != null) {
20392032
logger.error(err);
@@ -2046,7 +2039,10 @@ HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long conv
20462039
List<HostVO> hosts = hostDao.listByClusterHypervisorTypeAndHostCapability(destinationCluster.getId(), destinationCluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION);
20472040
if (CollectionUtils.isNotEmpty(hosts)) {
20482041
if (useVddk) {
2049-
hosts = filterHostsWithVddkLibDir(hosts);
2042+
List<HostVO> vddkHosts = filterHostsWithVddkSupport(hosts);
2043+
if (CollectionUtils.isNotEmpty(vddkHosts)) {
2044+
hosts = vddkHosts;
2045+
}
20502046
}
20512047
if (CollectionUtils.isNotEmpty(hosts)) {
20522048
return hosts.get(new Random().nextInt(hosts.size()));
@@ -2057,7 +2053,10 @@ HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long conv
20572053
hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType());
20582054
if (CollectionUtils.isNotEmpty(hosts)) {
20592055
if (useVddk) {
2060-
hosts = filterHostsWithVddkLibDir(hosts);
2056+
List<HostVO> vddkHosts = filterHostsWithVddkSupport(hosts);
2057+
if (CollectionUtils.isNotEmpty(vddkHosts)) {
2058+
hosts = vddkHosts;
2059+
}
20612060
}
20622061
if (CollectionUtils.isNotEmpty(hosts)) {
20632062
return hosts.get(new Random().nextInt(hosts.size()));
@@ -2073,16 +2072,24 @@ HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long conv
20732072
throw new CloudRuntimeException(err);
20742073
}
20752074

2076-
private List<HostVO> filterHostsWithVddkLibDir(List<HostVO> hosts) {
2075+
private List<HostVO> filterHostsWithVddkSupport(List<HostVO> hosts) {
20772076
return hosts.stream().filter(h -> {
20782077
hostDao.loadDetails(h);
2079-
return StringUtils.isNotBlank(h.getDetail(Host.HOST_VDDK_SUPPORT));
2078+
return Boolean.parseBoolean(h.getDetail(Host.HOST_VDDK_SUPPORT));
20802079
}).collect(Collectors.toList());
20812080
}
20822081

2083-
private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHost, String sourceVM, boolean checkWindowsGuestConversionSupport) {
2084-
logger.debug(String.format("Checking the %s conversion support on the host %s", checkWindowsGuestConversionSupport? "windows guest" : "", convertHost));
2085-
CheckConvertInstanceCommand cmd = new CheckConvertInstanceCommand(checkWindowsGuestConversionSupport);
2082+
private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHost, String sourceVM,
2083+
boolean checkWindowsGuestConversionSupport,
2084+
boolean useVddk, Map<String, String> details) {
2085+
logger.debug(String.format("Checking the %s%s conversion support on the host %s",
2086+
useVddk ? "VDDK " : "",
2087+
checkWindowsGuestConversionSupport ? "windows guest " : "",
2088+
convertHost));
2089+
CheckConvertInstanceCommand cmd = new CheckConvertInstanceCommand(checkWindowsGuestConversionSupport, useVddk);
2090+
if (MapUtils.isNotEmpty(details)) {
2091+
cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR)));
2092+
}
20862093
int timeoutSeconds = 60;
20872094
cmd.setWait(timeoutSeconds);
20882095

server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,37 +1361,6 @@ public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidHo
13611361
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false);
13621362
}
13631363

1364-
@Test
1365-
public void testSelectKVMHostForConversionInClusterVddkWithExplicitHostHavingVddkLibDir() {
1366-
Long hostId = 1L;
1367-
ClusterVO cluster = getClusterForTests();
1368-
HostVO host = Mockito.mock(HostVO.class);
1369-
when(host.getResourceState()).thenReturn(ResourceState.Enabled);
1370-
when(host.getStatus()).thenReturn(Status.Up);
1371-
when(host.getType()).thenReturn(Host.Type.Routing);
1372-
when(host.getDataCenterId()).thenReturn(1L);
1373-
when(host.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn("true");
1374-
when(hostDao.findById(hostId)).thenReturn(host);
1375-
1376-
HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, true);
1377-
Assert.assertEquals(host, returnedHost);
1378-
Mockito.verify(hostDao).loadDetails(host);
1379-
}
1380-
1381-
@Test(expected = CloudRuntimeException.class)
1382-
public void testSelectKVMHostForConversionInClusterVddkWithExplicitHostMissingVddkLibDir() {
1383-
Long hostId = 1L;
1384-
ClusterVO cluster = getClusterForTests();
1385-
HostVO host = Mockito.mock(HostVO.class);
1386-
when(host.getResourceState()).thenReturn(ResourceState.Enabled);
1387-
when(host.getStatus()).thenReturn(Status.Up);
1388-
when(host.getType()).thenReturn(Host.Type.Routing);
1389-
when(host.getDataCenterId()).thenReturn(1L);
1390-
when(hostDao.findById(hostId)).thenReturn(host);
1391-
1392-
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, true);
1393-
}
1394-
13951364
@Test
13961365
public void testSelectKVMHostForConversionInClusterVddkAutoSelectsHostWithVddkSupport() {
13971366
ClusterVO cluster = getClusterForTests();
@@ -1408,19 +1377,6 @@ public void testSelectKVMHostForConversionInClusterVddkAutoSelectsHostWithVddkSu
14081377
Assert.assertEquals(hostWithVddk, returnedHost);
14091378
}
14101379

1411-
@Test(expected = CloudRuntimeException.class)
1412-
public void testSelectKVMHostForConversionInClusterVddkFailsWhenNoHostHasVddkSupport() {
1413-
ClusterVO cluster = getClusterForTests();
1414-
HostVO host = Mockito.mock(HostVO.class);
1415-
when(host.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn(null);
1416-
1417-
when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(),
1418-
cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(host));
1419-
when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host));
1420-
1421-
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, true);
1422-
}
1423-
14241380
@Test
14251381
public void testCheckUnmanagedDiskLimits() {
14261382
Account owner = Mockito.mock(Account.class);

0 commit comments

Comments
 (0)