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 @@
+
+ migr
+ 10b01607-0323-486b-afe2-3014a8a5b98b
+ sourcehost
+ 1f5e0da0-fecf-413f-9bf1-1aa9c21e71e4
+
+
+
+
+
+
+ EPYC-Rome
+ AMD
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+ migr
+ 10b01607-0323-486b-afe2-3014a8a5b98b
+ hostname
+ 4a802f00-4cba-5df6-9679-a08c4c5b577f
+
+
+
+
+
+ EPYC-Rome
+ AMD
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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: