Skip to content

Commit a429813

Browse files
Skip stale destroyed volumes in local storage checks
1 parent f6efda5 commit a429813

2 files changed

Lines changed: 70 additions & 2 deletions

File tree

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7660,11 +7660,27 @@ private boolean isImplicitPlannerUsedByOffering(long offeringId) {
76607660

76617661
protected boolean isAnyVmVolumeUsingLocalStorage(final List<VolumeVO> volumes) {
76627662
for (VolumeVO vol : volumes) {
7663+
if (vol == null || vol.getRemoved() != null ||
7664+
Volume.State.Destroy.equals(vol.getState()) ||
7665+
Volume.State.Expunged.equals(vol.getState())) {
7666+
logger.debug("Skipping non-active volume while checking local storage usage: {}", vol);
7667+
continue;
7668+
}
76637669
DiskOfferingVO diskOffering = _diskOfferingDao.findById(vol.getDiskOfferingId());
7664-
if (diskOffering.isUseLocalStorage()) {
7670+
if (diskOffering != null && diskOffering.isUseLocalStorage()) {
76657671
return true;
76667672
}
7667-
StoragePoolVO storagePool = _storagePoolDao.findById(vol.getPoolId());
7673+
Long poolId = vol.getPoolId();
7674+
if (poolId == null) {
7675+
logger.debug("Skipping volume without storage pool while checking local storage usage: {}", vol);
7676+
continue;
7677+
}
7678+
StoragePoolVO storagePool = _storagePoolDao.findById(poolId);
7679+
if (storagePool == null || storagePool.getRemoved() != null) {
7680+
throw new CloudRuntimeException(String.format(
7681+
"Cannot determine local storage usage for active volume %s because storage pool ID %s is missing or removed",
7682+
vol, poolId));
7683+
}
76687684
if (storagePool.isLocal()) {
76697685
return true;
76707686
}

server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,58 @@ public void testIsAnyVmVolumeUsingLocalStorage() {
12641264
}
12651265
}
12661266

1267+
@Test
1268+
public void testIsAnyVmVolumeUsingLocalStorageSkipsDestroyedVolumeWithMissingPool() {
1269+
VolumeVO volume = Mockito.mock(VolumeVO.class);
1270+
Mockito.when(volume.getState()).thenReturn(Volume.State.Destroy);
1271+
1272+
Assert.assertFalse(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(Collections.singletonList(volume)));
1273+
Mockito.verify(primaryDataStoreDao, never()).findById(anyLong());
1274+
}
1275+
1276+
@Test
1277+
public void testIsAnyVmVolumeUsingLocalStorageSkipsRemovedVolume() {
1278+
VolumeVO volume = Mockito.mock(VolumeVO.class);
1279+
Mockito.when(volume.getRemoved()).thenReturn(new Date());
1280+
1281+
Assert.assertFalse(userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(Collections.singletonList(volume)));
1282+
Mockito.verify(primaryDataStoreDao, never()).findById(anyLong());
1283+
}
1284+
1285+
@Test
1286+
public void testIsAnyVmVolumeUsingLocalStorageFailsForActiveVolumeWithMissingPool() {
1287+
VolumeVO volume = Mockito.mock(VolumeVO.class);
1288+
Mockito.when(volume.getState()).thenReturn(Volume.State.Ready);
1289+
Mockito.when(volume.getDiskOfferingId()).thenReturn(1L);
1290+
Mockito.when(volume.getPoolId()).thenReturn(2L);
1291+
DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
1292+
Mockito.when(diskOfferingDao.findById(1L)).thenReturn(diskOffering);
1293+
Mockito.when(diskOffering.isUseLocalStorage()).thenReturn(false);
1294+
Mockito.when(primaryDataStoreDao.findById(2L)).thenReturn(null);
1295+
1296+
CloudRuntimeException exception = assertThrows(CloudRuntimeException.class, () ->
1297+
userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(Collections.singletonList(volume)));
1298+
Assert.assertTrue(exception.getMessage().contains("storage pool ID 2 is missing or removed"));
1299+
}
1300+
1301+
@Test
1302+
public void testIsAnyVmVolumeUsingLocalStorageFailsForActiveVolumeWithRemovedPool() {
1303+
VolumeVO volume = Mockito.mock(VolumeVO.class);
1304+
Mockito.when(volume.getState()).thenReturn(Volume.State.Ready);
1305+
Mockito.when(volume.getDiskOfferingId()).thenReturn(1L);
1306+
Mockito.when(volume.getPoolId()).thenReturn(2L);
1307+
DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
1308+
Mockito.when(diskOfferingDao.findById(1L)).thenReturn(diskOffering);
1309+
Mockito.when(diskOffering.isUseLocalStorage()).thenReturn(false);
1310+
StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class);
1311+
Mockito.when(storagePool.getRemoved()).thenReturn(new Date());
1312+
Mockito.when(primaryDataStoreDao.findById(2L)).thenReturn(storagePool);
1313+
1314+
CloudRuntimeException exception = assertThrows(CloudRuntimeException.class, () ->
1315+
userVmManagerImpl.isAnyVmVolumeUsingLocalStorage(Collections.singletonList(volume)));
1316+
Assert.assertTrue(exception.getMessage().contains("storage pool ID 2 is missing or removed"));
1317+
}
1318+
12671319
private List<VolumeVO> mockVolumesForIsAllVmVolumesOnZoneWideStore(int nullPoolIdVolumes, int nullPoolVolumes, int zoneVolumes, int nonZoneVolumes) {
12681320
List<VolumeVO> volumes = new ArrayList<>();
12691321
for (int i=0; i< nullPoolIdVolumes + nullPoolVolumes + zoneVolumes + nonZoneVolumes; ++i) {

0 commit comments

Comments
 (0)