Attached are the python bindings for domain events as previously submitted:
https://www.redhat.com/archives/libvir-list/2008-October/msg00707.html
https://www.redhat.com/archives/libvir-list/2008-October/msg00668.html

I have resolved most of the issues Daniel V. commented on
I also addressed a number of ref counting problems.

 examples/domain-events/events-python/event-test.py |  186 ++++++++
 python/Makefile.am                                 |    5
 python/generator.py                                |   19
 python/libvir.c                                    |  441 +++++++++++++++++++++
 python/libvir.py                                   |   20
 python/libvirt_wrap.h                              |   27 +
 python/types.c                                     |   47 ++
 python/virConnect.py                               |   43 ++
 8 files changed, 782 insertions(+), 6 deletions(-)
diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py
new file mode 100755
index 0000000..7082db0
--- /dev/null
+++ b/examples/domain-events/events-python/event-test.py
@@ -0,0 +1,186 @@
+#!/usr/bin/python -u
+import sys,getopt,os
+import libvirt
+import select
+
+mypoll = select.poll()
+TIMEOUT_MS = 1000
+
+# handle globals
+h_fd       = 0
+h_events   = 0
+h_cb       = None
+h_opaque   = None
+
+# timeout globals
+t_active   = 0
+t_timeout  = -1
+t_cb       = None
+t_opaque   = None
+
+#####################################################
+# Callback Functions
+#####################################################
+def eventToString(event):
+    eventStrings = ( "Added",
+                     "Removed",
+                     "Started",
+                     "Suspended",
+                     "Resumed",
+                     "Stopped",
+                     "Saved",
+                     "Restored" );
+    return eventStrings[event];
+
+def myDomainEventCallback1 (conn, dom, event, opaque):
+    print "myDomainEventCallback1 EVENT: Domain %s(%s) %s" % (dom.name(), dom.ID(), eventToString(event))
+
+def myDomainEventCallback2 (conn, dom, event, opaque):
+    print "myDomainEventCallback2 EVENT: Domain %s(%s) %s" % (dom.name(), dom.ID(), eventToString(event))
+
+#####################################################
+# EventImpl Functions
+#####################################################
+def myEventHandleTypeToPollEvent(events):
+    ret = 0
+    if events & libvirt.VIR_EVENT_HANDLE_READABLE:
+        ret |= select.POLLIN
+    if events & libvirt.VIR_EVENT_HANDLE_WRITABLE:
+        ret |= select.POLLOUT
+    if events & libvirt.VIR_EVENT_HANDLE_ERROR:
+        ret |= select.POLLERR;
+    if events & libvirt.VIR_EVENT_HANDLE_HANGUP:
+        ret |= select.POLLHUP;
+    return ret
+
+def myPollEventToEventHandleType(events):
+    ret = 0;
+    if events & select.POLLIN:
+        ret |= libvirt.VIR_EVENT_HANDLE_READABLE;
+    if events & select.POLLOUT:
+        ret |= libvirt.VIR_EVENT_HANDLE_WRITABLE;
+    if events & select.POLLERR:
+        ret |= libvirt.VIR_EVENT_HANDLE_ERROR;
+    if events & select.POLLHUP:
+        ret |= libvirt.VIR_EVENT_HANDLE_HANGUP;
+    return ret;
+
+def myAddHandle(fd, events, cb, opaque):
+    global h_fd, h_events, h_cb, h_opaque
+    #print "Adding Handle %s %s %s %s" % (str(fd), str(events), str(cb), str(opaque))
+    h_fd = fd
+    h_events = events
+    h_cb = cb
+    h_opaque = opaque
+
+    mypoll.register(fd, myEventHandleTypeToPollEvent(events))
+
+def myUpdateHandle(fd, event):
+    global h_fd, h_events
+    #print "Updating Handle %s %s" % (str(fd), str(events))
+    h_fd = fd
+    h_events = event
+    mypoll.unregister(fd)
+    mypoll.register(fd, myEventHandleTypeToPollEvent(event))
+
+def myRemoveHandle(fd):
+    global h_fd
+    #print "Removing Handle %s" % str(fd)
+    h_fd = 0
+    mypoll.unregister(fd)
+
+def myAddTimeout(timeout, cb, opaque):
+    global t_active, t_timeout, t_cb, t_opaque
+    #print "Adding Timeout %s %s %s" % (str(timeout), str(cb), str(opaque))
+    t_active = 1;
+    t_timeout = timeout;
+    t_cb = cb;
+    t_opaque = opaque;
+
+def myUpdateTimeout(timer, timeout):
+    global t_timeout
+    #print "Updating Timeout %s" % (str(timer), str(timeout))
+    t_timeout = timeout;
+
+def myRemoveTimeout(timer):
+    global t_active
+    #print "Removing Timeout %s" % str(timer)
+    t_active = 0;
+
+##########################################
+# Main
+##########################################
+
+def usage():
+        print "usage: "+os.path.basename(sys.argv[0])+" [uri]"
+        print "   uri will default to qemu:///system"
+
+def main():
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"] )
+    except getopt.GetoptError, err:
+        # print help information and exit:
+        print str(err) # will print something like "option -a not recognized"
+        usage()
+        sys.exit(2)
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+
+    if len(sys.argv) > 1:
+        uri = sys.argv[1]
+    else:
+        uri = "qemu:///system"
+
+    print "Using uri:" + uri
+
+    libvirt.virEventRegisterImpl( myAddHandle,
+                               myUpdateHandle,
+                               myRemoveHandle,
+                               myAddTimeout,
+                               myUpdateTimeout,
+                               myRemoveTimeout );
+    vc = libvirt.open(uri)
+
+    #Add 2 callbacks to prove this works with more than just one
+    vc.domainEventRegister(myDomainEventCallback1,None)
+    vc.domainEventRegister(myDomainEventCallback2,None)
+
+    while 1:
+        try:
+            sts = mypoll.poll(TIMEOUT_MS)
+        except select.error, err:
+            if err[0] == errno.EINTR:
+                    continue
+            raise
+        except KeyboardInterrupt:
+            print "Keyboard Interrupt caught - exiting cleanly"
+            break
+
+        if not sts:
+            #print "Timed out"
+            continue
+
+        rfd = sts[0][0]
+        revents = sts[0][1]
+
+        if t_active:
+            #print "Invoking Timeout CB"
+            t_cb(t_timeout, t_opaque[0], t_opaque[1])
+
+        if revents & select.POLLHUP:
+            print "Reset by peer";
+            return -1;
+
+        if h_cb != None:
+            #print "Invoking Handle CB"
+            h_cb(h_fd, myPollEventToEventHandleType(revents & h_events),
+                 h_opaque[0], h_opaque[1])
+
+        #print "DEBUG EXIT"
+        #break
+
+if __name__ == "__main__":
+    main()
+
diff --git a/python/Makefile.am b/python/Makefile.am
index cd9b6af..90b87bb 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -13,6 +13,8 @@ DOCS_DIR = $(datadir)/doc/libvirt-python-$(LIBVIRT_VERSION)
 
 DOCS = ${srcdir}/TODO
 
