Skip to content

Commit e881ee7

Browse files
committed
Allow import from VMWare via another host in the cluster
1 parent b4f43de commit e881ee7

File tree

6 files changed

+48
-74
lines changed

6 files changed

+48
-74
lines changed

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

Lines changed: 0 additions & 40 deletions
This file was deleted.

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import com.cloud.agent.api.to.RemoteInstanceTO;
2121
import com.cloud.hypervisor.Hypervisor;
2222

23-
import java.util.List;
24-
2523
public class ConvertInstanceCommand extends Command {
2624

2725
private RemoteInstanceTO sourceInstance;

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import com.cloud.agent.api.to.DataStoreTO;
2020
import com.cloud.agent.api.to.RemoteInstanceTO;
21-
import com.cloud.hypervisor.Hypervisor;
2221

2322
import java.util.List;
2423

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

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@
1818
//
1919
package com.cloud.hypervisor.kvm.resource.wrapper;
2020

21-
import java.io.BufferedInputStream;
22-
import java.io.File;
23-
import java.io.FileInputStream;
24-
import java.io.IOException;
25-
import java.io.InputStream;
2621
import java.net.URLEncoder;
2722
import java.nio.charset.Charset;
2823
import java.util.ArrayList;
@@ -33,12 +28,10 @@
3328
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
3429
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
3530
import org.apache.commons.collections.CollectionUtils;
36-
import org.apache.commons.io.IOUtils;
3731
import org.apache.commons.lang3.StringUtils;
3832
import org.apache.log4j.Logger;
3933

4034
import com.cloud.agent.api.Answer;
41-
import com.cloud.agent.api.ConvertInstanceAnswer;
4235
import com.cloud.agent.api.ConvertInstanceCommand;
4336
import com.cloud.agent.api.to.DataStoreTO;
4437
import com.cloud.agent.api.to.NfsTO;
@@ -80,15 +73,15 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
8073
String msg = String.format("Cannot convert the instance %s from VMware as the virt-v2v binary is not found. " +
8174
"Please install virt-v2v%s on the host before attempting the instance conversion.", sourceInstanceName, serverResource.isUbuntuHost()? ", nbdkit" : "");
8275
s_logger.info(msg);
83-
return new ConvertInstanceAnswer(cmd, false, msg);
76+
return new Answer(cmd, false, msg);
8477
}
8578

8679
if (!areSourceAndDestinationHypervisorsSupported(sourceHypervisorType, destinationHypervisorType)) {
8780
String err = destinationHypervisorType != Hypervisor.HypervisorType.KVM ?
8881
String.format("The destination hypervisor type is %s, KVM was expected, cannot handle it", destinationHypervisorType) :
8982
String.format("The source hypervisor type %s is not supported for KVM conversion", sourceHypervisorType);
9083
s_logger.error(err);
91-
return new ConvertInstanceAnswer(cmd, false, err);
84+
return new Answer(cmd, false, err);
9285
}
9386

9487
final KVMStoragePoolManager storagePoolMgr = serverResource.getStoragePoolMgr();
@@ -103,7 +96,7 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
10396
if (StringUtils.isBlank(exportInstanceOVAUrl)) {
10497
String err = String.format("Couldn't export OVA for the VM %s, due to empty url", sourceInstanceName);
10598
s_logger.error(err);
106-
return new ConvertInstanceAnswer(cmd, false, err);
99+
return new Answer(cmd, false, err);
107100
}
108101

109102
int noOfThreads = cmd.getThreadsCountToExportOvf();
@@ -117,7 +110,7 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
117110
if (!ovfExported) {
118111
String err = String.format("Export OVA for the VM %s failed", sourceInstanceName);
119112
s_logger.error(err);
120-
return new ConvertInstanceAnswer(cmd, false, err);
113+
return new Answer(cmd, false, err);
121114
}
122115
sourceOVFDirPath = String.format("%s%s/", sourceOVFDirPath, sourceInstanceName);
123116
} else {
@@ -136,14 +129,14 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
136129
String err = String.format("The virt-v2v conversion for the OVF %s failed. " +
137130
"Please check the agent logs for the virt-v2v output", ovfTemplateDirOnConversionLocation);
138131
s_logger.error(err);
139-
return new ConvertInstanceAnswer(cmd, false, err);
132+
return new Answer(cmd, false, err);
140133
}
141-
return new ConvertInstanceAnswer(cmd, false, null);
134+
return new Answer(cmd, false, null);
142135
} catch (Exception e) {
143136
String error = String.format("Error converting instance %s from %s, due to: %s",
144137
sourceInstanceName, sourceHypervisorType, e.getMessage());
145138
s_logger.error(error, e);
146-
return new ConvertInstanceAnswer(cmd, false, error);
139+
return new Answer(cmd, false, error);
147140
} finally {
148141
if (ovfExported && StringUtils.isNotBlank(ovfTemplateDirOnConversionLocation)) {
149142
String sourceOVFDir = String.format("%s/%s", temporaryConvertPath, ovfTemplateDirOnConversionLocation);

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

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.cloud.agent.api.CheckConvertInstanceCommand;
2424
import com.cloud.agent.api.CheckVolumeAnswer;
2525
import com.cloud.agent.api.CheckVolumeCommand;
26-
import com.cloud.agent.api.ConvertInstanceAnswer;
2726
import com.cloud.agent.api.ConvertInstanceCommand;
2827
import com.cloud.agent.api.CopyRemoteVolumeAnswer;
2928
import com.cloud.agent.api.CopyRemoteVolumeCommand;
@@ -1600,6 +1599,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
16001599
String ovfTemplateOnConvertLocation = null;
16011600
try {
16021601
HostVO convertHost = selectInstanceConversionKVMHostInCluster(destinationCluster, convertInstanceHostId);
1602+
HostVO destinationHost = convertInstanceHostId == null ? convertHost : selectInstanceConversionKVMHostInCluster(destinationCluster, null);
16031603
CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false);
16041604
LOGGER.debug(String.format("The host %s (%s) is selected to execute the conversion of the instance %s" +
16051605
" from VMware to KVM ", convertHost.getId(), convertHost.getName(), sourceVMName));
@@ -1623,11 +1623,13 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
16231623
int noOfThreads = UnmanagedVMsManager.ThreadsOnMSToImportVMwareVMFiles.value();
16241624
ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password,
16251625
clusterName, sourceHostName, sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads);
1626-
convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName, sourceVMwareInstance, convertHost, convertStoragePools,
1626+
convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName,
1627+
sourceVMwareInstance, convertHost, destinationHost, convertStoragePools,
16271628
temporaryConvertLocation, ovfTemplateOnConvertLocation);
16281629
} else {
16291630
// Uses KVM Host for OVF export to temporary conversion location, through ovftool
1630-
convertedInstance = convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(sourceVMName, sourceVMwareInstance, convertHost, convertStoragePools,
1631+
convertedInstance = convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(
1632+
sourceVMName, sourceVMwareInstance, convertHost, destinationHost, convertStoragePools,
16311633
temporaryConvertLocation, vcenter, username, password, datacenterName);
16321634
}
16331635

@@ -1844,9 +1846,12 @@ private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHo
18441846
return checkConvertInstanceAnswer;
18451847
}
18461848

1847-
private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation(String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
1848-
List<StoragePoolVO> convertStoragePools, DataStoreTO temporaryConvertLocation,
1849-
String ovfTemplateDirConvertLocation) {
1849+
private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation(
1850+
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
1851+
HostVO convertHost, HostVO destinationHost,
1852+
List<StoragePoolVO> convertStoragePools, DataStoreTO temporaryConvertLocation,
1853+
String ovfTemplateDirConvertLocation
1854+
) {
18501855
LOGGER.debug(String.format("Delegating the conversion of instance %s from VMware to KVM to the host %s (%s) using OVF %s on conversion datastore",
18511856
sourceVM, convertHost.getId(), convertHost.getName(), ovfTemplateDirConvertLocation));
18521857

@@ -1877,21 +1882,24 @@ private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation(S
18771882
try {
18781883
ImportConvertedInstanceCommand importCmd = new ImportConvertedInstanceCommand(remoteInstanceTO,
18791884
destinationStoragePools, temporaryConvertLocation);
1880-
importAnswer = agentManager.send(convertHost.getId(), importCmd);
1885+
importAnswer = agentManager.send(destinationHost.getId(), importCmd);
18811886
} catch (AgentUnavailableException | OperationTimedoutException e) {
18821887
String err = String.format(
1883-
"Could not import the converted instance command to host %d (%s) due to: %s",
1884-
convertHost.getId(), convertHost.getName(), e.getMessage());
1888+
"Could not send the import converted instance command to host %d (%s) due to: %s",
1889+
destinationHost.getId(), destinationHost.getName(), e.getMessage());
18851890
LOGGER.error(err, e);
18861891
throw new CloudRuntimeException(err);
18871892
}
18881893

18891894
return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance();
18901895
}
18911896

1892-
private UnmanagedInstanceTO convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
1893-
List<StoragePoolVO> convertStoragePools, DataStoreTO temporaryConvertLocation,
1894-
String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) {
1897+
private UnmanagedInstanceTO convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(
1898+
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
1899+
HostVO convertHost, HostVO destinationHost, List<StoragePoolVO> convertStoragePools,
1900+
DataStoreTO temporaryConvertLocation, String vcenterHost,
1901+
String vcenterUsername, String vcenterPassword, String datacenterName
1902+
) {
18951903
LOGGER.debug(String.format("Delegating the conversion of instance %s from VMware to KVM to the host %s (%s) after OVF export through ovftool",
18961904
sourceVM, convertHost.getId(), convertHost.getName()));
18971905

@@ -1924,7 +1932,20 @@ private UnmanagedInstanceTO convertVmwareInstanceToKVMAfterExportingOVFToConvert
19241932
LOGGER.error(err);
19251933
throw new CloudRuntimeException(err);
19261934
}
1927-
return ((ConvertInstanceAnswer) convertAnswer).getConvertedInstance();
1935+
1936+
Answer importAnswer;
1937+
try {
1938+
ImportConvertedInstanceCommand importCmd = new ImportConvertedInstanceCommand(remoteInstanceTO,
1939+
destinationStoragePools, temporaryConvertLocation);
1940+
importAnswer = agentManager.send(destinationHost.getId(), importCmd);
1941+
} catch (AgentUnavailableException | OperationTimedoutException e) {
1942+
String err = String.format(
1943+
"Could not send the import converted instance command to host %d (%s) due to: %s",
1944+
destinationHost.getId(), destinationHost.getName(), e.getMessage());
1945+
LOGGER.error(err, e);
1946+
throw new CloudRuntimeException(err);
1947+
}
1948+
return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance();
19281949
}
19291950

