package org.ovirt.engine.core.bll.validator.storage; import org.ovirt.engine.core.bll.ValidationResult; import org.ovirt.engine.core.bll.utils.VmDeviceUtils; import org.ovirt.engine.core.bll.validator.VmValidationUtils; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.storage.Disk; 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.LunDisk; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.osinfo.OsRepository; import org.ovirt.engine.core.common.utils.SimpleDependencyInjector; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.StorageDomainDao; import org.ovirt.engine.core.di.Injector; public class DiskVmElementValidator { private Disk disk; private DiskVmElement diskVmElement; public DiskVmElementValidator(Disk disk, DiskVmElement diskVmElement) { this.disk = disk; this.diskVmElement = diskVmElement; } public Guid getDiskId() { return disk.getId(); } public ValidationResult isReadOnlyPropertyCompatibleWithInterface() { if (Boolean.TRUE.equals(diskVmElement.isReadOnly())) { DiskInterface diskInterface = diskVmElement.getDiskInterface(); if (diskInterface == DiskInterface.IDE) { return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_INTERFACE_DOES_NOT_SUPPORT_READ_ONLY_ATTR, String.format("$interface %1$s", diskInterface)); } if (disk.isScsiPassthrough()) { return new ValidationResult(EngineMessage.SCSI_PASSTHROUGH_IS_NOT_SUPPORTED_FOR_READ_ONLY_DISK); } } return ValidationResult.VALID; } /** * Verifies Virtio-SCSI interface validity. */ public ValidationResult isVirtIoScsiValid(VM vm) { if (vm != null && DiskInterface.VirtIO_SCSI != diskVmElement.getDiskInterface()) { return ValidationResult.VALID; } if (disk.getSgio() != null) { if (DiskStorageType.IMAGE == disk.getDiskStorageType()) { return new ValidationResult(EngineMessage.SCSI_GENERIC_IO_IS_NOT_SUPPORTED_FOR_IMAGE_DISK); } } if (vm != null) { if (!isVirtioScsiControllerAttached(vm.getId())) { return new ValidationResult(EngineMessage.CANNOT_PERFORM_ACTION_VIRTIO_SCSI_IS_DISABLED); } else { return isOsSupportedForVirtIoScsi(vm); } } return ValidationResult.VALID; } private boolean isVirtioScsiControllerAttached(Guid vmId) { VmDeviceUtils vmDeviceUtils = Injector.get(VmDeviceUtils.class); return vmDeviceUtils.hasVirtioScsiController(vmId); } /** * Validates that the OS is supported for Virtio-SCSI interface. */ private ValidationResult isOsSupportedForVirtIoScsi(VM vm) { if (!VmValidationUtils.isDiskInterfaceSupportedByOs( vm.getOs(), vm.getCompatibilityVersion(), DiskInterface.VirtIO_SCSI)) { return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_GUEST_OS_VERSION_IS_NOT_SUPPORTED); } return ValidationResult.VALID; } public ValidationResult isDiskInterfaceSupported(VM vm) { if (vm != null) { if (!VmValidationUtils.isDiskInterfaceSupportedByOs( vm.getOs(), vm.getCompatibilityVersion(), diskVmElement.getDiskInterface())) { return new ValidationResult(EngineMessage.ACTION_TYPE_DISK_INTERFACE_UNSUPPORTED, String.format("$osName %s", getOsRepository().getOsName(vm.getOs()))); } } return ValidationResult.VALID; } private static OsRepository getOsRepository() { return SimpleDependencyInjector.getInstance().get(OsRepository.class); } public ValidationResult isPassDiscardSupported(Guid storageDomainId) { if (!diskVmElement.isPassDiscard()) { return ValidationResult.VALID; } DiskInterface diskInterface = diskVmElement.getDiskInterface(); if (diskInterface != DiskInterface.VirtIO_SCSI && diskInterface != DiskInterface.IDE) { return new ValidationResult( EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_DISK_INTERFACE, getDiskAliasVarReplacement()); } if (disk.getDiskStorageType() == DiskStorageType.LUN) { return isPassDiscardSupportedByUnderlyingStorageForDirectLun(); } if (disk.getDiskStorageType() == DiskStorageType.IMAGE) { return isPassDiscardSupportedByUnderlyingStorageForDiskImage(storageDomainId); } return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_DISK_STORAGE_TYPE, getDiskAliasVarReplacement(), String.format("$diskStorageType %s", disk.getDiskStorageType())); } private ValidationResult isPassDiscardSupportedByUnderlyingStorageForDirectLun() { if (((LunDisk) disk).getLun().supportsDiscard()) { return ValidationResult.VALID; } return new ValidationResult( EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_FOR_DIRECT_LUN_BY_UNDERLYING_STORAGE, getDiskAliasVarReplacement()); } private ValidationResult isPassDiscardSupportedByUnderlyingStorageForDiskImage(Guid storageDomainId) { StorageDomain diskStorageDomain = Injector.get(StorageDomainDao.class).get(storageDomainId); if (diskStorageDomain.getStorageType().isFileDomain()) { return ValidationResult.VALID; } else if (diskStorageDomain.getStorageType().isBlockDomain()) { if (!diskStorageDomain.getSupportsDiscard()) { return new ValidationResult(EngineMessage .ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_FOR_DISK_IMAGE_BY_UNDERLYING_STORAGE, getDiskAliasVarReplacement(), getStorageDomainNameVarReplacement(diskStorageDomain)); } if (disk.isWipeAfterDelete() && !diskStorageDomain.getSupportsDiscardZeroesData()) { return new ValidationResult(EngineMessage .ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_UNDERLYING_STORAGE_WHEN_WAD_IS_ENABLED, getStorageDomainNameVarReplacement(diskStorageDomain), getDiskAliasVarReplacement()); } return ValidationResult.VALID; } return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_PASS_DISCARD_NOT_SUPPORTED_BY_STORAGE_TYPE, getDiskAliasVarReplacement(), getStorageDomainNameVarReplacement(diskStorageDomain), String.format("$storageType %s", diskStorageDomain.getStorageType())); } private String getDiskAliasVarReplacement() { return String.format("$diskAlias %s", disk.getDiskAlias()); } private String getStorageDomainNameVarReplacement(StorageDomain storageDomain) { return String.format("$storageDomainName %s", storageDomain.getName()); } }