package org.ovirt.engine.core.bll.storage.domain;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.LockMessagesMatchUtil;
import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.validator.storage.StorageDomainToPoolRelationValidator;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.DetachStorageDomainFromPoolParameters;
import org.ovirt.engine.core.common.action.LockProperties;
import org.ovirt.engine.core.common.action.LockProperties.Scope;
import org.ovirt.engine.core.common.action.RemoveStorageDomainParameters;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.errors.EngineError;
import org.ovirt.engine.core.common.errors.EngineException;
import org.ovirt.engine.core.common.errors.EngineFault;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.locks.LockingGroup;
import org.ovirt.engine.core.common.queries.StorageDomainsAndStoragePoolIdQueryParameters;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.common.vdscommands.FormatStorageDomainVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.StorageDomainDao;
import org.ovirt.engine.core.dao.StoragePoolIsoMapDao;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;
@NonTransactiveCommandAttribute
public class RemoveStorageDomainCommand<T extends RemoveStorageDomainParameters> extends StorageDomainCommandBase<T> {
@Inject
private StoragePoolIsoMapDao storagePoolIsoMapDao;
@Inject
private StorageDomainDao storageDomainDao;
public RemoveStorageDomainCommand(T parameters, CommandContext commandContext) {
super(parameters, commandContext);
}
@Override
protected LockProperties applyLockProperties(LockProperties lockProperties) {
return lockProperties.withScope(Scope.Execution);
}
@Override
protected void executeCommand() {
final StorageDomain dom = getStorageDomain();
VDS vds = getVds();
boolean format = getParameters().getDoFormat();
setSucceeded(false);
if (detachLocalStorageDomain(dom)) {
return;
}
if (format) {
Pair<Boolean, EngineFault> connectResult = connectStorage();
if (!connectResult.getFirst()) {
getReturnValue().setFault(connectResult.getSecond());
return;
}
boolean failed = !formatStorage(dom, vds);
disconnectStorage();
if (failed) {
return;
}
}
TransactionSupport.executeInNewTransaction(() -> {
getStorageHelper(dom).storageDomainRemoved(dom.getStorageStaticData());
storageDomainDao.remove(dom.getId());
return null;
});
setSucceeded(true);
}
private boolean detachLocalStorageDomain(StorageDomain dom) {
return isLocalFs(dom) && isDomainAttached(dom) && !detachStorage(dom);
}
@Override
public AuditLogType getAuditLogTypeValue() {
return getSucceeded() ? AuditLogType.USER_REMOVE_STORAGE_DOMAIN
: AuditLogType.USER_REMOVE_STORAGE_DOMAIN_FAILED;
}
@Override
protected void setActionMessageParameters() {
super.setActionMessageParameters();
addValidationMessage(EngineMessage.VAR__ACTION__REMOVE);
}
@Override
protected boolean validate() {
if (!super.validate()) {
return false;
}
StorageDomain dom = getStorageDomain();
if (dom == null) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_EXIST);
}
boolean localFs = isLocalFs(dom);
if (getParameters().getDoFormat() && !localFs && isStorageDomainAttached(dom)) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_FORMAT_STORAGE_DOMAIN_WITH_ATTACHED_DATA_DOMAIN);
}
VDS vds = getVds();
StorageDomainToPoolRelationValidator domainPoolValidator = createDomainToPoolValidator(dom);
if (!checkStorageDomain()) {
return false;
}
if (!localFs && !validate(domainPoolValidator.isStorageDomainNotInAnyPool())) {
return false;
}
if (localFs && isDomainAttached(dom) && !canDetachDomain(getParameters().getDestroyingPool(), false)) {
return false;
}
if (vds == null) {
if (localFs) {
if (!initializeVds()) {
return false;
}
} else {
return failValidation(EngineMessage.CANNOT_REMOVE_STORAGE_DOMAIN_INVALID_HOST_ID);
}
}
if (dom.getStorageType().isOpenStackDomain()) {
return failValidation(EngineMessage.ERROR_CANNOT_MANAGE_STORAGE_DOMAIN);
}
return true;
}
protected boolean isStorageDomainAttached(StorageDomain dom) {
List<StorageDomain> storageDomainList =
getBackend().runInternalQuery(VdcQueryType.GetStorageDomainsWithAttachedStoragePoolGuid,
new StorageDomainsAndStoragePoolIdQueryParameters(dom, getStoragePoolId(), getVds().getId(), false))
.getReturnValue();
return !storageDomainList.isEmpty();
}
protected StorageDomainToPoolRelationValidator createDomainToPoolValidator(StorageDomain dom) {
return new StorageDomainToPoolRelationValidator(dom.getStorageStaticData(), null);
}
private Pair<Boolean, EngineFault> connectStorage() {
return getStorageHelper(getStorageDomain()).connectStorageToDomainByVdsIdDetails(getStorageDomain(),
getVds().getId());
}
private void disconnectStorage() {
getStorageHelper(getStorageDomain()).disconnectStorageFromDomainByVdsId(getStorageDomain(),
getVds().getId());
}
protected boolean isLocalFs(StorageDomain dom) {
return dom.getStorageType() == StorageType.LOCALFS;
}
protected boolean isDomainAttached(StorageDomain storageDomain) {
if (storageDomain.getStoragePoolId() == null) {
return false;
}
Guid storageDomainId = storageDomain.getId();
Guid storagePoolId = storageDomain.getStoragePoolId();
return storagePoolIsoMapDao.get(new StoragePoolIsoMapId(storageDomainId, storagePoolId)) != null;
}
protected boolean detachStorage(StorageDomain dom) {
Guid domId = dom.getId();
Guid poolId = dom.getStoragePoolId();
DetachStorageDomainFromPoolParameters params = new DetachStorageDomainFromPoolParameters(domId, poolId);
params.setDestroyingPool(getParameters().getDestroyingPool());
return getBackend()
.runInternalAction(VdcActionType.DetachStorageDomainFromPool,
params, cloneContext().withoutCompensationContext().withoutExecutionContext()).getSucceeded();
}
protected boolean formatStorage(StorageDomain dom, VDS vds) {
try {
return runVdsCommand(VDSCommandType.FormatStorageDomain,
new FormatStorageDomainVDSCommandParameters(vds.getId(), dom.getId())).getSucceeded();
} catch (EngineException e) {
if (e.getErrorCode() != EngineError.StorageDomainDoesNotExist) {
throw e;
}
log.warn("Storage Domain '{}' which was about to be formatted does not exist in VDS '{}'",
dom.getName(),
vds.getName());
return true;
}
}
@Override
protected Map<String, Pair<String, String>> getExclusiveLocks() {
return Collections.singletonMap(getParameters().getStorageDomainId().toString(),
LockMessagesMatchUtil.makeLockingPair(LockingGroup.STORAGE, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));
}
}