[libvirt] [PATCH v1 02/11] Introduce NBD migration cookie

Michal Privoznik mprivozn at redhat.com
Tue Nov 27 18:49:56 UTC 2012


This migration cookie is meant for two purposes. The first is to be sent
in begin phase from source to destination to let it know we support new
implementation of VIR_MIGRATE_NON_SHARED_{DISK,INC} so destination can
start NBD server. Then, the second purpose is, destination can let us
know, on which port is NBD server running.
---
 src/qemu/qemu_migration.c |  108 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 97 insertions(+), 11 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index d52ec59..cd59eda 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -72,6 +72,7 @@ enum qemuMigrationCookieFlags {
     QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
     QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
     QEMU_MIGRATION_COOKIE_FLAG_NETWORK,
+    QEMU_MIGRATION_COOKIE_FLAG_NBD,
 
     QEMU_MIGRATION_COOKIE_FLAG_LAST
 };
@@ -79,13 +80,14 @@ enum qemuMigrationCookieFlags {
 VIR_ENUM_DECL(qemuMigrationCookieFlag);
 VIR_ENUM_IMPL(qemuMigrationCookieFlag,
               QEMU_MIGRATION_COOKIE_FLAG_LAST,
-              "graphics", "lockstate", "persistent", "network");
+              "graphics", "lockstate", "persistent", "network", "nbd");
 
 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_NETWORK = (1 << QEMU_MIGRATION_COOKIE_FLAG_NETWORK),
+    QEMU_MIGRATION_COOKIE_NBD = (1 << QEMU_MIGRATION_COOKIE_FLAG_NBD),
 };
 
 typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@@ -119,6 +121,17 @@ struct _qemuMigrationCookieNetwork {
     qemuMigrationCookieNetDataPtr net;
 };
 
+typedef struct _qemuMigrationCookieNBD qemuMigrationCookieNBD;
+typedef qemuMigrationCookieNBD *qemuMigrationCookieNBDPtr;
+struct _qemuMigrationCookieNBD {
+    int port; /* on which port does NBD server listen for incoming data.
+                 Zero value has special meaning - it is there just to let
+                 destination know we (the source) do support NBD.
+                 Negative one is meant to be sent when translating from
+                 perform to finish phase to let destination know it's
+                 safe to stop NBD server.*/
+};
+
 typedef struct _qemuMigrationCookie qemuMigrationCookie;
 typedef qemuMigrationCookie *qemuMigrationCookiePtr;
 struct _qemuMigrationCookie {
@@ -147,6 +160,9 @@ struct _qemuMigrationCookie {
 
     /* If (flags & QEMU_MIGRATION_COOKIE_NETWORK) */
     qemuMigrationCookieNetworkPtr network;
+
+    /* If (flags & QEMU_MIGRATION_COOKIE_NBD) */
+    qemuMigrationCookieNBDPtr nbd;
 };
 
 static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
@@ -192,6 +208,7 @@ static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
     VIR_FREE(mig->name);
     VIR_FREE(mig->lockState);
     VIR_FREE(mig->lockDriver);
+    VIR_FREE(mig->nbd);
     VIR_FREE(mig);
 }
 
@@ -492,6 +509,24 @@ qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
 }
 
 
+static int
+qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig,
+                          int nbdPort)
+{
+    /* It is not a bug if there already is a NBD data */
+    if (!mig->nbd &&
+        VIR_ALLOC(mig->nbd) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    mig->nbd->port = nbdPort;
+    mig->flags |= QEMU_MIGRATION_COOKIE_NBD;
+
+    return 0;
+}
+
+
 static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
                                                  qemuMigrationCookieGraphicsPtr grap)
 {
@@ -594,6 +629,13 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
     if ((mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) && mig->network)
         qemuMigrationCookieNetworkXMLFormat(buf, mig->network);
 
+    if ((mig->flags & QEMU_MIGRATION_COOKIE_NBD) && mig->nbd) {
+        virBufferAddLit(buf, "  <nbd");
+        if (mig->nbd->port)
+            virBufferAsprintf(buf, " port='%d'", mig->nbd->port);
+        virBufferAddLit(buf, "/>\n");
+    }
+
     virBufferAddLit(buf, "</qemu-migration>\n");
     return 0;
 }
@@ -821,6 +863,12 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
             goto error;
         }
 
+        /* nbd is optional */
+        if (val == QEMU_MIGRATION_COOKIE_FLAG_NBD) {
+            VIR_FREE(str);
+            continue;
+        }
+
         if ((flags & (1 << val)) == 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Unsupported migration cookie feature %s"),
@@ -873,6 +921,25 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
         (!(mig->network = qemuMigrationCookieNetworkXMLParse(ctxt))))
         goto error;
 
