]> xenbits.xensource.com Git - libvirt.git/commitdiff
* TODO: updated
authorDaniel Veillard <veillard@redhat.com>
Tue, 28 Feb 2006 12:17:00 +0000 (12:17 +0000)
committerDaniel Veillard <veillard@redhat.com>
Tue, 28 Feb 2006 12:17:00 +0000 (12:17 +0000)
* python/Makefile.am python/generator.py python/libvir.c
  python/libvir.py: improved python binding, raise exception
  when an instance creation or lookup fails, and add support
  for the global error handler, per conn handler still needed
* python/tests/error.py python/tests/Makefile.am: adding a
  regression test
Daniel

ChangeLog
TODO
python/Makefile.am
python/generator.py
python/libvir.c
python/libvir.py [new file with mode: 0644]
python/tests/Makefile.am
python/tests/error.py [new file with mode: 0755]

index dfe00875f85cc9ef0c3109da5cab35e89de3f256..00de3ae97f8ee5a16e95b8018ac49b4f27636f62 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Tue Feb 28 13:12:50 CET 2006 Daniel Veillard <veillard@redhat.com>
+
+       * TODO: updated
+       * python/Makefile.am python/generator.py python/libvir.c 
+         python/libvir.py: improved python binding, raise exception 
+         when an instance creation or lookup fails, and add support
+         for the global error handler, per conn handler still needed
+       * python/tests/error.py python/tests/Makefile.am: adding a
+         regression test
+
 Mon Feb 27 17:36:29 EST 2006 Daniel Veillard <veillard@redhat.com>
 
        * doc//*: rebuilt
diff --git a/TODO b/TODO
index dc51e2dbda6dc327602d9859fa93ae21ae1c917c..afbe1ef762398243d64a6b44d568f3261d19967d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -32,6 +32,7 @@ Would-be-nice TODO:
 - man page for virsh and the libraries entry points
 - support for QEmu and other virtualization engines
 - more documentation and examples on using the toolkit
+- examples and docs for the principle in the error handling code
 
 Cleanup:
 - now that libxml2 is linked in, drop hash.[ch] and get back to libxml2 ones ?
index c57b9f7e683a4b3dce0725f16c3e18c59e24745a..96865a44dd731a575888391f6bd99c2dd580043f 100644 (file)
@@ -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)
index 005ac07f44ebf153b883e2c9da17ba68f37f6f6b..af44cae413caf66890c5ac5f66efaba1789b04f9 100755 (executable)
@@ -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
index 2a43142f1643a5842e107bfa10edfe0bcfdd6cf9..47da369d2532e92928436477f3b7ae72bed54ee1 100644 (file)
 
 #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/python/libvir.py b/python/libvir.py
new file mode 100644 (file)
index 0000000..29dc8c4
--- /dev/null
@@ -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
index fd1d5fa8f67b9f6357ccb5aff388607aff94a2fd..58601907867877f5a9cfdafb6f4b5ac74394ff00 100644 (file)
@@ -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/python/tests/error.py b/python/tests/error.py
new file mode 100755 (executable)
index 0000000..9979ed1
--- /dev/null
@@ -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)