package org.ovirt.engine.core.bll; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.spy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import junit.framework.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.ovirt.engine.core.bll.interfaces.BackendInternal; import org.ovirt.engine.core.common.action.RunVmParams; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.IVdsAsyncCommand; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.storage_domains; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.config.IConfigUtilsInterface; import org.ovirt.engine.core.common.interfaces.VDSBrokerFrontend; import org.ovirt.engine.core.common.vdscommands.IrsBaseVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSParametersBase; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.common.vdscommands.VdsAndVmIDVDSParametersBase; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.NGuid; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBaseMockUtils; import org.ovirt.engine.core.dao.DiskImageDAO; import org.ovirt.engine.core.dao.StorageDomainDAO; import org.ovirt.engine.core.dao.VmDAO; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest({ DbFacade.class, Backend.class, ImagesHandler.class }) public class RunVmCommandTest { /** * The command under test. */ private RunVmCommand<RunVmParams> command; @Mock VDSBrokerFrontend vdsBrokerFrontend; @Mock private VmDAO vmDAO; @Mock BackendInternal backend; private static String ISO_PREFIX = "iso://"; private static String ACTIVE_ISO_PREFIX = "/rhev/data-center/mnt/some_computer/f6bccab4-e2f5-4e02-bba0-5748a7bc07b6/images/11111111-1111-1111-1111-111111111111"; private static String INACTIVE_ISO_PREFIX = ""; public RunVmCommandTest() { MockitoAnnotations.initMocks(this); mockStatic(DbFacade.class); mockStatic(Backend.class); } @Before public void testBackendSetup() { when(Backend.getInstance()).thenReturn(backend); when(backend.getResourceManager()).thenReturn(vdsBrokerFrontend); // Set Valid Iso Prefix setIsoPrefixVDSMethod(ACTIVE_ISO_PREFIX); // Set create Vm. setCreateVmVDSMethod(); } /** * Set create VM to return VM with status Up. */ private void setCreateVmVDSMethod() { VDSReturnValue returnValue = new VDSReturnValue(); returnValue.setReturnValue(VMStatus.Up); when(backend.getResourceManager().RunAsyncVdsCommand(Matchers.eq(VDSCommandType.CreateVm), Matchers.any(VdsAndVmIDVDSParametersBase.class), Matchers.any(IVdsAsyncCommand.class))).thenReturn(returnValue); } /** * Set the Iso prefix. * * @param isoPrefix * - Valid Iso patch or blank (when the Iso is not active. */ private void setIsoPrefixVDSMethod(String isoPrefix) { VDSReturnValue isoPrefixReturnValue = new VDSReturnValue(); isoPrefixReturnValue.setReturnValue(isoPrefix); when(backend.getResourceManager().RunVdsCommand(Matchers.eq(VDSCommandType.IsoPrefix), Matchers.any(IrsBaseVDSCommandParameters.class))).thenReturn(isoPrefixReturnValue); } @Test public void validateSimpleInitrdAndKernelName() throws Exception { String Initrd = "/boot/initrd.initrd"; String Kernel = "/boot/kernel.image"; VM vm = createVmForTesting(Initrd, Kernel); assertEquals(vm.getinitrd_url(), Initrd); assertEquals(vm.getkernel_url(), Kernel); } @Test public void validateIsoPrefix() throws Exception { String initrd = "initrd"; String kernel = "kernel"; VM vm = createVmForTesting(ISO_PREFIX + initrd, ISO_PREFIX + kernel); assertEquals(vm.getinitrd_url(), ACTIVE_ISO_PREFIX + "/" + initrd); assertEquals(vm.getkernel_url(), ACTIVE_ISO_PREFIX + "/" + kernel); } @Test public void validateIsoPrefixForKernelAndNoPrefixForInitrd() throws Exception { String initrd = "initrd"; String kernel = "kernel"; VM vm = createVmForTesting(initrd, ISO_PREFIX + kernel); assertEquals(vm.getinitrd_url(), initrd); assertEquals(vm.getkernel_url(), ACTIVE_ISO_PREFIX + "/" + kernel); } @Test public void validateIsoPrefixForInitrdAndNoPrefixForKernel() throws Exception { String initrd = "initrd"; String kernel = "kernel"; VM vm = createVmForTesting(ISO_PREFIX + initrd, kernel); assertEquals(vm.getinitrd_url(), ACTIVE_ISO_PREFIX + "/" + initrd); assertEquals(vm.getkernel_url(), kernel); } @Test public void validateIsoPrefixNameForKernelAndNullForInitrd() throws Exception { String kernel = "kernel"; VM vm = createVmForTesting(null, ISO_PREFIX + kernel); assertEquals(vm.getinitrd_url(), null); assertEquals(vm.getkernel_url(), ACTIVE_ISO_PREFIX + "/" + kernel); } @Test public void validateIsoPrefixCaseSensitive() throws Exception { String initrd = "ISO://"; VM vm = createVmForTesting(initrd, null); assertEquals(vm.getinitrd_url(), ""); } @Test public void validateIsoPrefixForOnlyIsoPrefixInKernelAndInitrd() throws Exception { String initrd = ISO_PREFIX; String kernelUrl = ISO_PREFIX; VM vm = createVmForTesting(initrd, kernelUrl); assertEquals(vm.getinitrd_url(), ""); assertEquals(vm.getkernel_url(), ""); } @Test public void checkIsoPrefixForNastyCharacters() throws Exception { String initrd = "@#$!"; String kernelUrl = " "; VM vm = createVmForTesting(initrd, kernelUrl); assertEquals(vm.getinitrd_url(), initrd); assertEquals(vm.getkernel_url(), kernelUrl); } @Test public void validateIsoPrefixNameForInitrdAndNullForKernel() throws Exception { String initrd = "initrd"; VM vm = createVmForTesting(ISO_PREFIX + initrd, null); assertEquals(vm.getinitrd_url(), ACTIVE_ISO_PREFIX + "/" + initrd); assertEquals(vm.getkernel_url(), null); } @Test public void validateIsoPrefixWhenNoActiveIso() throws Exception { // Set Valid Iso Prefix setIsoPrefixVDSMethod(INACTIVE_ISO_PREFIX); String initrd = "initrd"; VM vm = createVmForTesting(ISO_PREFIX + initrd, null); assertEquals(vm.getinitrd_url(), INACTIVE_ISO_PREFIX + "/" + initrd); } @Test public void validateIsoPrefixWithTrippleSlash() throws Exception { String initrd = ISO_PREFIX + "/"; VM vm = createVmForTesting(initrd, null); assertEquals(vm.getinitrd_url(), ACTIVE_ISO_PREFIX + "/"); } @Test public void validateIsoPrefixInTheMiddleOfTheInitrdAndKerenelName() throws Exception { String initrd = "initrd " + ISO_PREFIX; String kernelUrl = "kernelUrl " + ISO_PREFIX; VM vm = createVmForTesting(initrd, kernelUrl); assertEquals(vm.getinitrd_url(), initrd); assertEquals(vm.getkernel_url(), kernelUrl); } @Test public void validateInitrdWithSlashOnly() throws Exception { String initrd = "/"; VM vm = createVmForTesting(initrd, null); assertEquals(vm.getinitrd_url(), "/"); } @Test public void validateIsoPrefixWithBackSlash() throws Exception { String initrd = "iso:\\"; VM vm = createVmForTesting(initrd, null); assertEquals(vm.getinitrd_url(), "iso:\\"); } @Test public void validateBootPrefixForInitrdAndKernelImage() throws Exception { String initrd = "/boot"; String kernelImage = "/boot"; VM vm = createVmForTesting(initrd, kernelImage); assertEquals(vm.getinitrd_url(), initrd); assertEquals(vm.getkernel_url(), kernelImage); } @Test public void validateInitrdAndKernelImageWithOneCharacter() throws Exception { String initrd = "i"; String kernelImage = "k"; VM vm = createVmForTesting(initrd, kernelImage); assertEquals(vm.getinitrd_url(), "i"); assertEquals(vm.getkernel_url(), "k"); } private VM createVmForTesting(String initrd, String kernel) { RunVmCommand<RunVmParams> spyCommand = createCommand(); mockVm(spyCommand); // Set parameter RunVmParams runVmParams = command.getParameters(); runVmParams.setinitrd_url(initrd); runVmParams.setkernel_url(kernel); spyCommand.CreateVm(); // Check Vm VM vm = vmDAO.getById(command.getParameters().getVmId()); return vm; } /** * Mock a VM. */ private VM mockVm(RunVmCommand<RunVmParams> spyVmCommand) { VM vm = new VM(); vm.setstatus(VMStatus.Down); AuditLogableBaseMockUtils.mockVmDao(spyVmCommand, vmDAO); when(vmDAO.getById(command.getParameters().getVmId())).thenReturn(vm); return vm; } private RunVmCommand<RunVmParams> createCommand() { RunVmParams param = new RunVmParams(Guid.NewGuid()); command = new RunVmCommand<RunVmParams>(param); return spy(command); } @Test public void canRunVmFailNodisk() { initMocks(new ArrayList<DiskImage>(), new HashMap<VDSCommandType, Boolean>()); final VM vm = new VM(); final ArrayList<String> messages = new ArrayList<String>(); Assert.assertFalse(RunVmCommand.CanRunVm(vm, messages, new RunVmParams(), new VdsSelector(vm, new NGuid(), true))); Assert.assertTrue(messages.contains("VM_CANNOT_RUN_FROM_DISK_WITHOUT_DISK")); } @Test public void canRunVmFailVmRunning() { final ArrayList<DiskImage> disks = new ArrayList<DiskImage>(); final DiskImage diskImage = new DiskImage(); diskImage.setstorage_id(new Guid()); disks.add(diskImage); initMocks(disks, new HashMap<VDSCommandType, Boolean>()); final VM vm = new VM(); vm.setstatus(VMStatus.Up); final ArrayList<String> messages = new ArrayList<String>(); Assert.assertFalse(RunVmCommand.CanRunVm(vm, messages, new RunVmParams(), new VdsSelector(vm, new NGuid(), true))); Assert.assertTrue(messages.contains("ACTION_TYPE_FAILED_VM_IS_RUNNING")); } private void canRunStatelessVmTest(boolean autoStartUp, boolean isVmStateless, Boolean isStatelessParam, boolean shouldPass) { final ArrayList<DiskImage> disks = new ArrayList<DiskImage>(); final DiskImage diskImage = new DiskImage(); diskImage.setstorage_id(new Guid()); disks.add(diskImage); final HashMap<VDSCommandType, Boolean> calls = new HashMap<VDSCommandType, Boolean>(); final VdsSelector vdsSelector = Mockito.mock(VdsSelector.class); Mockito.when(vdsSelector.CanFindVdsToRunOn(any(ArrayList.class), anyBoolean())).thenReturn(true); calls.put(VDSCommandType.IsVmDuringInitiating, false); initMocks(disks, calls); final VM vm = new VM(); // set stateless and HA vm.setis_stateless(isVmStateless); vm.setauto_startup(autoStartUp); final ArrayList<String> messages = new ArrayList<String>(); final RunVmParams runParams = new RunVmParams(); runParams.setRunAsStateless(isStatelessParam); boolean canRunVm = RunVmCommand.CanRunVm(vm, messages, runParams, vdsSelector); if (shouldPass) { Assert.assertTrue(canRunVm); Assert.assertFalse(messages.contains("VM_CANNOT_RUN_STATELESS_HA")); } else { Assert.assertFalse(canRunVm); Assert.assertTrue(messages.contains("VM_CANNOT_RUN_STATELESS_HA")); } } @Test public void canRunVmFailStatelessWhenVmHA() { canRunStatelessVmTest(true, false, Boolean.TRUE, false); } @Test public void canRunVmPassStatelessWhenVmHAandStatelessFalse() { canRunStatelessVmTest(true, true, Boolean.FALSE, true); } @Test public void canRunVmFailStatelessWhenVmHAwithNullStatelessParam() { canRunStatelessVmTest(true, true, null, false); } @Test public void canRunVmPassStatelessWhenVmHAwithNullStatelessParam() { canRunStatelessVmTest(true, false, null, true); } @Test public void canRunVmPassStatelessWhenVmHAwithNegativeStatelessParam() { canRunStatelessVmTest(true, false, Boolean.FALSE, true); } @Test public void canRunVmPassStatelessWhenVmNotHAwithNegativeStatelessParam() { canRunStatelessVmTest(false, false, Boolean.TRUE, true); } /** * Workaround of the singleton design pattern with PowerMock and EasyMock. * * @param disks * the disks for the VM */ private void initMocks(final List<DiskImage> disks, final Map<VDSCommandType, Boolean> calls) { final Guid guid = new Guid("00000000-0000-0000-0000-000000000000"); final IConfigUtilsInterface cfgUtils = Mockito.mock(IConfigUtilsInterface.class); Mockito.when(cfgUtils.GetValue(ConfigValues.VdsSelectionAlgorithm, "general")).thenReturn("0"); Mockito.when(cfgUtils.GetValue(ConfigValues.PredefinedVMProperties, "3.0")).thenReturn("0"); Mockito.when(cfgUtils.GetValue(ConfigValues.UserDefinedVMProperties, "3.0")).thenReturn("0"); Config.setConfigUtils(cfgUtils); final DiskImageDAO diskImageDao = Mockito.mock(DiskImageDAO.class); Mockito.when(diskImageDao.getAllForVm(guid)).thenReturn(disks); final StorageDomainDAO storageDomainDAO = Mockito.mock(StorageDomainDAO.class); Mockito.when(storageDomainDAO.getAllForStoragePool(guid)) .thenReturn(new ArrayList<storage_domains>()); final DbFacade facadeMock = new DbFacade() { @Override public DiskImageDAO getDiskImageDAO() { return diskImageDao; } @Override public StorageDomainDAO getStorageDomainDAO() { return storageDomainDAO; } }; final VDSBrokerFrontend vdsBrokerFrontendMock = new VDSBrokerFrontend() { @Override public VDSReturnValue RunVdsCommand(VDSCommandType commandType, VDSParametersBase parameters) { final VDSReturnValue vdsReturnValue = new VDSReturnValue(); if (calls.containsKey(commandType)) { vdsReturnValue.setReturnValue(calls.get(commandType)); } else { vdsReturnValue.setReturnValue(Boolean.TRUE); } return vdsReturnValue; } @Override public VDSReturnValue RunAsyncVdsCommand(VDSCommandType commandType, VdsAndVmIDVDSParametersBase parameters, IVdsAsyncCommand command) { return null; } @Override public IVdsAsyncCommand GetAsyncCommandForVm(Guid vmId) { return null; } @Override public void RemoveAsyncRunningCommand(Guid vmId) { } }; final Backend backendMock = new Backend() { @Override public VDSBrokerFrontend getResourceManager() { return vdsBrokerFrontendMock; } }; PowerMockito.mockStatic(Backend.class); Mockito.when(Backend.getInstance()).thenReturn(backendMock); PowerMockito.mockStatic(DbFacade.class); Mockito.when(DbFacade.getInstance()).thenReturn(facadeMock); PowerMockito.mockStatic(ImagesHandler.class); Mockito.when(ImagesHandler.PerformImagesChecks(guid, new ArrayList<String>(), guid, guid, true, true, false, false, false, false, false, true)) .thenReturn(true); Mockito.when(ImagesHandler.PerformImagesChecks(guid, new ArrayList<String>(), guid, guid, false, true, false, false, false, false, true, true)) .thenReturn(true); Mockito.when(ImagesHandler.isVmInPreview(disks)).thenReturn(false); } }