+    if (flags & QEMU_MIGRATION_COOKIE_NBD &&
+        virXPathBoolean("count(./nbd) > 0", ctxt)) {
+        char *port;
+
+        if (VIR_ALLOC(mig->nbd) < 0) {
+            virReportOOMError();
+            goto error;
+        }
+
+        port = virXPathString("string(./nbd/@port)", ctxt);
+        if (port &&
+            virStrToLong_i(port, NULL, 10, &mig->nbd->port) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Malformed nbd port '%s'"),
+                           port);
+            goto error;
+        }
+    }
+
     return 0;
 
 error:
@@ -911,6 +978,7 @@ static int
 qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
                         struct qemud_driver *driver,
                         virDomainObjPtr dom,
+                        int nbdPort,
                         char **cookieout,
                         int *cookieoutlen,
                         unsigned int flags)
@@ -937,6 +1005,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
         return -1;
     }
 
+    if (flags & QEMU_MIGRATION_COOKIE_NBD &&
+        qemuMigrationCookieAddNBD(mig, nbdPort) < 0)
+        return -1;
+
     if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
         return -1;
 
@@ -1415,6 +1487,7 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
     qemuMigrationCookiePtr mig = NULL;
     virDomainDefPtr def = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    unsigned int cookie_flags = QEMU_MIGRATION_COOKIE_LOCKSTATE;
 
     VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s,"
               " cookieout=%p, cookieoutlen=%p, flags=%lx",
@@ -1434,12 +1507,15 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
     if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
         goto cleanup;
 
+    if (qemuCapsGet(priv->caps, QEMU_CAPS_NBD_SERVER))
+        cookie_flags |= QEMU_MIGRATION_COOKIE_NBD;
+
     if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0)))
         goto cleanup;
 
-    if (qemuMigrationBakeCookie(mig, driver, vm,
+    if (qemuMigrationBakeCookie(mig, driver, vm, 0,
                                 cookieout, cookieoutlen,
-                                QEMU_MIGRATION_COOKIE_LOCKSTATE) < 0)
+                                cookie_flags) < 0)
         goto cleanup;
 
     if (xmlin) {
@@ -1512,6 +1588,8 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
     bool tunnel = !!st;
     char *origname = NULL;
     char *xmlout = NULL;
+    int nbdPort = 0;
+    unsigned int cookie_flags = QEMU_MIGRATION_COOKIE_GRAPHICS;
 
     if (virTimeMillisNow(&now) < 0)
         return -1;
@@ -1589,7 +1667,8 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
     origname = NULL;
 
     if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
-                                       QEMU_MIGRATION_COOKIE_LOCKSTATE)))
+                                       QEMU_MIGRATION_COOKIE_LOCKSTATE |
+                                       QEMU_MIGRATION_COOKIE_NBD)))
         goto cleanup;
 
     if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
@@ -1640,8 +1719,12 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
         VIR_DEBUG("Received no lockstate");
     }
 
-    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen,
-                                QEMU_MIGRATION_COOKIE_GRAPHICS) < 0) {
+    /* dummy place holder for real work */
+    nbdPort = 0;
+    cookie_flags |= QEMU_MIGRATION_COOKIE_NBD;
+
+    if (qemuMigrationBakeCookie(mig, driver, vm, nbdPort,
+                                cookieout, cookieoutlen, cookie_flags) < 0) {
         /* We could tear down the whole guest here, but
          * cookie data is (so far) non-critical, so that
          * seems a little harsh. We'll just warn for now.
@@ -2150,7 +2233,8 @@ qemuMigrationRun(struct qemud_driver *driver,
     }
 
     if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
-                                       QEMU_MIGRATION_COOKIE_GRAPHICS)))
+                                       QEMU_MIGRATION_COOKIE_GRAPHICS |
+                                       QEMU_MIGRATION_COOKIE_NBD)))
         goto cleanup;
 
     if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig) < 0)
@@ -2296,9 +2380,10 @@ cleanup:
     }
 
     if (ret == 0 &&
-        qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen,
+        qemuMigrationBakeCookie(mig, driver, vm, -1, cookieout, cookieoutlen,
                                 QEMU_MIGRATION_COOKIE_PERSISTENT |
-                                QEMU_MIGRATION_COOKIE_NETWORK) < 0) {
+                                QEMU_MIGRATION_COOKIE_NETWORK |
+                                QEMU_MIGRATION_COOKIE_NBD) < 0) {
         VIR_WARN("Unable to encode migration cookie");
     }
 
@@ -3233,7 +3318,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
 
     qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);
 
-    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK;
+    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK | QEMU_MIGRATION_COOKIE_NBD;
     if (flags & VIR_MIGRATE_PERSIST_DEST)
         cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
 
@@ -3377,7 +3462,8 @@ qemuMigrationFinish(struct qemud_driver *driver,
                                          VIR_DOMAIN_EVENT_STOPPED_FAILED);
     }
 
-    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
+    if (qemuMigrationBakeCookie(mig, driver, vm, 0,
+                                cookieout, cookieoutlen, 0) < 0)
         VIR_WARN("Unable to encode migration cookie");
 
 endjob:
-- 
1.7.8.6




More information about the libvir-list mailing list