[libvirt PATCH 3/6] Add local migration support in QEMU Migration framework

Daniel P. Berrangé berrange at redhat.com
Mon Feb 3 12:43:30 UTC 2020


From: Shaju Abraham <shaju.abraham at nutanix.com>

The local migration is selected by the option 'local' in virsh migrate
command. Once 'local' is specified in the command line, the migration
framework needs to follow the local migration path. Use the passed flag
to selectively bypass the checks that otherwise prevents the local
migration in QEMU migration framework.

Signed-off-by: Shaju Abraham <shaju.abraham at nutanix.com>
---
 src/qemu/qemu_migration.c        |  46 +++++++-----
 src/qemu/qemu_migration.h        |   1 +
 src/qemu/qemu_migration_cookie.c | 121 ++++++++++++++++---------------
 src/qemu/qemu_migration_cookie.h |   2 +
 src/qemu/qemu_process.c          |   3 +-
 src/qemu/qemu_process.h          |   2 +
 6 files changed, 98 insertions(+), 77 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index d7814208a2..d22daeac9c 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2334,15 +2334,30 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver,
     bool tunnel = !!st;
     char *xmlout = NULL;
     unsigned int cookieFlags;
-    unsigned int startFlags;
+    unsigned int startFlags = 0;
+    unsigned int eatCookieFlags;
     qemuProcessIncomingDefPtr incoming = NULL;
     bool taint_hook = false;
     bool stopProcess = false;
     bool relabel = false;
     int rv;
     char *tlsAlias = NULL;
+    unsigned long list_flags = VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
+                               VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE;
+    eatCookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE |
+                     QEMU_MIGRATION_COOKIE_NBD |
+                     QEMU_MIGRATION_COOKIE_MEMORY_HOTPLUG |
+                     QEMU_MIGRATION_COOKIE_CPU_HOTPLUG |
+                     QEMU_MIGRATION_COOKIE_CPU |
+                     QEMU_MIGRATION_COOKIE_ALLOW_REBOOT |
+                     QEMU_MIGRATION_COOKIE_CAPS;
 
     virNWFilterReadLockFilterUpdates();
+    if (flags & VIR_MIGRATE_LOCAL) {
+        list_flags |= VIR_DOMAIN_OBJ_LIST_ADD_LIVE_LOCAL;
+        eatCookieFlags |= QEMU_MIGRATION_COOKIE_LOCAL_MIGRATION;
+        startFlags |= VIR_QEMU_PROCESS_START_LOCAL_MIG;
+    }
 
     if (flags & VIR_MIGRATE_OFFLINE) {
         if (flags & (VIR_MIGRATE_NON_SHARED_DISK |
@@ -2439,19 +2454,12 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver,
      * point in having the domain in the list at that point. */
     if (!(mig = qemuMigrationEatCookie(driver, *def, origname, NULL,
                                        cookiein, cookieinlen,
-                                       QEMU_MIGRATION_COOKIE_LOCKSTATE |
-                                       QEMU_MIGRATION_COOKIE_NBD |
-                                       QEMU_MIGRATION_COOKIE_MEMORY_HOTPLUG |
-                                       QEMU_MIGRATION_COOKIE_CPU_HOTPLUG |
-                                       QEMU_MIGRATION_COOKIE_CPU |
-                                       QEMU_MIGRATION_COOKIE_ALLOW_REBOOT |
-                                       QEMU_MIGRATION_COOKIE_CAPS)))
+                                       eatCookieFlags)))
         goto cleanup;
 
     if (!(vm = virDomainObjListAdd(driver->domains, *def,
                                    driver->xmlopt,
-                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
-                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
+                                   list_flags,
                                    NULL)))
         goto cleanup;
     *def = NULL;
@@ -2494,9 +2502,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver,
                              _("cannot create pipe for tunnelled migration"));
         goto stopjob;
     }
-
-    startFlags = VIR_QEMU_PROCESS_START_AUTODESTROY;
-
+    startFlags |= VIR_QEMU_PROCESS_START_AUTODESTROY;
     if (qemuProcessInit(driver, vm, mig->cpu, QEMU_ASYNC_JOB_MIGRATION_IN,
                         true, startFlags) < 0)
         goto stopjob;
@@ -2938,6 +2944,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver,
     qemuMigrationCookiePtr mig;
     virObjectEventPtr event;
     int rv = -1;
+    unsigned int cookieFlags = 0;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     qemuDomainObjPrivatePtr priv = vm->privateData;
     qemuDomainJobInfoPtr jobInfo = NULL;
@@ -2948,15 +2955,16 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver,
               flags, retcode);
 
     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
