Skip to content

Commit

Permalink
Python binding for node poll lifecycle events API
Browse files Browse the repository at this point in the history
  • Loading branch information
JGulic authored and crobinso committed Aug 2, 2016
1 parent 94a4f35 commit 58a9869
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 0 deletions.
2 changes: 2 additions & 0 deletions generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,8 @@ def qemu_enum(type, name, value):
'virConnectNetworkEventDeregisterAny', # overridden in virConnect.py
'virConnectStoragePoolEventRegisterAny', # overridden in virConnect.py
'virConnectStoragePoolEventDeregisterAny', # overridden in virConnect.py
'virConnectNodeDeviceEventRegisterAny', # overridden in virConnect.py
'virConnectNodeDeviceEventDeregisterAny', # overridden in virConnect.py
'virSaveLastError', # We have our own python error wrapper
'virFreeError', # Only needed if we use virSaveLastError
'virConnectListAllDomains', # overridden in virConnect.py
Expand Down
35 changes: 35 additions & 0 deletions libvirt-override-virConnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,41 @@ def storagePoolEventRegisterAny(self, pool, eventID, cb, opaque):
self.storagePoolEventCallbackID[ret] = opaque
return ret

def _dispatchNodeDeviceEventLifecycleCallback(self, dev, event, detail, cbData):
"""Dispatches events to python user node device
lifecycle event callbacks
"""
cb = cbData["cb"]
opaque = cbData["opaque"]

cb(self, virNodeDevice(self, _obj=dev), event, detail, opaque)
return 0

def nodeDeviceEventDeregisterAny(self, callbackID):
"""Removes a Node Device Event Callback. De-registering for a
node device callback will disable delivery of this event type"""
try:
ret = libvirtmod.virConnectNodeDeviceEventDeregisterAny(self._o, callbackID)
if ret == -1: raise libvirtError ('virConnectNodeDeviceEventDeregisterAny() failed', conn=self)
del self.nodeDeviceEventCallbackID[callbackID]
except AttributeError:
pass

def nodeDeviceEventRegisterAny(self, dev, eventID, cb, opaque):
"""Adds a Node Device Event Callback. Registering for a node device
callback will enable delivery of the events"""
if not hasattr(self, 'nodeDeviceEventCallbackID'):
self.nodeDeviceEventCallbackID = {}
cbData = { "cb": cb, "conn": self, "opaque": opaque }
if dev is None:
ret = libvirtmod.virConnectNodeDeviceEventRegisterAny(self._o, None, eventID, cbData)
else:
ret = libvirtmod.virConnectNodeDeviceEventRegisterAny(self._o, dev._o, eventID, cbData)
if ret == -1:
raise libvirtError ('virConnectNodeDeviceEventRegisterAny() failed', conn=self)
self.nodeDeviceEventCallbackID[ret] = opaque
return ret

def listAllDomains(self, flags=0):
"""List all domains and returns a list of domain objects"""
ret = libvirtmod.virConnectListAllDomains(self._o, flags)
Expand Down
153 changes: 153 additions & 0 deletions libvirt-override.c
Original file line number Diff line number Diff line change
Expand Up @@ -9003,6 +9003,155 @@ libvirt_virDomainGetGuestVcpus(PyObject *self ATTRIBUTE_UNUSED,
}
#endif /* LIBVIR_CHECK_VERSION(2, 0, 0)*/

#if LIBVIR_CHECK_VERSION(2, 2, 0)
static void
libvirt_virConnectNodeDeviceEventFreeFunc(void *opaque)
{
PyObject *pyobj_conn = (PyObject*)opaque;
LIBVIRT_ENSURE_THREAD_STATE;
Py_DECREF(pyobj_conn);
LIBVIRT_RELEASE_THREAD_STATE;
}

static int
libvirt_virConnectNodeDeviceEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
virNodeDevicePtr dev,
int event,
int detail,
void *opaque)
{
PyObject *pyobj_cbData = (PyObject*)opaque;
PyObject *pyobj_dev;
PyObject *pyobj_ret = NULL;
PyObject *pyobj_conn;
PyObject *dictKey;
int ret = -1;

LIBVIRT_ENSURE_THREAD_STATE;

if (!(dictKey = libvirt_constcharPtrWrap("conn")))
goto cleanup;
pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
Py_DECREF(dictKey);

/* Create a python instance of this virNodeDevicePtr */
virNodeDeviceRef(dev);
if (!(pyobj_dev = libvirt_virNodeDevicePtrWrap(dev))) {
virNodeDeviceFree(dev);
goto cleanup;
}
Py_INCREF(pyobj_cbData);

/* Call the Callback Dispatcher */
pyobj_ret = PyObject_CallMethod(pyobj_conn,
(char*)"_dispatchNodeDeviceEventLifecycleCallback",
(char*)"OiiO",
pyobj_dev,
event,
detail,
pyobj_cbData);

Py_DECREF(pyobj_cbData);
Py_DECREF(pyobj_dev);

cleanup:
if (!pyobj_ret) {
DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
PyErr_Print();
} else {
Py_DECREF(pyobj_ret);
ret = 0;
}

LIBVIRT_RELEASE_THREAD_STATE;
return ret;
}

