[libvirt] [PATCH] Bind connection close callback APIs to python binding

Daniel P. Berrange berrange at redhat.com
Mon Jul 30 16:31:30 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

Add code in the python binding to cope with the new APIs
virConnectRegisterCloseCallback and
virConnectDeregisterCloseCallback. Also demonstrate their
use in the python domain events demo
---
 examples/domain-events/events-python/event-test.py |   14 ++-
 python/generator.py                                |    5 +-
 python/libvirt-override-virConnect.py              |   24 +++++
 python/libvirt-override.c                          |  107 ++++++++++++++++++++
 4 files changed, 147 insertions(+), 3 deletions(-)

diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py
index 736c225..8193d18 100644
--- a/examples/domain-events/events-python/event-test.py
+++ b/examples/domain-events/events-python/event-test.py
@@ -490,6 +490,16 @@ def myDomainEventPMSuspendCallback(conn, dom, reason, opaque):
             dom.name(), dom.ID())
 def myDomainEventBalloonChangeCallback(conn, dom, utcoffset, actual):
     print "myDomainEventBalloonChangeCallback: Domain %s(%s) %d" % (dom.name(), dom.ID(), actual)
+
+run = True
+
+def myConnectionCloseCallback(conn, reason, opaque):
+    reasonStrings = (
+        "Error", "End-of-file", "Keepalive", "Client",
+        )
+    print "myConnectionCloseCallback: %s: %s" % (conn.getURI(), reasonStrings[reason])
+    run = False
+
 def usage(out=sys.stderr):
     print >>out, "usage: "+os.path.basename(sys.argv[0])+" [-hdl] [uri]"
     print >>out, "   uri will default to qemu:///system"
@@ -539,6 +549,8 @@ def main():
         if (old_exitfunc): old_exitfunc()
     sys.exitfunc = exit
 
+    vc.registerCloseCallback(myConnectionCloseCallback, None)
+
     #Add 2 callbacks to prove this works with more than just one
     vc.domainEventRegister(myDomainEventCallback1,None)
     vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, myDomainEventCallback2, None)
@@ -559,7 +571,7 @@ def main():
     # of demo we'll just go to sleep. The other option is to
     # run the event loop in your main thread if your app is
     # totally event based.
-    while vc.isAlive() == 1:
+    while run:
         time.sleep(1)
 
 
