package org.ovirt.engine.core.bll; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; import java.util.ArrayList; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.ovirt.engine.core.bll.command.utils.StorageDomainSpaceChecker; import org.ovirt.engine.core.common.action.AddDiskToVmParameters; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.DiskImageBase; import org.ovirt.engine.core.common.businessentities.DiskInterface; import org.ovirt.engine.core.common.businessentities.DiskType; import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VolumeFormat; import org.ovirt.engine.core.common.businessentities.VolumeType; import org.ovirt.engine.core.common.businessentities.storage_domains; import org.ovirt.engine.core.common.businessentities.storage_pool_iso_map; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBaseMockUtils; import org.ovirt.engine.core.dao.StorageDomainDAO; import org.ovirt.engine.core.dao.StorageDomainStaticDAO; import org.ovirt.engine.core.dao.StoragePoolIsoMapDAO; import org.ovirt.engine.core.dao.VmDAO; import org.ovirt.engine.core.dao.VmNetworkInterfaceDAO; import org.ovirt.engine.core.utils.RandomUtils; import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest({ VmHandler.class, ImagesHandler.class, StorageDomainSpaceChecker.class, Config.class, AsyncTaskManager.class, SchedulerUtilQuartzImpl.class }) public class AddDiskToVmCommandTest { @Mock private StorageDomainDAO storageDomainDAO; @Mock private StorageDomainStaticDAO storageDomainStaticDAO; @Mock private StoragePoolIsoMapDAO storagePoolIsoMapDAO; @Mock private VmNetworkInterfaceDAO vmNetworkInterfaceDAO; @Mock private VmDAO vmDAO; @Mock private AsyncTaskManager asyncTaskManager; /** * The command under test. */ private AddDiskToVmCommand<AddDiskToVmParameters> command; @SuppressWarnings("unchecked") @Before public void setUp() { mockStatic(SchedulerUtilQuartzImpl.class); SchedulerUtilQuartzImpl scheduler = mock(SchedulerUtilQuartzImpl.class); when(SchedulerUtilQuartzImpl.getInstance()).thenReturn(scheduler); mockStatic(Config.class); when(Config.GetValue(ConfigValues.AsyncTaskPollingRate)).thenReturn(Integer.MAX_VALUE); when(Config.GetValue(ConfigValues.AsyncTaskStatusCacheRefreshRateInSeconds)). thenReturn(Integer.MAX_VALUE); when(Config.GetValue(ConfigValues.AsyncTaskStatusCachingTimeInMinutes)). thenReturn(Integer.MAX_VALUE); mockStatic(AsyncTaskManager.class); MockitoAnnotations.initMocks(this); mockStatic(VmHandler.class); mockStatic(ImagesHandler.class); when(ImagesHandler.CheckImagesConfiguration( any(Guid.class), any(ArrayList.class), any(ArrayList.class))).thenReturn(true); when(ImagesHandler.PerformImagesChecks( any(Guid.class), any(ArrayList.class), any(Guid.class), any(Guid.class), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(true); mockStatic(StorageDomainSpaceChecker.class); when(StorageDomainSpaceChecker.isBelowThresholds(any(storage_domains.class))).thenReturn(true); when(Config.GetValue(ConfigValues.MaxDiskSize)).thenReturn(Integer.MAX_VALUE); when(AsyncTaskManager.getInstance()).thenReturn(asyncTaskManager); when(asyncTaskManager.EntityHasTasks(any(Guid.class))).thenReturn(false); final int defaultFreeSpaceLow = 10; when(Config.<Integer> GetValue(ConfigValues.FreeSpaceLow)).thenReturn(defaultFreeSpaceLow); final int defaultFreeSpaceGB = 5; when(Config.<Integer> GetValue(ConfigValues.FreeSpaceCriticalLowInGB)).thenReturn(defaultFreeSpaceGB); } @Test public void canDoActionSucceedsOnDiskDomainCheckWhenNoDisks() throws Exception { Guid storageId = Guid.NewGuid(); initializeCommand(storageId); mockVm(); mockVmNetworks(); mockStorageDomain(storageId); mockStoragePoolIsoMap(); runAndAssertCanDoActionSuccess(); } @Test public void canDoActionSucceedsOnDiskDomainCheckWhenEmptyStorageGuidInParams() throws Exception { initializeCommand(Guid.Empty); Guid storageId = Guid.NewGuid(); mockVmWithDisk(storageId); mockVmNetworks(); mockStorageDomain(storageId); mockStoragePoolIsoMap(); runAndAssertCanDoActionSuccess(); } @Test public void canDoActionSucceedsOnDiskDomainCheckWhenStorageGuidInParamsMatches() throws Exception { Guid storageId = Guid.NewGuid(); initializeCommand(storageId); mockVmWithDisk(storageId); mockVmNetworks(); mockStorageDomain(storageId); mockStoragePoolIsoMap(); runAndAssertCanDoActionSuccess(); } @Test public void canDoActionFailsOnDiskDomainCheckWhenStorageGuidInParamsMismatches() throws Exception { Guid storageId = Guid.NewGuid(); initializeCommand(storageId); mockVmWithDisk(Guid.NewGuid()); mockVmNetworks(); mockStorageDomain(storageId); mockStoragePoolIsoMap(); doReturn(storageDomainStaticDAO).when(command).getStorageDomainStaticDao(); assertFalse(command.canDoAction()); assertTrue(command.getReturnValue().getCanDoActionMessages().contains( VdcBllMessages.ACTION_TYPE_FAILED_DISK_DOMAIN_MISMATCH.toString())); } @Test public void canDoActionFailsOnNullDiskType() throws Exception { Guid storageId = Guid.NewGuid(); DiskImageBase image = new DiskImageBase(); image.setdisk_interface(DiskInterface.IDE); image.setvolume_type(VolumeType.Preallocated); image.setvolume_format(VolumeFormat.COW); AddDiskToVmParameters params = new AddDiskToVmParameters(Guid.NewGuid(), image); initializeCommand(storageId, params); assertFalse(command.validateInputs()); assertTrue(command.getReturnValue().getCanDoActionMessages().contains("VALIDATION.DISK_TYPE.NOT_NULL")); } @Test public void canDoActionFailsOnNullDiskInterface() throws Exception { Guid storageId = Guid.NewGuid(); DiskImageBase image = new DiskImageBase(); image.setdisk_type(DiskType.Data); image.setvolume_format(VolumeFormat.COW); image.setvolume_type(VolumeType.Preallocated); AddDiskToVmParameters params = new AddDiskToVmParameters(Guid.NewGuid(), image); initializeCommand(storageId, params); assertFalse(command.validateInputs()); assertTrue(command.getReturnValue().getCanDoActionMessages().contains("VALIDATION.DISK_INTERFACE.NOT_NULL")); } @Test public void canDoActionThinProvisioningSpaceCheckSucceeds() throws Exception { final int availableSize = 6; final int usedSize = 4; Guid sdid = Guid.NewGuid(); initializeCommand(sdid, VolumeType.Sparse); mockVm(); mockVmNetworks(); storage_domains domains = mockStorageDomain(sdid, availableSize, usedSize); mockStoragePoolIsoMap(); mockStorageDomainSpaceChecker(domains, true); assertTrue(command.canDoAction()); } @Test public void canDoActionThinProvisioningSpaceCheckFailsSize() { final int availableSize = 4; final int usedSize = 6; Guid sdid = Guid.NewGuid(); initializeCommand(sdid, VolumeType.Sparse); mockVm(); mockVmNetworks(); storage_domains domains = mockStorageDomain(sdid, availableSize, usedSize); mockStoragePoolIsoMap(); mockStorageDomainSpaceChecker(domains, false); assertFalse(command.canDoAction()); assertTrue(command.getReturnValue() .getCanDoActionMessages() .contains(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW.toString())); } @Test public void canDoActionThinProvisioningSpaceCheckFailsPct() { final int availableSize = 9; final int usedSize = 191; Guid sdid = Guid.NewGuid(); initializeCommand(sdid, VolumeType.Sparse); mockVm(); mockVmNetworks(); storage_domains domains = mockStorageDomain(sdid, availableSize, usedSize); mockStoragePoolIsoMap(); mockStorageDomainSpaceChecker(domains, false); assertFalse(command.canDoAction()); assertTrue(command.getReturnValue() .getCanDoActionMessages() .contains(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW.toString())); } @Test public void canDoActionPreallocatedSpaceCheckSucceeds() { final int availableSize = 12; final int usedSize = 8; Guid sdid = Guid.NewGuid(); initializeCommand(sdid, VolumeType.Preallocated); mockVm(); mockVmNetworks(); storage_domains domains = mockStorageDomain(sdid, availableSize, usedSize); mockStoragePoolIsoMap(); mockStorageDomainSpaceCheckerRequest(domains, true); assertTrue(command.canDoAction()); } @Test public void canDoActionPreallocatedSpaceCheckFailsSize() { final int availableSize = 8; final int usedSize = 7; Guid sdid = Guid.NewGuid(); initializeCommand(sdid, VolumeType.Preallocated); mockVm(); mockVmNetworks(); storage_domains domains = mockStorageDomain(sdid, availableSize, usedSize); mockStoragePoolIsoMap(); mockStorageDomainSpaceCheckerRequest(domains, false); assertFalse(command.canDoAction()); assertTrue(command.getReturnValue() .getCanDoActionMessages() .contains(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW.toString())); } @Test public void canDoActionPreallocatedSpaceCheckFailsPct() { final int availableSize = 9; final int usedSize = 191; Guid sdid = Guid.NewGuid(); initializeCommand(sdid, VolumeType.Preallocated); mockVm(); mockVmNetworks(); storage_domains domains = mockStorageDomain(sdid, availableSize, usedSize); mockStoragePoolIsoMap(); mockStorageDomainSpaceCheckerRequest(domains, false); assertFalse(command.canDoAction()); assertTrue(command.getReturnValue() .getCanDoActionMessages() .contains(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW.toString())); } /** * Initialize the command for testing, using the given storage domain id for the parameters. * * @param storageId * Storage domain id for the parameters */ private void initializeCommand(Guid storageId) { initializeCommand(storageId, VolumeType.Unassigned); } private void initializeCommand(Guid storageId, VolumeType volumeType) { AddDiskToVmParameters parameters = createParameters(); parameters.setStorageDomainId(storageId); if (volumeType == VolumeType.Preallocated) { parameters.setDiskInfo(createPreallocDiskImageBase()); } else if (volumeType == VolumeType.Sparse) { parameters.setDiskInfo(createSparseDiskImageBase()); } initializeCommand(storageId, parameters); } private void initializeCommand(Guid storageId, AddDiskToVmParameters params) { params.setStorageDomainId(storageId); command = spy(new AddDiskToVmCommand<AddDiskToVmParameters>(params)); } /** * Mock a VM that has a disk. * * @param storageId * Storage domain id of the disk. */ private void mockVmWithDisk(Guid storageId) { DiskImage image = new DiskImage(); image.setstorage_id(storageId); mockVm().addDriveToImageMap(RandomUtils.instance().nextNumericString(1), image); } /** * Mock a good {@link storage_pool_iso_map}. */ private void mockStoragePoolIsoMap() { storage_pool_iso_map spim = new storage_pool_iso_map(); doReturn(storagePoolIsoMapDAO).when(command).getStoragePoolIsoMapDao(); when(storagePoolIsoMapDAO.get(any(StoragePoolIsoMapId.class))).thenReturn(spim); } /** * Mock a VM. */ private VM mockVm() { VM vm = new VM(); vm.setstatus(VMStatus.Down); vm.setstorage_pool_id(Guid.NewGuid()); AuditLogableBaseMockUtils.mockVmDao(command, vmDAO); when(vmDAO.getById(command.getParameters().getVmId())).thenReturn(vm); return vm; } /** * Mock the VM networks (none). */ private void mockVmNetworks() { doReturn(vmNetworkInterfaceDAO).when(command).getVmNetworkInterfaceDao(); } /** * Mock a {@link storage_domains}. * * @param storageId * Id of the domain. */ private storage_domains mockStorageDomain(Guid storageId) { return mockStorageDomain(storageId, 6, 4); } private storage_domains mockStorageDomain(Guid storageId, int availableSize, int usedSize) { storage_domains sd = new storage_domains(); sd.setavailable_disk_size(availableSize); sd.setused_disk_size(usedSize); doReturn(storageDomainDAO).when(command).getStorageDomainDao(); when(storageDomainDAO.get(storageId)).thenReturn(sd); return sd; } /** * Run the canDoAction and assert that it succeeds, while printing the messages (for easier debug if test fails). */ private void runAndAssertCanDoActionSuccess() { boolean canDoAction = command.canDoAction(); System.out.println(command.getReturnValue().getCanDoActionMessages()); assertTrue(canDoAction); } /** * @return Valid parameters for the command. */ private AddDiskToVmParameters createParameters() { DiskImageBase image = new DiskImageBase(); image.setdisk_type(DiskType.Data); image.setdisk_interface(DiskInterface.IDE); AddDiskToVmParameters parameters = new AddDiskToVmParameters(Guid.NewGuid(), image); return parameters; } private DiskImageBase createSparseDiskImageBase() { DiskImageBase base = new DiskImageBase(); base.setvolume_type(VolumeType.Sparse); base.setdisk_type(DiskType.Data); base.setdisk_interface(DiskInterface.IDE); return base; } private DiskImageBase createPreallocDiskImageBase() { DiskImageBase base = new DiskImageBase(); base.setvolume_type(VolumeType.Preallocated); base.setdisk_type(DiskType.Data); base.setdisk_interface(DiskInterface.IDE); base.setSizeInGigabytes(5); return base; } private void mockStorageDomainSpaceChecker(storage_domains domain, boolean succeeded) { when(StorageDomainSpaceChecker.isBelowThresholds(domain)).thenReturn(succeeded); } private void mockStorageDomainSpaceCheckerRequest(storage_domains domain, boolean succeeded) { when(StorageDomainSpaceChecker.hasSpaceForRequest(eq(domain), anyInt())).thenReturn(succeeded); } }