mirror of https://github.com/apache/cloudstack.git
Preserve VM settings on Instance Snapshot revert for Custom Service Offering (#12555)
This commit is contained in:
parent
ce42ce54c2
commit
9ae696d1c8
|
|
@ -23,6 +23,7 @@ import java.util.Date;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
|
@ -182,6 +183,11 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
Long.class, "vm.job.check.interval", "3000",
|
||||
"Interval in milliseconds to check if the job is complete", false);
|
||||
|
||||
private static final Set<String> VM_SNAPSHOT_CUSTOM_SERVICE_OFFERING_DETAILS = Set.of(
|
||||
VmDetailConstants.CPU_NUMBER.toLowerCase(),
|
||||
VmDetailConstants.CPU_SPEED.toLowerCase(),
|
||||
VmDetailConstants.MEMORY.toLowerCase());
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
_name = name;
|
||||
|
|
@ -473,7 +479,8 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
}
|
||||
|
||||
/**
|
||||
* Add entries on vm_snapshot_details if service offering is dynamic. This will allow setting details when revert to vm snapshot
|
||||
* Add entries about cpu, cpu_speed and memory in vm_snapshot_details if service offering is dynamic.
|
||||
* This will allow setting details when revert to vm snapshot.
|
||||
* @param vmId vm id
|
||||
* @param serviceOfferingId service offering id
|
||||
* @param vmSnapshotId vm snapshot id
|
||||
|
|
@ -484,7 +491,7 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
List<UserVmDetailVO> vmDetails = _userVmDetailsDao.listDetails(vmId);
|
||||
List<VMSnapshotDetailsVO> vmSnapshotDetails = new ArrayList<VMSnapshotDetailsVO>();
|
||||
for (UserVmDetailVO detail : vmDetails) {
|
||||
if(detail.getName().equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || detail.getName().equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || detail.getName().equalsIgnoreCase(VmDetailConstants.MEMORY)) {
|
||||
if (VM_SNAPSHOT_CUSTOM_SERVICE_OFFERING_DETAILS.contains(detail.getName().toLowerCase())) {
|
||||
vmSnapshotDetails.add(new VMSnapshotDetailsVO(vmSnapshotId, detail.getName(), detail.getValue(), detail.isDisplay()));
|
||||
}
|
||||
}
|
||||
|
|
@ -931,7 +938,7 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<CloudRuntimeException>() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws CloudRuntimeException {
|
||||
revertUserVmDetailsFromVmSnapshot(userVm, vmSnapshotVo);
|
||||
revertCustomServiceOfferingDetailsFromVmSnapshot(userVm, vmSnapshotVo);
|
||||
updateUserVmServiceOffering(userVm, vmSnapshotVo);
|
||||
}
|
||||
});
|
||||
|
|
@ -943,19 +950,19 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
}
|
||||
|
||||
/**
|
||||
* Update or add user vm details from vm snapshot for vms with custom service offerings
|
||||
* Update or add user vm details (cpu, cpu_speed and memory) from vm snapshot for vms with custom service offerings
|
||||
* @param userVm user vm
|
||||
* @param vmSnapshotVo vm snapshot
|
||||
*/
|
||||
protected void revertUserVmDetailsFromVmSnapshot(UserVmVO userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
protected void revertCustomServiceOfferingDetailsFromVmSnapshot(UserVmVO userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
ServiceOfferingVO serviceOfferingVO = _serviceOfferingDao.findById(vmSnapshotVo.getServiceOfferingId());
|
||||
if (serviceOfferingVO.isDynamic()) {
|
||||
List<VMSnapshotDetailsVO> vmSnapshotDetails = _vmSnapshotDetailsDao.listDetails(vmSnapshotVo.getId());
|
||||
List<UserVmDetailVO> userVmDetails = new ArrayList<UserVmDetailVO>();
|
||||
for (VMSnapshotDetailsVO detail : vmSnapshotDetails) {
|
||||
userVmDetails.add(new UserVmDetailVO(userVm.getId(), detail.getName(), detail.getValue(), detail.isDisplay()));
|
||||
if (VM_SNAPSHOT_CUSTOM_SERVICE_OFFERING_DETAILS.contains(detail.getName().toLowerCase())) {
|
||||
_userVmDetailsDao.addDetail(userVm.getId(), detail.getName(), detail.getValue(), detail.isDisplay());
|
||||
}
|
||||
}
|
||||
_userVmDetailsDao.saveDetails(userVmDetails);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import com.cloud.vm.UserVmManager;
|
|||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
|
@ -67,7 +68,6 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
|
|
@ -79,13 +79,18 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
|
@ -225,13 +230,13 @@ public class VMSnapshotManagerTest {
|
|||
when(_serviceOfferingDao.findById(SERVICE_OFFERING_ID)).thenReturn(serviceOffering);
|
||||
|
||||
for (ResourceDetail detail : Arrays.asList(userVmDetailCpuNumber, vmSnapshotDetailCpuNumber)) {
|
||||
when(detail.getName()).thenReturn("cpuNumber");
|
||||
when(detail.getName()).thenReturn(VmDetailConstants.CPU_NUMBER);
|
||||
when(detail.getValue()).thenReturn("2");
|
||||
when(detail.isDisplay()).thenReturn(true);
|
||||
}
|
||||
|
||||
for (ResourceDetail detail : Arrays.asList(userVmDetailMemory, vmSnapshotDetailMemory)) {
|
||||
when(detail.getName()).thenReturn("memory");
|
||||
when(detail.getName()).thenReturn(VmDetailConstants.MEMORY);
|
||||
when(detail.getValue()).thenReturn("2048");
|
||||
when(detail.isDisplay()).thenReturn(true);
|
||||
}
|
||||
|
|
@ -348,12 +353,12 @@ public class VMSnapshotManagerTest {
|
|||
@Test
|
||||
public void testUpdateUserVmServiceOfferingDifferentServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(userVm.getServiceOfferingId()).thenReturn(SERVICE_OFFERING_DIFFERENT_ID);
|
||||
when(_userVmManager.upgradeVirtualMachine(ArgumentMatchers.eq(TEST_VM_ID), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
_vmSnapshotMgr.updateUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
|
||||
verify(_vmSnapshotMgr).changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(ArgumentMatchers.eq(userVm), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -368,18 +373,18 @@ public class VMSnapshotManagerTest {
|
|||
|
||||
@Test
|
||||
public void testChangeUserVmServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(ArgumentMatchers.eq(TEST_VM_ID), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(ArgumentMatchers.eq(userVm), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test(expected=CloudRuntimeException.class)
|
||||
public void testChangeUserVmServiceOfferingFailOnUpgradeVMServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(ArgumentMatchers.eq(TEST_VM_ID), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(false);
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(false);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(ArgumentMatchers.eq(userVm), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -396,16 +401,27 @@ public class VMSnapshotManagerTest {
|
|||
|
||||
@Test
|
||||
public void testRevertUserVmDetailsFromVmSnapshotNotDynamicServiceOffering() {
|
||||
_vmSnapshotMgr.revertUserVmDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
_vmSnapshotMgr.revertCustomServiceOfferingDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
verify(_vmSnapshotDetailsDao, never()).listDetails(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevertUserVmDetailsFromVmSnapshotDynamicServiceOffering() {
|
||||
when(serviceOffering.isDynamic()).thenReturn(true);
|
||||
_vmSnapshotMgr.revertUserVmDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
verify(_vmSnapshotDetailsDao).listDetails(VM_SNAPSHOT_ID);
|
||||
verify(_userVmDetailsDao).saveDetails(listUserVmDetailsCaptor.capture());
|
||||
}
|
||||
VMSnapshotDetailsVO uefiSnapshotDetail = new VMSnapshotDetailsVO(VM_SNAPSHOT_ID, "UEFI", "SECURE", true);
|
||||
List<VMSnapshotDetailsVO> snapshotDetailsWithUefi = Arrays.asList(
|
||||
vmSnapshotDetailCpuNumber, vmSnapshotDetailMemory, uefiSnapshotDetail);
|
||||
when(_vmSnapshotDetailsDao.listDetails(VM_SNAPSHOT_ID)).thenReturn(snapshotDetailsWithUefi);
|
||||
|
||||
_vmSnapshotMgr.revertCustomServiceOfferingDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
|
||||
verify(_vmSnapshotDetailsDao).listDetails(VM_SNAPSHOT_ID);
|
||||
verify(_userVmDetailsDao, never()).saveDetails(any());
|
||||
ArgumentCaptor<String> detailNameCaptor = ArgumentCaptor.forClass(String.class);
|
||||
verify(_userVmDetailsDao, times(2)).addDetail(eq(TEST_VM_ID), detailNameCaptor.capture(), anyString(), anyBoolean());
|
||||
List<String> appliedNames = detailNameCaptor.getAllValues();
|
||||
assertTrue(appliedNames.contains(VmDetailConstants.CPU_NUMBER));
|
||||
assertTrue(appliedNames.contains(VmDetailConstants.MEMORY));
|
||||
assertFalse("UEFI must not be applied from snapshot so that existing UEFI setting is preserved", appliedNames.contains("UEFI"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue