]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
list: add virDomainListAllSnapshots API
authorEric Blake <eblake@redhat.com>
Wed, 23 May 2012 16:40:50 +0000 (10:40 -0600)
committerEric Blake <eblake@redhat.com>
Tue, 19 Jun 2012 19:50:03 +0000 (13:50 -0600)
There was an inherent race between virDomainSnapshotNum() and
virDomainSnapshotListNames(), where an additional snapshot could
be created in the meantime, or where a snapshot could be deleted
before converting the name back to a virDomainSnapshotPtr.  It
was also an awkward name: the function operates on domains, not
domain snapshots.  virDomainSnapshotListChildrenNames() suffered
from the same inherent race, although its naming was nicer.

This patch makes things nicer by grabbing a snapshot list
atomically, in the format most useful to the user.

* include/libvirt/libvirt.h.in (virDomainListAllSnapshots)
(virDomainSnapshotListAllChildren): New declarations.
* src/libvirt.c (virDomainSnapshotListNames)
(virDomainSnapshotListChildrenNames): Add cross-references.
(virDomainListAllSnapshots, virDomainSnapshotListAllChildren):
New functions.
* src/libvirt_public.syms (LIBVIRT_0.9.13): Export them.
* src/driver.h (virDrvDomainListAllSnapshots)
(virDrvDomainSnapshotListAllChildren): New callbacks.
* python/generator.py (skip_function): Prepare for later
hand-written versions.

include/libvirt/libvirt.h.in
python/generator.py
src/driver.h
src/libvirt.c
src/libvirt_public.syms

index 0504a1c384b7496d6b4da08f3c8c5cff6af50019..024c4ec552bd1b273c0bd004a7db83bac609e038 100644 (file)
@@ -3390,7 +3390,8 @@ char *virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
  *
  * Flags valid for virDomainSnapshotNum(),
  * virDomainSnapshotListNames(), virDomainSnapshotNumChildren(), and
- * virDomainSnapshotListChildrenNames().  Note that the interpretation
+ * virDomainSnapshotListChildrenNames(), virDomainListAllSnapshots(),
+ * and virDomainSnapshotListAllChildren().  Note that the interpretation
  * of flag (1<<0) depends on which function it is passed to; but serves
  * to toggle the per-call default of whether the listing is shallow or
  * recursive.  Remaining bits come in groups; if all bits from a group are
@@ -3423,6 +3424,11 @@ int virDomainSnapshotNum(virDomainPtr domain, unsigned int flags);
 int virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
                                unsigned int flags);
 
+/* Get all snapshot objects for this domain */
+int virDomainListAllSnapshots(virDomainPtr domain,
+                              virDomainSnapshotPtr **snaps,
+                              unsigned int flags);
+
 /* Return the number of child snapshots for this snapshot */
 int virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
                                  unsigned int flags);
@@ -3432,6 +3438,11 @@ int virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
                                        char **names, int nameslen,
                                        unsigned int flags);
 
+/* Get all snapshot object children for this snapshot */
+int virDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
+                                     virDomainSnapshotPtr **snaps,
+                                     unsigned int flags);
+
 /* Get a handle to a named snapshot */
 virDomainSnapshotPtr virDomainSnapshotLookupByName(virDomainPtr domain,
                                                    const char *name,
index 0b6ac7c2ab8635426fcd482c3ee2058fb98ab479..2dada6e17401d0b89c06903c4ef2c8755439ee31 100755 (executable)
@@ -454,6 +454,8 @@ skip_function = (
     'virSaveLastError', # We have our own python error wrapper
     'virFreeError', # Only needed if we use virSaveLastError
     'virConnectListAllDomains', #overridden in virConnect.py
+    'virDomainListAllSnapshots', # overridden in virDomain.py
+    'virDomainSnapshotListAllChildren', # overridden in virDomainSnapshot.py
 
     'virStreamRecvAll', # Pure python libvirt-override-virStream.py
     'virStreamSendAll', # Pure python libvirt-override-virStream.py
index 09a8adf99799acf00fb2eacb21cb135960fc29a2..b3c1740a5ec561ba850c01b8cfdc43f5d9947b15 100644 (file)
@@ -627,6 +627,11 @@ typedef int
                                      int nameslen,
                                      unsigned int flags);
 
+typedef int
+    (*virDrvDomainListAllSnapshots)(virDomainPtr domain,
+                                    virDomainSnapshotPtr **snaps,
+                                    unsigned int flags);
+
 typedef int
     (*virDrvDomainSnapshotNumChildren)(virDomainSnapshotPtr snapshot,
                                        unsigned int flags);
@@ -637,6 +642,11 @@ typedef int
                                              int nameslen,
                                              unsigned int flags);
 
