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 <henriquesato2003@gmail.com>

* apply change method name

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

Co-authored-by: João Jandre <48719461+JoaoJandre@users.noreply.github.com>

---------

Co-authored-by: Gabriel <gabriel.fernandes@scclouds.com.br>
Co-authored-by: sato03 <henriquesato2003@gmail.com>
Co-authored-by: João Jandre <48719461+JoaoJandre@users.noreply.github.com>
This commit is contained in:
GaOrtiga 2024-02-14 18:57:47 -03:00 committed by GitHub
parent 4a0ca2071d
commit a31449b104
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 115 additions and 2 deletions

View File

@ -399,7 +399,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Inject @Inject
private VMTemplateZoneDao _templateZoneDao; private VMTemplateZoneDao _templateZoneDao;
@Inject @Inject
private TemplateDataStoreDao _templateStoreDao; protected TemplateDataStoreDao _templateStoreDao;
@Inject @Inject
private DomainDao _domainDao; private DomainDao _domainDao;
@Inject @Inject
@ -1226,6 +1226,39 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return userVm; 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) { 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(); 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) { if (offering.getCpu() > maxCPUCores) {
@ -1891,7 +1924,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
CallContext.current().setEventDetails("Vm Id: " + vm.getUuid()); 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) { if (result) {
UserVmVO vmInstance = _vmDao.findById(vmId); UserVmVO vmInstance = _vmDao.findById(vmId);
if (vmInstance.getState().equals(State.Stopped)) { if (vmInstance.getState().equals(State.Stopped)) {

View File

@ -267,6 +267,9 @@ public class UserVmManagerImplTest {
@Mock @Mock
ServiceOfferingJoinDao serviceOfferingJoinDao; ServiceOfferingJoinDao serviceOfferingJoinDao;
@Mock
private VMInstanceVO vmInstanceMock;
private static final long vmId = 1l; private static final long vmId = 1l;
private static final long zoneId = 2L; private static final long zoneId = 2L;
private static final long accountId = 3L; private static final long accountId = 3L;
@ -277,6 +280,8 @@ public class UserVmManagerImplTest {
private Map<String, String> customParameters = new HashMap<>(); 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 smallerDisdkOffering = prepareDiskOffering(5l * GiB_TO_BYTES, 1l, 1L, 2L);
private DiskOfferingVO largerDisdkOffering = prepareDiskOffering(10l * GiB_TO_BYTES, 2l, 10L, 20L); private DiskOfferingVO largerDisdkOffering = prepareDiskOffering(10l * GiB_TO_BYTES, 2l, 10L, 20L);
@ -293,6 +298,10 @@ public class UserVmManagerImplTest {
CallContext.register(callerUser, callerAccount); CallContext.register(callerUser, callerAccount);
customParameters.put(VmDetailConstants.ROOT_DISK_SIZE, "123"); 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).incrementResourceCount(anyLong(), any(Resource.ResourceType.class));
lenient().doNothing().when(resourceLimitMgr).decrementResourceCount(anyLong(), any(Resource.ResourceType.class), anyLong()); lenient().doNothing().when(resourceLimitMgr).decrementResourceCount(anyLong(), any(Resource.ResourceType.class), anyLong());
@ -1443,4 +1452,71 @@ public class UserVmManagerImplTest {
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId); 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());
}
} }