]> xenbits.xensource.com Git - libvirt.git/commitdiff
snapshot: support extra state in snapshots
authorEric Blake <eblake@redhat.com>
Fri, 19 Aug 2011 00:14:40 +0000 (18:14 -0600)
committerEric Blake <eblake@redhat.com>
Mon, 5 Sep 2011 13:03:04 +0000 (07:03 -0600)
In order to distinguish disk snapshots from system checkpoints, a
new state value that is only valid for snapshots is helpful.

* include/libvirt/libvirt.h.in (VIR_DOMAIN_LAST): New placeholder.
* src/conf/domain_conf.h (virDomainSnapshotState): New enum mapping.
(VIR_DOMAIN_DISK_SNAPSHOT): New internal enum value.
* src/conf/domain_conf.c (virDomainState): Use placeholder.
(virDomainSnapshotState): Extend mapping by one for use in snapshot.
(virDomainSnapshotDefParseString, virDomainSnapshotDefFormat):
Handle new state.
(virDomainObjSetState, virDomainStateReasonToString)
(virDomainStateReasonFromString): Avoid compiler warnings.
* tools/virsh.c (vshDomainState, vshDomainStateReasonToString):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Export new functions.
* docs/schemas/domainsnapshot.rng: Tighten state definition.
* docs/formatsnapshot.html.in: Document it.
* tests/domainsnapshotxml2xmlout/disk_snapshot.xml: New test.

docs/formatsnapshot.html.in
docs/schemas/domainsnapshot.rng
include/libvirt/libvirt.h.in
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
tests/domainsnapshotxml2xmlout/disk_snapshot.xml [new file with mode: 0644]
tools/virsh.c

index 91799b42c7c8f53edc8137dffdf9730a6815f9df..a0940ac4ba1217370414af74a19f699035413975 100644 (file)
@@ -6,6 +6,65 @@
 
     <h2><a name="SnapshotAttributes">Snapshot XML</a></h2>
 
+    <p>
+      There are several types of snapshots:
+    </p>
+    <dl>
+      <dt>disk snapshot</dt>
+      <dd>Contents of disks (whether a subset or all disks associated
+        with the domain) are saved at a given point of time, and can
+        be restored back to that state.  On a running guest, a disk
+        snapshot is likely to be only crash-consistent rather than
+        clean (that is, it represents the state of the disk on a
+        sudden power outage, and may need fsck or journal replays to
+        be made consistent); on an inactive guest, a disk snapshot is
+        clean if the disks were clean when the guest was last shut
+        down.  Disk snapshots exist in two forms: internal (file
+        formats such as qcow2 track both the snapshot and changes
+        since the snapshot in a single file) and external (the
+        snapshot is one file, and the changes since the snapshot are
+        in another file).</dd>
+      <dt>VM state</dt>
+      <dd>Tracks only the state of RAM and all other resources in use
+        by the VM.  If the disks are unmodified between the time a VM
+        state snapshot is taken and restored, then the guest will
+        resume in a consistent state; but if the disks are modified
+        externally in the meantime, this is likely to lead to data
+        corruption.</dd>
+      <dt>system checkpoint</dt>
+      <dd>A combination of disk snapshots for all disks as well as VM
+        state, which can be used to resume the guest from where it
+        left off with symptoms similar to hibernation (that is, TCP
+        connections in the guest may have timed out, but no files or
+        processes are lost).</dd>
+    </dl>
+
+    <p>
+      Libvirt can manage all three types of snapshots.  For now, VM
+      state snapshots are created only by
+      the <code>virDomainSave()</code>, <code>virDomainSaveFlags</code>,
+      and <code>virDomainManagedSave()</code> functions, and restored
+      via the <code>virDomainRestore()</code>,
+      <code>virDomainRestoreFlags()</code>, <code>virDomainCreate()</code>,
+      and <code>virDomainCreateWithFlags()</code> functions (as well
+      as via domain autostart).  With managed snapshots, libvirt
+      tracks all information internally; with save images, the user
+      tracks the snapshot file, but libvirt provides functions such
+      as <code>virDomainSaveImageGetXMLDesc()</code> to work with
+      those files.
+    </p>
+    <p>System checkpoints are created
+      by <code>virDomainSnapshotCreateXML()</code> with no flags, and
+      disk snapshots are created by the same function with
+      the <code>VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY</code> flag; in
+      both cases, they are restored by
+      the <code>virDomainRevertToSnapshot()</code> function.  For
+      these types of snapshots, libvirt tracks each snapshot as a
+      separate <code>virDomainSnapshotPtr</code> object, and maintains
+      a tree relationship of which snapshots descended from an earlier
+      point in time.
+    </p>
+
     <p>
       Attributes of libvirt snapshots are stored as child elements of
       the <code>domainsnapshot</code> element.  At snapshot creation
       </dd>
       <dt><code>state</code></dt>
       <dd>The state of the domain at the time this snapshot was taken.