19301951
private List<StoragePoolVO> findInstanceConversionStoragePoolsInCluster(Cluster destinationCluster) {

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@
2323
import com.cloud.agent.api.CheckConvertInstanceCommand;
2424
import com.cloud.agent.api.CheckVolumeAnswer;
2525
import com.cloud.agent.api.CheckVolumeCommand;
26-
import com.cloud.agent.api.ConvertInstanceAnswer;
2726
import com.cloud.agent.api.ConvertInstanceCommand;
2827
import com.cloud.agent.api.CopyRemoteVolumeAnswer;
2928
import com.cloud.agent.api.CopyRemoteVolumeCommand;
3029
import com.cloud.agent.api.GetRemoteVmsAnswer;
3130
import com.cloud.agent.api.GetRemoteVmsCommand;
3231
import com.cloud.agent.api.GetUnmanagedInstancesAnswer;
3332
import com.cloud.agent.api.GetUnmanagedInstancesCommand;
33+
import com.cloud.agent.api.ImportConvertedInstanceAnswer;
34+
import com.cloud.agent.api.ImportConvertedInstanceCommand;
3435
import com.cloud.agent.api.to.DataStoreTO;
3536
import com.cloud.configuration.Resource;
3637
import com.cloud.dc.ClusterVO;
@@ -630,11 +631,11 @@ private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter,
630631
when(convertHost.getId()).thenReturn(convertHostId);
631632
when(convertHost.getName()).thenReturn("KVM-Convert-Host");
632633
when(convertHost.getType()).thenReturn(Host.Type.Routing);
633-
when(convertHost.getClusterId()).thenReturn(clusterId);
634634
if (selectConvertHost) {
635635
when(importVmCmd.getConvertInstanceHostId()).thenReturn(convertHostId);
636636
when(hostDao.findById(convertHostId)).thenReturn(convertHost);
637637
}
638+
when(hostDao.listByClusterHypervisorTypeAndHostCapability(clusterId, Hypervisor.HypervisorType.KVM, Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(convertHost));
638639

639640
DataStoreTO dataStoreTO = mock(DataStoreTO.class);
640641
DataStore dataStore = mock(DataStore.class);
@@ -693,11 +694,13 @@ private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter,
693694
when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer);
694695
}
695696

696-
ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class);
697+
Answer convertInstanceAnswer = mock(Answer.class);
698+
ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class);
697699
when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE);
698-
when(convertInstanceAnswer.getConvertedInstance()).thenReturn(instance);
700+
when(convertImportedInstanceAnswer.getConvertedInstance()).thenReturn(instance);
699701
if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) {
700702
when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ConvertInstanceCommand.class))).thenReturn(convertInstanceAnswer);
703+
when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer);
701704
}
702705

703706
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {

0 commit comments

Comments
 (0)