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

Reply via email to