+typedef int
+    (*virDrvDomainSnapshotListAllChildren)(virDomainSnapshotPtr snapshot,
+                                           virDomainSnapshotPtr **snaps,
+                                           unsigned int flags);
+
 typedef virDomainSnapshotPtr
     (*virDrvDomainSnapshotLookupByName)(virDomainPtr domain,
                                         const char *name,
@@ -993,8 +1003,10 @@ struct _virDriver {
     virDrvDomainSnapshotGetXMLDesc      domainSnapshotGetXMLDesc;
     virDrvDomainSnapshotNum             domainSnapshotNum;
     virDrvDomainSnapshotListNames       domainSnapshotListNames;
+    virDrvDomainListAllSnapshots        domainListAllSnapshots;
     virDrvDomainSnapshotNumChildren     domainSnapshotNumChildren;
     virDrvDomainSnapshotListChildrenNames domainSnapshotListChildrenNames;
+    virDrvDomainSnapshotListAllChildren domainSnapshotListAllChildren;
     virDrvDomainSnapshotLookupByName    domainSnapshotLookupByName;
     virDrvDomainHasCurrentSnapshot      domainHasCurrentSnapshot;
     virDrvDomainSnapshotGetParent       domainSnapshotGetParent;
index 748791f3306e65a39d8e1697f94bbe75f06148a8..0aa50cb6e9558b433a788931f49c906bfc62e1f6 100644 (file)
@@ -17123,9 +17123,8 @@ error:
  * @flags: bitwise-OR of supported virDomainSnapshotListFlags
  *
  * Collect the list of domain snapshots for the given domain, and store
- * their names in @names.  Caller is responsible for freeing each member
- * of the array.  The value to use for @nameslen can be determined by
- * virDomainSnapshotNum() with the same @flags.
+ * their names in @names.  The value to use for @nameslen can be determined
+ * by virDomainSnapshotNum() with the same @flags.
  *
  * By default, this command covers all snapshots; it is also possible to
  * limit things to just snapshots with no parents, when @flags includes
@@ -17149,14 +17148,17 @@ error:
  * whether they have metadata that would prevent the removal of the last
  * reference to a domain.
  *
- * Returns the number of domain snapshots found or -1 in case of error.
  * Note that this command is inherently racy: another connection can
  * define a new snapshot between a call to virDomainSnapshotNum() and
  * this call.  You are only guaranteed that all currently defined
  * snapshots were listed if the return is less than @nameslen.  Likewise,
  * you should be prepared for virDomainSnapshotLookupByName() to fail when
  * converting a name from this call into a snapshot object, if another
- * connection deletes the snapshot in the meantime.
+ * connection deletes the snapshot in the meantime.  For more control over
+ * the results, see virDomainListAllSnapshots().
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ * The caller is responsible for freeing each member of the array.
  */
 int
 virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
@@ -17194,6 +17196,81 @@ error:
     return -1;
 }
 
+/**
+ * virDomainListAllSnapshots:
+ * @domain: a domain object
+ * @snaps: pointer to variable to store the array containing snapshot objects,
+ *         or NULL if the list is not required (just returns number of
+ *         snapshots)
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Collect the list of domain snapshots for the given domain, and allocate
+ * an array to store those objects.  This API solves the race inherent in
+ * virDomainSnapshotListNames().
+ *
+ * By default, this command covers all snapshots; it is also possible to
+ * limit things to just snapshots with no parents, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_ROOTS.  Additional filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * Returns the number of domain snapshots found or -1 and sets @snaps to
+ * NULL in case of error.  On success, the array stored into @snaps is
+ * guaranteed to have an extra allocated element set to NULL but not included
+ * in the return count, to make iteration easier.  The caller is responsible
+ * for calling virDomainSnapshotFree() on each array element, then calling
+ * free() on @snaps.
+ */
+int
+virDomainListAllSnapshots(virDomainPtr domain, virDomainSnapshotPtr **snaps,
+                          unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "snaps=%p, flags=%x", snaps, flags);
+
+    virResetLastError();
+
+    if (snaps)
+        *snaps = NULL;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainListAllSnapshots) {
+        int ret = conn->driver->domainListAllSnapshots(domain, snaps, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    virDispatchError(conn);
+    return -1;
+}
+
 /**
  * virDomainSnapshotNumChildren:
  * @snapshot: a domain snapshot object
@@ -17263,9 +17340,9 @@ error:
  * @flags: bitwise-OR of supported virDomainSnapshotListFlags
  *
  * Collect the list of domain snapshots that are children of the given
- * snapshot, and store their names in @names.  Caller is responsible for
- * freeing each member of the array.  The value to use for @nameslen can
- * be determined by virDomainSnapshotNumChildren() with the same @flags.
+ * snapshot, and store their names in @names.  The value to use for
+ * @nameslen can be determined by virDomainSnapshotNumChildren() with
+ * the same @flags.
  *
  * By default, this command covers only direct children; it is also possible
  * to expand things to cover all descendants, when @flags includes
@@ -17296,7 +17373,11 @@ error:
  * snapshots were listed if the return is less than @nameslen.  Likewise,
  * you should be prepared for virDomainSnapshotLookupByName() to fail when
  * converting a name from this call into a snapshot object, if another
- * connection deletes the snapshot in the meantime.
+ * connection deletes the snapshot in the meantime.  For more control over
+ * the results, see virDomainSnapshotListAllChildren().
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ * The caller is responsible for freeing each member of the array.
  */
 int
 virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
@@ -17338,6 +17419,84 @@ error:
     return -1;
 }
 
