Skip to content

Commit 9ff5318

Browse files
committed
unit tests to improve coverage
1 parent bd5d79c commit 9ff5318

File tree

4 files changed

+193
-7
lines changed

4 files changed

+193
-7
lines changed

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import javax.naming.ConfigurationException;
5050
import javax.persistence.EntityExistsException;
5151

52+
5253
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
5354
import org.apache.cloudstack.annotation.AnnotationService;
5455
import org.apache.cloudstack.annotation.dao.AnnotationDao;
@@ -299,8 +300,8 @@
299300
import com.cloud.vm.VirtualMachine.State;
300301
import com.cloud.vm.dao.NicDao;
301302
import com.cloud.vm.dao.UserVmDao;
302-
import com.cloud.vm.dao.VMInstanceDao;
303303
import com.cloud.vm.dao.VMInstanceDetailsDao;
304+
import com.cloud.vm.dao.VMInstanceDao;
304305
import com.cloud.vm.snapshot.VMSnapshotManager;
305306
import com.cloud.vm.snapshot.VMSnapshotVO;
306307
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@@ -4068,12 +4069,15 @@ protected VirtualMachineTO prepVmSpecForUnmanageCmd(Long vmId, Long hostId) {
40684069
List<VolumeVO> volumes = _volsDao.findUsableVolumesForInstance(vmId);
40694070
for (VolumeVO vol: volumes) {
40704071
VolumeInfo volumeInfo = volumeDataFactory.getVolume(vol.getId());
4071-
DataTO volTO = volumeInfo.getTO();
4072-
DiskTO disk = storageMgr.getDiskWithThrottling(volTO, vol.getVolumeType(), vol.getDeviceId(), vol.getPath(), vm.getServiceOfferingId(), vol.getDiskOfferingId());
4072+
DataTO dataTO = volumeInfo.getTO();
4073+
DiskTO disk = storageMgr.getDiskWithThrottling(dataTO, vol.getVolumeType(), vol.getDeviceId(), vol.getPath(), vm.getServiceOfferingId(), vol.getDiskOfferingId());
40734074
vmProfile.addDisk(disk);
40744075
}
40754076

4076-
Map<String, String> details = vmInstanceDetailsDao.listDetailsKeyPairs(vmId);
4077+
Map<String, String> details = vmInstanceDetailsDao.listDetailsKeyPairs(vmId,
4078+
List.of(VirtualMachineProfile.Param.BootType.getName(), VirtualMachineProfile.Param.BootMode.getName(),
4079+
VirtualMachineProfile.Param.UefiFlag.getName()));
4080+
40774081
if (details.containsKey(VirtualMachineProfile.Param.BootType.getName())) {
40784082
vmProfile.getParameters().put(VirtualMachineProfile.Param.BootType, details.get(VirtualMachineProfile.Param.BootType.getName()));
40794083
}

engine/orchestration/src/test/java/com/cloud/vm/VirtualMachineManagerImplTest.java

Lines changed: 171 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@
1919

2020
import static org.junit.Assert.assertEquals;
2121
import static org.junit.Assert.assertFalse;
22+
import static org.junit.Assert.assertNotNull;
2223
import static org.junit.Assert.assertNull;
24+
import static org.junit.Assert.assertThrows;
2325
import static org.junit.Assert.assertTrue;
2426
import static org.mockito.ArgumentMatchers.any;
27+
import static org.mockito.ArgumentMatchers.anyList;
2528
import static org.mockito.ArgumentMatchers.anyLong;
2629
import static org.mockito.ArgumentMatchers.anyString;
2730
import static org.mockito.ArgumentMatchers.eq;
2831
import static org.mockito.Mockito.doNothing;
2932
import static org.mockito.Mockito.doReturn;
33+
import static org.mockito.Mockito.doThrow;
3034
import static org.mockito.Mockito.mock;
3135
import static org.mockito.Mockito.never;
3236
import static org.mockito.Mockito.times;
@@ -43,10 +47,18 @@
4347
import java.util.UUID;
4448
import java.util.stream.Collectors;
4549

50+
import com.cloud.agent.api.UnmanageInstanceAnswer;
51+
import com.cloud.agent.api.UnmanageInstanceCommand;
52+
import com.cloud.agent.api.to.DataTO;
53+
import com.cloud.agent.api.to.DiskTO;;
54+
import com.cloud.network.Network;
55+
import com.cloud.network.NetworkModel;
4656
import com.cloud.resource.ResourceManager;
4757
import org.apache.cloudstack.api.ApiConstants;
4858
import org.apache.cloudstack.context.CallContext;
4959
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
60+
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
61+
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
5062
import org.apache.cloudstack.framework.config.ConfigKey;
5163
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
5264
import org.apache.cloudstack.framework.extensions.dao.ExtensionDetailsDao;
@@ -61,6 +73,7 @@
6173
import org.junit.Before;
6274
import org.junit.Test;
6375
import org.junit.runner.RunWith;
76+
import org.mockito.ArgumentCaptor;
6477
import org.mockito.InOrder;
6578
import org.mockito.InjectMocks;
6679
import org.mockito.Mock;
@@ -192,6 +205,7 @@ public class VirtualMachineManagerImplTest {
192205
private StoragePoolVO storagePoolVoMock;
193206
private long storagePoolVoMockId = 11L;
194207
private long storagePoolVoMockClusterId = 234L;
208+
private String vmName = "vm1";
195209

196210
@Mock
197211
private VolumeVO volumeVoMock;
@@ -254,6 +268,12 @@ public class VirtualMachineManagerImplTest {
254268
NicDao _nicsDao;
255269
@Mock
256270
NetworkService networkService;
271+
@Mock
272+
NetworkModel networkModel;
273+
@Mock
274+
VolumeDataFactory volumeDataFactoryMock;
275+
@Mock
276+
StorageManager storageManager;
257277

258278
private ConfigDepotImpl configDepotImpl;
259279
private boolean updatedConfigKeyDepot = false;
@@ -263,6 +283,7 @@ public void setup() {
263283
ReflectionTestUtils.getField(VirtualMachineManager.VmMetadataManufacturer, "s_depot");
264284
virtualMachineManagerImpl.setHostAllocators(new ArrayList<>());
265285

286+
when(vmInstanceMock.getName()).thenReturn(vmName);
266287
when(vmInstanceMock.getId()).thenReturn(vmInstanceVoMockId);
267288
when(vmInstanceMock.getServiceOfferingId()).thenReturn(2L);
268289
when(hostMock.getId()).thenReturn(hostMockId);
@@ -1361,7 +1382,7 @@ public void recreateCheckpointsKvmOnVmAfterMigrationTestAgentUnavailableThrowsCl
13611382
Mockito.doReturn(HypervisorType.KVM).when(vmInstanceMock).getHypervisorType();
13621383
Mockito.doReturn(List.of(new VolumeObjectTO())).when(virtualMachineManagerImpl).getVmVolumesWithCheckpointsToRecreate(Mockito.any());
13631384

1364-
Mockito.doThrow(new AgentUnavailableException(0)).when(agentManagerMock).send(Mockito.anyLong(), (Command) any());
1385+
doThrow(new AgentUnavailableException(0)).when(agentManagerMock).send(Mockito.anyLong(), (Command) any());
13651386
Mockito.doNothing().when(snapshotManagerMock).endSnapshotChainForVolume(Mockito.anyLong(), Mockito.any());
13661387

13671388
virtualMachineManagerImpl.recreateCheckpointsKvmOnVmAfterMigration(vmInstanceMock, 0);
@@ -1374,7 +1395,7 @@ public void recreateCheckpointsKvmOnVmAfterMigrationTestOperationTimedoutExcepti
13741395
Mockito.doReturn(HypervisorType.KVM).when(vmInstanceMock).getHypervisorType();
13751396
Mockito.doReturn(List.of(new VolumeObjectTO())).when(virtualMachineManagerImpl).getVmVolumesWithCheckpointsToRecreate(Mockito.any());
13761397

1377-
Mockito.doThrow(new OperationTimedoutException(null, 0, 0, 0, false)).when(agentManagerMock).send(Mockito.anyLong(), (Command) any());
1398+
doThrow(new OperationTimedoutException(null, 0, 0, 0, false)).when(agentManagerMock).send(Mockito.anyLong(), (Command) any());
13781399
Mockito.doNothing().when(snapshotManagerMock).endSnapshotChainForVolume(Mockito.anyLong(), Mockito.any());
13791400

13801401
virtualMachineManagerImpl.recreateCheckpointsKvmOnVmAfterMigration(vmInstanceMock, 0);
@@ -1641,4 +1662,152 @@ public void processPrepareExternalProvisioning_externalHypervisor_sendsCommand()
16411662
virtualMachineManagerImpl.processPrepareExternalProvisioning(true, host, vmProfile, mock(DataCenter.class));
16421663
verify(agentManagerMock).send(anyLong(), any(Command.class));
16431664
}
1665+
1666+
@Test
1667+
public void testPrepVMSpecForUnmanageInstance() {
1668+
// Arrange
1669+
final Long accountId = 1L;
1670+
final Long offeringId = 1L;
1671+
final Long templateId = 1L;
1672+
1673+
// Mock vm
1674+
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
1675+
when(vm.getId()).thenReturn(vmInstanceVoMockId);
1676+
when(vm.getAccountId()).thenReturn(accountId);
1677+
when(vm.getServiceOfferingId()).thenReturn(offeringId);
1678+
when(vm.getTemplateId()).thenReturn(templateId);
1679+
when(vm.getHypervisorType()).thenReturn(HypervisorType.KVM);
1680+
when(vmInstanceDaoMock.findById(vmInstanceVoMockId)).thenReturn(vm);
1681+
1682+
// Mock owner
1683+
AccountVO owner = Mockito.mock(AccountVO.class);
1684+
when(_entityMgr.findById(Account.class, accountId)).thenReturn(owner);
1685+
1686+
ServiceOfferingVO offering = Mockito.mock(ServiceOfferingVO.class);
1687+
when(serviceOfferingDaoMock.findById(vmInstanceVoMockId, offeringId)).thenReturn(offering);
1688+
1689+
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
1690+
when(_entityMgr.findByIdIncludingRemoved(VirtualMachineTemplate.class, templateId)).thenReturn(template);
1691+
1692+
when(hostMock.getClusterId()).thenReturn(clusterMockId);
1693+
1694+
// Mock cpuOvercommitRatio and ramOvercommitRatio
1695+
ClusterDetailsVO cpuOvercommitRatio = Mockito.mock(ClusterDetailsVO.class);
1696+
when(cpuOvercommitRatio.getValue()).thenReturn("1.0");
1697+
when(_clusterDetailsDao.findDetail(clusterMockId, VmDetailConstants.CPU_OVER_COMMIT_RATIO)).thenReturn(cpuOvercommitRatio);
1698+
ClusterDetailsVO ramOvercommitRatio = Mockito.mock(ClusterDetailsVO.class);
1699+
when(ramOvercommitRatio.getValue()).thenReturn("1.0");
1700+
when(_clusterDetailsDao.findDetail(clusterMockId, VmDetailConstants.MEMORY_OVER_COMMIT_RATIO)).thenReturn(ramOvercommitRatio);
1701+
1702+
// Mock NICs
1703+
List<NicVO> nics = new ArrayList<>();
1704+
NicVO nic1 = Mockito.mock(NicVO.class);
1705+
when(nic1.getDeviceId()).thenReturn(1);
1706+
nics.add(nic1);
1707+
NicVO nic2 = Mockito.mock(NicVO.class);
1708+
when(nic2.getDeviceId()).thenReturn(0);
1709+
nics.add(nic2);
1710+
when(_nicsDao.listByVmId(vmInstanceVoMockId)).thenReturn(nics);
1711+
1712+
Network networkMock = Mockito.mock(Network.class);
1713+
when(networkModel.getNetwork(anyLong())).thenReturn(networkMock);
1714+
1715+
when(volumeVoMock.getVolumeType()).thenReturn(Volume.Type.ROOT);
1716+
when(volumeVoMock.getDeviceId()).thenReturn(0L);
1717+
when(volumeVoMock.getPath()).thenReturn("/");
1718+
when(volumeVoMock.getDiskOfferingId()).thenReturn(1L);
1719+
when(volumeDaoMock.findUsableVolumesForInstance(vmInstanceVoMockId)).thenReturn(List.of(volumeVoMock));
1720+
1721+
VolumeInfo volumeInfo = mock(VolumeInfo.class);
1722+
DataTO dataTO = mock(DataTO.class);
1723+
when(volumeInfo.getTO()).thenReturn(dataTO);
1724+
when(volumeDataFactoryMock.getVolume(anyLong())).thenReturn(volumeInfo);
1725+
when(storageManager.getDiskWithThrottling(any(), any(), anyLong(), anyString(), anyLong(), anyLong())).thenReturn(Mockito.mock(DiskTO.class));
1726+
1727+
Map<String, String> details = new HashMap<>();
1728+
details.put(VirtualMachineProfile.Param.BootType.getName(), "BIOS");
1729+
details.put(VirtualMachineProfile.Param.BootMode.getName(), "LEGACY");
1730+
details.put(VirtualMachineProfile.Param.UefiFlag.getName(), "Yes");
1731+
when(vmInstanceDetailsDao.listDetailsKeyPairs(anyLong(), anyList())).thenReturn(details);
1732+
1733+
com.cloud.hypervisor.HypervisorGuru guru = Mockito.mock(com.cloud.hypervisor.HypervisorGuru.class);
1734+
when(_hvGuruMgr.getGuru(HypervisorType.KVM)).thenReturn(guru);
1735+
VirtualMachineTO vmTO = new VirtualMachineTO() {};
1736+
when(guru.implement(any(VirtualMachineProfile.class))).thenAnswer((Answer<VirtualMachineTO>) invocation -> {
1737+
VirtualMachineProfile profile = invocation.getArgument(0);
1738+
assertEquals("BIOS", profile.getParameter(VirtualMachineProfile.Param.BootType));
1739+
return vmTO;
1740+
});
1741+
1742+
// Act
1743+
VirtualMachineTO result = virtualMachineManagerImpl.prepVmSpecForUnmanageCmd(vmInstanceVoMockId, hostMockId);
1744+
1745+
// Assert
1746+
assertNotNull(result);
1747+
assertEquals(vmTO, result);
1748+
verify(_clusterDetailsDao, times(2)).findDetail(eq(clusterMockId), anyString());
1749+
verify(vmInstanceDetailsDao).listDetailsKeyPairs(anyLong(), anyList());
1750+
}
1751+
1752+
@Test
1753+
public void testPersistDomainForKvmForRunningVmSuccess() throws AgentUnavailableException, OperationTimedoutException {
1754+
when(vmInstanceMock.getState()).thenReturn(VirtualMachine.State.Running);
1755+
when(vmInstanceMock.getHostId()).thenReturn(hostMockId);
1756+
UnmanageInstanceAnswer successAnswer = new UnmanageInstanceAnswer(null, true, "success");
1757+
when(agentManagerMock.send(anyLong(), any(Command.class))).thenReturn(successAnswer);
1758+
virtualMachineManagerImpl.persistDomainForKVM(vmInstanceMock);
1759+
ArgumentCaptor<Long> hostIdCaptor = ArgumentCaptor.forClass(Long.class);
1760+
ArgumentCaptor<UnmanageInstanceCommand> commandCaptor = ArgumentCaptor.forClass(UnmanageInstanceCommand.class);
1761+
verify(agentManagerMock).send(hostIdCaptor.capture(), commandCaptor.capture());
1762+
assertEquals(hostMockId, hostIdCaptor.getValue().longValue());
1763+
}
1764+
1765+
@Test
1766+
public void testPersistDomainForKvmForStoppedVmSuccess() throws AgentUnavailableException, OperationTimedoutException {
1767+
when(vmInstanceMock.getState()).thenReturn(VirtualMachine.State.Stopped);
1768+
when(vmInstanceMock.getLastHostId()).thenReturn(1L);
1769+
VirtualMachineTO vmTO = new VirtualMachineTO() {};
1770+
vmTO.setName(vmName);
1771+
doReturn(vmTO).when(virtualMachineManagerImpl).prepVmSpecForUnmanageCmd(vmInstanceVoMockId, 1L);
1772+
UnmanageInstanceAnswer successAnswer = new UnmanageInstanceAnswer(null, true, "success");
1773+
when(agentManagerMock.send(anyLong(), any(UnmanageInstanceCommand.class))).thenReturn(successAnswer);
1774+
virtualMachineManagerImpl.persistDomainForKVM(vmInstanceMock);
1775+
ArgumentCaptor<Long> hostIdCaptor = ArgumentCaptor.forClass(Long.class);
1776+
ArgumentCaptor<UnmanageInstanceCommand> commandCaptor = ArgumentCaptor.forClass(UnmanageInstanceCommand.class);
1777+
verify(agentManagerMock).send(hostIdCaptor.capture(), commandCaptor.capture());
1778+
assertEquals(1L, hostIdCaptor.getValue().longValue());
1779+
UnmanageInstanceCommand sentCommand = commandCaptor.getValue();
1780+
assertNotNull(sentCommand.getVm());
1781+
assertEquals(vmTO, sentCommand.getVm());
1782+
assertEquals(vmName, sentCommand.getInstanceName());
1783+
verify(virtualMachineManagerImpl).prepVmSpecForUnmanageCmd(vmInstanceVoMockId, 1L);
1784+
}
1785+
1786+
@Test
1787+
public void testPersistDomainForKvmForRunningVmAgentFailure() throws AgentUnavailableException, OperationTimedoutException {
1788+
when(vmInstanceMock.getState()).thenReturn(VirtualMachine.State.Running);
1789+
when(vmInstanceMock.getHostId()).thenReturn(hostMockId);
1790+
UnmanageInstanceAnswer failureAnswer = new UnmanageInstanceAnswer(null, false, "failure");
1791+
when(agentManagerMock.send(anyLong(), any(UnmanageInstanceCommand.class))).thenReturn(failureAnswer);
1792+
CloudRuntimeException exception = assertThrows(CloudRuntimeException.class, () -> virtualMachineManagerImpl.persistDomainForKVM(vmInstanceMock));
1793+
assertEquals("Failed to persist domainXML for instance: " + vmName, exception.getMessage());
1794+
}
1795+
1796+
@Test
1797+
public void testPersistDomainForKvmAgentUnavailable() throws AgentUnavailableException, OperationTimedoutException {
1798+
when(vmInstanceMock.getState()).thenReturn(VirtualMachine.State.Running);
1799+
when(vmInstanceMock.getHostId()).thenReturn(hostMockId);
1800+
doThrow(new AgentUnavailableException("Agent down", hostMockId)).when(agentManagerMock).send(anyLong(), any(UnmanageInstanceCommand.class));
1801+
CloudRuntimeException exception = assertThrows(CloudRuntimeException.class, () -> virtualMachineManagerImpl.persistDomainForKVM(vmInstanceMock));
1802+
assertEquals("Failed to send command, agent unavailable", exception.getMessage());
1803+
}
1804+
1805+
@Test
1806+
public void testPersistDomainForKvmOperationTimedOut() throws AgentUnavailableException, OperationTimedoutException {
1807+
when(vmInstanceMock.getState()).thenReturn(VirtualMachine.State.Running);
1808+
when(vmInstanceMock.getHostId()).thenReturn(hostMockId);
1809+
doThrow(new OperationTimedoutException(null, hostMockId, 123L, 60, false)).when(agentManagerMock).send(anyLong(), any(UnmanageInstanceCommand.class));
1810+
CloudRuntimeException exception = assertThrows(CloudRuntimeException.class, () -> virtualMachineManagerImpl.persistDomainForKVM(vmInstanceMock));
1811+
assertEquals("Failed to send command, operation timed out", exception.getMessage());
1812+
}
16441813
}

server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2205,7 +2205,7 @@ public List<Class<?>> getCommands() {
22052205
* - VM must not have any associated volume snapshot
22062206
* - VM must not have an attached ISO
22072207
*/
2208-
private void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) {
2208+
void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) {
22092209
if (hasVolumeSnapshotsPriorToUnmanageVM(vmVO)) {
22102210
throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() +
22112211
" as there are volume snapshots for its volume(s). Please remove snapshots before unmanaging.");

server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.mockito.MockedStatic;
7171
import org.mockito.Mockito;
7272
import org.mockito.MockitoAnnotations;
73+
import org.mockito.Spy;
7374
import org.mockito.junit.MockitoJUnitRunner;
7475

7576
import com.cloud.agent.AgentManager;
@@ -167,6 +168,7 @@
167168
@RunWith(MockitoJUnitRunner.class)
168169
public class UnmanagedVMsManagerImplTest {
169170

171+
@Spy
170172
@InjectMocks
171173
private UnmanagedVMsManagerImpl unmanagedVMsManager = new UnmanagedVMsManagerImpl();
172174

@@ -479,6 +481,17 @@ public void unmanageVMInstanceExistingISOAttachedTest() {
479481
unmanagedVMsManager.unmanageVMInstance(virtualMachineId);
480482
}
481483

484+
@Test
485+
public void unmanageVMInstanceStoppedInstanceTest() {
486+
when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
487+
when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User);
488+
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
489+
UserVmVO userVmVO = mock(UserVmVO.class);
490+
when(userVmDao.findById(anyLong())).thenReturn(userVmVO);
491+
Mockito.doNothing().when(unmanagedVMsManager).performUnmanageVMInstancePrechecks(any());
492+
unmanagedVMsManager.unmanageVMInstance(virtualMachineId);
493+
}
494+
482495
@Test
483496
public void testListRemoteInstancesTest() {
484497
ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class);

0 commit comments

Comments
 (0)