[libvirt PATCH v2 59/81] qemu: Refactor qemuMigrationDstPrepareFresh

Jiri Denemark jdenemar at redhat.com
Wed Jun 1 12:49:59 UTC 2022


Offline migration jumps over a big part of qemuMigrationDstPrepareFresh.
Let's move that part into a new qemuMigrationDstPrepareActive function
to make the code easier to follow.

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:
    - dropped line breaks from error messages
    - fixed indentation
    - dropped VIR_MIGRATE_OFFLINE check from qemuMigrationDstPrepareActive

 src/qemu/qemu_migration.c | 371 +++++++++++++++++++++-----------------
 1 file changed, 203 insertions(+), 168 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index d4683a9922..53236b7239 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3083,6 +3083,197 @@ qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObj *vm,
 }
 
 
+static int
+qemuMigrationDstPrepareActive(virQEMUDriver *driver,
+                              virDomainObj *vm,
+                              virConnectPtr dconn,
+                              qemuMigrationCookie *mig,
+                              virStreamPtr st,
+                              const char *protocol,
+                              unsigned short port,
+                              const char *listenAddress,
+                              size_t nmigrate_disks,
+                              const char **migrate_disks,
+                              int nbdPort,
+                              const char *nbdURI,
+                              qemuMigrationParams *migParams,
+                              unsigned long flags)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    qemuDomainJobPrivate *jobPriv = priv->job.privateData;
+    qemuProcessIncomingDef *incoming = NULL;
+    g_autofree char *tlsAlias = NULL;
+    virObjectEvent *event = NULL;
+    virErrorPtr origErr = NULL;
+    int dataFD[2] = { -1, -1 };
+    bool stopProcess = false;
+    unsigned int startFlags;
+    bool relabel = false;
+    bool tunnel = !!st;
+    int ret = -1;
+    int rv;
+
+    if (STREQ_NULLABLE(protocol, "rdma") &&
+        !virMemoryLimitIsSet(vm->def->mem.hard_limit)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot start RDMA migration with no memory hard limit set"));
+        goto error;
+    }
+
+    if (qemuMigrationDstPrecreateStorage(vm, mig->nbd,
+                                         nmigrate_disks, migrate_disks,
+                                         !!(flags & VIR_MIGRATE_NON_SHARED_INC)) < 0)
+        goto error;
+
+    if (tunnel &&
+        virPipe(dataFD) < 0)
+        goto error;
+
+    startFlags = VIR_QEMU_PROCESS_START_AUTODESTROY;
+
+    if (qemuProcessInit(driver, vm, mig->cpu, VIR_ASYNC_JOB_MIGRATION_IN,
+                        true, startFlags) < 0)
+        goto error;
+    stopProcess = true;
+
+    if (!(incoming = qemuMigrationDstPrepare(vm, tunnel, protocol,
+                                             listenAddress, port,
+                                             dataFD[0])))
+        goto error;
+
+    if (qemuProcessPrepareDomain(driver, vm, startFlags) < 0)
+        goto error;
+
+    if (qemuProcessPrepareHost(driver, vm, startFlags) < 0)
+        goto error;
+
+    rv = qemuProcessLaunch(dconn, driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
+                           incoming, NULL,
+                           VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START,
+                           startFlags);
+    if (rv < 0) {
+        if (rv == -2)
+            relabel = true;
+        goto error;
+    }
+    relabel = true;
+
+    if (tunnel) {
+        if (virFDStreamOpen(st, dataFD[1]) < 0) {
+            virReportSystemError(errno, "%s",
+                                 _("cannot pass pipe for tunnelled migration"));
+            goto error;
+        }
+        dataFD[1] = -1; /* 'st' owns the FD now & will close it */
+    }
+
+    if (STREQ_NULLABLE(protocol, "rdma") &&
+        vm->def->mem.hard_limit > 0 &&
+        virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) {
+        goto error;
+    }
+
+    if (qemuMigrationDstPrepareAnyBlockDirtyBitmaps(vm, mig, migParams, flags) < 0)
+        goto error;
+
+    if (qemuMigrationParamsCheck(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
+                                 migParams, mig->caps->automatic) < 0)
+        goto error;
+
+    /* Migrations using TLS need to add the "tls-creds-x509" object and
+     * set the migration TLS parameters */
+    if (flags & VIR_MIGRATE_TLS) {
+        if (qemuMigrationParamsEnableTLS(driver, vm, true,
+                                         VIR_ASYNC_JOB_MIGRATION_IN,
+                                         &tlsAlias, NULL,
+                                         migParams) < 0)
+            goto error;
+    } else {
+        if (qemuMigrationParamsDisableTLS(vm, migParams) < 0)
+            goto error;
+    }
+
+    if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
+                                 migParams) < 0)
+        goto error;
+
+    if (mig->nbd &&
+        flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
+        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER)) {
+        const char *nbdTLSAlias = NULL;
+
+        if (flags & VIR_MIGRATE_TLS) {
+            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_TLS)) {
+                virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                               _("QEMU NBD server does not support TLS transport"));
+                goto error;
+            }
+
+            nbdTLSAlias = tlsAlias;
+        }
+
+        if (qemuMigrationDstStartNBDServer(driver, vm, incoming->address,
+                                           nmigrate_disks, migrate_disks,
+                                           nbdPort, nbdURI,
+                                           nbdTLSAlias) < 0) {
+            goto error;
+        }
+    }
+
+    if (mig->lockState) {
+        VIR_DEBUG("Received lockstate %s", mig->lockState);
+        VIR_FREE(priv->lockState);
+        priv->lockState = g_steal_pointer(&mig->lockState);
+    } else {
+        VIR_DEBUG("Received no lockstate");
+    }
+
+    if (qemuMigrationDstRun(driver, vm, incoming->uri,
+                            VIR_ASYNC_JOB_MIGRATION_IN) < 0)
+        goto error;
+
+    if (qemuProcessFinishStartup(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
+                                 false, VIR_DOMAIN_PAUSED_MIGRATION) < 0)
+        goto error;
+
+    virDomainAuditStart(vm, "migrated", true);
+    event = virDomainEventLifecycleNewFromObj(vm,
+                                              VIR_DOMAIN_EVENT_STARTED,
+                                              VIR_DOMAIN_EVENT_STARTED_MIGRATED);
+
+    ret = 0;
+
+ cleanup:
+    qemuProcessIncomingDefFree(incoming);
+    VIR_FORCE_CLOSE(dataFD[0]);
+    VIR_FORCE_CLOSE(dataFD[1]);
+    virObjectEventStateQueue(driver->domainEventState, event);
+    virErrorRestore(&origErr);
+    return ret;
+
+ error:
+    virErrorPreserveLast(&origErr);
+    qemuMigrationParamsReset(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
+                             jobPriv->migParams, priv->job.apiFlags);
+
+    if (stopProcess) {
+        unsigned int stopFlags = VIR_QEMU_PROCESS_STOP_MIGRATED;
+        if (!relabel)
+            stopFlags |= VIR_QEMU_PROCESS_STOP_NO_RELABEL;
+        virDomainAuditStart(vm, "migrated", false);
+        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
+                        VIR_ASYNC_JOB_MIGRATION_IN, stopFlags);
+        /* release if port is auto selected which is not the case if
+         * it is given in parameters
+         */
+        if (nbdPort == 0)
+            virPortAllocatorRelease(priv->nbdPort);
+        priv->nbdPort = 0;
+    }
+    goto cleanup;
+}
+
+
 static int
 qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
                              virConnectPtr dconn,
