[PATCH 1/3] qemu_migration: Add hooks to transport network data during migration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add the ability for the Qemu V3 migration protocol to
include transporting network configuration. A generic
framework is proposed with this patch to allow for the
transfer of opaque data.

Signed-off-by: Kyle Mestery <kmestery@xxxxxxxxx>
---
 src/qemu/qemu_migration.c | 260 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 258 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1b21ef6..539b361 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_NETWORK,
 
     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", "network");
 
 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),
 };
 
 typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@@ -95,6 +97,22 @@ struct _qemuMigrationCookieGraphics {
     char *tlsSubject;
 };
 
+typedef struct _qemuMigrationCookieNetwork qemuMigrationCookieNetwork;
+typedef qemuMigrationCookieNetwork *qemuMigrationCookieNetworkPtr;
+struct _qemuMigrationCookieNetwork {
+    /* How many virtual NICs are we saving data for? */
+    int nnets;
+
+    /*
+     * Array of pointers to saved data. Each VIF will have it's own
+     * data to transfer.
+     */
+    char **netdata;
+
+    /* What type is each VIF? */
+    int **viftype;
+};
+
 typedef struct _qemuMigrationCookie qemuMigrationCookie;
 typedef qemuMigrationCookie *qemuMigrationCookiePtr;
 struct _qemuMigrationCookie {
@@ -120,6 +138,9 @@ struct _qemuMigrationCookie {
 
     /* If (flags & QEMU_MIGRATION_COOKIE_PERSISTENT) */
     virDomainDefPtr persistent;
+
+    /* If (flags & QEMU_MIGRATION_COOKIE_NETWORK) */
+    qemuMigrationCookieNetworkPtr network;
 };
 
 static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
@@ -132,6 +153,27 @@ static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
 }
 
 
+static void qemuMigrationCookieNetworkFree(qemuMigrationCookieNetworkPtr
+                                               network)
+{
+    int i;
+
+    if (!network)
+        return;
+
+    for (i = 0; i < network->nnets; i++) {
+        VIR_FREE(network->viftype[i]);
+        VIR_FREE(network->netdata[i]);
+    }
+
+    VIR_FREE(network->viftype);
+
+    VIR_FREE(network->netdata);
+
+    VIR_FREE(network);
+}
+
+
 static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
 {
     if (!mig)
@@ -140,6 +182,10 @@ static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
     if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS)
         qemuMigrationCookieGraphicsFree(mig->graphics);
 
+    if (mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) {
+        qemuMigrationCookieNetworkFree(mig->network);
+    }
+
     VIR_FREE(mig->localHostname);
     VIR_FREE(mig->remoteHostname);
     VIR_FREE(mig->name);
@@ -256,6 +302,59 @@ error:
 }
 
 
+static qemuMigrationCookieNetworkPtr
+qemuMigrationCookieNetworkAlloc(struct qemud_driver *driver ATTRIBUTE_UNUSED,
+                                    virDomainDefPtr def)
+{
+    qemuMigrationCookieNetworkPtr mig;
+    int i;
+    virDomainNetDefPtr netptr ATTRIBUTE_UNUSED;
+
+    if (VIR_ALLOC(mig) < 0)
+        goto no_memory;
+
+    mig->nnets = def->nnets;
+
+    if (VIR_ALLOC_N(mig->netdata, def->nnets) < 0)
+        goto no_memory;
+
+    if (VIR_ALLOC_N(mig->viftype, def->nnets) < 0)
+        goto no_memory;
+
+    for (i = 0; i < def->nnets; i++) {
+        virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(def->nets[i]);
+        netptr = def->nets[i];
+
+        if (vport) {
+            if (VIR_ALLOC(mig->viftype[i]) < 0)
+                goto no_memory;
+
+            *mig->viftype[i] = vport->virtPortType;
+
+            switch (vport->virtPortType) {
+            case VIR_NETDEV_VPORT_PROFILE_NONE:
+                break;
+            case VIR_NETDEV_VPORT_PROFILE_8021QBG:
+                break;
+            case VIR_NETDEV_VPORT_PROFILE_8021QBH:
+                break;
+            case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+    return mig;
+
+no_memory:
+    virReportOOMError();
+    qemuMigrationCookieNetworkFree(mig);
+    return NULL;
+}
+
+
 static qemuMigrationCookiePtr
 qemuMigrationCookieNew(virDomainObjPtr dom)
 {
@@ -370,6 +469,27 @@ qemuMigrationCookieAddPersistent(qemuMigrationCookiePtr mig,
 }
 
 
+static int
+qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
+                                  struct qemud_driver *driver,
+                                  virDomainObjPtr dom)
+{
+    if (mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Network migration data already present"));
+        return -1;
+    }
+
+    if (dom->def->nnets >= 1) {
+        if (!(mig->network = qemuMigrationCookieNetworkAlloc(
+                                        driver, dom->def)))
+            return -1;
+        mig->flags |= QEMU_MIGRATION_COOKIE_NETWORK;
+    }
+
+    return 0;
+}
+
 
 static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
                                                  qemuMigrationCookieGraphicsPtr grap)
@@ -389,6 +509,25 @@ static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
 }
 
 
+static void qemuMigrationCookieNetworkXMLFormat(virBufferPtr buf,
+                                                    qemuMigrationCookieNetworkPtr optr)
+{
+    int i;
+
+    virBufferAsprintf(buf, "  <network nnets='%d'>\n", optr->nnets);
+    if (optr->nnets > 0)
+        virBufferAsprintf(buf, "    <vifs>\n");
+    for (i = 0; i < optr->nnets; i++) {
+        virBufferAsprintf(buf, "      <vif num='%d' viftype='%d' netdata='%s'/>\n",
+                          i, *optr->viftype[i], optr->netdata[i]);
+    }
+    if (optr->nnets > 0)
+        virBufferAsprintf(buf, "    </vifs>\n");
+
+    virBufferAddLit(buf, "  </network>\n");
+}
+
+
 static int
 qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
                              virBufferPtr buf,
@@ -439,6 +578,10 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
         virBufferAdjustIndent(buf, -2);
     }
 
+    if ((mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) &&
+        mig->network)
+        qemuMigrationCookieNetworkXMLFormat(buf, mig->network);
+
     virBufferAddLit(buf, "</qemu-migration>\n");
     return 0;
 }
@@ -516,6 +659,74 @@ error:
 }
 
 
+static qemuMigrationCookieNetworkPtr
+qemuMigrationCookieNetworkXMLParse(xmlXPathContextPtr ctxt)
+{
+    qemuMigrationCookieNetworkPtr optr;
+    int i;
+    int n;
+    xmlNodePtr *vifs = NULL;
+    char *viftype;
+
+    if (VIR_ALLOC(optr) < 0)
+        goto no_memory;
+
+    if (virXPathInt("string(./network/@nnets)", ctxt, &optr->nnets) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("missing nnets attribute in migration data"));
+        goto error;
+    }
+
+    if (VIR_ALLOC_N(optr->netdata, optr->nnets) < 0)
+        goto no_memory;
+
+    if (VIR_ALLOC_N(optr->viftype, optr->nnets) < 0)
+        goto no_memory;
+
+    if ((n = virXPathNodeSet("./network/vifs/vif", ctxt, &vifs)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("missing vif information"));
+        goto error;
+    }
+
+    for (i = 0; i < n; i++) {
+        if (VIR_ALLOC(optr->netdata[i]) < 0)
+            goto no_memory;
+
+        if (VIR_ALLOC(optr->viftype[i]) < 0)
+            goto no_memory;
+
+        if (!(optr->netdata[i] = virXMLPropString(vifs[i], "netdata"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("missing netdata attribute in migration data"));
+            goto error;
+        }
+
+        if (!(viftype = virXMLPropString(vifs[i], "viftype"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("missing viftype attribute in migration data"));
+            goto error;
+        }
+
+        *optr->viftype[i] = atoi(viftype);
+
+        VIR_FREE(viftype);
+    }
+
+    VIR_FREE(vifs);
+
+    return optr;
+
+no_memory:
+    virReportOOMError();
+error:
+    if (vifs)
+        VIR_FREE(vifs);
+    qemuMigrationCookieNetworkFree(optr);
+    return NULL;
+}
+
+
 static int
 qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
                             struct qemud_driver *driver,
@@ -662,6 +873,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
         VIR_FREE(nodes);
     }
 
+    if ((flags & QEMU_MIGRATION_COOKIE_NETWORK) &&
+        virXPathBoolean("count(./network) > 0", ctxt) &&
+        (!(mig->network = qemuMigrationCookieNetworkXMLParse(ctxt))))
+        goto error;
+
     return 0;
 
 error:
@@ -721,6 +937,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
         qemuMigrationCookieAddPersistent(mig, dom) < 0)
         return -1;
 
+    if (flags & QEMU_MIGRATION_COOKIE_NETWORK &&
+        qemuMigrationCookieAddNetwork(mig, driver, dom) < 0)
+        return -1;
+
     if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
         return -1;
 
@@ -1050,6 +1270,36 @@ qemuDomainMigrateGraphicsRelocate(struct qemud_driver *driver,
 }
 
 
+static int
+qemuDomainMigrateOPDRelocate(struct qemud_driver *driver ATTRIBUTE_UNUSED,
+                             virDomainObjPtr vm,
+                             qemuMigrationCookiePtr cookie)
+{
+    virDomainNetDefPtr netptr ATTRIBUTE_UNUSED;
+    int ret = 0;
+    int i;
+
+    for (i = 0; i < cookie->network->nnets; i++) {
+        netptr = vm->def->nets[i];
+
+        switch (*cookie->network->viftype[i]) {
+        case VIR_NETDEV_VPORT_PROFILE_NONE:
+            break;
+        case VIR_NETDEV_VPORT_PROFILE_8021QBG:
+            break;
+        case VIR_NETDEV_VPORT_PROFILE_8021QBH:
+            break;
+        case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
+            break;
+        default:
+            break;
+        }
+    }
+
+    return ret;
+}
+
+
 /* This is called for outgoing non-p2p migrations when a connection to the
  * client which initiated the migration was closed but we were waiting for it
  * to follow up with the next phase, that is, in between
@@ -1994,7 +2244,8 @@ cleanup:
 
     if (ret == 0 &&
         qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen,
-                                QEMU_MIGRATION_COOKIE_PERSISTENT ) < 0)
+                                QEMU_MIGRATION_COOKIE_PERSISTENT |
+                                QEMU_MIGRATION_COOKIE_NETWORK) < 0)
         VIR_WARN("Unable to encode migration cookie");
 
     qemuMigrationCookieFree(mig);
@@ -2929,6 +3180,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
 
     qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);
 
+    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK;
     if (flags & VIR_MIGRATE_PERSIST_DEST)
         cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
 
@@ -2956,6 +3208,10 @@ qemuMigrationFinish(struct qemud_driver *driver,
             goto endjob;
         }
 
+        if (mig->network)
+            if (qemuDomainMigrateOPDRelocate(driver, vm, mig) < 0)
+                VIR_WARN("unable to provide network data for relocation");
+
         if (flags & VIR_MIGRATE_PERSIST_DEST) {
             virDomainDefPtr vmdef;
             if (vm->persistent)
-- 
1.7.11.4

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]