package org.ovirt.engine.core.dao; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.apache.commons.collections.CollectionUtils; import org.hamcrest.Matchers; import org.junit.ClassRule; import org.junit.Test; import org.ovirt.engine.core.common.businessentities.ConsoleDisconnectAction; import org.ovirt.engine.core.common.businessentities.MigrationSupport; import org.ovirt.engine.core.common.businessentities.OriginType; import org.ovirt.engine.core.common.businessentities.Snapshot; import org.ovirt.engine.core.common.businessentities.VmBase; import org.ovirt.engine.core.common.businessentities.VmDevice; import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; import org.ovirt.engine.core.common.businessentities.VmDeviceId; import org.ovirt.engine.core.common.businessentities.VmStatic; import org.ovirt.engine.core.common.utils.VmDeviceType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.utils.MockConfigRule; public class VmStaticDaoTest extends BaseDaoTestCase { @ClassRule public static MockConfigRule mcr = new MockConfigRule(); private static final Guid EXISTING_VM_ID = new Guid("77296e00-0cad-4e5a-9299-008a7b6f4355"); private static final Guid VDS_STATIC_ID = new Guid("afce7a39-8e8c-4819-ba9c-796d316592e6"); private static final Guid CLUSTER_ID = new Guid("b399944a-81ab-4ec5-8266-e19ba7c3c9d1"); private static final Guid QUOTA_ID = new Guid("88296e00-0cad-4e5a-9291-008a7b7f4399"); private static final Guid SMALL_ICON_ID = new Guid("38fc5e1a-f96b-339b-9894-def6f366daf5"); private static final Guid LARGE_ICON_ID = new Guid("a3b954f0-31ff-3166-b7a1-28b23202b198"); private static final Guid EXISTING_PROVIDER_ID = new Guid("1115c1c6-cb15-4832-b2a4-023770607111"); protected static final Guid[] HOST_GUIDS = {new Guid("afce7a39-8e8c-4819-ba9c-796d316592e8"), new Guid("afce7a39-8e8c-4819-ba9c-796d316592e7"), new Guid("23f6d691-5dfb-472b-86dc-9e1d2d3c18f3")}; private static final String STATIC_VM_NAME = "rhel5-pool-50"; private static final int NUM_OF_VM_STATIC_IN_FIXTURES = 3; private static final Guid VM_TEMPLATE_ID = new Guid("1b85420c-b84c-4f29-997e-0eb674b40b79"); private VmStaticDao dao; private VmStatic existingVmStatic; private VmStatic newVmStatic; @Override public void setUp() throws Exception { super.setUp(); dao = dbFacade.getVmStaticDao(); existingVmStatic = dao.get(EXISTING_VM_ID); newVmStatic = new VmStatic(); newVmStatic.setId(Guid.newGuid()); newVmStatic.setName("New Virtual Machine"); newVmStatic.setClusterId(CLUSTER_ID); newVmStatic.setVmtGuid(VM_TEMPLATE_ID); newVmStatic.setOrigin(OriginType.OVIRT); newVmStatic.setQuotaId(QUOTA_ID); newVmStatic.setCpuProfileId(FixturesTool.CPU_PROFILE_1); newVmStatic.setSmallIconId(SMALL_ICON_ID); newVmStatic.setLargeIconId(LARGE_ICON_ID); } /** * Ensures that get requires a valid id. */ @Test public void testGetWithInvalidId() { VmStatic result = dao.get(Guid.newGuid()); assertNull(result); } /** * Ensures that get works as expected. */ @Test public void testGet() { VmStatic result = dao.get(existingVmStatic.getId()); assertNotNull(result); assertEquals(result, existingVmStatic); } /** * Ensures that all VMs are returned. */ @Test public void testGetAllStaticByName() { List<VmStatic> result = dao.getAllByName("rhel5-pool-50"); assertNotNull(result); assertFalse(result.isEmpty()); for (VmStatic vm : result) { assertEquals("rhel5-pool-50", vm.getName()); } } /** * Ensures that all VMs are returned from storage pool */ @Test public void testGetAllStaticByStoragePool() { Guid spID = dbFacade.getClusterDao().get(newVmStatic.getClusterId()).getStoragePoolId(); assertNotNull(spID); List<VmStatic> result = dao.getAllByStoragePoolId(spID); assertNotNull(result); assertFalse(result.isEmpty()); } /** * Ensures that all static vm details for the specified group and network are returned. */ @Test public void testGetAllByGroupAndNetwork() { List<VmStatic> result = dao.getAllByGroupAndNetworkName( CLUSTER_ID, "engine"); assertNotNull(result); assertFalse(result.isEmpty()); for (VmStatic vm : result) { assertEquals(CLUSTER_ID, vm.getClusterId()); } } /** * Ensures that all static VMs for the specified VDS group are returned. */ @Test public void testGetAllByCluster() { List<VmStatic> result = dao.getAllByCluster(CLUSTER_ID); assertNotNull(result); assertFalse(result.isEmpty()); for (VmStatic vm : result) { assertEquals(CLUSTER_ID, vm.getClusterId()); } } /** * Ensures that the right set of VMs are returned. */ @Test public void testGetAllWithFailbackByVds() { List<VmStatic> result = dao.getAllWithFailbackByVds(VDS_STATIC_ID); assertNotNull(result); assertFalse(result.isEmpty()); for (VmStatic vm : result) { assertEquals(CLUSTER_ID, vm.getClusterId()); } } @Test(expected = UnsupportedOperationException.class) public void testGetAll() { dao.getAll(); } @Test public void testSave() { newVmStatic.setDedicatedVmForVdsList(Arrays.asList(HOST_GUIDS)); dao.save(newVmStatic); VmStatic result = dao.get(newVmStatic.getId()); assertNotNull(result); assertTrue("Add 3 dedicated hosts", CollectionUtils.isEqualCollection(result.getDedicatedVmForVdsList(), newVmStatic.getDedicatedVmForVdsList())); assertEquals(newVmStatic, result); } @Test public void testUpdate() { assertEquals(EXISTING_PROVIDER_ID, existingVmStatic.getProviderId()); existingVmStatic.setDescription("updated"); existingVmStatic.setCpuProfileId(FixturesTool.CPU_PROFILE_2); existingVmStatic.setProviderId(null); List<Guid> hostGuidsList = Arrays.asList(HOST_GUIDS); existingVmStatic.setDedicatedVmForVdsList(hostGuidsList); dao.update(existingVmStatic); VmStatic result = dao.get(EXISTING_VM_ID); assertNotNull(result); assertTrue("Update dedicated hosts", CollectionUtils.isEqualCollection(result.getDedicatedVmForVdsList(), existingVmStatic.getDedicatedVmForVdsList())); assertEquals(existingVmStatic, result); assertNull(result.getProviderId()); hostGuidsList = new LinkedList<>(); hostGuidsList.add(HOST_GUIDS[0]); hostGuidsList.add(HOST_GUIDS[1]); existingVmStatic.setDedicatedVmForVdsList(hostGuidsList); dao.update(existingVmStatic); result = dao.get(EXISTING_VM_ID); // assert 1 dedicated hosts assertTrue("Reduce dedicated hosts", CollectionUtils.isEqualCollection(result.getDedicatedVmForVdsList(), existingVmStatic.getDedicatedVmForVdsList())); } @Test public void testRemove() { for (Snapshot s : dbFacade.getSnapshotDao().getAll()) { dbFacade.getSnapshotDao().remove(s.getId()); } dao.remove(EXISTING_VM_ID); VmStatic result = dao.get(EXISTING_VM_ID); assertNull(result); PermissionDao permissionsDao = dbFacade.getPermissionDao(); assertEquals("vm permissions wasn't removed", 0, permissionsDao.getAllForEntity(EXISTING_VM_ID).size()); } @Test public void testRemoveWithoutPermissions() { for (Snapshot s : dbFacade.getSnapshotDao().getAll()) { dbFacade.getSnapshotDao().remove(s.getId()); } PermissionDao permissionsDao = dbFacade.getPermissionDao(); int numberOfPermissionsBeforeRemove = permissionsDao.getAllForEntity(EXISTING_VM_ID).size(); dao.remove(EXISTING_VM_ID, false); VmStatic result = dao.get(EXISTING_VM_ID); assertNull(result); assertEquals("vm permissions changed during remove although shouldnt have.", numberOfPermissionsBeforeRemove, permissionsDao.getAllForEntity(EXISTING_VM_ID).size()); } private void checkDisks(Guid id, boolean hasDisks) { assertEquals(hasDisks, !dbFacade.getDiskDao().getAllForVm(id).isEmpty()); } private void checkVmsDcAndDisks(List<Guid> vmIds, Guid storagePoolId, boolean hasDisks) { for (Guid vmId : vmIds) { assertEquals(storagePoolId, dbFacade.getVmDao().get(vmId).getStoragePoolId()); checkDisks(vmId, hasDisks); } } private void checkTemplatesDcAndDisks(List<Guid> templateIds, Guid storagePoolId, boolean hasDisks) { for (Guid templateId : templateIds) { assertEquals(storagePoolId, dbFacade.getVmTemplateDao().get(templateId).getStoragePoolId()); checkDisks(templateId, hasDisks); } } @Test public void getVmAndTemplatesIdsWithoutAttachedImageDisks() { List<Guid> disklessVms = Arrays.asList(FixturesTool.VM_WITH_NO_ATTACHED_DISKS, FixturesTool.VM_RHEL5_POOL_51); List<Guid> disklessTemplates = Collections.singletonList(FixturesTool.VM_TEMPLATE_RHEL5_2); List<Guid> diskVms = Collections.singletonList(FixturesTool.VM_RHEL5_POOL_57); List<Guid> diskTemplates = Collections.singletonList(FixturesTool.VM_TEMPLATE_RHEL5); Guid dataCenterId = FixturesTool.DATA_CENTER; checkTemplatesDcAndDisks(disklessTemplates, dataCenterId, false); checkVmsDcAndDisks(disklessVms, dataCenterId, false); checkTemplatesDcAndDisks(diskTemplates, dataCenterId, true); checkVmsDcAndDisks(diskVms, dataCenterId, true); // attaching shareable and snapshots disk to a diskless vm addVmDevice(disklessVms.get(0), FixturesTool.IMAGE_GROUP_ID_2, null); addVmDevice(disklessVms.get(0), FixturesTool.DISK_ID, FixturesTool.EXISTING_SNAPSHOT_ID); List<Guid> ids = dao.getVmAndTemplatesIdsWithoutAttachedImageDisks(dataCenterId, false); assertTrue(ids.containsAll(disklessVms)); assertTrue(ids.containsAll(disklessTemplates)); assertTrue(Collections.disjoint(ids, diskVms)); assertTrue(Collections.disjoint(ids, diskTemplates)); assertTrue(dao.getVmAndTemplatesIdsWithoutAttachedImageDisks(Guid.newGuid(), false).isEmpty()); } private void addVmDevice(Guid vmId, Guid diskId, Guid snapshotId) { VmDevice device = new VmDevice(new VmDeviceId(diskId, vmId), VmDeviceGeneralType.DISK, VmDeviceType.DISK.getName(), "", null, true, false, false, "", null, snapshotId, null); dbFacade.getVmDeviceDao().save(device); } @Test public void testGetAllNamesPinnedToHostReturnsNothingForRandomHost() throws Exception { assertTrue(dao.getAllNamesPinnedToHost(Guid.newGuid()).isEmpty()); } @Test public void testGetDbGeneration() { Long version = dao.getDbGeneration(FixturesTool.VM_RHEL5_POOL_50); assertNotNull("db generation shouldn't be null", version); assertEquals("db generation should be 1 by default for vm", 1, version.longValue()); } @Test public void testIncrementDbGenerationForAllInStoragePool() { dao.incrementDbGenerationForAllInStoragePool(FixturesTool.STORAGE_POOL_RHEL6_ISCSI_OTHER); Long version = dao.getDbGeneration(FixturesTool.VM_RHEL5_POOL_50); assertEquals("db geneeration wasn't incremented to all vms in pool", 2, version.longValue()); version = dao.getDbGeneration(FixturesTool.VM_RHEL5_POOL_51); assertEquals("db generation wasn't incremented to all vms in pool", 2, version.longValue()); version = dao.getDbGeneration(FixturesTool.VM_RHEL5_POOL_60); assertEquals("db generation was incremented for vm in different pool", 1, version.longValue()); } @Test public void testIncrementDbGeneration() { dao.incrementDbGeneration(FixturesTool.VM_RHEL5_POOL_50); Long version = dao.getDbGeneration(FixturesTool.VM_RHEL5_POOL_50); assertEquals("db generation wasn't incremented as expected", 2, version.longValue()); } @Test public void testGetAllNamesPinnedToHostReturnsNothingForHostButNotPinned() throws Exception { assertTrue(dao.getAllNamesPinnedToHost(new Guid("afce7a39-8e8c-4819-ba9c-796d316592e7")).isEmpty()); } @Test public void testGetAllNamesPinnedToHostReturnsVmNameForHostPinned() throws Exception { List<String> namesPinnedToHost = dao.getAllNamesPinnedToHost(VDS_STATIC_ID); assertFalse(namesPinnedToHost.isEmpty()); assertTrue(namesPinnedToHost.contains(existingVmStatic.getName())); } /** * Checking if the function gets the VmStatics in correct order according to priority */ @Test public void testGetOrderedVmGuidsForRunMultipleActionsByPriority() { List<VmStatic> vmStatics = dao.getAllByName(STATIC_VM_NAME); VmStatic[] vmStaticArrayInDescOrder = initVmStaticsOrderedByPriority(vmStatics); // execute List<Guid> vmStaticGuidsInDb = dao.getOrderedVmGuidsForRunMultipleActions(getListOfGuidFromListOfVmStatics(vmStatics)); assertNotNull(vmStaticGuidsInDb); Guid[] guidsArrayToBeChecked = vmStaticGuidsInDb.toArray(new Guid[vmStaticGuidsInDb.size()]); boolean result = compareGuidArrays(guidsArrayToBeChecked, vmStaticArrayInDescOrder); assertTrue(result); } /** * Checking if the function gets the VmStatics in correct order according to auto_startup */ @Test public void testGetOrderedVmGuidsForRunMultipleActionsByAutoStartup() { List<VmStatic> vmStatics = dao.getAllByName(STATIC_VM_NAME); VmStatic[] vmStaticArrayInDescOrder = initVmStaticsOrderedByAutoStartup(vmStatics); // execute List<Guid> vmStaticGuidsInDb = dao.getOrderedVmGuidsForRunMultipleActions(getListOfGuidFromListOfVmStatics(vmStatics)); assertNotNull(vmStaticGuidsInDb); Guid[] guidsArrayToBeChecked = vmStaticGuidsInDb.toArray(new Guid[vmStaticGuidsInDb.size()]); boolean result = compareGuidArrays(guidsArrayToBeChecked, vmStaticArrayInDescOrder); assertTrue(result); } /** * Checking if the function gets the VmStatics in correct order according to MigrationSupport */ @Test public void testGetOrderedVmGuidsForRunMultipleActionsByMigrationSupport() { List<VmStatic> vmStatics = dao.getAllByName(STATIC_VM_NAME); if (vmStatics.size() > 3) { // migration support has only 3 possible values vmStatics = vmStatics.subList(0, 3); } VmStatic[] vmStaticArrayInDescOrder = initVmStaticsOrderedByMigrationSupport(vmStatics); // execute List<Guid> vmStaticGuidsInDb = dao.getOrderedVmGuidsForRunMultipleActions(getListOfGuidFromListOfVmStatics(vmStatics)); assertNotNull(vmStaticGuidsInDb); Guid[] guidsArrayToBeChecked = vmStaticGuidsInDb.toArray(new Guid[vmStaticGuidsInDb.size()]); boolean result = compareGuidArrays(guidsArrayToBeChecked, vmStaticArrayInDescOrder); assertTrue(result); } /** * {@code initVmStaticsOrderedByAutoStartup(List)} is the first method in VMs order selection tests. The other init * methods: <br> * {@code initVmStaticsOrderedByPriority} and {@code initVmStaticsOrderedByAutoStartup} are relying on each other * for creating an array of VM Static objects.<br> * Each of the methods modifies the VM static array according to the column which is being tested, started from the * least important column to the most.<br> * That way prioritizing a preceded column should be reflected in the selection and therefore to validate the order * is maintained. * * @return an array of VmStatics, in descending order according to: auto_startup, priority, MigrationSupport.<br> * The MigrationSupport is the one being checked.<br> */ private VmStatic[] initVmStaticsOrderedByMigrationSupport(List<VmStatic> vmStatics) { VmStatic[] vmStaticArray = new VmStatic[NUM_OF_VM_STATIC_IN_FIXTURES]; vmStaticArray = vmStatics.toArray(vmStaticArray); // initialize the VMs with equal settings: non HA, priority 1 and MIGRATABLE for (VmStatic element : vmStaticArray) { element.setAutoStartup(false); element.setPriority(1); element.setMigrationSupport(MigrationSupport.MIGRATABLE); } // set higher migration support value for the first VM vmStaticArray[0].setMigrationSupport(MigrationSupport.PINNED_TO_HOST); vmStaticArray[1].setMigrationSupport(MigrationSupport.IMPLICITLY_NON_MIGRATABLE); updateArrayOfVmStaticsInDb(vmStaticArray); return vmStaticArray; } /** * Creates an array of VM static which was initiated for MigrationSupport order, and modified the priority to * reflect the precedence of the priority column on top the MigrationSupport. * * @return an array of VmStatics, in descending order according to: auto_startup, priority, MigrationSupport. The * priority is the one being checked. */ private VmStatic[] initVmStaticsOrderedByPriority(List<VmStatic> vmStatics) { VmStatic[] vmStaticArray = initVmStaticsOrderedByMigrationSupport(vmStatics); // Swapping the first two VmStatics VmStatic tempVmStatic = vmStaticArray[0]; vmStaticArray[0] = vmStaticArray[1]; vmStaticArray[1] = tempVmStatic; int arrayLength = vmStaticArray.length; // Setting the array in descending order due to their priorities to maintain its correctness for (int i = 0; i < arrayLength; i++) { vmStaticArray[i].setPriority(arrayLength - i + 1); } updateArrayOfVmStaticsInDb(vmStaticArray); return vmStaticArray; } /** * Creates an array of VM static which was initiated for Priority and MigrationSupport order, and modified the * auto-startup to reflect the precedence of the auto-startup column on top the Priority. * * @return an array of VmStatics, in descending order according to: auto_startup, priority, MigrationSupport. The * auto_startup is the one being checked */ private VmStatic[] initVmStaticsOrderedByAutoStartup(List<VmStatic> vmStatics) { VmStatic[] vmStaticArray = initVmStaticsOrderedByPriority(vmStatics); // Swapping the first two VmStatics VmStatic tempVmStatic = vmStaticArray[0]; vmStaticArray[0] = vmStaticArray[1]; vmStaticArray[1] = tempVmStatic; // Maintaining the order correctness of the elements by incrementing the auto_startup of the first element vmStaticArray[0].setAutoStartup(true); updateArrayOfVmStaticsInDb(vmStaticArray); return vmStaticArray; } /** * Updates the given array of vmStatics in the Database */ private void updateArrayOfVmStaticsInDb(VmStatic[] vmStaticArray) { for (VmStatic element : vmStaticArray) { dao.update(element); } } /** * Converts a list of vmStatics to a list if Guids */ private static List<Guid> getListOfGuidFromListOfVmStatics(List<VmStatic> vmStatics) { return vmStatics.stream().map(VmBase::getId).collect(Collectors.toList()); } /** * Compares between the two given guid arrays, returns true if they are equal and false otherwise */ private static boolean compareGuidArrays(Guid[] guidsArrayToBeChecked, VmStatic[] vmStaticArrayInDescOrder) { return guidsArrayToBeChecked.length == vmStaticArrayInDescOrder.length && IntStream.range(0, guidsArrayToBeChecked.length) .allMatch(i -> guidsArrayToBeChecked[i].equals(vmStaticArrayInDescOrder[i].getId())); } @Test public void testUpdateVmCpuProfileIdForClusterId() { Guid clusterId = FixturesTool.CLUSTER_RHEL6_ISCSI; Guid cpuProfileId = FixturesTool.CPU_PROFILE_2; testAllCpuProfileValuesEqualTo(clusterId, cpuProfileId, false); dao.updateVmCpuProfileIdForClusterId(clusterId, cpuProfileId); testAllCpuProfileValuesEqualTo(clusterId, cpuProfileId, true); } private void testAllCpuProfileValuesEqualTo(Guid clusterId, Guid cpuProfileId, boolean isAllNull) { List<VmStatic> allByCluster = dao.getAllByCluster(clusterId); assertNotNull(allByCluster); assertFalse(allByCluster.isEmpty()); boolean allValues = true; for (VmStatic vmStatic : allByCluster) { allValues &= Objects.equals(vmStatic.getCpuProfileId(), cpuProfileId); } assertEquals(isAllNull, allValues); } @Test public void testConsoleDisconnectActionDefault() { assertEquals(ConsoleDisconnectAction.LOCK_SCREEN, newVmStatic.getConsoleDisconnectAction()); } @Test public void testConsoleDisconnectActionSaved() { newVmStatic.setConsoleDisconnectAction(ConsoleDisconnectAction.REBOOT); dao.save(newVmStatic); VmStatic loaded = dao.get(newVmStatic.getId()); assertEquals(ConsoleDisconnectAction.REBOOT, loaded.getConsoleDisconnectAction()); } @Test public void testGetAllWithLeaseOnStorageDomain() { List<Guid> vmAndTemplatesWithLeasesIds = dao.getAllWithLeaseOnStorageDomain(FixturesTool.STORAGE_DOAMIN_NFS2_1) .stream().map(t -> t.getId()).collect(Collectors.toList()); assertThat(vmAndTemplatesWithLeasesIds, Matchers.containsInAnyOrder(FixturesTool.VM_RHEL5_POOL_57, FixturesTool.VM_TEMPLATE_RHEL5_2)); } @Test public void testGetAllActiveWithLeaseOnForStorageDomain() { List<Guid> runningVmsWithLeasesIds = dao.getAllRunningWithLeaseOnStorageDomain(FixturesTool.STORAGE_DOAMIN_NFS2_1) .stream().map(v -> v.getId()).collect(Collectors.toList()); assertThat(runningVmsWithLeasesIds, Matchers.contains(FixturesTool.VM_RHEL5_POOL_57)); } @Test public void testGetAllRunningForVds() { List<VmStatic> vms = dao.getAllRunningForVds(FixturesTool.VDS_RHEL6_NFS_SPM); assertEquals(vms.size(), 3); List<Guid> vmIds = vms.stream().map(VmStatic::getId).collect(Collectors.toList()); assertTrue(vmIds.contains(FixturesTool.VM_RHEL5_POOL_57)); assertFalse(vmIds.contains(FixturesTool.VM_RHEL5_POOL_52)); } }