qemu: new function to retrieve migration blocker reasons from QEMU

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 <eperezma@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
This commit is contained in:
Eugenio Pérez 2022-07-20 18:05:47 +02:00 committed by Laine Stump
parent 1e9d84d9f9
commit 7e52c4839f
4 changed files with 65 additions and 0 deletions

View File

@ -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);
}

View File

@ -1543,3 +1543,7 @@ qemuMonitorChangeMemoryRequestedSize(qemuMonitor *mon,
int
qemuMonitorMigrateRecover(qemuMonitor *mon,
const char *uri);
int
qemuMonitorGetMigrationBlockers(qemuMonitor *mon,
char ***blockers);

View File

@ -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);

View File

@ -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);