[libvirt PATCH v2 66/81] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase

Jiri Denemark jdenemar at redhat.com
Wed Jun 1 12:50:06 UTC 2022


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 at redhat.com>
Reviewed-by: Peter Krempa <pkrempa at redhat.com>
Reviewed-by: Pavel Hrdina <phrdina at redhat.com>
---

Notes:
    Version 2:
    - no change

 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 616f812ef1..dbebd215b4 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3474,6 +3474,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,
@@ -3538,6 +3630,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



More information about the libvir-list mailing list