render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
7a3408
From 9ac80cb260482543d02c9d8fd79162c05d684a74 Mon Sep 17 00:00:00 2001
7a3408
Message-Id: <9ac80cb260482543d02c9d8fd79162c05d684a74@dist-git>
7a3408
From: Jiri Denemark <jdenemar@redhat.com>
7a3408
Date: Thu, 2 Jul 2015 21:46:56 +0200
7a3408
Subject: [PATCH] qemu: Use error from Finish instead of "unexpectedly failed"
7a3408
7a3408
When QEMU exits on destination during migration, the source reports
7a3408
either success (if the failure happened at the very end) or unhelpful
7a3408
"unexpectedly failed" error message. However, the Finish API called on
7a3408
the destination may report a real error so let's use it instead of the
7a3408
generic one.
7a3408
7a3408
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
7a3408
(cherry picked from commit 2e7cea24355328102c40dd127329ddf47d55a3e2)
7a3408
7a3408
https://bugzilla.redhat.com/show_bug.cgi?id=1090093
7a3408
7a3408
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
7a3408
---
7a3408
 src/libvirt-domain.c      | 30 ++++++++++++++++++++++++++++--
7a3408
 src/qemu/qemu_migration.c | 39 +++++++++++++++++++++++++++++++++++++--
7a3408
 2 files changed, 65 insertions(+), 4 deletions(-)
7a3408
7a3408
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
7a3408
index 909c264..837933f 100644
7a3408
--- a/src/libvirt-domain.c
7a3408
+++ b/src/libvirt-domain.c
7a3408
@@ -3175,8 +3175,34 @@ virDomainMigrateVersion3Full(virDomainPtr domain,
7a3408
             (dconn, dname, cookiein, cookieinlen, &cookieout, &cookieoutlen,
7a3408
              NULL, uri, destflags, cancelled);
7a3408
     }
7a3408
-    if (cancelled && ddomain)
7a3408
-        VIR_ERROR(_("finish step ignored that migration was cancelled"));
7a3408
+
7a3408
+    if (cancelled) {
7a3408
+        if (ddomain) {
7a3408
+            VIR_ERROR(_("finish step ignored that migration was cancelled"));
7a3408
+        } else {
7a3408
+            /* If Finish reported a useful error, use it instead of the
7a3408
+             * original "migration unexpectedly failed" error.
7a3408
+             *
7a3408
+             * This is ugly but we can't do better with the APIs we have. We
7a3408
+             * only replace the error if Finish was called with cancelled == 1
7a3408
+             * and reported a real error (old libvirt would report an error
7a3408
+             * from RPC instead of MIGRATE_FINISH_OK), which only happens when
7a3408
+             * the domain died on destination. To further reduce a possibility
7a3408
+             * of false positives we also check that Perform returned
7a3408
+             * VIR_ERR_OPERATION_FAILED.
7a3408
+             */
7a3408
+            if (orig_err &&
7a3408
+                orig_err->domain == VIR_FROM_QEMU &&
7a3408
+                orig_err->code == VIR_ERR_OPERATION_FAILED) {
7a3408
+                virErrorPtr err = virGetLastError();
7a3408
+                if (err->domain == VIR_FROM_QEMU &&
7a3408
+                    err->code != VIR_ERR_MIGRATE_FINISH_OK) {
7a3408
+                    virFreeError(orig_err);
7a3408
+                    orig_err = NULL;
7a3408
+                }
7a3408
+            }
7a3408
+        }
7a3408
+    }
7a3408
 
7a3408
     /* If ddomain is NULL, then we were unable to start
7a3408
      * the guest on the target, and must restart on the
7a3408
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
7a3408
index a9cbada..d789110 100644
7a3408
--- a/src/qemu/qemu_migration.c
7a3408
+++ b/src/qemu/qemu_migration.c
7a3408
@@ -4982,8 +4982,34 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
7a3408
              dconnuri, uri, destflags, cancelled);
7a3408
         qemuDomainObjExitRemote(vm);
7a3408
     }
7a3408
-    if (cancelled && ddomain)
7a3408
-        VIR_ERROR(_("finish step ignored that migration was cancelled"));
7a3408
+
7a3408
+    if (cancelled) {
7a3408
+        if (ddomain) {
7a3408
+            VIR_ERROR(_("finish step ignored that migration was cancelled"));
7a3408
+        } else {
7a3408
+            /* If Finish reported a useful error, use it instead of the
7a3408
+             * original "migration unexpectedly failed" error.
7a3408
+             *
7a3408
+             * This is ugly but we can't do better with the APIs we have. We
7a3408
+             * only replace the error if Finish was called with cancelled == 1
7a3408
+             * and reported a real error (old libvirt would report an error
7a3408
+             * from RPC instead of MIGRATE_FINISH_OK), which only happens when
7a3408
+             * the domain died on destination. To further reduce a possibility
7a3408
+             * of false positives we also check that Perform returned
7a3408
+             * VIR_ERR_OPERATION_FAILED.
7a3408
+             */
7a3408
+            if (orig_err &&
7a3408
+                orig_err->domain == VIR_FROM_QEMU &&
7a3408
+                orig_err->code == VIR_ERR_OPERATION_FAILED) {
7a3408
+                virErrorPtr err = virGetLastError();
7a3408
+                if (err->domain == VIR_FROM_QEMU &&
7a3408
+                    err->code != VIR_ERR_MIGRATE_FINISH_OK) {
7a3408
+                    virFreeError(orig_err);
7a3408
+                    orig_err = NULL;
7a3408
+                }
7a3408
+            }
7a3408
+        }
7a3408
+    }
7a3408
 
7a3408
     /* If ddomain is NULL, then we were unable to start
7a3408
      * the guest on the target, and must restart on the
7a3408
@@ -5719,6 +5745,15 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
7a3408
         /* Guest is successfully running, so cancel previous auto destroy */
7a3408
         qemuProcessAutoDestroyRemove(driver, vm);
7a3408
     } else if (!(flags & VIR_MIGRATE_OFFLINE)) {
7a3408
+        qemuDomainJobInfo info;
7a3408
+
7a3408
+        /* Check for a possible error on the monitor in case Finish was called
7a3408
+         * earlier than monitor EOF handler got a chance to process the error
7a3408
+         */
7a3408
+        qemuMigrationFetchJobStatus(driver, vm,
7a3408
+                                    QEMU_ASYNC_JOB_MIGRATION_IN,
7a3408
+                                    &info;;
7a3408
+
7a3408
         qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
7a3408
                         VIR_QEMU_PROCESS_STOP_MIGRATED);
7a3408
         virDomainAuditStop(vm, "failed");
7a3408
-- 
7a3408
2.4.5
7a3408