-
+    cookieFlags = QEMU_MIGRATION_COOKIE_STATS;
+    if (flags & VIR_MIGRATE_LOCAL)
+        cookieFlags |= QEMU_MIGRATION_COOKIE_LOCAL_MIGRATION;
     qemuMigrationJobSetPhase(driver, vm,
                              retcode == 0
                              ? QEMU_MIGRATION_PHASE_CONFIRM3
                              : QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED);
 
     if (!(mig = qemuMigrationEatCookie(driver, vm->def, priv->origname, priv,
-                                       cookiein, cookieinlen,
-                                       QEMU_MIGRATION_COOKIE_STATS)))
+                                       cookiein, cookieinlen, cookieFlags)))
         goto cleanup;
 
     if (retcode == 0)
@@ -3420,7 +3428,8 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver,
               cookieout, cookieoutlen, flags, resource,
               spec, spec->destType, spec->fwdType, dconn,
               NULLSTR(graphicsuri), nmigrate_disks, migrate_disks);
-
+    if (flags & VIR_MIGRATE_LOCAL)
+        cookieFlags |= QEMU_MIGRATION_COOKIE_LOCAL_MIGRATION;
     if (flags & VIR_MIGRATE_NON_SHARED_DISK) {
         migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
         cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
@@ -4955,6 +4964,9 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver,
      * even though VIR_MIGRATE_PERSIST_DEST was not used. */
     cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
 
+    if (flags & VIR_MIGRATE_LOCAL)
+        cookie_flags |= QEMU_MIGRATION_COOKIE_LOCAL_MIGRATION;
+
     if (!(mig = qemuMigrationEatCookie(driver, vm->def, priv->origname, priv,
                                        cookiein, cookieinlen, cookie_flags)))
         goto endjob;
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index b6f88d3fd9..2cb4bb9023 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -59,6 +59,7 @@
      VIR_MIGRATE_POSTCOPY | \
      VIR_MIGRATE_TLS | \
      VIR_MIGRATE_PARALLEL | \
+     VIR_MIGRATE_LOCAL  |\
      0)
 
 /* All supported migration parameters and their types. */
diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c
index 299bf17c9e..18544dbaac 100644
--- a/src/qemu/qemu_migration_cookie.c
+++ b/src/qemu/qemu_migration_cookie.c
@@ -51,6 +51,7 @@ VIR_ENUM_IMPL(qemuMigrationCookieFlag,
               "cpu",
               "allowReboot",
               "capabilities",
+              "local-migration",
 );
 
 
@@ -1199,69 +1200,71 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
 
     /* We don't store the uuid, name, hostname, or hostuuid
      * values. We just compare them to local data to do some
-     * sanity checking on migration operation
+     * sanity checking on migration operation. In case of Local
+     * Migration bypass the checks. We know that we are migrating
+     * to the same host and the name and UUID will be existing in
+     * the host.
      */
 
     /* Extract domain name */
