[libvirt] [PATCHv2 1/7] snapshot: new virDomainSnapshotListChildrenNames API

Eric Blake eblake at redhat.com
Fri Sep 30 23:09:23 UTC 2011


The previous API addition allowed traversal up the hierarchy;
this one makes it easier to traverse down the hierarchy.

In the python bindings, virDomainSnapshotNumChildren can be
generated, but virDomainSnapshotListChildrenNames had to copy
from the hand-written example of virDomainSnapshotListNames.

* include/libvirt/libvirt.h.in (virDomainSnapshotNumChildren)
(virDomainSnapshotListChildrenNames): New prototypes.
(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS): New flag alias.
* src/libvirt.c (virDomainSnapshotNumChildren)
(virDomainSnapshotListChildrenNames): New functions.
* src/libvirt_public.syms: Export them.
* src/driver.h (virDrvDomainSnapshotNumChildren)
(virDrvDomainSnapshotListChildrenNames): New callbacks.
* python/generator.py (skip_impl, nameFixup): Update lists.
* python/libvirt-override-api.xml: Likewise.
* python/libvirt-override.c
(libvirt_virDomainSnapshotListChildrenNames): New wrapper function.
---

v2: no change

 include/libvirt/libvirt.h.in    |   27 +++++++--
 python/generator.py             |    4 ++
 python/libvirt-override-api.xml |   12 +++-
 python/libvirt-override.c       |   45 ++++++++++++++++
 src/driver.h                    |   12 ++++
 src/libvirt.c                   |  111 +++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms         |    2 +
 7 files changed, 204 insertions(+), 9 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a832b65..7403a9a 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2686,13 +2686,19 @@ virDomainSnapshotPtr virDomainSnapshotCreateXML(virDomainPtr domain,
 char *virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                                   unsigned int flags);

-/* Flags valid for both virDomainSnapshotNum() and
- * virDomainSnapshotListNames().  */
+/* Flags valid for virDomainSnapshotNum(),
+ * virDomainSnapshotListNames(), virDomainSnapshotNumChildren(), and
+ * virDomainSnapshotListChildrenNames().  Note that the interpretation
+ * of flag (1<<0) depends on which function it is passed to.  */
 typedef enum {
-    VIR_DOMAIN_SNAPSHOT_LIST_ROOTS    = (1 << 0), /* Filter by snapshots which
-                                                     have no parents */
-    VIR_DOMAIN_SNAPSHOT_LIST_METADATA = (1 << 1), /* Filter by snapshots which
-                                                     have metadata */
+    VIR_DOMAIN_SNAPSHOT_LIST_ROOTS       = (1 << 0), /* Filter by snapshots
+                                                        with no parents, when
+                                                        listing a domain */
+    VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS = (1 << 0), /* List all descendants,
+                                                        not just children, when
+                                                        listing a snapshot */
+    VIR_DOMAIN_SNAPSHOT_LIST_METADATA    = (1 << 1), /* Filter by snapshots
+                                                        which have metadata */
 } virDomainSnapshotListFlags;

 /* Return the number of snapshots for this domain */
@@ -2702,6 +2708,15 @@ int virDomainSnapshotNum(virDomainPtr domain, unsigned int flags);
 int virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
                                unsigned int flags);