-        When the domain is reverted to this snapshot, the domain's
-        state will default to whatever is in this field.  Readonly.
+        If the snapshot was created as a system checkpoint, then this
+        is the state of the domain at that time; when the domain is
+        reverted to this snapshot, the domain's state will default to
+        whatever is in this field unless additional flags are passed
+        to <code>virDomainRevertToSnapshot()</code>.  Additionally,
+        this field can be the value "disk-snapshot"
+        (<span class="since">since 0.9.5</span>) when it represents
+        only a disk snapshot (no VM state), and reverting to this
+        snapshot will default to an inactive guest.  Readonly.
       </dd>
       <dt><code>parent</code></dt>
-      <dd>The parent of this snapshot.  This element contains exactly
-        one child element, name.  This specifies the name of the parent
-        snapshot of this snapshot, and is used to represent trees of
-        snapshots, as described above.  Readonly.
+      <dd>The parent of this snapshot.  If present, this element
+        contains exactly one child element, name.  This specifies the
+        name of the parent snapshot of this snapshot, and is used to
+        represent trees of snapshots.  Readonly.
       </dd>
       <dt><code>domain</code></dt>
       <dd>The domain that this snapshot was taken against.  Older
         created in, and requires the use of the
         <code>VIR_DOMAIN_SNAPSHOT_REVERT_FORCE</code> flag
         in <code>virDomainRevertToSnapshot()</code>.  Newer versions
-        of libvirt store the entire
+        of libvirt (<span class="since">since 0.9.5</span>) store the entire
         inactive <a href="formatdomain.html">domain configuration</a>
         at the time of the snapshot (<span class="since">since
         0.9.5</span>).  Readonly.
index a16d73132ca20d925d7b56ed9109a43a8edc8388..130dad9ca6a3eeaa18af290dd485a495a51c5157 100644 (file)
@@ -22,7 +22,7 @@
         </optional>
         <optional>
           <element name='state'>
-            <text/>
+            <ref name='state'/>
           </element>
         </optional>
         <optional>
     </element>
   </define>
 
+  <define name='state'>
+    <choice>
+      <value>nostate</value>
+      <value>running</value>
+      <value>blocked</value>
+      <value>paused</value>
+      <value>shutdown</value>
+      <value>shutoff</value>
+      <value>crashed</value>
+      <value>disk-snapshot</value>
+    </choice>
+  </define>
+
 </grammar>
index 0f0efc1a4ed0c71d6a88a07b82934ec970ff5bd1..4292736f8ac388e4df103a9a3e5acca8cb7ff617 100644 (file)
@@ -86,7 +86,14 @@ typedef enum {
      VIR_DOMAIN_PAUSED  = 3, /* the domain is paused by user */
      VIR_DOMAIN_SHUTDOWN= 4, /* the domain is being shut down */
      VIR_DOMAIN_SHUTOFF = 5, /* the domain is shut off */
-     VIR_DOMAIN_CRASHED = 6  /* the domain is crashed */
+     VIR_DOMAIN_CRASHED = 6, /* the domain is crashed */
+
+    /*
+     * NB: this enum value will increase over time as new events are
+     * added to the libvirt API. It reflects the last state supported
+     * by this version of the libvirt API.
+     */
+     VIR_DOMAIN_LAST
 } virDomainState;
 
 typedef enum {
@@ -1892,6 +1899,11 @@ typedef enum {
     VIR_KEYCODE_SET_WIN32          = 8,
     VIR_KEYCODE_SET_RFB            = 9,
 
+    /*
+     * NB: this enum value will increase over time as new events are
+     * added to the libvirt API. It reflects the last keycode set supported
+     * by this version of the libvirt API.
+     */
     VIR_KEYCODE_SET_LAST,
 } virKeycodeSet;
 
index c9e6e38bfae5665fe2a4c8e64380725482d465eb..270d02dcd206b64dab534a258e4ae355198bf8ec 100644 (file)
@@ -437,7 +437,13 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
               "usb",
               "pci")
 
-VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
+VIR_ENUM_IMPL(virDomainHub, VIR_DOMAIN_HUB_TYPE_LAST,
+              "usb")
+
+VIR_ENUM_IMPL(virDomainRedirdevBus, VIR_DOMAIN_REDIRDEV_BUS_LAST,
+              "usb")
+
+VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_LAST,
               "nostate",
               "running",
               "blocked",
@@ -446,11 +452,16 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
               "shutoff",
               "crashed")
 
-VIR_ENUM_IMPL(virDomainHub, VIR_DOMAIN_HUB_TYPE_LAST,
-              "usb")
-
-VIR_ENUM_IMPL(virDomainRedirdevBus, VIR_DOMAIN_REDIRDEV_BUS_LAST,
-              "usb")
+/* virDomainSnapshotState is really virDomainState plus one extra state */
+VIR_ENUM_IMPL(virDomainSnapshotState, VIR_DOMAIN_DISK_SNAPSHOT+1,
+              "nostate",
+              "running",
+              "blocked",
+              "paused",
+              "shutdown",
+              "shutoff",
+              "crashed",
+              "disk-snapshot")
 
 #define VIR_DOMAIN_NOSTATE_LAST (VIR_DOMAIN_NOSTATE_UNKNOWN + 1)
 VIR_ENUM_IMPL(virDomainNostateReason, VIR_DOMAIN_NOSTATE_LAST,
@@ -11486,7 +11497,7 @@ virDomainSnapshotDefParseString(const char *xmlStr,
                                  _("missing state from existing snapshot"));
             goto cleanup;
         }
-        def->state = virDomainStateTypeFromString(state);
+        def->state = virDomainSnapshotStateTypeFromString(state);
         if (def->state < 0) {
             virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                                  _("Invalid state '%s' in domain snapshot XML"),
@@ -11559,7 +11570,7 @@ char *virDomainSnapshotDefFormat(char *domain_uuid,
         virBufferEscapeString(&buf, "  <description>%s</description>\n",
                               def->description);
     virBufferAsprintf(&buf, "  <state>%s</state>\n",
-                      virDomainStateTypeToString(def->state));
+                      virDomainSnapshotStateTypeToString(def->state));
     if (def->parent) {
         virBufferAddLit(&buf, "  <parent>\n");
         virBufferEscapeString(&buf, "    <name>%s</name>\n", def->parent);
@@ -12139,6 +12150,7 @@ virDomainObjSetState(virDomainObjPtr dom, virDomainState state, int reason)
     case VIR_DOMAIN_SHUTDOWN:   last = VIR_DOMAIN_SHUTDOWN_LAST;    break;
     case VIR_DOMAIN_SHUTOFF:    last = VIR_DOMAIN_SHUTOFF_LAST;     break;
     case VIR_DOMAIN_CRASHED:    last = VIR_DOMAIN_CRASHED_LAST;     break;
+    default: last = -1;
     }
 
     if (last < 0) {
@@ -12172,9 +12184,9 @@ virDomainStateReasonToString(virDomainState state, int reason)
         return virDomainShutoffReasonTypeToString(reason);
     case VIR_DOMAIN_CRASHED:
         return virDomainCrashedReasonTypeToString(reason);
+    default:
+        return NULL;
     }
-
-    return NULL;
 }
 
 
