[libvirt] [PATCH 4/6] add virsh --suspend

Paolo Bonzini pbonzini at redhat.com
Thu Oct 1 18:18:31 UTC 2009


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





More information about the libvir-list mailing list