diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index 77abc7191f..548bb1c0dd 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -591,6 +591,53 @@ qemuMigrationParamsToJSON(qemuMigrationParamsPtr migParams) } +virJSONValuePtr +qemuMigrationCapsToJSON(virBitmapPtr caps, + virBitmapPtr states) +{ + virJSONValuePtr json = NULL; + virJSONValuePtr cap = NULL; + qemuMonitorMigrationCaps bit; + const char *name; + + if (!(json = virJSONValueNewArray())) + return NULL; + + for (bit = 0; bit < QEMU_MONITOR_MIGRATION_CAPS_LAST; bit++) { + bool supported = false; + bool state = false; + + ignore_value(virBitmapGetBit(caps, bit, &supported)); + if (!supported) + continue; + + ignore_value(virBitmapGetBit(states, bit, &state)); + + if (!(cap = virJSONValueNewObject())) + goto error; + + name = qemuMonitorMigrationCapsTypeToString(bit); + if (virJSONValueObjectAppendString(cap, "capability", name) < 0) + goto error; + + if (virJSONValueObjectAppendBoolean(cap, "state", state) < 0) + goto error; + + if (virJSONValueArrayAppend(json, cap) < 0) + goto error; + + cap = NULL; + } + + return json; + + error: + virJSONValueFree(json); + virJSONValueFree(cap); + return NULL; +} + + /** * qemuMigrationParamsApply * @driver: qemu driver @@ -611,6 +658,7 @@ qemuMigrationParamsApply(virQEMUDriverPtr driver, qemuDomainObjPrivatePtr priv = vm->privateData; bool xbzrleCacheSize_old = false; virJSONValuePtr params = NULL; + virJSONValuePtr caps = NULL; qemuMigrationParam xbzrle = QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE; int ret = -1; int rc; @@ -618,10 +666,16 @@ qemuMigrationParamsApply(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) return -1; - if (qemuMonitorSetMigrationCapabilities(priv->mon, priv->migrationCaps, - migParams->caps) < 0) + 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 QEMU is too old to support xbzrle-cache-size migration parameter, * we need to set it via migrate-set-cache-size and tell * qemuMonitorSetMigrationParams to ignore this parameter. @@ -974,6 +1028,7 @@ qemuMigrationCapsCheck(virQEMUDriverPtr driver, { qemuDomainObjPrivatePtr priv = vm->privateData; virBitmapPtr migEvent = NULL; + virJSONValuePtr json = NULL; char **caps = NULL; char **capStr; int ret = -1; @@ -1014,10 +1069,14 @@ qemuMigrationCapsCheck(virQEMUDriverPtr driver, ignore_value(virBitmapSetBit(migEvent, QEMU_MONITOR_MIGRATION_CAPS_EVENTS)); + if (!(json = qemuMigrationCapsToJSON(migEvent, migEvent))) + goto cleanup; + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) goto cleanup; - rc = qemuMonitorSetMigrationCapabilities(priv->mon, migEvent, migEvent); + rc = qemuMonitorSetMigrationCapabilities(priv->mon, json); + json = NULL; if (qemuDomainObjExitMonitor(driver, vm) < 0) goto cleanup; @@ -1039,6 +1098,7 @@ qemuMigrationCapsCheck(virQEMUDriverPtr driver, ret = 0; cleanup: + virJSONValueFree(json); virStringListFree(caps); return ret; } diff --git a/src/qemu/qemu_migration_paramspriv.h b/src/qemu/qemu_migration_paramspriv.h index 350973b6f9..30773a679d 100644 --- a/src/qemu/qemu_migration_paramspriv.h +++ b/src/qemu/qemu_migration_paramspriv.h @@ -28,4 +28,8 @@ qemuMigrationParamsToJSON(qemuMigrationParamsPtr migParams); qemuMigrationParamsPtr qemuMigrationParamsFromJSON(virJSONValuePtr params); +virJSONValuePtr +qemuMigrationCapsToJSON(virBitmapPtr caps, + virBitmapPtr states); + #endif /* __QEMU_MIGRATION_PARAMSPRIV_H__ */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 108d934444..50036919c4 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3957,22 +3957,27 @@ qemuMonitorGetMigrationCapabilities(qemuMonitorPtr mon, } +/** + * qemuMonitorSetMigrationCapabilities: + * @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. + * + * Returns 0 on success, -1 on error. + */ int qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon, - virBitmapPtr caps, - virBitmapPtr states) + virJSONValuePtr caps) { - char *capsStr = virBitmapFormat(caps); - char *statesStr = virBitmapFormat(states); + QEMU_CHECK_MONITOR_JSON_GOTO(mon, error); - VIR_DEBUG("caps=%s, states=%s", NULLSTR(capsStr), NULLSTR(statesStr)); + return qemuMonitorJSONSetMigrationCapabilities(mon, caps); - VIR_FREE(capsStr); - VIR_FREE(statesStr); - - QEMU_CHECK_MONITOR_JSON(mon); - - return qemuMonitorJSONSetMigrationCapabilities(mon, caps, states); + error: + virJSONValueFree(caps); + return -1; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a77ad00d16..e444d0a068 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -728,8 +728,7 @@ VIR_ENUM_DECL(qemuMonitorMigrationCaps); int qemuMonitorGetMigrationCapabilities(qemuMonitorPtr mon, char ***capabilities); int qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon, - virBitmapPtr caps, - virBitmapPtr states); + 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 b00bca7d46..7fd8e756b3 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6111,47 +6111,14 @@ qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon, int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon, - virBitmapPtr caps, - virBitmapPtr states) + virJSONValuePtr caps) { int ret = -1; - qemuMonitorMigrationCaps bit; virJSONValuePtr cmd = NULL; virJSONValuePtr reply = NULL; - virJSONValuePtr cap = NULL; - virJSONValuePtr array; - - if (!(array = virJSONValueNewArray())) - goto cleanup; - - for (bit = 0; bit < QEMU_MONITOR_MIGRATION_CAPS_LAST; bit++) { - bool supported = false; - bool state = false; - - ignore_value(virBitmapGetBit(caps, bit, &supported)); - if (!supported) - continue; - - ignore_value(virBitmapGetBit(states, bit, &state)); - - if (!(cap = virJSONValueNewObject())) - goto cleanup; - - if (virJSONValueObjectAppendString(cap, "capability", - qemuMonitorMigrationCapsTypeToString(bit)) < 0) - goto cleanup; - - if (virJSONValueObjectAppendBoolean(cap, "state", state) < 0) - goto cleanup; - - if (virJSONValueArrayAppend(array, cap) < 0) - goto cleanup; - - cap = NULL; - } cmd = qemuMonitorJSONMakeCommand("migrate-set-capabilities", - "a:capabilities", &array, + "a:capabilities", &caps, NULL); if (!cmd) goto cleanup; @@ -6164,8 +6131,7 @@ qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon, ret = 0; cleanup: - virJSONValueFree(array); - virJSONValueFree(cap); + 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 5ada38b9fa..c6ad83af4c 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -146,8 +146,7 @@ int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon, char ***capabilities); int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon, - virBitmapPtr caps, - virBitmapPtr states); + virJSONValuePtr caps); int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon, virGICCapability **capabilities); diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index dafcccebad..697126f298 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -32,6 +32,7 @@ #include "virstring.h" #include "cpu/cpu.h" #include "qemu/qemu_monitor.h" +#include "qemu/qemu_migration_paramspriv.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -2141,6 +2142,7 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationCapabilities(const void *data) const char *cap; char **caps = NULL; virBitmapPtr bitmap = NULL; + virJSONValuePtr json = NULL; const char *reply = "{" " \"return\": [" @@ -2176,12 +2178,15 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationCapabilities(const void *data) goto cleanup; ignore_value(virBitmapSetBit(bitmap, QEMU_MONITOR_MIGRATION_CAPS_XBZRLE)); - if (qemuMonitorJSONSetMigrationCapabilities(qemuMonitorTestGetMonitor(test), - bitmap, bitmap) < 0) + if (!(json = qemuMigrationCapsToJSON(bitmap, bitmap))) goto cleanup; - ret = 0; + ret = qemuMonitorJSONSetMigrationCapabilities(qemuMonitorTestGetMonitor(test), + json); + json = NULL; + cleanup: + virJSONValueFree(json); qemuMonitorTestFree(test); virStringListFree(caps); virBitmapFree(bitmap);