From 3221868c5ca0be83d4e5f9a9f489e73d5b509a6e Mon Sep 17 00:00:00 2001 From: Jim Fehlig Date: Tue, 5 Jul 2022 11:26:24 -0600 Subject: libvirt: set migration constraints from cmdline References: fate#316614 Signed-off-by: Olaf Hering --- 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(¶ms, &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(¶ms, &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(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_SUSE_MIN_REMAINING, uint_opt) < 0) + goto save_error; + } + if (vshCommandOptBool(cmd, "abort_if_busy")) { + if (virTypedParamsAddUInt(¶ms, &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) {