Skip to content

Commit 3d00943

Browse files
committed
Address comments
1 parent 7137286 commit 3d00943

File tree

5 files changed

+91
-8
lines changed

5 files changed

+91
-8
lines changed

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ public class ApiConstants {
225225
public static final String ICMP_TYPE = "icmptype";
226226
public static final String ID = "id";
227227
public static final String IDS = "ids";
228+
public static final String IMPORT_INSTANCE_HOST_ID = "importinstancehostid";
228229
public static final String INDEX = "index";
229230
public static final String INSTANCES_DISKS_STATS_RETENTION_ENABLED = "instancesdisksstatsretentionenabled";
230231
public static final String INSTANCES_DISKS_STATS_RETENTION_TIME = "instancesdisksstatsretentiontime";

api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportVmCmd.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,13 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
146146
private String clusterName;
147147

148148
@Parameter(name = ApiConstants.CONVERT_INSTANCE_HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
149-
description = "(only for importing VMs from VMware to KVM) optional - the host to perform the virt-v2v migration from VMware to KVM.")
149+
description = "(only for importing VMs from VMware to KVM) optional - the host to perform the virt-v2v conversion from VMware to KVM.")
150150
private Long convertInstanceHostId;
151151

152+
@Parameter(name = ApiConstants.IMPORT_INSTANCE_HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, since = "4.19.2",
153+
description = "(only for importing VMs from VMware to KVM) optional - the host to use to import the converted instance for migration from VMware to KVM.")
154+
private Long importInstanceHostId;
155+
152156
@Parameter(name = ApiConstants.CONVERT_INSTANCE_STORAGE_POOL_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class,
153157
description = "(only for importing VMs from VMware to KVM) optional - the temporary storage pool to perform the virt-v2v migration from VMware to KVM.")
154158
private Long convertStoragePoolId;
@@ -201,6 +205,10 @@ public Long getConvertInstanceHostId() {
201205
return convertInstanceHostId;
202206
}
203207

208+
public Long getImportInstanceHostId() {
209+
return importInstanceHostId;
210+
}
211+
204212
public Long getConvertStoragePoolId() {
205213
return convertStoragePoolId;
206214
}

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

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
15701570
String clusterName = cmd.getClusterName();
15711571
String sourceHostName = cmd.getHostIp();
15721572
Long convertInstanceHostId = cmd.getConvertInstanceHostId();
1573+
Long importInstanceHostId = cmd.getImportInstanceHostId();
15731574
Long convertStoragePoolId = cmd.getConvertStoragePoolId();
15741575

