diff --git a/build-aux/.gitignore b/build-aux/.gitignore index af7a347..043aafa 100644 --- a/build-aux/.gitignore +++ b/build-aux/.gitignore @@ -5,3 +5,4 @@ /gitlog-to-changelog /useless-if-before-free /vc-list-files +/warn-on-use.h diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 260505e..2b867fe 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -397,6 +397,9 @@ typedef enum { VIR_MIGRATE_PERSIST_DEST = (1 << 3), /* persist the VM on the destination */ VIR_MIGRATE_UNDEFINE_SOURCE = (1 << 4), /* undefine the VM on the source */ VIR_MIGRATE_PAUSED = (1 << 5), /* pause on remote side */ + VIR_MIGRATE_NON_SHARED_DISK = (1 << 6), /* migration with non-shared storage with full disk copy */ + VIR_MIGRATE_NON_SHARED_INC = (1 << 7), /* migration with non-shared storage with incremental copy */ + /* (same base image shared between source and destination) */ } virDomainMigrateFlags; /* Domain migration. */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 30742fc..7328dfe 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7889,7 +7889,7 @@ cleanup: static int doNativeMigrate(struct qemud_driver *driver, virDomainObjPtr vm, const char *uri, - unsigned long flags ATTRIBUTE_UNUSED, + unsigned long flags , const char *dname ATTRIBUTE_UNUSED, unsigned long resource) { @@ -7898,6 +7898,7 @@ static int doNativeMigrate(struct qemud_driver *driver, int status; unsigned long long transferred, remaining, total; qemuDomainObjPrivatePtr priv = vm->privateData; + int background_flags = 0; /* Issue the migrate command. */ if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) { @@ -7925,7 +7926,13 @@ static int doNativeMigrate(struct qemud_driver *driver, goto cleanup; } - if (qemuMonitorMigrateToHost(priv->mon, 0, uribits->server, uribits->port) < 0) { + if (flags & VIR_MIGRATE_NON_SHARED_DISK) + background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; + + if (flags & VIR_MIGRATE_NON_SHARED_INC) + background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC; + + if (qemuMonitorMigrateToHost(priv->mon, background_flags, uribits->server, uribits->port) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); goto cleanup; } @@ -8013,6 +8020,7 @@ static int doTunnelMigrate(virDomainPtr dom, unsigned long long qemuCmdFlags; int status; unsigned long long transferred, remaining, total; + int background_flags = 0; /* * The order of operations is important here to avoid touching @@ -8097,12 +8105,19 @@ static int doTunnelMigrate(virDomainPtr dom, goto cleanup; /* 3. start migration on source */ + background_flags = QEMU_MONITOR_MIGRATE_BACKGROUND; + if (flags & VIR_MIGRATE_NON_SHARED_DISK) + background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; + + if (flags & VIR_MIGRATE_NON_SHARED_INC) + background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC; + qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX) - internalret = qemuMonitorMigrateToUnix(priv->mon, 1, unixfile); + internalret = qemuMonitorMigrateToUnix(priv->mon, background_flags, unixfile); else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) { const char *args[] = { "nc", "-U", unixfile, NULL }; - internalret = qemuMonitorMigrateToCommand(priv->mon, 1, args, "/dev/null"); + internalret = qemuMonitorMigrateToCommand(priv->mon, background_flags, args, "/dev/null"); } else { internalret = -1; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 786ad7a..a02e14f 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -190,6 +190,13 @@ int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon, unsigned long long *remaining, unsigned long long *total); +typedef enum { + QEMU_MONITOR_MIGRATE_BACKGROUND = 1 << 0, + QEMU_MONITOR_MIGRATE_NON_SHARED_DISK = 1 << 1, /* migration with non-shared storage with full disk copy */ + QEMU_MONITOR_MIGRATE_NON_SHARED_INC = 1 << 2, /* migration with non-shared storage with incremental copy */ + QEMU_MONITOR_MIGRATION_FLAGS_LAST +}; + int qemuMonitorMigrateToHost(qemuMonitorPtr mon, int background, const char *hostname, diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index e993699..a402eeb 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1053,18 +1053,19 @@ static int qemuMonitorTextMigrate(qemuMonitorPtr mon, char *info = NULL; int ret = -1; char *safedest = qemuMonitorEscapeArg(dest); - const char *extra; + //const char *extra; + const char extra[25] = " "; if (!safedest) { virReportOOMError(); return -1; } - - if (background) - extra = "-d "; - else - extra = " "; - + if (background & QEMU_MONITOR_MIGRATE_BACKGROUND) + strcat(extra," -d"); + if (background & QEMU_MONITOR_MIGRATE_NON_SHARED_DISK) + strcat(extra," -b"); + if (background & QEMU_MONITOR_MIGRATE_NON_SHARED_INC) + strcat(extra," -i"); if (virAsprintf(&cmd, "migrate %s\"%s\"", extra, safedest) < 0) { virReportOOMError(); goto cleanup; diff --git a/tools/virsh.c b/tools/virsh.c index 7db48d9..53d7548 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2545,6 +2545,8 @@ static const vshCmdOptDef opts_migrate[] = { {"persistent", VSH_OT_BOOL, 0, gettext_noop("persist VM on destination")}, {"undefinesource", VSH_OT_BOOL, 0, gettext_noop("undefine VM on source")}, {"suspend", VSH_OT_BOOL, 0, gettext_noop("do not restart the domain on the destination host")}, + {"non_shared_disk", VSH_OT_BOOL, 0, gettext_noop("migration with non-shared storage with full disk copy")}, + {"non_shared_inc", VSH_OT_BOOL, 0, gettext_noop("migration with non-shared storage with incremental copy (same base image shared between source and destination)")}, {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, {"desturi", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("connection URI of the destination host")}, {"migrateuri", VSH_OT_DATA, 0, gettext_noop("migration URI, usually can be omitted")}, @@ -2592,6 +2594,13 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool (cmd, "suspend")) flags |= VIR_MIGRATE_PAUSED; + if (vshCommandOptBool (cmd, "non_shared_disk")) + flags |= VIR_MIGRATE_NON_SHARED_DISK; + + if (vshCommandOptBool (cmd, "non_shared_inc")) + flags |= VIR_MIGRATE_NON_SHARED_INC; + + if ((flags & VIR_MIGRATE_PEER2PEER) || vshCommandOptBool (cmd, "direct")) { /* For peer2peer migration or direct migration we only expect one URI