From 7e52c4839fabac2d19c6f22c99142e992e3d898e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Eugenio=20P=C3=A9rez?= Date: Wed, 20 Jul 2022 18:05:47 +0200 Subject: [PATCH] qemu: new function to retrieve migration blocker reasons from QEMU MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Since QEMU 6.0, if migration is blocked for some reason, 'query-migrate' will return an array of error strings describing the migration blockers. This can be used to check whether there are any devices, or other conditions, that would cause migration to fail. This patch adds a function that sends this query via a QMP command and returns the resulting array of reasons. qemuMigrationSrcIsAllowed() will be able to use the new function to ask QEMU for migration blockers, instead of the hardcoded guesses that libvirt currently has. Signed-off-by: Eugenio Pérez Reviewed-by: Jiri Denemark Reviewed-by: Laine Stump --- src/qemu/qemu_monitor.c | 12 ++++++++++ src/qemu/qemu_monitor.h | 4 ++++ src/qemu/qemu_monitor_json.c | 46 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 3 +++ 4 files changed, 65 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 109107eaae..9687746703 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4486,3 +4486,15 @@ qemuMonitorMigrateRecover(qemuMonitor *mon, return qemuMonitorJSONMigrateRecover(mon, uri); } + + +int +qemuMonitorGetMigrationBlockers(qemuMonitor *mon, + char ***blockers) +{ + VIR_DEBUG("blockers=%p", blockers); + + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONGetMigrationBlockers(mon, blockers); +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index cc1a0bc8c9..b82f198285 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1543,3 +1543,7 @@ qemuMonitorChangeMemoryRequestedSize(qemuMonitor *mon, int qemuMonitorMigrateRecover(qemuMonitor *mon, const char *uri); + +int +qemuMonitorGetMigrationBlockers(qemuMonitor *mon, + char ***blockers); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 5e4a86e5ad..941596563a 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3338,6 +3338,52 @@ int qemuMonitorJSONMigrate(qemuMonitor *mon, return 0; } + +/* + * Get the exposed migration blockers. + * + * This function assume qemu has the capability of request them. + * + * It returns a NULL terminated array on blockers if there are any, or it set + * it to NULL otherwise. + */ +int +qemuMonitorJSONGetMigrationBlockers(qemuMonitor *mon, + char ***blockers) +{ + g_autoptr(virJSONValue) cmd = NULL; + g_autoptr(virJSONValue) reply = NULL; + virJSONValue *data; + virJSONValue *jblockers; + size_t i; + + *blockers = NULL; + if (!(cmd = qemuMonitorJSONMakeCommand("query-migrate", NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0) + return -1; + + data = virJSONValueObjectGetObject(reply, "return"); + + if (!(jblockers = virJSONValueObjectGetArray(data, "blocked-reasons"))) + return 0; + + *blockers = g_new0(char *, virJSONValueArraySize(jblockers) + 1); + for (i = 0; i < virJSONValueArraySize(jblockers); i++) { + virJSONValue *jblocker = virJSONValueArrayGet(jblockers, i); + const char *blocker = virJSONValueGetString(jblocker); + + (*blockers)[i] = g_strdup(blocker); + } + + return 0; +} + + int qemuMonitorJSONMigrateCancel(qemuMonitor *mon) { g_autoptr(virJSONValue) cmd = qemuMonitorJSONMakeCommand("migrate_cancel", NULL); diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 2759566892..e4c65e250e 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -184,6 +184,9 @@ qemuMonitorJSONMigrate(qemuMonitor *mon, unsigned int flags, const char *uri); int +qemuMonitorJSONGetMigrationBlockers(qemuMonitor *mon, + char ***blockers); +int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitor *mon, bool *spice_migrated); -- 2.47.3