Arik Hadas has uploaded a new change for review. Change subject: core: managed removal of memory volumes in negative flows ......................................................................
core: managed removal of memory volumes in negative flows On failure while importing VM or creating snapshot with memory, we need to remove the memory volumes that were copied/created. The remove image operation is asynchronous, i.e it is based on tasks. On negative flows such as the ones mentioned above, we need to remove the memory image in the end-action phase. Since our infrastructure for commands doesn't support scenarios where tasks are created in the end-action phase well, we used to create the tasks for the remove operation without polling them. The problem was that without polling the tasks they remained in VDSM forever. The solution is to invoke the command that removes memory volumes as a stand-alone command, and not as a child of the failed command. It means that the tasks will be created as tasks of RemoveMemoryVolumesCommand and thus its end-action methods will be called and not the ones of the failed command. Change-Id: Ib4b270ec0e1ab41cae34459dde9f9cf47b1b5bdf Bug-Url: https://bugzilla.redhat.com/1019394 Signed-off-by: Arik Hadas <aha...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveMemoryVolumesCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemover.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemoverOnDataDomain.java 6 files changed, 69 insertions(+), 39 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/22/23222/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java index fa9f0e0..4de449b 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java @@ -309,14 +309,9 @@ } private void removeMemoryVolumesOfSnapshot(Snapshot snapshot) { - RemoveMemoryVolumesParameters parameters = new RemoveMemoryVolumesParameters(snapshot.getMemoryVolume(), getVmId()); - parameters.setParentCommand(getActionType()); - parameters.setEntityInfo(getParameters().getEntityInfo()); - parameters.setParentParameters(getParameters()); - VdcReturnValueBase retVal = getBackend().runInternalAction( VdcActionType.RemoveMemoryVolumes, - parameters, + new RemoveMemoryVolumesParameters(snapshot.getMemoryVolume(), getVmId()), ExecutionHandler.createDefaultContexForTasks(getExecutionContext())); if (!retVal.getSucceeded()) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java index ad8d2dd..1c28434 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java @@ -1172,14 +1172,9 @@ } private void removeMemoryVolumes(String memoryVolume, Guid vmId) { - RemoveMemoryVolumesParameters parameters = new RemoveMemoryVolumesParameters(memoryVolume, vmId); - parameters.setParentCommand(getActionType()); - parameters.setEntityInfo(getParameters().getEntityInfo()); - parameters.setParentParameters(getParameters()); - VdcReturnValueBase retVal = getBackend().runInternalAction( VdcActionType.RemoveMemoryVolumes, - parameters, + new RemoveMemoryVolumesParameters(memoryVolume, vmId), ExecutionHandler.createDefaultContexForTasks(getExecutionContext())); if (!retVal.getSucceeded()) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveMemoryVolumesCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveMemoryVolumesCommand.java index da03968..3a942de 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveMemoryVolumesCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveMemoryVolumesCommand.java @@ -4,13 +4,14 @@ import java.util.Collections; import java.util.List; -import org.ovirt.engine.core.bll.memory.HibernationVolumesRemover; +import org.ovirt.engine.core.bll.memory.MemoryImageRemoverOnDataDomain; import org.ovirt.engine.core.bll.tasks.TaskHandlerCommand; import org.ovirt.engine.core.bll.utils.PermissionSubject; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.RemoveMemoryVolumesParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.asynctasks.AsyncTaskCreationInfo; +import org.ovirt.engine.core.common.asynctasks.AsyncTaskType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.NotImplementedException; @@ -22,8 +23,6 @@ @NonTransactiveCommandAttribute @InternalCommandAttribute public class RemoveMemoryVolumesCommand<T extends RemoveMemoryVolumesParameters> extends CommandBase<T> implements TaskHandlerCommand<T> { - /** fictive list of task IDs, used when we don't want to add tasks */ - private static final ArrayList<Guid> dummyTaskIdList = new ArrayList<>(); public RemoveMemoryVolumesCommand(T parameters) { super(parameters); @@ -35,13 +34,18 @@ @Override protected void executeCommand() { - HibernationVolumesRemover hibernationVolumesRemover = - new HibernationVolumesRemover( - getParameters().getMemoryVolumes(), + MemoryImageRemoverOnDataDomain memoryImageRemover = + new MemoryImageRemoverOnDataDomain( getParameters().getVmId(), this); - setSucceeded(hibernationVolumesRemover.remove()); + setSucceeded(memoryImageRemover.remove( + Collections.singleton(getParameters().getMemoryVolumes()))); + } + + @Override + protected AsyncTaskType getTaskType() { + return AsyncTaskType.deleteImage; } ////////////////////////////////// @@ -50,7 +54,8 @@ @Override public VdcActionType getActionType() { - return super.getActionType(); + return getParameters().getParentCommand() == VdcActionType.Unknown ? + super.getActionType() : getParameters().getParentCommand(); } /** @@ -58,7 +63,7 @@ */ @Override public Guid createTask(Guid taskId, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { - return Guid.Empty; + return super.createTask(taskId, asyncTaskCreationInfo, parentCommand); } /** @@ -70,7 +75,7 @@ VdcActionType parentCommand, VdcObjectType vdcObjectType, Guid... entityIds) { - return Guid.Empty; + return super.createTask(taskId, asyncTaskCreationInfo, parentCommand, vdcObjectType, entityIds); } /** @@ -78,7 +83,7 @@ */ @Override public ArrayList<Guid> getTaskIdList() { - return dummyTaskIdList; + return super.getTaskIdList(); } @Override @@ -91,7 +96,7 @@ */ @Override public Guid persistAsyncTaskPlaceHolder() { - return Guid.Empty; + return super.persistAsyncTaskPlaceHolder(getActionType()); } /** @@ -99,7 +104,7 @@ */ @Override public Guid persistAsyncTaskPlaceHolder(String taskKey) { - return Guid.Empty; + return super.persistAsyncTaskPlaceHolder(getActionType(), taskKey); } @Override diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveVmCommand.java index 6cccb55..11f1876 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveVmCommand.java @@ -10,7 +10,6 @@ import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.bll.job.ExecutionContext; import org.ovirt.engine.core.bll.job.ExecutionHandler; -import org.ovirt.engine.core.bll.memory.MemoryImageRemoverOnDataDomain; import org.ovirt.engine.core.bll.network.ExternalNetworkManager; import org.ovirt.engine.core.bll.quota.QuotaConsumptionParameter; import org.ovirt.engine.core.bll.quota.QuotaStorageConsumptionParameter; @@ -25,6 +24,7 @@ import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.RemoveAllVmImagesParameters; +import org.ovirt.engine.core.common.action.RemoveMemoryVolumesParameters; import org.ovirt.engine.core.common.action.RemoveVmParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; @@ -117,11 +117,35 @@ } } - new MemoryImageRemoverOnDataDomain(getVm(), this).remove(memoryStates); + removeMemoryVolumes(); return true; } + private void removeMemoryVolumes() { + for (String memoryState : memoryStates) { + VdcReturnValueBase retVal = getBackend().runInternalAction( + VdcActionType.RemoveMemoryVolumes, + buildRemoveMemoryVolumesParameters(memoryState, getVmId()), + ExecutionHandler.createDefaultContexForTasks(getExecutionContext())); + + if (!retVal.getSucceeded()) { + log.errorFormat("Failed to remove memory volumes whie removing vm {0} (volumes: {1})", + getVmId(), memoryState); + } + } + } + + private RemoveMemoryVolumesParameters buildRemoveMemoryVolumesParameters(String memoryState, Guid vmId) { + RemoveMemoryVolumesParameters parameters = + new RemoveMemoryVolumesParameters(memoryState, getVmId()); + parameters.setParentCommand(getActionType()); + parameters.setParentParameters(getParameters()); + parameters.setEntityInfo(getParameters().getEntityInfo()); + + return parameters; + } + @Override protected boolean canDoAction() { if (getVm() == null) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemover.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemover.java index 3750a91..54322b2 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemover.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemover.java @@ -60,13 +60,17 @@ if (isMemoryStateRemovable(memoryVolumes)) { return removeMemoryVolumes(memoryVolumes); } + return true; } - protected void removeMemoryVolumes(Set<String> memoryVolumes) { + protected boolean removeMemoryVolumes(Set<String> memoryVolumes) { + boolean result = true; for (String memoryVols : memoryVolumes) { - removeMemoryVolume(memoryVols); + result &= removeMemoryVolume(memoryVols); } + + return result; } private boolean removeMemoryVolumes(String memVols) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemoverOnDataDomain.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemoverOnDataDomain.java index ac48c3e..0a4ec61 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemoverOnDataDomain.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/memory/MemoryImageRemoverOnDataDomain.java @@ -4,7 +4,7 @@ import java.util.Set; import org.ovirt.engine.core.bll.tasks.TaskHandlerCommand; -import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.vdscommands.DeleteImageGroupVDSCommandParameters; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.DbFacade; @@ -13,15 +13,15 @@ public class MemoryImageRemoverOnDataDomain extends MemoryImageRemover { protected Boolean cachedPostZero; - private VM vm; + private Guid vmId; - public MemoryImageRemoverOnDataDomain(VM vm, TaskHandlerCommand<?> enclosingCommand) { - super(enclosingCommand); - this.vm = vm; + public MemoryImageRemoverOnDataDomain(Guid vmId, TaskHandlerCommand<?> enclosingCommand) { + super(enclosingCommand, false); + this.vmId = vmId; } - public void remove(Set<String> memoryStates) { - removeMemoryVolumes(memoryStates); + public boolean remove(Set<String> memoryStates) { + return removeMemoryVolumes(memoryStates); } @Override @@ -38,15 +38,22 @@ protected boolean isPostZero() { if (cachedPostZero == null) { - cachedPostZero = isDiskWithWipeAfterDeleteExist(getDiskDao().getAllForVm(vm.getId())); + cachedPostZero = isDiskWithWipeAfterDeleteExist(getDiskDao().getAllForVm(vmId)); } return cachedPostZero; } @Override protected boolean isMemoryStateRemovable(String memoryVolume) { - return !memoryVolume.isEmpty() && - getSnapshotDao().getNumOfSnapshotsByMemory(memoryVolume) == 0; + if (memoryVolume.isEmpty()) { + return false; + } + + // from RemoveVmCommand this command is called before the snapshot + // is removed from the DB (because it is transactive command) + return enclosingCommand.getParameters().getParentCommand() == VdcActionType.RemoveVm ? + getSnapshotDao().getNumOfSnapshotsByMemory(memoryVolume) == 0 + : getSnapshotDao().getNumOfSnapshotsByMemory(memoryVolume) == 1; } protected SnapshotDao getSnapshotDao() { -- To view, visit http://gerrit.ovirt.org/23222 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ib4b270ec0e1ab41cae34459dde9f9cf47b1b5bdf Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Arik Hadas <aha...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches