On Fri, Sep 30, 2011 at 05:09:23PM -0600, Eric Blake wrote: > 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; Hum, okay, a tad bit confusing though > /* 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, Okay > 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 .... ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list