mirror of
https://gitlab.com/libvirt/libvirt-python.git
synced 2025-08-10 09:49:26 +03:00
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>
This commit is contained in:
20
generator.py
20
generator.py
@ -570,6 +570,8 @@ lxc_skip_function = (
|
|||||||
)
|
)
|
||||||
qemu_skip_function = (
|
qemu_skip_function = (
|
||||||
#"virDomainQemuAttach",
|
#"virDomainQemuAttach",
|
||||||
|
'virConnectDomainQemuMonitorEventRegister', # overridden in -qemu.py
|
||||||
|
'virConnectDomainQemuMonitorEventDeregister', # overridden in -qemu.py
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generate C code, but skip python impl
|
# Generate C code, but skip python impl
|
||||||
@ -1813,16 +1815,8 @@ def qemuBuildWrappers(module):
|
|||||||
fd.write("#\n")
|
fd.write("#\n")
|
||||||
fd.write("# WARNING WARNING WARNING WARNING\n")
|
fd.write("# WARNING WARNING WARNING WARNING\n")
|
||||||
fd.write("#\n")
|
fd.write("#\n")
|
||||||
if extra is not None:
|
|
||||||
fd.writelines(extra.readlines())
|
|
||||||
fd.write("#\n")
|
|
||||||
fd.write("# WARNING WARNING WARNING WARNING\n")
|
|
||||||
fd.write("#\n")
|
|
||||||
fd.write("# Automatically written part of python bindings for libvirt\n")
|
fd.write("# Automatically written part of python bindings for libvirt\n")
|
||||||
fd.write("#\n")
|
fd.write("#\n")
|
||||||
fd.write("# WARNING WARNING WARNING WARNING\n")
|
|
||||||
if extra is not None:
|
|
||||||
extra.close()
|
|
||||||
|
|
||||||
fd.write("try:\n")
|
fd.write("try:\n")
|
||||||
fd.write(" import libvirtmod_qemu\n")
|
fd.write(" import libvirtmod_qemu\n")
|
||||||
@ -1836,6 +1830,16 @@ def qemuBuildWrappers(module):
|
|||||||
fd.write(" raise lib_e\n\n")
|
fd.write(" raise lib_e\n\n")
|
||||||
|
|
||||||
fd.write("import libvirt\n\n")
|
fd.write("import libvirt\n\n")
|
||||||
|
fd.write("# WARNING WARNING WARNING WARNING\n")
|
||||||
|
fd.write("#\n")
|
||||||
|
if extra is not None:
|
||||||
|
fd.writelines(extra.readlines())
|
||||||
|
fd.write("#\n")
|
||||||
|
if extra is not None:
|
||||||
|
extra.close()
|
||||||
|
|
||||||
|
fd.write("# WARNING WARNING WARNING WARNING\n")
|
||||||
|
fd.write("#\n")
|
||||||
fd.write("#\n# Functions from module %s\n#\n\n" % module)
|
fd.write("#\n# Functions from module %s\n#\n\n" % module)
|
||||||
#
|
#
|
||||||
# Generate functions directly, no classes
|
# Generate functions directly, no classes
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* entry points where an automatically generated stub is
|
* entry points where an automatically generated stub is
|
||||||
* unpractical
|
* unpractical
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2012 Red Hat, Inc.
|
* Copyright (C) 2011-2014 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* Daniel Veillard <veillard@redhat.com>
|
* 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_FAIL (libvirt_intWrap(-1))
|
||||||
#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
|
#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 *
|
* Statistics *
|
||||||
@ -122,6 +192,153 @@ libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject
|
|||||||
}
|
}
|
||||||
#endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */
|
#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 *
|
* The registration stuff *
|
||||||
@ -133,6 +350,10 @@ static PyMethodDef libvirtQemuMethods[] = {
|
|||||||
#if LIBVIR_CHECK_VERSION(0, 10, 0)
|
#if LIBVIR_CHECK_VERSION(0, 10, 0)
|
||||||
{(char *) "virDomainQemuAgentCommand", libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL},
|
{(char *) "virDomainQemuAgentCommand", libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL},
|
||||||
#endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */
|
#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}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
35
libvirt-qemu-override.py
Normal file
35
libvirt-qemu-override.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Manually written part of python bindings for libvirt-qemu
|
||||||
|
|
||||||
|
def _dispatchQemuMonitorEventCallback(conn, dom, event, seconds, micros, details, cbData):
|
||||||
|
"""Dispatches events to python user qemu monitor event callbacks
|
||||||
|
"""
|
||||||
|
cb = cbData["cb"]
|
||||||
|
opaque = cbData["opaque"]
|
||||||
|
|
||||||
|
cb(conn, libvirt.virDomain(conn, _obj=dom), event, seconds, micros, details, opaque)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def qemuMonitorEventDeregister(conn, callbackID):
|
||||||
|
"""Removes a qemu monitor event callback. De-registering for a callback
|
||||||
|
will disable delivery of this event type"""
|
||||||
|
try:
|
||||||
|
ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventDeregister(conn._o, callbackID)
|
||||||
|
if ret == -1: raise libvirt.libvirtError ('virConnectDomainQemuMonitorEventDeregister() failed')
|
||||||
|
del conn.qemuMonitorEventCallbackID[callbackID]
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def qemuMonitorEventRegister(conn, dom, event, cb, opaque, flags=0):
|
||||||
|
"""Adds a qemu monitor event callback. Registering for a monitor
|
||||||
|
callback will enable delivery of the events"""
|
||||||
|
if not hasattr(conn, 'qemuMonitorEventCallbackID'):
|
||||||
|
conn.qemuMonitorEventCallbackID = {}
|
||||||
|
cbData = { "cb": cb, "conn": conn, "opaque": opaque }
|
||||||
|
if dom is None:
|
||||||
|
ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventRegister(conn._o, None, event, cbData, flags)
|
||||||
|
else:
|
||||||
|
ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventRegister(conn._o, dom._o, event, cbData, flags)
|
||||||
|
if ret == -1:
|
||||||
|
raise libvirt.libvirtError ('virConnectDomainQemuMonitorEventRegister() failed')
|
||||||
|
conn.qemuMonitorEventCallbackID[ret] = opaque
|
||||||
|
return ret
|
Reference in New Issue
Block a user