[libvirt] [PATCH] add a default event handle, to passthough the new events come from qemu
Sheldon
shaohef at linux.vnet.ibm.com
Mon Oct 10 15:58:04 UTC 2011
On 10/10/2011 11:54 PM, shaohef at linux.vnet.ibm.com wrote:
> From: Shaohe Feng<shaohef at linux.vnet.ibm.com>
>
> Basically, this feature can go along with qemu monitor passthrough.
> That way, if we use new commands in the monitor that generate new events, we want
> some way to receive those new events too.
>
> In order to test this patch, see the attached python test case. When domains are started,
> it will be able to catch RESUME events.
>
> Signed-off-by: Shaohe Feng<shaohef at linux.vnet.ibm.com>
> ---
> daemon/remote.c | 34 ++++++++++++++++++++++
> include/libvirt/libvirt.h.in | 14 +++++++++
> python/libvirt-override-virConnect.py | 12 ++++++++
> python/libvirt-override.c | 50 +++++++++++++++++++++++++++++++++
> src/conf/domain_event.c | 46 ++++++++++++++++++++++++++++++
> src/conf/domain_event.h | 5 +++
> src/libvirt_private.syms | 2 +
> src/qemu/qemu_monitor.c | 9 ++++++
> src/qemu/qemu_monitor.h | 6 ++++
> src/qemu/qemu_monitor_json.c | 31 ++++++++++++++++++++
> src/qemu/qemu_process.c | 23 +++++++++++++++
> src/remote/remote_driver.c | 31 ++++++++++++++++++++
> src/remote/remote_protocol.x | 8 ++++-
> src/remote_protocol-structs | 5 +++
> 14 files changed, 275 insertions(+), 1 deletions(-)
>
> diff --git a/daemon/remote.c b/daemon/remote.c
> index 245d41c..ef7d513 100644
> --- a/daemon/remote.c
> +++ b/daemon/remote.c
> @@ -426,6 +426,38 @@ mem_error:
> return -1;
> }
>
> +static int remoteRelayDomainEventDefault(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virDomainPtr dom,
> + const char *rawEvent,
> + void *opaque)
> +{
> + virNetServerClientPtr client = opaque;
> + remote_domain_event_default_event_msg data;
> +
> + if (!client)
> + return -1;
> +
> + VIR_DEBUG("Relaying domain default event event %s %d %s",
> + dom->name, dom->id, rawEvent);
> +
> + /* build return data */
> + memset(&data, 0, sizeof data);
> + data.rawEvent = (char*)strdup(rawEvent);
> + if (data.rawEvent == NULL)
> + goto mem_error;
> + make_nonnull_domain(&data.dom, dom);
> + remoteDispatchDomainEventSend(client, remoteProgram,
> + REMOTE_PROC_DOMAIN_EVENT_DEFAULT_EVENT,
> + (xdrproc_t)xdr_remote_domain_event_default_event_msg,&data);
> +
> + return 0;
> +
> +mem_error:
> + virReportOOMError();
> + VIR_FREE(data.rawEvent);
> + return -1;
> +}
> +
>
> static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED,
> virDomainPtr dom,
> @@ -461,6 +493,8 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOErrorReason),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventControlError),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob),
> + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDefault),
> +
> };
>
> verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index 07617be..5ccf8c7 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -2975,6 +2975,19 @@ typedef void (*virConnectDomainEventBlockJobCallback)(virConnectPtr conn,
> int type,
> int status,
> void *opaque);
> +/**
> + * virConnectDomainEventDefaultCallback:
> + * @conn: connection object
> + * @dom: domain on which the event occurred
> + * @rawEvent: the content of the unknow or un-implementation event
> + *
> + * The callback signature to use when registering for an event of type
> + * VIR_DOMAIN_EVENT_ID_DEFAULT with virConnectDomainEventRegisterAny()
> + */
> +typedef void (*virConnectDomainEventDefaultCallback)(virConnectPtr conn,
> + virDomainPtr dom,
> + const char *rawEvent,
> + void *opaque);
>
> /**
> * VIR_DOMAIN_EVENT_CALLBACK:
> @@ -2995,6 +3008,7 @@ typedef enum {
> VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON = 6, /* virConnectDomainEventIOErrorReasonCallback */
> VIR_DOMAIN_EVENT_ID_CONTROL_ERROR = 7, /* virConnectDomainEventGenericCallback */
> VIR_DOMAIN_EVENT_ID_BLOCK_JOB = 8, /* virConnectDomainEventBlockJobCallback */
> + VIR_DOMAIN_EVENT_ID_DEFAULT = 9, /* virConnectDomainEventDefaultCallback */
>
> /*
> * NB: this enum value will increase over time as new events are
> diff --git a/python/libvirt-override-virConnect.py b/python/libvirt-override-virConnect.py
> index 65b5342..f00cbb9 100644
> --- a/python/libvirt-override-virConnect.py
> +++ b/python/libvirt-override-virConnect.py
> @@ -125,6 +125,18 @@
> except AttributeError:
> pass
>
> + def dispatchDomainEventDefaultCallback(self, dom, path, cbData):
> + """Dispatches events to python user Default event callbacks
> + """
> + try:
> + cb = cbData["cb"]
> + opaque = cbData["opaque"]
> +
> + cb(self, virDomain(self, _obj=dom), path, opaque)
> + return 0
> + except AttributeError:
> + pass
> +
> def domainEventDeregisterAny(self, callbackID):
> """Removes a Domain Event Callback. De-registering for a
> domain callback will disable delivery of this event type """
> diff --git a/python/libvirt-override.c b/python/libvirt-override.c
> index d65423d..c674390 100644
> --- a/python/libvirt-override.c
> +++ b/python/libvirt-override.c
> @@ -4329,6 +4329,53 @@ libvirt_virConnectDomainEventBlockJobCallback(virConnectPtr conn ATTRIBUTE_UNUSE
> return ret;
> }
>
> +static int
> +libvirt_virConnectDomainEventDefaultCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virDomainPtr dom,
> + const char *rawEvent,
> + 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*)"dispatchDomainEventDefaultCallback",
> + (char*)"OsO",
> + pyobj_dom, rawEvent, 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_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
> PyObject * args)
> @@ -4386,6 +4433,9 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
> case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
> cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventBlockJobCallback);
> break;
> + case VIR_DOMAIN_EVENT_ID_DEFAULT:
> + cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDefaultCallback);
> + break;
> }
>
> if (!cb) {
> diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
> index 3189346..04f44fb 100644
> --- a/src/conf/domain_event.c
> +++ b/src/conf/domain_event.c
> @@ -88,6 +88,9 @@ struct _virDomainEvent {
> int type;
> int status;
> } blockJob;
> + struct {
> + char *rawEvent;
> + }defaultEvent;
> } data;
> };
>
> @@ -509,6 +512,9 @@ void virDomainEventFree(virDomainEventPtr event)
> case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
> VIR_FREE(event->data.blockJob.path);
> break;
> + case VIR_DOMAIN_EVENT_ID_DEFAULT:
> + VIR_FREE(event->data.defaultEvent.rawEvent);
> + break;
> }
>
> VIR_FREE(event->dom.name);
> @@ -923,6 +929,40 @@ virDomainEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom,
> path, type, status);
> }
>
> +static virDomainEventPtr
> +virDomainEventDefaultNew(int id, const char *name, unsigned char *uuid,
> + const char *rawEvent)
> +{
> + virDomainEventPtr ev =
> + virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_DEFAULT,
> + id, name, uuid);
> + if (ev) {
> + if (!(ev->data.defaultEvent.rawEvent = strdup(rawEvent))) {
> + virReportOOMError();
> + VIR_FREE(ev->dom.name);
> + VIR_FREE(ev);
> + return NULL;
> + }
> + }
> +
> + return ev;
> +}
> +
> +virDomainEventPtr virDomainEventDefaultNewFromObj(virDomainObjPtr obj,
> + const char *rawEvent)
> +{
> +
> + return virDomainEventDefaultNew(obj->def->id, obj->def->name,
> + obj->def->uuid, rawEvent);
> +}
> +
> +virDomainEventPtr virDomainEventDefaultNewFromDom(virDomainPtr dom,
> + const char *rawEvent)
> +{
> + return virDomainEventDefaultNew(dom->id, dom->name, dom->uuid,
> + rawEvent);
> +}
> +
> virDomainEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom)
> {
> virDomainEventPtr ev =
> @@ -1083,6 +1123,12 @@ void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
> cbopaque);
> break;
>
> + case VIR_DOMAIN_EVENT_ID_DEFAULT:
> + ((virConnectDomainEventDefaultCallback)cb)(conn, dom,
> + event->data.defaultEvent.rawEvent,
> + cbopaque);
> + break;
> +
> default:
> VIR_WARN("Unexpected event ID %d", event->eventID);
> break;
> diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
> index b06be16..401f781 100644
> --- a/src/conf/domain_event.h
> +++ b/src/conf/domain_event.h
> @@ -178,6 +178,11 @@ virDomainEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom,
> int type,
> int status);
>
> +virDomainEventPtr virDomainEventDefaultNewFromObj(virDomainObjPtr obj,
> + const char *rawEvent);
> +virDomainEventPtr virDomainEventDefaultNewFromDom(virDomainPtr dom,
> + const char *rawEvent);
> +
> int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
> virDomainEventPtr event);
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 1ac486f..1dcfc3e 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -457,6 +457,8 @@ virDomainWatchdogModelTypeToString;
> # domain_event.h
> virDomainEventBlockJobNewFromObj;
> virDomainEventBlockJobNewFromDom;
> +virDomainEventDefaultNewFromObj;
> +virDomainEventDefaultNewFromDom;
> virDomainEventCallbackListAdd;
> virDomainEventCallbackListAddID;
> virDomainEventCallbackListCount;
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index c9dd69e..a2b4036 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -976,6 +976,15 @@ int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
> return ret;
> }
>
> +int qemuMonitorEmitDefaultEvent(qemuMonitorPtr mon,
> + const char *rawEvent)
> +{
> + int ret = -1;
> + VIR_DEBUG("mon=%p", mon);
> + QEMU_MONITOR_CALLBACK(mon, ret, domainDefaultEvent, mon->vm,
> + rawEvent);
> + return ret;
> +}
>
>
> int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 3ec78ad..23a03e5 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -123,6 +123,9 @@ struct _qemuMonitorCallbacks {
> const char *diskAlias,
> int type,
> int status);
> + int (*domainDefaultEvent)(qemuMonitorPtr mon,
> + virDomainObjPtr vm,
> + const char *rawEvent)
> };
>
>
> @@ -194,6 +197,9 @@ int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
> int type,
> int status);
>
> +int qemuMonitorEmitDefaultEvent(qemuMonitorPtr mon,
> + const char *rawEvent);
> +
>
>
> int qemuMonitorStartCPUs(qemuMonitorPtr mon,
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 3d383c8..dab03cd 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -58,6 +58,7 @@ static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr
> static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data);
> static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data);
> static void qemuMonitorJSONHandleBlockJob(qemuMonitorPtr mon, virJSONValuePtr data);
> +static void qemuMonitorJSONHandleDefaultEvent(qemuMonitorPtr mon, virJSONValuePtr data);
>
> struct {
> const char *type;
> @@ -74,6 +75,7 @@ struct {
> { "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, },
> { "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, },
> { "BLOCK_JOB_COMPLETED", qemuMonitorJSONHandleBlockJob, },
> + { "DEFAULT_UNKNOW_EVENT", qemuMonitorJSONHandleDefaultEvent, },
> };
>
>
> @@ -83,6 +85,7 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
> {
> const char *type;
> int i;
> + int findEventFlag = -1;
> VIR_DEBUG("mon=%p obj=%p", mon, obj);
>
> type = virJSONValueObjectGetString(obj, "event");
> @@ -98,9 +101,24 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
> VIR_DEBUG("handle %s handler=%p data=%p", type,
> eventHandlers[i].handler, data);
> (eventHandlers[i].handler)(mon, data);
> + findEventFlag = 0;
> break;
> }
> }
> + if (findEventFlag != 0) {
> + if (!STREQ(eventHandlers[ARRAY_CARDINALITY(eventHandlers)-1].type, "DEFAULT_UNKNOW_EVENT")) {
> + VIR_ERROR("the last element is not the default event handler");
> + }
> + else {
> + char *event = NULL;
> + event = virJSONValueToString(obj);
> + if (event != NULL){
> + VIR_DEBUG("Unknow event,call default event handler %s",event);
> + free(event);
> + }
> + (eventHandlers[ARRAY_CARDINALITY(eventHandlers)-1].handler)(mon, obj);
> + }
> + }
> return 0;
> }
>
> @@ -720,6 +738,19 @@ out:
> }
>
>
> +static void qemuMonitorJSONHandleDefaultEvent(qemuMonitorPtr mon, virJSONValuePtr data)
> +{
> + char *defaultEventStr = NULL;
> + defaultEventStr = virJSONValueToString(data);
> + if (defaultEventStr == NULL){
> + VIR_ERROR("Can not get string form JSONValue");
> + return;
> + }
> + qemuMonitorEmitDefaultEvent(mon, defaultEventStr);
> + free(defaultEventStr);
> +}
> +
> +
> int
> qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
> const char *cmd_str,
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index a7fe86c..46881eb 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -713,6 +713,28 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> }
>
> static int
> +qemuProcessHandleDefaultEvent(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> + virDomainObjPtr vm,
> + const char *rawEvent)
> +{
> + struct qemud_driver *driver = qemu_driver;
> + virDomainEventPtr event = NULL;
> +
> + virDomainObjLock(vm);
> + event = virDomainEventDefaultNewFromObj(vm, rawEvent);
> +
> + virDomainObjUnlock(vm);
> +
> + if (event) {
> + qemuDriverLock(driver);
> + qemuDomainEventQueue(driver, event);
> + qemuDriverUnlock(driver);
> + }
> +
> + return 0;
> +}
> +
> +static int
> qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> virDomainObjPtr vm,
> int phase,
> @@ -829,6 +851,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
> .domainIOError = qemuProcessHandleIOError,
> .domainGraphics = qemuProcessHandleGraphics,
> .domainBlockJob = qemuProcessHandleBlockJob,
> + .domainDefaultEvent = qemuProcessHandleDefaultEvent,
> };
>
> static int
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index 2b2f41e..9648661 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -228,6 +228,11 @@ remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog,
> virNetClientPtr client,
> void *evdata, void *opaque);
>
> +static void
> +remoteDomainBuildEventDefaultEvent(virNetClientProgramPtr prog,
> + virNetClientPtr client,
> + void *evdata, void *opaque);
> +
> static virNetClientProgramEvent remoteDomainEvents[] = {
> { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
> remoteDomainBuildEventRTCChange,
> @@ -265,6 +270,10 @@ static virNetClientProgramEvent remoteDomainEvents[] = {
> remoteDomainBuildEventBlockJob,
> sizeof(remote_domain_event_block_job_msg),
> (xdrproc_t)xdr_remote_domain_event_block_job_msg },
> + { REMOTE_PROC_DOMAIN_EVENT_DEFAULT_EVENT,
> + remoteDomainBuildEventDefaultEvent,
> + sizeof(remote_domain_event_default_event_msg),
> + (xdrproc_t)xdr_remote_domain_event_default_event_msg },
> };
>
> enum virDrvOpenRemoteFlags {
> @@ -3220,6 +3229,28 @@ remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> }
>
> static void
> +remoteDomainBuildEventDefaultEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> + virNetClientPtr client ATTRIBUTE_UNUSED,
> + void *evdata, void *opaque)
> +{
> + virConnectPtr conn = opaque;
> + struct private_data *priv = conn->privateData;
> + remote_domain_event_default_event_msg *msg = evdata;
> + virDomainPtr dom;
> + virDomainEventPtr event = NULL;
> +
> + dom = get_nonnull_domain(conn, msg->dom);
> + if (!dom)
> + return;
> +
> + event = virDomainEventDefaultNewFromDom(dom, msg->rawEvent);
> +
> + virDomainFree(dom);
> +
> + remoteDomainEventQueue(priv, event);
> +}
> +
> +static void
> remoteDomainBuildEventGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> virNetClientPtr client ATTRIBUTE_UNUSED,
> void *evdata, void *opaque)
> diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
> index c8a92fd..81c6a4e 100644
> --- a/src/remote/remote_protocol.x
> +++ b/src/remote/remote_protocol.x
> @@ -2010,6 +2010,11 @@ struct remote_domain_event_block_job_msg {
> int status;
> };
>
> +struct remote_domain_event_default_event_msg {
> + remote_nonnull_domain dom;
> + remote_nonnull_string rawEvent;
> +};
> +
> struct remote_domain_managed_save_args {
> remote_nonnull_domain dom;
> unsigned int flags;
> @@ -2525,7 +2530,8 @@ enum remote_procedure {
> REMOTE_PROC_DOMAIN_MIGRATE_GET_MAX_SPEED = 242, /* autogen autogen */
> REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243, /* skipgen skipgen */
> REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244, /* autogen autogen */
> - REMOTE_PROC_DOMAIN_RESET = 245 /* autogen autogen */
> + REMOTE_PROC_DOMAIN_RESET = 245, /* autogen autogen */
> + REMOTE_PROC_DOMAIN_EVENT_DEFAULT_EVENT = 246 /* skipgen skipgen */
>
> /*
> * Notice how the entries are grouped in sets of 10 ?
> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
> index 69175cc..7d0d0d4 100644
> --- a/src/remote_protocol-structs
> +++ b/src/remote_protocol-structs
> @@ -1509,6 +1509,10 @@ struct remote_domain_event_block_job_msg {
> int type;
> int status;
> };
> +struct remote_domain_event_default_event_msg {
> + remote_nonnull_domain dom;
> + remote_nonnull_string rawEvent;
> +};
> struct remote_domain_managed_save_args {
> remote_nonnull_domain dom;
> u_int flags;
> @@ -1971,4 +1975,5 @@ enum remote_procedure {
> REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243,
> REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244,
> REMOTE_PROC_DOMAIN_RESET = 245,
> + REMOTE_PROC_DOMAIN_EVENT_DEFAULT_EVENT = 246,
> };
-------------- next part --------------
A non-text attachment was scrubbed...
Name: default-event-test.py
Type: text/x-python
Size: 827 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20111010/f1334131/attachment-0001.py>
More information about the libvir-list
mailing list