diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rwxr-xr-x | generator.py | 25 | ||||
-rw-r--r-- | libvir.c | 99 | ||||
-rw-r--r-- | libvir.py | 30 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rwxr-xr-x | tests/error.py | 41 |
6 files changed, 186 insertions, 15 deletions
diff --git a/Makefile.am b/Makefile.am index c57b9f7..96865a4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,7 @@ EXTRA_DIST = \ generator.py \ libvirt_wrap.h \ libvirt.py \ + libvir.py \ libvirt-python-api.xml \ $(DOCS) @@ -33,6 +34,8 @@ python_LTLIBRARIES = libvirtmod.la libvirtmod_la_SOURCES = libvir.c types.c libvirt-py.c libvirt-py.h libvirtmod_la_LIBADD = $(mylibs) +libvirt.py: $(srcdir)/libvir.py libvirtclass.py + cat $(srcdir)/libvir.py libvirtclass.py > libvirt.py install-data-local: $(mkinstalldirs) $(DESTDIR)$(pythondir) diff --git a/generator.py b/generator.py index 005ac07..af44cae 100755 --- a/generator.py +++ b/generator.py @@ -251,7 +251,7 @@ foreign_encoding_args = ( ####################################################################### # -# This part writes the C <-> Python stubs libxml2-py.[ch] and +# This part writes the C <-> Python stubs libvirt2-py.[ch] and # the table libxml2-export.c to add when registrering the Python module # ####################################################################### @@ -691,17 +691,7 @@ def buildWrappers(): info = (0, func, name, ret, args, file) function_classes['None'].append(info) - classes = open("libvirt.py", "w") - classes.write("""#!/usr/bin/python -u -# -# Those are the autogenerated Python bindings for libvirt. -# Check python/generator.py in the source distribution of libvirt -# to find out more about the generation process -# -""") - - classes.write("import libvirtmod\n") - classes.write("import types\n\n") + classes = open("libvirtclass.py", "w") txt = open("libvirtclass.txt", "w") txt.write(" Generated Classes for libvir-python\n\n") @@ -754,7 +744,12 @@ def buildWrappers(): # Raise an exception # if functions_noexcept.has_key(name): - classes.write(" if ret is None:return None\n"); + classes.write(" if ret is None:return None\n"); + else: + classes.write( + " if ret is None:raise libvirtError('%s() failed')\n" % + (name)) + classes.write(" return "); classes.write(classes_type[ret[0]][1] % ("ret")); classes.write("\n"); @@ -867,6 +862,10 @@ def buildWrappers(): if functions_noexcept.has_key(name): classes.write( " if ret is None:return None\n"); + else: + classes.write( + " if ret is None:raise libvirtError('%s() failed')\n" % + (name)) # # generate the returned class wrapper for the object @@ -11,11 +11,108 @@ #include <Python.h> #include <libvirt.h> +#include <virterror.h> #include "libvirt_wrap.h" #include "libvirt-py.h" void initlibvirmod(void); +PyObject *libvirt_virDomainGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args); +/************************************************************************ + * * + * Global error handler at the Python level * + * * + ************************************************************************/ + +static PyObject *libvirt_virPythonErrorFuncHandler = NULL; +static PyObject *libvirt_virPythonErrorFuncCtxt = NULL; + +static void +libvirt_virErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, virErrorPtr err) +{ + PyObject *list, *info; + PyObject *result; + +#ifdef DEBUG_ERROR + printf("libvirt_virErrorFuncHandler(%p, %s, ...) called\n", ctx, msg); +#endif + + if ((err == NULL) || (err->code == VIR_ERR_OK)) + return; + + if ((libvirt_virPythonErrorFuncHandler == NULL) || + (libvirt_virPythonErrorFuncHandler == Py_None)) { + virDefaultErrorFunc(err); + } else { + list = PyTuple_New(2); + info = PyTuple_New(9); + PyTuple_SetItem(list, 0, libvirt_virPythonErrorFuncCtxt); + PyTuple_SetItem(list, 1, info); + Py_XINCREF(libvirt_virPythonErrorFuncCtxt); + PyTuple_SetItem(info, 0, PyInt_FromLong((long) err->code)); + PyTuple_SetItem(info, 1, PyInt_FromLong((long) err->domain)); + PyTuple_SetItem(info, 2, libvirt_charPtrWrap(err->message)); + PyTuple_SetItem(info, 3, PyInt_FromLong((long) err->level)); + PyTuple_SetItem(info, 4, libvirt_charPtrWrap(err->str1)); + PyTuple_SetItem(info, 5, libvirt_charPtrWrap(err->str2)); + PyTuple_SetItem(info, 6, libvirt_charPtrWrap(err->str3)); + PyTuple_SetItem(info, 7, PyInt_FromLong((long) err->int1)); + PyTuple_SetItem(info, 8, PyInt_FromLong((long) err->int2)); + /* TODO pass conn and dom if available */ + result = PyEval_CallObject(libvirt_virPythonErrorFuncHandler, list); + Py_XDECREF(list); + Py_XDECREF(result); + } +} + +static PyObject * +libvirt_virRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self, + PyObject * args) +{ + PyObject *py_retval; + PyObject *pyobj_f; + PyObject *pyobj_ctx; + + if (!PyArg_ParseTuple + (args, (char *) "OO:xmlRegisterErrorHandler", &pyobj_f, + &pyobj_ctx)) + return (NULL); + +#ifdef DEBUG_ERROR + printf("libvirt_virRegisterErrorHandler(%p, %p) called\n", pyobj_ctx, + pyobj_f); +#endif + + virSetErrorFunc(NULL, libvirt_virErrorFuncHandler); + if (libvirt_virPythonErrorFuncHandler != NULL) { + Py_XDECREF(libvirt_virPythonErrorFuncHandler); + } + if (libvirt_virPythonErrorFuncCtxt != NULL) { + Py_XDECREF(libvirt_virPythonErrorFuncCtxt); + } + + if ((pyobj_f == Py_None) && (pyobj_ctx == Py_None)) { + libvirt_virPythonErrorFuncHandler = NULL; + libvirt_virPythonErrorFuncCtxt = NULL; + } else { + Py_XINCREF(pyobj_ctx); + Py_XINCREF(pyobj_f); + + /* TODO: check f is a function ! */ + libvirt_virPythonErrorFuncHandler = pyobj_f; + libvirt_virPythonErrorFuncCtxt = pyobj_ctx; + } + + py_retval = libvirt_intWrap(1); + return (py_retval); +} + +/************************************************************************ + * * + * Wrappers for functions where generator fails * + * * + ************************************************************************/ + static PyObject * libvirt_virDomainFree(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; @@ -106,7 +203,6 @@ libvirt_virDomainGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned char uuid[16]; virDomainPtr domain; PyObject *pyobj_domain; - virDomainInfo info; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetUUID", &pyobj_domain)) return(NULL); @@ -161,6 +257,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL}, {(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL}, {(char *) "virDomainLookupByUUID", libvirt_virDomainLookupByUUID, METH_VARARGS, NULL}, + {(char *) "virRegisterErrorHandler", libvirt_virRegisterErrorHandler, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; diff --git a/libvir.py b/libvir.py new file mode 100644 index 0000000..29dc8c4 --- /dev/null +++ b/libvir.py @@ -0,0 +1,30 @@ +#!/usr/bin/python -u +# +# Those are the autogenerated Python bindings for libvirt. +# Check python/generator.py in the source distribution of libvir +# to find out more about the generation process +# +import libvirtmod +import types + +# The root of all libxml2 errors. +class libvirtError(Exception): + pass + + +# +# register the libvirt global error handler +# +def registerErrorHandler(f, ctx): + """Register a Python written function to for error reporting. + The function is called back as f(ctx, error), with error + being a list of informations about the error being raised. + Returns 1 in case of success.""" + return libvirtmod.virRegisterErrorHandler(f,ctx) + +# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING +# +# Everything before this line comes from libvir.py +# Everything after this line is automatically generated +# +# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING diff --git a/tests/Makefile.am b/tests/Makefile.am index fd1d5fa..5860190 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,7 +3,8 @@ EXAMPLE_DIR = $(datadir)/doc/libvirt-python-$(LIBVIRT_VERSION)/examples PYTESTS= \ basic.py \ create.py \ - uuid.py + uuid.py \ + error.py EXTRA_DIST = $(PYTESTS) diff --git a/tests/error.py b/tests/error.py new file mode 100755 index 0000000..9979ed1 --- /dev/null +++ b/tests/error.py @@ -0,0 +1,41 @@ +#!/usr/bin/python -u +# +# Tests global error handlers at the python level. +# +import libvirt +import sys +import os + +errno = None + +def handler(ctxt, err): + global errno + + #print "handler(%s, %s)" % (ctxt, err) + errno = err + +libvirt.registerErrorHandler(handler, 'context') + +conn = libvirt.openReadOnly(None) +if conn == None: + print 'Failed to open connection to the hypervisor' + sys.exit(1) + +try: + dom0 = conn.lookupByName("Does_not_exist") + print 'strange found a Does_not_exist domain' + sys.exit(1) +except: + pass + +del conn + +if errno == None: + print 'failed to get an error' +elif errno[0] == libvirt.VIR_ERR_NO_CONNECT or \ + errno[0] == libvirt.VIR_ERR_INVALID_DOMAIN: + print "OK" +else: + print 'got unexpected error %s' % (errno) + +sys.exit(0) |