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

Jiri Denemark posted 81 patches 3 years, 8 months ago
[libvirt PATCH v2 66/81] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Jiri Denemark 3 years, 8 months ago
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@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@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
Re: [libvirt PATCH v2 66/81] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Jiri Denemark 3 years, 8 months ago
On Wed, Jun 01, 2022 at 14:50:06 +0200, Jiri Denemark wrote:
> 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@redhat.com>
> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
> Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
> ---
> 
> Notes:
>     Version 2:
>     - no change
> 
>  src/qemu/qemu_migration.c | 99 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 99 insertions(+)

And the following diff is needed to make sure the Finish phase sees the
original name of the domain in case it was renamed during migration (via
--dname ... option).

Jirka

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 22a80d8430..506b6cde7a 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3534,6 +3534,8 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
                                          QEMU_MIGRATION_COOKIE_CAPS)))
         goto cleanup;

+    priv->origname = g_strdup(origname);
+
     if (!(incoming = qemuMigrationDstPrepare(vm, false, protocol,
                                              listenAddress, port, -1)))
         goto cleanup;
@@ -3561,8 +3563,10 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,

  cleanup:
     qemuProcessIncomingDefFree(incoming);
-    if (ret < 0)
+    if (ret < 0) {
+        VIR_FREE(priv->origname);
         ignore_value(qemuMigrationJobSetPhase(vm, QEMU_MIGRATION_PHASE_POSTCOPY_FAILED));
+    }
     qemuDomainCleanupAdd(vm, qemuProcessCleanupMigrationJob);
     qemuMigrationJobContinue(vm);
     virDomainObjEndAPI(&vm);
Re: [libvirt PATCH v2 66/81] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Peter Krempa 3 years, 8 months ago
On Fri, Jun 03, 2022 at 16:10:07 +0200, Jiri Denemark wrote:
> On Wed, Jun 01, 2022 at 14:50:06 +0200, Jiri Denemark wrote:
> > 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@redhat.com>
> > Reviewed-by: Peter Krempa <pkrempa@redhat.com>
> > Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
> > ---
> > 
> > Notes:
> >     Version 2:
> >     - no change
> > 
> >  src/qemu/qemu_migration.c | 99 +++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 99 insertions(+)
> 
> And the following diff is needed to make sure the Finish phase sees the
> original name of the domain in case it was renamed during migration (via
> --dname ... option).
> 
> Jirka
> 
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index 22a80d8430..506b6cde7a 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -3534,6 +3534,8 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
>                                           QEMU_MIGRATION_COOKIE_CAPS)))
>          goto cleanup;
> 
> +    priv->origname = g_strdup(origname);
> +
>      if (!(incoming = qemuMigrationDstPrepare(vm, false, protocol,
>                                               listenAddress, port, -1)))
>          goto cleanup;
> @@ -3561,8 +3563,10 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
> 
>   cleanup:
>      qemuProcessIncomingDefFree(incoming);
> -    if (ret < 0)
> +    if (ret < 0) {
> +        VIR_FREE(priv->origname);
>          ignore_value(qemuMigrationJobSetPhase(vm, QEMU_MIGRATION_PHASE_POSTCOPY_FAILED));
> +    }
>      qemuDomainCleanupAdd(vm, qemuProcessCleanupMigrationJob);
>      qemuMigrationJobContinue(vm);
>      virDomainObjEndAPI(&vm);
> 

Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Re: [libvirt PATCH v2 66/81] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Jiri Denemark 3 years, 8 months ago
On Wed, Jun 01, 2022 at 14:50:06 +0200, Jiri Denemark wrote:
> 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@redhat.com>
> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
> Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
> ---
> 
> Notes:
>     Version 2:
>     - no change
> 
>  src/qemu/qemu_migration.c | 99 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 99 insertions(+)

The following patch needs to be squashed in to make sure the
automatically allocated port is properly released at the end of resume.

Jirka

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index dbebd215b4..22a80d8430 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3485,6 +3485,7 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
                               const char *origname,
                               const char *protocol,
                               unsigned short port,
+                              bool autoPort,
                               const char *listenAddress,
                               unsigned long flags)
 {
@@ -3555,6 +3556,9 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
     virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
                          qemuMigrationAnyConnectionClosed);

+    if (autoPort)
+        priv->migrationPort = port;
+
  cleanup:
     qemuProcessIncomingDefFree(incoming);
     if (ret < 0)
@@ -3633,7 +3637,8 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver,
     if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
         return qemuMigrationDstPrepareResume(driver, dconn, cookiein, cookieinlen,
                                              cookieout, cookieoutlen,
-                                             *def, origname, protocol, port,
+                                             *def, origname, protocol,
+                                             port, autoPort,
                                              listenAddress, flags);
     }
Re: [libvirt PATCH v2 66/81] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Peter Krempa 3 years, 8 months ago
On Fri, Jun 03, 2022 at 14:27:55 +0200, Jiri Denemark wrote:
> On Wed, Jun 01, 2022 at 14:50:06 +0200, Jiri Denemark wrote:
> > 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@redhat.com>
> > Reviewed-by: Peter Krempa <pkrempa@redhat.com>
> > Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
> > ---
> > 
> > Notes:
> >     Version 2:
> >     - no change
> > 
> >  src/qemu/qemu_migration.c | 99 +++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 99 insertions(+)
> 
> The following patch needs to be squashed in to make sure the
> automatically allocated port is properly released at the end of resume.
> 
> Jirka
> 
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index dbebd215b4..22a80d8430 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -3485,6 +3485,7 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
>                                const char *origname,
>                                const char *protocol,
>                                unsigned short port,
> +                              bool autoPort,
>                                const char *listenAddress,
>                                unsigned long flags)
>  {
> @@ -3555,6 +3556,9 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
>      virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
>                           qemuMigrationAnyConnectionClosed);
> 
> +    if (autoPort)
> +        priv->migrationPort = port;
> +
>   cleanup:
>      qemuProcessIncomingDefFree(incoming);
>      if (ret < 0)
> @@ -3633,7 +3637,8 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver,
>      if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
>          return qemuMigrationDstPrepareResume(driver, dconn, cookiein, cookieinlen,
>                                               cookieout, cookieoutlen,
> -                                             *def, origname, protocol, port,
> +                                             *def, origname, protocol,
> +                                             port, autoPort,
>                                               listenAddress, flags);



Reviewed-by: Peter Krempa <pkrempa@redhat.com>