+/* Return the number of child snapshots for this snapshot */
+int virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
+                                 unsigned int flags);
+
+/* Get the names of all child snapshots for this snapshot */
+int virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
+                                       char **names, int nameslen,
+                                       unsigned int flags);
+
 /* Get a handle to a named snapshot */
 virDomainSnapshotPtr virDomainSnapshotLookupByName(virDomainPtr domain,
                                                    const char *name,
diff --git a/python/generator.py b/python/generator.py
index 79558dd..71afdb7 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -352,6 +352,7 @@ skip_impl = (
     'virConnectListDefinedInterfaces',
     'virConnectListNWFilters',
     'virDomainSnapshotListNames',
+    'virDomainSnapshotListChildrenNames',
     'virConnGetLastError',
     'virGetLastError',
     'virDomainGetInfo',
@@ -963,6 +964,9 @@ def nameFixup(name, classe, type, file):
     elif name[0:26] == "virDomainSnapshotListNames":
         func = name[9:]
         func = string.lower(func[0:1]) + func[1:]
+    elif name[0:28] == "virDomainSnapshotNumChildren":
+        func = name[17:]
+        func = string.lower(func[0:1]) + func[1:]
     elif name[0:20] == "virDomainSnapshotNum":
         func = name[9:]
         func = string.lower(func[0:1]) + func[1:]
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 3013e46..ef02f34 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -346,14 +346,20 @@
     <function name='virDomainSnapshotListNames' file='python'>
       <info>collect the list of snapshots for the given domain</info>
       <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
-      <arg name='flags' type='unsigned int' info='flags, curently unused'/>
-      <return type='str *' info='the list of Names of None in case of error'/>
+      <arg name='flags' type='unsigned int' info='flags'/>
+      <return type='str *' info='the list of Names or None in case of error'/>
+    </function>
+    <function name='virDomainSnapshotListChildrenNames' file='python'>
+      <info>collect the list of child snapshots for the given snapshot</info>
+      <arg name='snapshot' type='virDomainSnapshotPtr' info='pointer to the snapshot'/>
+      <arg name='flags' type='unsigned int' info='flags'/>
+      <return type='str *' info='the list of Names or None in case of error'/>
     </function>
     <function name='virDomainRevertToSnapshot' file='python'>
       <info>revert the domain to the given snapshot</info>
       <arg name='dom' type='virDomainPtr' info='dummy domain pointer'/>
       <arg name='snap' type='virDomainSnapshotPtr' info='pointer to the snapshot'/>
-      <arg name='flags' type='unsigned int' info='flags, curently unused'/>
+      <arg name='flags' type='unsigned int' info='flags'/>
       <return type='int' info="0 on success, -1 on error"/>
     </function>
     <function name='virDomainGetBlockJobInfo' file='python'>
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index d65423d..523c03b 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -1727,6 +1727,51 @@ libvirt_virDomainSnapshotListNames(PyObject *self ATTRIBUTE_UNUSED,
 }

 static PyObject *
+libvirt_virDomainSnapshotListChildrenNames(PyObject *self ATTRIBUTE_UNUSED,
+                                   PyObject *args) {
+    PyObject *py_retval;
+    char **names = NULL;
+    int c_retval, i;
+    virDomainSnapshotPtr snap;
+    PyObject *pyobj_snap;
+    unsigned int flags;
+
+    if (!PyArg_ParseTuple(args, (char *)"Oi:virDomainSnapshotListChildrenNames", &pyobj_snap, &flags))
+        return(NULL);
+    snap = (virDomainSnapshotPtr) PyvirDomainSnapshot_Get(pyobj_snap);
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+    c_retval = virDomainSnapshotNumChildren(snap, flags);
+    LIBVIRT_END_ALLOW_THREADS;
+    if (c_retval < 0)
+        return VIR_PY_NONE;
+
+    if (c_retval) {
+        names = malloc(sizeof(*names) * c_retval);
+        if (!names)
+            return VIR_PY_NONE;
+        LIBVIRT_BEGIN_ALLOW_THREADS;
+        c_retval = virDomainSnapshotListChildrenNames(snap, names, c_retval, flags);
+        LIBVIRT_END_ALLOW_THREADS;
+        if (c_retval < 0) {
+            free(names);
+            return VIR_PY_NONE;
+        }
+    }
+    py_retval = PyList_New(c_retval);
+
+    if (names) {
+        for (i = 0;i < c_retval;i++) {
+            PyList_SetItem(py_retval, i, libvirt_constcharPtrWrap(names[i]));
+            free(names[i]);
+        }
+        free(names);
+    }
+
+    return(py_retval);
+}
+
+static PyObject *
 libvirt_virDomainRevertToSnapshot(PyObject *self ATTRIBUTE_UNUSED,
                                   PyObject *args) {
     int c_retval;
diff --git a/src/driver.h b/src/driver.h
index f85a1b1..b899d0e 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -584,6 +584,16 @@ typedef int
                                      int nameslen,
                                      unsigned int flags);

+typedef int
+    (*virDrvDomainSnapshotNumChildren)(virDomainSnapshotPtr snapshot,
+                                       unsigned int flags);
+
+typedef int
+    (*virDrvDomainSnapshotListChildrenNames)(virDomainSnapshotPtr snapshot,
+                                             char **names,
+                                             int nameslen,
+                                             unsigned int flags);
+
 typedef virDomainSnapshotPtr
     (*virDrvDomainSnapshotLookupByName)(virDomainPtr domain,
                                         const char *name,
@@ -860,6 +870,8 @@ struct _virDriver {
     virDrvDomainSnapshotGetXMLDesc domainSnapshotGetXMLDesc;
     virDrvDomainSnapshotNum domainSnapshotNum;
     virDrvDomainSnapshotListNames domainSnapshotListNames;
+    virDrvDomainSnapshotNumChildren domainSnapshotNumChildren;
+    virDrvDomainSnapshotListChildrenNames domainSnapshotListChildrenNames;
     virDrvDomainSnapshotLookupByName domainSnapshotLookupByName;
     virDrvDomainHasCurrentSnapshot domainHasCurrentSnapshot;
     virDrvDomainSnapshotGetParent domainSnapshotGetParent;
diff --git a/src/libvirt.c b/src/libvirt.c
index 7b1d953..c2aabf7 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -16068,6 +16068,117 @@ error:
 }

 /**
+ * virDomainSnapshotNumChildren:
+ * @snapshot: a domain snapshot object
+ * @flags: bitwise-or of supported virDomainSnapshotListFlags
+ *
+ * Provides the number of child snapshots for this domain snapshot.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS, then the result
+ * includes all descendants, otherwise it is limited to direct children.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_LIST_METADATA, then the result is
+ * the number of snapshots that also include metadata that would prevent
+ * the removal of the last reference to a domain; this value will either
+ * be 0 or the same value as if the flag were not given.
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ */
+int
+virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot, unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+        virLibDomainSnapshotError(VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
+                                  __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    conn = snapshot->domain->conn;
+    if (conn->driver->domainSnapshotNumChildren) {
+        int ret = conn->driver->domainSnapshotNumChildren(snapshot, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    virDispatchError(conn);
+    return -1;
+}
+
+/**
+ * virDomainSnapshotListChildrenNames:
+ * @snapshot: a domain snapshot object
+ * @names: array to collect the list of names of snapshots
+ * @nameslen: size of @names
+ * @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.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS, then the result
+ * includes all descendants, otherwise it is limited to direct children.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_LIST_METADATA, then the result is
+ * the number of snapshots that also include metadata that would prevent
+ * the removal of the last reference to a domain; this value will either
+ * be 0 or the same value as if the flag were not given.
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ */
+int
+virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
+                                   char **names, int nameslen,
+                                   unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, names=%p, nameslen=%d, flags=%x",
+              snapshot, names, nameslen, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+        virLibDomainSnapshotError(VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
+                                  __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    conn = snapshot->domain->conn;
+
+    if ((names == NULL) || (nameslen < 0)) {
+        virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainSnapshotListChildrenNames) {
+        int ret = conn->driver->domainSnapshotListChildrenNames(snapshot,
+                                                                names,
+                                                                nameslen,
+                                                                flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    virDispatchError(conn);
+    return -1;
+}
+
+/**
  * virDomainSnapshotLookupByName:
  * @domain: a domain object
  * @name: name for the domain snapshot
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index afea29b..9762fc4 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -493,6 +493,8 @@ LIBVIRT_0.9.7 {
     global:
         virDomainReset;
         virDomainSnapshotGetParent;
+        virDomainSnapshotListChildrenNames;
+        virDomainSnapshotNumChildren;
 } LIBVIRT_0.9.5;

 # .... define new API here using predicted next version number ....
-- 
1.7.4.4




More information about the libvir-list mailing list