Skip to content

Commit d8c321d

Browse files
authored
check tags while fetching storage pool for importing vm (#9764)
1 parent 5c01cff commit d8c321d

File tree

2 files changed

+105
-33
lines changed

2 files changed

+105
-33
lines changed

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

Lines changed: 101 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ private Map<String, Network.IpAddresses> getNicIpAddresses(final List<UnmanagedI
536536
return nicIpAddresses;
537537
}
538538

539-
private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster) {
539+
private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, String diskOfferingTags) {
540540
StoragePool storagePool = null;
541541
final String dsHost = disk.getDatastoreHost();
542542
final String dsPath = disk.getDatastorePath();
@@ -546,7 +546,8 @@ private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final Da
546546
List<StoragePoolVO> pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath);
547547
for (StoragePool pool : pools) {
548548
if (pool.getDataCenterId() == zone.getId() &&
549-
(pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId()))) {
549+
(pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) &&
550+
volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) {
550551
storagePool = pool;
551552
break;
552553
}
@@ -558,7 +559,8 @@ private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final Da
558559
pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId()));
559560
for (StoragePool pool : pools) {
560561
String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName;
561-
if (StringUtils.contains(pool.getPath(), searchPoolParam)) {
562+
if (StringUtils.contains(pool.getPath(), searchPoolParam) &&
563+
volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) {
562564
storagePool = pool;
563565
break;
564566
}
@@ -621,7 +623,8 @@ private void checkUnmanagedDiskAndOfferingForImport(String instanceName, Unmanag
621623
if (diskOffering != null && !diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) {
622624
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB))));
623625
}
624-
StoragePool storagePool = getStoragePool(disk, zone, cluster);
626+
diskOffering = diskOffering != null ? diskOffering : diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
627+
StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering != null ? diskOffering.getTags() : null);
625628
if (diskOffering != null && !migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) {
626629
throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId()));
627630
}
@@ -858,7 +861,7 @@ private Pair<DiskProfile, StoragePool> importDisk(UnmanagedInstanceTO.Disk disk,
858861
diskInfo.setDiskChain(new String[]{disk.getImagePath()});
859862
chainInfo = gson.toJson(diskInfo);
860863
}
861-
StoragePool storagePool = getStoragePool(disk, zone, cluster);
864+
StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering != null ? diskOffering.getTags() : null);
862865
DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize,
863866
minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), path, chainInfo);
864867

@@ -1612,7 +1615,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
16121615

16131616
temporaryConvertLocation = selectInstanceConversionTemporaryLocation(
16141617
destinationCluster, convertHost, convertStoragePoolId);
1615-
List<StoragePoolVO> convertStoragePools = findInstanceConversionStoragePoolsInCluster(destinationCluster);
1618+
List<StoragePoolVO> convertStoragePools = findInstanceConversionStoragePoolsInCluster(destinationCluster, serviceOffering, dataDiskOfferingMap);
16161619
long importStartTime = System.currentTimeMillis();
16171620
Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName);
16181621
sourceVMwareInstance = sourceInstanceDetails.first();
@@ -1628,15 +1631,18 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
16281631
if (cmd.getForceMsToImportVmFiles() || !conversionSupportAnswer.isOvfExportSupported()) {
16291632
// Uses MS for OVF export to temporary conversion location
16301633
int noOfThreads = UnmanagedVMsManager.ThreadsOnMSToImportVMwareVMFiles.value();
1631-
ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password,
1632-
clusterName, sourceHostName, sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads);
1634+
ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance(
1635+
vcenter, datacenterName, username, password, clusterName, sourceHostName,
1636+
sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads);
16331637
convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName,
1634-
sourceVMwareInstance, convertHost, importHost, convertStoragePools,
1635-
temporaryConvertLocation, ovfTemplateOnConvertLocation);
1638+
sourceVMwareInstance, convertHost, importHost, convertStoragePools,
1639+
serviceOffering, dataDiskOfferingMap, temporaryConvertLocation,
1640+
ovfTemplateOnConvertLocation);
16361641
} else {
16371642
// Uses KVM Host for OVF export to temporary conversion location, through ovftool
16381643
convertedInstance = convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(
1639-
sourceVMName, sourceVMwareInstance, convertHost, importHost, convertStoragePools,
1644+
sourceVMName, sourceVMwareInstance, convertHost, importHost,
1645+
convertStoragePools, serviceOffering, dataDiskOfferingMap,
16401646
temporaryConvertLocation, vcenter, username, password, datacenterName);
16411647
}
16421648

@@ -1726,9 +1732,9 @@ private void sanitizeConvertedInstance(UnmanagedInstanceTO convertedInstance, Un
17261732
convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff);
17271733
List<UnmanagedInstanceTO.Disk> convertedInstanceDisks = convertedInstance.getDisks();
17281734
List<UnmanagedInstanceTO.Disk> sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks();
1729-
for (int i = 0; i < convertedInstanceDisks.size(); i++) {
1730-
UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i);
1731-
disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId());
1735+
for (UnmanagedInstanceTO.Disk sourceVMwareInstanceDisk : sourceVMwareInstanceDisks) {
1736+
UnmanagedInstanceTO.Disk convertedDisk = convertedInstanceDisks.get(sourceVMwareInstanceDisk.getPosition());
1737+
convertedDisk.setDiskId(sourceVMwareInstanceDisk.getDiskId());
17321738
}
17331739
List<UnmanagedInstanceTO.Nic> convertedInstanceNics = convertedInstance.getNics();
17341740
List<UnmanagedInstanceTO.Nic> sourceVMwareInstanceNics = sourceVMwareInstance.getNics();
@@ -1912,16 +1918,16 @@ private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHo
19121918
}
19131919

19141920
private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation(
1915-
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
1916-
HostVO convertHost, HostVO importHost,
1917-
List<StoragePoolVO> convertStoragePools, DataStoreTO temporaryConvertLocation,
1918-
String ovfTemplateDirConvertLocation
1921+
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
1922+
HostVO importHost, List<StoragePoolVO> convertStoragePools,
1923+
ServiceOfferingVO serviceOffering, Map<String, Long> dataDiskOfferingMap,
1924+
DataStoreTO temporaryConvertLocation, String ovfTemplateDirConvertLocation
19191925
) {
19201926
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",
19211927
sourceVM, convertHost.getId(), convertHost.getName(), ovfTemplateDirConvertLocation));
19221928

19231929
RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVM);
1924-
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks());
1930+
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap);
19251931
ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO,
19261932
Hypervisor.HypervisorType.KVM, temporaryConvertLocation, ovfTemplateDirConvertLocation, false, false);
19271933
int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60;
@@ -1932,16 +1938,17 @@ private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation(
19321938
}
19331939

19341940
private UnmanagedInstanceTO convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(
1935-
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
1936-
HostVO convertHost, HostVO importHost, List<StoragePoolVO> convertStoragePools,
1937-
DataStoreTO temporaryConvertLocation, String vcenterHost,
1938-
String vcenterUsername, String vcenterPassword, String datacenterName
1941+
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
1942+
HostVO importHost, List<StoragePoolVO> convertStoragePools,
1943+
ServiceOfferingVO serviceOffering, Map<String, Long> dataDiskOfferingMap,
1944+
DataStoreTO temporaryConvertLocation, String vcenterHost, String vcenterUsername,
1945+
String vcenterPassword, String datacenterName
19391946
) {
19401947
LOGGER.debug(String.format("Delegating the conversion of instance %s from VMware to KVM to the host %s (%s) after OVF export through ovftool",
19411948
sourceVM, convertHost.getId(), convertHost.getName()));
19421949

19431950
RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName);
1944-
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks());
1951+
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap);
19451952
ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO,
19461953
Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true);
19471954
int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60;
@@ -2004,12 +2011,31 @@ private UnmanagedInstanceTO convertAndImportToKVM(ConvertInstanceCommand convert
20042011
return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance();
20052012
}
20062013

