The current python bindings throw a generic libvirtError exception object whose message merely consists of the name of the method which failed. This isn't really all that useful to the caller, since they know exactly which method failed - its the one they just called! The attached patch adds a binding for virConGetLastError & virGetLastError & pulls this info into the libvirtError object being thrown. Regards, Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
Index: python/generator.py =================================================================== RCS file: /data/cvs/libvirt/python/generator.py,v retrieving revision 1.11 diff -c -r1.11 generator.py *** python/generator.py 24 Oct 2006 20:28:16 -0000 1.11 --- python/generator.py 25 Oct 2006 19:07:43 -0000 *************** *** 260,265 **** --- 260,267 ---- # code is still automatically generated (so they are not in skip_function()). skip_impl = ( 'virConnectListDomainsID', + 'virConnGetLastError', + 'virGetLastError', 'virDomainGetInfo', 'virNodeGetInfo', 'virDomainGetUUID', *************** *** 869,877 **** 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 --- 871,888 ---- classes.write( " if ret is None:return None\n"); else: ! if classname == "virConnect": ! classes.write( ! " if ret is None:raise libvirtError('%s() failed', conn=self)\n" % ! (name)) ! elif classname == "virDomain": ! classes.write( ! " if ret is None:raise libvirtError('%s() failed')\n" % ! (name)) ! else: ! classes.write( " if ret is None:raise libvirtError('%s() failed')\n" % ! (name)) # # generate the returned class wrapper for the object Index: python/libvir.c =================================================================== RCS file: /data/cvs/libvirt/python/libvir.c,v retrieving revision 1.14 diff -c -r1.14 libvir.c *** python/libvir.c 24 Oct 2006 20:28:16 -0000 1.14 --- python/libvir.c 25 Oct 2006 19:07:43 -0000 *************** *** 18,23 **** --- 18,25 ---- void initlibvirmod(void); PyObject *libvirt_virDomainGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args); + PyObject *libvirt_virGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args); + PyObject *libvirt_virConnGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args); /************************************************************************ *************** *** 29,34 **** --- 31,92 ---- static PyObject *libvirt_virPythonErrorFuncHandler = NULL; static PyObject *libvirt_virPythonErrorFuncCtxt = NULL; + PyObject * + libvirt_virGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args ATTRIBUTE_UNUSED) + { + virError err; + PyObject *info; + + if (virCopyLastError(&err) <= 0) { + Py_INCREF(Py_None); + return(Py_None); + } + + info = PyTuple_New(9); + PyTuple_SetItem(info, 0, PyInt_FromLong((long) err.code)); + PyTuple_SetItem(info, 1, PyInt_FromLong((long) err.domain)); + PyTuple_SetItem(info, 2, libvirt_constcharPtrWrap(err.message)); + PyTuple_SetItem(info, 3, PyInt_FromLong((long) err.level)); + PyTuple_SetItem(info, 4, libvirt_constcharPtrWrap(err.str1)); + PyTuple_SetItem(info, 5, libvirt_constcharPtrWrap(err.str2)); + PyTuple_SetItem(info, 6, libvirt_constcharPtrWrap(err.str3)); + PyTuple_SetItem(info, 7, PyInt_FromLong((long) err.int1)); + PyTuple_SetItem(info, 8, PyInt_FromLong((long) err.int2)); + + return info; + } + + PyObject * + libvirt_virConnGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) + { + virError err; + PyObject *info; + virConnectPtr conn; + PyObject *pyobj_conn; + + if (!PyArg_ParseTuple(args, (char *)"O:virConGetLastError", &pyobj_conn)) + return(NULL); + conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + + if (virConnCopyLastError(conn, &err) <= 0) { + Py_INCREF(Py_None); + return(Py_None); + } + + info = PyTuple_New(9); + PyTuple_SetItem(info, 0, PyInt_FromLong((long) err.code)); + PyTuple_SetItem(info, 1, PyInt_FromLong((long) err.domain)); + PyTuple_SetItem(info, 2, libvirt_constcharPtrWrap(err.message)); + PyTuple_SetItem(info, 3, PyInt_FromLong((long) err.level)); + PyTuple_SetItem(info, 4, libvirt_constcharPtrWrap(err.str1)); + PyTuple_SetItem(info, 5, libvirt_constcharPtrWrap(err.str2)); + PyTuple_SetItem(info, 6, libvirt_constcharPtrWrap(err.str3)); + PyTuple_SetItem(info, 7, PyInt_FromLong((long) err.int1)); + PyTuple_SetItem(info, 8, PyInt_FromLong((long) err.int2)); + + return info; + } + static void libvirt_virErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, virErrorPtr err) { *************** *** 311,316 **** --- 369,376 ---- {(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL}, {(char *) "virDomainLookupByUUID", libvirt_virDomainLookupByUUID, METH_VARARGS, NULL}, {(char *) "virRegisterErrorHandler", libvirt_virRegisterErrorHandler, METH_VARARGS, NULL}, + {(char *) "virGetLastError", libvirt_virGetLastError, METH_VARARGS, NULL}, + {(char *) "virConnGetLastError", libvirt_virConnGetLastError, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; Index: python/libvir.py =================================================================== RCS file: /data/cvs/libvirt/python/libvir.py,v retrieving revision 1.1 diff -c -r1.1 libvir.py *** python/libvir.py 28 Feb 2006 12:17:00 -0000 1.1 --- python/libvir.py 25 Oct 2006 19:07:43 -0000 *************** *** 7,16 **** import libvirtmod import types ! # The root of all libxml2 errors. class libvirtError(Exception): ! pass # # register the libvirt global error handler --- 7,51 ---- import libvirtmod import types ! # The root of all libvirt errors. class libvirtError(Exception): ! def __init__(self, msg, conn=None): ! Exception.__init__(self, msg) + if conn is None: + self.err = virGetLastError() + else: + self.err = conn.virConnGetLastError() + + def get_error_code(self): + return self.err[0] + + def get_error_domain(self): + return self.err[1] + + def get_error_message(self): + return self.err[2] + + def get_error_level(self): + return self.err[3] + + def get_str1(self): + return self.err[4] + + def get_str2(self): + return self.err[5] + + def get_str3(self): + return self.err[6] + + def get_int1(self): + return self.err[7] + + def get_int2(self): + return self.err[8] + + def __str__(self): + return Exception.__str__(self) + " " + self.get_error_message() # # register the libvirt global error handler