summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rwxr-xr-xgenerator.py25
-rw-r--r--libvir.c99
-rw-r--r--libvir.py30
-rw-r--r--tests/Makefile.am3
-rwxr-xr-xtests/error.py41
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
diff --git a/libvir.c b/libvir.c
index 2a43142..47da369 100644
--- a/libvir.c
+++ b/libvir.c
@@ -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)