2007-
private List<StoragePoolVO> findInstanceConversionStoragePoolsInCluster(Cluster destinationCluster) {
2014+
private List<StoragePoolVO> findInstanceConversionStoragePoolsInCluster(
2015+
Cluster destinationCluster, ServiceOfferingVO serviceOffering,
2016+
Map<String, Long> dataDiskOfferingMap
2017+
) {
20082018
List<StoragePoolVO> pools = new ArrayList<>();
2009-
List<StoragePoolVO> clusterPools = primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem);
2010-
pools.addAll(clusterPools);
2011-
List<StoragePoolVO> zonePools = primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem);
2012-
pools.addAll(zonePools);
2019+
pools.addAll(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem));
2020+
pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem));
2021+
List<String> diskOfferingTags = new ArrayList<>();
2022+
for (Long diskOfferingId : dataDiskOfferingMap.values()) {
2023+
DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId);
2024+
if (diskOffering == null) {
2025+
String msg = String.format("Cannot find disk offering with ID %s", diskOfferingId);
2026+
LOGGER.error(msg);
2027+
throw new CloudRuntimeException(msg);
2028+
}
2029+
diskOfferingTags.add(diskOffering.getTags());
2030+
}
2031+
if (serviceOffering.getDiskOfferingId() != null) {
2032+
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
2033+
if (diskOffering != null) {
2034+
diskOfferingTags.add(diskOffering.getTags());
2035+
}
2036+
}
2037+
2038+
pools = getPoolsWithMatchingTags(pools, diskOfferingTags);
20132039
if (pools.isEmpty()) {
20142040
String msg = String.format("Cannot find suitable storage pools in cluster %s for the conversion", destinationCluster.getName());
20152041
LOGGER.error(msg);
@@ -2018,12 +2044,54 @@ private List<StoragePoolVO> findInstanceConversionStoragePoolsInCluster(Cluster
20182044
return pools;
20192045
}
20202046

2021-
private List<String> selectInstanceConversionStoragePools(List<StoragePoolVO> pools, List<UnmanagedInstanceTO.Disk> disks) {
2047+
private List<StoragePoolVO> getPoolsWithMatchingTags(List<StoragePoolVO> pools, List<String> diskOfferingTags) {
2048+
if (diskOfferingTags.isEmpty()) {
2049+
return pools;
2050+
}
2051+
List<StoragePoolVO> poolsSupportingTags = new ArrayList<>(pools);
2052+
for (String tags : diskOfferingTags) {
2053+
boolean tagsMatched = false;
2054+
for (StoragePoolVO pool : pools) {
2055+
if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, tags)) {
2056+
poolsSupportingTags.add(pool);
2057+
tagsMatched = true;
2058+
}
2059+
}
2060+
if (!tagsMatched) {
2061+
String msg = String.format("Cannot find suitable storage pools for the conversion with disk offering tags %s", tags);
2062+
LOGGER.error(msg);
2063+
throw new CloudRuntimeException(msg);
2064+
}
2065+
}
2066+
return poolsSupportingTags;
2067+
}
2068+
2069+
private List<String> selectInstanceConversionStoragePools(
2070+
List<StoragePoolVO> pools, List<UnmanagedInstanceTO.Disk> disks,
2071+
ServiceOfferingVO serviceOffering, Map<String, Long> dataDiskOfferingMap
2072+
) {
20222073
List<String> storagePools = new ArrayList<>(disks.size());
2023-
//TODO: Choose pools by capacity
2074+
for (int i = 0; i < disks.size(); i++) {
2075+
storagePools.add(null);
2076+
}
2077+
Set<String> dataDiskIds = dataDiskOfferingMap.keySet();
20242078
for (UnmanagedInstanceTO.Disk disk : disks) {
2025-
Long capacity = disk.getCapacity();
2026-
storagePools.add(pools.get(0).getUuid());
2079+
Long diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId());
2080+
if (diskOfferingId == null && !dataDiskIds.contains(disk.getDiskId())) {
2081+
diskOfferingId = serviceOffering.getDiskOfferingId();
2082+
}
2083+
//TODO: Choose pools by capacity
2084+
if (diskOfferingId == null) {
2085+
storagePools.set(disk.getPosition(), pools.get(0).getUuid());
2086+
} else {
2087+
DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId);
2088+
for (StoragePoolVO pool : pools) {
2089+
if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags())) {
2090+
storagePools.set(disk.getPosition(), pool.getUuid());
2091+
break;
2092+
}
2093+
}
2094+
}
20272095
}
20282096
return storagePools;
20292097
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ public void setUp() throws Exception {
277277
List<UnmanagedInstanceTO.Disk> instanceDisks = new ArrayList<>();
278278
UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk();
279279
instanceDisk.setDiskId("1000-1");
280+
instanceDisk.setPosition(0);
280281
instanceDisk.setLabel("DiskLabel");
281282
instanceDisk.setController("scsi");
282283
instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk");
@@ -423,6 +424,7 @@ public void importUnmanagedInstanceTest() {
423424
ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class);
424425
when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance");
425426
when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null);
427+
when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
426428
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
427429
unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd);
428430
}
@@ -702,6 +704,8 @@ private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter,
702704
when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer);
703705
}
704706

707+
when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
708+
705709
ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class);
706710
ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class);
707711
when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE);

0 commit comments

Comments
 (0)