const char *uri,
virDomainAsyncJob asyncJob)
{
+ virTristateBool exitOnError = VIR_TRISTATE_BOOL_ABSENT;
qemuDomainObjPrivate *priv = vm->privateData;
int rv;
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)
return -1;
if (rv < 0)
goto exit_monitor;
- rv = qemuMonitorMigrateIncoming(priv->mon, uri);
+ rv = qemuMonitorMigrateIncoming(priv->mon, uri, exitOnError);
exit_monitor:
qemuDomainObjExitMonitor(vm);
int
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);
- return qemuMonitorJSONMigrateIncoming(mon, uri);
+ return qemuMonitorJSONMigrateIncoming(mon, uri, exitOnError);
}
ATTRIBUTE_NONNULL(2);
int qemuMonitorMigrateIncoming(qemuMonitor *mon,
- const char *uri);
+ const char *uri,
+ virTristateBool exitOnError);
int qemuMonitorMigrateStartPostCopy(qemuMonitor *mon);
int
qemuMonitorJSONMigrateIncoming(qemuMonitor *mon,
- const char *uri)
+ const char *uri,
+ virTristateBool exitOnError)
{
g_autoptr(virJSONValue) cmd = NULL;
g_autoptr(virJSONValue) reply = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("migrate-incoming",
"s:uri", uri,
+ "T:exit-on-error", exitOnError,
NULL)))
return -1;
int
qemuMonitorJSONMigrateIncoming(qemuMonitor *mon,
- const char *uri)
+ const char *uri,
+ virTristateBool exitOnError)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int