From 7b716fce8ecaaef408f0e5ddc8f8349f86300af7 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Fri, 31 Oct 2008 10:13:45 +0000 Subject: [PATCH] * python/Makefile.am python/generator.py python/libvir.c python/libvir.py python/libvirt_wrap.h python/types.c: adds support for events from the python bindings, also improves the generator allowing to embbed per function definition files, patch by Ben Guthro * examples/domain-events/events-python/event-test.py: also adds a programming example Daniel --- ChangeLog | 10 + .../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 ++ 8 files changed, 749 insertions(+), 6 deletions(-) create mode 100644 examples/domain-events/events-python/event-test.py diff --git a/ChangeLog b/ChangeLog index f23c5c155f..f2075507a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Fri Oct 31 11:11:30 CET 2008 Daniel Veillard + + * python/Makefile.am python/generator.py python/libvir.c + python/libvir.py python/libvirt_wrap.h python/types.c: + adds support for events from the python bindings, also + improves the generator allowing to embbed per function + definition files, patch by Ben Guthro + * examples/domain-events/events-python/event-test.py: also + adds a programming example + Thu Oct 30 13:39:00 EST 2008 Cole Robinson * src/test.c: Add a test storage driver. diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py new file mode 100644 index 0000000000..7082db00a4 --- /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 cd9b6af466..90b87bb907 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 > $@-t mv $@-t $@ diff --git a/python/generator.py b/python/generator.py index ca83eafe2b..7b153b9cd7 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 ".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 9cc0c8166b..a2e4c79542 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 cf5e776987..86bf422df6 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 f8ecb76c55..b46deafae2 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 8e08d25eac..1c1db89a04 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); +} -- GitLab