On 05/20/2010 12:34 PM, Cole Robinson wrote:
On 05/20/2010 11:14 AM, Chris Lalancette wrote:
> This involved a few fixes. To start with,
> an virDomainSnapshot object is really tied to a
> domain, not a connection, so we have to generate
> a slightly different object so that we can get
> at self._dom for the object.
>
> Next, we had to "dummy" up an override piece of
> XML with a bogus argument that the function doesn't
> actually take. That's so that the generator places
> virDomainRevertToSnapshot underneath the correct
> class (namely, the virDomain class).
>
> Finally, we had to hand-implement the
> virDomainRevertToSnapshot implementation, ignoring the
> bogus pointer we are being passed.
>
> With all of this in place, I was able to successfully
> take a snapshot and revert to it using only the
> Python bindings.
>
> Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
> ---
> python/generator.py | 26 +++++++++++++++++++++++---
> python/libvirt-override-api.xml | 7 +++++++
> python/libvirt-override.c | 23 +++++++++++++++++++++++
> 3 files changed, 53 insertions(+), 3 deletions(-)
>
> diff --git a/python/generator.py b/python/generator.py
> index a243c82..d876df6 100755
> --- a/python/generator.py
> +++ b/python/generator.py
> @@ -331,7 +331,7 @@ skip_impl = (
> 'virNodeListDevices',
> 'virNodeDeviceListCaps',
> 'virConnectBaselineCPU',
> - 'virDomainSnapshotListNames',
> + 'virDomainRevertToSnapshot',
> )
>
>
> @@ -385,6 +385,10 @@ skip_function = (
> "virStorageVolGetConnect",
> )
>
> +function_skip_index_one = (
> + "virDomainRevertToSnapshot",
> +)
> +
>
> def print_function_wrapper(name, output, export, include):
> global py_types
> @@ -688,9 +692,13 @@ classes_destructors = {
> }
>
> class_skip_connect_impl = {
> - "virConnect" : True
> + "virConnect" : True,
> + "virDomainSnapshot": True,
> }
>
> +class_domain_impl = {
> + "virDomainSnapshot": True,
> +}
>
> functions_noexcept = {
> 'virDomainGetID': True,
> @@ -986,7 +994,7 @@ def buildWrappers():
> info = (0, func, name, ret, args, file)
> function_classes[classe].append(info)
> elif name[0:3] == "vir" and len(args) >= 2 and args[1][1] == type
\
> - and file != "python_accessor":
> + and file != "python_accessor" and not name in
function_skip_index_one:
> found = 1
> func = nameFixup(name, classe, type, file)
> info = (1, func, name, ret, args, file)
> @@ -1128,6 +1136,8 @@ def buildWrappers():
> "virStorageVol",
"virNodeDevice", "virSecret","virStream",
> "virNWFilter" ]:
> classes.write(" def __init__(self, conn,
_obj=None):\n")
> + elif classname in [ 'virDomainSnapshot' ]:
> + classes.write(" def __init__(self, dom,
_obj=None):\n")
> else:
> classes.write(" def __init__(self, _obj=None):\n")
> if reference_keepers.has_key(classname):
> @@ -1142,6 +1152,8 @@ def buildWrappers():
> classes.write(" self._conn = conn\n" + \
> " if not isinstance(conn,
virConnect):\n" + \
> " self._conn =
conn._conn\n")
> + elif classname in [ "virDomainSnapshot" ]:
> + classes.write(" self._dom = dom\n")
> classes.write(" if _obj != None:self._o = _obj;return\n")
> classes.write(" self._o = None\n\n");
> destruct=None
> @@ -1158,6 +1170,10 @@ def buildWrappers():
> classes.write(" def connect(self):\n")
> classes.write(" return self._conn\n\n")
>
> + if class_domain_impl.has_key(classname):
> + classes.write(" def domain(self):\n")
> + classes.write(" return self._dom\n\n")
> +
> flist = function_classes[classname]
> flist.sort(functionCompare)
> oldfile = ""
> @@ -1252,6 +1268,10 @@ def buildWrappers():
> classes.write(
> " if ret is None:raise libvirtError('%s() failed',
vol=self)\n" %
> (name))
> + elif classname == "virDomainSnapshot":
> + classes.write(
> + " if ret is None:raise libvirtError('%s()
failed', dom=self._dom)\n" %
> + (name))
> else:
> classes.write(
> " if ret is None:raise libvirtError('%s()
failed')\n" %
> diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
> index 9ba8e4e..be28b40 100644
> --- a/python/libvirt-override-api.xml
> +++ b/python/libvirt-override-api.xml
> @@ -277,5 +277,12 @@
> <arg name='flags' type='unsigned int' info='flags,
curently unused'/>
> <return type='str *' info='the list of Names of 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'/>
> + <return type='int' info="0 on success, -1 on error"/>
> + </function>
> </symbols>
> </api>
> diff --git a/python/libvirt-override.c b/python/libvirt-override.c
> index c9721f7..ad55940 100644
> --- a/python/libvirt-override.c
> +++ b/python/libvirt-override.c
> @@ -988,6 +988,28 @@ libvirt_virDomainSnapshotListNames(PyObject *self
ATTRIBUTE_UNUSED,
> }
>
> static PyObject *
> +libvirt_virDomainRevertToSnapshot(PyObject *self ATTRIBUTE_UNUSED,
> + PyObject *args) {
> + int c_retval;
> + virDomainSnapshotPtr snap;
> + PyObject *pyobj_snap;
> + PyObject *pyobj_dom;
> + int flags;
> +
> + if (!PyArg_ParseTuple(args, (char *)"OOi:virDomainRevertToSnapshot",
&pyobj_dom, &pyobj_snap, &flags))
> + return(NULL);
> + snap = (virDomainSnapshotPtr) PyvirDomainSnapshot_Get(pyobj_snap);
> +
> + LIBVIRT_BEGIN_ALLOW_THREADS;
> + c_retval = virDomainRevertToSnapshot(snap, flags);
> + LIBVIRT_END_ALLOW_THREADS;
> + if (c_retval < 0)
> + return VIR_PY_INT_FAIL;
> +
> + return PyInt_FromLong(c_retval);
> +}
> +
> +static PyObject *
> libvirt_virDomainGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
> PyObject *py_retval;
> int c_retval;
> @@ -3527,6 +3549,7 @@ static PyMethodDef libvirtMethods[] = {
> {(char *) "virConnectBaselineCPU", libvirt_virConnectBaselineCPU,
METH_VARARGS, NULL},
> {(char *) "virDomainGetJobInfo", libvirt_virDomainGetJobInfo,
METH_VARARGS, NULL},
> {(char *) "virDomainSnapshotListNames",
libvirt_virDomainSnapshotListNames, METH_VARARGS, NULL},
> + {(char *) "virDomainRevertToSnapshot",
libvirt_virDomainRevertToSnapshot, METH_VARARGS, NULL},
> {NULL, NULL, 0, NULL}
> };
>
ACK, change looks fine. Might be worth checking the python bindings diff
though, the generator is fragile and changes can sometimes muck up
existing APIs.
Excellent thought. I did that across libvirt.c, libvirt-export.c, libvirt.h
and libvirt.py, and the only changes were the ones I expected. Thanks for
the heads up. I've now pushed this patch.
--
Chris Lalancette