This adds a new flag, VIR_MIGRATE_PAUSED, that mandates pausing
the migrated VM before starting it.
* include/libvirt/libvirt.h.in (virDomainMigrateFlags): Add
VIR_MIGRATE_PAUSED.
* src/libvirt.c (virDomainMigrateVersion2): "Optimize" combination of
VIR_MIGRATE_LIVE and VIR_MIGRATE_PAUSED.
* src/qemu/qemu_driver.c (qemudDomainMigrateFinish2): Handle
VIR_MIGRATE_PAUSED.
* tools/virsh.c (opts_migrate): Add --suspend.
(cmdMigrate): Handle it.
* tools/virsh.pod (migrate): Document it.
* docs/libvirt-api.xml: Regenerate.
* docs/libvirt-refs.xml: Regenerate.
---
I'm including regenerated files to aid whoever commits the
patch.
docs/libvirt-api.xml | 9 ++++++---
docs/libvirt-refs.xml | 14 ++++++++++++++
include/libvirt/libvirt.h.in | 1 +
src/libvirt.c | 9 ++++++++-
src/qemu/qemu_driver.c | 28 ++++++++++++++++++----------
tools/virsh.c | 4 ++++
tools/virsh.pod | 7 ++++---
7 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/docs/libvirt-api.xml b/docs/libvirt-api.xml
index 88dc246..f93980b 100644
--- a/docs/libvirt-api.xml
+++ b/docs/libvirt-api.xml
@@ -47,6 +47,7 @@
<exports symbol='VIR_MIGRATE_LIVE' type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_STOPPED_DESTROYED'
type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_DEFINED_ADDED'
type='enum'/>
+ <exports symbol='VIR_STORAGE_POOL_DELETE_NORMAL'
type='enum'/>
<exports symbol='VIR_SECRET_USAGE_TYPE_NONE' type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_STARTED_MIGRATED'
type='enum'/>
<exports symbol='VIR_STREAM_EVENT_HANGUP' type='enum'/>
@@ -63,7 +64,7 @@
<exports symbol='VIR_EVENT_HANDLE_WRITABLE' type='enum'/>
<exports symbol='VIR_STORAGE_POOL_BUILD_NEW' type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_SUSPENDED_PAUSED'
type='enum'/>
- <exports symbol='VIR_STORAGE_POOL_DELETE_NORMAL'
type='enum'/>
+ <exports symbol='VIR_MIGRATE_PAUSED' type='enum'/>
<exports symbol='VIR_MEMORY_PHYSICAL' type='enum'/>
<exports symbol='VIR_DOMAIN_SCHED_FIELD_INT' type='enum'/>
<exports symbol='VIR_DOMAIN_SCHED_FIELD_ULLONG' type='enum'/>
@@ -718,7 +719,8 @@
<enum name='VIR_FROM_XML' file='virterror' value='5'
type='virErrorDomain' info='Error in the XML code'/>
<enum name='VIR_MEMORY_PHYSICAL' file='libvirt' value='2'
type='virDomainMemoryFlags' info=' addresses are physical addresses'/>
<enum name='VIR_MEMORY_VIRTUAL' file='libvirt' value='1'
type='virDomainMemoryFlags' info='addresses are virtual addresses'/>
- <enum name='VIR_MIGRATE_LIVE' file='libvirt' value='1'
type='virDomainMigrateFlags' info=' live migration'/>
+ <enum name='VIR_MIGRATE_LIVE' file='libvirt' value='1'
type='virDomainMigrateFlags' info='live migration'/>
+ <enum name='VIR_MIGRATE_PAUSED' file='libvirt' value='2'
type='virDomainMigrateFlags' info=' pause on remote side'/>
<enum name='VIR_SECRET_USAGE_TYPE_NONE' file='libvirt'
value='0' type='virSecretUsageType'/>
<enum name='VIR_SECRET_USAGE_TYPE_VOLUME' file='libvirt'
value='1' type='virSecretUsageType' info=' Expect more owner types
later...'/>
<enum name='VIR_STORAGE_POOL_BUILDING' file='libvirt'
value='1' type='virStoragePoolState' info='Initializing pool, not
available'/>
@@ -1595,7 +1597,8 @@ connection you should split large requests to <= 65536
bytes.]]></info>
host given by dconn (a connection to the destination host).
Flags may be one of more of the following:
- VIR_MIGRATE_LIVE Attempt a live migration.
+ VIR_MIGRATE_LIVE Attempt a live migration.
+ VIR_MIGRATE_PAUSED Leave the domain suspended on the remote side.
If a hypervisor supports renaming domains during migration,
then you may set the dname parameter to the new name (otherwise
diff --git a/docs/libvirt-refs.xml b/docs/libvirt-refs.xml
index 08034e4..b72ecf2 100644
--- a/docs/libvirt-refs.xml
+++ b/docs/libvirt-refs.xml
@@ -154,6 +154,7 @@
<reference name='VIR_MEMORY_PHYSICAL'
href='html/libvirt-libvirt.html#VIR_MEMORY_PHYSICAL'/>
<reference name='VIR_MEMORY_VIRTUAL'
href='html/libvirt-libvirt.html#VIR_MEMORY_VIRTUAL'/>
<reference name='VIR_MIGRATE_LIVE'
href='html/libvirt-libvirt.html#VIR_MIGRATE_LIVE'/>
+ <reference name='VIR_MIGRATE_PAUSED'
href='html/libvirt-libvirt.html#VIR_MIGRATE_PAUSED'/>
<reference name='VIR_NODEINFO_MAXCPUS'
href='html/libvirt-libvirt.html#VIR_NODEINFO_MAXCPUS'/>
<reference name='VIR_SECRET_USAGE_TYPE_NONE'
href='html/libvirt-libvirt.html#VIR_SECRET_USAGE_TYPE_NONE'/>
<reference name='VIR_SECRET_USAGE_TYPE_VOLUME'
href='html/libvirt-libvirt.html#VIR_SECRET_USAGE_TYPE_VOLUME'/>
@@ -659,6 +660,7 @@
<ref name='VIR_MEMORY_PHYSICAL'/>
<ref name='VIR_MEMORY_VIRTUAL'/>
<ref name='VIR_MIGRATE_LIVE'/>
+ <ref name='VIR_MIGRATE_PAUSED'/>
<ref name='VIR_NODEINFO_MAXCPUS'/>
<ref name='VIR_SECRET_USAGE_TYPE_NONE'/>
<ref name='VIR_SECRET_USAGE_TYPE_VOLUME'/>
@@ -1596,6 +1598,7 @@
<ref name='VIR_MEMORY_PHYSICAL'/>
<ref name='VIR_MEMORY_VIRTUAL'/>
<ref name='VIR_MIGRATE_LIVE'/>
+ <ref name='VIR_MIGRATE_PAUSED'/>
<ref name='VIR_NODEINFO_MAXCPUS'/>
<ref name='VIR_SECRET_USAGE_TYPE_NONE'/>
<ref name='VIR_SECRET_USAGE_TYPE_VOLUME'/>
@@ -2463,6 +2466,9 @@
<word name='Launch'>
<ref name='virDomainCreateXML'/>
</word>
+ <word name='Leave'>
+ <ref name='virDomainMigrate'/>
+ </word>
<word name='Length'>
<ref name='_virConnectCredential'/>
</word>
@@ -2912,6 +2918,9 @@
<word name='VIR_MIGRATE_LIVE'>
<ref name='virDomainMigrate'/>
</word>
+ <word name='VIR_MIGRATE_PAUSED'>
+ <ref name='virDomainMigrate'/>
+ </word>
<word name='VIR_SECRET_USAGE_TYPE_VOLUME'>
<ref name='virSecretGetUsageID'/>
</word>
@@ -6569,6 +6578,7 @@
<ref name='virDomainBlockPeek'/>
<ref name='virDomainCoreDump'/>
<ref name='virDomainMemoryPeek'/>
+ <ref name='virDomainMigrate'/>
<ref name='virStoragePoolRefresh'/>
</word>
<word name='remove'>
@@ -6954,6 +6964,9 @@
<ref name='virDomainDestroy'/>
<ref name='virNetworkDestroy'/>
</word>
+ <word name='side'>
+ <ref name='virDomainMigrate'/>
+ </word>
<word name='significant'>
<ref name='virDomainPinVcpu'/>
</word>
@@ -7239,6 +7252,7 @@
<ref name='virDomainSave'/>
</word>
<word name='suspended'>
+ <ref name='virDomainMigrate'/>
<ref name='virDomainResume'/>
</word>
<word name='synchronization'>
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 4e63e48..0bc0c06 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -337,6 +337,7 @@ typedef virDomainInterfaceStatsStruct *virDomainInterfaceStatsPtr;
/* Domain migration flags. */
typedef enum {
VIR_MIGRATE_LIVE = 1, /* live migration */
+ VIR_MIGRATE_PAUSED = 2, /* pause on remote side */
} virDomainMigrateFlags;
/* Domain migration. */
diff --git a/src/libvirt.c b/src/libvirt.c
index dacf8c4..8569fcb 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3057,7 +3057,8 @@ virDomainMigrateVersion2 (virDomainPtr domain,
* host given by dconn (a connection to the destination host).
*
* Flags may be one of more of the following:
- * VIR_MIGRATE_LIVE Attempt a live migration.
+ * VIR_MIGRATE_LIVE Attempt a live migration.
+ * VIR_MIGRATE_PAUSED Leave the domain suspended on the remote side.
*
* If a hypervisor supports renaming domains during migration,
* then you may set the dname parameter to the new name (otherwise
@@ -3106,6 +3107,12 @@ virDomainMigrate (virDomainPtr domain,
virResetLastError();
+ if ((flags & VIR_MIGRATE_PAUSED)) {
+ /* Not doing migration live in this case reduces traffic,
+ and the effect is not visible. */
+ flags &= ~VIR_MIGRATE_LIVE;
+ }
+
/* First checkout the source */
if (!VIR_IS_CONNECTED_DOMAIN (domain)) {
virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3d5ef92..d0b2942 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6131,21 +6131,29 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
if (retcode == 0) {
dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
- /* run 'cont' on the destination, which allows migration on qemu
- * >= 0.10.6 to work properly. This isn't strictly necessary on
- * older qemu's, but it also doesn't hurt anything there
- */
- if (qemuMonitorStartCPUs(dconn, vm) < 0) {
- if (virGetLastError() == NULL)
- qemudReportError(dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("resume operation
failed"));
- goto cleanup;
+ if (!(flags & VIR_MIGRATE_PAUSED)) {
+ /* run 'cont' on the destination, which allows migration on qemu
+ * >= 0.10.6 to work properly. This isn't strictly necessary on
+ * older qemu's, but it also doesn't hurt anything there
+ */
+ if (qemuMonitorStartCPUs(dconn, vm) < 0) {
+ if (virGetLastError() == NULL)
+ qemudReportError(dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("resume operation
failed"));
+ goto cleanup;
+ }
+ vm->state = VIR_DOMAIN_RUNNING;
}
- vm->state = VIR_DOMAIN_RUNNING;
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_RESUMED,
VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+ if (vm->state == VIR_DOMAIN_PAUSED) {
+ qemuDomainEventQueue(driver, event);
+ event = virDomainEventNewFromObj(vm,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
+ }
virDomainSaveStatus(dconn, driver->stateDir, vm);
} else {
qemudShutdownVMDaemon (dconn, driver, vm);
diff --git a/tools/virsh.c b/tools/virsh.c
index 3482389..307807e 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -2462,6 +2462,7 @@ static const vshCmdInfo info_migrate[] = {
static const vshCmdOptDef opts_migrate[] = {
{"live", VSH_OT_BOOL, 0, gettext_noop("live migration")},
+ {"suspend", VSH_OT_BOOL, 0, gettext_noop("do not restart the domain on
the destination host")},
{"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")},
@@ -2499,6 +2500,9 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
if (vshCommandOptBool (cmd, "live"))
flags |= VIR_MIGRATE_LIVE;
+ if (vshCommandOptBool (cmd, "suspend"))
+ flags |= VIR_MIGRATE_PAUSED;
+
/* Temporarily connect to the destination host. */
dconn = virConnectOpenAuth (desturi, virConnectAuthPtrDefault, 0);
if (!dconn) goto done;
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 55ec64a..34c9b34 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -303,10 +303,11 @@ except that it does some error checking.
The editor used can be supplied by the C<$EDITOR> environment
variable, or if that is not defined defaults to C<vi>.
-=item B<migrate> optional I<--live> I<domain-id> I<desturi>
I<migrateuri>
+=item B<migrate> optional I<--live> I<--suspend> I<domain-id>
I<desturi> I<migrateuri>
-Migrate domain to another host. Add --live for live migration. The I<desturi>
-is the connection URI of the destination host, and I<migrateuri> is the
+Migrate domain to another host. Add --live for live migration; --suspend
+leaves the domain paused on the destination host. The I<desturi> is the
+connection URI of the destination host, and I<migrateuri> is the
migration URI, which usually can be omitted.
=item B<reboot> I<domain-id>
--
1.6.2.5