+/**
+ * virDomainSnapshotListAllChildren:
+ * @snapshot: a domain snapshot object
+ * @snaps: pointer to variable to store the array containing snapshot objects,
+ *         or NULL if the list is not required (just returns number of
+ *         snapshots)
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Collect the list of domain snapshots that are children of the given
+ * snapshot, and allocate an array to store those objects.  This API solves
+ * the race inherent in virDomainSnapshotListChildrenNames().
+ *
+ * By default, this command covers only direct children; it is also possible
+ * to expand things to cover all descendants, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS.  Also, some filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * Returns the number of domain snapshots found or -1 and sets @snaps to
+ * NULL in case of error.  On success, the array stored into @snaps is
+ * guaranteed to have an extra allocated element set to NULL but not included
+ * in the return count, to make iteration easier.  The caller is responsible
+ * for calling virDomainSnapshotFree() on each array element, then calling
+ * free() on @snaps.
+ */
+int
+virDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
+                                 virDomainSnapshotPtr **snaps,
+                                 unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, snaps=%p, flags=%x", snapshot, snaps, flags);
+
+    virResetLastError();
+
+    if (snaps)
+        *snaps = NULL;
+
+    if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+        virLibDomainSnapshotError(VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
+                                  __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    conn = snapshot->domain->conn;
+
+    if (conn->driver->domainSnapshotListAllChildren) {
+        int ret = conn->driver->domainSnapshotListAllChildren(snapshot, snaps,
+                                                              flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    virDispatchError(conn);
+    return -1;
+}
+
 /**
  * virDomainSnapshotLookupByName:
  * @domain: a domain object
index ea49a68dbf4a91abe4bda52661c8693e4d0d511f..2913a819095a092c3d51561d1456a2aac380d5e8 100644 (file)
@@ -537,8 +537,10 @@ LIBVIRT_0.9.11 {
 LIBVIRT_0.9.13 {
     global:
         virConnectListAllDomains;
+        virDomainListAllSnapshots;
         virDomainSnapshotHasMetadata;
         virDomainSnapshotIsCurrent;
+        virDomainSnapshotListAllChildren;
         virDomainSnapshotRef;
 } LIBVIRT_0.9.11;