diff --git a/python/generator.py b/python/generator.py
index 6559ece..6ccbf56 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -425,8 +425,6 @@ skip_impl = (
     'virDomainGetInterfaceParameters',
     'virDomainGetCPUStats',
     'virDomainGetDiskErrors',
-    'virConnectUnregisterCloseCallback',
-    'virConnectRegisterCloseCallback',
 )
 
 qemu_skip_impl = (
@@ -464,6 +462,9 @@ skip_function = (
     'virStreamRecv', # overridden in libvirt-override-virStream.py
     'virStreamSend', # overridden in libvirt-override-virStream.py
 
+    'virConnectDeregisterCloseCallback', # overriden in virConnect.py
+    'virConnectRegisterCloseCallback', # overriden in virConnect.py
+
     # 'Ref' functions have no use for bindings users.
     "virConnectRef",
     "virDomainRef",
diff --git a/python/libvirt-override-virConnect.py b/python/libvirt-override-virConnect.py
index 50177ab..de8167e 100644
--- a/python/libvirt-override-virConnect.py
+++ b/python/libvirt-override-virConnect.py
@@ -206,3 +206,27 @@
             retlist.append(virDomain(self, _obj=domptr))
 
         return retlist
+
+    def _dispatchCloseCallback(self, reason, cbData):
+        """Dispatches events to python user close callback"""
+        cb = cbData["cb"]
+        opaque = cbData["opaque"]
+
+        cb(self, reason, opaque)
+        return 0
+
+
+    def deregisterCloseCallback(self):
+        """Removes a close event callback"""
+        ret = libvirtmod.virConnectDeregisterCloseCallback(self._o)
+        if ret == -1: raise libvirtError ('virConnectDeregisterCloseCallback() failed', conn=self)
+
+    def registerCloseCallback(self, cb, opaque):
+        """Adds a close event callback, providing a notification
+         when a connection fails / closes"""
+        cbData = { "cb": cb, "conn": self, "opaque": opaque }
+        ret = libvirtmod.virConnectRegisterCloseCallback(self._o, cbData)
+        if ret == -1:
+            raise libvirtError ('virConnectRegisterCloseCallback() failed', conn=self)
+        return ret
+
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 8b41dff..b7269fc 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -5521,6 +5521,111 @@ libvirt_virConnectDomainEventDeregisterAny(ATTRIBUTE_UNUSED PyObject * self,
     return py_retval;
 }
 
+
+static void
+libvirt_virConnectCloseCallbackDispatch(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                        int reason,
+                                        void *opaque)
+{
+    PyObject *pyobj_cbData = (PyObject*)opaque;
+    PyObject *pyobj_ret;
+    PyObject *pyobj_conn;
+    PyObject *dictKey;
+
+    LIBVIRT_ENSURE_THREAD_STATE;
+
+    Py_INCREF(pyobj_cbData);
+
+    dictKey = libvirt_constcharPtrWrap("conn");
+    pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
+    Py_DECREF(dictKey);
+
+    /* Call the Callback Dispatcher */
+    pyobj_ret = PyObject_CallMethod(pyobj_conn,
+                                    (char*)"_dispatchCloseCallback",
+                                    (char*)"iO",
+                                    reason,
+                                    pyobj_cbData);
+
+    Py_DECREF(pyobj_cbData);
+
+    if(!pyobj_ret) {
+        DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+        PyErr_Print();
+    } else {
+        Py_DECREF(pyobj_ret);
+    }
+
+    LIBVIRT_RELEASE_THREAD_STATE;
+}
+
+static PyObject *
+libvirt_virConnectRegisterCloseCallback(ATTRIBUTE_UNUSED PyObject * self,
+                                        PyObject * args)
+{
+    PyObject *py_retval;        /* return value */
+    PyObject *pyobj_conn;       /* virConnectPtr */
+    PyObject *pyobj_cbData;     /* hash of callback data */
+    virConnectPtr conn;
+    int ret = 0;
+
+    if (!PyArg_ParseTuple
+        (args, (char *) "OO:virConnectRegisterCloseCallback",
+         &pyobj_conn, &pyobj_cbData)) {
+        DEBUG("%s failed parsing tuple\n", __FUNCTION__);
+        return VIR_PY_INT_FAIL;
+    }
+
+    DEBUG("libvirt_virConnectRegisterCloseCallback(%p %p) called\n",
+           pyobj_conn, pyobj_cbData);
+    conn = PyvirConnect_Get(pyobj_conn);
+
+    Py_INCREF(pyobj_cbData);
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+    ret = virConnectRegisterCloseCallback(conn,
+                                          libvirt_virConnectCloseCallbackDispatch,
+                                          pyobj_cbData,
+                                          libvirt_virConnectDomainEventFreeFunc);
+    LIBVIRT_END_ALLOW_THREADS;
+
+    if (ret < 0) {
+        Py_DECREF(pyobj_cbData);
+    }
+
+    py_retval = libvirt_intWrap(ret);
+    return py_retval;
+}
+
+static PyObject *
+libvirt_virConnectDeregisterCloseCallback(ATTRIBUTE_UNUSED PyObject * self,
+                                          PyObject * args)
+{
+    PyObject *py_retval;
+    PyObject *pyobj_conn;
+    virConnectPtr conn;
+    int ret = 0;
+
+    if (!PyArg_ParseTuple
+        (args, (char *) "O:virConnectDomainEventDeregister",
+         &pyobj_conn))
+        return NULL;
+
+    DEBUG("libvirt_virConnectDomainEventDeregister(%p) called\n",
+          pyobj_conn);
+
+    conn = PyvirConnect_Get(pyobj_conn);
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+
+    ret = virConnectDeregisterCloseCallback(conn,
+                                            libvirt_virConnectCloseCallbackDispatch);
+
+    LIBVIRT_END_ALLOW_THREADS;
+    py_retval = libvirt_intWrap(ret);
+    return py_retval;
+}
+
 static void
 libvirt_virStreamEventFreeFunc(void *opaque)
 {
@@ -5822,10 +5927,12 @@ static PyMethodDef libvirtMethods[] = {
     {(char *) "virConnectListDomainsID", libvirt_virConnectListDomainsID, METH_VARARGS, NULL},
     {(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, METH_VARARGS, NULL},
     {(char *) "virConnectListAllDomains", libvirt_virConnectListAllDomains, METH_VARARGS, NULL},
+    {(char *) "virConnectDeregisterCloseCallback", libvirt_virConnectDeregisterCloseCallback, METH_VARARGS, NULL},
     {(char *) "virConnectDomainEventRegister", libvirt_virConnectDomainEventRegister, METH_VARARGS, NULL},
     {(char *) "virConnectDomainEventDeregister", libvirt_virConnectDomainEventDeregister, METH_VARARGS, NULL},
     {(char *) "virConnectDomainEventRegisterAny", libvirt_virConnectDomainEventRegisterAny, METH_VARARGS, NULL},
     {(char *) "virConnectDomainEventDeregisterAny", libvirt_virConnectDomainEventDeregisterAny, METH_VARARGS, NULL},
+    {(char *) "virConnectRegisterCloseCallback", libvirt_virConnectRegisterCloseCallback, METH_VARARGS, NULL},
     {(char *) "virStreamEventAddCallback", libvirt_virStreamEventAddCallback, METH_VARARGS, NULL},
     {(char *) "virStreamRecv", libvirt_virStreamRecv, METH_VARARGS, NULL},
     {(char *) "virStreamSend", libvirt_virStreamSend, METH_VARARGS, NULL},
-- 
1.7.10.4




More information about the libvir-list mailing list