[libvirt PATCH 68/80] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase

Jiri Denemark posted 80 patches 3 years, 9 months ago
There is a newer version of this series
[libvirt PATCH 68/80] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Jiri Denemark 3 years, 9 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>
---
 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
Re: [libvirt PATCH 68/80] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Peter Krempa 3 years, 9 months ago
On Tue, May 10, 2022 at 17:21:29 +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>
> ---
>  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,
>  }

[...]

> +
> +    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;
> +    }

Is there any reason not to allow adopting a running unattended migration
with a recovery API?
Re: [libvirt PATCH 68/80] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Jiri Denemark 3 years, 8 months ago
On Thu, May 12, 2022 at 17:16:32 +0200, Peter Krempa wrote:
> On Tue, May 10, 2022 at 17:21:29 +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>
> > ---
> >  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,
> >  }
> 
> [...]
> 
> > +
> > +    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;
> > +    }
> 
> Is there any reason not to allow adopting a running unattended migration
> with a recovery API?

It's easier this way :-) The migration will happily finish anyway so it
does not really matter. You can't just have a synchronous API call and
finished migration is only announced via events. Anyway, it can
definitely be done in a follow up series if desired, although it will
make the code even more complicated as we would have to do all the steps
and just avoid running any QMP commands and jump right into waiting for
migration to finish on both sides.

Jirka
Re: [libvirt PATCH 68/80] qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Prepare phase
Posted by Peter Krempa 3 years, 9 months ago
On Tue, May 10, 2022 at 17:21:29 +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>
> ---
>  src/qemu/qemu_migration.c | 99 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 99 insertions(+)

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