This is an automated email from the ASF dual-hosted git repository.
gutoveronezi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new a31449b1049 Allow altering only either CPU or memory during VM live
scale (#8234)
a31449b1049 is described below
commit a31449b10490cb386d60fc961f6d3bf3bdb09ccd
Author: GaOrtiga <[email protected]>
AuthorDate: Wed Feb 14 18:57:47 2024 -0300
Allow altering only either CPU or memory during VM live scale (#8234)
* allow change only one parameter during live scale
* Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
Co-authored-by: sato03 <[email protected]>
* apply change method name
* Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
Co-authored-by: João Jandre <[email protected]>
---------
Co-authored-by: Gabriel <[email protected]>
Co-authored-by: sato03 <[email protected]>
Co-authored-by: João Jandre <[email protected]>
---
.../main/java/com/cloud/vm/UserVmManagerImpl.java | 41 +++++++++++-
.../java/com/cloud/vm/UserVmManagerImplTest.java | 76 ++++++++++++++++++++++
2 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 063ed09c839..99b334a9f74 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -399,7 +399,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
@Inject
private VMTemplateZoneDao _templateZoneDao;
@Inject
- private TemplateDataStoreDao _templateStoreDao;
+ protected TemplateDataStoreDao _templateStoreDao;
@Inject
private DomainDao _domainDao;
@Inject
@@ -1226,6 +1226,39 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
return userVm;
}
+ /**
+ Updates the instance details map with the current values of the instance
for the CPU speed, memory, and CPU number if they have not been specified.
+ @param details Map containing the instance details.
+ @param vmInstance The virtual machine instance.
+ @param newServiceOfferingId The ID of the new service offering.
+ */
+
+ protected void updateInstanceDetails (Map<String, String> details,
VirtualMachine vmInstance, Long newServiceOfferingId) {
+ ServiceOfferingVO currentServiceOffering =
serviceOfferingDao.findByIdIncludingRemoved(vmInstance.getId(),
vmInstance.getServiceOfferingId());
+ ServiceOfferingVO newServiceOffering =
serviceOfferingDao.findById(newServiceOfferingId);
+
updateInstanceDetailsKeepCurrentValueIfNull(newServiceOffering.getSpeed(),
details, VmDetailConstants.CPU_SPEED, currentServiceOffering.getSpeed());
+
updateInstanceDetailsKeepCurrentValueIfNull(newServiceOffering.getRamSize(),
details, VmDetailConstants.MEMORY, currentServiceOffering.getRamSize());
+
updateInstanceDetailsKeepCurrentValueIfNull(newServiceOffering.getCpu(),
details, VmDetailConstants.CPU_NUMBER, currentServiceOffering.getCpu());
+ }
+
+ /**
+ * Updates a specific instance detail with the current instance value if
the new value is null.
+ *
+ * @param newValue the new value to be set
+ * @param details a map of instance details
+ * @param detailsConstant the name of the detail constant to be updated
+ * @param currentValue the current value of the detail constant
+ */
+
+ protected void updateInstanceDetailsKeepCurrentValueIfNull(Integer
newValue, Map<String, String> details, String detailsConstant, Integer
currentValue) {
+ if (newValue == null && details.get(detailsConstant) == null) {
+ String currentValueString = String.valueOf(currentValue);
+ logger.debug("{} was not specified, keeping the current value:
{}.", detailsConstant, currentValueString);
+ details.put(detailsConstant, currentValueString);
+ }
+ }
+
+
private void validateOfferingMaxResource(ServiceOfferingVO offering) {
Integer maxCPUCores =
ConfigurationManagerImpl.VM_SERVICE_OFFERING_MAX_CPU_CORES.value() == 0 ?
Integer.MAX_VALUE:
ConfigurationManagerImpl.VM_SERVICE_OFFERING_MAX_CPU_CORES.value();
if (offering.getCpu() > maxCPUCores) {
@@ -1891,7 +1924,11 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
}
CallContext.current().setEventDetails("Vm Id: " + vm.getUuid());
- boolean result = upgradeVirtualMachine(vmId, newServiceOfferingId,
cmd.getDetails());
+ Map<String, String> cmdDetails = cmd.getDetails();
+
+ updateInstanceDetails(cmdDetails, vm, newServiceOfferingId);
+
+ boolean result = upgradeVirtualMachine(vmId, newServiceOfferingId,
cmdDetails);
if (result) {
UserVmVO vmInstance = _vmDao.findById(vmId);
if (vmInstance.getState().equals(State.Stopped)) {
diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
index 13b937789f2..ffd0c407f13 100644
--- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
+++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
@@ -267,6 +267,9 @@ public class UserVmManagerImplTest {
@Mock
ServiceOfferingJoinDao serviceOfferingJoinDao;
+ @Mock
+ private VMInstanceVO vmInstanceMock;
+
private static final long vmId = 1l;
private static final long zoneId = 2L;
private static final long accountId = 3L;
@@ -277,6 +280,8 @@ public class UserVmManagerImplTest {
private Map<String, String> customParameters = new HashMap<>();
+ String[] detailsConstants = {VmDetailConstants.MEMORY,
VmDetailConstants.CPU_NUMBER, VmDetailConstants.CPU_SPEED};
+
private DiskOfferingVO smallerDisdkOffering = prepareDiskOffering(5l *
GiB_TO_BYTES, 1l, 1L, 2L);
private DiskOfferingVO largerDisdkOffering = prepareDiskOffering(10l *
GiB_TO_BYTES, 2l, 10L, 20L);
@@ -293,6 +298,10 @@ public class UserVmManagerImplTest {
CallContext.register(callerUser, callerAccount);
customParameters.put(VmDetailConstants.ROOT_DISK_SIZE, "123");
+ customParameters.put(VmDetailConstants.MEMORY, "2048");
+ customParameters.put(VmDetailConstants.CPU_NUMBER, "4");
+ customParameters.put(VmDetailConstants.CPU_SPEED, "1000");
+
lenient().doNothing().when(resourceLimitMgr).incrementResourceCount(anyLong(),
any(Resource.ResourceType.class));
lenient().doNothing().when(resourceLimitMgr).decrementResourceCount(anyLong(),
any(Resource.ResourceType.class), anyLong());
@@ -1443,4 +1452,71 @@ public class UserVmManagerImplTest {
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId,
newTemplateId);
}
+
+ @Test
+ public void
updateInstanceDetailsKeepCurrentValueIfNullTestDetailsConstantIsNotNullDoNothing()
{
+ int currentValue = 123;
+
+ for (String detailsConstant : detailsConstants) {
+
userVmManagerImpl.updateInstanceDetailsKeepCurrentValueIfNull(null,
customParameters, detailsConstant, currentValue);
+ }
+
+ Assert.assertEquals(customParameters.get(VmDetailConstants.MEMORY),
"2048");
+
Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_NUMBER), "4");
+ Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_SPEED),
"1000");
+ }
+
+ @Test
+ public void
updateInstanceDetailsKeepCurrentValueIfNullTestNewValueIsNotNullDoNothing() {
+ Map<String, String> details = new HashMap<>();
+ int currentValue = 123;
+
+ for (String detailsConstant : detailsConstants) {
+ userVmManagerImpl.updateInstanceDetailsKeepCurrentValueIfNull(321,
details, detailsConstant, currentValue);
+ }
+
+ Assert.assertNull(details.get(VmDetailConstants.MEMORY));
+ Assert.assertNull(details.get(VmDetailConstants.CPU_NUMBER));
+ Assert.assertNull(details.get(VmDetailConstants.CPU_SPEED));
+ }
+
+ @Test
+ public void
updateInstanceDetailsKeepCurrentValueIfNullTestBothValuesAreNullKeepCurrentValue()
{
+ Map<String, String> details = new HashMap<>();
+ int currentValue = 123;
+
+ for (String detailsConstant : detailsConstants) {
+
userVmManagerImpl.updateInstanceDetailsKeepCurrentValueIfNull(null, details,
detailsConstant, currentValue);
+ }
+
+ Assert.assertEquals(details.get(VmDetailConstants.MEMORY),
String.valueOf(currentValue));
+ Assert.assertEquals(details.get(VmDetailConstants.CPU_NUMBER),
String.valueOf(currentValue));
+
Assert.assertEquals(details.get(VmDetailConstants.CPU_SPEED),String.valueOf(currentValue));
+ }
+
+ @Test
+ public void
updateInstanceDetailsKeepCurrentValueIfNullTestNeitherValueIsNullDoNothing() {
+ int currentValue = 123;
+
+ for (String detailsConstant : detailsConstants) {
+ userVmManagerImpl.updateInstanceDetailsKeepCurrentValueIfNull(321,
customParameters, detailsConstant, currentValue);
+ }
+
+ Assert.assertEquals(customParameters.get(VmDetailConstants.MEMORY),
"2048");
+
Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_NUMBER), "4");
+
Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_SPEED),"1000");
+ }
+
+ @Test
+ public void updateInstanceDetailsTestAllConstantsAreUpdated() {
+
Mockito.doReturn(serviceOffering).when(_serviceOfferingDao).findById(Mockito.anyLong());
+ Mockito.doReturn(1L).when(vmInstanceMock).getId();
+ Mockito.doReturn(1L).when(vmInstanceMock).getServiceOfferingId();
+
Mockito.doReturn(serviceOffering).when(_serviceOfferingDao).findByIdIncludingRemoved(Mockito.anyLong(),
Mockito.anyLong());
+ userVmManagerImpl.updateInstanceDetails(null, vmInstanceMock, 0l);
+
+
Mockito.verify(userVmManagerImpl).updateInstanceDetailsKeepCurrentValueIfNull(Mockito.any(),
Mockito.any(), Mockito.eq(VmDetailConstants.CPU_SPEED), Mockito.any());
+
Mockito.verify(userVmManagerImpl).updateInstanceDetailsKeepCurrentValueIfNull(Mockito.any(),
Mockito.any(), Mockito.eq(VmDetailConstants.MEMORY), Mockito.any());
+
Mockito.verify(userVmManagerImpl).updateInstanceDetailsKeepCurrentValueIfNull(Mockito.any(),
Mockito.any(), Mockito.eq(VmDetailConstants.CPU_NUMBER), Mockito.any());
+ }
}