package org.ovirt.engine.core.bll.storage.utils;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
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.LUNs;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.DiskImageDao;
import org.ovirt.engine.core.dao.DiskVmElementDao;
import org.ovirt.engine.core.dao.StorageDomainDao;
@RunWith(MockitoJUnitRunner.class)
public class BlockStorageDiscardFunctionalityHelperTest {
private StorageDomain storageDomain;
private List<DiskImage> storageDomainDisks;
private List<DiskVmElement> storageDomainVmDisks;
@InjectMocks
public BlockStorageDiscardFunctionalityHelper discardHelper;
@Mock
public DiskImageDao diskImageDao;
@Mock
public DiskVmElementDao diskVmElementDao;
@Mock
private StorageDomainDao storageDomainDao;
@Before
public void setUp() {
createStorageDomain();
storageDomainDisks = new LinkedList<>();
when(diskImageDao.getAllForStorageDomain(storageDomain.getId())).thenReturn(storageDomainDisks);
storageDomainVmDisks = new LinkedList<>();
when(diskVmElementDao.getAllDiskVmElementsByDisksIds(anyCollection())).thenReturn(storageDomainVmDisks);
when(storageDomainDao.get(storageDomain.getId())).thenReturn(storageDomain);
}
@Test
public void testAllLunsSupportDiscardSucceeds() {
assertTrue(discardHelper.allLunsSupportDiscard(Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(2048L, false))));
}
@Test
public void testAllLunsSupportDiscardFailsOneLunDoesNotSupport() {
assertFalse(discardHelper.allLunsSupportDiscard(Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(2048L, false),
createLunWithDiscardFunctionality(0L, true)))); // This lun does not support discard.
}
@Test
public void testAllLunsSupportDiscardFailsOneLunHasNullValue() {
assertFalse(discardHelper.allLunsSupportDiscard(Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(2048L, false),
createLunWithDiscardFunctionality(null, true)))); // This lun does not support discard.
}
@Test
public void testAllLunsHaveDiscardZeroesTheDataSupportSucceeds() {
assertTrue(discardHelper.allLunsHaveDiscardZeroesTheDataSupport(Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(0L, true))));
}
@Test
public void testAllLunsHaveDiscardZeroesTheDataSupportFailsOneLunDoesNotSupport() {
assertFalse(discardHelper.allLunsHaveDiscardZeroesTheDataSupport(Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(0L, true),
createLunWithDiscardFunctionality(2048L, false)))); // This lun does not support discard zeroes the data.
}
@Test
public void testAllLunsHaveDiscardZeroesTheDataSupportFailsOneLunHasNullValue() {
assertFalse(discardHelper.allLunsHaveDiscardZeroesTheDataSupport(Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(0L, true),
createLunWithDiscardFunctionality(2048L, null)))); // This lun does not support discard zeroes the data.
}
@Test
public void testVmDiskWithPassDiscardExistsSucceeds() {
assertTrue(discardHelper.vmDiskWithPassDiscardExists(Arrays.asList(
createVmDisk(Guid.newGuid(), false),
createVmDisk(Guid.newGuid(), true))));
}
@Test
public void testVmDiskWithPassDiscardExistsFails() {
assertFalse(discardHelper.vmDiskWithPassDiscardExists(Arrays.asList(
createVmDisk(Guid.newGuid(), false),
createVmDisk(Guid.newGuid(), false))));
}
@Test
public void testVmDiskWithPassDiscardAndWadExistsSucceeds() {
createVmDiskOnSd(false, false);
createVmDiskOnSd(true, false);
createVmDiskOnSd(false, true);
createVmDiskOnSd(true, true);
assertTrue(discardHelper.vmDiskWithPassDiscardAndWadExists(storageDomainDisks, storageDomainVmDisks));
}
@Test
public void testVmDiskWithPassDiscardAndWadExistsFails() {
createVmDiskOnSd(false, false);
createVmDiskOnSd(true, false);
createVmDiskOnSd(false, true);
assertFalse(discardHelper.vmDiskWithPassDiscardAndWadExists(storageDomainDisks, storageDomainVmDisks));
}
@Test
public void testExistingPassDiscardFunctionalityIsPreservedSdHasNoDiscardFunctionality() {
setSdDiscardSupport(false, true);
assertTrue(discardHelper.isExistingPassDiscardFunctionalityPreserved(new LinkedList<>(), storageDomain));
}
@Test
public void testExistingPassDiscardFunctionalityIsPreservedSdHasNoDisks() {
setSdFullDiscardSupport();
assertTrue(discardHelper.isExistingPassDiscardFunctionalityPreserved(new LinkedList<>(), storageDomain));
}
@Test
public void testExistingPassDiscardFunctionalityIsPreservedAllLunsHaveDiscardFunctionality() {
setSdFullDiscardSupport();
storageDomainDisks.add(new DiskImage());
assertTrue(discardHelper.isExistingPassDiscardFunctionalityPreserved(Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(2048L, true)), storageDomain));
}
@Test
public void testExistingPassDiscardFunctionalityIsPreservedNoDiskRequiresPassDiscardFunctionality() {
setSdFullDiscardSupport();
createVmDiskOnSd(false, false);
createVmDiskOnSd(true, false);
assertTrue(discardHelper.isExistingPassDiscardFunctionalityPreserved(Arrays.asList(
createLunWithDiscardFunctionality(0L, true),
createLunWithDiscardFunctionality(2048L, false)), storageDomain));
}
@Test
public void testExistingPassDiscardFunctionalityIsNotPreservedSdDiscardSupportBreaks() {
setSdDiscardSupport(true, false);
createVmDiskOnSd(false, false);
createVmDiskOnSd(false, true); // This disk requires discard support from the storage domain.
assertFalse(discardHelper.isExistingPassDiscardFunctionalityPreserved(Arrays.asList(
createLunWithDiscardFunctionality(0L, true), // This lun breaks the storage domain's discard support.
createLunWithDiscardFunctionality(2048L, false)), storageDomain));
}
@Test
public void testExistingPassDiscardFunctionalityIsNotPreservedSdDiscardZeroesTheDataSupportBreaks() {
setSdDiscardSupport(true, true);
createVmDiskOnSd(false, false);
createVmDiskOnSd(true, true); // This disk requires the storage domain's support for discard zeroes the data.
assertFalse(discardHelper.isExistingPassDiscardFunctionalityPreserved(Arrays.asList(
// This lun breaks the storage domain's support for discard zeroes the data.
createLunWithDiscardFunctionality(1024L, false),
createLunWithDiscardFunctionality(2048L, true)), storageDomain));
}
@Test
public void testExistingDiscardAfterDeleteFunctionalityPreservedNoDiscardAfterDeleteFunctionality() {
storageDomain.setDiscardAfterDelete(false);
assertTrue(discardHelper.isExistingDiscardAfterDeleteFunctionalityPreserved(Arrays.asList(
createLunWithDiscardFunctionality(0L, false),
createLunWithDiscardFunctionality(0L, true)), storageDomain));
}
@Test
public void testExistingDiscardAfterDeleteFunctionalityPreservedAllLunsHaveDiscardAfterDeleteFunctionality() {
storageDomain.setDiscardAfterDelete(true);
assertTrue(discardHelper.isExistingDiscardAfterDeleteFunctionalityPreserved(Arrays.asList(
createLunWithDiscardFunctionality(1024L, false),
createLunWithDiscardFunctionality(2048L, true)), storageDomain));
}
@Test
public void testExistingDiscardAfterDeleteFunctionalityPreservedDiscardAfterDeleteFunctionalityBreaks() {
storageDomain.setDiscardAfterDelete(true);
assertFalse(discardHelper.isExistingDiscardAfterDeleteFunctionalityPreserved(Arrays.asList(
createLunWithDiscardFunctionality(1024L, false),
createLunWithDiscardFunctionality(0L, true)), storageDomain));
}
@Test
public void testGetLunsThatBreakPassDiscardFunctionalityPassDiscardBreaks() {
createVmDiskOnSd(false, false);
createVmDiskOnSd(false, true); // This disk requires pass discard support.
LUNs lunThatBreaksDiscardSupport = createLunWithDiscardFunctionality(0L, false);
assertGetLunsThatBreakPassDiscardFunctionalityContainsExpectedLuns(
Arrays.asList(createLunWithDiscardFunctionality(1024L, false), lunThatBreaksDiscardSupport),
Collections.singletonList(lunThatBreaksDiscardSupport));
}
@Test
public void testGetLunsThatBreakPassDiscardFunctionalityDiscardZeroesTheDataBreaks() {
createVmDiskOnSd(false, false);
createVmDiskOnSd(true, true); // This disk requires discard zeroes the data support.
LUNs lunThatBreaksDiscardZeroesTheDataSupport = createLunWithDiscardFunctionality(1024L, false);
assertGetLunsThatBreakPassDiscardFunctionalityContainsExpectedLuns(
Arrays.asList(createLunWithDiscardFunctionality(1024L, true), lunThatBreaksDiscardZeroesTheDataSupport),
Collections.singletonList(lunThatBreaksDiscardZeroesTheDataSupport));
}
@Test
public void testGetLunsThatBreakPassDiscardFunctionalityFullDiscardFunctionalityBreaks() {
createVmDiskOnSd(false, false);
createVmDiskOnSd(true, true); // This disk requires both pass discard and discard zeroes the data support.
LUNs lunThatBreaksDiscardSupport = createLunWithDiscardFunctionality(0L, false);
LUNs lunThatBreaksDiscardZeroesTheDataSupport = createLunWithDiscardFunctionality(1024L, false);
assertGetLunsThatBreakPassDiscardFunctionalityContainsExpectedLuns(
Arrays.asList(createLunWithDiscardFunctionality(1024L, true), lunThatBreaksDiscardSupport,
lunThatBreaksDiscardZeroesTheDataSupport),
Arrays.asList(lunThatBreaksDiscardSupport, lunThatBreaksDiscardZeroesTheDataSupport));
}
@Test
public void testGetLunsThatBreakPassDiscardFunctionalityDiscardFunctionalityDoesntBreak() {
createVmDiskOnSd(false, false); // This disk does not require any discard functionality.
createVmDiskOnSd(true, true); // This disk requires both pass discard and discard zeroes the data support.
assertGetLunsThatBreakPassDiscardFunctionalityContainsExpectedLuns(
Arrays.asList(createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(2048L, true)),
Collections.emptyList());
}
@Test
public void testGetLunsThatBreakDiscardAfterDeleteSupportStorageDomainDiscardAfterDeleteDisabled() {
storageDomain.setDiscardAfterDelete(false);
assertGetLunsThatBreakDiscardAfterDeleteSupportContainsExpectedLuns(
Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(0L, false)),
Collections.emptyList());
}
@Test
public void testGetLunsThatBreakDiscardAfterDeleteSupportDiscardAfterDeleteBreaks() {
storageDomain.setDiscardAfterDelete(true);
LUNs lunThatBreaksDiscardSupport = createLunWithDiscardFunctionality(0L, true);
assertGetLunsThatBreakDiscardAfterDeleteSupportContainsExpectedLuns(
Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
lunThatBreaksDiscardSupport),
Collections.singletonList(lunThatBreaksDiscardSupport));
}
@Test
public void testGetLunsThatBreakDiscardAfterDeleteSupportDiscardAfterDeleteDoesntBreak() {
storageDomain.setDiscardAfterDelete(true);
assertGetLunsThatBreakDiscardAfterDeleteSupportContainsExpectedLuns(
Arrays.asList(
createLunWithDiscardFunctionality(1024L, true),
createLunWithDiscardFunctionality(2048L, false)),
Collections.emptyList());
}
private void createStorageDomain() {
storageDomain = new StorageDomain();
storageDomain.setId(Guid.newGuid());
}
private void setSdDiscardSupport(boolean sdSupportsDiscard, boolean sdDiscardZeroesData) {
storageDomain.setSupportsDiscard(sdSupportsDiscard);
storageDomain.setSupportsDiscardZeroesData(sdDiscardZeroesData);
}
private LUNs createLunWithDiscardFunctionality(Long discardMaxSize, Boolean discardZeroesData) {
LUNs lun = new LUNs();
lun.setDiscardMaxSize(discardMaxSize);
lun.setDiscardZeroesData(discardZeroesData);
return lun;
}
private void setSdFullDiscardSupport() {
setSdDiscardSupport(true, true);
}
private DiskVmElement createVmDisk(Guid diskId, boolean passDiscard) {
DiskVmElement diskVmElement = new DiskVmElement(diskId, Guid.newGuid());
diskVmElement.setPassDiscard(passDiscard);
return diskVmElement;
}
private void createVmDiskOnSd(boolean wipeAfterDelete, boolean passDiscard) {
DiskImage disk = new DiskImage();
Guid diskId = Guid.newGuid();
disk.setId(diskId);
disk.setWipeAfterDelete(wipeAfterDelete);
storageDomainDisks.add(disk);
storageDomainVmDisks.add(createVmDisk(diskId, passDiscard));
}
private void assertGetLunsThatBreakPassDiscardFunctionalityContainsExpectedLuns(Collection<LUNs> luns,
Collection<LUNs> expectedLunsThatBreakPassDiscardFunctionality) {
Collection<LUNs> lunsThatBreakPassDiscardFunctionality =
discardHelper.getLunsThatBreakPassDiscardSupport(luns, storageDomain.getId());
assertTrue(CollectionUtils.isEqualCollection(lunsThatBreakPassDiscardFunctionality,
expectedLunsThatBreakPassDiscardFunctionality));
}
private void assertGetLunsThatBreakDiscardAfterDeleteSupportContainsExpectedLuns(Collection<LUNs> luns,
Collection<LUNs> expectedLunsThatBreakDiscardAfterDeleteSupport) {
Collection<LUNs> lunsThatBreakDiscardAfterDeleteSupport =
discardHelper.getLunsThatBreakDiscardAfterDeleteSupport(luns, storageDomain.getId());
assertTrue(CollectionUtils.isEqualCollection(lunsThatBreakDiscardAfterDeleteSupport,
expectedLunsThatBreakDiscardAfterDeleteSupport));
}
}