[PATCH 00/24] qemu: Prepare for QAPIfied 'object-add'

Prepare libvirt for the changes proposed for qemu: https://www.redhat.com/archives/libvir-list/2020-November/msg01580.html Patches 1-12/24 are pure refactors and can be merged right away. Patches 13-15/24 can be merged, but the justification will be weak without the rest. Patches 16-22/24 are RFC until the qemu bits are merged. Patch 23/24 adds capabilities and needs to be udpated later Patch 24/24 is not to be merged! Note that patch 23/24 is intentionally missing from the mailing list posting as it's just a dump of QEMU capabilities from newest qemu. No need to litter the list with it. Also note that after the last patch tests will fail. See that patch for the reason. Fetch the full series at: git fetch https://gitlab.com/pipo.sk/libvirt.git object-add-qapi-3 Peter Krempa (24): qemuMonitorJSONSetMigrationParams: Take double pointer for @params qemuMonitorSetMigrationCapabilities: Take double pointer for @caps qemuMonitorJSONSetMigrationCapabilities: Refactor cleanup testQemuMonitorJSONqemuMonitorJSONGetMigrationCapabilities: refactor cleanup qemuMonitorJSONAddObject: Take double pointer for @props qemuMonitorJSONMakeCommandInternal: Clear @arguments when stolen qemuMonitorAddObject: Fix semantics of @alias qemuMonitorAddObject: Refactor cleanup util: json: Replace virJSONValueObjectSteal by virJSONValueObjectRemoveKey tests: qemuxml2argv: Don't check whether -netdev was QAPIfied repeatedly qemuBuildChrChardevStr: Rename 'flags' to 'cdevflags' testCompareXMLToArgvValidateSchema: Populate autoNodeset qemu: command: Generate commandline of 'masterKey0' secret via JSON qemu: command: Generate commandline of 'sev0' sev-guest object via JSON qemu: command: Generate commandline of iothread objects JSON qemu: capabilities: Introduce QEMU_CAPS_OBJECT_QAPIFIED tests: qemuxml2argv: Validate generation of JSON props for object-add qemu: command: Introduce raw JSON passthrough for '-object' for testing qemu: monitor: Make wrapping of 'props' of 'object-add' optional qemuMonitorCreateObjectPropsWrap: Open-code in qemuBuildMemoryBackendProps qemu: monitor: Don't add 'props' wrapper if qemu has QEMU_CAPS_OBJECT_QAPIFIED qemumonitorjsontest: Remove bomb guarding object-add qemu: capabilities: Add 6.0 capabilities with qapified object-add [DONTMERGE] qemuxml2argvtest: Force QMP validation with latest caps src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 332 +- src/qemu/qemu_migration_params.c | 22 +- src/qemu/qemu_monitor.c | 121 +- src/qemu/qemu_monitor.h | 8 +- src/qemu/qemu_monitor_json.c | 57 +- src/qemu/qemu_monitor_json.h | 6 +- src/util/virjson.c | 29 +- src/util/virqemu.c | 48 +- src/util/virqemu.h | 3 +- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 197 + .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 203 + tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 197 + .../caps_6.0.0.x86_64.replies | 32021 ++++++++++++++++ .../caps_6.0.0.x86_64.xml | 3205 ++ tests/qemumonitorjsontest.c | 40 +- ...v-missing-platform-info.x86_64-2.12.0.args | 2 +- .../launch-security-sev.x86_64-2.12.0.args | 2 +- tests/qemuxml2argvtest.c | 44 +- 20 files changed, 36202 insertions(+), 338 deletions(-) create mode 100644 tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml create mode 100644 tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml create mode 100644 tests/domaincapsdata/qemu_6.0.0.x86_64.xml create mode 100644 tests/qemucapabilitiesdata/caps_6.0.0.x86_64.replies create mode 100644 tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml -- 2.28.0

This allows simplification of the caller as well as will enable a later refactor of qemuMonitorJSONMakeCommandInternal. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_migration_params.c | 9 +++------ src/qemu/qemu_monitor.c | 11 +++-------- src/qemu/qemu_monitor.h | 2 +- src/qemu/qemu_monitor_json.c | 5 +++-- src/qemu/qemu_monitor_json.h | 2 +- 5 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index df5560d39f..d1d59aeb01 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -843,12 +843,9 @@ qemuMigrationParamsApply(virQEMUDriverPtr driver, if (!(params = qemuMigrationParamsToJSON(migParams))) goto cleanup; - if (virJSONValueObjectKeysNumber(params) > 0) { - rc = qemuMonitorSetMigrationParams(priv->mon, params); - params = NULL; - if (rc < 0) - goto cleanup; - } + if (virJSONValueObjectKeysNumber(params) > 0 && + qemuMonitorSetMigrationParams(priv->mon, ¶ms) < 0) + goto cleanup; ret = 0; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index f2ed165b22..f8287d375f 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2492,22 +2492,17 @@ qemuMonitorGetMigrationParams(qemuMonitorPtr mon, * @mon: Pointer to the monitor object. * @params: Migration parameters. * - * The @params object is consumed and should not be referenced by the caller - * after this function returns. + * The @params object is consumed and cleared. * * Returns 0 on success, -1 on error. */ int qemuMonitorSetMigrationParams(qemuMonitorPtr mon, - virJSONValuePtr params) + virJSONValuePtr *params) { - QEMU_CHECK_MONITOR_GOTO(mon, error); + QEMU_CHECK_MONITOR(mon); return qemuMonitorJSONSetMigrationParams(mon, params); - - error: - virJSONValueFree(params); - return -1; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d301568e40..c8b9111633 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -799,7 +799,7 @@ int qemuMonitorSetMigrationCacheSize(qemuMonitorPtr mon, int qemuMonitorGetMigrationParams(qemuMonitorPtr mon, virJSONValuePtr *params); int qemuMonitorSetMigrationParams(qemuMonitorPtr mon, - virJSONValuePtr params); + virJSONValuePtr *params); typedef enum { QEMU_MONITOR_MIGRATION_STATUS_INACTIVE, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 723bdb4426..bb454bf49d 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3501,12 +3501,13 @@ qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon, int qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, - virJSONValuePtr params) + virJSONValuePtr *params) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; + virJSONValuePtr par = g_steal_pointer(params); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("migrate-set-parameters", params))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("migrate-set-parameters", par))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index b588722d90..b3f3e79041 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -142,7 +142,7 @@ int qemuMonitorJSONSetMigrationCacheSize(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon, virJSONValuePtr *params); int qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, - virJSONValuePtr params); + virJSONValuePtr *params); int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, qemuMonitorMigrationStatsPtr stats, -- 2.28.0

This allows simplification of the callers. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_migration_params.c | 13 ++++--------- src/qemu/qemu_monitor.c | 11 +++-------- src/qemu/qemu_monitor.h | 2 +- src/qemu/qemu_monitor_json.c | 5 ++--- src/qemu/qemu_monitor_json.h | 2 +- tests/qemumonitorjsontest.c | 3 +-- 6 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index d1d59aeb01..8c019bf2ce 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -803,7 +803,6 @@ qemuMigrationParamsApply(virQEMUDriverPtr driver, g_autoptr(virJSONValue) caps = NULL; qemuMigrationParam xbzrle = QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE; int ret = -1; - int rc; if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) return -1; @@ -819,12 +818,9 @@ qemuMigrationParamsApply(virQEMUDriverPtr driver, if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps))) goto cleanup; - if (virJSONValueArraySize(caps) > 0) { - rc = qemuMonitorSetMigrationCapabilities(priv->mon, caps); - caps = NULL; - if (rc < 0) - goto cleanup; - } + if (virJSONValueArraySize(caps) > 0 && + qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0) + goto cleanup; } /* If QEMU is too old to support xbzrle-cache-size migration parameter, @@ -1389,8 +1385,7 @@ qemuMigrationCapsCheck(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) return -1; - rc = qemuMonitorSetMigrationCapabilities(priv->mon, json); - json = NULL; + rc = qemuMonitorSetMigrationCapabilities(priv->mon, &json); if (qemuDomainObjExitMonitor(driver, vm) < 0) return -1; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index f8287d375f..b29779f8e4 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3942,22 +3942,17 @@ qemuMonitorGetMigrationCapabilities(qemuMonitorPtr mon, * @mon: Pointer to the monitor object. * @caps: Migration capabilities. * - * The @caps object is consumed and should not be referenced by the caller - * after this function returns. + * The @caps object is consumed cleared. * * Returns 0 on success, -1 on error. */ int qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon, - virJSONValuePtr caps) + virJSONValuePtr *caps) { - QEMU_CHECK_MONITOR_GOTO(mon, error); + QEMU_CHECK_MONITOR(mon); return qemuMonitorJSONSetMigrationCapabilities(mon, caps); - - error: - virJSONValueFree(caps); - return -1; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c8b9111633..a7fba393bf 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -870,7 +870,7 @@ int qemuMonitorGetMigrationStats(qemuMonitorPtr mon, int qemuMonitorGetMigrationCapabilities(qemuMonitorPtr mon, char ***capabilities); int qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon, - virJSONValuePtr caps); + virJSONValuePtr *caps); int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon, virGICCapability **capabilities); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index bb454bf49d..fe5c26f37f 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7131,14 +7131,14 @@ qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon, int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon, - virJSONValuePtr caps) + virJSONValuePtr *caps) { int ret = -1; virJSONValuePtr cmd = NULL; virJSONValuePtr reply = NULL; cmd = qemuMonitorJSONMakeCommand("migrate-set-capabilities", - "a:capabilities", &caps, + "a:capabilities", caps, NULL); if (!cmd) goto cleanup; @@ -7151,7 +7151,6 @@ qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon, ret = 0; cleanup: - virJSONValueFree(caps); virJSONValueFree(cmd); virJSONValueFree(reply); return ret; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index b3f3e79041..9cb4ec264b 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -151,7 +151,7 @@ int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon, char ***capabilities); int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon, - virJSONValuePtr caps); + virJSONValuePtr *caps); int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon, virGICCapability **capabilities); diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 25ebf06eb0..954a074f15 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2259,8 +2259,7 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationCapabilities(const void *opaque) goto cleanup; ret = qemuMonitorJSONSetMigrationCapabilities(qemuMonitorTestGetMonitor(test), - json); - json = NULL; + &json); cleanup: virJSONValueFree(json); -- 2.28.0

Use automatic memory freeing and remove the 'cleanup' label and 'ret' variable. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor_json.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index fe5c26f37f..8fd53a565d 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7133,27 +7133,21 @@ int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon, virJSONValuePtr *caps) { - int ret = -1; - virJSONValuePtr cmd = NULL; - virJSONValuePtr reply = NULL; + g_autoptr(virJSONValue) cmd = NULL; + g_autoptr(virJSONValue) reply = NULL; - cmd = qemuMonitorJSONMakeCommand("migrate-set-capabilities", - "a:capabilities", caps, - NULL); - if (!cmd) - goto cleanup; + if (!(cmd = qemuMonitorJSONMakeCommand("migrate-set-capabilities", + "a:capabilities", caps, + NULL))) + return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) - goto cleanup; + return -1; if (qemuMonitorJSONCheckError(cmd, reply) < 0) - goto cleanup; + return -1; - ret = 0; - cleanup: - virJSONValueFree(cmd); - virJSONValueFree(reply); - return ret; + return 0; } -- 2.28.0

Use automatic memory freeing to remove the 'cleanup:' label and 'ret' variable. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemumonitorjsontest.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 954a074f15..5a3926bb11 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2217,11 +2217,10 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationCapabilities(const void *opaque) { const testGenericData *data = opaque; virDomainXMLOptionPtr xmlopt = data->xmlopt; - int ret = -1; const char *cap; - char **caps = NULL; - virBitmapPtr bitmap = NULL; - virJSONValuePtr json = NULL; + g_auto(GStrv) caps = NULL; + g_autoptr(virBitmap) bitmap = NULL; + g_autoptr(virJSONValue) json = NULL; const char *reply = "{" " \"return\": [" @@ -2240,32 +2239,26 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationCapabilities(const void *opaque) if (qemuMonitorTestAddItem(test, "query-migrate-capabilities", reply) < 0 || qemuMonitorTestAddItem(test, "migrate-set-capabilities", "{\"return\":{}}") < 0) - goto cleanup; + return -1; if (qemuMonitorGetMigrationCapabilities(qemuMonitorTestGetMonitor(test), &caps) < 0) - goto cleanup; + return -1; cap = qemuMigrationCapabilityTypeToString(QEMU_MIGRATION_CAP_XBZRLE); if (!virStringListHasString((const char **) caps, cap)) { virReportError(VIR_ERR_INTERNAL_ERROR, "Expected capability %s is missing", cap); - goto cleanup; + return -1; } bitmap = virBitmapNew(QEMU_MIGRATION_CAP_LAST); ignore_value(virBitmapSetBit(bitmap, QEMU_MIGRATION_CAP_XBZRLE)); if (!(json = qemuMigrationCapsToJSON(bitmap, bitmap))) - goto cleanup; - - ret = qemuMonitorJSONSetMigrationCapabilities(qemuMonitorTestGetMonitor(test), - &json); + return -1; - cleanup: - virJSONValueFree(json); - g_strfreev(caps); - virBitmapFree(bitmap); - return ret; + return qemuMonitorJSONSetMigrationCapabilities(qemuMonitorTestGetMonitor(test), + &json); } static int -- 2.28.0

Prepare for a refactor of qemuMonitorJSONMakeCommandInternal. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 3 +-- src/qemu/qemu_monitor_json.c | 5 +++-- src/qemu/qemu_monitor_json.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b29779f8e4..7f58c16987 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3104,8 +3104,7 @@ qemuMonitorAddObject(qemuMonitorPtr mon, if (alias) tmp = g_strdup(id); - ret = qemuMonitorJSONAddObject(mon, *props); - *props = NULL; + ret = qemuMonitorJSONAddObject(mon, props); if (alias) *alias = g_steal_pointer(&tmp); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8fd53a565d..fbcd1d8e08 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4633,12 +4633,13 @@ qemuMonitorJSONAddDevice(qemuMonitorPtr mon, int qemuMonitorJSONAddObject(qemuMonitorPtr mon, - virJSONValuePtr props) + virJSONValuePtr *props) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; + virJSONValuePtr pr = g_steal_pointer(props); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("object-add", props))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("object-add", pr))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 9cb4ec264b..d123c38812 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -246,7 +246,7 @@ int qemuMonitorJSONDelDevice(qemuMonitorPtr mon, const char *devalias); int qemuMonitorJSONAddObject(qemuMonitorPtr mon, - virJSONValuePtr props); + virJSONValuePtr *props); int qemuMonitorJSONDelObject(qemuMonitorPtr mon, const char *objalias, -- 2.28.0

All callers of qemuMonitorJSONMakeCommandInternal will benefit from making @arguments a double pointer and passing it to virJSONValueObjectCreate directly which will clear it if it steals the value. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor_json.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index fbcd1d8e08..272f7a9433 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -546,20 +546,18 @@ qemuMonitorJSONTransactionAdd(virJSONValuePtr actions, * * Create a JSON object used on the QMP monitor to call a command. * - * Note that @arguments is always consumed and should not be referenced after - * the call to this function. + * Note that @arguments is consumed and cleared. */ static virJSONValuePtr qemuMonitorJSONMakeCommandInternal(const char *cmdname, - virJSONValuePtr arguments) + virJSONValuePtr *arguments) { virJSONValuePtr ret = NULL; ignore_value(virJSONValueObjectCreate(&ret, "s:execute", cmdname, - "A:arguments", &arguments, NULL)); + "A:arguments", arguments, NULL)); - virJSONValueFree(arguments); return ret; } @@ -569,7 +567,7 @@ qemuMonitorJSONMakeCommand(const char *cmdname, ...) { virJSONValuePtr obj = NULL; - virJSONValuePtr jargs = NULL; + g_autoptr(virJSONValue) jargs = NULL; va_list args; va_start(args, cmdname); @@ -577,7 +575,7 @@ qemuMonitorJSONMakeCommand(const char *cmdname, if (virJSONValueObjectCreateVArgs(&jargs, args) < 0) goto cleanup; - obj = qemuMonitorJSONMakeCommandInternal(cmdname, jargs); + obj = qemuMonitorJSONMakeCommandInternal(cmdname, &jargs); cleanup: va_end(args); @@ -3505,9 +3503,8 @@ qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; - virJSONValuePtr par = g_steal_pointer(params); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("migrate-set-parameters", par))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("migrate-set-parameters", params))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) @@ -4024,7 +4021,7 @@ int qemuMonitorJSONAddFileHandleToSet(qemuMonitorPtr mon, return -1; } - if (!(cmd = qemuMonitorJSONMakeCommandInternal("add-fd", g_steal_pointer(&args)))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("add-fd", &args))) return -1; if (qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply) < 0) @@ -4208,9 +4205,8 @@ qemuMonitorJSONAddNetdev(qemuMonitorPtr mon, { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; - virJSONValuePtr pr = g_steal_pointer(props); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("netdev_add", pr))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("netdev_add", props))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) @@ -4637,9 +4633,8 @@ qemuMonitorJSONAddObject(qemuMonitorPtr mon, { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; - virJSONValuePtr pr = g_steal_pointer(props); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("object-add", pr))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("object-add", props))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) @@ -7506,9 +7501,8 @@ qemuMonitorJSONBlockExportAdd(qemuMonitorPtr mon, { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; - virJSONValuePtr pr = g_steal_pointer(props); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("block-export-add", pr))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("block-export-add", props))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) @@ -9036,9 +9030,8 @@ qemuMonitorJSONBlockdevAdd(qemuMonitorPtr mon, { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; - virJSONValuePtr pr = g_steal_pointer(props); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-add", pr))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-add", props))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) @@ -9057,9 +9050,8 @@ qemuMonitorJSONBlockdevReopen(qemuMonitorPtr mon, { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; - virJSONValuePtr pr = g_steal_pointer(props); - if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-reopen", pr))) + if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-reopen", props))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) -- 2.28.0

The callers of qemuMonitorAddObject rely on the fact that @alias is filled only when the object is added successfully. This is documented but the code didn't behave like that. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7f58c16987..c4fa111836 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3104,11 +3104,14 @@ qemuMonitorAddObject(qemuMonitorPtr mon, if (alias) tmp = g_strdup(id); - ret = qemuMonitorJSONAddObject(mon, props); + if (qemuMonitorJSONAddObject(mon, props) < 0) + goto cleanup; if (alias) *alias = g_steal_pointer(&tmp); + ret = 0; + cleanup: VIR_FREE(tmp); virJSONValueFree(*props); -- 2.28.0

Remove freeing/clearing of @props as the function doesn't guarantee that it happens on success, rename the variable hodling copy of the alias and use g_autofree to automatically free it and remove the cleanup label as well as 'ret' variable. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c4fa111836..b26fba303d 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3078,13 +3078,12 @@ qemuMonitorAddObject(qemuMonitorPtr mon, { const char *type = NULL; const char *id = NULL; - char *tmp = NULL; - int ret = -1; + g_autofree char *aliasCopy = NULL; if (!*props) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("object props can't be NULL")); - goto cleanup; + return -1; } type = virJSONValueObjectGetString(*props, "qom-type"); @@ -3092,31 +3091,25 @@ qemuMonitorAddObject(qemuMonitorPtr mon, VIR_DEBUG("type=%s id=%s", NULLSTR(type), NULLSTR(id)); - QEMU_CHECK_MONITOR_GOTO(mon, cleanup); + QEMU_CHECK_MONITOR(mon); if (!id || !type) { virReportError(VIR_ERR_INTERNAL_ERROR, _("missing alias or qom-type for qemu object '%s'"), NULLSTR(type)); - goto cleanup; + return -1; } if (alias) - tmp = g_strdup(id); + aliasCopy = g_strdup(id); if (qemuMonitorJSONAddObject(mon, props) < 0) - goto cleanup; + return -1; if (alias) - *alias = g_steal_pointer(&tmp); - - ret = 0; + *alias = g_steal_pointer(&aliasCopy); - cleanup: - VIR_FREE(tmp); - virJSONValueFree(*props); - *props = NULL; - return ret; + return 0; } -- 2.28.0

virJSONValueObjectRemoveKey can be used as direct replacement. Fix the one caller and remove the duplicate function. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/util/virjson.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/src/util/virjson.c b/src/util/virjson.c index 3fa9a9ca24..9b01e28eb5 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -883,30 +883,6 @@ virJSONValueObjectGet(virJSONValuePtr object, } -static virJSONValuePtr -virJSONValueObjectSteal(virJSONValuePtr object, - const char *key) -{ - size_t i; - virJSONValuePtr obj = NULL; - - if (object->type != VIR_JSON_TYPE_OBJECT) - return NULL; - - for (i = 0; i < object->data.object.npairs; i++) { - if (STREQ(object->data.object.pairs[i].key, key)) { - obj = g_steal_pointer(&object->data.object.pairs[i].value); - VIR_FREE(object->data.object.pairs[i].key); - VIR_DELETE_ELEMENT(object->data.object.pairs, i, - object->data.object.npairs); - break; - } - } - - return obj; -} - - /* Return the value associated with KEY within OBJECT, but return NULL * if the key is missing or if value is not the correct TYPE. */ virJSONValuePtr @@ -929,7 +905,10 @@ virJSONValueObjectStealByType(virJSONValuePtr object, const char *key, virJSONType type) { - virJSONValuePtr value = virJSONValueObjectSteal(object, key); + virJSONValuePtr value; + + if (virJSONValueObjectRemoveKey(object, key, &value) <= 0) + return NULL; if (value && value->type == type) return value; -- 2.28.0

Check once before looping through the args. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemuxml2argvtest.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 42d147243e..ae8eaa7768 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -524,6 +524,7 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, g_autoptr(GHashTable) schema = NULL; g_autoptr(virCommand) cmd = NULL; unsigned int parseFlags = info->parseFlags; + bool netdevQAPIfied = false; if (info->schemafile) schema = testQEMUSchemaLoad(info->schemafile); @@ -552,6 +553,8 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, if (virCommandGetArgList(cmd, &args, &nargs) < 0) return -1; + netdevQAPIfied = !virQEMUQAPISchemaPathExists("netdev_add/arg-type/type/!string", schema); + for (i = 0; i < nargs; i++) { g_auto(virBuffer) debug = VIR_BUFFER_INITIALIZER; g_autoptr(virJSONValue) jsonargs = NULL; @@ -569,13 +572,14 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, i++; } else if (STREQ(args[i], "-netdev")) { + if (!netdevQAPIfied) { + i++; + continue; + } + if (!(jsonargs = virJSONValueFromString(args[i + 1]))) return -1; - /* skip the validation for pre-QAPIfication cases */ - if (virQEMUQAPISchemaPathExists("netdev_add/arg-type/type/!string", schema)) - continue; - if (testQEMUSchemaValidateCommand("netdev_add", jsonargs, schema, false, false, &debug) < 0) { VIR_TEST_VERBOSE("failed to validate -netdev '%s' against QAPI schema: %s", -- 2.28.0

The monitor code uses 'flags' for the flags of the monitor builder, while in this function it's a different set of flags. All callers pass a variable named 'cdevflags', so rename the argument to suit. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 479bcc0b0c..f0798b5595 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4738,7 +4738,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, const virDomainChrSourceDef *dev, const char *alias, virQEMUCapsPtr qemuCaps, - unsigned int flags) + unsigned int cdevflags) { qemuDomainChrSourcePrivatePtr chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev); g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; @@ -4771,7 +4771,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, case VIR_DOMAIN_CHR_TYPE_FILE: virBufferAsprintf(&buf, "file,id=%s", charAlias); - if (qemuBuildChrChardevFileStr(flags & QEMU_BUILD_CHARDEV_FILE_LOGD ? + if (qemuBuildChrChardevFileStr(cdevflags & QEMU_BUILD_CHARDEV_FILE_LOGD ? logManager : NULL, cmd, def, &buf, "path", dev->data.file.path, @@ -4820,7 +4820,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, if (dev->data.tcp.listen) { virBufferAddLit(&buf, ",server"); - if (flags & QEMU_BUILD_CHARDEV_TCP_NOWAIT) + if (cdevflags & QEMU_BUILD_CHARDEV_TCP_NOWAIT) virBufferAddLit(&buf, ",nowait"); } @@ -4860,7 +4860,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, case VIR_DOMAIN_CHR_TYPE_UNIX: virBufferAsprintf(&buf, "socket,id=%s", charAlias); if (dev->data.nix.listen && - (flags & QEMU_BUILD_CHARDEV_UNIX_FD_PASS) && + (cdevflags & QEMU_BUILD_CHARDEV_UNIX_FD_PASS) && virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS)) { int fd; @@ -4883,7 +4883,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, } if (dev->data.nix.listen) { virBufferAddLit(&buf, ",server"); - if (flags & QEMU_BUILD_CHARDEV_TCP_NOWAIT) + if (cdevflags & QEMU_BUILD_CHARDEV_TCP_NOWAIT) virBufferAddLit(&buf, ",nowait"); } -- 2.28.0

We create a new 'vm' so we must also fake the nodeset. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemuxml2argvtest.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index ae8eaa7768..225cb70edf 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -519,6 +519,7 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, { VIR_AUTOSTRINGLIST args = NULL; g_autoptr(virDomainObj) vm = NULL; + qemuDomainObjPrivatePtr priv = NULL; size_t nargs = 0; size_t i; g_autoptr(GHashTable) schema = NULL; @@ -546,6 +547,11 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, NULL, parseFlags))) return -1; + priv = vm->privateData; + + if (virBitmapParse("0-3", &priv->autoNodeset, 4) < 0) + return -1; + if (!(cmd = testCompareXMLToArgvCreateArgs(drv, vm, migrateURI, info, flags, true))) return -1; -- 2.28.0

While the 'masterKey0' secret object will never be hotplugged we want to generate it through JSON so that we'll be able to validate all parameters of '-object' against the QAPI schema once 'object-add' is qapified in qemu. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f0798b5595..86b3c3d642 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -194,6 +194,7 @@ qemuBuildMasterKeyCommandLine(virCommandPtr cmd, g_autofree char *alias = NULL; g_autofree char *path = NULL; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; + g_autoptr(virJSONValue) props = NULL; /* If the -object secret does not exist, then just return. This just * means the domain won't be able to use a secret master key and is @@ -215,9 +216,16 @@ qemuBuildMasterKeyCommandLine(virCommandPtr cmd, if (!(path = qemuDomainGetMasterKeyFilePath(priv->libDir))) return -1; + if (qemuMonitorCreateObjectProps(&props, "secret", alias, + "s:format", "raw", + "s:file", path, + NULL) < 0) + return -1; + + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + return -1; + virCommandAddArg(cmd, "-object"); - virBufferAsprintf(&buf, "secret,id=%s,format=raw,file=", alias); - virQEMUBuildBufferEscapeComma(&buf, path); virCommandAddArgBuffer(cmd, &buf); return 0; -- 2.28.0

While the 'sev0' sev-guest object will never be hotplugged, but we want to generate it through JSON so that we'll be able to validate all parameters of '-object' against the QAPI schema once 'object-add' is qapified in qemu. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 32 +++++++++++-------- ...v-missing-platform-info.x86_64-2.12.0.args | 2 +- .../launch-security-sev.x86_64-2.12.0.args | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 86b3c3d642..feec884e85 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9341,9 +9341,11 @@ static int qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd, virDomainSEVDefPtr sev) { + g_autoptr(virJSONValue) props = NULL; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; qemuDomainObjPrivatePtr priv = vm->privateData; - char *path = NULL; + g_autofree char *dhpath = NULL; + g_autofree char *sessionpath = NULL; if (!sev) return 0; @@ -9351,21 +9353,23 @@ qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd, VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d", sev->policy, sev->cbitpos, sev->reduced_phys_bits); - virBufferAsprintf(&buf, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos); - virBufferAsprintf(&buf, ",reduced-phys-bits=%d", sev->reduced_phys_bits); - virBufferAsprintf(&buf, ",policy=0x%x", sev->policy); + if (sev->dh_cert) + dhpath = g_strdup_printf("%s/dh_cert.base64", priv->libDir); - if (sev->dh_cert) { - path = g_strdup_printf("%s/dh_cert.base64", priv->libDir); - virBufferAsprintf(&buf, ",dh-cert-file=%s", path); - VIR_FREE(path); - } + if (sev->session) + sessionpath = g_strdup_printf("%s/session.base64", priv->libDir); - if (sev->session) { - path = g_strdup_printf("%s/session.base64", priv->libDir); - virBufferAsprintf(&buf, ",session-file=%s", path); - VIR_FREE(path); - } + if (qemuMonitorCreateObjectProps(&props, "sev-guest", "sev0", + "u:cbitpos", sev->cbitpos, + "u:reduced-phys-bits", sev->reduced_phys_bits, + "u:policy", sev->policy, + "S:dh-cert-file", dhpath, + "S:session-file", sessionpath, + NULL) < 0) + return -1; + + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + return -1; virCommandAddArg(cmd, "-object"); virCommandAddArgBuffer(cmd, &buf); diff --git a/tests/qemuxml2argvdata/launch-security-sev-missing-platform-info.x86_64-2.12.0.args b/tests/qemuxml2argvdata/launch-security-sev-missing-platform-info.x86_64-2.12.0.args index 378c3b681c..9fad85737a 100644 --- a/tests/qemuxml2argvdata/launch-security-sev-missing-platform-info.x86_64-2.12.0.args +++ b/tests/qemuxml2argvdata/launch-security-sev-missing-platform-info.x86_64-2.12.0.args @@ -29,7 +29,7 @@ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \ -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \ --object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x1,\ +-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=1,\ dh-cert-file=/tmp/lib/domain--1-QEMUGuest1/dh_cert.base64,\ session-file=/tmp/lib/domain--1-QEMUGuest1/session.base64 \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ diff --git a/tests/qemuxml2argvdata/launch-security-sev.x86_64-2.12.0.args b/tests/qemuxml2argvdata/launch-security-sev.x86_64-2.12.0.args index 378c3b681c..9fad85737a 100644 --- a/tests/qemuxml2argvdata/launch-security-sev.x86_64-2.12.0.args +++ b/tests/qemuxml2argvdata/launch-security-sev.x86_64-2.12.0.args @@ -29,7 +29,7 @@ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \ -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \ --object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x1,\ +-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=1,\ dh-cert-file=/tmp/lib/domain--1-QEMUGuest1/dh_cert.base64,\ session-file=/tmp/lib/domain--1-QEMUGuest1/session.base64 \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ -- 2.28.0

The commandline generator for 'iothread' objects has a private implementation of the properties. Convert it to JSON so that it can be later validated. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index feec884e85..4dde946e82 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7137,15 +7137,19 @@ qemuBuildIOThreadCommandLine(virCommandPtr cmd, if (def->niothreadids == 0) return 0; - /* Create iothread objects using the defined iothreadids list - * and the defined id and name from the list. These may be used - * by a disk definition which will associate to an iothread by - * supplying a value of an id from the list - */ for (i = 0; i < def->niothreadids; i++) { + g_autoptr(virJSONValue) props = NULL; + g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; + g_autofree char *alias = g_strdup_printf("iothread%u", def->iothreadids[i]->iothread_id); + + if (qemuMonitorCreateObjectProps(&props, "iothread", alias, NULL) < 0) + return -1; + + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + return -1; + virCommandAddArg(cmd, "-object"); - virCommandAddArgFormat(cmd, "iothread,id=iothread%u", - def->iothreadids[i]->iothread_id); + virCommandAddArgBuffer(cmd, &buf); } return 0; -- 2.28.0

Starting from qemu-6.0 the parameters of -object/object-add are formally described by the QAPI schema. Additionally this changes the nesting of the properties as the 'props' nested object will be flattened to the parent. We'll need to detect whether qemu switched to this new approach to generate the objects with proper nesting and also allow testing. The capability is based on the presence of the 'secret' object in the 'qom-type' enum. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 538551e772..e2ee418f39 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -609,6 +609,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "ncr53c90", "dc390", "am53c974", + "object.qapified" ); @@ -1533,6 +1534,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "migrate-set-parameters/arg-type/xbzrle-cache-size", QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE }, { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT }, { "netdev_add/arg-type/+vhost-vdpa", QEMU_CAPS_NETDEV_VHOST_VDPA }, + { "object-add/arg-type/qom-type/^secret", QEMU_CAPS_OBJECT_QAPIFIED }, }; typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 0f90efa459..d942c5536d 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -589,6 +589,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_SCSI_NCR53C90, /* built-in SCSI */ QEMU_CAPS_SCSI_DC390, /* -device dc-390 */ QEMU_CAPS_SCSI_AM53C974, /* -device am53c974 */ + QEMU_CAPS_OBJECT_QAPIFIED, /* parameters for object-add are formally described */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; -- 2.28.0

Similarly to the validation for blockdev-add and netdev_add, use the qemuxml2argv test repository to drive validation of props for object-add. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemuxml2argvtest.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 225cb70edf..fafc214e57 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -526,6 +526,7 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, g_autoptr(virCommand) cmd = NULL; unsigned int parseFlags = info->parseFlags; bool netdevQAPIfied = false; + bool objectQAPIfied = false; if (info->schemafile) schema = testQEMUSchemaLoad(info->schemafile); @@ -560,6 +561,7 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, return -1; netdevQAPIfied = !virQEMUQAPISchemaPathExists("netdev_add/arg-type/type/!string", schema); + objectQAPIfied = virQEMUQAPISchemaPathExists("object-add/arg-type/qom-type/^secret", schema); for (i = 0; i < nargs; i++) { g_auto(virBuffer) debug = VIR_BUFFER_INITIALIZER; @@ -593,6 +595,24 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, return -1; } + i++; + } else if (STREQ(args[i], "-object")) { + + if (!objectQAPIfied) { + i++; + continue; + } + + if (!(jsonargs = virJSONValueFromString(args[i + 1]))) + return -1; + + if (testQEMUSchemaValidateCommand("object-add", jsonargs, + schema, false, false, &debug) < 0) { + VIR_TEST_VERBOSE("failed to validate -object '%s' against QAPI schema: %s", + args[i + 1], virBufferCurrentContent(&debug)); + return -1; + } + i++; } } -- 2.28.0

The qemu commandline builder's QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON flag disables JSON->commandline conversion so that our qemuxml2argvtest can use the commandline test repostitory for validating our JSON props generators which are in many cases used on the montitor where we need to conform to the schema. Wire this up for the -object/object-add pair by adding a flag to virQEMUBuildObjectCommandlineFromJSON to pass through JSON and pipe through the 'flags' variable where necessary. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 264 ++++++++++++++++++++++++---------------- src/util/virqemu.c | 16 ++- src/util/virqemu.h | 3 +- 3 files changed, 176 insertions(+), 107 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4dde946e82..4050e1e7af 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -189,7 +189,8 @@ VIR_ENUM_IMPL(qemuNumaPolicy, */ static int qemuBuildMasterKeyCommandLine(virCommandPtr cmd, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { g_autofree char *alias = NULL; g_autofree char *path = NULL; @@ -222,7 +223,8 @@ qemuBuildMasterKeyCommandLine(virCommandPtr cmd, NULL) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -677,6 +679,7 @@ qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo, * qemuBuildObjectSecretCommandLine: * @cmd: the command to modify * @secinfo: pointer to the secret info object + * @flags: commandline builder flags * * If the secinfo is available and associated with an AES secret, * then format the command line for the secret object. This object @@ -687,7 +690,8 @@ qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo, */ static int qemuBuildObjectSecretCommandLine(virCommandPtr cmd, - qemuDomainSecretInfoPtr secinfo) + qemuDomainSecretInfoPtr secinfo, + unsigned int flags) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; g_autoptr(virJSONValue) props = NULL; @@ -695,7 +699,8 @@ qemuBuildObjectSecretCommandLine(virCommandPtr cmd, if (qemuBuildSecretInfoProps(secinfo, &props) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -842,6 +847,7 @@ qemuBuildTLSx509BackendProps(const char *tlspath, * (optional) * @alias: TLS object alias * @qemuCaps: capabilities + * @flags: commandline builder flags * * Create the command line for a TLS object * @@ -854,7 +860,8 @@ qemuBuildTLSx509CommandLine(virCommandPtr cmd, bool verifypeer, const char *certEncSecretAlias, const char *alias, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps, + unsigned int flags) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; g_autoptr(virJSONValue) props = NULL; @@ -863,7 +870,8 @@ qemuBuildTLSx509CommandLine(virCommandPtr cmd, certEncSecretAlias, qemuCaps, &props) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -1938,14 +1946,16 @@ qemuBuildFloppyCommandLineControllerOptions(virCommandPtr cmd, static int qemuBuildObjectCommandline(virCommandPtr cmd, - virJSONValuePtr objProps) + virJSONValuePtr objProps, + unsigned int flags) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; if (!objProps) return 0; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, objProps) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, objProps, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -1957,16 +1967,17 @@ qemuBuildObjectCommandline(virCommandPtr cmd, static int qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd, - qemuBlockStorageSourceAttachDataPtr data) + qemuBlockStorageSourceAttachDataPtr data, + unsigned int flags) { char *tmp; - if (qemuBuildObjectCommandline(cmd, data->prmgrProps) < 0 || - qemuBuildObjectCommandline(cmd, data->authsecretProps) < 0 || - qemuBuildObjectCommandline(cmd, data->encryptsecretProps) < 0 || - qemuBuildObjectCommandline(cmd, data->httpcookiesecretProps) < 0 || - qemuBuildObjectCommandline(cmd, data->tlsKeySecretProps) < 0 || - qemuBuildObjectCommandline(cmd, data->tlsProps) < 0) + if (qemuBuildObjectCommandline(cmd, data->prmgrProps, flags) < 0 || + qemuBuildObjectCommandline(cmd, data->authsecretProps, flags) < 0 || + qemuBuildObjectCommandline(cmd, data->encryptsecretProps, flags) < 0 || + qemuBuildObjectCommandline(cmd, data->httpcookiesecretProps, flags) < 0 || + qemuBuildObjectCommandline(cmd, data->tlsKeySecretProps, flags) < 0 || + qemuBuildObjectCommandline(cmd, data->tlsProps, flags) < 0) return -1; if (data->driveCmd) @@ -2003,7 +2014,8 @@ qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd, static int qemuBuildDiskSourceCommandLine(virCommandPtr cmd, virDomainDiskDefPtr disk, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps, + unsigned int flags) { g_autoptr(qemuBlockStorageSourceChainData) data = NULL; g_autoptr(virJSONValue) copyOnReadProps = NULL; @@ -2029,7 +2041,8 @@ qemuBuildDiskSourceCommandLine(virCommandPtr cmd, for (i = data->nsrcdata; i > 0; i--) { if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd, - data->srcdata[i - 1]) < 0) + data->srcdata[i - 1], + flags) < 0) return -1; } @@ -2049,11 +2062,12 @@ qemuBuildDiskCommandLine(virCommandPtr cmd, const virDomainDef *def, virDomainDiskDefPtr disk, virQEMUCapsPtr qemuCaps, - unsigned int bootindex) + unsigned int bootindex, + unsigned int flags) { g_autofree char *optstr = NULL; - if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0) + if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps, flags) < 0) return -1; /* SD cards are currently instantiated via -drive if=sd, so the -device @@ -2084,7 +2098,8 @@ qemuBuildDiskCommandLine(virCommandPtr cmd, static int qemuBuildDisksCommandLine(virCommandPtr cmd, const virDomainDef *def, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps, + unsigned int flags) { size_t i; unsigned int bootCD = 0; @@ -2137,7 +2152,7 @@ qemuBuildDisksCommandLine(virCommandPtr cmd, if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) bootindex = 0; - if (qemuBuildDiskCommandLine(cmd, def, disk, qemuCaps, bootindex) < 0) + if (qemuBuildDiskCommandLine(cmd, def, disk, qemuCaps, bootindex, flags) < 0) return -1; } @@ -3204,7 +3219,8 @@ qemuBuildMemoryCellBackendStr(virDomainDefPtr def, virQEMUDriverConfigPtr cfg, size_t cell, qemuDomainObjPrivatePtr priv, - virBufferPtr buf) + virBufferPtr buf, + unsigned int flags) { g_autoptr(virJSONValue) props = NULL; g_autofree char *alias = NULL; @@ -3223,7 +3239,8 @@ qemuBuildMemoryCellBackendStr(virDomainDefPtr def, priv, def, &mem, false)) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; return rc; @@ -3235,7 +3252,8 @@ qemuBuildMemoryDimmBackendStr(virBufferPtr buf, virDomainMemoryDefPtr mem, virDomainDefPtr def, virQEMUDriverConfigPtr cfg, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { g_autoptr(virJSONValue) props = NULL; g_autofree char *alias = NULL; @@ -3252,7 +3270,8 @@ qemuBuildMemoryDimmBackendStr(virBufferPtr buf, priv, def, mem, true) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; return 0; @@ -4746,7 +4765,8 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, const virDomainChrSourceDef *dev, const char *alias, virQEMUCapsPtr qemuCaps, - unsigned int cdevflags) + unsigned int cdevflags, + unsigned int flags) { qemuDomainChrSourcePrivatePtr chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev); g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; @@ -4844,7 +4864,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, * functions can just check the config fields */ if (chrSourcePriv && chrSourcePriv->secinfo) { if (qemuBuildObjectSecretCommandLine(cmd, - chrSourcePriv->secinfo) < 0) + chrSourcePriv->secinfo, flags) < 0) return NULL; tlsCertEncSecAlias = chrSourcePriv->secinfo->s.aes.alias; @@ -4857,7 +4877,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, dev->data.tcp.listen, cfg->chardevTLSx509verify, tlsCertEncSecAlias, - objalias, qemuCaps) < 0) { + objalias, qemuCaps, flags) < 0) { return NULL; } @@ -5073,7 +5093,8 @@ static int qemuBuildHostdevSCSICommandLine(virCommandPtr cmd, const virDomainDef *def, virDomainHostdevDefPtr hostdev, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps, + unsigned int flags) { g_autoptr(qemuBlockStorageSourceAttachData) data = NULL; g_autofree char *devstr = NULL; @@ -5082,7 +5103,7 @@ qemuBuildHostdevSCSICommandLine(virCommandPtr cmd, if (!(data = qemuBuildHostdevSCSIAttachPrepare(hostdev, &backendAlias, qemuCaps))) return -1; - if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd, data) < 0) + if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd, data, flags) < 0) return -1; virCommandAddArg(cmd, "-device"); @@ -5098,7 +5119,8 @@ static int qemuBuildHostdevCommandLine(virCommandPtr cmd, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - unsigned int *bootHostdevNet) + unsigned int *bootHostdevNet, + unsigned int flags) { size_t i; @@ -5152,7 +5174,7 @@ qemuBuildHostdevCommandLine(virCommandPtr cmd, /* SCSI */ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: - if (qemuBuildHostdevSCSICommandLine(cmd, def, hostdev, qemuCaps) < 0) + if (qemuBuildHostdevSCSICommandLine(cmd, def, hostdev, qemuCaps, flags) < 0) return -1; break; @@ -5218,7 +5240,8 @@ qemuBuildMonitorCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, virQEMUDriverConfigPtr cfg, virDomainDefPtr def, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { g_autofree char *chrdev = NULL; unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT | @@ -5232,7 +5255,7 @@ qemuBuildMonitorCommandLine(virLogManagerPtr logManager, if (!(chrdev = qemuBuildChrChardevStr(logManager, secManager, cmd, cfg, def, priv->monConfig, "monitor", - priv->qemuCaps, cdevflags))) + priv->qemuCaps, cdevflags, flags))) return -1; virCommandAddArg(cmd, "-chardev"); virCommandAddArg(cmd, chrdev); @@ -5340,7 +5363,8 @@ qemuBuildRNGBackendChrdevStr(virLogManagerPtr logManager, virDomainRNGDefPtr rng, virQEMUCapsPtr qemuCaps, char **chr, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT | QEMU_BUILD_CHARDEV_UNIX_FD_PASS; @@ -5362,7 +5386,7 @@ qemuBuildRNGBackendChrdevStr(virLogManagerPtr logManager, cmd, cfg, def, rng->source.chardev, rng->info.alias, qemuCaps, - cdevflags))) + cdevflags, flags))) return -1; break; } @@ -5458,7 +5482,8 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager, virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { size_t i; @@ -5479,7 +5504,7 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager, /* possibly add character device for backend */ if (qemuBuildRNGBackendChrdevStr(logManager, secManager, cmd, cfg, def, rng, qemuCaps, &chardev, - chardevStdioLogd) < 0) + chardevStdioLogd, flags) < 0) return -1; if (chardev) @@ -5488,7 +5513,8 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager, if (qemuBuildRNGBackendProps(rng, &props) < 0) return -1; - rc = virQEMUBuildObjectCommandlineFromJSON(&buf, props); + rc = virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)); if (rc < 0) return -1; @@ -7042,7 +7068,8 @@ static int qemuBuildMemCommandLineMemoryDefaultBackend(virCommandPtr cmd, const virDomainDef *def, qemuDomainObjPrivatePtr priv, - const char *defaultRAMid) + const char *defaultRAMid, + unsigned int flags) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver); g_autoptr(virJSONValue) props = NULL; @@ -7057,7 +7084,8 @@ qemuBuildMemCommandLineMemoryDefaultBackend(virCommandPtr cmd, priv, def, &mem, false) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -7070,7 +7098,8 @@ static int qemuBuildMemCommandLine(virCommandPtr cmd, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { const char *defaultRAMid = NULL; @@ -7099,7 +7128,7 @@ qemuBuildMemCommandLine(virCommandPtr cmd, * However, if domain has one or more NUMA nodes then there is no * default RAM and we mustn't generate the memory object. */ if (!virDomainNumaGetNodeCount(def->numa)) - qemuBuildMemCommandLineMemoryDefaultBackend(cmd, def, priv, defaultRAMid); + qemuBuildMemCommandLineMemoryDefaultBackend(cmd, def, priv, defaultRAMid, flags); } else { if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) { virCommandAddArgList(cmd, "-mem-prealloc", NULL); @@ -7130,7 +7159,8 @@ qemuBuildMemCommandLine(virCommandPtr cmd, static int qemuBuildIOThreadCommandLine(virCommandPtr cmd, - const virDomainDef *def) + const virDomainDef *def, + unsigned int flags) { size_t i; @@ -7145,7 +7175,8 @@ qemuBuildIOThreadCommandLine(virCommandPtr cmd, if (qemuMonitorCreateObjectProps(&props, "iothread", alias, NULL) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -7288,7 +7319,8 @@ static int qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg, virDomainDefPtr def, virCommandPtr cmd, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { size_t i, j; virQEMUCapsPtr qemuCaps = priv->qemuCaps; @@ -7325,7 +7357,7 @@ qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg, for (i = 0; i < ncells; i++) { if ((rc = qemuBuildMemoryCellBackendStr(def, cfg, i, priv, - &nodeBackends[i])) < 0) + &nodeBackends[i], flags)) < 0) goto cleanup; if (rc == 0) @@ -7439,7 +7471,8 @@ static int qemuBuildMemoryDeviceCommandLine(virCommandPtr cmd, virQEMUDriverConfigPtr cfg, virDomainDefPtr def, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { size_t i; @@ -7449,7 +7482,7 @@ qemuBuildMemoryDeviceCommandLine(virCommandPtr cmd, g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; char *dimmStr; - if (qemuBuildMemoryDimmBackendStr(&buf, def->mems[i], def, cfg, priv) < 0) + if (qemuBuildMemoryDimmBackendStr(&buf, def->mems[i], def, cfg, priv, flags) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -7506,7 +7539,8 @@ static int qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg, virCommandPtr cmd, virQEMUCapsPtr qemuCaps, - virDomainGraphicsDefPtr graphics) + virDomainGraphicsDefPtr graphics, + unsigned int flags) { g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; virDomainGraphicsListenDefPtr glisten = NULL; @@ -7575,7 +7609,7 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg, if (gfxPriv->secinfo) { if (qemuBuildObjectSecretCommandLine(cmd, - gfxPriv->secinfo) < 0) + gfxPriv->secinfo, flags) < 0) return -1; secretAlias = gfxPriv->secinfo->s.aes.alias; } @@ -7586,7 +7620,8 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg, cfg->vncTLSx509verify, secretAlias, gfxPriv->tlsAlias, - qemuCaps) < 0) + qemuCaps, + flags) < 0) return -1; virBufferAsprintf(&opt, ",tls-creds=%s", gfxPriv->tlsAlias); @@ -7864,7 +7899,8 @@ static int qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg, virCommandPtr cmd, virDomainDefPtr def, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps, + unsigned int flags) { size_t i; @@ -7880,7 +7916,7 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg, break; case VIR_DOMAIN_GRAPHICS_TYPE_VNC: if (qemuBuildGraphicsVNCCommandLine(cfg, cmd, - qemuCaps, graphics) < 0) + qemuCaps, graphics, flags) < 0) return -1; break; @@ -7917,7 +7953,8 @@ qemuInterfaceVhostuserConnect(virQEMUDriverPtr driver, virDomainDefPtr def, virDomainNetDefPtr net, virQEMUCapsPtr qemuCaps, - char **chardev) + char **chardev, + unsigned int flags) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); @@ -7926,7 +7963,7 @@ qemuInterfaceVhostuserConnect(virQEMUDriverPtr driver, if (!(*chardev = qemuBuildChrChardevStr(logManager, secManager, cmd, cfg, def, net->data.vhostuser, - net->info.alias, qemuCaps, 0))) + net->info.alias, qemuCaps, 0, flags))) return -1; break; @@ -8054,7 +8091,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, requireNicdev = true; if (qemuInterfaceVhostuserConnect(driver, logManager, secManager, - cmd, def, net, qemuCaps, &chardev) < 0) + cmd, def, net, qemuCaps, &chardev, flags) < 0) goto cleanup; if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path, @@ -8384,7 +8421,8 @@ qemuBuildSmartcardCommandLine(virLogManagerPtr logManager, virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { size_t i; virDomainSmartcardDefPtr smartcard; @@ -8439,7 +8477,7 @@ qemuBuildSmartcardCommandLine(virLogManagerPtr logManager, cmd, cfg, def, smartcard->data.passthru, smartcard->info.alias, - qemuCaps, cdevflags))) { + qemuCaps, cdevflags, flags))) { return -1; } virCommandAddArg(cmd, "-chardev"); @@ -8574,7 +8612,8 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, virDomainDefPtr def, virDomainShmemDefPtr shmem, virQEMUCapsPtr qemuCaps, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { g_autoptr(virJSONValue) memProps = NULL; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; @@ -8621,7 +8660,8 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, if (!(memProps = qemuBuildShmemBackendMemProps(shmem))) return -1; - rc = virQEMUBuildObjectCommandlineFromJSON(&buf, memProps); + rc = virQEMUBuildObjectCommandlineFromJSON(&buf, memProps, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)); if (rc < 0) return -1; @@ -8651,7 +8691,7 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, cmd, cfg, def, &shmem->server.chr, shmem->info.alias, qemuCaps, - cdevflags); + cdevflags, flags); if (!chardev) return -1; @@ -8751,7 +8791,8 @@ qemuBuildSerialCommandLine(virLogManagerPtr logManager, virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { size_t i; bool havespice = false; @@ -8778,7 +8819,7 @@ qemuBuildSerialCommandLine(virLogManagerPtr logManager, cmd, cfg, def, serial->source, serial->info.alias, - qemuCaps, cdevflags))) + qemuCaps, cdevflags, flags))) return -1; virCommandAddArg(cmd, "-chardev"); virCommandAddArg(cmd, devstr); @@ -8815,7 +8856,8 @@ qemuBuildParallelsCommandLine(virLogManagerPtr logManager, virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { size_t i; unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT | @@ -8831,7 +8873,7 @@ qemuBuildParallelsCommandLine(virLogManagerPtr logManager, cmd, cfg, def, parallel->source, parallel->info.alias, - qemuCaps, cdevflags))) + qemuCaps, cdevflags, flags))) return -1; virCommandAddArg(cmd, "-chardev"); virCommandAddArg(cmd, devstr); @@ -8871,7 +8913,7 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager, cmd, cfg, def, channel->source, channel->info.alias, - qemuCaps, cdevflags))) + qemuCaps, cdevflags, flags))) return -1; virCommandAddArg(cmd, "-chardev"); @@ -8912,7 +8954,8 @@ qemuBuildConsoleCommandLine(virLogManagerPtr logManager, virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { size_t i; unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT | @@ -8931,7 +8974,7 @@ qemuBuildConsoleCommandLine(virLogManagerPtr logManager, cmd, cfg, def, console->source, console->info.alias, - qemuCaps, cdevflags))) + qemuCaps, cdevflags, flags))) return -1; virCommandAddArg(cmd, "-chardev"); virCommandAddArg(cmd, devstr); @@ -8946,7 +8989,7 @@ qemuBuildConsoleCommandLine(virLogManagerPtr logManager, cmd, cfg, def, console->source, console->info.alias, - qemuCaps, cdevflags))) + qemuCaps, cdevflags, flags))) return -1; virCommandAddArg(cmd, "-chardev"); virCommandAddArg(cmd, devstr); @@ -8961,7 +9004,7 @@ qemuBuildConsoleCommandLine(virLogManagerPtr logManager, cmd, cfg, def, console->source, console->info.alias, - qemuCaps, cdevflags))) + qemuCaps, cdevflags, flags))) return -1; virCommandAddArg(cmd, "-chardev"); virCommandAddArg(cmd, devstr); @@ -9043,7 +9086,8 @@ qemuBuildRedirdevCommandLine(virLogManagerPtr logManager, virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - bool chardevStdioLogd) + bool chardevStdioLogd, + unsigned int flags) { size_t i; unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT | @@ -9059,7 +9103,7 @@ qemuBuildRedirdevCommandLine(virLogManagerPtr logManager, cmd, cfg, def, redirdev->source, redirdev->info.alias, - qemuCaps, cdevflags))) { + qemuCaps, cdevflags, flags))) { return -1; } @@ -9342,8 +9386,10 @@ qemuBuildTPMsCommandLine(virCommandPtr cmd, static int -qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd, - virDomainSEVDefPtr sev) +qemuBuildSEVCommandLine(virDomainObjPtr vm, + virCommandPtr cmd, + virDomainSEVDefPtr sev, + unsigned int flags) { g_autoptr(virJSONValue) props = NULL; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; @@ -9372,7 +9418,8 @@ qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd, NULL) < 0) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -9479,7 +9526,8 @@ qemuBuildPRManagerInfoProps(virStorageSourcePtr src) static int qemuBuildManagedPRCommandLine(virCommandPtr cmd, const virDomainDef *def, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; g_autoptr(virJSONValue) props = NULL; @@ -9490,7 +9538,8 @@ qemuBuildManagedPRCommandLine(virCommandPtr cmd, if (!(props = qemuBuildPRManagedManagerInfoProps(priv))) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -9503,7 +9552,8 @@ qemuBuildManagedPRCommandLine(virCommandPtr cmd, static int qemuBuildPflashBlockdevOne(virCommandPtr cmd, virStorageSourcePtr src, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps, + unsigned int flags) { g_autoptr(qemuBlockStorageSourceChainData) data = NULL; size_t i; @@ -9514,7 +9564,8 @@ qemuBuildPflashBlockdevOne(virCommandPtr cmd, for (i = data->nsrcdata; i > 0; i--) { if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd, - data->srcdata[i - 1]) < 0) + data->srcdata[i - 1], + flags) < 0) return -1; } @@ -9524,17 +9575,18 @@ qemuBuildPflashBlockdevOne(virCommandPtr cmd, static int qemuBuildPflashBlockdevCommandLine(virCommandPtr cmd, - qemuDomainObjPrivatePtr priv) + qemuDomainObjPrivatePtr priv, + unsigned int flags) { if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) return 0; if (priv->pflash0 && - qemuBuildPflashBlockdevOne(cmd, priv->pflash0, priv->qemuCaps) < 0) + qemuBuildPflashBlockdevOne(cmd, priv->pflash0, priv->qemuCaps, flags) < 0) return -1; if (priv->pflash1 && - qemuBuildPflashBlockdevOne(cmd, priv->pflash1, priv->qemuCaps) < 0) + qemuBuildPflashBlockdevOne(cmd, priv->pflash1, priv->qemuCaps, flags) < 0) return -1; return 0; @@ -9562,7 +9614,8 @@ qemuBuildDBusVMStateInfoProps(virQEMUDriverPtr driver, static int qemuBuildDBusVMStateCommandLine(virCommandPtr cmd, virQEMUDriverPtr driver, - virDomainObjPtr vm) + virDomainObjPtr vm, + unsigned int flags) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; g_autoptr(virJSONValue) props = NULL; @@ -9579,7 +9632,8 @@ qemuBuildDBusVMStateCommandLine(virCommandPtr cmd, if (!(props = qemuBuildDBusVMStateInfoProps(driver, vm))) return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props, + (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON)) < 0) return -1; virCommandAddArg(cmd, "-object"); @@ -9820,16 +9874,16 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (!standalone) virCommandAddArg(cmd, "-S"); /* freeze CPU */ - if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0) + if (qemuBuildMasterKeyCommandLine(cmd, priv, flags) < 0) return NULL; - if (qemuBuildDBusVMStateCommandLine(cmd, driver, vm) < 0) + if (qemuBuildDBusVMStateCommandLine(cmd, driver, vm, flags) < 0) return NULL; - if (qemuBuildManagedPRCommandLine(cmd, def, priv) < 0) + if (qemuBuildManagedPRCommandLine(cmd, def, priv, flags) < 0) return NULL; - if (qemuBuildPflashBlockdevCommandLine(cmd, priv) < 0) + if (qemuBuildPflashBlockdevCommandLine(cmd, priv, flags) < 0) return NULL; if (enableFips) @@ -9848,20 +9902,20 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (!migrateURI && !snapshot && qemuDomainAlignMemorySizes(def) < 0) return NULL; - if (qemuBuildMemCommandLine(cmd, def, qemuCaps, priv) < 0) + if (qemuBuildMemCommandLine(cmd, def, qemuCaps, priv, flags) < 0) return NULL; if (qemuBuildSmpCommandLine(cmd, def, qemuCaps) < 0) return NULL; - if (qemuBuildIOThreadCommandLine(cmd, def) < 0) + if (qemuBuildIOThreadCommandLine(cmd, def, flags) < 0) return NULL; if (virDomainNumaGetNodeCount(def->numa) && - qemuBuildNumaCommandLine(cfg, def, cmd, priv) < 0) + qemuBuildNumaCommandLine(cfg, def, cmd, priv, flags) < 0) return NULL; - if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv) < 0) + if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv, flags) < 0) return NULL; virUUIDFormat(def->uuid, uuid); @@ -9900,7 +9954,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildSgaCommandLine(cmd, def) < 0) return NULL; - if (qemuBuildMonitorCommandLine(logManager, secManager, cmd, cfg, def, priv) < 0) + if (qemuBuildMonitorCommandLine(logManager, secManager, cmd, cfg, def, priv, flags) < 0) return NULL; if (qemuBuildClockCommandLine(cmd, def, qemuCaps) < 0) @@ -9928,7 +9982,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, VIR_DOMAIN_CONTROLLER_TYPE_CCID) < 0) return NULL; - if (qemuBuildDisksCommandLine(cmd, def, qemuCaps) < 0) + if (qemuBuildDisksCommandLine(cmd, def, qemuCaps, flags) < 0) return NULL; if (qemuBuildFilesystemCommandLine(cmd, def, qemuCaps, priv) < 0) @@ -9940,15 +9994,15 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, return NULL; if (qemuBuildSmartcardCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, - chardevStdioLogd) < 0) + chardevStdioLogd, flags) < 0) return NULL; if (qemuBuildSerialCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, - chardevStdioLogd) < 0) + chardevStdioLogd, flags) < 0) return NULL; if (qemuBuildParallelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, - chardevStdioLogd) < 0) + chardevStdioLogd, flags) < 0) return NULL; if (qemuBuildChannelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, @@ -9956,7 +10010,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, return NULL; if (qemuBuildConsoleCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, - chardevStdioLogd) < 0) + chardevStdioLogd, flags) < 0) return NULL; if (qemuBuildTPMsCommandLine(cmd, def, qemuCaps) < 0) @@ -9965,7 +10019,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0) return NULL; - if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps) < 0) + if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps, flags) < 0) return NULL; if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0) @@ -9978,10 +10032,10 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, return NULL; if (qemuBuildRedirdevCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, - chardevStdioLogd) < 0) + chardevStdioLogd, flags) < 0) return NULL; - if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, &bootHostdevNet) < 0) + if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, &bootHostdevNet, flags) < 0) return NULL; if (migrateURI) @@ -9991,7 +10045,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, return NULL; if (qemuBuildRNGCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, - chardevStdioLogd) < 0) + chardevStdioLogd, flags) < 0) return NULL; if (qemuBuildNVRAMCommandLine(cmd, def) < 0) @@ -10000,7 +10054,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildVMCoreInfoCommandLine(cmd, def) < 0) return NULL; - if (qemuBuildSEVCommandLine(vm, cmd, def->sev) < 0) + if (qemuBuildSEVCommandLine(vm, cmd, def->sev, flags) < 0) return NULL; if (snapshot) @@ -10026,7 +10080,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, for (i = 0; i < def->nshmems; i++) { if (qemuBuildShmemCommandLine(logManager, secManager, cmd, cfg, def, def->shmems[i], qemuCaps, - chardevStdioLogd)) + chardevStdioLogd, flags)) return NULL; } diff --git a/src/util/virqemu.c b/src/util/virqemu.c index 5405c9eac9..fd8661951a 100644 --- a/src/util/virqemu.c +++ b/src/util/virqemu.c @@ -346,14 +346,28 @@ virQEMUBuildObjectCommandlineFromJSONInternal(virBufferPtr buf, } +/** + * virQEMUBuildObjectCommandlineFromJSON: + * @buf: buffer to format output to + * @objprops: JSON object describing a qemu 'object' + * @rawjson: don't transform to commandline args, just stringify json + * + * Converts @objprops into arguments for -object. + * + * @rawjson is meant for testing of the schema in the xml2argvtest + */ int virQEMUBuildObjectCommandlineFromJSON(virBufferPtr buf, - virJSONValuePtr objprops) + virJSONValuePtr objprops, + bool rawjson) { const char *type = virJSONValueObjectGetString(objprops, "qom-type"); const char *alias = virJSONValueObjectGetString(objprops, "id"); virJSONValuePtr props = virJSONValueObjectGetObject(objprops, "props"); + if (rawjson) + return virJSONValueToBuffer(objprops, buf, false); + return virQEMUBuildObjectCommandlineFromJSONInternal(buf, type, alias, props); } diff --git a/src/util/virqemu.h b/src/util/virqemu.h index 2b33968158..ef51dcd111 100644 --- a/src/util/virqemu.h +++ b/src/util/virqemu.h @@ -54,7 +54,8 @@ virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props, bool rawjson); int virQEMUBuildObjectCommandlineFromJSON(virBufferPtr buf, - virJSONValuePtr objprops); + virJSONValuePtr objprops, + bool rawjson); char *virQEMUBuildDriveCommandlineFromJSON(virJSONValuePtr src); -- 2.28.0

Construct the JSON object which is used for object-add without the 'props' wrapper and add the wrapper only in the monitor code. This simplifies the JSON->commandline generator in the first place and also prepares for upcoming qemu where 'props' will be removed. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 68 +++++++++++++++++++++++++++++------------ src/util/virqemu.c | 42 +++++++++---------------- 2 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b26fba303d..5da3213976 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -112,6 +112,9 @@ struct _qemuMonitor { qemuMonitorReportDomainLogError logFunc; void *logOpaque; virFreeCallback logDestroy; + + /* true if qemu no longer wants 'props' sub-object of object-add */ + bool objectAddNoWrap; }; /** @@ -3010,14 +3013,12 @@ qemuMonitorCreateObjectPropsWrap(const char *type, const char *alias, virJSONValuePtr *props) { - virJSONValuePtr ret; - ignore_value(virJSONValueObjectCreate(&ret, - "s:qom-type", type, - "s:id", alias, - "A:props", props, - NULL)); - return ret; + if (virJSONValueObjectPrependString(*props, "id", alias) < 0 || + virJSONValueObjectPrependString(*props, "qom-type", type)) + return NULL; + + return g_steal_pointer(props); } @@ -3037,26 +3038,28 @@ qemuMonitorCreateObjectProps(virJSONValuePtr *propsret, const char *alias, ...) { - virJSONValuePtr props = NULL; - int ret = -1; + g_autoptr(virJSONValue) props = NULL; + int rc; va_list args; - *propsret = NULL; + if (virJSONValueObjectCreate(&props, + "s:qom-type", type, + "s:id", alias, + NULL) < 0) + return -1; + va_start(args, alias); - if (virJSONValueObjectCreateVArgs(&props, args) < 0) - goto cleanup; + rc = virJSONValueObjectAddVArgs(props, args); - if (!(*propsret = qemuMonitorCreateObjectPropsWrap(type, alias, &props))) - goto cleanup; + va_end(args); - ret = 0; + if (rc < 0) + return -1; - cleanup: - virJSONValueFree(props); - va_end(args); - return ret; + *propsret = g_steal_pointer(&props); + return 0; } @@ -3076,6 +3079,7 @@ qemuMonitorAddObject(qemuMonitorPtr mon, virJSONValuePtr *props, char **alias) { + g_autoptr(virJSONValue) pr = NULL; const char *type = NULL; const char *id = NULL; g_autofree char *aliasCopy = NULL; @@ -3103,7 +3107,31 @@ qemuMonitorAddObject(qemuMonitorPtr mon, if (alias) aliasCopy = g_strdup(id); - if (qemuMonitorJSONAddObject(mon, props) < 0) + if (mon->objectAddNoWrap) { + pr = g_steal_pointer(props); + } else { + /* we need to create a wrapper which has the 'qom-type' and 'id' and + * store everything else under a 'props' sub-object */ + g_autoptr(virJSONValue) typeobj = NULL; + g_autoptr(virJSONValue) idobj = NULL; + + ignore_value(virJSONValueObjectRemoveKey(*props, "qom-type", &typeobj)); + ignore_value(virJSONValueObjectRemoveKey(*props, "id", &idobj)); + + if (!virJSONValueObjectGetKey(*props, 0)) { + virJSONValueFree(*props); + *props = NULL; + } + + if (virJSONValueObjectCreate(&pr, + "s:qom-type", type, + "s:id", id, + "A:props", props, + NULL) < 0) + return -1; + } + + if (qemuMonitorJSONAddObject(mon, &pr) < 0) return -1; if (alias) diff --git a/src/util/virqemu.c b/src/util/virqemu.c index fd8661951a..8a705b79a0 100644 --- a/src/util/virqemu.c +++ b/src/util/virqemu.c @@ -320,32 +320,6 @@ virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props, } -static int -virQEMUBuildObjectCommandlineFromJSONInternal(virBufferPtr buf, - const char *type, - const char *alias, - virJSONValuePtr props) -{ - if (!type || !alias) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("missing 'type'(%s) or 'alias'(%s) field of QOM 'object'"), - NULLSTR(type), NULLSTR(alias)); - return -1; - } - - virBufferAsprintf(buf, "%s,id=%s", type, alias); - - if (props) { - virBufferAddLit(buf, ","); - if (virQEMUBuildCommandLineJSON(props, buf, NULL, false, - virQEMUBuildCommandLineJSONArrayBitmap) < 0) - return -1; - } - - return 0; -} - - /** * virQEMUBuildObjectCommandlineFromJSON: * @buf: buffer to format output to @@ -363,12 +337,24 @@ virQEMUBuildObjectCommandlineFromJSON(virBufferPtr buf, { const char *type = virJSONValueObjectGetString(objprops, "qom-type"); const char *alias = virJSONValueObjectGetString(objprops, "id"); - virJSONValuePtr props = virJSONValueObjectGetObject(objprops, "props"); + + if (!type || !alias) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing 'type'(%s) or 'alias'(%s) field of QOM 'object'"), + NULLSTR(type), NULLSTR(alias)); + return -1; + } if (rawjson) return virJSONValueToBuffer(objprops, buf, false); - return virQEMUBuildObjectCommandlineFromJSONInternal(buf, type, alias, props); + virBufferAsprintf(buf, "%s,", type); + + if (virQEMUBuildCommandLineJSON(objprops, buf, "qom-type", false, + virQEMUBuildCommandLineJSONArrayBitmap) < 0) + return -1; + + return 0; } -- 2.28.0

There's just one caller left. Since qemuBuildMemoryBackendProps is too complex to be modified for now, just move the adding of 'id' and 'qom' type directly into the function. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 6 ++++-- src/qemu/qemu_monitor.c | 15 --------------- src/qemu/qemu_monitor.h | 4 ---- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4050e1e7af..e21cbb451e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3206,10 +3206,12 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps, rc = 0; } - if (!(*backendProps = qemuMonitorCreateObjectPropsWrap(backendType, alias, - &props))) + if (virJSONValueObjectPrependString(props, "id", alias) < 0 || + virJSONValueObjectPrependString(props, "qom-type", backendType) < 0) return -1; + *backendProps = g_steal_pointer(&props); + return rc; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 5da3213976..e0eee3ce9e 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3008,21 +3008,6 @@ qemuMonitorAddDeviceArgs(qemuMonitorPtr mon, } -virJSONValuePtr -qemuMonitorCreateObjectPropsWrap(const char *type, - const char *alias, - virJSONValuePtr *props) -{ - - if (virJSONValueObjectPrependString(*props, "id", alias) < 0 || - virJSONValueObjectPrependString(*props, "qom-type", type)) - return NULL; - - return g_steal_pointer(props); -} - - - /** * qemuMonitorCreateObjectProps: * @propsret: returns full object properties diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a7fba393bf..e02e131e3b 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1009,10 +1009,6 @@ int qemuMonitorAddDeviceWithFd(qemuMonitorPtr mon, int qemuMonitorDelDevice(qemuMonitorPtr mon, const char *devalias); -virJSONValuePtr qemuMonitorCreateObjectPropsWrap(const char *type, - const char *alias, - virJSONValuePtr *props); - int qemuMonitorCreateObjectProps(virJSONValuePtr *propsret, const char *type, const char *alias, -- 2.28.0

Set 'objectAddNoWrap' when the capability is present. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index e0eee3ce9e..145c03413f 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -32,6 +32,7 @@ #include "qemu_monitor_json.h" #include "qemu_domain.h" #include "qemu_process.h" +#include "qemu_capabilities.h" #include "virerror.h" #include "viralloc.h" #include "virlog.h" @@ -676,6 +677,7 @@ qemuMonitorOpenInternal(virDomainObjPtr vm, qemuMonitorCallbacksPtr cb, void *opaque) { + qemuDomainObjPrivatePtr priv = vm->privateData; qemuMonitorPtr mon; g_autoptr(GError) gerr = NULL; @@ -708,6 +710,9 @@ qemuMonitorOpenInternal(virDomainObjPtr vm, mon->cb = cb; mon->callbackOpaque = opaque; + if (priv) + mon->objectAddNoWrap = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_QAPIFIED); + if (virSetCloseExec(mon->fd) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to set monitor close-on-exec flag")); -- 2.28.0

Libvirt is now prepared for QAPIfied object-add. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemumonitorjsontest.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 5a3926bb11..47c909fd7a 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2906,20 +2906,6 @@ testQAPISchemaObjectDeviceAdd(const void *opaque) return -1; } - if (virQEMUQAPISchemaPathGet("object-add/arg-type", schema, &entry) < 0) { - fprintf(stderr, "schema for 'objectadd' not found\n"); - return -1; - } - - if (testQEMUSchemaEntryMatchTemplate(entry, - "str:qom-type", - "str:id", - "any:props", - NULL) < 0) { - VIR_TEST_VERBOSE("object-add has unexpected members in schema"); - return -1; - } - return 0; } -- 2.28.0

Note that it's expected that the 'vxhs' and 'sev-guest' test cases fail as this overrides just the QMP schema but not the qemu capabilities which result in enabling the features that are missing. --- tests/qemuxml2argvtest.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index fafc214e57..a73408c029 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -531,9 +531,9 @@ testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv, if (info->schemafile) schema = testQEMUSchemaLoad(info->schemafile); - /* comment out with line comment to enable schema checking for non _CAPS tests - if (!schema) - schema = testQEMUSchemaLoadLatest(virArchToString(info->arch)); +// /* comment out with line comment to enable schema checking for non _CAPS tests +// if (!schema) + schema = testQEMUSchemaLoadLatest("x86_64"); // */ if (!schema) -- 2.28.0
participants (1)
-
Peter Krempa