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

liguang lig.fnst at cn.fujitsu.com
Mon Oct 15 02:48:34 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 use had been discussed before,
http://www.redhat.com/archives/libvir-list/2011-December/msg00451.html

It did not handle more about complete situations
suggested by Daniel P. Berrange,
https://www.redhat.com/archives/libvir-list/2012-October/msg00407.html

Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
---
 src/libvirt_private.syms  |    1 +
 src/qemu/qemu_migration.c |   92 +++++++++++++++++++++++++++++++++++++++++++-
 src/util/util.c           |   17 ++++++++
 src/util/util.h           |    1 +
 4 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a8c81e7..a293184 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1202,6 +1202,7 @@ virArgvToString;
 virAsprintf;
 virBuildPathInternal;
 virDirCreate;
+virDirOfFile;
 virDoubleToStr;
 virEnumFromString;
 virEnumToString;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index db69a0a..ac3e1c3 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -70,6 +70,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 +78,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 +441,10 @@ 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:
@@ -1215,6 +1226,60 @@ qemuMigrationPrepareCleanup(struct qemud_driver *driver,
     qemuDomainObjDiscardAsyncJob(driver, vm);
 }
 
+static int qemuMigrationHandleDiskFiles(const char *dom_xml, int pin)
+{
+    xmlDocPtr doc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlNodePtr *disks = NULL;
+    virCommandPtr cmd = NULL;
+    int i, nr, ret = -1;
+    char *file_name[] = {}, *file_fmt[] = {};
+    char *driver_name, *tmp_dir;
+
+    if (!(doc = virXMLParseStringCtxt(dom_xml, _("(domain_definition)"), &ctxt)))
+        goto cleanup;
+
+    if ((nr = virXPathNodeSet("./devices/disk", ctxt, &disks)) <= 0)
+        goto cleanup;
+
+    for (i = 0; i < nr; i++) {
+        ctxt->node = disks[i];
+        driver_name = virXPathString("string(./driver/@name)", ctxt);
+        if (STRNEQ(driver_name, "qemu"))
+            continue;
+        file_fmt[i] = virXPathString("string(./driver/@type)", ctxt);
+        file_name[i] = virXPathString("string(./source/file)", ctxt);
+        if (virFileExists(file_name[i]) && !pin)
+            continue;
+        if ((tmp_dir = virDirOfFile(file_name[i])) == NULL)
+            continue;
+        if (!virFileExists(tmp_dir))
+            if (virFileMakePath(tmp_dir) < 0)
+                continue;
+        if (pin)
+            cmd = virCommandNewArgList("qemu-img", "create", "-f",
+                                       file_fmt[i], file_name[i], ~0UL, NULL);
+        else
+            cmd = virCommandNewArgList("rm", "-f", file_name[i], NULL);
+        if (virCommandRun(cmd, NULL) < 0) {
+            goto cleanup;
+            virReportSystemError(errno, "%s",
+                                 _("unable create disk images by qemu-img"));
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(doc);
+    VIR_FREE(disks);
+    virCommandFree(cmd);
+    VIR_FREE(driver_name);
+    VIR_FREE(tmp_dir);
+    return ret;
+}
+
 static int
 qemuMigrationPrepareAny(struct qemud_driver *driver,
                         virConnectPtr dconn,
@@ -1314,6 +1379,14 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
     origname = NULL;
 
     if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
+                                       QEMU_MIGRATION_COOKIE_COPYSTORAGE)))
+        goto cleanup;
+
+    if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)
+        if (qemuMigrationHandleDiskFiles(dom_xml, 1) < 0)
+            goto cleanup;
+
+    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
                                        QEMU_MIGRATION_COOKIE_LOCKSTATE)))
         goto cleanup;
 
@@ -1900,8 +1973,13 @@ qemuMigrationRun(struct qemud_driver *driver,
     if (flags & VIR_MIGRATE_NON_SHARED_DISK)
         migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
 
-    if (flags & VIR_MIGRATE_NON_SHARED_INC)
+    if (flags & VIR_MIGRATE_NON_SHARED_INC) {
         migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC;
+        if (qemuMigrationBakeCookie(mig, driver, vm,
+                                    cookieout, cookieoutlen,
+                                    QEMU_MIGRATION_COOKIE_COPYSTORAGE) < 0)
+            goto cleanup;
+    }
 
     /* connect to the destination qemu if needed */
     if (spec->destType == MIGRATION_DEST_CONNECT_HOST &&
@@ -2929,14 +3007,18 @@ 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;
+    char *dom_xml = NULL;
 
     VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
               "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
               driver, dconn, vm, NULLSTR(cookiein), cookieinlen,
               cookieout, cookieoutlen, flags, retcode);
 
+    if (!(dom_xml = qemuDomainFormatXML(driver, vm, VIR_DOMAIN_XML_SECURE, false)))
+        goto cleanup;
+
     if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
         goto cleanup;
 
@@ -3088,7 +3170,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(dom_xml, 0);
     if (qemuMigrationJobFinish(driver, vm) == 0) {
         vm = NULL;
     } else if (!vm->persistent && !virDomainObjIsActive(vm)) {
diff --git a/src/util/util.c b/src/util/util.c
index 348c388..1f51a77 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -3108,3 +3108,20 @@ virValidateWWN(const char *wwn) {
 
     return true;
 }
+
+char *virDirOfFile(const char *file)
+{
+    char *p, *tmp;
+
+    if (file == NULL)
+        return NULL;
+    if ((tmp = strdup(file)) == NULL)
+        return NULL;
+    if ((p = strrchr(file, '/')) == NULL)
+        return getcwd(tmp, strlen(file));
+    if (strlen(p) == 0)
+        return NULL;
+    tmp[strlen(file) - strlen(p)] = '\0';
+
+    return tmp;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 4316ab1..255b7b2 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -114,6 +114,7 @@ enum {
 };
 int virDirCreate(const char *path, mode_t mode, uid_t uid, gid_t gid,
                  unsigned int flags) ATTRIBUTE_RETURN_CHECK;
+char *virDirOfFile(const char *file) ATTRIBUTE_RETURN_CHECK;
 int virFileMakePath(const char *path) ATTRIBUTE_RETURN_CHECK;
 int virFileMakePathWithMode(const char *path,
                             mode_t mode) ATTRIBUTE_RETURN_CHECK;
-- 
1.7.2.5




More information about the libvir-list mailing list