@@ -3105,32 +3296,20 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
                              unsigned long flags)
 {
     virDomainObj *vm = NULL;
-    virObjectEvent *event = NULL;
     virErrorPtr origErr;
     int ret = -1;
-    int dataFD[2] = { -1, -1 };
     qemuDomainObjPrivate *priv = NULL;
     qemuMigrationCookie *mig = NULL;
-    qemuDomainJobPrivate *jobPriv = NULL;
-    bool tunnel = !!st;
     g_autofree char *xmlout = NULL;
-    unsigned int cookieFlags;
-    unsigned int startFlags;
-    qemuProcessIncomingDef *incoming = NULL;
+    unsigned int cookieFlags = 0;
     bool taint_hook = false;
-    bool stopProcess = false;
-    bool relabel = false;
-    int rv;
-    g_autofree char *tlsAlias = NULL;
 
     VIR_DEBUG("name=%s, origname=%s, protocol=%s, port=%hu, "
               "listenAddress=%s, nbdPort=%d, nbdURI=%s, flags=0x%lx",
               (*def)->name, NULLSTR(origname), protocol, port,
               listenAddress, nbdPort, NULLSTR(nbdURI), flags);
 
-    if (flags & VIR_MIGRATE_OFFLINE) {
-        cookieFlags = 0;
-    } else {
+    if (!(flags & VIR_MIGRATE_OFFLINE)) {
         cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS |
                       QEMU_MIGRATION_COOKIE_CAPS;
     }
@@ -3203,7 +3382,6 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
         goto cleanup;
 
     priv = vm->privateData;
-    jobPriv = priv->job.privateData;
     priv->origname = g_strdup(origname);
 
     if (taint_hook) {
@@ -3211,19 +3389,6 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
         priv->hookRun = true;
     }
 
-    if (STREQ_NULLABLE(protocol, "rdma") &&
-        !virMemoryLimitIsSet(vm->def->mem.hard_limit)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("cannot start RDMA migration with no memory hard "
-                         "limit set"));
-        goto cleanup;
-    }
-
-    if (qemuMigrationDstPrecreateStorage(vm, mig->nbd,
-                                         nmigrate_disks, migrate_disks,
-                                         !!(flags & VIR_MIGRATE_NON_SHARED_INC)) < 0)
-        goto cleanup;
-
     if (qemuMigrationJobStart(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
                               flags) < 0)
         goto cleanup;
@@ -3234,122 +3399,21 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
     /* Domain starts inactive, even if the domain XML had an id field. */
     vm->def->id = -1;
 
-    if (flags & VIR_MIGRATE_OFFLINE)
-        goto done;
-
-    if (tunnel &&
-        virPipe(dataFD) < 0)
-        goto stopjob;
-
-    startFlags = VIR_QEMU_PROCESS_START_AUTODESTROY;
-
-    if (qemuProcessInit(driver, vm, mig->cpu, VIR_ASYNC_JOB_MIGRATION_IN,
-                        true, startFlags) < 0)
-        goto stopjob;
-    stopProcess = true;
-
-    if (!(incoming = qemuMigrationDstPrepare(vm, tunnel, protocol,
-                                             listenAddress, port,
-                                             dataFD[0])))
-        goto stopjob;
-
-    if (qemuProcessPrepareDomain(driver, vm, startFlags) < 0)
-        goto stopjob;
-
-    if (qemuProcessPrepareHost(driver, vm, startFlags) < 0)
-        goto stopjob;
-
-    rv = qemuProcessLaunch(dconn, driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
-                           incoming, NULL,
-                           VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START,
-                           startFlags);
-    if (rv < 0) {
-        if (rv == -2)
-            relabel = true;
-        goto stopjob;
-    }
-    relabel = true;
-
-    if (tunnel) {
-        if (virFDStreamOpen(st, dataFD[1]) < 0) {
-            virReportSystemError(errno, "%s",
-                                 _("cannot pass pipe for tunnelled migration"));
-            goto stopjob;
-        }
-        dataFD[1] = -1; /* 'st' owns the FD now & will close it */
-    }
-
-    if (STREQ_NULLABLE(protocol, "rdma") &&
-        vm->def->mem.hard_limit > 0 &&
-        virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) {
-        goto stopjob;
-    }
-
-    if (qemuMigrationDstPrepareAnyBlockDirtyBitmaps(vm, mig, migParams, flags) < 0)
-        goto stopjob;
-
-    if (qemuMigrationParamsCheck(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
-                                 migParams, mig->caps->automatic) < 0)
-        goto stopjob;
-
-    /* Migrations using TLS need to add the "tls-creds-x509" object and
-     * set the migration TLS parameters */
-    if (flags & VIR_MIGRATE_TLS) {
-        if (qemuMigrationParamsEnableTLS(driver, vm, true,
-                                         VIR_ASYNC_JOB_MIGRATION_IN,
-                                         &tlsAlias, NULL,
-                                         migParams) < 0)
-            goto stopjob;
-    } else {
-        if (qemuMigrationParamsDisableTLS(vm, migParams) < 0)
+    if (!(flags & VIR_MIGRATE_OFFLINE)) {
+        if (qemuMigrationDstPrepareActive(driver, vm, dconn, mig, st,
+                                          protocol, port, listenAddress,
+                                          nmigrate_disks, migrate_disks,
+                                          nbdPort, nbdURI,
+                                          migParams, flags) < 0) {
             goto stopjob;
-    }
-
-    if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
-                                 migParams) < 0)
-        goto stopjob;
-
-    if (mig->nbd &&
-        flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
-        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER)) {
-        const char *nbdTLSAlias = NULL;
-
-        if (flags & VIR_MIGRATE_TLS) {
-            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_TLS)) {
-                virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
-                               _("QEMU NBD server does not support TLS transport"));
-                goto stopjob;
-            }
-
-            nbdTLSAlias = tlsAlias;
         }
 
-        if (qemuMigrationDstStartNBDServer(driver, vm, incoming->address,
-                                           nmigrate_disks, migrate_disks,
-                                           nbdPort, nbdURI,
-                                           nbdTLSAlias) < 0) {
-            goto stopjob;
-        }
-        cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
+        if (mig->nbd &&
+            flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
+            virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER))
+            cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
     }
 
-    if (mig->lockState) {
-        VIR_DEBUG("Received lockstate %s", mig->lockState);
-        VIR_FREE(priv->lockState);
-        priv->lockState = g_steal_pointer(&mig->lockState);
-    } else {
-        VIR_DEBUG("Received no lockstate");
-    }
-
-    if (qemuMigrationDstRun(driver, vm, incoming->uri,
-                            VIR_ASYNC_JOB_MIGRATION_IN) < 0)
-        goto stopjob;
-
-    if (qemuProcessFinishStartup(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
-                                 false, VIR_DOMAIN_PAUSED_MIGRATION) < 0)
-        goto stopjob;
-
- done:
     if (qemuMigrationCookieFormat(mig, driver, vm,
                                   QEMU_MIGRATION_DESTINATION,
                                   cookieout, cookieoutlen, cookieFlags) < 0) {
@@ -3362,13 +3426,6 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
 
     qemuDomainCleanupAdd(vm, qemuMigrationDstPrepareCleanup);
 
-    if (!(flags & VIR_MIGRATE_OFFLINE)) {
-        virDomainAuditStart(vm, "migrated", true);
-        event = virDomainEventLifecycleNewFromObj(vm,
-                                         VIR_DOMAIN_EVENT_STARTED,
-                                         VIR_DOMAIN_EVENT_STARTED_MIGRATED);
-    }
-
     /* We keep the job active across API calls until the finish() call.
      * This prevents any other APIs being invoked while incoming
      * migration is taking place.
@@ -3386,41 +3443,19 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
 
  cleanup:
     virErrorPreserveLast(&origErr);
-    qemuProcessIncomingDefFree(incoming);
-    VIR_FORCE_CLOSE(dataFD[0]);
-    VIR_FORCE_CLOSE(dataFD[1]);
     if (ret < 0 && priv) {
         /* priv is set right after vm is added to the list of domains
          * and there is no 'goto cleanup;' in the middle of those */
         VIR_FREE(priv->origname);
-        /* release if port is auto selected which is not the case if
-         * it is given in parameters
-         */
-        if (nbdPort == 0)
-            virPortAllocatorRelease(priv->nbdPort);
-        priv->nbdPort = 0;
         virDomainObjRemoveTransientDef(vm);
         qemuDomainRemoveInactive(driver, vm);
     }
     virDomainObjEndAPI(&vm);
-    virObjectEventStateQueue(driver->domainEventState, event);
     qemuMigrationCookieFree(mig);
     virErrorRestore(&origErr);
     return ret;
 
  stopjob:
-    qemuMigrationParamsReset(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN,
-                             jobPriv->migParams, priv->job.apiFlags);
-
-    if (stopProcess) {
-        unsigned int stopFlags = VIR_QEMU_PROCESS_STOP_MIGRATED;
-        if (!relabel)
-            stopFlags |= VIR_QEMU_PROCESS_STOP_NO_RELABEL;
-        virDomainAuditStart(vm, "migrated", false);
-        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
-                        VIR_ASYNC_JOB_MIGRATION_IN, stopFlags);
-    }
-
     qemuMigrationJobFinish(vm);
     goto cleanup;
 }
-- 
2.35.1



More information about the libvir-list mailing list