+CLASSES_EXTRA = virConnect.py
+
 EXTRA_DIST =		\
 	libvir.c	\
 	types.c		\
@@ -21,6 +23,7 @@ EXTRA_DIST =		\
 	libvirt.py	\
 	libvir.py	\
 	libvirt-python-api.xml \
+	$(CLASSES_EXTRA) \
 	$(DOCS)
 
 if WITH_PYTHON
@@ -50,7 +53,7 @@ GENERATED= libvirt-export.c \
 $(GENERATED): $(srcdir)/$(GENERATE) $(API_DESC)
 	$(PYTHON) $(srcdir)/$(GENERATE) $(srcdir)
 
-libvirt.py: $(srcdir)/libvir.py $(GENERATED)
+libvirt.py: $(srcdir)/libvir.py $(GENERATED) $(CLASSES_EXTRA)
 	cat $(srcdir)/libvir.py libvirtclass.py > [EMAIL PROTECTED]
 	mv [EMAIL PROTECTED] $@
 
diff --git a/python/generator.py b/python/generator.py
index ca83eaf..7b153b9 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -213,6 +213,8 @@ skipped_modules = {
 
 skipped_types = {
 #    'int *': "usually a return type",
+     'virConnectDomainEventCallback': "No function types in python",
+     'virEventAddHandleFunc': "No function types in python",
 }
 
 #######################################################################
@@ -315,6 +317,7 @@ skip_impl = (
     'virStoragePoolListVolumes',
     'virDomainBlockPeek',
     'virDomainMemoryPeek',
+    'virEventRegisterImpl',
 )
 
 
@@ -332,9 +335,8 @@ skip_function = (
     'virCopyLastError', # Python API is called virGetLastError instead
     'virConnectOpenAuth', # Python C code is manually written
     'virDefaultErrorFunc', # Python virErrorFuncHandler impl calls this from C
-    'virConnectDomainEventRegister', # TODO: generate python bindings for these below XXX
-    'virConnectDomainEventDeregister',
-    'virEventRegisterImpl',
+    'virConnectDomainEventRegister',   # overridden in virConnect.py
+    'virConnectDomainEventDeregister', # overridden in virConnect.py
 )
 
 
@@ -615,7 +617,6 @@ classes_destructors = {
     "virNetwork": "virNetworkFree",
     "virStoragePool": "virStoragePoolFree",
     "virStorageVol": "virStorageVolFree",
-    "virConnect": "virConnectClose",
 }
 
 functions_noexcept = {
@@ -1210,6 +1211,16 @@ def buildWrappers():
 			classes.write("        return ret\n");
 
 		classes.write("\n");
+            # Append "<classname>.py" to class def, iff it exists
+            try:
+                extra = open(classname + ".py", "r")
+                classes.write ("    #\n")
+                classes.write ("    # %s methods from %s.py (hand coded)\n" % (classname,classname))
+                classes.write ("    #\n")
+                classes.writelines(extra.readlines())
+                extra.close()
+            except:
+                pass
 
     #
     # Generate enum constants
diff --git a/python/libvir.c b/python/libvir.c
index 9cc0c81..a2e4c79 100644
--- a/python/libvir.c
+++ b/python/libvir.c
@@ -1466,7 +1466,443 @@ libvirt_virStoragePoolLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *ar
     return(py_retval);
 }
 
+/*******************************************
+ * Helper functions to avoid importing modules
+ * for every callback
+ *******************************************/
+static PyObject *libvirt_module    = NULL;
+static PyObject *libvirt_dict      = NULL;
+static PyObject *libvirt_dom_class = NULL;
 
+static PyObject *
+getLibvirtModuleObject (void) {
+    if(libvirt_module)
+        return libvirt_module;
+
+    // PyImport_ImportModule returns a new reference
+    libvirt_module = PyImport_ImportModule("libvirt");
+    if(!libvirt_module) {
+        printf("%s Error importing libvirt module\n", __FUNCTION__);
+        PyErr_Print();
+        return NULL;
+    }
+
+    return libvirt_module;
+}
+
+static PyObject *
+getLibvirtDictObject (void) {
+    if(libvirt_dict)
+        return libvirt_dict;
+
+    // PyModule_GetDict returns a borrowed reference
+    libvirt_dict = PyModule_GetDict(getLibvirtModuleObject());
+    if(!libvirt_dict) {
+        printf("%s Error importing libvirt dictionary\n", __FUNCTION__);
+        PyErr_Print();
+        return NULL;
+    }
+
+    Py_INCREF(libvirt_dict);
+    return libvirt_dict;
+}
+
+static PyObject *
+getLibvirtDomainClassObject (void) {
+    if(libvirt_dom_class)
+        return libvirt_dom_class;
+
+    // PyDict_GetItemString returns a borrowed reference
+    libvirt_dom_class = PyDict_GetItemString(getLibvirtDictObject(),
+                                             "virDomain");
+    if(!libvirt_dom_class) {
+        printf("%s Error importing virDomain class\n", __FUNCTION__);
+        PyErr_Print();
+        return NULL;
+    }
+
+    Py_INCREF(libvirt_dom_class);
+    return libvirt_dom_class;
+}
+/*******************************************
+ * Domain Events
+ *******************************************/
+
+static int
+libvirt_virConnectDomainEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                      virDomainPtr dom,
+                                      int event,
+                                      void *opaque)
+{
+    PyObject *pyobj_ret;
+
+    PyObject *pyobj_conn_inst = (PyObject*)opaque;
+    PyObject *pyobj_dom = libvirt_virDomainPtrWrap(dom);
+
+    PyObject *pyobj_dom_args;
+    PyObject *pyobj_dom_inst;
+
+    PyObject *dom_class;
+
+    /* Create a python instance of this virDomainPtr */
+    pyobj_dom_args = PyTuple_New(2);
+    if(PyTuple_SetItem(pyobj_dom_args, 0, pyobj_conn_inst)!=0) {
+        printf("%s error creating tuple",__FUNCTION__);
+        return -1;
+    }
+    if(PyTuple_SetItem(pyobj_dom_args, 1, pyobj_dom)!=0) {
+        printf("%s error creating tuple",__FUNCTION__);
+        return -1;
+    }
+    Py_INCREF(pyobj_conn_inst);
+
+    dom_class = getLibvirtDomainClassObject();
+    if(!PyClass_Check(dom_class)) {
+        printf("%s dom_class is not a class!\n", __FUNCTION__);
+        return -1;
+    }
+
+    pyobj_dom_inst = PyInstance_New(dom_class,
+                                    pyobj_dom_args,
+                                    NULL);
+
+    Py_DECREF(pyobj_dom_args);
+
+    if(!pyobj_dom_inst) {
+        printf("%s Error creating a python instance of virDomain\n", __FUNCTION__);
+        PyErr_Print();
+        return -1;
+    }
+
+    /* Call the Callback Dispatcher */
+    pyobj_ret = PyObject_CallMethod(pyobj_conn_inst,
+                                    (char*)"dispatchDomainEventCallbacks",
+                                    (char*)"Oi",
+                                    pyobj_dom_inst,
+                                    event);
+
+    Py_DECREF(pyobj_dom_inst);
+
+    if(!pyobj_ret) {
+        printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+        PyErr_Print();
+        return -1;
+    } else {
+        Py_DECREF(pyobj_ret);
+        return 0;
+    }
+
+}
+
+static PyObject *
+libvirt_virConnectDomainEventRegister(ATTRIBUTE_UNUSED PyObject * self,
+                                      PyObject * args)
+{
+    PyObject *py_retval;        /* return value */
+    PyObject *pyobj_conn;       /* virConnectPtr */
+    PyObject *pyobj_conn_inst;  /* virConnect Python object */
+
+    virConnectPtr conn;
+    int ret = 0;
+
+    if (!PyArg_ParseTuple
+        (args, (char *) "OO:virConnectDomainEventRegister",
+                        &pyobj_conn, &pyobj_conn_inst)) {
+        printf("%s failed parsing tuple\n", __FUNCTION__);
+        return VIR_PY_INT_FAIL;
+        }
+
+#ifdef DEBUG_ERROR
+    printf("libvirt_virConnectDomainEventRegister(%p %p) called\n",
+           pyobj_conn, pyobj_conn_inst);
+#endif
+    conn   = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+
+    Py_INCREF(pyobj_conn_inst);
+
+    ret = virConnectDomainEventRegister(conn,
+                                        libvirt_virConnectDomainEventCallback,
+                                        (void *)pyobj_conn_inst);
+
+    py_retval = libvirt_intWrap(ret);
+    return (py_retval);
+}
+
+static PyObject *
+libvirt_virConnectDomainEventDeregister(ATTRIBUTE_UNUSED PyObject * self,
+                                        PyObject * args)
+{
+    PyObject *py_retval;
+    PyObject *pyobj_conn;
+    PyObject *pyobj_conn_inst;
+
+    virConnectPtr conn;
+    int ret = 0;
+
+    if (!PyArg_ParseTuple
+        (args, (char *) "OO:virConnectDomainEventDeregister",
+         &pyobj_conn, &pyobj_conn_inst))
+        return (NULL);
+
+#ifdef DEBUG_ERROR
+    printf("libvirt_virConnectDomainEventDeregister(%p) called\n", pyobj_conn);
+#endif
+
+    conn   = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+
+    ret = virConnectDomainEventDeregister(conn, libvirt_virConnectDomainEventCallback);
+
+    Py_DECREF(pyobj_conn_inst);
+    py_retval = libvirt_intWrap(ret);
+    return (py_retval);
+}
+
+/*******************************************
+ * Event Impl
+ *******************************************/
+static PyObject *addHandleObj     = NULL;
+static PyObject *updateHandleObj  = NULL;
+static PyObject *removeHandleObj  = NULL;
+static PyObject *addTimeoutObj    = NULL;
+static PyObject *updateTimeoutObj = NULL;
+static PyObject *removeTimeoutObj = NULL;
+
+
+static int
+libvirt_virEventAddHandleFunc  (int fd ATTRIBUTE_UNUSED, int event ATTRIBUTE_UNUSED,
+                                virEventHandleCallback cb, void *opaque)
+{
+    PyObject *result = NULL;
+    PyObject *python_cb;
+    PyObject *cb_obj;
+    PyObject *opaque_obj;
+    PyObject *cb_args;
+    PyObject *pyobj_args;
+
+    /* Lookup the python callback */
+    python_cb = PyDict_GetItemString(getLibvirtDictObject(),
+                                     "eventInvokeHandleCallback");
+    if(!python_cb) {
+        printf("%s Error finding eventInvokeHandleCallback\n", __FUNCTION__);
+        PyErr_Print();
+        return -1;
+    }
+    Py_INCREF(python_cb);
+
+    /* create tuple for cb */
+    cb_obj = libvirt_virEventHandleCallbackWrap(cb);
+    opaque_obj = libvirt_virVoidPtrWrap(opaque);
+
+    cb_args = PyTuple_New(2);
+    PyTuple_SetItem(cb_args, 0, cb_obj);
+    PyTuple_SetItem(cb_args, 1, opaque_obj);
+
+    pyobj_args = PyTuple_New(4);
+    PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(fd));
+    PyTuple_SetItem(pyobj_args, 1, libvirt_intWrap(event));
+    PyTuple_SetItem(pyobj_args, 2, python_cb);
+    PyTuple_SetItem(pyobj_args, 3, cb_args);
+
+    if(addHandleObj && PyCallable_Check(addHandleObj))
+        result = PyEval_CallObject(addHandleObj, pyobj_args);
+
+    Py_XDECREF(result);
+    Py_DECREF(pyobj_args);
+    return 0;
+}
+
+static void
+libvirt_virEventUpdateHandleFunc(int fd, int event)
+{
+    PyObject *result = NULL;
+    PyObject *pyobj_args = PyTuple_New(2);
+    PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(fd));
+    PyTuple_SetItem(pyobj_args, 1, libvirt_intWrap(event));
+
+    if(updateHandleObj && PyCallable_Check(updateHandleObj))
+        result = PyEval_CallObject(updateHandleObj, pyobj_args);
+
+    Py_XDECREF(result);
+    Py_DECREF(pyobj_args);
+}
+
+static int
+libvirt_virEventRemoveHandleFunc(int fd)
+{
+    PyObject *result = NULL;
+    PyObject *pyobj_args = PyTuple_New(1);
+    PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(fd));
+
+    if(removeHandleObj && PyCallable_Check(removeHandleObj))
+        result = PyEval_CallObject(removeHandleObj, pyobj_args);
+
+    Py_XDECREF(result);
+    Py_DECREF(pyobj_args);
+    return 0;
+}
+
+static int
+libvirt_virEventAddTimeoutFunc(int timeout, virEventTimeoutCallback cb,
+                               void *opaque)
+{
+    PyObject *result = NULL;
+
+    PyObject *python_cb;
+
+    PyObject *cb_obj;
+    PyObject *opaque_obj;
+    PyObject *cb_args;
+    PyObject *pyobj_args;
+
+    /* Lookup the python callback */
+    python_cb = PyDict_GetItemString(getLibvirtDictObject(),
+                                     "eventInvokeTimeoutCallback");
+    if(!python_cb) {
+        printf("%s Error finding eventInvokeTimeoutCallback\n", __FUNCTION__);
+        PyErr_Print();
+        return -1;
+    }
+    Py_INCREF(python_cb);
+
+    /* create tuple for cb */
+    cb_obj = libvirt_virEventTimeoutCallbackWrap(cb);
+    opaque_obj = libvirt_virVoidPtrWrap(opaque);
+
+    cb_args = PyTuple_New(2);
+    PyTuple_SetItem(cb_args, 0, cb_obj);
+    PyTuple_SetItem(cb_args, 1, opaque_obj);
+
+    pyobj_args = PyTuple_New(3);
+
+    PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(timeout));
+    PyTuple_SetItem(pyobj_args, 1, python_cb);
+    PyTuple_SetItem(pyobj_args, 2, cb_args);
+
+    if(addTimeoutObj && PyCallable_Check(addTimeoutObj))
+        result = PyEval_CallObject(addTimeoutObj, pyobj_args);
+
+    Py_XDECREF(result);
+    Py_DECREF(pyobj_args);
+    return 0;
+}
+
+static void
+libvirt_virEventUpdateTimeoutFunc(int timer, int timeout)
+{
+    PyObject *result = NULL;
+    PyObject *pyobj_args = PyTuple_New(2);
+    PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(timer));
+    PyTuple_SetItem(pyobj_args, 1, libvirt_intWrap(timeout));
+
+    if(updateTimeoutObj && PyCallable_Check(updateTimeoutObj))
+        result = PyEval_CallObject(updateTimeoutObj, pyobj_args);
+
+    Py_XDECREF(result);
+    Py_DECREF(pyobj_args);
+}
+
+static int
+libvirt_virEventRemoveTimeoutFunc(int timer)
+{
+    PyObject *result = NULL;
+    PyObject *pyobj_args = PyTuple_New(1);
+    PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(timer));
+
+    if(updateTimeoutObj && PyCallable_Check(updateTimeoutObj))
+        result = PyEval_CallObject(removeTimeoutObj, pyobj_args);
+
+    Py_XDECREF(result);
+    Py_DECREF(pyobj_args);
+    return 0;
+}
+
+static PyObject *
+libvirt_virEventRegisterImpl(ATTRIBUTE_UNUSED PyObject * self,
+                             PyObject * args)
+{
+    Py_XDECREF(addHandleObj);
+    Py_XDECREF(updateHandleObj);
+    Py_XDECREF(removeHandleObj);
+    Py_XDECREF(addTimeoutObj);
+    Py_XDECREF(updateTimeoutObj);
+    Py_XDECREF(removeTimeoutObj);
+
+    if (!PyArg_ParseTuple
+        (args, (char *) "OOOOOO:virEventRegisterImpl",
+                        &addHandleObj,
+                        &updateHandleObj,
+                        &removeHandleObj,
+                        &addTimeoutObj,
+                        &updateTimeoutObj,
+                        &removeTimeoutObj
+        ))
+        return VIR_PY_INT_FAIL;
+
+    Py_INCREF(addHandleObj);
+    Py_INCREF(updateHandleObj);
+    Py_INCREF(removeHandleObj);
+    Py_INCREF(addTimeoutObj);
+    Py_INCREF(updateTimeoutObj);
+    Py_INCREF(removeTimeoutObj);
+
+    virEventRegisterImpl(libvirt_virEventAddHandleFunc,
+                         libvirt_virEventUpdateHandleFunc,
+                         libvirt_virEventRemoveHandleFunc,
+                         libvirt_virEventAddTimeoutFunc,
+                         libvirt_virEventUpdateTimeoutFunc,
+                         libvirt_virEventRemoveTimeoutFunc);
+
+    return VIR_PY_INT_SUCCESS;
+}
+
+static PyObject *
+libvirt_virEventInvokeHandleCallback(PyObject *self ATTRIBUTE_UNUSED,
+                                     PyObject *args)
+{
+    int fd, event;
+    PyObject *py_f;
+    PyObject *py_opaque;
+    virEventHandleCallback cb;
+    void *opaque;
+
+    if (!PyArg_ParseTuple
+        (args, (char *) "iiOO:virEventInvokeHandleCallback",
+                        &fd, &event, &py_f, &py_opaque
+        ))
+        return VIR_PY_INT_FAIL;
+
+    cb     = (virEventHandleCallback) PyvirEventHandleCallback_Get(py_f);
+    opaque = (void *) PyvirVoidPtr_Get(py_opaque);
+
+    if(cb)
+        cb (fd, event, opaque);
+
+    return VIR_PY_INT_SUCCESS;
+}
+
+static PyObject *
+libvirt_virEventInvokeTimeoutCallback(PyObject *self ATTRIBUTE_UNUSED,
+                                      PyObject *args)
+{
+    int timer;
+    PyObject *py_f;
+    PyObject *py_opaque;
+    virEventTimeoutCallback cb;
+    void *opaque;
+
+    if (!PyArg_ParseTuple
+        (args, (char *) "iOO:virEventInvokeTimeoutCallback",
+                        &timer, &py_f, &py_opaque
+        ))
+        return VIR_PY_INT_FAIL;
+
+    cb     = (virEventTimeoutCallback) PyvirEventTimeoutCallback_Get(py_f);
+    opaque = (void *) PyvirVoidPtr_Get(py_opaque);
+    if(cb)
+        cb (timer, opaque);
+
+    return VIR_PY_INT_SUCCESS;
+}
 
 /************************************************************************
  *									*
@@ -1479,6 +1915,8 @@ static PyMethodDef libvirtMethods[] = {
     {(char *) "virConnectOpenAuth", libvirt_virConnectOpenAuth, METH_VARARGS, NULL},
     {(char *) "virConnectListDomainsID", libvirt_virConnectListDomainsID, METH_VARARGS, NULL},
     {(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, METH_VARARGS, NULL},
+    {(char *) "virConnectDomainEventRegister", libvirt_virConnectDomainEventRegister, METH_VARARGS, NULL},
+    {(char *) "virConnectDomainEventDeregister", libvirt_virConnectDomainEventDeregister, METH_VARARGS, NULL},
     {(char *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL},
     {(char *) "virNodeGetInfo", libvirt_virNodeGetInfo, METH_VARARGS, NULL},
     {(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL},
@@ -1511,6 +1949,9 @@ static PyMethodDef libvirtMethods[] = {
     {(char *) "virStoragePoolGetUUID", libvirt_virStoragePoolGetUUID, METH_VARARGS, NULL},
     {(char *) "virStoragePoolGetUUIDString", libvirt_virStoragePoolGetUUIDString, METH_VARARGS, NULL},
     {(char *) "virStoragePoolLookupByUUID", libvirt_virStoragePoolLookupByUUID, METH_VARARGS, NULL},
+    {(char *) "virEventRegisterImpl", libvirt_virEventRegisterImpl, METH_VARARGS, NULL},
+    {(char *) "virEventInvokeHandleCallback", libvirt_virEventInvokeHandleCallback, METH_VARARGS, NULL},
+    {(char *) "virEventInvokeTimeoutCallback", libvirt_virEventInvokeTimeoutCallback, METH_VARARGS, NULL},
     {NULL, NULL, 0, NULL}
 };
 
diff --git a/python/libvir.py b/python/libvir.py
index cf5e776..86bf422 100644
--- a/python/libvir.py
+++ b/python/libvir.py
@@ -123,6 +123,26 @@ def getVersion (name = None):
     return ret
 
 
+#
+# Invoke an EventHandle callback
+#
+def eventInvokeHandleCallback (fd, event, callback, opaque):
+    """
+    Invoke the Event Impl Handle Callback in C
+    """
+    libvirtmod.virEventInvokeHandleCallback(fd, event, callback, opaque);
+
+#
+# Invoke an EventTimeout callback
+#
+def eventInvokeTimeoutCallback (timer, callback, opaque):
+    """
+    Invoke the Event Impl Timeout Callback in C
+    """
+    libvirtmod.virEventInvokeTimeoutCallback(timer, callback, opaque);
+
+
+
 # WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 #
 # Everything before this line comes from libvir.py
diff --git a/python/libvirt_wrap.h b/python/libvirt_wrap.h
index f8ecb76..b46deaf 100644
--- a/python/libvirt_wrap.h
+++ b/python/libvirt_wrap.h
@@ -65,6 +65,29 @@ typedef struct {
     virStorageVolPtr obj;
 } PyvirStorageVol_Object;
 
+#define PyvirEventHandleCallback_Get(v) (((v) == Py_None) ? NULL : \
+        (((PyvirEventHandleCallback_Object *)(v))->obj))
+
+typedef struct {
+    PyObject_HEAD
+    virEventHandleCallback obj;
+} PyvirEventHandleCallback_Object;
+
+#define PyvirEventTimeoutCallback_Get(v) (((v) == Py_None) ? NULL : \
+        (((PyvirEventTimeoutCallback_Object *)(v))->obj))
+
+typedef struct {
+    PyObject_HEAD
+    virEventTimeoutCallback obj;
+} PyvirEventTimeoutCallback_Object;
+
+#define PyvirVoidPtr_Get(v) (((v) == Py_None) ? NULL : \
+        (((PyvirVoidPtr_Object *)(v))->obj))
+
+typedef struct {
+    PyObject_HEAD
+    void* obj;
+} PyvirVoidPtr_Object;
 
 PyObject * libvirt_intWrap(int val);
 PyObject * libvirt_longWrap(long val);
@@ -78,7 +101,9 @@ PyObject * libvirt_virDomainPtrWrap(virDomainPtr node);
 PyObject * libvirt_virNetworkPtrWrap(virNetworkPtr node);
 PyObject * libvirt_virStoragePoolPtrWrap(virStoragePoolPtr node);
 PyObject * libvirt_virStorageVolPtrWrap(virStorageVolPtr node);
-
+PyObject * libvirt_virEventHandleCallbackWrap(virEventHandleCallback node);
+PyObject * libvirt_virEventTimeoutCallbackWrap(virEventTimeoutCallback node);
+PyObject * libvirt_virVoidPtrWrap(void* node);
 
 /* Provide simple macro statement wrappers (adapted from GLib, in turn from Perl):
  *  LIBVIRT_STMT_START { statements; } LIBVIRT_STMT_END;
diff --git a/python/types.c b/python/types.c
index 8e08d25..1c1db89 100644
--- a/python/types.c
+++ b/python/types.c
@@ -162,3 +162,50 @@ libvirt_virConnectPtrWrap(virConnectPtr node)
                                      NULL);
     return (ret);
 }
+
+PyObject *
+libvirt_virEventHandleCallbackWrap(virEventHandleCallback node)
+{
+    PyObject *ret;
+
+    if (node == NULL) {
+        Py_INCREF(Py_None);
+        printf("%s: WARNING - Wrapping None\n", __FUNCTION__);
+        return (Py_None);
+    }
+    ret =
+        PyCObject_FromVoidPtrAndDesc((void *) node, (char *) "virEventHandleCallback",
+                                     NULL);
+    return (ret);
+}
+
+PyObject *
+libvirt_virEventTimeoutCallbackWrap(virEventTimeoutCallback node)
+{
+    PyObject *ret;
+
+    if (node == NULL) {
+        printf("%s: WARNING - Wrapping None\n", __FUNCTION__);
+        Py_INCREF(Py_None);
+        return (Py_None);
+    }
+    ret =
+        PyCObject_FromVoidPtrAndDesc((void *) node, (char *) "virEventTimeoutCallback",
+                                     NULL);
+    return (ret);
+}
+
+PyObject *
+libvirt_virVoidPtrWrap(void* node)
+{
+    PyObject *ret;
+
+    if (node == NULL) {
+        Py_INCREF(Py_None);
+        return (Py_None);
+    }
+    ret =
+        PyCObject_FromVoidPtrAndDesc((void *) node, (char *) "void*",
+                                     NULL);
+    return (ret);
+}
diff --git a/python/virConnect.py b/python/virConnect.py
new file mode 100644
index 0000000..ec29b33
--- /dev/null
+++ b/python/virConnect.py
@@ -0,0 +1,43 @@
+    def __del__(self):
+        try:
+           for cb,opaque in self.domainEventCallbacks.items():
+               del self.domainEventCallbacks[cb]
+           self.domainEventCallbacks = None
+           libvirtmod.virConnectDomainEventDeregister(self._o, self)
+        except AttributeError:
+           pass
+
+        if self._o != None:
+            libvirtmod.virConnectClose(self._o)
+        self._o = None
+
+    def domainEventDeregister(self, cb):
+        """Removes a Domain Event Callback. De-registering for a
+           domain callback will disable delivery of this event type """
+        try:
+            del self.domainEventCallbacks[cb]
+            if len(self.domainEventCallbacks) == 0:
+                ret = libvirtmod.virConnectDomainEventDeregister(self._o, self)
+                if ret == -1: raise libvirtError ('virConnectDomainEventDeregister() failed', conn=self)
+        except AttributeError:
+            pass
+
+    def domainEventRegister(self, cb, opaque):
+        """Adds a Domain Event Callback. Registering for a domain
+           callback will enable delivery of the events """
+        try:
+            self.domainEventCallbacks[cb] = opaque
+        except AttributeError:
+            self.domainEventCallbacks = {cb:opaque}
+            ret = libvirtmod.virConnectDomainEventRegister(self._o, self)
+            if ret == -1: raise libvirtError ('virConnectDomainEventRegister() failed', conn=self)
+
+    def dispatchDomainEventCallbacks(self, dom, event):
+        """Dispatches events to python user domain event callbacks
+        """
+        try:
+            for cb,opaque in self.domainEventCallbacks.items():
+                cb(self,dom,event,opaque)
+            return 0
+        except AttributeError:
+            pass
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to