Attached is a preliminary patch implementing the python bindings for domain events, and the EventImpl code. This implements a python test app equivalent to the code in the C event-test app. Contrary to what Daniel B originally suggested, I thought that the EventImpl would be useful to expose for apps that are strictly using python, and not integrating with glib, or another event loop. It also makes the test case easier to debug. I have not marked this with [PATCH] in the subject, as I don't believe it is quite complete. I am still having a few issues with the Refcounting in the C code, and I think there is still some cleanup code I haven't quite handled quite right. That said - I would welcome some comments/suggestions on this thus far, to make sure I'm not going off in a direction contrary to where you think I should be. examples/domain-events/events-python/event-test.py | 187 ++++++++ python/generator.py | 8 python/libvir.c | 454 +++++++++++++++++++++ python/libvir.py | 20 python/libvirt_wrap.h | 27 + python/types.c | 48 ++ 6 files changed, 740 insertions(+), 4 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..6774f4d --- /dev/null +++ b/examples/domain-events/events-python/event-test.py @@ -0,0 +1,187 @@ +#!/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 = cb; + 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]" + +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 = "None" + + 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" + vc.domainEventDeregister(myDomainEventCallback1) + vc.domainEventDeregister(myDomainEventCallback2) + 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/generator.py b/python/generator.py index ca83eaf..fa1faba 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,9 @@ skip_impl = ( 'virStoragePoolListVolumes', 'virDomainBlockPeek', 'virDomainMemoryPeek', + 'virConnectDomainEventRegister', + 'virConnectDomainEventDeregister', + 'virEventRegisterImpl', ) @@ -332,9 +337,6 @@ 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', ) diff --git a/python/libvir.c b/python/libvir.c index 9cc0c81..ca77d73 100644 --- a/python/libvir.c +++ b/python/libvir.c @@ -1467,6 +1467,455 @@ libvirt_virStoragePoolLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *ar } +/******************************************* + * Domain Events + *******************************************/ + +/* a list of tuples, containing the python callback data */ +static PyObject *pyobj_domain_event_cbs = NULL; + +#define DUMP_REF(x) printf("%s:%d %s %d\n",__FUNCTION__,__LINE__,#x,(int)(x)->ob_refcnt) +static int +libvirt_virConnectDomainEventCallback(virConnectPtr conn, + virDomainPtr dom, + int event, + void *opaque) +{ + int i, n; + PyObject *pyobj_tuple_list = (PyObject*)opaque; + PyObject *pyobj_tuple; + + PyObject *pyobj_conn; /* the conn on the tuple list */ + PyObject *pyobj_dom; + PyObject *pyobj_cb; /* the Python callable object */ + PyObject *pyobj_userdata; /* user data registered to pass along */ + PyObject *pyobj_args; /* The tuple we will pass to the callback */ + + PyObject *libvirt_module; + PyObject *libvirt_dict; + PyObject *pyobj_dom_class; + PyObject *pyobj_conn_class; + + PyObject *pyobj_dom_args; + PyObject *pyobj_dom_kw; + PyObject *pyobj_dom_obj; + + PyObject *pyobj_conn_args; + PyObject *pyobj_conn_kw; + PyObject *pyobj_conn_obj; + + virConnectPtr tconn; + + libvirt_module = PyImport_ImportModule("libvirt"); + if(!libvirt_module) { + return -1; + } + libvirt_dict = PyModule_GetDict(libvirt_module); + pyobj_dom_class = PyDict_GetItemString(libvirt_dict, "virDomain"); + pyobj_conn_class = PyDict_GetItemString(libvirt_dict, "virConnect"); + + n = PyList_Size(pyobj_tuple_list); + + pyobj_dom = libvirt_virDomainPtrWrap(dom); + + for (i=0 ; i < n ; i++) { + pyobj_tuple = PyList_GetItem(pyobj_tuple_list, i); + pyobj_conn = PyTuple_GetItem(pyobj_tuple, 0); + tconn = PyvirConnect_Get(pyobj_conn); + + if(tconn == conn) { + /* This callback is appropriate for our conn. + Build a tuple, and call the object back */ + pyobj_cb = PyTuple_GetItem(pyobj_tuple, 1); + pyobj_userdata = PyTuple_GetItem(pyobj_tuple, 2); + + /* build the params for the python conn constructor */ + pyobj_conn_kw = PyDict_New(); + pyobj_conn_args = PyTuple_New(0); + + PyDict_SetItemString(pyobj_conn_kw, "_obj", pyobj_conn); + pyobj_conn_obj = PyInstance_New(pyobj_conn_class, pyobj_conn_args, pyobj_conn_kw); + + /* build the params for the python dom constructor */ + pyobj_dom_args = PyTuple_New(1); + PyTuple_SetItem(pyobj_dom_args, 0, pyobj_conn_obj); + Py_INCREF(pyobj_conn_obj); + + pyobj_dom_kw = PyDict_New(); + PyDict_SetItemString(pyobj_dom_kw, "_obj", pyobj_dom); + + pyobj_dom_obj = PyInstance_New(pyobj_dom_class, pyobj_dom_args, pyobj_dom_kw); + + /* build the params for the cb */ + pyobj_args = PyTuple_New(4); + + PyTuple_SetItem(pyobj_args, 0, pyobj_conn_obj); + PyTuple_SetItem(pyobj_args, 1, pyobj_dom_obj); + + PyTuple_SetItem(pyobj_args, 2, libvirt_intWrap(event)); + PyTuple_SetItem(pyobj_args, 3, pyobj_userdata); + Py_INCREF(pyobj_userdata); + + if(PyCallable_Check(pyobj_cb)) + PyEval_CallObject(pyobj_cb, pyobj_args); + + /* FIXME: Why do we need these increfs? + * Is this a leak? + * callback 2 had bad domain data if dom_obj not registered + */ + Py_INCREF(pyobj_conn_obj); + Py_INCREF(pyobj_dom_obj); + + Py_DECREF(pyobj_conn_args); + Py_DECREF(pyobj_conn_kw); + + Py_DECREF(pyobj_dom_args); + Py_DECREF(pyobj_dom_kw); + Py_DECREF(pyobj_args); /* decrements pyobj_conn_obj twice */ + + } + } + + Py_DECREF(pyobj_dom); + return 0; +} + +static PyObject * +libvirt_virConnectDomainEventRegister(ATTRIBUTE_UNUSED PyObject * self, + PyObject * args) +{ + PyObject *py_retval; /* return value */ + PyObject *pyobj_conn; /* connection ptr */ + PyObject *pyobj_f; /* python callable object */ + PyObject *pyobj_userdata; /* userdata to pass along */ + PyObject *pyobj_args; /* the list of args to pass + to libvirt_virConnectDomainEventCallback */ + + virConnectPtr conn; + int ret = 0; + + if (!PyArg_ParseTuple + (args, (char *) "OOO:virConnectDomainEventRegister", &pyobj_conn, + &pyobj_f, + &pyobj_userdata)) + return (NULL); + +#ifdef DEBUG_ERROR + printf("libvirt_virConnectDomainEventRegister(%p, %p, %p) called\n", + pyobj_conn, pyobj_f, pyobj_userdata); +#endif + conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + + pyobj_args = PyTuple_New(3); + PyTuple_SetItem(pyobj_args, 0, pyobj_conn); + Py_INCREF(pyobj_conn); + PyTuple_SetItem(pyobj_args, 1, pyobj_f); + Py_INCREF(pyobj_f); + PyTuple_SetItem(pyobj_args, 2, pyobj_userdata); + Py_INCREF(pyobj_userdata); + + if(!pyobj_domain_event_cbs) { + /* First time through. register callback, and init list */ + pyobj_domain_event_cbs = PyList_New(0); + ret = virConnectDomainEventRegister(conn, + libvirt_virConnectDomainEventCallback, + (void *)pyobj_domain_event_cbs); + } + + PyList_Append(pyobj_domain_event_cbs, pyobj_args); + Py_DECREF(pyobj_args); + + py_retval = libvirt_intWrap(ret); + return (py_retval); +} + +static PyObject * +libvirt_virConnectDomainEventDeregister(ATTRIBUTE_UNUSED PyObject * self, + PyObject * args) +{ + int i; + PyObject *py_retval; + PyObject *pyobj_conn; + PyObject *pyobj_f; + + PyObject *pyobj_cb_tuple; + PyObject *pyobj_t_conn; + PyObject *pyobj_t_f; + + virConnectPtr conn; + virConnectPtr tconn; + int ret = 0; + + if (!PyArg_ParseTuple + (args, (char *) "OO:virConnectDomainEventDeregister", &pyobj_conn, + &pyobj_f)) + return (NULL); + +#ifdef DEBUG_ERROR + printf("libvirt_virConnectDomainEventDeregister(%p, %p) called\n", + pyobj_conn, pyobj_f); +#endif + + conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + /* Remove pyobj_f from list. If 0 size, deregister */ + for (i=0; i < PyList_Size(pyobj_domain_event_cbs); i++) { + pyobj_cb_tuple = PyList_GetItem(pyobj_domain_event_cbs, i); + pyobj_t_conn = PyTuple_GetItem(pyobj_cb_tuple,0); + pyobj_t_f = PyTuple_GetItem(pyobj_cb_tuple,1); + tconn = PyvirConnect_Get(pyobj_t_conn); + if( tconn == conn && pyobj_t_f == pyobj_f ) { + /* delete the tuple object from the list*/ + PySequence_DelItem(pyobj_domain_event_cbs, i); + break; + } + } + + /* Remove callback when list reaches 0 */ + if(!PyList_Size(pyobj_domain_event_cbs)) { + ret = virConnectDomainEventDeregister(conn, libvirt_virConnectDomainEventCallback); + Py_DECREF(pyobj_domain_event_cbs); + pyobj_domain_event_cbs = NULL; + } + 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 *libvirt_dict; + PyObject *libvirt_module; + PyObject *python_cb; + PyObject *cb_obj; + PyObject *opaque_obj; + PyObject *cb_args; + PyObject *pyobj_args; + + /* Lookup the python callback */ + libvirt_module = PyImport_ImportModule("libvirt"); + if(!libvirt_module) { + return -1; + } + libvirt_dict = PyModule_GetDict(libvirt_module); + python_cb = PyDict_GetItemString(libvirt_dict, "eventInvokeHandleCallback"); + Py_INCREF(python_cb); + + /* create tuple for cb */ + cb_obj = libvirt_virEventHandleCallbackWrap(cb); + opaque_obj = libvirt_virEventHandleCallbackWrap(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)) + PyEval_CallObject(addHandleObj, pyobj_args); + + Py_DECREF(pyobj_args); + return 0; +} + +static void +libvirt_virEventUpdateHandleFunc(int fd, int event) +{ + 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)) + PyEval_CallObject(updateHandleObj, pyobj_args); + + Py_DECREF(pyobj_args); +} + +static int +libvirt_virEventRemoveHandleFunc(int fd) +{ + PyObject *pyobj_args = PyTuple_New(1); + PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(fd)); + + if(removeHandleObj && PyCallable_Check(removeHandleObj)) + PyEval_CallObject(removeHandleObj, pyobj_args); + + Py_DECREF(pyobj_args); + return 0; +} + +static int +libvirt_virEventAddTimeoutFunc(int timeout, virEventTimeoutCallback cb, + void *opaque) +{ + + PyObject *libvirt_dict; + PyObject *libvirt_module; + PyObject *python_cb; + + PyObject *cb_obj; + PyObject *opaque_obj; + PyObject *cb_args; + PyObject *pyobj_args; + + /* Lookup the python callback */ + libvirt_module = PyImport_ImportModule("libvirt"); + if(!libvirt_module) { + return -1; + } + libvirt_dict = PyModule_GetDict(libvirt_module); + python_cb = PyDict_GetItemString(libvirt_dict, "eventInvokeTimeoutCallback"); + Py_INCREF(python_cb); + + /* create tuple for cb */ + cb_obj = libvirt_virEventTimeoutCallbackWrap(cb); + opaque_obj = libvirt_virEventHandleCallbackWrap(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)) + PyEval_CallObject(addTimeoutObj, pyobj_args); + + Py_DECREF(pyobj_args); + return 0; +} + +static void +libvirt_virEventUpdateTimeoutFunc(int timer, int timeout) +{ + 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)) + PyEval_CallObject(updateTimeoutObj, pyobj_args); + + Py_DECREF(pyobj_args); +} + +static int +libvirt_virEventRemoveTimeoutFunc(int timer) +{ + PyObject *pyobj_args = PyTuple_New(1); + PyTuple_SetItem(pyobj_args, 0, libvirt_intWrap(timer)); + + if(updateTimeoutObj && PyCallable_Check(updateTimeoutObj)) + PyEval_CallObject(updateTimeoutObj, pyobj_args); + + 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 +1928,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 +1962,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..a8b3b57 100644 --- a/python/types.c +++ b/python/types.c @@ -162,3 +162,51 @@ 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) { + printf("%s: WARNING - Wrapping None\n", __FUNCTION__); + Py_INCREF(Py_None); + return (Py_None); + } + ret = + PyCObject_FromVoidPtrAndDesc((void *) node, (char *) "void*", + NULL); + return (ret); +}
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list