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@xxxxxxxxxx> --- 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