From baf1c859a0e2e58df8c06dd865045d2fa1e81a97 Mon Sep 17 00:00:00 2001 From: Ramgopal Nagaboina Date: Tue, 1 Sep 2026 12:06:19 -0400 Subject: [PATCH] server: apply the restored volume max IOPS to the max IOPS field getRootVolumeSizeForVmRestore set the requested max IOPS onto the min IOPS field, overwriting the min value and never applying the max, so restoring a VM with an IOPS spec silently corrupted the volume QoS. Set the max IOPS on the max IOPS field. --- .../main/java/com/cloud/vm/UserVmManagerImpl.java | 2 +- .../java/com/cloud/vm/UserVmManagerImplTest.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 8617a2137c92..7037dbfda2ec 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -8665,7 +8665,7 @@ Long getRootVolumeSizeForVmRestore(Volume vol, VMTemplateVO template, UserVmVO u resizedVolume.setMinIops(Long.parseLong(minIops)); } if (StringUtils.isNumeric(maxIops)) { - resizedVolume.setMinIops(Long.parseLong(maxIops)); + resizedVolume.setMaxIops(Long.parseLong(maxIops)); } } } diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java index 15defe25dee3..6626e5af8b14 100644 --- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java +++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java @@ -3207,4 +3207,19 @@ public void verifyVmLimits_constrainedOffering_throwsException() { userVmManagerImpl.verifyVmLimits(userVmVoMock, customParameters)); Assert.assertTrue(ex.getMessage().startsWith("The CPU speed of this offering")); } + + @Test + public void getRootVolumeSizeForVmRestoreAppliesMaxIopsToTheMaxIopsField() { + VolumeVO volume = new VolumeVO(Volume.Type.ROOT, "root", 1L, 1L, 1L, 1L, + com.cloud.storage.Storage.ProvisioningType.THIN, 10L, null, null, null); + UserVmVO restoreVm = Mockito.mock(UserVmVO.class); + Map details = new HashMap<>(); + details.put(ApiConstants.MIN_IOPS, "500"); + details.put(ApiConstants.MAX_IOPS, "2000"); + + userVmManagerImpl.getRootVolumeSizeForVmRestore(volume, null, restoreVm, null, details, true); + + Assert.assertEquals(Long.valueOf(500L), volume.getMinIops()); + Assert.assertEquals(Long.valueOf(2000L), volume.getMaxIops()); + } }