check tags while fetching storage pool for importing vm (#9764)

This commit is contained in:
Vishesh 2025-01-03 13:35:54 +05:30 committed by GitHub
parent 5c01cff304
commit d8c321d57a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 105 additions and 33 deletions

View File

@ -536,7 +536,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
return nicIpAddresses;
}
private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster) {
private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, String diskOfferingTags) {
StoragePool storagePool = null;
final String dsHost = disk.getDatastoreHost();
final String dsPath = disk.getDatastorePath();
@ -546,7 +546,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
List<StoragePoolVO> pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath);
for (StoragePool pool : pools) {
if (pool.getDataCenterId() == zone.getId() &&
(pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId()))) {
(pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) &&
volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) {
storagePool = pool;
break;
}
@ -558,7 +559,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId()));
for (StoragePool pool : pools) {
String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName;
if (StringUtils.contains(pool.getPath(), searchPoolParam)) {
if (StringUtils.contains(pool.getPath(), searchPoolParam) &&
volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) {
storagePool = pool;
break;
}
@ -621,7 +623,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
if (diskOffering != null && !diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) {
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))));
}
StoragePool storagePool = getStoragePool(disk, zone, cluster);
diskOffering = diskOffering != null ? diskOffering : diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering != null ? diskOffering.getTags() : null);
if (diskOffering != null && !migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) {
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()));
}
@ -858,7 +861,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
diskInfo.setDiskChain(new String[]{disk.getImagePath()});
chainInfo = gson.toJson(diskInfo);
}
StoragePool storagePool = getStoragePool(disk, zone, cluster);
StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering != null ? diskOffering.getTags() : null);
DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize,
minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), path, chainInfo);
@ -1612,7 +1615,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
temporaryConvertLocation = selectInstanceConversionTemporaryLocation(
destinationCluster, convertHost, convertStoragePoolId);
List<StoragePoolVO> convertStoragePools = findInstanceConversionStoragePoolsInCluster(destinationCluster);
List<StoragePoolVO> convertStoragePools = findInstanceConversionStoragePoolsInCluster(destinationCluster, serviceOffering, dataDiskOfferingMap);
long importStartTime = System.currentTimeMillis();
Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName);
sourceVMwareInstance = sourceInstanceDetails.first();
@ -1628,15 +1631,18 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
if (cmd.getForceMsToImportVmFiles() || !conversionSupportAnswer.isOvfExportSupported()) {
// Uses MS for OVF export to temporary conversion location
int noOfThreads = UnmanagedVMsManager.ThreadsOnMSToImportVMwareVMFiles.value();
ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password,
clusterName, sourceHostName, sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads);
ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance(
vcenter, datacenterName, username, password, clusterName, sourceHostName,
sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads);
convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName,
sourceVMwareInstance, convertHost, importHost, convertStoragePools,
temporaryConvertLocation, ovfTemplateOnConvertLocation);
sourceVMwareInstance, convertHost, importHost, convertStoragePools,
serviceOffering, dataDiskOfferingMap, temporaryConvertLocation,
ovfTemplateOnConvertLocation);
} else {
// Uses KVM Host for OVF export to temporary conversion location, through ovftool
convertedInstance = convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(
sourceVMName, sourceVMwareInstance, convertHost, importHost, convertStoragePools,
sourceVMName, sourceVMwareInstance, convertHost, importHost,
convertStoragePools, serviceOffering, dataDiskOfferingMap,
temporaryConvertLocation, vcenter, username, password, datacenterName);
}
@ -1726,9 +1732,9 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff);
List<UnmanagedInstanceTO.Disk> convertedInstanceDisks = convertedInstance.getDisks();
List<UnmanagedInstanceTO.Disk> sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks();
for (int i = 0; i < convertedInstanceDisks.size(); i++) {
UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i);
disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId());
for (UnmanagedInstanceTO.Disk sourceVMwareInstanceDisk : sourceVMwareInstanceDisks) {
UnmanagedInstanceTO.Disk convertedDisk = convertedInstanceDisks.get(sourceVMwareInstanceDisk.getPosition());
convertedDisk.setDiskId(sourceVMwareInstanceDisk.getDiskId());
}
List<UnmanagedInstanceTO.Nic> convertedInstanceNics = convertedInstance.getNics();
List<UnmanagedInstanceTO.Nic> sourceVMwareInstanceNics = sourceVMwareInstance.getNics();
@ -1912,16 +1918,16 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
}
private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation(
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
HostVO convertHost, HostVO importHost,
List<StoragePoolVO> convertStoragePools, DataStoreTO temporaryConvertLocation,
String ovfTemplateDirConvertLocation
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
HostVO importHost, List<StoragePoolVO> convertStoragePools,
ServiceOfferingVO serviceOffering, Map<String, Long> dataDiskOfferingMap,
DataStoreTO temporaryConvertLocation, String ovfTemplateDirConvertLocation
) {
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",
sourceVM, convertHost.getId(), convertHost.getName(), ovfTemplateDirConvertLocation));
RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVM);
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks());
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap);
ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO,
Hypervisor.HypervisorType.KVM, temporaryConvertLocation, ovfTemplateDirConvertLocation, false, false);
int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60;
@ -1932,16 +1938,17 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
}
private UnmanagedInstanceTO convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
HostVO convertHost, HostVO importHost, List<StoragePoolVO> convertStoragePools,
DataStoreTO temporaryConvertLocation, String vcenterHost,
String vcenterUsername, String vcenterPassword, String datacenterName
String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
HostVO importHost, List<StoragePoolVO> convertStoragePools,
ServiceOfferingVO serviceOffering, Map<String, Long> dataDiskOfferingMap,
DataStoreTO temporaryConvertLocation, String vcenterHost, String vcenterUsername,
String vcenterPassword, String datacenterName
) {
LOGGER.debug(String.format("Delegating the conversion of instance %s from VMware to KVM to the host %s (%s) after OVF export through ovftool",
sourceVM, convertHost.getId(), convertHost.getName()));
RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName);
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks());
List<String> destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap);
ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO,
Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true);
int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60;
@ -2004,12 +2011,31 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance();
}
private List<StoragePoolVO> findInstanceConversionStoragePoolsInCluster(Cluster destinationCluster) {
private List<StoragePoolVO> findInstanceConversionStoragePoolsInCluster(
Cluster destinationCluster, ServiceOfferingVO serviceOffering,
Map<String, Long> dataDiskOfferingMap
) {
List<StoragePoolVO> pools = new ArrayList<>();
List<StoragePoolVO> clusterPools = primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem);
pools.addAll(clusterPools);
List<StoragePoolVO> zonePools = primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem);
pools.addAll(zonePools);
pools.addAll(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem));
pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem));
List<String> diskOfferingTags = new ArrayList<>();
for (Long diskOfferingId : dataDiskOfferingMap.values()) {
DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId);
if (diskOffering == null) {
String msg = String.format("Cannot find disk offering with ID %s", diskOfferingId);
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
diskOfferingTags.add(diskOffering.getTags());
}
if (serviceOffering.getDiskOfferingId() != null) {
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
if (diskOffering != null) {
diskOfferingTags.add(diskOffering.getTags());
}
}
pools = getPoolsWithMatchingTags(pools, diskOfferingTags);
if (pools.isEmpty()) {
String msg = String.format("Cannot find suitable storage pools in cluster %s for the conversion", destinationCluster.getName());
LOGGER.error(msg);
@ -2018,12 +2044,54 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
return pools;
}
private List<String> selectInstanceConversionStoragePools(List<StoragePoolVO> pools, List<UnmanagedInstanceTO.Disk> disks) {
private List<StoragePoolVO> getPoolsWithMatchingTags(List<StoragePoolVO> pools, List<String> diskOfferingTags) {
if (diskOfferingTags.isEmpty()) {
return pools;
}
List<StoragePoolVO> poolsSupportingTags = new ArrayList<>(pools);
for (String tags : diskOfferingTags) {
boolean tagsMatched = false;
for (StoragePoolVO pool : pools) {
if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, tags)) {
poolsSupportingTags.add(pool);
tagsMatched = true;
}
}
if (!tagsMatched) {
String msg = String.format("Cannot find suitable storage pools for the conversion with disk offering tags %s", tags);
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
}
return poolsSupportingTags;
}
private List<String> selectInstanceConversionStoragePools(
List<StoragePoolVO> pools, List<UnmanagedInstanceTO.Disk> disks,
ServiceOfferingVO serviceOffering, Map<String, Long> dataDiskOfferingMap
) {
List<String> storagePools = new ArrayList<>(disks.size());
//TODO: Choose pools by capacity
for (int i = 0; i < disks.size(); i++) {
storagePools.add(null);
}
Set<String> dataDiskIds = dataDiskOfferingMap.keySet();
for (UnmanagedInstanceTO.Disk disk : disks) {
Long capacity = disk.getCapacity();
storagePools.add(pools.get(0).getUuid());
Long diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId());
if (diskOfferingId == null && !dataDiskIds.contains(disk.getDiskId())) {
diskOfferingId = serviceOffering.getDiskOfferingId();
}
//TODO: Choose pools by capacity
if (diskOfferingId == null) {
storagePools.set(disk.getPosition(), pools.get(0).getUuid());
} else {
DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId);
for (StoragePoolVO pool : pools) {
if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags())) {
storagePools.set(disk.getPosition(), pool.getUuid());
break;
}
}
}
}
return storagePools;
}

View File

@ -277,6 +277,7 @@ public class UnmanagedVMsManagerImplTest {
List<UnmanagedInstanceTO.Disk> instanceDisks = new ArrayList<>();
UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk();
instanceDisk.setDiskId("1000-1");
instanceDisk.setPosition(0);
instanceDisk.setLabel("DiskLabel");
instanceDisk.setController("scsi");
instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk");
@ -423,6 +424,7 @@ public class UnmanagedVMsManagerImplTest {
ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class);
when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance");
when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null);
when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd);
}
@ -702,6 +704,8 @@ public class UnmanagedVMsManagerImplTest {
when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer);
}
when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class);
ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class);
when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE);