summaryrefslogtreecommitdiff
path: root/libvirt-qemu-override.c
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2014-02-04 16:14:16 -0700
committerEric Blake <eblake@redhat.com>2014-03-25 09:12:22 -0600
commite3da8f178ec007c79bb9305e61bbea222f71b232 (patch)
tree4862420d968a8caa20a9adfb6f0928a24ae3fabe /libvirt-qemu-override.c
parent493ca0883dc3caf6a9a6aff1e7ead7a5a1365973 (diff)
downloadlibvirt-python-e3da8f178ec007c79bb9305e61bbea222f71b232.tar.gz
qemu: support arbitrary monitor events
Wrap the new virConnectDomainQemuMonitorEventRegister function added in libvirt 1.2.3. This patch copies heavily from network events (commit 6ea5be0) and from event loop callbacks in libvirt-override.c, since in the libvirt_qemu module, we must expose top-level functions rather than class members. * generator.py (qemu_skip_function): Don't generate event code. (qemuBuildWrappers): Delay manual portion until after imports. * libvirt-qemu-override.py (qemuMonitorEventRegister) (qemuMonitorEventDeregister): New file. * libvirt-qemu-override.c (libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc) (libvirt_qemu_virConnectDomainQemuMonitorEventCallback) (libvirt_qemu_virConnectDomainQemuMonitorEventRegister) (libvirt_qemu_virConnectDomainQemuMonitorEventDeregister) (libvirt_qemu_lookupPythonFunc, getLibvirtQemuDictObject) (getLibvirtQemuModuleObject): New functions. Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'libvirt-qemu-override.c')
-rw-r--r--libvirt-qemu-override.c223
1 files changed, 222 insertions, 1 deletions
diff --git a/libvirt-qemu-override.c b/libvirt-qemu-override.c
index 480a7d3..05ead30 100644
--- a/libvirt-qemu-override.c
+++ b/libvirt-qemu-override.c
@@ -4,7 +4,7 @@
* entry points where an automatically generated stub is
* unpractical
*
- * Copyright (C) 2011-2012 Red Hat, Inc.
+ * Copyright (C) 2011-2014 Red Hat, Inc.
*
* Daniel Veillard <veillard@redhat.com>
*/
@@ -54,6 +54,76 @@ extern void initcygvirtmod_qemu(void);
#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
+/*******************************************
+ * Helper functions to avoid importing modules
+ * for every callback
+ *******************************************/
+#if LIBVIR_CHECK_VERSION(1, 2, 3)
+static PyObject *libvirt_qemu_module;
+static PyObject *libvirt_qemu_dict;
+
+static PyObject *
+getLibvirtQemuModuleObject(void)
+{
+ if (libvirt_qemu_module)
+ return libvirt_qemu_module;
+
+ // PyImport_ImportModule returns a new reference
+ /* Bogus (char *) cast for RHEL-5 python API brokenness */
+ libvirt_qemu_module = PyImport_ImportModule((char *)"libvirt_qemu");
+ if (!libvirt_qemu_module) {
+ DEBUG("%s Error importing libvirt_qemu module\n", __FUNCTION__);
+ PyErr_Print();
+ return NULL;
+ }
+
+ return libvirt_qemu_module;
+}
+
+static PyObject *
+getLibvirtQemuDictObject(void)
+{
+ if (libvirt_qemu_dict)
+ return libvirt_qemu_dict;
+
+ // PyModule_GetDict returns a borrowed reference
+ libvirt_qemu_dict = PyModule_GetDict(getLibvirtQemuModuleObject());
+ if (!libvirt_qemu_dict) {
+ DEBUG("%s Error importing libvirt_qemu dictionary\n", __FUNCTION__);
+ PyErr_Print();
+ return NULL;
+ }
+
+ Py_INCREF(libvirt_qemu_dict);
+ return libvirt_qemu_dict;
+}
+
+
+static PyObject *
+libvirt_qemu_lookupPythonFunc(const char *funcname)
+{
+ PyObject *python_cb;
+
+ /* Lookup the python callback */
+ python_cb = PyDict_GetItemString(getLibvirtQemuDictObject(), funcname);
+
+ if (!python_cb) {
+ DEBUG("%s: Error finding %s\n", __FUNCTION__, funcname);
+ PyErr_Print();
+ PyErr_Clear();
+ return NULL;
+ }
+
+ if (!PyCallable_Check(python_cb)) {
+ DEBUG("%s: %s is not callable\n", __FUNCTION__, funcname);
+ return NULL;
+ }
+
+ return python_cb;
+}
+#endif /* LIBVIR_CHECK_VERSION(1, 2, 3) */
+
+
/************************************************************************
* *
* Statistics *
@@ -122,6 +192,153 @@ libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject
}
#endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */
+
+#if LIBVIR_CHECK_VERSION(1, 2, 3)
+static void
+libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc(void *opaque)
+{
+ PyObject *pyobj_conn = (PyObject*)opaque;
+ LIBVIRT_ENSURE_THREAD_STATE;
+ Py_DECREF(pyobj_conn);
+ LIBVIRT_RELEASE_THREAD_STATE;
+}
+
+static void
+libvirt_qemu_virConnectDomainQemuMonitorEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *event,
+ long long seconds,
+ unsigned int micros,
+ const char *details,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret = NULL;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ PyObject *pyobj_cb;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ pyobj_cb = libvirt_qemu_lookupPythonFunc("_dispatchQemuMonitorEventCallback");
+ if (!pyobj_cb)
+ goto cleanup;
+
+ dictKey = libvirt_constcharPtrWrap("conn");
+ if (!dictKey)
+ goto cleanup;
+ pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
+ Py_DECREF(dictKey);
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) {
+ virDomainFree(dom);
+ goto cleanup;
+ }
+ Py_INCREF(pyobj_cbData);
+
+ /* Call the Callback Dispatcher */
+ pyobj_ret = PyObject_CallFunction(pyobj_cb,
+ (char *)"OOsLIsO",
+ pyobj_conn, pyobj_dom, event, seconds,
+ micros, details, pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+cleanup:
+ if (!pyobj_ret) {
+ DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+}
+
+
+static PyObject *
+libvirt_qemu_virConnectDomainQemuMonitorEventRegister(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval;
+ PyObject *pyobj_conn;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_cbData;
+ const char *event;
+ virConnectPtr conn;
+ int ret = 0;
+ virConnectDomainQemuMonitorEventCallback cb = NULL;
+ virDomainPtr dom;
+ unsigned int flags;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "OOzOI",
+ &pyobj_conn, &pyobj_dom, &event, &pyobj_cbData, &flags)) {
+ DEBUG("%s failed parsing tuple\n", __FUNCTION__);
+ return VIR_PY_INT_FAIL;
+ }
+
+ DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventRegister(%p %p %s %p %x) called\n",
+ pyobj_conn, pyobj_dom, NULLSTR(event), pyobj_cbData, flags);
+ conn = PyvirConnect_Get(pyobj_conn);
+ if (pyobj_dom == Py_None)
+ dom = NULL;
+ else
+ dom = PyvirDomain_Get(pyobj_dom);
+
+ cb = libvirt_qemu_virConnectDomainQemuMonitorEventCallback;
+
+ Py_INCREF(pyobj_cbData);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ ret = virConnectDomainQemuMonitorEventRegister(conn, dom, event,
+ cb, pyobj_cbData,
+ libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc,
+ flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (ret < 0)
+ Py_DECREF(pyobj_cbData);
+
+ py_retval = libvirt_intWrap(ret);
+ return py_retval;
+}
+
+
+static PyObject *
+libvirt_qemu_virConnectDomainQemuMonitorEventDeregister(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval;
+ PyObject *pyobj_conn;
+ int callbackID;
+ virConnectPtr conn;
+ int ret = 0;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "Oi:virConnectDomainQemuMonitorEventDeregister",
+ &pyobj_conn, &callbackID))
+ return NULL;
+
+ DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventDeregister(%p) called\n",
+ pyobj_conn);
+
+ conn = PyvirConnect_Get(pyobj_conn);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+
+ ret = virConnectDomainQemuMonitorEventDeregister(conn, callbackID);
+
+ LIBVIRT_END_ALLOW_THREADS;
+ py_retval = libvirt_intWrap(ret);
+ return py_retval;
+}
+#endif /* LIBVIR_CHECK_VERSION(1, 2, 3) */
+
/************************************************************************
* *
* The registration stuff *
@@ -133,6 +350,10 @@ static PyMethodDef libvirtQemuMethods[] = {
#if LIBVIR_CHECK_VERSION(0, 10, 0)
{(char *) "virDomainQemuAgentCommand", libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL},
#endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */
+#if LIBVIR_CHECK_VERSION(1, 2, 3)
+ {(char *) "virConnectDomainQemuMonitorEventRegister", libvirt_qemu_virConnectDomainQemuMonitorEventRegister, METH_VARARGS, NULL},
+ {(char *) "virConnectDomainQemuMonitorEventDeregister", libvirt_qemu_virConnectDomainQemuMonitorEventDeregister, METH_VARARGS, NULL},
+#endif /* LIBVIR_CHECK_VERSION(1, 2, 3) */
{NULL, NULL, 0, NULL}
};