Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, ApiConstants.USE_VDDK));
}

convertStoragePoolId = resolveImplicitConversionStoragePoolId(destinationCluster, convertStoragePoolId, forceConvertToPool);
checkConversionStoragePool(convertStoragePoolId, forceConvertToPool);
validateSelectedConversionStoragePoolForVddk(useVddk, convertStoragePoolId, serviceOffering, dataDiskOfferingMap);

Expand Down Expand Up @@ -1816,6 +1817,45 @@ protected void checkConversionStoragePool(Long convertStoragePoolId, boolean for
}
}

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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,46 @@ public void testCheckConversionStoragePoolTemporarySecondaryStorageForceConvertT
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);
Expand Down
37 changes: 28 additions & 9 deletions ui/src/views/tools/ImportUnmanagedInstance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down Expand Up @@ -1162,6 +1170,9 @@ export default {
this.selectedStoragePoolForConversion = null
this.showStoragePoolsForConversion = false
this.resetStorageOptionsForConversion()
if (val) {
this.selectPrimaryStorageForForcedConversion()
}
},
onUseVddkChange (val, isUserChange = true) {
if (isUserChange) {
Expand All @@ -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]
Expand Down
Loading