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: