]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Add support for sending capabilities in migration cookie
authorJiri Denemark <jdenemar@redhat.com>
Fri, 6 Apr 2018 08:18:52 +0000 (10:18 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Tue, 17 Apr 2018 08:46:23 +0000 (10:46 +0200)
Some migration capabilities may be enabled automatically, but only if
both sides of migration support them. Thus we need to be able transfer
the list of supported migration capabilities in migration cookie.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_migration.c
src/qemu/qemu_migration_cookie.c
src/qemu/qemu_migration_cookie.h
src/qemu/qemu_migration_params.c
src/qemu/qemu_migration_params.h

index 319b4d000a5a4c720e6cf523c5263cbf18a6ae61..f573bd3eba0065865ac246194a0f1837c3678056 100644 (file)
@@ -1917,6 +1917,7 @@ qemuMigrationSrcBeginPhase(virQEMUDriverPtr driver,
         goto cleanup;
 
     if (qemuMigrationBakeCookie(mig, driver, vm,
+                                QEMU_MIGRATION_SOURCE,
                                 cookieout, cookieoutlen,
                                 cookieFlags) < 0)
         goto cleanup;
@@ -2429,8 +2430,9 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver,
         goto stopjob;
 
  done:
-    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout,
-                                cookieoutlen, cookieFlags) < 0) {
+    if (qemuMigrationBakeCookie(mig, driver, vm,
+                                QEMU_MIGRATION_DESTINATION,
+                                cookieout, cookieoutlen, cookieFlags) < 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.
@@ -3523,8 +3525,9 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver,
                    QEMU_MIGRATION_COOKIE_STATS;
 
     if (qemuMigrationCookieAddPersistent(mig, &persistDef) < 0 ||
-        qemuMigrationBakeCookie(mig, driver, vm, cookieout,
-                                cookieoutlen, cookieFlags) < 0) {
+        qemuMigrationBakeCookie(mig, driver, vm,
+                                QEMU_MIGRATION_SOURCE,
+                                cookieout, cookieoutlen, cookieFlags) < 0) {
         VIR_WARN("Unable to encode migration cookie");
     }
 
@@ -5019,7 +5022,9 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver,
             priv->job.completed->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED;
         }
 
-        if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen,
+        if (qemuMigrationBakeCookie(mig, driver, vm,
+                                    QEMU_MIGRATION_DESTINATION,
+                                    cookieout, cookieoutlen,
                                     QEMU_MIGRATION_COOKIE_STATS) < 0)
             VIR_WARN("Unable to encode migration cookie");
 
index 5a1e299ca2db376556927f4e407b5cc437fd037d..eca1b74d63bc3f4266055f7e10c86cb208cfb30f 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "qemu_domain.h"
 #include "qemu_migration_cookie.h"
+#include "qemu_migration_params.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -50,7 +51,8 @@ VIR_ENUM_IMPL(qemuMigrationCookieFlag,
               "memory-hotplug",
               "cpu-hotplug",
               "cpu",
-              "allowReboot");
+              "allowReboot",
+              "capabilities");
 
 
 static void
@@ -94,6 +96,18 @@ qemuMigrationCookieNBDFree(qemuMigrationCookieNBDPtr nbd)
 }
 
 
+static void
+qemuMigrationCookieCapsFree(qemuMigrationCookieCapsPtr caps)
+{
+    if (!caps)
+        return;
+
+    virBitmapFree(caps->supported);
+    virBitmapFree(caps->automatic);
+    VIR_FREE(caps);
+}
+
+
 void
 qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
 {
@@ -112,6 +126,7 @@ qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
     VIR_FREE(mig->lockDriver);
     VIR_FREE(mig->jobInfo);
     virCPUDefFree(mig->cpu);
+    qemuMigrationCookieCapsFree(mig->caps);
     VIR_FREE(mig);
 }
 
@@ -550,6 +565,33 @@ qemuMigrationCookieAddAllowReboot(qemuMigrationCookiePtr mig,
 }
 
 
+static int
+qemuMigrationCookieAddCaps(qemuMigrationCookiePtr mig,
+                           virDomainObjPtr vm,
+                           qemuMigrationParty party)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+
+    qemuMigrationCookieCapsFree(mig->caps);
+    if (VIR_ALLOC(mig->caps) < 0)
+        return -1;
+
+    if (priv->migrationCaps)
+        mig->caps->supported = virBitmapNewCopy(priv->migrationCaps);
+    else
+        mig->caps->supported = virBitmapNew(0);
+
+    mig->caps->automatic = qemuMigrationParamsGetAlwaysOnCaps(party);
+
+    if (!mig->caps->supported || !mig->caps->automatic)
+        return -1;
+
+    mig->flags |= QEMU_MIGRATION_COOKIE_CAPS;
+
+    return 0;
+}
+
+
 static void
 qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
                                      qemuMigrationCookieGraphicsPtr grap)
@@ -710,6 +752,33 @@ qemuMigrationCookieStatisticsXMLFormat(virBufferPtr buf,
 }
 
 
+static void
+qemuMigrationCookieCapsXMLFormat(virBufferPtr buf,
+                                 qemuMigrationCookieCapsPtr caps)
+{
+    qemuMigrationCapability cap;
+
+    virBufferAddLit(buf, "<capabilities>\n");
+    virBufferAdjustIndent(buf, 2);
+
+    for (cap = 0; cap < QEMU_MIGRATION_CAP_LAST; cap++) {
+        bool supported = false;
+        bool automatic = false;
+
+        ignore_value(virBitmapGetBit(caps->supported, cap, &supported));
+        ignore_value(virBitmapGetBit(caps->automatic, cap, &automatic));
+        if (supported) {
+            virBufferAsprintf(buf, "<cap name='%s' auto='%s'/>\n",
+                              qemuMigrationCapabilityTypeToString(cap),
+                              automatic ? "yes" : "no");
+        }
+    }
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</capabilities>\n");
+}
+
+
 static int
 qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
                              virBufferPtr buf,
@@ -793,6 +862,9 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
     if (mig->flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT)
         qemuDomainObjPrivateXMLFormatAllowReboot(buf, mig->allowReboot);
 
+    if (mig->flags & QEMU_MIGRATION_COOKIE_CAPS)
+        qemuMigrationCookieCapsXMLFormat(buf, mig->caps);
+
     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</qemu-migration>\n");
     return 0;
@@ -1067,6 +1139,59 @@ qemuMigrationCookieStatisticsXMLParse(xmlXPathContextPtr ctxt)
 }
 
 
+static qemuMigrationCookieCapsPtr
+qemuMigrationCookieCapsXMLParse(xmlXPathContextPtr ctxt)
+{
+    qemuMigrationCookieCapsPtr caps = NULL;
+    xmlNodePtr *nodes = NULL;
+    qemuMigrationCookieCapsPtr ret = NULL;
+    char *name = NULL;
+    char *automatic = NULL;
+    int cap;
+    size_t i;
+    int n;
+
+    if (VIR_ALLOC(caps) < 0)
+        return NULL;
+
+    if (!(caps->supported = virBitmapNew(QEMU_MIGRATION_CAP_LAST)) ||
+        !(caps->automatic = virBitmapNew(QEMU_MIGRATION_CAP_LAST)))
+        goto cleanup;
+
+    if ((n = virXPathNodeSet("./capabilities[1]/cap", ctxt, &nodes)) < 0)
+        goto cleanup;
+
+    for (i = 0; i < n; i++) {
+        if (!(name = virXMLPropString(nodes[i], "name"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("missing migration capability name"));
+            goto cleanup;
+        }
+
+        if ((cap = qemuMigrationCapabilityTypeFromString(name)) < 0)
+            VIR_DEBUG("unknown migration capability '%s'", name);
+        else
+            ignore_value(virBitmapSetBit(caps->supported, cap));
+
+        if ((automatic = virXMLPropString(nodes[i], "auto")) &&
+            STREQ(automatic, "yes"))
+            ignore_value(virBitmapSetBit(caps->automatic, cap));
+
+        VIR_FREE(name);
+        VIR_FREE(automatic);
+    }
+
+    VIR_STEAL_PTR(ret, caps);
+
+ cleanup:
+    qemuMigrationCookieCapsFree(caps);
+    VIR_FREE(nodes);
+    VIR_FREE(name);
+    VIR_FREE(automatic);
+    return ret;
+}
+
+
 static int
 qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
                             virQEMUDriverPtr driver,
@@ -1246,6 +1371,10 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
         qemuDomainObjPrivateXMLParseAllowReboot(ctxt, &mig->allowReboot) < 0)
         goto error;
 
+    if (flags & QEMU_MIGRATION_COOKIE_CAPS &&
+        !(mig->caps = qemuMigrationCookieCapsXMLParse(ctxt)))
+        goto error;
+
     virObjectUnref(caps);
     return 0;
 
@@ -1286,6 +1415,7 @@ int
 qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
                         virQEMUDriverPtr driver,
                         virDomainObjPtr dom,
+                        qemuMigrationParty party,
                         char **cookieout,
                         int *cookieoutlen,
                         unsigned int flags)
@@ -1329,6 +1459,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
     if (flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT)
         qemuMigrationCookieAddAllowReboot(mig, dom);
 
+    if (flags & QEMU_MIGRATION_COOKIE_CAPS &&
+        qemuMigrationCookieAddCaps(mig, dom, party) < 0)
+        return -1;
+
     if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
         return -1;
 
index 4a25511a9a2f9ff35c0b8a2fd0f496f12023f08d..08c5de8f0686579b3b649196ebfaa6d31d38e54a 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef __QEMU_MIGRATION_COOKIE_H__
 # define __QEMU_MIGRATION_COOKIE_H__
 
+# include "qemu_migration_params.h"
+
 typedef enum {
     QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
     QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
@@ -30,6 +32,7 @@ typedef enum {
     QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG,
     QEMU_MIGRATION_COOKIE_FLAG_CPU,
     QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT,
+    QEMU_MIGRATION_COOKIE_FLAG_CAPS,
 
     QEMU_MIGRATION_COOKIE_FLAG_LAST
 } qemuMigrationCookieFlags;
@@ -47,6 +50,7 @@ typedef enum {
     QEMU_MIGRATION_COOKIE_CPU_HOTPLUG = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG),
     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),
 } qemuMigrationCookieFeatures;
 
 typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@@ -92,6 +96,13 @@ struct _qemuMigrationCookieNBD {
     } *disks;
 };
 
+typedef struct _qemuMigrationCookieCaps qemuMigrationCookieCaps;
+typedef qemuMigrationCookieCaps *qemuMigrationCookieCapsPtr;
+struct _qemuMigrationCookieCaps {
+    virBitmapPtr supported;
+    virBitmapPtr automatic;
+};
+
 typedef struct _qemuMigrationCookie qemuMigrationCookie;
 typedef qemuMigrationCookie *qemuMigrationCookiePtr;
 struct _qemuMigrationCookie {
@@ -132,6 +143,9 @@ struct _qemuMigrationCookie {
 
     /* If flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT */
     virTristateBool allowReboot;
+
+    /* If flags & QEMU_MIGRATION_COOKIE_CAPS */
+    qemuMigrationCookieCapsPtr caps;
 };
 
 
@@ -139,6 +153,7 @@ int
 qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
                         virQEMUDriverPtr driver,
                         virDomainObjPtr dom,
+                        qemuMigrationParty party,
                         char **cookieout,
                         int *cookieoutlen,
                         unsigned int flags);
index 2723288dfc7760232c6fb88ebb0ca7747d283b29..1b1e5829e8a754bb58ad584b8587746d7ff1782d 100644 (file)
@@ -153,6 +153,26 @@ static const qemuMigrationParamType qemuMigrationParamTypes[] = {
 verify(ARRAY_CARDINALITY(qemuMigrationParamTypes) == QEMU_MIGRATION_PARAM_LAST);
 
 
+virBitmapPtr
+qemuMigrationParamsGetAlwaysOnCaps(qemuMigrationParty party)
+{
+    virBitmapPtr caps = NULL;
+    size_t i;
+
+    if (!(caps = virBitmapNew(QEMU_MIGRATION_CAP_LAST)))
+        return NULL;
+
+    for (i = 0; i < ARRAY_CARDINALITY(qemuMigrationParamsAlwaysOn); i++) {
+        if (!(qemuMigrationParamsAlwaysOn[i].party & party))
+            continue;
+
+        ignore_value(virBitmapSetBit(caps, qemuMigrationParamsAlwaysOn[i].cap));
+    }
+
+    return caps;
+}
+
+
 static qemuMigrationParamsPtr
 qemuMigrationParamsNew(void)
 {
index ceba0eb68a143b072dc581265ffdc56094a63821..75a441e1e17e601db29152a8ec005260dc63e1fb 100644 (file)
@@ -65,6 +65,9 @@ typedef enum {
 } qemuMigrationParty;
 
 
+virBitmapPtr
+qemuMigrationParamsGetAlwaysOnCaps(qemuMigrationParty party);
+
 qemuMigrationParamsPtr
 qemuMigrationParamsFromFlags(virTypedParameterPtr params,
                              int nparams,