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
This commit is contained in:
Daniel P. Berrange 2010-03-26 13:22:06 +00:00
parent df62337289
commit 6df7d55d39
3 changed files with 517 additions and 1 deletions

View File

@ -412,6 +412,21 @@ def myDomainEventCallback1 (conn, dom, event, detail, opaque):
def myDomainEventCallback2 (conn, dom, event, detail, opaque): def myDomainEventCallback2 (conn, dom, event, detail, opaque):
print "myDomainEventCallback2 EVENT: Domain %s(%s) %s %d" % (dom.name(), dom.ID(), eventToString(event), detail) print "myDomainEventCallback2 EVENT: Domain %s(%s) %s %d" % (dom.name(), dom.ID(), eventToString(event), detail)
def myDomainEventRebootCallback(conn, dom, opaque):
print "myDomainEventRebootCallback: Domain %s(%s)" % (dom.name(), dom.ID())
def myDomainEventRTCChangeCallback(conn, dom, utcoffset, opaque):
print "myDomainEventRTCChangeCallback: Domain %s(%s) %d" % (dom.name(), dom.ID(), utcoffset)
def myDomainEventWatchdogCallback(conn, dom, action, opaque):
print "myDomainEventWatchdogCallback: Domain %s(%s) %d" % (dom.name(), dom.ID(), action)
def myDomainEventIOErrorCallback(conn, dom, srcpath, devalias, action, opaque):
print "myDomainEventIOErrorCallback: Domain %s(%s) %s %s %d" % (dom.name(), dom.ID(), srcpath, devalias, action)
def myDomainEventGraphicsCallback(conn, dom, phase, localAddr, remoteAddr, authScheme, subject, opaque):
print "myDomainEventGraphicsCallback: Domain %s(%s) %d %s" % (dom.name(), dom.ID(), phase, authScheme)
def usage(): def usage():
print "usage: "+os.path.basename(sys.argv[0])+" [uri]" print "usage: "+os.path.basename(sys.argv[0])+" [uri]"
print " uri will default to qemu:///system" print " uri will default to qemu:///system"
@ -451,7 +466,12 @@ def main():
#Add 2 callbacks to prove this works with more than just one #Add 2 callbacks to prove this works with more than just one
vc.domainEventRegister(myDomainEventCallback1,None) vc.domainEventRegister(myDomainEventCallback1,None)
vc.domainEventRegister(myDomainEventCallback2,None) vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, myDomainEventCallback2, None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_REBOOT, myDomainEventRebootCallback, None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_RTC_CHANGE, myDomainEventRTCChangeCallback, None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR, myDomainEventIOErrorCallback, None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, myDomainEventWatchdogCallback, None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, myDomainEventGraphicsCallback, None)
# The rest of your app would go here normally, but for sake # The rest of your app would go here normally, but for sake
# of demo we'll just go to sleep. The other option is to # of demo we'll just go to sleep. The other option is to

View File

@ -41,3 +41,48 @@
return 0 return 0
except AttributeError: except AttributeError:
pass 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

View File

@ -2761,6 +2761,455 @@ libvirt_virEventInvokeTimeoutCallback(PyObject *self ATTRIBUTE_UNUSED,
return VIR_PY_INT_SUCCESS; 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 * * The registration stuff *
@ -2776,6 +3225,8 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, METH_VARARGS, NULL}, {(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, METH_VARARGS, NULL},
{(char *) "virConnectDomainEventRegister", libvirt_virConnectDomainEventRegister, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventRegister", libvirt_virConnectDomainEventRegister, METH_VARARGS, NULL},
{(char *) "virConnectDomainEventDeregister", libvirt_virConnectDomainEventDeregister, 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 *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL},
{(char *) "virNodeGetInfo", libvirt_virNodeGetInfo, METH_VARARGS, NULL}, {(char *) "virNodeGetInfo", libvirt_virNodeGetInfo, METH_VARARGS, NULL},
{(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL}, {(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL},