package org.ovirt.engine.core.bll.validator.storage;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.mockito.Mock;
import org.ovirt.engine.core.bll.ValidationResult;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.storage.CinderDisk;
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.DiskInterface;
import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType;
import org.ovirt.engine.core.common.businessentities.storage.DiskVmElement;
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.StorageType;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.StorageDomainDao;
import org.ovirt.engine.core.di.InjectorRule;
@RunWith(Parameterized.class)
public class DiskVmElementDiscardSupportValidatorTest {
@ClassRule
public static InjectorRule injectorRule = new InjectorRule();
@Mock
private StorageDomainDao storageDomainDao;
private Disk disk;
private static String diskAlias = "disk1";
private Guid storageDomainId;
private static String storageDomainName = "sd1";
private DiskVmElementValidator validator;
private ValidationResult expectedResult;
public DiskVmElementDiscardSupportValidatorTest(Disk disk, boolean isPassDiscard, DiskInterface diskInterface,
Long lunDiscardMaxSize, StorageType storageType, Boolean sdSupportsDiscard, Boolean diskWipeAfterDelete,
Boolean sdSupportsDiscardZeroesData, ValidationResult expectedResult) {
this.disk = disk;
this.disk.setDiskAlias(diskAlias);
DiskVmElement diskVmElement = new DiskVmElement();
diskVmElement.setPassDiscard(isPassDiscard);
diskVmElement.setDiskInterface(diskInterface);
this.validator = new DiskVmElementValidator(this.disk, diskVmElement);
if (lunDiscardMaxSize != null) {
LUNs lun = new LUNs();
lun.setDiscardMaxSize(lunDiscardMaxSize);
((LunDisk) this.disk).setLun(lun);
}
if (storageType != null) {
initDiskStorageDomain(storageType, sdSupportsDiscard, sdSupportsDiscardZeroesData);
}
if (diskWipeAfterDelete != null) {
this.disk.setWipeAfterDelete(diskWipeAfterDelete);
}
this.expectedResult = expectedResult;
}
@Parameters
public static Object[][] data() {
ValidationResult passDiscardNotSupportedByDiskInterface = new ValidationResult(
EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_DISK_INTERFACE,
getDiskAliasVarReplacement());
ValidationResult passDiscardNotSupportedForDirectLunByUnderlyingStorage = new ValidationResult(
EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_FOR_DIRECT_LUN_BY_UNDERLYING_STORAGE,
getDiskAliasVarReplacement());
ValidationResult passDiscardNotSupportedForDiskImageByUnderlyingStorage = new ValidationResult(
EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_FOR_DISK_IMAGE_BY_UNDERLYING_STORAGE,
getDiskAliasVarReplacement(), getStorageDomainNameVarReplacement());
ValidationResult passDiscardNotSupportedByCinder = new ValidationResult(
EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_DISK_STORAGE_TYPE,
getDiskAliasVarReplacement(), String.format("$diskStorageType %s", DiskStorageType.CINDER));
// disk, isPassDiscard, diskInterface, lunDiscardMaxSize, storageType,
// sdSupportsDiscard, diskWipeAfterDelete, sdSupportsDiscardZeroesData, expectedResult.
return new Object[][] {
// isPassDiscard == false
{new DiskImage(), false, null, null, null,
null, null, null, ValidationResult.VALID},
// Unsupported interface
{new DiskImage(), true, DiskInterface.VirtIO, null, null,
null, null, null, passDiscardNotSupportedByDiskInterface},
{new DiskImage(), true, DiskInterface.SPAPR_VSCSI, null, null,
null, null, null, passDiscardNotSupportedByDiskInterface},
// Direct lun without support from underlying storage (different interfaces)
{new LunDisk(), true, DiskInterface.VirtIO_SCSI, 0L, null,
null, null, null, passDiscardNotSupportedForDirectLunByUnderlyingStorage},
{new LunDisk(), true, DiskInterface.IDE, 0L, null,
null, null, null, passDiscardNotSupportedForDirectLunByUnderlyingStorage},
// Direct lun with support from underlying storage (different interfaces)
{new LunDisk(), true, DiskInterface.VirtIO_SCSI, 1024L, null,
null, null, null, ValidationResult.VALID},
{new LunDisk(), true, DiskInterface.IDE, 1024L, null,
null, null, null, ValidationResult.VALID},
/*
Image on file storage domain:
- with/without support from underlying storage
- different interfaces
- different file storage types
*/
{new DiskImage(), true, DiskInterface.VirtIO_SCSI, null, StorageType.NFS,
true, null, null, ValidationResult.VALID},
{new DiskImage(), true, DiskInterface.IDE, null, StorageType.POSIXFS,
false, null, null, ValidationResult.VALID},
{new DiskImage(), true, DiskInterface.IDE, null, StorageType.POSIXFS,
null, null, null, ValidationResult.VALID},
/*
Image on block storage domain without support from underlying storage:
- different interfaces
- different block storage types
*/
{new DiskImage(), true, DiskInterface.VirtIO_SCSI, null, StorageType.ISCSI,
false, null, null, passDiscardNotSupportedForDiskImageByUnderlyingStorage},
{new DiskImage(), true, DiskInterface.IDE, null, StorageType.FCP,
false, null, null, passDiscardNotSupportedForDiskImageByUnderlyingStorage},
/*
Image on block storage domain with support from underlying storage:
- different interfaces
- different block storage types
*/
{new DiskImage(), true, DiskInterface.VirtIO_SCSI, null, StorageType.ISCSI,
true, null, null, ValidationResult.VALID},
{new DiskImage(), true, DiskInterface.IDE, null, StorageType.FCP,
true, null, null, ValidationResult.VALID},
/*
Image on block storage domain with support from underlying storage and WAD enabled:
- different interfaces
- different block storage types
- with/without sd support from discard zeroes the data.
*/
{new DiskImage(), true, DiskInterface.VirtIO_SCSI, null, StorageType.ISCSI,
true, true, true, ValidationResult.VALID},
{new DiskImage(), true, DiskInterface.IDE, null, StorageType.FCP,
true, true, false, new ValidationResult(EngineMessage
.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_UNDERLYING_STORAGE_WHEN_WAD_IS_ENABLED,
getStorageDomainNameVarReplacement(), getDiskAliasVarReplacement())},
/*
Image on non file or block storage domain:
- different interfaces
- different non file or block storage types
*/
{new DiskImage(), true, DiskInterface.VirtIO_SCSI, null, StorageType.UNKNOWN,
null, null, null, createPassDiscardNotSupportedByStorageTypeValResult(StorageType.UNKNOWN)},
{new DiskImage(), true, DiskInterface.IDE, null, StorageType.CINDER,
null, null, null, createPassDiscardNotSupportedByStorageTypeValResult(StorageType.CINDER)},
// Unsupported disk storage type (different interfaces)
{new CinderDisk(), true, DiskInterface.VirtIO_SCSI, null, null,
null, null, null, passDiscardNotSupportedByCinder},
{new CinderDisk(), true, DiskInterface.IDE, null, null,
null, null, null, passDiscardNotSupportedByCinder},
};
}
@Test
public void testPassDiscardSupport() {
assertEquals(expectedResult, validator.isPassDiscardSupported(storageDomainId));
}
private void initDiskStorageDomain(StorageType storageType, Boolean sdSupportsDiscard,
Boolean sdSupportsDiscardZeroesData) {
StorageDomain storageDomain = new StorageDomain();
storageDomain.setStorageName(storageDomainName);
storageDomain.setStorageType(storageType);
storageDomain.setSupportsDiscard(sdSupportsDiscard);
storageDomain.setSupportsDiscardZeroesData(sdSupportsDiscardZeroesData);
storageDomainId = Guid.newGuid();
storageDomain.setId(storageDomainId);
initMocks(this);
injectorRule.bind(StorageDomainDao.class, storageDomainDao);
when(storageDomainDao.get(storageDomainId)).thenReturn(storageDomain);
}
private static String getDiskAliasVarReplacement() {
return String.format("$diskAlias %s", diskAlias);
}
private static String getStorageDomainNameVarReplacement() {
return String.format("$storageDomainName %s", storageDomainName);
}
private static ValidationResult createPassDiscardNotSupportedByStorageTypeValResult(
StorageType storageType) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_STORAGE_TYPE,
getDiskAliasVarReplacement(), getStorageDomainNameVarReplacement(),
String.format("$storageType %s", storageType));
}
}