15751576
if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) {
@@ -1599,8 +1600,8 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
15991600
DataStoreTO temporaryConvertLocation = null;
16001601
String ovfTemplateOnConvertLocation = null;
16011602
try {
1602-
HostVO convertHost = selectInstanceConversionKVMHostInCluster(destinationCluster, convertInstanceHostId);
1603-
HostVO importHost = convertInstanceHostId == null ? convertHost : selectInstanceConversionKVMHostInCluster(destinationCluster, null);
1603+
HostVO convertHost = selectKVMHostForConversionInCluster(destinationCluster, convertInstanceHostId);
1604+
HostVO importHost = selectKVMHostForImportingInCluster(destinationCluster, importInstanceHostId);
16041605
CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false);
16051606
LOGGER.debug(String.format("The host %s (%s) is selected to execute the conversion of the instance %s" +
16061607
" from VMware to KVM ", convertHost.getId(), convertHost.getName(), sourceVMName));
@@ -1787,17 +1788,54 @@ private Map<String, String> createParamsForRemoveClonedInstance(String vcenter,
17871788
return params;
17881789
}
17891790

1790-
private HostVO selectInstanceConversionKVMHostInCluster(Cluster destinationCluster, Long convertInstanceHostId) {
1791+
private HostVO selectKVMHostForImportingInCluster(Cluster destinationCluster, Long importInstanceHostId) {
1792+
if (importInstanceHostId != null) {
1793+
HostVO selectedHost = hostDao.findById(importInstanceHostId);
1794+
if (selectedHost == null) {
1795+
String msg = String.format("Cannot find host with ID %s", importInstanceHostId);
1796+
LOGGER.error(msg);
1797+
throw new CloudRuntimeException(msg);
1798+
}
1799+
if (selectedHost.getResourceState() != ResourceState.Enabled ||
1800+
selectedHost.getStatus() != Status.Up || selectedHost.getType() != Host.Type.Routing ||
1801+
destinationCluster.getDataCenterId() != selectedHost.getDataCenterId() ||
1802+
selectedHost.getClusterId() != destinationCluster.getId()
1803+
) {
1804+
String msg = String.format(
1805+
"Cannot import the converted instance on the host %s as it is not a running and Enabled host",
1806+
selectedHost.getName());
1807+
LOGGER.error(msg);
1808+
throw new CloudRuntimeException(msg);
1809+
}
1810+
return selectedHost;
1811+
}
1812+
1813+
List<HostVO> hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType());
1814+
if (CollectionUtils.isNotEmpty(hosts)) {
1815+
return hosts.get(new Random().nextInt(hosts.size()));
1816+
}
1817+
1818+
String err = String.format(
1819+
"Could not find any suitable %s host in cluster %s to import the converted instance",
1820+
destinationCluster.getHypervisorType(), destinationCluster.getName());
1821+
LOGGER.error(err);
1822+
throw new CloudRuntimeException(err);
1823+
}
1824+
1825+
private HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long convertInstanceHostId) {
17911826
if (convertInstanceHostId != null) {
17921827
HostVO selectedHost = hostDao.findById(convertInstanceHostId);
17931828
if (selectedHost == null) {
17941829
String msg = String.format("Cannot find host with ID %s", convertInstanceHostId);
17951830
LOGGER.error(msg);
17961831
throw new CloudRuntimeException(msg);
17971832
}
1798-
if (selectedHost.getResourceState() != ResourceState.Enabled ||
1799-
selectedHost.getStatus() != Status.Up || selectedHost.getType() != Host.Type.Routing) {
1800-
String msg = String.format("Cannot perform the conversion on the host %s as it is not a running and Enabled host", selectedHost.getName());
1833+
1834+
if (!List.of(ResourceState.Enabled, ResourceState.Disabled).contains(selectedHost.getResourceState()) ||
1835+
selectedHost.getStatus() != Status.Up || selectedHost.getType() != Host.Type.Routing ||
1836+
destinationCluster.getDataCenterId() != selectedHost.getDataCenterId()
1837+
) {
1838+
String msg = String.format("Cannot perform the conversion on the host %s as it is not running", selectedHost.getName());
18011839
LOGGER.error(msg);
18021840
throw new CloudRuntimeException(msg);
18031841
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,11 +632,13 @@ private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter,
632632
when(convertHost.getId()).thenReturn(convertHostId);
633633
when(convertHost.getName()).thenReturn("KVM-Convert-Host");
634634
when(convertHost.getType()).thenReturn(Host.Type.Routing);
635+
when(convertHost.getDataCenterId()).thenReturn(zoneId);
636+
when(convertHost.getClusterId()).thenReturn(clusterId);
635637
if (selectConvertHost) {
636638
when(importVmCmd.getConvertInstanceHostId()).thenReturn(convertHostId);
639+
when(importVmCmd.getImportInstanceHostId()).thenReturn(convertHostId);
637640
when(hostDao.findById(convertHostId)).thenReturn(convertHost);
638641
}
639-
when(hostDao.listByClusterHypervisorTypeAndHostCapability(clusterId, Hypervisor.HypervisorType.KVM, Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(convertHost));
640642

641643
DataStoreTO dataStoreTO = mock(DataStoreTO.class);
642644
DataStore dataStore = mock(DataStore.class);

ui/src/views/tools/ImportUnmanagedInstance.vue

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,18 @@
164164
@handle-checkselectpair-change="updateSelectedKvmHostForConversion"
165165
/>
166166
</a-form-item>
167+
<a-form-item name="importhostid" ref="importhostid">
168+
<check-box-select-pair
169+
layout="vertical"
170+
v-if="cluster.hypervisortype === 'KVM' && selectedVmwareVcenter"
171+
:resourceKey="cluster.id"
172+
:selectOptions="kvmHostsForImporting"
173+
:checkBoxLabel="$t('message.select.kvm.host.instance.conversion')"
174+
:defaultCheckBoxValue="false"
175+
:reversed="false"
176+
@handle-checkselectpair-change="updateSelectedKvmHostForImporting"
177+
/>
178+
</a-form-item>
167179
<a-form-item name="convertstorageoption" ref="convertstorageoption">
168180
<check-box-select-pair
169181
layout="vertical"
@@ -494,7 +506,9 @@ export default {
494506
switches: {},
495507
loading: false,
496508
kvmHostsForConversion: [],
509+
kvmHostsForImporting: [],
497510
selectedKvmHostForConversion: null,
511+
selectedKvmHostForImporting: null,
498512
storageOptionsForConversion: [
499513
{
500514
id: 'secondary',
@@ -730,6 +744,7 @@ export default {
730744
page: 1
731745
})
732746
this.fetchKvmHostsForConversion()
747+
this.fetchKvmHostsForImporting()
733748
if (this.resource?.disk?.length > 1) {
734749
this.updateSelectedRootDisk()
735750
}
@@ -930,6 +945,17 @@ export default {
930945
})
931946
})
932947
},
948+
fetchKvmHostsForImporting () {
949+
api('listHosts', {
950+
clusterid: this.cluster.id,
951+
hypervisor: this.cluster.hypervisortype,
952+
type: 'Routing',
953+
state: 'Up',
954+
resourcestate: 'Enabled'
955+
}).then(json => {
956+
this.kvmHostsForImporting = json.listhostsresponse.host || []
957+
})
958+
},
933959
fetchStoragePoolsForConversion () {
934960
if (this.selectedStorageOptionForConversion === 'primary') {
935961
const params = {
@@ -956,6 +982,14 @@ export default {
956982
})
957983
}
958984
},
985+
updateSelectedKvmHostForImporting (clusterid, checked, value) {
986+
if (checked) {
987+
this.selectedKvmHostForImporting = value
988+
} else {
989+
this.selectedKvmHostForImporting = null
990+
this.resetStorageOptionsForConversion()
991+
}
992+
},
959993
updateSelectedKvmHostForConversion (clusterid, checked, value) {
960994
if (checked) {
961995
this.selectedKvmHostForConversion = value

0 commit comments

Comments
 (0)