diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 1a2edb58a002..11b24a9beef6 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -1456,11 +1456,13 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) { volumeResizeRequired = true; } - if (!volumeMigrateRequired && !volumeResizeRequired && newDiskOffering != null) { - _volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId()); - volume = _volsDao.findById(volume.getId()); - updateStorageWithTheNewDiskOffering(volume, newDiskOffering); + if (!volumeMigrateRequired && !volumeResizeRequired) { + if (newDiskOffering != null && newDiskOffering.getId() != diskOffering.getId()) { + _volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId()); + volume = _volsDao.findById(volume.getId()); + updateStorageWithTheNewDiskOffering(volume, newDiskOffering); + } return volume; } diff --git a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java index 334bb3f659fd..401b12ebbf46 100644 --- a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java @@ -55,6 +55,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -2058,6 +2059,75 @@ public void testResizeVolumeInAllocateState() throws ResourceAllocationException verify(volumeServiceMock, times(0)).resize(any(VolumeInfo.class)); } } + + @Test + public void testResizeVolumeNoChangeSkipsDriver() throws ResourceAllocationException, ExecutionException, InterruptedException { + ResizeVolumeCmd cmd = new ResizeVolumeCmd(); + ReflectionTestUtils.setField(cmd, "id", volumeMockId); + + testResizeVolumeSetup(); + when(storageMgr.storagePoolHasEnoughSpaceForResize(any(), nullable(Long.class), nullable(Long.class))).thenReturn(true); + + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class)) { + Volume result = volumeApiServiceImpl.resizeVolume(cmd); + + Assert.assertSame(volumeVoMock, result); + verify(volumeServiceMock, times(0)).resize(any(VolumeInfo.class)); + verify(volumeDaoMock, times(0)).updateDiskOffering(anyLong(), anyLong()); + } + } + + @Test + public void testResizeVolumeSameDiskOfferingSkipsDriver() throws ResourceAllocationException, ExecutionException, InterruptedException { + ResizeVolumeCmd cmd = new ResizeVolumeCmd(); + ReflectionTestUtils.setField(cmd, "id", volumeMockId); + ReflectionTestUtils.setField(cmd, "newDiskOfferingId", newDiskOfferingMockId); + + testResizeVolumeSetup(); + when(newDiskOfferingMock.getDiskSize()).thenReturn(volumeSizeMock); + when(diskOfferingMock.getId()).thenReturn(diskOfferingMockId); + when(newDiskOfferingMock.getId()).thenReturn(diskOfferingMockId); + when(storageMgr.storagePoolHasEnoughSpaceForResize(any(), nullable(Long.class), nullable(Long.class))).thenReturn(true); + + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class)) { + Volume result = volumeApiServiceImpl.resizeVolume(cmd); + + Assert.assertSame(volumeVoMock, result); + verify(volumeServiceMock, times(0)).resize(any(VolumeInfo.class)); + verify(volumeDaoMock, times(0)).updateDiskOffering(anyLong(), anyLong()); + } + } + + @Test + public void testResizeVolumeNewDiskOfferingSameSizeUpdatesOfferingWithoutResize() throws ResourceAllocationException, ExecutionException, InterruptedException { + ResizeVolumeCmd cmd = new ResizeVolumeCmd(); + ReflectionTestUtils.setField(cmd, "id", volumeMockId); + ReflectionTestUtils.setField(cmd, "newDiskOfferingId", newDiskOfferingMockId); + + testResizeVolumeSetup(); + when(newDiskOfferingMock.getDiskSize()).thenReturn(volumeSizeMock); + when(diskOfferingMock.getId()).thenReturn(diskOfferingMockId); + when(newDiskOfferingMock.getId()).thenReturn(newDiskOfferingMockId); + when(storageMgr.storagePoolHasEnoughSpaceForResize(any(), nullable(Long.class), nullable(Long.class))).thenReturn(true); + + DataStore offeringStore = Mockito.mock(DataStore.class); + PrimaryDataStoreDriver driver = Mockito.mock(PrimaryDataStoreDriver.class); + when(dataStoreMgr.getDataStore(anyLong(), eq(DataStoreRole.Primary))).thenReturn(offeringStore); + when(offeringStore.getDriver()).thenReturn(driver); + when(driver.informStorageForDiskOfferingChange()).thenReturn(true); + + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class)) { + Mockito.clearInvocations(volumeDaoMock); + Volume result = volumeApiServiceImpl.resizeVolume(cmd); + + Assert.assertSame(volumeVoMock, result); + verify(volumeDaoMock).updateDiskOffering(volumeMockId, newDiskOfferingMockId); + verify(volumeDaoMock, times(2)).findById(volumeMockId); + verify(driver).updateStorageWithTheNewDiskOffering(volumeVoMock, newDiskOfferingMock); + verify(volumeServiceMock, times(0)).resize(any(VolumeInfo.class)); + } + } + private UserVmVO getMockedVm() { UserVmVO vm = Mockito.mock(UserVmVO.class); Mockito.when(vm.getId()).thenReturn(1L);