summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2010-03-26 13:22:06 +0000
committerDaniel P. Berrange <berrange@redhat.com>2010-04-08 12:41:40 +0100
commit24f9a46106ff5f55bf225867f259573241061719 (patch)
tree1437bd4247f7a2627266d76c5b231059eec2a125
parentbe5c34b75242f68dce33ba08081c46d27eae05bb (diff)
Fix up python bindings for new event callbacks
The generator was disabled for the new event callbacks, since they need to be hand written. This patch adds the C and python glue to expose the new APIs in the python binding. The python example program is extended to demonstrate of the code * python/libvirt-override.c: Registration and dispatch of events at the C layer * python/libvirt-override-virConnect.py: Python glue for events * examples/domain-events/events-python/event-test.py: Demo use of new event callbacks
-rw-r--r--libvirt-override-virConnect.py45
-rw-r--r--libvirt-override.c451
2 files changed, 496 insertions, 0 deletions
diff --git a/libvirt-override-virConnect.py b/libvirt-override-virConnect.py
index 1fdf548..444a499 100644
--- a/libvirt-override-virConnect.py
+++ b/libvirt-override-virConnect.py
@@ -41,3 +41,48 @@
return 0
except AttributeError:
pass
+
+ def dispatchDomainEventLifecycleCallback(self, dom, event, detail, cbData):
+ """Dispatches events to python user domain event callbacks
+ """
+ cb = cbData["cb"]
+ opaque = cbData["opaque"]
+
+ cb(self, virDomain(self, _obj=dom), event, detail, opaque)
+ return 0
+
+ def dispatchDomainEventGenericCallback(self, dom, cbData):
+ """Dispatches events to python user domain event callbacks
+ """
+ try:
+ cb = cbData["cb"]
+ opaque = cbData["opaque"]
+
+ cb(self, virDomain(self, _obj=dom), opaque)
+ return 0
+ except AttributeError:
+ pass
+
+ def domainEventDeregisterAny(self, callbackID):
+ """Removes a Domain Event Callback. De-registering for a
+ domain callback will disable delivery of this event type """
+ try:
+ ret = libvirtmod.virConnectDomainEventDeregisterAny(self._o, callbackID)
+ if ret == -1: raise libvirtError ('virConnectDomainEventDeregisterAny() failed', conn=self)
+ del self.domainEventCallbackID[callbackID]
+ except AttributeError:
+ pass
+
+ def domainEventRegisterAny(self, dom, eventID, cb, opaque):
+ """Adds a Domain Event Callback. Registering for a domain
+ callback will enable delivery of the events """
+ if not hasattr(self, 'domainEventCallbackID'):
+ self.domainEventCallbackID = {}
+ cbData = { "cb": cb, "conn": self, "opaque": opaque }
+ if dom is None:
+ ret = libvirtmod.virConnectDomainEventRegisterAny(self._o, None, eventID, cbData)
+ else:
+ ret = libvirtmod.virConnectDomainEventRegisterAny(self._o, dom._o, eventID, cbData)
+ if ret == -1:
+ raise libvirtError ('virConnectDomainEventRegisterAny() failed', conn=self)
+ self.domainEventCallbackID[ret] = opaque
diff --git a/libvirt-override.c b/libvirt-override.c
index e27bce6..02bc313 100644
--- a/libvirt-override.c
+++ b/libvirt-override.c
@@ -2761,6 +2761,455 @@ libvirt_virEventInvokeTimeoutCallback(PyObject *self ATTRIBUTE_UNUSED,
return VIR_PY_INT_SUCCESS;
}
+
+static void
+libvirt_virConnectDomainEventFreeFunc(void *opaque)
+{
+ PyObject *pyobj_conn = (PyObject*)opaque;
+ LIBVIRT_ENSURE_THREAD_STATE;
+ Py_DECREF(pyobj_conn);
+ LIBVIRT_RELEASE_THREAD_STATE;
+}
+
+static int
+libvirt_virConnectDomainEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int event,
+ int detail,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ int ret = -1;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ 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*)"dispatchDomainEventLifecycleCallback",
+ (char*)"OiiO",
+ pyobj_dom,
+ event, detail,
+ pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+#if DEBUG_ERROR
+ printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
+static int
+libvirt_virConnectDomainEventGenericCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ int ret = -1;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ 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*)"dispatchDomainEventGenericCallback",
+ (char*)"OO",
+ pyobj_dom, pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+#if DEBUG_ERROR
+ printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
+static int
+libvirt_virConnectDomainEventRTCChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ long long utcoffset,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ int ret = -1;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ 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*)"dispatchDomainEventRTCChangeCallback",
+ (char*)"OLO",
+ pyobj_dom,
+ (PY_LONG_LONG)utcoffset,
+ pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+#if DEBUG_ERROR
+ printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
+static int
+libvirt_virConnectDomainEventWatchdogCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int action,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ int ret = -1;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ 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*)"dispatchDomainEventWatchdogCallback",
+ (char*)"OiO",
+ pyobj_dom,
+ action,
+ pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+#if DEBUG_ERROR
+ printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
+static int
+libvirt_virConnectDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ int ret = -1;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ 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*)"dispatchDomainEventIOErrorCallback",
+ (char*)"OssiO",
+ pyobj_dom,
+ srcPath, devAlias, action,
+ pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+#if DEBUG_ERROR
+ printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
+static int
+libvirt_virConnectDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ PyObject *pyobj_local;
+ PyObject *pyobj_remote;
+ PyObject *pyobj_subject;
+ int ret = -1;
+ int i;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ Py_INCREF(pyobj_cbData);
+
+ dictKey = libvirt_constcharPtrWrap("conn");
+ pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
+ Py_DECREF(dictKey);
+
+ pyobj_local = PyDict_New();
+ PyDict_SetItem(pyobj_local,
+ libvirt_constcharPtrWrap("family"),
+ libvirt_intWrap(local->family));
+ PyDict_SetItem(pyobj_local,
+ libvirt_constcharPtrWrap("node"),
+ libvirt_constcharPtrWrap(local->node));
+ PyDict_SetItem(pyobj_local,
+ libvirt_constcharPtrWrap("service"),
+ libvirt_constcharPtrWrap(local->service));
+
+ pyobj_remote = PyDict_New();
+ PyDict_SetItem(pyobj_remote,
+ libvirt_constcharPtrWrap("family"),
+ libvirt_intWrap(remote->family));
+ PyDict_SetItem(pyobj_remote,
+ libvirt_constcharPtrWrap("node"),
+ libvirt_constcharPtrWrap(remote->node));
+ PyDict_SetItem(pyobj_remote,
+ libvirt_constcharPtrWrap("service"),
+ libvirt_constcharPtrWrap(remote->service));
+
+ pyobj_subject = PyList_New(subject->nidentity);
+ for (i = 0 ; i < subject->nidentity ; i++) {
+ PyObject *pair = PyTuple_New(2);
+ PyTuple_SetItem(pair, 0, libvirt_constcharPtrWrap(subject->identities[i].type));
+ PyTuple_SetItem(pair, 1, libvirt_constcharPtrWrap(subject->identities[i].name));
+
+ PyList_SetItem(pyobj_subject, i, pair);
+ }
+
+ /* Call the Callback Dispatcher */
+ pyobj_ret = PyObject_CallMethod(pyobj_conn,
+ (char*)"dispatchDomainEventGraphicsCallback",
+ (char*)"OiOOsOO",
+ pyobj_dom,
+ phase, pyobj_local, pyobj_remote,
+ authScheme, pyobj_subject,
+ pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+#if DEBUG_ERROR
+ printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
+static PyObject *
+libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
+ PyObject * args)
+{
+ PyObject *py_retval; /* return value */
+ PyObject *pyobj_conn; /* virConnectPtr */
+ PyObject *pyobj_dom;
+ PyObject *pyobj_cbData; /* hash of callback data */
+ int eventID;
+ virConnectPtr conn;
+ int ret = 0;
+ virConnectDomainEventGenericCallback cb = NULL;
+ virDomainPtr dom;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "OOiO:virConnectDomainEventRegisterAny",
+ &pyobj_conn, &pyobj_dom, &eventID, &pyobj_cbData)) {
+#if DEBUG_ERROR
+ printf("%s failed parsing tuple\n", __FUNCTION__);
+#endif
+ return VIR_PY_INT_FAIL;
+ }
+
+#ifdef DEBUG_ERROR
+ printf("libvirt_virConnectDomainEventRegister(%p %p %d %p) called\n",
+ pyobj_conn, pyobj_dom, eventID, pyobj_cbData);
+#endif
+ conn = PyvirConnect_Get(pyobj_conn);
+ if (pyobj_dom == Py_None)
+ dom = NULL;
+ else
+ dom = PyvirDomain_Get(pyobj_dom);
+
+ switch (eventID) {
+ case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventLifecycleCallback);
+ break;
+ case VIR_DOMAIN_EVENT_ID_REBOOT:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGenericCallback);
+ break;
+ case VIR_DOMAIN_EVENT_ID_RTC_CHANGE:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventRTCChangeCallback);
+ break;
+ case VIR_DOMAIN_EVENT_ID_WATCHDOG:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventWatchdogCallback);
+ break;
+ case VIR_DOMAIN_EVENT_ID_IO_ERROR:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorCallback);
+ break;
+ case VIR_DOMAIN_EVENT_ID_GRAPHICS:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGraphicsCallback);
+ break;
+ }
+
+ if (!cb) {
+ return VIR_PY_INT_FAIL;
+ }
+
+ Py_INCREF(pyobj_cbData);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ ret = virConnectDomainEventRegisterAny(conn, dom, eventID,
+ cb, 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_virConnectDomainEventDeregisterAny(ATTRIBUTE_UNUSED PyObject * self,
+ PyObject * args)
+{
+ PyObject *py_retval;
+ PyObject *pyobj_conn;
+ int callbackID;
+ virConnectPtr conn;
+ int ret = 0;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "Oi:virConnectDomainEventDeregister",
+ &pyobj_conn, &callbackID))
+ return (NULL);
+
+#ifdef DEBUG_ERROR
+ printf("libvirt_virConnectDomainEventDeregister(%p) called\n", pyobj_conn);
+#endif
+
+ conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+
+ ret = virConnectDomainEventDeregisterAny(conn, callbackID);
+
+ LIBVIRT_END_ALLOW_THREADS;
+ py_retval = libvirt_intWrap(ret);
+ return (py_retval);
+}
+
+
/************************************************************************
* *
* The registration stuff *
@@ -2776,6 +3225,8 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, 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 *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL},
{(char *) "virNodeGetInfo", libvirt_virNodeGetInfo, METH_VARARGS, NULL},
{(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL},