[PATCH 16/19] tests: qemumigrationcookie: Add testing for block dirty bitmap migration

Peter Krempa pkrempa at redhat.com
Thu Feb 11 15:37:55 UTC 2021


Test the XML infrastructure for <blockDirtyBitmaps> migration cookie
element as well as the conversion to migration parameters for QMP schema
validation.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 tests/meson.build                             |   2 +-
 .../nbd-bitmaps-xml2xml-in.xml                |  52 ++++++
 .../nbd-bitmaps-xml2xml-migparams.json        |  25 +++
 .../nbd-bitmaps-xml2xml-out.xml               |  51 ++++++
 tests/qemumigrationcookiexmltest.c            | 166 +++++++++++++++---
 5 files changed, 269 insertions(+), 27 deletions(-)
 create mode 100644 tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-in.xml
 create mode 100644 tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-migparams.json
 create mode 100644 tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-out.xml

diff --git a/tests/meson.build b/tests/meson.build
index 0de0783839..b9b2255666 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -452,7 +452,7 @@ if conf.has('WITH_QEMU')
     { 'name': 'qemuhotplugtest', 'link_with': [ test_qemu_driver_lib, test_utils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib ] },
     { 'name': 'qemumemlocktest', 'link_with': [ test_qemu_driver_lib ], 'link_whole': [ test_utils_qemu_lib ] },
     { 'name': 'qemumigparamstest', 'link_with': [ test_qemu_driver_lib, test_utils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib ] },
-    { 'name': 'qemumigrationcookiexmltest', 'link_with': [ test_qemu_driver_lib ], 'link_whole': [ test_utils_qemu_lib, test_file_wrapper_lib ] },
+    { 'name': 'qemumigrationcookiexmltest', 'link_with': [ test_qemu_driver_lib, test_utils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib, test_file_wrapper_lib ] },
     { 'name': 'qemumonitorjsontest', 'link_with': [ test_qemu_driver_lib, test_utils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib ] },
     { 'name': 'qemusecuritytest', 'sources': [ 'qemusecuritytest.c', 'qemusecuritymock.c' ], 'link_with': [ test_qemu_driver_lib ], 'link_whole': [ test_utils_qemu_lib ] },
     { 'name': 'qemustatusxml2xmltest', 'link_with': [ test_qemu_driver_lib ], 'link_whole': [ test_utils_qemu_lib, test_file_wrapper_lib ] },
diff --git a/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-in.xml b/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-in.xml
new file mode 100644
index 0000000000..b219c25f27
--- /dev/null
+++ b/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-in.xml
@@ -0,0 +1,52 @@
+<qemu-migration>
+  <name>migr</name>
+  <uuid>10b01607-0323-486b-afe2-3014a8a5b98b</uuid>
+  <hostname>sourcehost</hostname>
+  <hostuuid>1f5e0da0-fecf-413f-9bf1-1aa9c21e71e4</hostuuid>
+  <feature name='lockstate'/>
+  <nbd>
+    <disk target='hda' capacity='708837376'/>
+    <disk target='vda' capacity='10485760'/>
+  </nbd>
+  <cpu mode='custom' match='exact' check='full'>
+    <model fallback='forbid'>EPYC-Rome</model>
+    <vendor>AMD</vendor>
+    <feature policy='require' name='x2apic'/>
+    <feature policy='require' name='tsc-deadline'/>
+    <feature policy='require' name='hypervisor'/>
+    <feature policy='require' name='tsc_adjust'/>
+    <feature policy='require' name='stibp'/>
+    <feature policy='require' name='arch-capabilities'/>
+    <feature policy='require' name='ssbd'/>
+    <feature policy='require' name='xsaves'/>
+    <feature policy='require' name='cmp_legacy'/>
+    <feature policy='require' name='amd-ssbd'/>
+    <feature policy='require' name='virt-ssbd'/>
+    <feature policy='require' name='rdctl-no'/>
+    <feature policy='require' name='skip-l1dfl-vmentry'/>
+    <feature policy='require' name='mds-no'/>
+    <feature policy='require' name='pschange-mc-no'/>
+    <feature policy='disable' name='svm'/>
+    <feature policy='disable' name='npt'/>
+    <feature policy='disable' name='nrip-save'/>
+  </cpu>
+  <allowReboot value='yes'/>
+  <capabilities>
+    <cap name='xbzrle' auto='no'/>
+    <cap name='auto-converge' auto='no'/>
+    <cap name='rdma-pin-all' auto='no'/>
+    <cap name='postcopy-ram' auto='no'/>
+    <cap name='compress' auto='no'/>
+    <cap name='pause-before-switchover' auto='yes'/>
+    <cap name='late-block-activate' auto='no'/>
+    <cap name='multifd' auto='no'/>
+    <cap name='dirty-bitmaps' auto='no'/>
+  </capabilities>
+  <blockDirtyBitmaps>
+    <disk target='vda'>
+      <bitmap name='a' alias='libvirt-vda-a'/>
+      <bitmap name='b' alias='libvirt-vda-b'/>
+      <bitmap name='c' alias='libvirt-vda-c'/>
+    </disk>
+  </blockDirtyBitmaps>
+</qemu-migration>
diff --git a/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-migparams.json b/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-migparams.json
new file mode 100644
index 0000000000..100da7c270
--- /dev/null
+++ b/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-migparams.json
@@ -0,0 +1,25 @@
+{
+  "block-bitmap-mapping": [
+    {
+      "node-name": "libvirt-1-format",
+      "alias": "vda",
+      "bitmaps": [
+        {
+          "name": "a",
+          "alias": "libvirt-vda-a",
+          "transform": {
+            "persistent": true
+          }
+        },
+        {
+          "name": "b",
+          "alias": "libvirt-vda-b"
+        },
+        {
+          "name": "c",
+          "alias": "libvirt-vda-c"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-out.xml b/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-out.xml
new file mode 100644
index 0000000000..09b6fa291c
--- /dev/null
+++ b/tests/qemumigrationcookiexmldata/nbd-bitmaps-xml2xml-out.xml
@@ -0,0 +1,51 @@
+<qemu-migration>
+  <name>migr</name>
+  <uuid>10b01607-0323-486b-afe2-3014a8a5b98b</uuid>
+  <hostname>hostname</hostname>
+  <hostuuid>4a802f00-4cba-5df6-9679-a08c4c5b577f</hostuuid>
+  <nbd>
+    <disk target='hda' capacity='708837376'/>
+    <disk target='vda' capacity='10485760'/>
+  </nbd>
+  <cpu mode='custom' match='exact' check='full'>
+    <model fallback='forbid'>EPYC-Rome</model>
+    <vendor>AMD</vendor>
+    <feature policy='require' name='x2apic'/>
+    <feature policy='require' name='tsc-deadline'/>
+    <feature policy='require' name='hypervisor'/>
+    <feature policy='require' name='tsc_adjust'/>
+    <feature policy='require' name='stibp'/>
+    <feature policy='require' name='arch-capabilities'/>
+    <feature policy='require' name='ssbd'/>
+    <feature policy='require' name='xsaves'/>
+    <feature policy='require' name='cmp_legacy'/>
+    <feature policy='require' name='amd-ssbd'/>
+    <feature policy='require' name='virt-ssbd'/>
+    <feature policy='require' name='rdctl-no'/>
+    <feature policy='require' name='skip-l1dfl-vmentry'/>
+    <feature policy='require' name='mds-no'/>
+    <feature policy='require' name='pschange-mc-no'/>
+    <feature policy='disable' name='svm'/>
+    <feature policy='disable' name='npt'/>
+    <feature policy='disable' name='nrip-save'/>
+  </cpu>
+  <allowReboot value='yes'/>
+  <capabilities>
+    <cap name='xbzrle' auto='no'/>
+    <cap name='auto-converge' auto='no'/>
+    <cap name='rdma-pin-all' auto='no'/>
+    <cap name='postcopy-ram' auto='no'/>
+    <cap name='compress' auto='no'/>
+    <cap name='pause-before-switchover' auto='yes'/>
+    <cap name='late-block-activate' auto='no'/>
+    <cap name='multifd' auto='no'/>
+    <cap name='dirty-bitmaps' auto='no'/>
+  </capabilities>
+  <blockDirtyBitmaps>
+    <disk target='vda'>
+      <bitmap name='a' alias='libvirt-vda-a'/>
+      <bitmap name='b' alias='libvirt-vda-b'/>
+      <bitmap name='c' alias='libvirt-vda-c'/>
+    </disk>
+  </blockDirtyBitmaps>
+</qemu-migration>
diff --git a/tests/qemumigrationcookiexmltest.c b/tests/qemumigrationcookiexmltest.c
index 5fe0ba8a8a..7f2437a7fe 100644
--- a/tests/qemumigrationcookiexmltest.c
+++ b/tests/qemumigrationcookiexmltest.c
@@ -25,9 +25,13 @@

 #include "internal.h"
 #include "testutilsqemu.h"
+#include "testutilsqemuschema.h"
 #include "configmake.h"

+#define LIBVIRT_QEMU_MIGRATION_PARAMSPRIV_H_ALLOW
+
 #include "qemu/qemu_migration_cookie.h"
+#include "qemu/qemu_migration_paramspriv.h"

 #define VIR_FROM_THIS VIR_FROM_NONE

@@ -61,13 +65,33 @@ struct testQemuMigrationCookieData {

     qemuMigrationParty cookiePopulateParty;

+    qemuMigrationCookiePtr cookie;
+
     char *xmlstr;
     int xmlstrlen;
     char *infile;
     char *outfile;
+    char *outmigparamsfile;
 };


+static void
+testQemuMigrationCookieDataFree(struct testQemuMigrationCookieData *data)
+{
+    if (!data)
+        return;
+
+    qemuMigrationCookieFree(data->cookie);
+    g_free(data->xmlstr);
+    g_free(data->outfile);
+    g_free(data->infile);
+    g_free(data->outmigparamsfile);
+    g_free(data->inStatus);
+    virDomainObjEndAPI(&data->vm);
+    g_free(data);
+}
+
+
 static int
 testQemuMigrationCookiePopulate(const void *opaque)
 {
@@ -115,26 +139,25 @@ testQemuMigrationCookieParse(const void *opaque)
     struct testQemuMigrationCookieData *data = (struct testQemuMigrationCookieData *) opaque;
     qemuDomainObjPrivatePtr priv = data->vm->privateData;
     g_auto(virBuffer) actual = VIR_BUFFER_INITIALIZER;
-    g_autoptr(qemuMigrationCookie) cookie = NULL;

-    if (!(cookie = qemuMigrationCookieParse(&driver,
-                                            data->vm->def,
-                                            NULL,
-                                            priv,
-                                            data->xmlstr,
-                                            data->xmlstrlen,
-                                            data->cookieParseFlags))) {
+    if (!(data->cookie = qemuMigrationCookieParse(&driver,
+                                                  data->vm->def,
+                                                  NULL,
+                                                  priv,
+                                                  data->xmlstr,
+                                                  data->xmlstrlen,
+                                                  data->cookieParseFlags))) {
         VIR_TEST_DEBUG("\nfailed to parse qemu migration cookie:\n%s\n", data->xmlstr);
         return -1;
     }

     /* set all flags so that formatter attempts to format everything */
-    cookie->flags = ~0;
+    data->cookie->flags = ~0;

     if (qemuMigrationCookieXMLFormat(&driver,
                                      priv->qemuCaps,
                                      &actual,
-                                     cookie) < 0) {
+                                     data->cookie) < 0) {
         VIR_TEST_DEBUG("\nfailed to format back qemu migration cookie");
         return -1;
     }
@@ -179,21 +202,6 @@ testQemuMigrationCookieXMLLoad(const void *opaque)
 }


-static void
-testQemuMigrationCookieDataFree(struct testQemuMigrationCookieData *data)
-{
-    if (!data)
-        return;
-
-    g_free(data->xmlstr);
-    g_free(data->outfile);
-    g_free(data->infile);
-    g_free(data->inStatus);
-    virDomainObjEndAPI(&data->vm);
-    g_free(data);
-}
-
-
 static int
 testQemuMigrationCookieDom2XML(const char *namesuffix,
                                const char *domxml,
@@ -207,9 +215,11 @@ testQemuMigrationCookieDom2XML(const char *namesuffix,
         /* flags unsupported by default:
          * - lockstate: internals are NULL in tests, causes crash
          * - nbd: monitor not present
+         * - dirty bitmaps: monitor not present
          */
         unsigned int cookiePopulateFlagMask = QEMU_MIGRATION_COOKIE_LOCKSTATE |
-                                              QEMU_MIGRATION_COOKIE_NBD;
+                                              QEMU_MIGRATION_COOKIE_NBD |
+                                              QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS;
         data->cookiePopulateFlags = ~cookiePopulateFlagMask;
     }

@@ -286,6 +296,107 @@ testQemuMigrationCookieXML2XML(const char *name,
 }


+static int
+testQemuMigrationCookieBlockDirtyBitmaps(const void *opaque)
+{
+    const struct testQemuMigrationCookieData *data = opaque;
+    g_autoptr(virJSONValue) migParamsBitmaps = NULL;
+    g_autofree char *actualJSON = NULL;
+    g_autoptr(virJSONValue) paramsOut = NULL;
+    g_auto(virBuffer) debug = VIR_BUFFER_INITIALIZER;
+    g_autoptr(qemuMigrationParams) migParams = NULL;
+    g_autoptr(GHashTable) qmpschema = NULL;
+    GSList *next;
+
+    if (!(qmpschema = testQEMUSchemaLoadLatest("x86_64"))) {
+        VIR_TEST_VERBOSE("failed to load QMP schema");
+        return -1;
+    }
+
+    if (qemuMigrationCookieBlockDirtyBitmapsMatchDisks(data->vm->def,
+                                                       data->cookie->blockDirtyBitmaps) < 0)
+        return -1;
+
+    for (next = data->cookie->blockDirtyBitmaps; next; next = next->next) {
+        qemuMigrationBlockDirtyBitmapsDiskPtr disk = next->data;
+        qemuMigrationBlockDirtyBitmapsDiskBitmapPtr bitmap = disk->bitmaps->data;
+
+        bitmap->persistent = VIR_TRISTATE_BOOL_YES;
+    }
+
+    if (qemuMigrationCookieBlockDirtyBitmapsToParams(data->cookie->blockDirtyBitmaps,
+                                                     &migParamsBitmaps))
+        return -1;
+
+    if (!(migParams = qemuMigrationParamsNew()))
+        return -1;
+
+    qemuMigrationParamsSetBlockDirtyBitmapMapping(migParams, &migParamsBitmaps);
+
+    if (!(paramsOut = qemuMigrationParamsToJSON(migParams)) ||
+        !(actualJSON = virJSONValueToString(paramsOut, true)))
+        return -1;
+
+    if (testQEMUSchemaValidateCommand("migrate-set-parameters",
+                                      paramsOut,
+                                      qmpschema,
+                                      false,
+                                      false,
+                                      &debug) < 0) {
+        VIR_TEST_VERBOSE("failed to validate migration params '%s' against QMP schema: %s",
+                         actualJSON, virBufferCurrentContent(&debug));
+        return -1;
+    }
+
+    if (virTestCompareToFile(actualJSON, data->outmigparamsfile) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+/* tests also the conversion to list of migrated bitmaps */
+static int
+testQemuMigrationCookieXML2XMLBitmaps(const char *name,
+                                      const char *statusxml,
+                                      unsigned int cookieParseFlags)
+{
+    struct testQemuMigrationCookieData *data = g_new0(struct testQemuMigrationCookieData, 1);
+    int ret = 0;
+
+    if (cookieParseFlags == 0)
+        data->cookieParseFlags = ~0;
+
+    data->inStatus = g_strconcat(abs_srcdir, "/", statusxml, NULL);
+    data->infile = g_strconcat(abs_srcdir, "/qemumigrationcookiexmldata/",
+                               name, "-xml2xml-in.xml", NULL);
+    data->outfile = g_strconcat(abs_srcdir, "/qemumigrationcookiexmldata/",
+                                name, "-xml2xml-out.xml", NULL);
+    data->outmigparamsfile = g_strconcat(abs_srcdir, "/qemumigrationcookiexmldata/",
+                                         name, "-xml2xml-migparams.json", NULL);
+
+    if (virTestRun(tn("qemumigrationcookieXML2XML-dom-", name, NULL),
+                   testQemuMigrationCookieDomInit, data) < 0)
+        ret = -1;
+
+    if (virTestRun(tn("qemumigrationcookieXML2XML-load-", name, NULL),
+                   testQemuMigrationCookieXMLLoad, data) < 0)
+        ret = -1;
+
+    if (virTestRun(tn("qemumigrationcookieXML2XML-parse-", name, NULL),
+                   testQemuMigrationCookieParse, data) < 0)
+        ret = -1;
+
+    if (virTestRun(tn("qemumigrationcookieXML2XML-migparams-", name, NULL),
+                   testQemuMigrationCookieBlockDirtyBitmaps, data) < 0)
+        ret = -1;
+
+    testQemuMigrationCookieDataFree(data);
+
+    return ret;
+}
+
+
 static int
 mymain(void)
 {
@@ -321,6 +432,9 @@ mymain(void)
         testQemuMigrationCookieXML2XML("full", "qemustatusxml2xmldata/modern-in.xml", 0) < 0)
         ret = -1;

+    if (testQemuMigrationCookieXML2XMLBitmaps("nbd-bitmaps", "qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml", 0) < 0)
+        ret = -1;
+
     virBufferFreeAndReset(&testnamebuf);

  cleanup:
-- 
2.29.2




More information about the libvir-list mailing list