File libxl-set-migration-constraints.patch of Package libvirt

From 3221868c5ca0be83d4e5f9a9f489e73d5b509a6e Mon Sep 17 00:00:00 2001
From: Jim Fehlig <jfehlig@suse.com>
Date: Tue, 5 Jul 2022 11:26:24 -0600
Subject: libvirt: set migration constraints from cmdline

References: fate#316614

Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
 docs/manpages/virsh.rst          |  7 +++++
 include/libvirt/libvirt-domain.h | 25 +++++++++++++++
 src/libxl/libxl_driver.c         | 16 ++++++++--
 src/libxl/libxl_migration.c      | 54 ++++++++++++++++++++++----------
 src/libxl/libxl_migration.h      | 14 +++++++--
 tools/virsh-domain.c             | 29 +++++++++++++++++
 6 files changed, 124 insertions(+), 21 deletions(-)

Index: libvirt-9.0.0/docs/manpages/virsh.rst
===================================================================
--- libvirt-9.0.0.orig/docs/manpages/virsh.rst
+++ libvirt-9.0.0/docs/manpages/virsh.rst
@@ -3362,6 +3362,7 @@ migrate
       [--parallel [--parallel-connections connections]]
       [--bandwidth bandwidth] [--tls-destination hostname]
       [--disks-uri URI] [--copy-storage-synchronous-writes]
+      [--max_iters num] [--min_remaining num] [--abort_if_busy]
 
 Migrate domain to another host.  Add *--live* for live migration; <--p2p>
 for peer-2-peer migration; *--direct* for direct migration; or *--tunnelled*
@@ -3488,6 +3489,12 @@ parallel connections. The number of such
 network link between the source and the target and thus speeding up the
 migration.
 
+SUSE-specific options for Xen: *--max_iters* allows specifying the maximum
+number of iterations before final suspend. Default is 2.  *--min_remaining*
+allows specifying the number of dirty pages before final suspend. Default is 50.
+*--abort_if_busy* can be used to abort the migration instead of doing the final
+suspend for domUs with busy workloads, to avoid a long suspend-time of the domU.
+
 Running migration can be canceled by interrupting virsh (usually using
 ``Ctrl-C``) or by ``domjobabort`` command sent from another virsh instance.
 
Index: libvirt-9.0.0/include/libvirt/libvirt-domain.h
===================================================================
--- libvirt-9.0.0.orig/include/libvirt/libvirt-domain.h
+++ libvirt-9.0.0/include/libvirt/libvirt-domain.h
@@ -1367,6 +1367,31 @@ typedef enum {
  */
 # define VIR_MIGRATE_PARAM_TLS_DESTINATION          "tls.destination"
 
+/**
+ * VIR_MIGRATE_PARAM_SUSE_MAX_ITERS:
+ *
+ * virDomainMigrate* params field: xc_domain_save max_iters
+ *
+ * Since: 1.2.5
+ */
+# define VIR_MIGRATE_PARAM_SUSE_MAX_ITERS     "max_iters"
+/**
+ * VIR_MIGRATE_PARAM_SUSE_MIN_REMAINING:
+ *
+ * virDomainMigrate* params field: xc_domain_save min_remaining
+ *
+ * Since: 1.2.5
+ */
+# define VIR_MIGRATE_PARAM_SUSE_MIN_REMAINING "min_remaining"
+/**
+ * VIR_MIGRATE_PARAM_SUSE_ABORT_IF_BUSY:
+ *
+ * virDomainMigrate* params field: xc_domain_save abort_if_busy
+ *
+ * Since: 1.2.5
+ */
+# define VIR_MIGRATE_PARAM_SUSE_ABORT_IF_BUSY "abort_if_busy"
+
 /* Domain migration. */
 virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn,
                                unsigned long flags, const char *dname,
Index: libvirt-9.0.0/src/libxl/libxl_driver.c
===================================================================
--- libvirt-9.0.0.orig/src/libxl/libxl_driver.c
+++ libvirt-9.0.0/src/libxl/libxl_driver.c
@@ -5996,6 +5996,9 @@ libxlDomainMigratePerform3Params(virDoma
     const char *dname = NULL;
     const char *uri = NULL;
     int ret = -1;
+    libxlDomainMigrationProps props = {
+        .virFlags = flags,
+    };
 
 #ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
     virReportUnsupportedError();
@@ -6012,6 +6015,15 @@ libxlDomainMigratePerform3Params(virDoma
         virTypedParamsGetString(params, nparams,
                                 VIR_MIGRATE_PARAM_DEST_NAME,
                                 &dname) < 0 ||
+        virTypedParamsGetUInt(params, nparams,
+                                VIR_MIGRATE_PARAM_SUSE_MAX_ITERS,
+                                &props.max_iters) < 0 ||
+        virTypedParamsGetUInt(params, nparams,
+                                VIR_MIGRATE_PARAM_SUSE_MIN_REMAINING,
+                                &props.min_remaining) < 0 ||
+        virTypedParamsGetUInt(params, nparams,
+                                VIR_MIGRATE_PARAM_SUSE_ABORT_IF_BUSY,
+                                &props.abort_if_busy) < 0 ||
         virTypedParamsGetString(params, nparams,
                                 VIR_MIGRATE_PARAM_URI,
                                 &uri) < 0)
@@ -6026,11 +6038,11 @@ libxlDomainMigratePerform3Params(virDoma
 
     if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
         if (libxlDomainMigrationSrcPerformP2P(driver, vm, dom->conn, dom_xml,
-                                              dconnuri, uri, dname, flags) < 0)
+                                              dconnuri, uri, dname, &props) < 0)
             goto cleanup;
     } else {
         if (libxlDomainMigrationSrcPerform(driver, vm, dom_xml, dconnuri,
-                                           uri, dname, flags) < 0)
+                                           uri, dname, &props) < 0)
             goto cleanup;
     }
 
Index: libvirt-9.0.0/src/libxl/libxl_migration.c
===================================================================
--- libvirt-9.0.0.orig/src/libxl/libxl_migration.c
+++ libvirt-9.0.0/src/libxl/libxl_migration.c
@@ -329,18 +329,38 @@ libxlMigrateDstReceive(virNetSocket *soc
 static int
 libxlDoMigrateSrcSend(libxlDriverPrivate *driver,
                       virDomainObj *vm,
-                      unsigned int flags,
+                      const libxlDomainMigrationProps *props,
                       int sockfd)
 {
     libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
+#ifdef LIBXL_HAVE_DOMAIN_SUSPEND_SUSE
+    libxl_domain_suspend_suse_properties libxl_props = {
+        .flags = 0,
+    };
+#else
     int xl_flags = 0;
+#endif
     int ret;
 
-    if (flags & VIR_MIGRATE_LIVE)
+#ifdef LIBXL_HAVE_DOMAIN_SUSPEND_SUSE
+    if (props->virFlags & VIR_MIGRATE_LIVE)
+        libxl_props.flags |= LIBXL_SUSPEND_LIVE;
+
+    libxl_props.max_iters = props->max_iters;
+    libxl_props.min_remaining = props->min_remaining;
+    if (props->abort_if_busy)
+        libxl_props.flags |= LIBXL_SUSPEND_ABORT_IF_BUSY;
+
+    ret = libxl_domain_suspend_suse(cfg->ctx, vm->def->id, sockfd,
+                                    &libxl_props, NULL);
+#else
+    if (props->virFlags & VIR_MIGRATE_LIVE)
         xl_flags = LIBXL_SUSPEND_LIVE;
 
     ret = libxl_domain_suspend(cfg->ctx, vm->def->id, sockfd,
                                xl_flags, NULL);
+#endif
+
     if (ret != 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("Failed to send migration data to destination host"));
@@ -877,7 +897,7 @@ struct libxlTunnelControl {
 static int
 libxlMigrationSrcStartTunnel(libxlDriverPrivate *driver,
                              virDomainObj *vm,
-                             unsigned int flags,
+                             const libxlDomainMigrationProps *props,
                              virStreamPtr st,
                              struct libxlTunnelControl **tnl)
 {
@@ -910,7 +930,7 @@ libxlMigrationSrcStartTunnel(libxlDriver
 
     virObjectUnlock(vm);
     /* Send data to pipe */
-    ret = libxlDoMigrateSrcSend(driver, vm, flags, tc->dataFD[1]);
+    ret = libxlDoMigrateSrcSend(driver, vm, props, tc->dataFD[1]);
     virObjectLock(vm);
 
     /* libxlMigrationSrcStopTunnel will be called in libxlDoMigrateSrcP2P
@@ -945,7 +965,7 @@ libxlDoMigrateSrcP2P(libxlDriverPrivate
                      const char *dconnuri G_GNUC_UNUSED,
                      const char *dname,
                      const char *uri,
-                     unsigned int flags)
+                     const libxlDomainMigrationProps *props)
 {
     virDomainPtr ddomain = NULL;
     virTypedParameterPtr params = NULL;
@@ -990,11 +1010,11 @@ libxlDoMigrateSrcP2P(libxlDriverPrivate
     /* We don't require the destination to have P2P support
      * as it looks to be normal migration from the receiver perspective.
      */
-    destflags = flags & ~(VIR_MIGRATE_PEER2PEER);
+    destflags = props->virFlags & ~(VIR_MIGRATE_PEER2PEER);
 
     VIR_DEBUG("Prepare3");
     virObjectUnlock(vm);
-    if (flags & VIR_MIGRATE_TUNNELLED) {
+    if (props->virFlags & VIR_MIGRATE_TUNNELLED) {
         if (!(st = virStreamNew(dconn, 0)))
             goto confirm;
         ret = dconn->driver->domainMigratePrepareTunnel3Params
@@ -1008,7 +1028,7 @@ libxlDoMigrateSrcP2P(libxlDriverPrivate
     if (ret == -1)
         goto confirm;
 
-    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
+    if (!(props->virFlags & VIR_MIGRATE_TUNNELLED)) {
         if (uri_out) {
             if (virTypedParamsReplaceString(&params, &nparams,
                                             VIR_MIGRATE_PARAM_URI, uri_out) < 0) {
@@ -1023,11 +1043,11 @@ libxlDoMigrateSrcP2P(libxlDriverPrivate
     }
 
     VIR_DEBUG("Perform3 uri=%s", NULLSTR(uri_out));
-    if (flags & VIR_MIGRATE_TUNNELLED)
-        ret = libxlMigrationSrcStartTunnel(driver, vm, flags, st, &tc);
+    if (props->virFlags & VIR_MIGRATE_TUNNELLED)
+        ret = libxlMigrationSrcStartTunnel(driver, vm, props, st, &tc);
     else
         ret = libxlDomainMigrationSrcPerform(driver, vm, NULL, NULL,
-                                             uri_out, NULL, flags);
+                                             uri_out, NULL, props);
     if (ret < 0) {
         notify_source = false;
         virErrorPreserveLast(&orig_err);
@@ -1062,7 +1082,7 @@ libxlDoMigrateSrcP2P(libxlDriverPrivate
  confirm:
     if (notify_source) {
         VIR_DEBUG("Confirm3 cancelled=%d vm=%p", cancelled, vm);
-        ret = libxlDomainMigrationSrcConfirm(driver, vm, flags, cancelled);
+        ret = libxlDomainMigrationSrcConfirm(driver, vm, props->virFlags, cancelled);
 
         if (ret < 0)
             VIR_WARN("Guest %s probably left in 'paused' state on source",
@@ -1070,7 +1090,7 @@ libxlDoMigrateSrcP2P(libxlDriverPrivate
     }
 
  cleanup:
-    if (flags & VIR_MIGRATE_TUNNELLED) {
+    if (props->virFlags & VIR_MIGRATE_TUNNELLED) {
         libxlMigrationSrcStopTunnel(tc);
         virObjectUnref(st);
     }
@@ -1114,7 +1134,7 @@ libxlDomainMigrationSrcPerformP2P(libxlD
                                   const char *dconnuri,
                                   const char *uri_str G_GNUC_UNUSED,
                                   const char *dname,
-                                  unsigned int flags)
+                                  const libxlDomainMigrationProps *props)
 {
     int ret = -1;
     int useParams;
@@ -1148,7 +1168,7 @@ libxlDomainMigrationSrcPerformP2P(libxlD
     }
 
     ret = libxlDoMigrateSrcP2P(driver, vm, sconn, xmlin, dconn, dconnuri,
-                               dname, uri_str, flags);
+                               dname, uri_str, props);
 
     if (ret < 0) {
         /*
@@ -1175,7 +1195,7 @@ libxlDomainMigrationSrcPerform(libxlDriv
                                const char *dconnuri G_GNUC_UNUSED,
                                const char *uri_str,
                                const char *dname G_GNUC_UNUSED,
-                               unsigned int flags)
+                               const libxlDomainMigrationProps *props)
 {
     libxlDomainObjPrivate *priv = vm->privateData;
     char *hostname = NULL;
@@ -1211,7 +1231,7 @@ libxlDomainMigrationSrcPerform(libxlDriv
 
     /* suspend vm and send saved data to dst through socket fd */
     virObjectUnlock(vm);
-    ret = libxlDoMigrateSrcSend(driver, vm, flags, sockfd);
+    ret = libxlDoMigrateSrcSend(driver, vm, props, sockfd);
     virObjectLock(vm);
 
     if (ret == 0) {
Index: libvirt-9.0.0/src/libxl/libxl_migration.h
===================================================================
--- libvirt-9.0.0.orig/src/libxl/libxl_migration.h
+++ libvirt-9.0.0/src/libxl/libxl_migration.h
@@ -35,6 +35,9 @@
     VIR_MIGRATE_PARAM_URI,              VIR_TYPED_PARAM_STRING, \
     VIR_MIGRATE_PARAM_DEST_NAME,        VIR_TYPED_PARAM_STRING, \
     VIR_MIGRATE_PARAM_DEST_XML,         VIR_TYPED_PARAM_STRING, \
+    VIR_MIGRATE_PARAM_SUSE_MAX_ITERS,   VIR_TYPED_PARAM_UINT, \
+    VIR_MIGRATE_PARAM_SUSE_MIN_REMAINING, VIR_TYPED_PARAM_UINT, \
+    VIR_MIGRATE_PARAM_SUSE_ABORT_IF_BUSY, VIR_TYPED_PARAM_UINT, \
     NULL
 
 char *
@@ -66,6 +69,13 @@ libxlDomainMigrationDstPrepare(virConnec
                                int cookieinlen,
                                unsigned int flags);
 
+typedef struct {
+    unsigned int virFlags;
+    unsigned int max_iters;
+    unsigned int min_remaining;
+    unsigned int abort_if_busy;
+} libxlDomainMigrationProps;
+
 int
 libxlDomainMigrationSrcPerformP2P(libxlDriverPrivate *driver,
                                   virDomainObj *vm,
@@ -74,7 +84,7 @@ libxlDomainMigrationSrcPerformP2P(libxlD
                                   const char *dconnuri,
                                   const char *uri_str,
                                   const char *dname,
-                                  unsigned int flags);
+                                  const libxlDomainMigrationProps *props);
 
 int
 libxlDomainMigrationSrcPerform(libxlDriverPrivate *driver,
@@ -83,7 +93,7 @@ libxlDomainMigrationSrcPerform(libxlDriv
                                const char *dconnuri,
                                const char *uri_str,
                                const char *dname,
-                               unsigned int flags);
+                               const libxlDomainMigrationProps *props);
 
 virDomainPtr
 libxlDomainMigrationDstFinish(virConnectPtr dconn,
Index: libvirt-9.0.0/tools/virsh-domain.c
===================================================================
--- libvirt-9.0.0.orig/tools/virsh-domain.c
+++ libvirt-9.0.0/tools/virsh-domain.c
@@ -11104,6 +11104,18 @@ static const vshCmdOptDef opts_migrate[]
      .completer = virshCompleteEmpty,
      .help = N_("override the destination host name used for TLS verification")
     },
+    {.name = "max_iters",
+     .type = VSH_OT_INT,
+     .help = N_("SUSE libxl: Number of iterations before final suspend (default: 2).")
+    },
+    {.name = "min_remaining",
+     .type = VSH_OT_INT,
+     .help = N_("SUSE libxl: Number of dirty pages before final suspend (default: 50).")
+    },
+    {.name = "abort_if_busy",
+     .type = VSH_OT_BOOL,
+     .help = N_("SUSE libxl: Abort migration instead of doing final suspend.")
+    },
     {.name = NULL}
 };
 
@@ -11124,6 +11136,7 @@ doMigrate(void *opaque)
     unsigned long long ullOpt = 0;
     int rv;
     virConnectPtr dconn = data->dconn;
+    unsigned int uint_opt = 0;
 #ifndef WIN32
     sigset_t sigmask, oldsigmask;
 
@@ -11254,6 +11267,22 @@ doMigrate(void *opaque)
             goto save_error;
     }
 
+    if (vshCommandOptUInt(ctl, cmd, "max_iters", &uint_opt) > 0 && uint_opt) {
+        if (virTypedParamsAddUInt(&params, &nparams, &maxparams,
+                                VIR_MIGRATE_PARAM_SUSE_MAX_ITERS, uint_opt) < 0)
+            goto save_error;
+    }
+    if (vshCommandOptUInt(ctl, cmd, "min_remaining", &uint_opt) > 0 && uint_opt) {
+        if (virTypedParamsAddUInt(&params, &nparams, &maxparams,
+                                VIR_MIGRATE_PARAM_SUSE_MIN_REMAINING, uint_opt) < 0)
+            goto save_error;
+    }
+    if (vshCommandOptBool(cmd, "abort_if_busy")) {
+        if (virTypedParamsAddUInt(&params, &nparams, &maxparams,
+                                VIR_MIGRATE_PARAM_SUSE_ABORT_IF_BUSY, 1) < 0)
+            goto save_error;
+    }
+
     if (vshCommandOptStringReq(ctl, cmd, "xml", &opt) < 0)
         goto out;
     if (opt) {
openSUSE Build Service is sponsored by