From: ShaoHe Feng <shaohef@xxxxxxxxxxxxxxxxxx> Signed-off-by: ShaoHe Feng <shaohef@xxxxxxxxxxxxxxxxxx> --- python/generator.py | 28 +++++---- python/libvirt-qemu-override.c | 140 +++++++++++++++++++++++++++++++++++++++ python/libvirt-qemu-override.py | 55 +++++++++++++++ python/libvirt_qemu.py | 105 +++++++++++++++++++++++++++++ 4 files changed, 316 insertions(+), 12 deletions(-) create mode 100644 python/libvirt-qemu-override.py create mode 100644 python/libvirt_qemu.py diff --git a/python/generator.py b/python/generator.py index 1657f4f..9a4cf83 100755 --- a/python/generator.py +++ b/python/generator.py @@ -234,6 +234,7 @@ skipped_types = { # 'int *': "usually a return type", 'virConnectDomainEventCallback': "No function types in python", 'virConnectDomainEventGenericCallback': "No function types in python", + 'virConnectDomainQemuEventCallback': "No function types in python", 'virConnectDomainEventRTCChangeCallback': "No function types in python", 'virConnectDomainEventWatchdogCallback': "No function types in python", 'virConnectDomainEventIOErrorCallback': "No function types in python", @@ -477,6 +478,9 @@ skip_function = ( qemu_skip_function = ( #"virDomainQemuAttach", + 'virConnectDomainQemuEventCallback', # overridden in libvirt_qemu_override.py + 'virConnectDomainQemuEventRegister', # overridden in libvirt_qemu_override.py + 'virConnectDomainQemuEventDeregister', # overridden in libvirt_qemu_override.py ) # Generate C code, but skip python impl @@ -1657,17 +1661,18 @@ def qemuBuildWrappers(module): if extra != None: extra.close() - fd.write("try:\n") - fd.write(" import libvirtmod_qemu\n") - fd.write("except ImportError, lib_e:\n") - fd.write(" try:\n") - fd.write(" import cygvirtmod_qemu as libvirtmod_qemu\n") - fd.write(" except ImportError, cyg_e:\n") - fd.write(" if str(cyg_e).count(\"No module named\"):\n") - fd.write(" raise lib_e\n\n") - - fd.write("import libvirt\n\n"); - fd.write("#\n# Functions from module %s\n#\n\n" % module) + if extra == None: + fd.write("try:\n") + fd.write(" import libvirtmod_qemu\n") + fd.write("except ImportError, lib_e:\n") + fd.write(" try:\n") + fd.write(" import cygvirtmod_qemu as libvirtmod_qemu\n") + fd.write(" except ImportError, cyg_e:\n") + fd.write(" if str(cyg_e).count(\"No module named\"):\n") + fd.write(" raise lib_e\n\n") + + fd.write("import libvirt\n\n"); + fd.write("#\n# Functions from module %s\n#\n\n" % module) # # Generate functions directly, no classes # @@ -1727,7 +1732,6 @@ def qemuBuildWrappers(module): items.sort(lambda i1,i2: cmp(long(i1[1]),long(i2[1]))) for name,value in items: fd.write("%s = %s\n" % (name,value)) - fd.write("\n"); fd.close() diff --git a/python/libvirt-qemu-override.c b/python/libvirt-qemu-override.c index 485c809..f5a8c09 100644 --- a/python/libvirt-qemu-override.c +++ b/python/libvirt-qemu-override.c @@ -18,6 +18,7 @@ #include <Python.h> #include "libvirt/libvirt-qemu.h" +#include "libvirt/libvirt.h" #include "libvirt/virterror.h" #include "typewrappers.h" #include "libvirt-qemu.h" @@ -96,6 +97,143 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, return(py_retval); } +static void +libvirt_qemu_virConnectDomainEventFreeFunc(void *opaque) +{ + PyObject *pyobj_conn = (PyObject*)opaque; + LIBVIRT_ENSURE_THREAD_STATE; + Py_DECREF(pyobj_conn); + LIBVIRT_RELEASE_THREAD_STATE; +} + +static int +libvirt_qemu_virConnectDomainEventUnknownCallback(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *eventName, + const char *eventArgs, + 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*)"_dispatchDomainEventUnknownCallback", + (char*)"OssO", + pyobj_dom, eventName, eventArgs, 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_qemu_virConnectDomainQemuEventRegister(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 */ + char *eventName; + virConnectPtr conn; + int ret = 0; + + virConnectDomainQemuEventCallback cb = NULL; + virDomainPtr dom; + + if (!PyArg_ParseTuple + (args, (char *) "OOsO:virConnectDomainQemuEventRegister", + &pyobj_conn, &pyobj_dom, &eventName, &pyobj_cbData)) { + DEBUG("%s failed parsing tuple\n", __FUNCTION__); + return VIR_PY_INT_FAIL; + } + + if (eventName == NULL) + return VIR_PY_INT_FAIL; + + DEBUG("libvirt_qemu_virConnectDomainQemuEventRegister(%p %p %s %p) called\n", + pyobj_conn, pyobj_dom, eventName, pyobj_cbData); + conn = PyvirConnect_Get(pyobj_conn); + if (pyobj_dom == Py_None) + dom = NULL; + else + dom = PyvirDomain_Get(pyobj_dom); + + cb = (virConnectDomainQemuEventCallback)(libvirt_qemu_virConnectDomainEventUnknownCallback); + if (!cb) { + return VIR_PY_INT_FAIL; + } + + Py_INCREF(pyobj_cbData); + + LIBVIRT_BEGIN_ALLOW_THREADS; + ret = virConnectDomainQemuEventRegister(conn, dom, eventName, + cb, pyobj_cbData, + libvirt_qemu_virConnectDomainEventFreeFunc); + LIBVIRT_END_ALLOW_THREADS; + if (ret < 0) { + Py_DECREF(pyobj_cbData); + } + py_retval = libvirt_intWrap(ret); + return (py_retval); +} + +static PyObject * +libvirt_qemu_virConnectDomainQemuEventDeregister(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:virConnectDomainQemuEventDeregister", + &pyobj_conn, &callbackID)) + return (NULL); + + DEBUG("libvirt_qemu_virConnectDomainQemuEventDeregister(%p) called\n", pyobj_conn); + + conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + + LIBVIRT_BEGIN_ALLOW_THREADS; + + ret = virConnectDomainQemuEventDeregister(conn, callbackID); + + LIBVIRT_END_ALLOW_THREADS; + py_retval = libvirt_intWrap(ret); + return (py_retval); +} + /************************************************************************ * * * The registration stuff * @@ -104,6 +242,8 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, static PyMethodDef libvirtQemuMethods[] = { #include "libvirt-qemu-export.c" {(char *) "virDomainQemuMonitorCommand", libvirt_qemu_virDomainQemuMonitorCommand, METH_VARARGS, NULL}, + {(char *) "virConnectDomainQemuEventRegister", libvirt_qemu_virConnectDomainQemuEventRegister, METH_VARARGS, NULL}, + {(char *) "virConnectDomainQemuEventDeregister", libvirt_qemu_virConnectDomainQemuEventDeregister, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; diff --git a/python/libvirt-qemu-override.py b/python/libvirt-qemu-override.py new file mode 100644 index 0000000..9838941 --- /dev/null +++ b/python/libvirt-qemu-override.py @@ -0,0 +1,55 @@ +# +# Manually written part of python bindings for libvirt_qemu +# + +# On cygwin, the DLL is called cygvirtmod.dll +try: + import libvirtmod_qemu +except ImportError, lib_e: + try: + import cygvirtmod_qemu as libvirtmod_qemu + except ImportError, cyg_e: + if str(cyg_e).count("No module named"): + raise lib_e + +import libvirt +import types + +def _dispatchDomainEventUnknownCallback(dom, eventName, eventArgs, cbData): + """Dispatches events to python user unknown event callbacks + """ + try: + cb = cbData["cb"] + opaque = cbData["opaque"] + conn = cbData["conn"] + cb(conn, libvirt.virDomain(conn, _obj=dom), eventName, eventArgs, opaque) + return 0 + except AttributeError: + pass + +def domainQemuEventDeregister(conn, callbackID): + """Removes a Domain Event Callback. De-registering for a + domain callback will disable delivery of this event type """ + try: + ret = libvirtmod_qemu.virConnectDomainQemuEventDeregister(conn._o, callbackID) + if ret == -1: raise libvirt.libvirtError ('virConnectDomainQemuEventDeregister() failed', conn) + del conn.domainEventCallbackID[callbackID] + except AttributeError: + pass + +def domainQemuEventRegister(conn, dom, eventName, cb, opaque): + """Adds a Domain Event Callback. Registering for a domain + callback will enable delivery of the events """ + if not hasattr(conn, 'domainEventCallbackID'): + conn.domainEventCallbackID = {} + if not hasattr(conn, '_dispatchDomainEventUnknownCallback'): + conn._dispatchDomainEventUnknownCallback = _dispatchDomainEventUnknownCallback + cbData = { "cb": cb, "conn": conn, "opaque": opaque } + if dom is None: + ret = libvirtmod_qemu.virConnectDomainQemuEventRegister(conn._o, None, eventName, cbData) + else: + ret = libvirtmod_qemu.virConnectDomainQemuEventRegister(conn._o, dom._o, eventName, cbData) + if ret == -1: + raise libvirt.libvirtError ('virConnectDomainQemuEventRegister() failed', conn) + conn.domainEventCallbackID[ret] = opaque + return ret diff --git a/python/libvirt_qemu.py b/python/libvirt_qemu.py new file mode 100644 index 0000000..9a2a8fd --- /dev/null +++ b/python/libvirt_qemu.py @@ -0,0 +1,105 @@ +#! /usr/bin/python -i +# +# WARNING WARNING WARNING WARNING +# +# This file is automatically written by generator.py. Any changes +# made here will be lost. +# +# To change the manually written methods edit libvirt-qemu-override.py +# To change the automatically written methods edit generator.py +# +# WARNING WARNING WARNING WARNING +# +# +# Manually written part of python bindings for libvirt_qemu +# + +# On cygwin, the DLL is called cygvirtmod.dll +try: + import libvirtmod_qemu +except ImportError, lib_e: + try: + import cygvirtmod_qemu as libvirtmod_qemu + except ImportError, cyg_e: + if str(cyg_e).count("No module named"): + raise lib_e + +import libvirt +import types + +def _dispatchDomainEventUnknownCallback(dom, eventName, eventArgs, cbData): + """Dispatches events to python user unknown event callbacks + """ + try: + cb = cbData["cb"] + opaque = cbData["opaque"] + conn = cbData["conn"] + cb(conn, libvirt.virDomain(conn, _obj=dom), eventName, eventArgs, opaque) + return 0 + except AttributeError: + pass + +def domainQemuEventDeregister(conn, callbackID): + """Removes a Domain Event Callback. De-registering for a + domain callback will disable delivery of this event type """ + try: + ret = libvirtmod_qemu.virConnectDomainQemuEventDeregister(conn._o, callbackID) + if ret == -1: raise libvirt.libvirtError ('virConnectDomainQemuEventDeregister() failed', conn) + del conn.domainEventCallbackID[callbackID] + except AttributeError: + pass + +def domainQemuEventRegister(conn, dom, eventName, cb, opaque): + """Adds a Domain Event Callback. Registering for a domain + callback will enable delivery of the events """ + if not hasattr(conn, 'domainEventCallbackID'): + conn.domainEventCallbackID = {} + if not hasattr(conn, '_dispatchDomainEventUnknownCallback'): + conn._dispatchDomainEventUnknownCallback = _dispatchDomainEventUnknownCallback + cbData = { "cb": cb, "conn": conn, "opaque": opaque } + if dom is None: + ret = libvirtmod_qemu.virConnectDomainQemuEventRegister(conn._o, None, eventName, cbData) + else: + ret = libvirtmod_qemu.virConnectDomainQemuEventRegister(conn._o, dom._o, eventName, cbData) + if ret == -1: + raise libvirt.libvirtError ('virConnectDomainQemuEventRegister() failed', conn) + conn.domainEventCallbackID[ret] = opaque + return ret +# +# WARNING WARNING WARNING WARNING +# +# Automatically written part of python bindings for libvirt +# +# WARNING WARNING WARNING WARNING +def qemuMonitorCommand(domain, cmd, flags): + """Send an arbitrary monitor command through qemu monitor of domain """ + ret = libvirtmod_qemu.virDomainQemuMonitorCommand(domain._o, cmd, flags) + if ret is None: raise libvirt.libvirtError('virDomainQemuMonitorCommand() failed') + return ret + +def qemuAttach(conn, pid, flags): + """This API is QEMU specific, so it will only work with hypervisor + connections to the QEMU driver. + + This API will attach to an externally launched QEMU process + identified by @pid. There are several requirements to successfully + attach to an external QEMU process: + + - It must have been started with a monitor socket using the UNIX + domain socket protocol. + - No device hotplug/unplug, or other configuration changes can + have been made via the monitor since it started. + - The '-name' and '-uuid' arguments should have been set (not + mandatory, but strongly recommended) + + If successful, then the guest will appear in the list of running + domains for this connection, and other APIs should operate + normally (provided the above requirements were honored). """ + ret = libvirtmod_qemu.virDomainQemuAttach(conn._o, pid, flags) + if ret is None: raise libvirt.libvirtError('virDomainQemuAttach() failed') + __tmp = virDomain(conn,_obj=ret) + return __tmp + +# virDomainQemuMonitorCommandFlags +VIR_DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT = 0 +VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP = 1 -- 1.7.5.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list