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@xxxxxxxxxx> --- 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