This commit is contained in:
Andrija Panic 2026-07-04 15:34:33 +01:00 committed by GitHub
commit 114917f377
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 108 additions and 9 deletions

View File

@ -1679,6 +1679,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, ApiConstants.USE_VDDK));
}
convertStoragePoolId = resolveImplicitConversionStoragePoolId(destinationCluster, convertStoragePoolId, forceConvertToPool);
checkConversionStoragePool(convertStoragePoolId, forceConvertToPool);
validateSelectedConversionStoragePoolForVddk(useVddk, convertStoragePoolId, serviceOffering, dataDiskOfferingMap);
@ -1816,6 +1817,45 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
}
}
protected Long resolveImplicitConversionStoragePoolId(Cluster destinationCluster, Long convertStoragePoolId,
boolean forceConvertToPool) {
if (!forceConvertToPool || convertStoragePoolId != null) {
return convertStoragePoolId;
}
List<StoragePoolVO> candidatePools = getImplicitForceConvertToPoolStoragePools(destinationCluster);
if (candidatePools.isEmpty()) {
logFailureAndThrowException(String.format("The parameter forceconverttopool is set to true, but no suitable primary storage pool was found in cluster %s",
destinationCluster.getName()));
}
if (candidatePools.size() > 1) {
logFailureAndThrowException(String.format("The parameter forceconverttopool is set to true, but multiple suitable primary storage pools were found in cluster %s. Please provide convertinstancepoolid.",
destinationCluster.getName()));
}
StoragePoolVO implicitPool = candidatePools.get(0);
logger.debug("The parameter forceconverttopool is set to true and no conversion storage pool was provided; using the only suitable primary storage pool [{}].",
implicitPool.getName());
return implicitPool.getId();
}
private List<StoragePoolVO> getImplicitForceConvertToPoolStoragePools(Cluster destinationCluster) {
Set<StoragePoolVO> pools = new HashSet<>();
for (Storage.StoragePoolType poolType : forceConvertToPoolAllowedTypes) {
List<StoragePoolVO> clusterPools = primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(),
Hypervisor.HypervisorType.KVM, poolType);
if (clusterPools != null) {
pools.addAll(clusterPools);
}
List<StoragePoolVO> zonePools = primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(),
Hypervisor.HypervisorType.KVM, poolType);
if (zonePools != null) {
pools.addAll(zonePools);
}
}
return new ArrayList<>(pools);
}
protected void validateSelectedConversionStoragePoolForVddk(boolean useVddk, Long convertStoragePoolId,
ServiceOfferingVO serviceOffering, Map<String, Long> dataDiskOfferingMap) {
if (!useVddk || convertStoragePoolId == null) {

View File

@ -1405,6 +1405,46 @@ public class UnmanagedVMsManagerImplTest {
unmanagedVMsManager.checkConversionStoragePool(null, true);
}
@Test
public void testResolveImplicitConversionStoragePoolIdUsesSingleSuitablePoolWhenForceConvertToPool() {
ClusterVO cluster = getClusterForTests();
StoragePoolVO storagePool = mock(StoragePoolVO.class);
when(storagePool.getId()).thenReturn(42L);
when(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(cluster.getId(),
Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem))
.thenReturn(List.of(storagePool));
Long storagePoolId = unmanagedVMsManager.resolveImplicitConversionStoragePoolId(cluster, null, true);
Assert.assertEquals(Long.valueOf(42L), storagePoolId);
}
@Test
public void testResolveImplicitConversionStoragePoolIdKeepsExplicitPoolWhenForceConvertToPool() {
ClusterVO cluster = getClusterForTests();
Long storagePoolId = unmanagedVMsManager.resolveImplicitConversionStoragePoolId(cluster, 42L, true);
Assert.assertEquals(Long.valueOf(42L), storagePoolId);
Mockito.verifyNoInteractions(primaryDataStoreDao);
}
@Test(expected = CloudRuntimeException.class)
public void testResolveImplicitConversionStoragePoolIdFailsWhenMultiplePoolsFound() {
ClusterVO cluster = getClusterForTests();
when(cluster.getName()).thenReturn("cluster-1");
StoragePoolVO firstStoragePool = mock(StoragePoolVO.class);
StoragePoolVO secondStoragePool = mock(StoragePoolVO.class);
when(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(cluster.getId(),
Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem))
.thenReturn(List.of(firstStoragePool));
when(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(cluster.getDataCenterId(),
Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem))
.thenReturn(List.of(secondStoragePool));
unmanagedVMsManager.resolveImplicitConversionStoragePoolId(cluster, null, true);
}
@Test
public void testCheckConversionStoragePoolPrimaryStagingPool() {
StoragePoolVO destPool = mock(StoragePoolVO.class);

View File

@ -1085,11 +1085,7 @@ export default {
}
getAPI('listStoragePools', params).then(json => {
this.storagePoolsForConversion = json.liststoragepoolsresponse.storagepool || []
// Keep selected pool state aligned when the value is auto-populated by v-model.
if (this.form.convertstoragepoolid) {
const poolExists = this.storagePoolsForConversion.some(pool => pool.id === this.form.convertstoragepoolid)
this.selectedStoragePoolForConversion = poolExists ? this.form.convertstoragepoolid : null
}
this.syncSelectedStoragePoolForConversion()
})
} else if (this.selectedStorageOptionForConversion === 'local') {
const kvmHost = this.kvmHostsForConversion.filter(x => x.id === this.selectedKvmHostForConversion)[0]
@ -1099,13 +1095,25 @@ export default {
status: 'Up'
}).then(json => {
this.storagePoolsForConversion = json.liststoragepoolsresponse.storagepool || []
if (this.form.convertstoragepoolid) {
const poolExists = this.storagePoolsForConversion.some(pool => pool.id === this.form.convertstoragepoolid)
this.selectedStoragePoolForConversion = poolExists ? this.form.convertstoragepoolid : null
}
this.syncSelectedStoragePoolForConversion()
})
}
},
syncSelectedStoragePoolForConversion () {
if (this.form.convertstoragepoolid) {
const poolExists = this.storagePoolsForConversion.some(pool => pool.id === this.form.convertstoragepoolid)
if (poolExists) {
this.selectedStoragePoolForConversion = this.form.convertstoragepoolid
return
}
this.form.convertstoragepoolid = null
this.selectedStoragePoolForConversion = null
}
if (this.storagePoolsForConversion.length === 1) {
this.form.convertstoragepoolid = this.storagePoolsForConversion[0].id
this.selectedStoragePoolForConversion = this.form.convertstoragepoolid
}
},
updateSelectedKvmHostForImporting (clusterid, checked, value) {
if (checked) {
this.selectedKvmHostForImporting = value
@ -1162,6 +1170,9 @@ export default {
this.selectedStoragePoolForConversion = null
this.showStoragePoolsForConversion = false
this.resetStorageOptionsForConversion()
if (val) {
this.selectPrimaryStorageForForcedConversion()
}
},
onUseVddkChange (val, isUserChange = true) {
if (isUserChange) {
@ -1186,6 +1197,14 @@ export default {
this.fetchKvmHostsForConversion()
}
this.resetStorageOptionsForConversion()
if (val) {
this.selectPrimaryStorageForForcedConversion()
}
},
selectPrimaryStorageForForcedConversion () {
this.selectedStorageOptionForConversion = 'primary'
this.showStoragePoolsForConversion = true
this.fetchStoragePoolsForConversion()
},
updateSelectedRootDisk () {
var rootDisk = this.resource.disk[this.selectedRootDiskIndex]