package org.ovirt.engine.core.bll.validator.storage; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import static org.ovirt.engine.core.bll.validator.ValidationResultMatchers.failsWith; import static org.ovirt.engine.core.bll.validator.ValidationResultMatchers.isValid; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner.Strict; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmDevice; import org.ovirt.engine.core.common.businessentities.VmDeviceId; import org.ovirt.engine.core.common.businessentities.storage.Disk; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.DiskVmElement; import org.ovirt.engine.core.common.businessentities.storage.Image; import org.ovirt.engine.core.common.businessentities.storage.LUNs; import org.ovirt.engine.core.common.businessentities.storage.LunDisk; import org.ovirt.engine.core.common.businessentities.storage.ScsiGenericIO; import org.ovirt.engine.core.common.businessentities.storage.StorageType; import org.ovirt.engine.core.common.businessentities.storage.VolumeType; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.StorageDomainDao; import org.ovirt.engine.core.dao.VmDao; import org.ovirt.engine.core.di.InjectorRule; import org.ovirt.engine.core.utils.ReplacementUtils; @RunWith(Strict.class) public class DiskValidatorTest { @ClassRule public static InjectorRule injectorRule = new InjectorRule(); @Mock private VmDao vmDao; @Mock private StorageDomainDao storageDomainDao; private DiskValidator validator; private DiskImage disk; private DiskValidator lunValidator; private static DiskImage createDiskImage() { DiskImage disk = new DiskImage(); disk.setId(Guid.newGuid()); Image image = new Image(); image.setVolumeType(VolumeType.Sparse); disk.setImage(image); return disk; } private static LunDisk createLunDisk() { LunDisk disk = new LunDisk(); LUNs lun = new LUNs(); lun.setLUNId("lun_id"); lun.setLunType(StorageType.ISCSI); disk.setLun(lun); return disk; } private static VM createVM() { VM vm = new VM(); vm.setStatus(VMStatus.Down); vm.setId(Guid.newGuid()); vm.setVmOs(1); return vm; } @Before public void setUp() { disk = createDiskImage(); disk.setDiskAlias("disk1"); validator = spy(new DiskValidator(disk)); doReturn(vmDao).when(validator).getVmDao(); } private void setupForLun() { LunDisk lunDisk = createLunDisk(); lunValidator = spy(new DiskValidator(lunDisk)); } private StorageDomain createStorageDomainForDisk(StorageType storageType) { StorageDomain domain = new StorageDomain(); domain.setId(Guid.newGuid()); domain.setStorageType(storageType); disk.setStorageIds(new ArrayList<>(Collections.singletonList(domain.getId()))); injectorRule.bind(StorageDomainDao.class, storageDomainDao); when(storageDomainDao.get(domain.getId())).thenReturn(domain); return domain; } private VmDevice createVmDeviceForDisk(VM vm, Disk disk, Guid snapshotId, boolean isPlugged) { VmDevice device = new VmDevice(); device.setId(new VmDeviceId(vm.getId(), disk.getId())); device.setSnapshotId(snapshotId); device.setPlugged(isPlugged); return device; } public List<Pair<VM, VmDevice>> prepareForCheckingIfDiskPluggedToVmsThatAreNotDown() { VM vm1 = createVM(); VM vm2 = createVM(); VmDevice device1 = createVmDeviceForDisk(vm1, disk, null, true); VmDevice device2 = createVmDeviceForDisk(vm1, disk, null, true); List<Pair<VM, VmDevice>> vmsInfo = new LinkedList<>(); vmsInfo.add(new Pair<>(vm1, device1)); vmsInfo.add(new Pair<>(vm2, device2)); return vmsInfo; } @Test public void diskPluggedToVmsThatAreNotDownValid() { List<Pair<VM, VmDevice>> vmsInfo = prepareForCheckingIfDiskPluggedToVmsThatAreNotDown(); assertThat(validator.isDiskPluggedToVmsThatAreNotDown(false, vmsInfo), isValid()); } @Test public void diskPluggedToVmsThatAreNotDownFail() { List<Pair<VM, VmDevice>> vmsInfo = prepareForCheckingIfDiskPluggedToVmsThatAreNotDown(); vmsInfo.get(0).getFirst().setStatus(VMStatus.Up); assertThat(validator.isDiskPluggedToVmsThatAreNotDown(false, vmsInfo), failsWith(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_DOWN)); } @Test public void diskPluggedToVmsNotAsSnapshotSuccess() { List<Pair<VM, VmDevice>> vmsInfo = prepareForCheckingIfDiskPluggedToVmsThatAreNotDown(); vmsInfo.get(0).getFirst().setStatus(VMStatus.Up); vmsInfo.get(1).getFirst().setStatus(VMStatus.Up); assertThat(validator.isDiskPluggedToVmsThatAreNotDown(true, vmsInfo), isValid()); } @Test public void diskPluggedToVmsCheckSnapshotsFail() { List<Pair<VM, VmDevice>> vmsInfo = prepareForCheckingIfDiskPluggedToVmsThatAreNotDown(); vmsInfo.get(1).getFirst().setStatus(VMStatus.Up); vmsInfo.get(1).getSecond().setSnapshotId(Guid.newGuid()); assertThat(validator.isDiskPluggedToVmsThatAreNotDown(true, vmsInfo), failsWith(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_DOWN)); } @Test public void testIsUsingScsiReservationValidWhenSgioIsUnFiltered() { setupForLun(); LunDisk lunDisk1 = createLunDisk(ScsiGenericIO.UNFILTERED); assertThat(lunValidator.isUsingScsiReservationValid(createVM(), createDiskVmElementUsingScsiReserevation(), lunDisk1), isValid()); } @Test public void testIsUsingScsiReservationValidWhenSgioIsFiltered() { setupForLun(); LunDisk lunDisk1 = createLunDisk(ScsiGenericIO.FILTERED); assertThat(lunValidator.isUsingScsiReservationValid(createVM(), createDiskVmElementUsingScsiReserevation(), lunDisk1), failsWith(EngineMessage.ACTION_TYPE_FAILED_SGIO_IS_FILTERED)); } @Test public void testDiskAttachedToVMValid() { VM vm = createVM(); when(vmDao.getVmsListForDisk(any(Guid.class), anyBoolean())).thenReturn(Collections.singletonList(vm)); assertThat(validator.isDiskAttachedToVm(vm), isValid()); } @Test public void testDiskAttachedToVMFail() { VM vm = createVM(); assertThat(validator.isDiskAttachedToVm(vm), failsWith(EngineMessage.ACTION_TYPE_FAILED_DISK_NOT_ATTACHED_TO_VM)); } @Test public void testDiskAttachedToAnyVM() { assertThat(validator.isDiskAttachedToAnyVm(), isValid()); } @Test public void testDiskAttachedToAnyVMFails() { VM vm1 = createVM(); VM vm2 = createVM(); vm1.setName("Vm1"); vm2.setName("Vm2"); List<VM> vmList = Arrays.asList(vm1, vm2); when(vmDao.getVmsListForDisk(any(Guid.class), anyBoolean())).thenReturn(vmList); String[] expectedReplacements = { ReplacementUtils.createSetVariableString(DiskValidator.DISK_NAME_VARIABLE, disk.getDiskAlias()), ReplacementUtils.createSetVariableString(DiskValidator.VM_LIST, "Vm1,Vm2")}; assertThat(validator.isDiskAttachedToAnyVm(), failsWith(EngineMessage.ACTION_TYPE_FAILED_DISK_ATTACHED_TO_VMS, expectedReplacements)); } @Test public void testDiskAttachedToVMFailWithCorrectReplacements() { VM vm = createVM(); vm.setName("MyVm"); disk.setDiskAlias("MyDisk"); String[] expectedReplacements = { ReplacementUtils.createSetVariableString(DiskValidator.DISK_NAME_VARIABLE, disk.getDiskAlias()), ReplacementUtils.createSetVariableString(DiskValidator.VM_NAME_VARIABLE, vm.getName())}; assertThat(validator.isDiskAttachedToVm(vm), failsWith(EngineMessage.ACTION_TYPE_FAILED_DISK_NOT_ATTACHED_TO_VM, expectedReplacements)); } @Test public void sparsifyNotSupportedForDirectLun() { setupForLun(); assertThat(lunValidator.isSparsifySupported(), failsWith(EngineMessage.ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_BY_DISK_STORAGE_TYPE)); } @Test public void sparsifySupportedByFileDomain() { createStorageDomainForDisk(StorageType.NFS); assertThat(validator.isSparsifySupported(), isValid()); } @Test public void sparsifyNotSupportedByOpenstackDomain() { createStorageDomainForDisk(StorageType.CINDER); assertThat(validator.isSparsifySupported(), failsWith(EngineMessage.ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_BY_STORAGE_TYPE)); } @Test public void sparsifySupportedWhenWipeAfterDeleteIsOff() { createStorageDomainForDisk(StorageType.ISCSI); assertThat(validator.isSparsifySupported(), isValid()); } @Test public void sparsifyNotSupportedWhenWipeAfterDeleteIsOn() { StorageDomain storageDomain = createStorageDomainForDisk(StorageType.ISCSI); disk.setWipeAfterDelete(true); storageDomain.setSupportsDiscardZeroesData(false); assertThat(validator.isSparsifySupported(), failsWith(EngineMessage .ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_BY_UNDERLYING_STORAGE_WHEN_WAD_IS_ENABLED)); } @Test public void sparsifySupportedWhenWipeAfterDeleteIsOn() { StorageDomain storageDomain = createStorageDomainForDisk(StorageType.FCP); disk.setWipeAfterDelete(true); storageDomain.setSupportsDiscardZeroesData(true); assertThat(validator.isSparsifySupported(), isValid()); } @Test public void sparsifyNotSupportedWhenDiskIsPreallocated() { createStorageDomainForDisk(StorageType.NFS); disk.getImage().setVolumeType(VolumeType.Preallocated); assertThat(validator.isSparsifySupported(), failsWith(EngineMessage .ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_FOR_PREALLOCATED)); } private LunDisk createLunDisk(ScsiGenericIO sgio) { LunDisk lunDisk = createLunDisk(); lunDisk.setSgio(sgio); return lunDisk; } private static DiskVmElement createDiskVmElementUsingScsiReserevation() { DiskVmElement dve = new DiskVmElement(); dve.setUsingScsiReservation(true); return dve; } }