The QEMU process is already running, all we need to do is to call
migrate-recover QMP command. Except for some checks and cookie handling,
of course.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_migration.c | 99 +++++++++++++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 2e9235e1d5..a8481f7515 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3509,6 +3509,98 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
}
+static int
+qemuMigrationDstPrepareResume(virQEMUDriver *driver,
+ virConnectPtr conn,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
+ virDomainDef *def,
+ const char *origname,
+ const char *protocol,
+ unsigned short port,
+ const char *listenAddress,
+ unsigned long flags)
+{
+ g_autoptr(qemuMigrationCookie) mig = NULL;
+ qemuProcessIncomingDef *incoming = NULL;
+ qemuDomainObjPrivate *priv;
+ virDomainJobStatus status;
+ virDomainObj *vm;
+ int ret = -1;
+
+ VIR_DEBUG("name=%s, origname=%s, protocol=%s, port=%hu, "
+ "listenAddress=%s, flags=0x%lx",
+ def->name, NULLSTR(origname), protocol, port,
+ NULLSTR(listenAddress), flags);
+
+ vm = virDomainObjListFindByName(driver->domains, def->name);
+ if (!vm) {
+ virReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching name '%s'"),
def->name);
+ qemuMigrationDstErrorReport(driver, def->name);
+ return -1;
+ }
+ priv = vm->privateData;
+
+ if (!qemuMigrationAnyCanResume(vm, VIR_ASYNC_JOB_MIGRATION_IN, flags,
+ QEMU_MIGRATION_PHASE_POSTCOPY_FAILED))
+ goto cleanup;
+
+ if (qemuMigrationJobStartPhase(vm, QEMU_MIGRATION_PHASE_PREPARE_RESUME) < 0)
+ goto cleanup;
+
+ qemuDomainCleanupRemove(vm, qemuProcessCleanupMigrationJob);
+
+ if (qemuMigrationAnyRefreshStatus(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
+ &status) < 0)
+ goto cleanup;
+
+ if (status != VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("QEMU reports migration is still running"));
+ goto cleanup;
+ }
+
+ if (!(mig = qemuMigrationCookieParse(driver, def, origname, NULL,
+ cookiein, cookieinlen,
+ QEMU_MIGRATION_COOKIE_CAPS)))
+ goto cleanup;
+
+ if (!(incoming = qemuMigrationDstPrepare(vm, false, protocol,
+ listenAddress, port, -1)))
+ goto cleanup;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN) < 0)
+ goto cleanup;
+
+ ret = qemuMonitorMigrateRecover(priv->mon, incoming->uri);
+ qemuDomainObjExitMonitor(vm);
+
+ if (ret < 0)
+ goto cleanup;
+
+ if (qemuMigrationCookieFormat(mig, driver, vm,
+ QEMU_MIGRATION_DESTINATION,
+ cookieout, cookieoutlen,
+ QEMU_MIGRATION_COOKIE_CAPS) < 0)
+ VIR_WARN("Unable to encode migration cookie");
+
+ virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
+ qemuMigrationAnyConnectionClosed);
+
+ cleanup:
+ qemuProcessIncomingDefFree(incoming);
+ if (ret < 0)
+ ignore_value(qemuMigrationJobSetPhase(vm,
QEMU_MIGRATION_PHASE_POSTCOPY_FAILED));
+ qemuDomainCleanupAdd(vm, qemuProcessCleanupMigrationJob);
+ qemuMigrationJobContinue(vm);
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
static int
qemuMigrationDstPrepareAny(virQEMUDriver *driver,
virConnectPtr dconn,
@@ -3577,6 +3669,13 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver,
return -1;
}
+ if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
+ return qemuMigrationDstPrepareResume(driver, dconn, cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ *def, origname, protocol, port,
+ listenAddress, flags);
+ }
+
return qemuMigrationDstPrepareFresh(driver, dconn,
cookiein, cookieinlen,
cookieout, cookieoutlen,
--
2.35.1