static PyObject *
libvirt_virConnectNodeDeviceEventRegisterAny(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args)
{
PyObject *pyobj_conn; /* virConnectPtr */
PyObject *pyobj_dev;
PyObject *pyobj_cbData; /* hash of callback data */
int eventID;
virConnectPtr conn;
int ret = 0;
virConnectNodeDeviceEventGenericCallback cb = NULL;
virNodeDevicePtr dev;

if (!PyArg_ParseTuple(args,
(char *) "OOiO:virConnectNodeDeviceEventRegisterAny",
&pyobj_conn, &pyobj_dev, &eventID, &pyobj_cbData))
return NULL;

DEBUG("libvirt_virConnectNodeDeviceEventRegister(%p %p %d %p) called\n",
pyobj_conn, pyobj_dev, eventID, pyobj_cbData);
conn = PyvirConnect_Get(pyobj_conn);
if (pyobj_dev == Py_None)
dev = NULL;
else
dev = PyvirNodeDevice_Get(pyobj_dev);

switch ((virNodeDeviceEventID) eventID) {
case VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE:
cb = VIR_NODE_DEVICE_EVENT_CALLBACK(libvirt_virConnectNodeDeviceEventLifecycleCallback);
break;

case VIR_NODE_DEVICE_EVENT_ID_LAST:
break;
}

if (!cb) {
return VIR_PY_INT_FAIL;
}

Py_INCREF(pyobj_cbData);

LIBVIRT_BEGIN_ALLOW_THREADS;
ret = virConnectNodeDeviceEventRegisterAny(conn,
dev,
eventID,
cb,
pyobj_cbData,
libvirt_virConnectNodeDeviceEventFreeFunc);
LIBVIRT_END_ALLOW_THREADS;

if (ret < 0) {
Py_DECREF(pyobj_cbData);
}

return libvirt_intWrap(ret);
}

static PyObject *
libvirt_virConnectNodeDeviceEventDeregisterAny(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args)
{
PyObject *pyobj_conn;
int callbackID;
virConnectPtr conn;
int ret = 0;

if (!PyArg_ParseTuple(args, (char *) "Oi:virConnectNodeDeviceEventDeregister",
&pyobj_conn, &callbackID))
return NULL;

DEBUG("libvirt_virConnectNodeDeviceEventDeregister(%p) called\n",
pyobj_conn);

conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);

LIBVIRT_BEGIN_ALLOW_THREADS;

ret = virConnectNodeDeviceEventDeregisterAny(conn, callbackID);

LIBVIRT_END_ALLOW_THREADS;

return libvirt_intWrap(ret);
}

#endif /* LIBVIR_CHECK_VERSION(2, 2, 0)*/

/************************************************************************
* *
Expand Down Expand Up @@ -9216,6 +9365,10 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virConnectStoragePoolEventDeregisterAny", libvirt_virConnectStoragePoolEventDeregisterAny, METH_VARARGS, NULL},
{(char *) "virDomainGetGuestVcpus", libvirt_virDomainGetGuestVcpus, METH_VARARGS, NULL},
#endif /* LIBVIR_CHECK_VERSION(2, 0, 0) */
#if LIBVIR_CHECK_VERSION(2, 2, 0)
{(char *) "virConnectNodeDeviceEventRegisterAny", libvirt_virConnectNodeDeviceEventRegisterAny, METH_VARARGS, NULL},
{(char *) "virConnectNodeDeviceEventDeregisterAny", libvirt_virConnectNodeDeviceEventDeregisterAny, METH_VARARGS, NULL},
#endif /* LIBVIR_CHECK_VERSION(2, 2, 0) */
{NULL, NULL, 0, NULL}
};

Expand Down
3 changes: 3 additions & 0 deletions sanitytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ def get_libvirt_api_xml_path():
if (name.startswith("virConnectStoragePoolEvent") and
name.endswith("Callback")):
continue
if (name.startswith("virConnectNodeDeviceEvent") and
name.endswith("Callback")):
continue


# virEvent APIs go into main 'libvirt' namespace not any class
Expand Down

0 comments on commit 58a9869

Please sign in to comment.