[PATCH v2 7/9] tests: Add testing of qemu migration cookie

Peter Krempa pkrempa at redhat.com
Wed Nov 4 13:25:43 UTC 2020


Migration cookie transports a lot of information but there are no tests
for it.

The test supports both xml2xml testing and also testing of the
population of the migration cookie data from a domain object, although
that option is not very useful as many things are collected from running
qemu and thus can't be tested efficiently here.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 tests/meson.build                             |   1 +
 .../basic-xml2xml-in.xml                      |   6 +
 .../basic-xml2xml-out.xml                     |   9 +
 .../modern-dom-out-dest.xml                   |  12 +
 .../modern-dom-out-source.xml                 |  12 +
 tests/qemumigrationcookiexmltest.c            | 336 ++++++++++++++++++
 6 files changed, 376 insertions(+)
 create mode 100644 tests/qemumigrationcookiexmldata/basic-xml2xml-in.xml
 create mode 100644 tests/qemumigrationcookiexmldata/basic-xml2xml-out.xml
 create mode 100644 tests/qemumigrationcookiexmldata/modern-dom-out-dest.xml
 create mode 100644 tests/qemumigrationcookiexmldata/modern-dom-out-source.xml
 create mode 100644 tests/qemumigrationcookiexmltest.c

diff --git a/tests/meson.build b/tests/meson.build
index 818fce65f3..68a309ebfb 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -456,6 +456,7 @@ if conf.has('WITH_QEMU')
     { 'name': 'qemuxml2argvtest', 'link_with': [ test_qemu_driver_lib, test_utils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib, test_file_wrapper_lib ] },
     { 'name': 'qemuxml2xmltest', 'link_with': [ test_qemu_driver_lib ], 'link_whole': [ test_utils_qemu_lib, test_file_wrapper_lib ] },
     { 'name': 'qemustatusxml2xmltest', 'link_with': [ test_qemu_driver_lib ], 'link_whole': [ test_utils_qemu_lib, test_file_wrapper_lib ] },
+    { 'name': 'qemumigrationcookiexmltest', 'link_with': [ test_qemu_driver_lib ], 'link_whole': [ test_utils_qemu_lib, test_file_wrapper_lib ] },
   ]
 endif