@@ -12196,9 +12208,9 @@ virDomainStateReasonFromString(virDomainState state, const char *reason)
         return virDomainShutoffReasonTypeFromString(reason);
     case VIR_DOMAIN_CRASHED:
         return virDomainCrashedReasonTypeFromString(reason);
+    default:
+        return -1;
     }
-
-    return -1;
 }
 
 
index 7e09c0abb45aef8fbcedfa17d83eaefa97e5c790..749fcce86d3e1a2b787dfbd8ccabdadda4f7048d 100644 (file)
@@ -253,6 +253,11 @@ enum virDomainDiskSnapshot {
     VIR_DOMAIN_DISK_SNAPSHOT_LAST
 };
 
+enum virDomainSnapshotState {
+    /* Inherit the VIR_DOMAIN_* states from virDomainState.  */
+    VIR_DOMAIN_DISK_SNAPSHOT = VIR_DOMAIN_LAST,
+};
+
 /* Stores the virtual disk configuration */
 typedef struct _virDomainDiskDef virDomainDiskDef;
 typedef virDomainDiskDef *virDomainDiskDefPtr;
@@ -1395,7 +1400,7 @@ struct _virDomainSnapshotDef {
     char *description;
     char *parent;
     long long creationTime; /* in seconds */
-    int state;
+    int state; /* enum virDomainSnapshotState */
     virDomainDefPtr dom;
 
     /* Internal use.  */
@@ -1832,6 +1837,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression)
 VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode)
 VIR_ENUM_DECL(virDomainGraphicsSpiceClipboardCopypaste)
 VIR_ENUM_DECL(virDomainNumatuneMemMode)
+VIR_ENUM_DECL(virDomainSnapshotState)
 /* from libvirt.h */
 VIR_ENUM_DECL(virDomainState)
 VIR_ENUM_DECL(virDomainNostateReason)
index 60e2f14e699eac9a65f8b4fb09e068b1ecb4c815..2341110ce9c04ddf01b114d3f7e7dc4be9131e9e 100644 (file)
@@ -399,6 +399,8 @@ virDomainSnapshotHasChildren;
 virDomainSnapshotObjListGetNames;
 virDomainSnapshotObjListNum;
 virDomainSnapshotObjListRemove;
+virDomainSnapshotStateTypeFromString;
+virDomainSnapshotStateTypeToString;
 virDomainSoundDefFree;
 virDomainSoundModelTypeFromString;
 virDomainSoundModelTypeToString;
diff --git a/tests/domainsnapshotxml2xmlout/disk_snapshot.xml b/tests/domainsnapshotxml2xmlout/disk_snapshot.xml
new file mode 100644 (file)
index 0000000..391bb57
--- /dev/null
@@ -0,0 +1,35 @@
+<domainsnapshot>
+  <name>my snap name</name>
+  <description>!@#$%^</description>
+  <parent>
+    <name>earlier_snap</name>
+  </parent>
+  <state>disk-snapshot</state>
+  <creationTime>1272917631</creationTime>
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu cpuset='1-4,8-20,525'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
+  <active>1</active>
+</domainsnapshot>
index d1ebc4093ad9fbda9d69ff40540f49127662fe45..7ae5b404e02c27b8a84d2be866f719edbd526788 100644 (file)
@@ -14588,6 +14588,8 @@ vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason)
 static const char *
 vshDomainStateToString(int state)
 {
+    /* Can't use virDomainStateTypeToString, because we want to mark
+     * strings for translation.  */
     switch ((virDomainState) state) {
     case VIR_DOMAIN_RUNNING:
         return N_("running");
@@ -14602,6 +14604,7 @@ vshDomainStateToString(int state)
     case VIR_DOMAIN_CRASHED:
         return N_("crashed");
     case VIR_DOMAIN_NOSTATE:
+    default:
         ;/*FALLTHROUGH*/
     }
     return N_("no state");  /* = dom0 state */
@@ -14703,6 +14706,9 @@ vshDomainStateReasonToString(int state, int reason)
             ;
         }
         break;
+
+    default:
+        ;
     }
 
     return N_("unknown");