Greg Padgett has uploaded a new change for review. Change subject: WIP core: Live Merge recovery flow ......................................................................
WIP core: Live Merge recovery flow When a VM stops running during a live merge, check the status using a new reconcileVolumeChain vdsm verb. This verb will ensure the volume chain is correct and return the comprising images, which we can then use to converge the Live Merge flow while the VM is still down. Change-Id: Ie858c69412698e9a11a7f52ee88c3c078b3f2303 Bug-Url: https://bugzilla.redhat.com/1129898 Signed-off-by: Greg Padgett <gpadg...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeCommandCallback.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeStatusCommand.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/ReconcileVolumeChainVDSCommandParameters.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IIrsServer.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerConnector.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerWrapper.java A backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/ReconcileVolumeChainVDSCommand.java A backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/VolumeListReturnForXmlRpc.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcIIrsServer.java 10 files changed, 149 insertions(+), 13 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/50/31850/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeCommandCallback.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeCommandCallback.java index ee8cb9e..eb84a70 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeCommandCallback.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeCommandCallback.java @@ -5,6 +5,7 @@ import org.ovirt.engine.core.bll.tasks.CommandCoordinatorUtil; import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallBack; import org.ovirt.engine.core.common.action.MergeParameters; +import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmJob; import org.ovirt.engine.core.compat.CommandStatus; import org.ovirt.engine.core.compat.Guid; @@ -20,13 +21,20 @@ // If the VM Job exists, the command is still active boolean isRunning = false; MergeCommand<MergeParameters> command = getCommand(cmdId); + VMStatus vmStatus = DbFacade.getInstance().getVmDynamicDao().get(command.getParameters().getVmId()).getStatus(); List<VmJob> vmJobs = DbFacade.getInstance().getVmJobDao().getAllForVmDisk( command.getParameters().getVmId(), command.getParameters().getImageGroupId()); for (VmJob vmJob : vmJobs) { if (vmJob.getId().equals(command.getParameters().getVmJobId())) { - isRunning = true; - log.info("Waiting on merge command to complete"); + if (vmStatus == VMStatus.Down) { + DbFacade.getInstance().getVmJobDao().remove(vmJob.getId()); + log.infoFormat("VM {0} is down, Merge command {1} removed", + command.getParameters().getVmId(), vmJob.getId()); + } else { + log.info("Waiting on merge command to complete"); + isRunning = true; + } break; } } @@ -36,10 +44,10 @@ command.setSucceeded(true); command.setCommandStatus(CommandStatus.SUCCEEDED); command.persistCommand(command.getParameters().getParentCommand(), true); + log.infoFormat("Merge command has completed for images {0}..{1}", + command.getParameters().getBaseImage().getImageId(), + command.getParameters().getTopImage().getImageId()); } - log.infoFormat("Merge command has completed for images {0}..{1}", - command.getParameters().getBaseImage().getImageId(), - command.getParameters().getTopImage().getImageId()); } private MergeCommand<MergeParameters> getCommand(Guid cmdId) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeStatusCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeStatusCommand.java index d6c2c1d..1ea33d9 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeStatusCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MergeStatusCommand.java @@ -17,6 +17,9 @@ import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VmBlockJobType; import org.ovirt.engine.core.common.vdscommands.FullListVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.ReconcileVolumeChainVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.VDSCommandType; +import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.CommandStatus; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.utils.log.Log; @@ -39,16 +42,13 @@ @Override protected void executeCommand() { - // Our contract with vdsm merge states that if the VM is found down, we - // have to assume the merge failed. (It's okay if it really succeeded, - // we can retry the operation without any issues.) + Set<Guid> images; if (getVmDAO().get(getParameters().getVmId()).isDown()) { - log.error("Failed to live merge, VM is not running"); - setCommandStatus(CommandStatus.FAILED); - return; + log.error("VM is not running, proceeding with Live Merge recovery"); + images = getVolumeChainFromRecovery(); + } else { + images = getVolumeChain(); } - - Set<Guid> images = getVolumeChain(); if (images == null) { setCommandStatus(CommandStatus.FAILED); return; @@ -120,6 +120,24 @@ return images; } + private Set<Guid> getVolumeChainFromRecovery() { + ReconcileVolumeChainVDSCommandParameters parameters = + new ReconcileVolumeChainVDSCommandParameters( + getParameters().getStoragePoolId(), + getParameters().getStorageDomainId(), + getParameters().getImageGroupId(), + getParameters().getImageId() + ); + + VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.ReconcileVolumeChain, + parameters); + if (!vdsReturnValue.getSucceeded()) { + log.error("Unable to retrieve volume list during Live Merge recovery"); + return null; + } + return new HashSet<>((List<Guid>) vdsReturnValue.getReturnValue()); + } + /** * Returns the set of images which may be merged/removed in the live merge operation * on this disk. We don't know whether VDSM will choose a forward or backward merge diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/ReconcileVolumeChainVDSCommandParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/ReconcileVolumeChainVDSCommandParameters.java new file mode 100644 index 0000000..eb5b553 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/ReconcileVolumeChainVDSCommandParameters.java @@ -0,0 +1,16 @@ +package org.ovirt.engine.core.common.vdscommands; + +import org.ovirt.engine.core.compat.Guid; + +public class ReconcileVolumeChainVDSCommandParameters extends AllStorageAndImageIdVDSCommandParametersBase { + + private ReconcileVolumeChainVDSCommandParameters() { } + + public ReconcileVolumeChainVDSCommandParameters( + Guid storagePoolId, + Guid storageDomainId, + Guid imageGroupId, + Guid imageId) { + super(storagePoolId, storageDomainId, imageGroupId, imageId); + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java index 6a055cc..eb97bf5 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java @@ -65,6 +65,7 @@ CreateSnapshot("org.ovirt.engine.core.vdsbroker.irsbroker"), MergeSnapshots("org.ovirt.engine.core.vdsbroker.irsbroker"), Merge("org.ovirt.engine.core.vdsbroker.vdsbroker"), + ReconcileVolumeChain("org.ovirt.engine.core.vdsbroker.irsbroker"), IsoPrefix("org.ovirt.engine.core.vdsbroker.vdsbroker"), IsoDirectory("org.ovirt.engine.core.vdsbroker.irsbroker"), ResetIrs("org.ovirt.engine.core.vdsbroker.irsbroker"), diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IIrsServer.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IIrsServer.java index 31a0087..a09da95 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IIrsServer.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IIrsServer.java @@ -22,6 +22,9 @@ OneUuidReturnForXmlRpc mergeSnapshots(String sdUUID, String spUUID, String vmGUID, String imgGUID, String ancestorUUID, String successorUUID, String postZero); + VolumeListReturnForXmlRpc reconcileVolumeChain(String spUUID, String sdUUID, String imgGUID, + String leafVolUUID); + OneUuidReturnForXmlRpc deleteVolume(String sdUUID, String spUUID, String imgGUID, String[] volUUID, String postZero, String force); diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerConnector.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerConnector.java index bd219b4..1b7c709 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerConnector.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerConnector.java @@ -26,6 +26,9 @@ public Map<String, Object> mergeSnapshots(String sdUUID, String spUUID, String vmGUID, String imgGUID, String ancestorUUID, String successorUUID, String postZero); + public Map<String, Object> reconcileVolumeChain(String spUUID, String sdUUID, String imgGUID, + String leafVolUUID); + public Map<String, Object> deleteVolume(String sdUUID, String spUUID, String imgGUID, String[] volUUID, String postZero); diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerWrapper.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerWrapper.java index 0821819..7388e88 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerWrapper.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/IrsServerWrapper.java @@ -61,6 +61,15 @@ } @Override + public VolumeListReturnForXmlRpc reconcileVolumeChain(String spUUID, String sdUUID, String imgGUID, + String leafVolUUID) { + Map<String, Object> xmlRpcReturnValue = irsServer.reconcileVolumeChain(spUUID, sdUUID, imgGUID, + leafVolUUID); + VolumeListReturnForXmlRpc wrapper = new VolumeListReturnForXmlRpc(xmlRpcReturnValue); + return wrapper; + } + + @Override public OneUuidReturnForXmlRpc deleteVolume(String sdUUID, String spUUID, String imgGUID, String[] volUUID, String postZero, String force) { Map<String, Object> xmlRpcReturnValue = irsServer.deleteVolume(sdUUID, spUUID, imgGUID, volUUID, postZero, diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/ReconcileVolumeChainVDSCommand.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/ReconcileVolumeChainVDSCommand.java new file mode 100644 index 0000000..bc5a27a --- /dev/null +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/ReconcileVolumeChainVDSCommand.java @@ -0,0 +1,40 @@ +package org.ovirt.engine.core.vdsbroker.irsbroker; + +import java.util.ArrayList; + +import org.ovirt.engine.core.common.vdscommands.ReconcileVolumeChainVDSCommandParameters; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.vdsbroker.vdsbroker.StatusForXmlRpc; + +public class ReconcileVolumeChainVDSCommand<P extends ReconcileVolumeChainVDSCommandParameters> extends IrsBrokerCommand<P> { + protected VolumeListReturnForXmlRpc volumeListReturn; + + public ReconcileVolumeChainVDSCommand(P parameters) { + super(parameters); + } + + @Override + protected void executeIrsBrokerCommand() { + volumeListReturn = getIrsProxy().reconcileVolumeChain( + getParameters().getStoragePoolId().toString(), + getParameters().getStorageDomainId().toString(), + getParameters().getImageGroupId().toString(), + getParameters().getImageId().toString()); + proceedProxyReturnValue(); + ArrayList<Guid> tempRetValue = new ArrayList<Guid>(volumeListReturn.getVolumeList().length); + for (String id : volumeListReturn.getVolumeList()) { + tempRetValue.add(new Guid(id)); + } + setReturnValue(tempRetValue); + } + + @Override + protected Object getReturnValueFromBroker() { + return volumeListReturn; + } + + @Override + protected StatusForXmlRpc getReturnStatus() { + return volumeListReturn.mStatus; + } +} diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/VolumeListReturnForXmlRpc.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/VolumeListReturnForXmlRpc.java new file mode 100644 index 0000000..4d58682 --- /dev/null +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/VolumeListReturnForXmlRpc.java @@ -0,0 +1,24 @@ +package org.ovirt.engine.core.vdsbroker.irsbroker; + +import java.util.Map; + +public final class VolumeListReturnForXmlRpc extends StatusReturnForXmlRpc { + private static final String VOLUMES = "volumes"; + public String[] mVolumeList; + + @SuppressWarnings("unchecked") + public VolumeListReturnForXmlRpc(Map<String, Object> innerMap) { + super(innerMap); + Object[] tempObj = (Object[]) innerMap.get(VOLUMES); + if (tempObj != null) { + mVolumeList = new String[tempObj.length]; + for (int i = 0; i < tempObj.length; i++) { + mVolumeList[i] = (String) tempObj[i]; + } + } + } + + public String[] getVolumeList() { + return mVolumeList; + } +} diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcIIrsServer.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcIIrsServer.java index 179d7c8..ea85138 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcIIrsServer.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcIIrsServer.java @@ -16,6 +16,7 @@ import org.ovirt.engine.core.vdsbroker.irsbroker.UUIDListReturnForXmlRpc; import org.ovirt.engine.core.vdsbroker.vdsbroker.StatusOnlyReturnForXmlRpc; import org.ovirt.engine.core.vdsbroker.vdsbroker.StorageDomainListReturnForXmlRpc; +import org.ovirt.engine.core.vdsbroker.irsbroker.VolumeListReturnForXmlRpc; import org.ovirt.vdsm.jsonrpc.client.JsonRpcClient; import org.ovirt.vdsm.jsonrpc.client.JsonRpcRequest; import org.ovirt.vdsm.jsonrpc.client.RequestBuilder; @@ -159,6 +160,19 @@ } @Override + public VolumeListReturnForXmlRpc reconcileVolumeChain(String spUUID, String sdUUID, String imgGUID, + String leafVolUUID) { + JsonRpcRequest request = + new RequestBuilder("VM.reconcileVolumeChain").withParameter("storagepoolID", spUUID) + .withParameter("storagedomainID", sdUUID) + .withParameter("imageID", imgGUID) + .withParameter("leafVolID", leafVolUUID) + .build(); + Map<String, Object> response = new FutureMap(this.client, request); + return new VolumeListReturnForXmlRpc(response); + } + + @Override public OneUuidReturnForXmlRpc deleteVolume(String sdUUID, String spUUID, String imgGUID, -- To view, visit http://gerrit.ovirt.org/31850 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie858c69412698e9a11a7f52ee88c3c078b3f2303 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Greg Padgett <gpadg...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches