qemu: Call migrate-incoming with exit-on-error=false

The exit-on-error=false argument of migrate-incoming tells the QEMU
process to keep running when incoming migration fails, which helps us in
two ways:

1. When migration enters Finish phase to cleanup the process, the domain
   might not even exist on the destination (because it has already been
   cleaned up by EOF monitor callback) and we would get rather unhelpful
   "operation failed: domain is no longer running" error message.

2. We can get the error that caused incoming migration to fail directly
   from QEMU via query-migrate QMP command.

https://issues.redhat.com/browse/RHEL-7041

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Jiri Denemark 2024-12-10 12:28:53 +01:00
parent 090a2f27c2
commit 060fd63c26
5 changed files with 20 additions and 7 deletions

View File

@ -2378,11 +2378,18 @@ qemuMigrationDstRun(virDomainObj *vm,
const char *uri, const char *uri,
virDomainAsyncJob asyncJob) virDomainAsyncJob asyncJob)
{ {
virTristateBool exitOnError = VIR_TRISTATE_BOOL_ABSENT;
qemuDomainObjPrivate *priv = vm->privateData; qemuDomainObjPrivate *priv = vm->privateData;
int rv; int rv;
VIR_DEBUG("Setting up incoming migration with URI %s", uri); VIR_DEBUG("Setting up incoming migration with URI %s", uri);
/* Ask QEMU not to exit on failure during incoming migration (if supported)
* so that we can properly check and report error during Finish phase.
*/
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR))
exitOnError = VIR_TRISTATE_BOOL_NO;
if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
return -1; return -1;
@ -2390,7 +2397,7 @@ qemuMigrationDstRun(virDomainObj *vm,
if (rv < 0) if (rv < 0)
goto exit_monitor; goto exit_monitor;
rv = qemuMonitorMigrateIncoming(priv->mon, uri); rv = qemuMonitorMigrateIncoming(priv->mon, uri, exitOnError);
exit_monitor: exit_monitor:
qemuDomainObjExitMonitor(vm); qemuDomainObjExitMonitor(vm);

View File

@ -3811,13 +3811,15 @@ qemuMonitorGetMemoryDeviceInfo(qemuMonitor *mon,
int int
qemuMonitorMigrateIncoming(qemuMonitor *mon, qemuMonitorMigrateIncoming(qemuMonitor *mon,
const char *uri) const char *uri,
virTristateBool exitOnError)
{ {
VIR_DEBUG("uri=%s", uri); VIR_DEBUG("uri=%s, exitOnError=%s",
uri, virTristateBoolTypeToString(exitOnError));
QEMU_CHECK_MONITOR(mon); QEMU_CHECK_MONITOR(mon);
return qemuMonitorJSONMigrateIncoming(mon, uri); return qemuMonitorJSONMigrateIncoming(mon, uri, exitOnError);
} }

View File

@ -1294,7 +1294,8 @@ int qemuMonitorGetMemoryDeviceInfo(qemuMonitor *mon,
ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(2);
int qemuMonitorMigrateIncoming(qemuMonitor *mon, int qemuMonitorMigrateIncoming(qemuMonitor *mon,
const char *uri); const char *uri,
virTristateBool exitOnError);
int qemuMonitorMigrateStartPostCopy(qemuMonitor *mon); int qemuMonitorMigrateStartPostCopy(qemuMonitor *mon);

View File

@ -7269,13 +7269,15 @@ qemuMonitorJSONFindLinkPath(qemuMonitor *mon,
int int
qemuMonitorJSONMigrateIncoming(qemuMonitor *mon, qemuMonitorJSONMigrateIncoming(qemuMonitor *mon,
const char *uri) const char *uri,
virTristateBool exitOnError)
{ {
g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) cmd = NULL;
g_autoptr(virJSONValue) reply = NULL; g_autoptr(virJSONValue) reply = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("migrate-incoming", if (!(cmd = qemuMonitorJSONMakeCommand("migrate-incoming",
"s:uri", uri, "s:uri", uri,
"T:exit-on-error", exitOnError,
NULL))) NULL)))
return -1; return -1;

View File

@ -607,7 +607,8 @@ qemuMonitorJSONFindLinkPath(qemuMonitor *mon,
int int
qemuMonitorJSONMigrateIncoming(qemuMonitor *mon, qemuMonitorJSONMigrateIncoming(qemuMonitor *mon,
const char *uri) const char *uri,
virTristateBool exitOnError)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int int