package org.ovirt.engine.core.bll.storage.domain; import javax.inject.Inject; import javax.inject.Singleton; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.storage.DiskVmElement; import org.ovirt.engine.core.common.vdscommands.PostDeleteAction; import org.ovirt.engine.core.common.vdscommands.StoragePoolDomainAndGroupIdBaseVDSCommandParameters; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogable; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableImpl; import org.ovirt.engine.core.dao.DiskVmElementDao; import org.ovirt.engine.core.dao.StorageDomainDao; @Singleton public class PostDeleteActionHandler { @Inject private StorageDomainDao storageDomainStaticDao; @Inject private DiskVmElementDao diskVmElementDao; @Inject private AuditLogDirector auditLogDirector; /** * Fixes the fields 'postZero' and 'discard' for parameters * with post delete action, before sending them to vdsm. * @param parameters the parameters of the command that should be executed. * @param <T> the parameters type. * @return the fixed parameters. */ public <T extends StoragePoolDomainAndGroupIdBaseVDSCommandParameters & PostDeleteAction> T fixParameters( T parameters) { StorageDomain storageDomain = storageDomainStaticDao.get(parameters.getStorageDomainId()); T parametersWithFixedPostZero = fixPostZeroField(parameters, storageDomain.getStorageType().isFileDomain()); return fixDiscardField(parametersWithFixedPostZero, storageDomain); } /** * Since the file system is responsible for handling block allocation, there is no need * for posting zeros on file domains. This method gets the parameters of a command that may * post zeros on the storage and fixes its postZero value if required. * @param parameters the parameters of the command that should be executed. * @param isFileDomain is the storage domain a file domain. * @param <T> the parameters type. * @return the fixed parameters. */ protected <T extends StoragePoolDomainAndGroupIdBaseVDSCommandParameters & PostDeleteAction> T fixPostZeroField( T parameters, boolean isFileDomain) { if (isFileDomain) { parameters.setPostZero(false); } return parameters; } /** * Since a storage domain's discard support may be changed since the discard after delete value was chosen by the * user, we should check its support before sending it to vdsm. If it doesn't support discard any more, that means * that discarding the disk will not work, and we can let the user know about it and send discard=false to vdsm. * @param parameters the parameters of the command that should be executed. * @param storageDomain the storage domain that the disk or snapshot belongs to. * @param <T> the parameters type. * @return the fixed parameters. */ protected <T extends StoragePoolDomainAndGroupIdBaseVDSCommandParameters & PostDeleteAction> T fixDiscardField( T parameters, StorageDomain storageDomain) { if (storageDomain.isDiscardAfterDelete()) { if (!Boolean.TRUE.equals(storageDomain.getSupportsDiscard())) { parameters.setDiscard(false); AuditLogable auditLog = new AuditLogableImpl(); auditLog.setStorageDomainId(storageDomain.getId()); auditLogDirector.log(auditLog, AuditLogType.ILLEGAL_STORAGE_DOMAIN_DISCARD_AFTER_DELETE); } } else if (diskVmElementWithPassDiscardExists(parameters.getImageGroupId()) && Boolean.TRUE.equals(storageDomain.getSupportsDiscard())) { // At least one vm has this disk with pass discard enabled. // Thus, although the relevant storage domain's discard after // delete value is false, we send discard = true to vdsm. parameters.setDiscard(true); } return parameters; } protected boolean diskVmElementWithPassDiscardExists(Guid diskId) { return diskVmElementDao.getAllDiskVmElementsByDiskId(diskId).stream().anyMatch(DiskVmElement::isPassDiscard); } }