-    if (!(tmp = virXPathString("string(./name[1])", ctxt))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("missing name element in migration data"));
-        goto error;
-    }
-    if (STRNEQ(tmp, mig->name)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Incoming cookie data had unexpected name %s vs %s"),
-                       tmp, mig->name);
-        goto error;
-    }
-    VIR_FREE(tmp);
-
-    /* Extract domain uuid */
-    tmp = virXPathString("string(./uuid[1])", ctxt);
-    if (!tmp) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("missing uuid element in migration data"));
-        goto error;
-    }
-    virUUIDFormat(mig->uuid, uuidstr);
-    if (STRNEQ(tmp, uuidstr)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Incoming cookie data had unexpected UUID %s vs %s"),
-                       tmp, uuidstr);
-        goto error;
-    }
-    VIR_FREE(tmp);
-
-    /* Check & forbid "localhost" migration */
-    if (!(mig->remoteHostname = virXPathString("string(./hostname[1])", ctxt))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("missing hostname element in migration data"));
-        goto error;
-    }
-    if (STREQ(mig->remoteHostname, mig->localHostname)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Attempt to migrate guest to the same host %s"),
-                       mig->remoteHostname);
-        goto error;
-    }
-
-    if (!(tmp = virXPathString("string(./hostuuid[1])", ctxt))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("missing hostuuid element in migration data"));
-        goto error;
-    }
-    if (virUUIDParse(tmp, mig->remoteHostuuid) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("malformed hostuuid element in migration data"));
-        goto error;
-    }
-    if (memcmp(mig->remoteHostuuid, mig->localHostuuid, VIR_UUID_BUFLEN) == 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Attempt to migrate guest to the same host %s"),
-                       tmp);
-        goto error;
+    if (!(flags & QEMU_MIGRATION_COOKIE_LOCAL_MIGRATION)) {
+        if (!(tmp = virXPathString("string(./name[1])", ctxt))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("missing name element in migration data"));
+            goto error;
+        }
+        if (STRNEQ(tmp, mig->name)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Incoming cookie data had unexpected name %s vs %s"),
+                           tmp, mig->name);
+            goto error;
+        }
+        VIR_FREE(tmp);
+        /* Extract domain uuid */
+        tmp = virXPathString("string(./uuid[1])", ctxt);
+        if (!tmp) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("missing uuid element in migration data"));
+            goto error;
+        }
+        virUUIDFormat(mig->uuid, uuidstr);
+        if (STRNEQ(tmp, uuidstr)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Incoming cookie data had unexpected UUID %s vs %s"),
+                           tmp, uuidstr);
+            goto error;
+        }
+        VIR_FREE(tmp);
+        /* Check & forbid "localhost" migration */
+        if (!(mig->remoteHostname = virXPathString("string(./hostname[1])", ctxt))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("missing hostname element in migration data"));
+            goto error;
+        }
+        if (STREQ(mig->remoteHostname, mig->localHostname)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Attempt to migrate guest to the same host %s"),
+                           mig->remoteHostname);
+            goto error;
+        }
+        if (!(tmp = virXPathString("string(./hostuuid[1])", ctxt))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("missing hostuuid element in migration data"));
+            goto error;
+        }
+        if (virUUIDParse(tmp, mig->remoteHostuuid) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("malformed hostuuid element in migration data"));
+            goto error;
+        }
+        if (memcmp(mig->remoteHostuuid, mig->localHostuuid, VIR_UUID_BUFLEN) == 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Attempt to migrate guest to the same host %s"),
+                           tmp);
+            goto error;
+        }
+        VIR_FREE(tmp);
     }
-    VIR_FREE(tmp);
 
     /* Check to ensure all mandatory features from XML are also
      * present in 'flags' */
diff --git a/src/qemu/qemu_migration_cookie.h b/src/qemu/qemu_migration_cookie.h
index 20e1ed60ca..7574672fd6 100644
--- a/src/qemu/qemu_migration_cookie.h
+++ b/src/qemu/qemu_migration_cookie.h
@@ -33,6 +33,7 @@ typedef enum {
     QEMU_MIGRATION_COOKIE_FLAG_CPU,
     QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT,
     QEMU_MIGRATION_COOKIE_FLAG_CAPS,
+    QEMU_MIGRATION_COOKIE_FLAG_LOCAL_MIGRATION,
 
     QEMU_MIGRATION_COOKIE_FLAG_LAST
 } qemuMigrationCookieFlags;
@@ -51,6 +52,7 @@ typedef enum {
     QEMU_MIGRATION_COOKIE_CPU = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU),
     QEMU_MIGRATION_COOKIE_ALLOW_REBOOT = (1 << QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT),
     QEMU_MIGRATION_COOKIE_CAPS = (1 << QEMU_MIGRATION_COOKIE_FLAG_CAPS),
+    QEMU_MIGRATION_COOKIE_LOCAL_MIGRATION = (1 << QEMU_MIGRATION_COOKIE_FLAG_LOCAL_MIGRATION),
 } qemuMigrationCookieFeatures;
 
 typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 57a60c568a..df0884a233 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6679,7 +6679,8 @@ qemuProcessLaunch(virConnectPtr conn,
                   VIR_QEMU_PROCESS_START_PAUSED |
                   VIR_QEMU_PROCESS_START_AUTODESTROY |
                   VIR_QEMU_PROCESS_START_NEW |
-                  VIR_QEMU_PROCESS_START_GEN_VMID, -1);
+                  VIR_QEMU_PROCESS_START_GEN_VMID |
+                  VIR_QEMU_PROCESS_START_LOCAL_MIG, -1);
 
     cfg = virQEMUDriverGetConfig(driver);
 
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 9af9f967fd..7aa67158b0 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -81,6 +81,8 @@ typedef enum {
     VIR_QEMU_PROCESS_START_GEN_VMID     = 1 << 5, /* Generate a new VMID */
     VIR_QEMU_PROCESS_START_STANDALONE   = 1 << 6, /* Require CLI args to be usable standalone,
                                                      ie no FD passing and the like */
+    VIR_QEMU_PROCESS_START_LOCAL_MIG    = 1 << 7, /* internal, new VM is starting
+                                                     for Local Migration */
 } qemuProcessStartFlags;
 
 int qemuProcessStart(virConnectPtr conn,
-- 
2.24.1




More information about the libvir-list mailing list