[libvirt] [PATCH v2] helper of copy-storage-* features

liguang lig.fnst at cn.fujitsu.com
Tue Oct 30 01:48:10 UTC 2012


help to create disk images copy-storage-* required,
try to do non-shared migration without bothering to
create disk images at target by hand.

consider this situation:
1. non-shared migration
   virsh migrate --copy-storage-all ...
2. migration fails
3. create disk images required
   qemu-img create ...
4  migration run smoothly
so, try do remove step 2, 3, 4

this kind of usage had been discussed before,
http://www.redhat.com/archives/libvir-list/2011-December/msg00451.html

maybe there're some flaws:
- It did not handle more about complete situations
  suggested by Daniel P. Berrange,
  https://www.redhat.com/archives/libvir-list/2012-October/msg00407.html
  but may try to take care of them later.
  so, now only normal disk image files be handled.
- for creation of disk images, size was setting as 0xffffffff boldly,
  hope it can consolidate qemu, haven't constructed a comfortable
  idea to solve it.

v2:
  1. handle disk encrytion case
  2. check kvm-img & qemu-img
  3. set disk image size to 0xfffffffK bytes blindly

Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
---
 src/qemu/qemu_migration.c |  112 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index db69a0a..55eb98e 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -49,6 +49,7 @@
 #include "storage_file.h"
 #include "viruri.h"
 #include "hooks.h"
+#include "dirname.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -70,6 +71,7 @@ enum qemuMigrationCookieFlags {
     QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
     QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
     QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
+    QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE,
 
     QEMU_MIGRATION_COOKIE_FLAG_LAST
 };
@@ -77,12 +79,13 @@ enum qemuMigrationCookieFlags {
 VIR_ENUM_DECL(qemuMigrationCookieFlag);
 VIR_ENUM_IMPL(qemuMigrationCookieFlag,
               QEMU_MIGRATION_COOKIE_FLAG_LAST,
-              "graphics", "lockstate", "persistent");
+              "graphics", "lockstate", "persistent", "copystorage");
 
 enum qemuMigrationCookieFeatures {
     QEMU_MIGRATION_COOKIE_GRAPHICS  = (1 << QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS),
     QEMU_MIGRATION_COOKIE_LOCKSTATE = (1 << QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE),
     QEMU_MIGRATION_COOKIE_PERSISTENT = (1 << QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT),
+    QEMU_MIGRATION_COOKIE_COPYSTORAGE = (1 << QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE),
 };
 
 typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@@ -439,6 +442,9 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
         virBufferAdjustIndent(buf, -2);
     }
 
+    if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)
+        virBufferAsprintf(buf, "  <copystorage/>\n");
+
     virBufferAddLit(buf, "</qemu-migration>\n");
     return 0;
 }
@@ -662,6 +668,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
         VIR_FREE(nodes);
     }
 
+    if ((flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)) {
+        if (virXPathBoolean("count(./copystorage) > 0", ctxt))
+            mig->flags |= QEMU_MIGRATION_COOKIE_COPYSTORAGE;
+    }
+
     return 0;
 
 error:
@@ -721,6 +732,9 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
         qemuMigrationCookieAddPersistent(mig, dom) < 0)
         return -1;
 
+    if (flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)
+        mig->flags |= QEMU_MIGRATION_COOKIE_COPYSTORAGE;
+
     if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
         return -1;
 
@@ -1168,6 +1182,14 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
                                 QEMU_MIGRATION_COOKIE_LOCKSTATE) < 0)
         goto cleanup;
 
+    if (flags & (VIR_MIGRATE_NON_SHARED_DISK |
+                         VIR_MIGRATE_NON_SHARED_INC)) {
+        if (qemuMigrationBakeCookie(mig, driver, vm,
+                                    cookieout, cookieoutlen,
+                                    QEMU_MIGRATION_COOKIE_COPYSTORAGE) < 0)
+            goto cleanup;
+    }
+
     if (xmlin) {
         if (!(def = virDomainDefParseString(driver->caps, xmlin,
                                             QEMU_EXPECTED_VIRT_TYPES,
@@ -1215,6 +1237,79 @@ qemuMigrationPrepareCleanup(struct qemud_driver *driver,
     qemuDomainObjDiscardAsyncJob(driver, vm);
 }
 
+/*
+  if gen_del is 1, find out disk images migration required,
+  so try to generate them at target,
+  if gen_del is 0, delete disk images generated before.
+*/
+static int qemuMigrationHandleDiskFiles(virDomainDefPtr def, int gen_del)
+{
+    char *tmp_dir = NULL, *outbuf = NULL;
+    char *size = _("0xffffffffK"), *img_tool;
+    virCommandPtr cmd = NULL;
+    int i, ret = -1;
+
+    if (!def->ndisks)
+        return 0;
+
+    img_tool = virFindFileInPath("kvm-img");
+    if (!img_tool)
+        img_tool = virFindFileInPath("qemu-img");
+    if (!img_tool) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("unable to find kvm-img or qemu-img"));
+        return -1;
+    }
+
+    for (i = 0; i < def->ndisks; i++) {
+        if (STRNEQ(def->disks[i]->driverName, "qemu"))
+            continue;
+        if (def->disks[i]->src == NULL)
+            continue;
+        if (def->disks[i]->driverType == NULL)
+            continue;
+        if (virFileExists(def->disks[i]->src) && gen_del)
+            continue;
+        if (!gen_del && !virFileExists(def->disks[i]->src))
+            continue;
+        if ((tmp_dir = mdir_name(def->disks[i]->src)) == NULL)
+            continue;
+        if (!virFileExists(tmp_dir))
+            if (virFileMakePath(tmp_dir) < 0)
+                continue;
+        if (gen_del) {
+            cmd = virCommandNewArgList(img_tool, "create", "-f",
+                                       def->disks[i]->driverType, def->disks[i]->src,
+                                       size, NULL);
+            if (def->disks[i]->encryption)
+                virCommandAddArgList(cmd, "-o", "encryption=on", NULL);
+            virCommandSetOutputBuffer(cmd, &outbuf);
+            if (virCommandRun(cmd, NULL) < 0) {
+                virReportSystemError(errno, "%s", outbuf);
+                goto cleanup;
+            }
+        } else {
+            if (unlink(def->disks[i]->src) < 0) {
+                virReportError(errno, "%s", _("fail to unlink disk image file"));
+                goto cleanup;
+            }
+        }
+        virCommandFree(cmd);
+        VIR_FREE(tmp_dir);
+        VIR_FREE(outbuf);
+    }
+
+    ret = 0;
+
+cleanup:
+    if (ret < 0) {
+        virCommandFree(cmd);
+        VIR_FREE(tmp_dir);
+        VIR_FREE(outbuf);
+    }
+    return ret;
+}
+
 static int
 qemuMigrationPrepareAny(struct qemud_driver *driver,
                         virConnectPtr dconn,
@@ -1308,6 +1403,15 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
         /* virDomainAssignDef already set the error */
         goto cleanup;
     }
+
+    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
+                                       QEMU_MIGRATION_COOKIE_COPYSTORAGE)))
+        goto cleanup;
+
+    if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)
+        if (qemuMigrationHandleDiskFiles(def, 1) < 0)
+            goto cleanup;
+
     def = NULL;
     priv = vm->privateData;
     priv->origname = origname;
@@ -2929,7 +3033,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
     int newVM = 1;
     qemuMigrationCookiePtr mig = NULL;
     virErrorPtr orig_err = NULL;
-    int cookie_flags = 0;
+    int cookie_flags = 0, migration_status = 0;
     qemuDomainObjPrivatePtr priv = vm->privateData;
 
     VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
@@ -3088,7 +3192,11 @@ qemuMigrationFinish(struct qemud_driver *driver,
     if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
         VIR_WARN("Unable to encode migration cookie");
 
+    migration_status = 1;
+
 endjob:
+    if (!migration_status)
+        qemuMigrationHandleDiskFiles(vm->def, 0);
     if (qemuMigrationJobFinish(driver, vm) == 0) {
         vm = NULL;
     } else if (!vm->persistent && !virDomainObjIsActive(vm)) {
-- 
1.7.1




More information about the libvir-list mailing list