package org.ovirt.engine.core.bll.exportimport; import static org.ovirt.engine.core.bll.storage.disk.image.DisksFilter.ONLY_ACTIVE; import static org.ovirt.engine.core.bll.storage.disk.image.DisksFilter.ONLY_NOT_SHAREABLE; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.ovirt.engine.core.bll.LockMessage; import org.ovirt.engine.core.bll.LockMessagesMatchUtil; import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute; import org.ovirt.engine.core.bll.RemoveVmCommand; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.memory.MemoryImageRemoverFromExportDomain; import org.ovirt.engine.core.bll.storage.disk.image.DisksFilter; import org.ovirt.engine.core.bll.tasks.CommandCoordinatorUtil; import org.ovirt.engine.core.bll.utils.PermissionSubject; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.LockProperties; import org.ovirt.engine.core.common.action.LockProperties.Scope; import org.ovirt.engine.core.common.action.RemoveVmFromImportExportParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.asynctasks.EntityInfo; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StorageDomainType; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.locks.LockingGroup; import org.ovirt.engine.core.common.queries.GetAllFromExportDomainQueryParameters; import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.common.vdscommands.RemoveVMVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.dao.StorageDomainDao; import org.ovirt.engine.core.dao.VmDao; @NonTransactiveCommandAttribute public class RemoveVmFromImportExportCommand<T extends RemoveVmFromImportExportParameters> extends RemoveVmCommand<T>{ @Inject private StorageDomainDao storageDomainDao; @Inject private VmDao vmDao; // this is needed since overriding getVmTemplate() private VM exportVm; public RemoveVmFromImportExportCommand(T parameters, CommandContext commandContext) { super(parameters, commandContext); setVmId(parameters.getVmId()); parameters.setEntityInfo(new EntityInfo(VdcObjectType.VM, parameters.getVmId())); setStorageDomainId(parameters.getStorageDomainId()); } @Override protected LockProperties applyLockProperties(LockProperties lockProperties) { return lockProperties.withScope(Scope.Command); } @Override protected Map<String, Pair<String, String>> getExclusiveLocks() { return Collections.singletonMap(getVmId().toString(), LockMessagesMatchUtil.makeLockingPair( LockingGroup.REMOTE_VM, new LockMessage(EngineMessage.ACTION_TYPE_FAILED_VM_IS_BEING_REMOVED_FROM_EXPORT_DOMAIN) .withOptional("VmName", getVmName()))); } @Override protected boolean validate() { StorageDomain storage = storageDomainDao.getForStoragePool( getParameters().getStorageDomainId(), getParameters().getStoragePoolId()); if (storage == null) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_EXIST); } if (storage.getStatus() == null || storage.getStatus() != StorageDomainStatus.Active) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_STATUS_ILLEGAL); } if (storage.getStorageDomainType() != StorageDomainType.ImportExport) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_TYPE_ILLEGAL); } // getVm() is the vm from the export domain if (getVm() == null) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND_ON_EXPORT_DOMAIN); } // not using getVm() since its overridden to get vm from export domain VM vm = vmDao.get(getVmId()); if (vm != null && vm.getStatus() == VMStatus.ImageLocked) { if (CommandCoordinatorUtil.hasTasksForEntityIdAndAction(vm.getId(), VdcActionType.ExportVm)) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_DURING_EXPORT); } } return true; } @Override protected void executeVmCommand() { removeVmInSpm(); removeDiskImages(); removeMemoryImages(); setSucceeded(true); } private void removeDiskImages() { List<DiskImage> images = DisksFilter.filterImageDisks(getVm().getDiskMap().values(), ONLY_NOT_SHAREABLE, ONLY_ACTIVE); for (DiskImage image : images) { image.setStorageIds(new ArrayList<>(Arrays.asList(getParameters().getStorageDomainId()))); image.setStoragePoolId(getParameters().getStoragePoolId()); } removeVmImages(images); } private boolean removeVmInSpm() { return runVdsCommand(VDSCommandType.RemoveVM, buildRemoveVmParameters()) .getSucceeded(); } private RemoveVMVDSCommandParameters buildRemoveVmParameters() { return new RemoveVMVDSCommandParameters( getParameters().getStoragePoolId(), getVmId(), getParameters().getStorageDomainId()); } private void removeMemoryImages() { new MemoryImageRemoverFromExportDomain(getVm(), this, getParameters().getStoragePoolId(), getParameters().getStorageDomainId()) .remove(); } @Override public AuditLogType getAuditLogTypeValue() { return getSucceeded() ? AuditLogType.IMPORTEXPORT_REMOVE_VM : AuditLogType.IMPORTEXPORT_REMOVE_VM_FAILED; } @Override protected void endVmCommand() { setCommandShouldBeLogged(false); setSucceeded(true); } /* * get vm from export domain */ @Override public VM getVm() { if (exportVm == null) { GetAllFromExportDomainQueryParameters tempVar = new GetAllFromExportDomainQueryParameters( getParameters().getStoragePoolId(), getParameters().getStorageDomainId()); tempVar.setIds(new ArrayList<>(Collections.singletonList(getVmId()))); VdcQueryReturnValue qretVal = runInternalQuery( VdcQueryType.GetVmsFromExportDomain, tempVar); if (qretVal != null && qretVal.getSucceeded()) { ArrayList<VM> vms = qretVal.getReturnValue(); if (!vms.isEmpty()) { exportVm = vms.get(0); setVm(exportVm); } } } return exportVm; } @Override public Map<String, String> getJobMessageProperties() { if (jobProperties == null) { jobProperties = super.getJobMessageProperties(); jobProperties.put(VdcObjectType.VM.name().toLowerCase(), (getVmName() == null) ? "" : getVmName()); jobProperties.put(VdcObjectType.Storage.name().toLowerCase(), getStorageDomainName()); } return jobProperties; } @Override public List<PermissionSubject> getPermissionCheckSubjects() { return Collections.singletonList(new PermissionSubject( getParameters().getStorageDomainId(), VdcObjectType.Storage, getActionType().getActionGroup())); } }