Signed-off-by: Cristian Klein <cristian.klein(a)cs.umu.se>
---
tools/virsh-domain.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++--
tools/virsh.pod | 5 ++++
2 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 36a6d52..395c73c 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -9251,6 +9251,10 @@ static const vshCmdOptDef opts_migrate[] = {
.type = VSH_OT_INT,
.help = N_("force guest to suspend if live migration exceeds timeout (in
seconds)")
},
+ {.name = "postcopy-after",
+ .type = VSH_OT_INT,
+ .help = N_("switch to post-copy migration if live migration exceeds timeout (in
seconds)")
+ },
{.name = "xml",
.type = VSH_OT_STRING,
.help = N_("filename containing updated XML for the target")
@@ -9332,6 +9336,8 @@ doMigrate(void *opaque)
VIR_FREE(xml);
}
+ if (vshCommandOptBool(cmd, "postcopy-after")) /* actually an int */
+ flags |= VIR_MIGRATE_POSTCOPY;
if (vshCommandOptBool(cmd, "live"))
flags |= VIR_MIGRATE_LIVE;
if (vshCommandOptBool(cmd, "p2p"))
@@ -9423,6 +9429,50 @@ vshMigrationTimeout(vshControl *ctl,
virDomainSuspend(dom);
}
+static void
+vshMigrationPostCopyAfter(vshControl *ctl,
+ virDomainPtr dom,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ vshDebug(ctl, VSH_ERR_DEBUG, "starting post-copy\n");
+ int rv = virDomainMigrateStartPostCopy(dom, 0);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("start post-copy command failed"));
+ } else {
+ vshDebug(ctl, VSH_ERR_INFO, "switched to post-copy\n");
+ }
+}
+
+/* Parse the --postcopy-after parameter in seconds, but store its
+ * value in milliseconds. Return -1 on error, 0 if
+ * no timeout was requested, and 1 if timeout was set.
+ * Copy-paste-adapted from vshCommandOptTimeoutToMs.
+ */
+static int
+vshCommandOptPostCopyAfterToMs(vshControl *ctl, const vshCmd *cmd, int *postCopyAfter)
+{
+ int rv = vshCommandOptInt(cmd, "postcopy-after", postCopyAfter);
+
+ if (rv < 0 || (rv > 0 && *postCopyAfter < 0)) {
+ vshError(ctl, "%s", _("invalid postcopy-after parameter"));
+ return -1;
+ }
+ if (rv > 0) {
+ /* Ensure that we can multiply by 1000 without overflowing. */
+ if (*postCopyAfter > INT_MAX / 1000) {
+ vshError(ctl, "%s", _("post-copy after parameter is too
big"));
+ return -1;
+ }
+ *postCopyAfter *= 1000;
+ /* 0 is a special value inside virsh, which means no timeout, so
+ * use 1ms instead for "start post-copy immediately"
+ */
+ if (*postCopyAfter == 0)
+ *postCopyAfter = 1;
+ }
+ return rv;
+}
+
static bool
cmdMigrate(vshControl *ctl, const vshCmd *cmd)
{
@@ -9432,6 +9482,7 @@ cmdMigrate(vshControl *ctl, const vshCmd *cmd)
bool verbose = false;
bool functionReturn = false;
int timeout = 0;
+ int postCopyAfter = 0;
bool live_flag = false;
vshCtrlData data = { .dconn = NULL };
@@ -9451,6 +9502,18 @@ cmdMigrate(vshControl *ctl, const vshCmd *cmd)
goto cleanup;
}
+ if (vshCommandOptPostCopyAfterToMs(ctl, cmd, &postCopyAfter) < 0) {
+ goto cleanup;
+ } else if (postCopyAfter > 0 && !live_flag) {
+ vshError(ctl, "%s",
+ _("migrate: Unexpected postcopy-after for offline
migration"));
+ goto cleanup;
+ } else if (postCopyAfter > 0 && timeout > 0) {
+ vshError(ctl, "%s",
+ _("migrate: --postcopy-after is incompatible with
--timeout"));
+ goto cleanup;
+ }
+
if (pipe(p) < 0)
goto cleanup;
@@ -9480,8 +9543,13 @@ cmdMigrate(vshControl *ctl, const vshCmd *cmd)
doMigrate,
&data) < 0)
goto cleanup;
- functionReturn = vshWatchJob(ctl, dom, verbose, p[0], timeout,
- vshMigrationTimeout, NULL, _("Migration"));
+ if (postCopyAfter != 0) {
+ functionReturn = vshWatchJob(ctl, dom, verbose, p[0], postCopyAfter,
+ vshMigrationPostCopyAfter, NULL,
_("Migration"));
+ } else {
+ functionReturn = vshWatchJob(ctl, dom, verbose, p[0], timeout,
+ vshMigrationTimeout, NULL,
_("Migration"));
+ }
virThreadJoin(&workerThread);
diff --git a/tools/virsh.pod b/tools/virsh.pod
index eae9195..2ae7afa 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1404,6 +1404,7 @@ to the I<uri> namespace is displayed instead of being
modified.
[I<--compressed>] [I<--abort-on-error>] [I<--auto-converge>]
I<domain> I<desturi> [I<migrateuri>] [I<graphicsuri>]
[I<listen-address>]
[I<dname>] [I<--timeout> B<seconds>] [I<--xml> B<file>]
+[I<--postcopy-after> B<seconds>]
Migrate domain to another host. Add I<--live> for live migration; <--p2p>
for peer-2-peer migration; I<--direct> for direct migration; or
I<--tunnelled>
@@ -1451,6 +1452,10 @@ I<--timeout> B<seconds> forces guest to suspend when
live migration exceeds
that many seconds, and
then the migration will complete offline. It can only be used with I<--live>.
+I<--postcopy-after> switches to post-copy migration when pre-copy migration
+exceeds that many seconds. Zero means start post-copy as soon as possible.
+It can only be used with I<--live>.
+
Running migration can be canceled by interrupting virsh (usually using
C<Ctrl-C>) or by B<domjobabort> command sent from another virsh instance.
--
1.9.1