Attached are the python bindings for domain events I have moved much of the complicated code from my prior submission out of C and into python. This required a slight change to the generator. The new convention that we came up with is to append <classname>.py to the class as it is being generated, iff that file exists. examples/domain-events/events-python/event-test.py | 186 +++++++++ python/generator.py | 16 python/libvir.c | 410 +++++++++++++++++++++ python/libvir.py | 20 + python/libvirt_wrap.h | 27 + python/types.c | 47 ++ python/virConnect.py | 46 ++ 7 files changed, 747 insertions(+), 5 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..ac53196 --- /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 = 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]" + 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/generator.py b/python/generator.py index ca83eaf..6233c83 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,13 @@ def buildWrappers(): classes.write(" return ret\n"); classes.write("\n"); + # Append "<classname>.py" to class def, iff it exists + try: + extra = open(classname + ".py", "r") + classes.writelines(extra.readlines()) + extra.close() + except: + pass # # Generate enum constants diff --git a/python/libvir.c b/python/libvir.c index 9cc0c81..9b0d66b 100644 --- a/python/libvir.c +++ b/python/libvir.c @@ -1467,6 +1467,411 @@ libvirt_virStoragePoolLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *ar } +/******************************************* + * 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 *libvirt_module; + PyObject *libvirt_dict; + PyObject *pyobj_dom_class; + + PyObject *pyobj_dom_args; + PyObject *pyobj_dom_kw; + PyObject *pyobj_dom_inst; + + libvirt_module = PyImport_ImportModule("libvirt"); + if(!libvirt_module) { + printf("%s Error importing libvirt module\n", __FUNCTION__); + PyErr_Print(); + return -1; + } + libvirt_dict = PyModule_GetDict(libvirt_module); + if(!libvirt_dict) { + printf("%s Error importing libvirt dictionary\n", __FUNCTION__); + PyErr_Print(); + return -1; + } + pyobj_dom_class = PyDict_GetItemString(libvirt_dict, "virDomain"); + if(!pyobj_dom_class) { + printf("%s Error importing virDomain class\n", __FUNCTION__); + PyErr_Print(); + return -1; + } + /* Create a python instance of this virDomainPtr */ + pyobj_dom_args = PyTuple_New(1); + PyTuple_SetItem(pyobj_dom_args, 0, pyobj_conn_inst); + Py_INCREF(pyobj_conn_inst); + pyobj_dom_kw = PyDict_New(); + PyDict_SetItemString(pyobj_dom_kw, "_obj", pyobj_dom); + pyobj_dom_inst = PyInstance_New(pyobj_dom_class, pyobj_dom_args, + pyobj_dom_kw); + if(!pyobj_conn_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); + Py_DECREF(pyobj_conn_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 *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) { + printf("%s Error importing libvirt module\n", __FUNCTION__); + PyErr_Print(); + return -1; + } + libvirt_dict = PyModule_GetDict(libvirt_module); + if(!libvirt_dict) { + printf("%s Error importing libvirt dict\n", __FUNCTION__); + PyErr_Print(); + return -1; + } + python_cb = PyDict_GetItemString(libvirt_dict, "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 *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) { + printf("%s Error importing libvirt module\n", __FUNCTION__); + PyErr_Print(); + return -1; + } + libvirt_dict = PyModule_GetDict(libvirt_module); + if(!libvirt_dict) { + printf("%s Error importing libvirt dict\n", __FUNCTION__); + PyErr_Print(); + return -1; + } + python_cb = PyDict_GetItemString(libvirt_dict, "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 +1884,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 +1918,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..1c1db89 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); +} diff --git a/python/virConnect.py b/python/virConnect.py new file mode 100644 index 0000000..23ae3e8 --- /dev/null +++ b/python/virConnect.py @@ -0,0 +1,46 @@ + # + # virConnect functions from virConnect.py (hand coded) + # + def __del__(self): + try: + for cb,opaque in self.domainEventCallbacks.items(): + del self.domainEventCallbacks[cb] + self.domainEventCallbacks = None + libvirtmod.virConnectDomainEventDeregister(self._o, self) + except AttributeError: + pass + + if self._o != None: + libvirtmod.virConnectClose(self._o) + self._o = None + + def domainEventDeregister(self, cb): + """Removes a Domain Event Callback. De-registering for a + domain callback will disable delivery of this event type """ + try: + del self.domainEventCallbacks[cb] + if len(self.domainEventCallbacks) == 0: + ret = libvirtmod.virConnectDomainEventDeregister(self._o, self) + if ret == -1: raise libvirtError ('virConnectDomainEventDeregister() failed', conn=self) + except AttributeError: + pass + + def domainEventRegister(self, cb, opaque): + """Adds a Domain Event Callback. Registering for a domain + callback will enable delivery of the events """ + try: + self.domainEventCallbacks[cb] = opaque + except AttributeError: + self.domainEventCallbacks = {cb:opaque} + ret = libvirtmod.virConnectDomainEventRegister(self._o, self) + if ret == -1: raise libvirtError ('virConnectDomainEventRegister() failed', conn=self) + + def dispatchDomainEventCallbacks(self, dom, event): + """Dispatches events to python user domain event callbacks + """ + try: + for cb,opaque in self.domainEventCallbacks.items(): + cb(self,dom,event,opaque) + return 0 + except AttributeError: + pass
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list