diff --git a/tests/qemumigrationcookiexmldata/basic-xml2xml-in.xml b/tests/qemumigrationcookiexmldata/basic-xml2xml-in.xml
new file mode 100644
index 0000000000..5722bafe89
--- /dev/null
+++ b/tests/qemumigrationcookiexmldata/basic-xml2xml-in.xml
@@ -0,0 +1,6 @@
+<qemu-migration>
+  <name>upstream</name>
+  <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
+  <hostname>hostname2</hostname>
+  <hostuuid>8b3f4dc4-6a8e-5f9b-94a5-4c35babd8d95</hostuuid>
+</qemu-migration>
diff --git a/tests/qemumigrationcookiexmldata/basic-xml2xml-out.xml b/tests/qemumigrationcookiexmldata/basic-xml2xml-out.xml
new file mode 100644
index 0000000000..42b351047e
--- /dev/null
+++ b/tests/qemumigrationcookiexmldata/basic-xml2xml-out.xml
@@ -0,0 +1,9 @@
+<qemu-migration>
+  <name>upstream</name>
+  <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
+  <hostname>hostname</hostname>
+  <hostuuid>4a802f00-4cba-5df6-9679-a08c4c5b577f</hostuuid>
+  <allowReboot value='default'/>
+  <capabilities>
+  </capabilities>
+</qemu-migration>
diff --git a/tests/qemumigrationcookiexmldata/modern-dom-out-dest.xml b/tests/qemumigrationcookiexmldata/modern-dom-out-dest.xml
new file mode 100644
index 0000000000..ba84c65a3d
--- /dev/null
+++ b/tests/qemumigrationcookiexmldata/modern-dom-out-dest.xml
@@ -0,0 +1,12 @@
+<qemu-migration>
+  <name>upstream</name>
+  <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
+  <hostname>hostname2</hostname>
+  <hostuuid>8b3f4dc4-6a8e-5f9b-94a5-4c35babd8d95</hostuuid>
+  <feature name='memory-hotplug'/>
+  <feature name='cpu-hotplug'/>
+  <graphics type='spice' port='5900' listen='127.0.0.1' tlsPort='-1'/>
+  <allowReboot value='yes'/>
+  <capabilities>
+  </capabilities>
+</qemu-migration>
diff --git a/tests/qemumigrationcookiexmldata/modern-dom-out-source.xml b/tests/qemumigrationcookiexmldata/modern-dom-out-source.xml
new file mode 100644
index 0000000000..ba84c65a3d
--- /dev/null
+++ b/tests/qemumigrationcookiexmldata/modern-dom-out-source.xml
@@ -0,0 +1,12 @@
+<qemu-migration>
+  <name>upstream</name>
+  <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
+  <hostname>hostname2</hostname>
+  <hostuuid>8b3f4dc4-6a8e-5f9b-94a5-4c35babd8d95</hostuuid>
+  <feature name='memory-hotplug'/>
+  <feature name='cpu-hotplug'/>
+  <graphics type='spice' port='5900' listen='127.0.0.1' tlsPort='-1'/>
+  <allowReboot value='yes'/>
+  <capabilities>
+  </capabilities>
+</qemu-migration>
diff --git a/tests/qemumigrationcookiexmltest.c b/tests/qemumigrationcookiexmltest.c
new file mode 100644
index 0000000000..d8ed8b253c
--- /dev/null
+++ b/tests/qemumigrationcookiexmltest.c
@@ -0,0 +1,336 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "testutils.h"
+
+#include "internal.h"
+#include "testutilsqemu.h"
+#include "configmake.h"
+
+#include "qemu/qemu_migration_cookie.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+static virQEMUDriver driver;
+
+static virBuffer testnamebuf = VIR_BUFFER_INITIALIZER;
+
+static const char *
+tn(const char *str, ...)
+{
+    va_list ap;
+
+    virBufferFreeAndReset(&testnamebuf);
+    virBufferAdd(&testnamebuf, str, -1);
+
+    va_start(ap, str);
+    virBufferStrcatVArgs(&testnamebuf, ap);
+    va_end(ap);
+
+    return virBufferCurrentContent(&testnamebuf);
+}
+
+
+struct testQemuMigrationCookieData {
+    const char *name;
+    char *inStatus;
+    virDomainObjPtr vm;
+
+    unsigned int cookiePopulateFlags;
+    unsigned int cookieParseFlags;
+
+    qemuMigrationParty cookiePopulateParty;
+
+    char *xmlstr;
+    int xmlstrlen;
+    char *infile;
+    char *outfile;
+};
+
+
+static int
+testQemuMigrationCookiePopulate(const void *opaque)
+{
+    struct testQemuMigrationCookieData *data = (struct testQemuMigrationCookieData *) opaque;
+    g_autoptr(qemuMigrationCookie) cookie = NULL;
+
+    if (!(cookie = qemuMigrationCookieNew(data->vm->def, NULL)))
+        return -1;
+
+    /* doctor the hostname and uuid, so that the output can be simply used for
+     * the xml2xmltest where the parser validates UUID match (yuck) */
+    g_free(cookie->localHostname);
+    cookie->localHostname = g_strdup("hostname2");
+
+    /* uuidgen --sha1 --namespace @dns --name "hostname2" */
+    if (virUUIDParse("8b3f4dc4-6a8e-5f9b-94a5-4c35babd8d95", cookie->localHostuuid) < 0) {
+        VIR_TEST_DEBUG("\nfailed to parse fake UUID");
+        return -1;
+    }
+
+    /* allow re-run for checking both miration parties */
+    g_clear_pointer(&data->xmlstr, g_free);
+
+    if (qemuMigrationCookieFormat(cookie,
+                                  &driver,
+                                  data->vm,
+                                  data->cookiePopulateParty,
+                                  &data->xmlstr,
+                                  &data->xmlstrlen,
+                                  data->cookiePopulateFlags) < 0) {
+        VIR_TEST_DEBUG("\n failed to populate and format qemu migration cookie");
+        return -1;
+    }
+
+    if (virTestCompareToFile(data->xmlstr, data->outfile) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+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))) {
+        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;
+
+    if (qemuMigrationCookieXMLFormat(&driver,
+                                     priv->qemuCaps,
+                                     &actual,
+                                     cookie) < 0) {
+        VIR_TEST_DEBUG("\nfailed to format back qemu migration cookie");
+        return -1;
+    }
+
+    if (virTestCompareToFile(virBufferCurrentContent(&actual), data->outfile) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+testQemuMigrationCookieDomInit(const void *opaque)
+{
+    struct testQemuMigrationCookieData *data = (struct testQemuMigrationCookieData *) opaque;
+
+    if (!(data->vm = virDomainObjParseFile(data->inStatus, driver.xmlopt,
+                                           VIR_DOMAIN_DEF_PARSE_STATUS |
+                                           VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
+                                           VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES |
+                                           VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE |
+                                           VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL))) {
+        VIR_TEST_DEBUG("\nfailed to parse status xml'%s'", data->inStatus);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+testQemuMigrationCookieXMLLoad(const void *opaque)
+{
+    struct testQemuMigrationCookieData *data = (struct testQemuMigrationCookieData *) opaque;
+
+    if (virTestLoadFile(data->infile, &data->xmlstr) < 0)
+        return -1;
+
+    data->xmlstrlen = strlen(data->xmlstr) + 1;
+
+    return 0;
+}
+
+
+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,
+                               unsigned int cookiePopulateFlags,
+                               unsigned int cookieParseFlags)
+{
+    struct testQemuMigrationCookieData *data = g_new0(struct testQemuMigrationCookieData, 1);
+    int ret = 0;
+
+    if (cookiePopulateFlags == 0) {
+        /* flags unsupported by default:
+         * - lockstate: internals are NULL in tests, causes crash
+         * - nbd: monitor not present
+         */
+        unsigned int cookiePopulateFlagMask = QEMU_MIGRATION_COOKIE_LOCKSTATE |
+                                              QEMU_MIGRATION_COOKIE_NBD;
+        data->cookiePopulateFlags = ~cookiePopulateFlagMask;
+    }
+
+    if (cookieParseFlags == 0)
+        data->cookieParseFlags = ~0;
+
+    data->inStatus = g_strconcat(abs_srcdir, "/", domxml, NULL);
+
+    /* load status XML as domain object */
+
+    if (virTestRun(tn("qemumigrationcookiedom2xml-load-", namesuffix, NULL),
+                   testQemuMigrationCookieDomInit, data) < 0)
+        ret = -1;
+
+    /* test dom -> migration cookie conversion for source */
+
+    data->cookiePopulateParty = QEMU_MIGRATION_SOURCE;
+    data->outfile = g_strconcat(abs_srcdir, "/qemumigrationcookiexmldata/",
+                                namesuffix, "-dom-out-source.xml", NULL);
+
+    if (virTestRun(tn("qemumigrationcookiedom2xml-source-populate-", namesuffix, NULL),
+                   testQemuMigrationCookiePopulate, data) < 0)
+        ret = -1;
+
+    /* test dom -> migration cookie conversion for destination */
+
+    g_free(data->outfile);
+    data->cookiePopulateParty = QEMU_MIGRATION_DESTINATION;
+    data->outfile = g_strconcat(abs_srcdir, "/qemumigrationcookiexmldata/",
+                                namesuffix, "-dom-out-dest.xml", NULL);
+
+    if (virTestRun(tn("qemumigrationcookiedom2xml-dest-populate-", namesuffix, NULL),
+                   testQemuMigrationCookiePopulate, data) < 0)
+        ret = -1;
+
+    testQemuMigrationCookieDataFree(data);
+
+    return ret;
+}
+
+
+static int
+testQemuMigrationCookieXML2XML(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);
+
+    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;
+
+    testQemuMigrationCookieDataFree(data);
+
+    return ret;
+}
+
+
+static int
+mymain(void)
+{
+    int ret = 0;
+    g_autoptr(virQEMUDriverConfig) cfg = NULL;
+    g_autoptr(virHashTable) capslatest = NULL;
+    g_autoptr(virConnect) conn = NULL;
+
+    capslatest = testQemuGetLatestCaps();
+    if (!capslatest)
+        return EXIT_FAILURE;
+
+    if (qemuTestDriverInit(&driver) < 0)
+        return EXIT_FAILURE;
+
+    cfg = virQEMUDriverGetConfig(&driver);
+    driver.privileged = true;
+
+    if (!(conn = virGetConnect()))
+        goto cleanup;
+
+    virSetConnectInterface(conn);
+    virSetConnectNetwork(conn);
+    virSetConnectNWFilter(conn);
+    virSetConnectNodeDev(conn);
+    virSetConnectSecret(conn);
+    virSetConnectStorage(conn);
+
+    if (testQemuMigrationCookieDom2XML("modern", "qemustatusxml2xmldata/modern-in.xml", 0, 0) < 0)
+        ret = -1;
+
+    if (testQemuMigrationCookieXML2XML("basic", "qemustatusxml2xmldata/modern-in.xml", 0) < 0)
+        ret = -1;
+
+    virBufferFreeAndReset(&testnamebuf);
+
+ cleanup:
+
+    qemuTestDriverFree(&driver);
+
+    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIR_TEST_MAIN_PRELOAD(mymain,
+                      VIR_TEST_MOCK("virpci"),
+                      VIR_TEST_MOCK("virrandom"),
+                      VIR_TEST_MOCK("domaincaps"),
+                      VIR_TEST_MOCK("hostid"))
-- 
2.26.2




More information about the libvir-list mailing list