diff options
author | Guido Günther <agx@sigxcpu.org> | 2014-01-16 22:33:43 +0100 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2014-01-16 22:33:43 +0100 |
commit | 22e83d797960efd261a6188c1ebe42b169fcbc86 (patch) | |
tree | 2d0dc63f3c54a1f91fdd3ff7f6e88c9160f642ab /src | |
parent | fef0f8f1ad69b37558ffa8d80d43e8626817130c (diff) |
New upstream version 1.2.1
Diffstat (limited to 'src')
29 files changed, 544 insertions, 158 deletions
diff --git a/src/access/org.libvirt.api.policy b/src/access/org.libvirt.api.policy index 9819f0a70..a33520951 100644 --- a/src/access/org.libvirt.api.policy +++ b/src/access/org.libvirt.api.policy @@ -51,7 +51,7 @@ </action> <action id="org.libvirt.api.connect.search-domains"> <description>List domains</description> - <message>Listing domains requires authorization</message> + <message>Listing domains or using domain events requires authorization</message> <defaults> <allow_any>yes</allow_any> <allow_inactive>yes</allow_inactive> @@ -69,7 +69,7 @@ </action> <action id="org.libvirt.api.connect.search-networks"> <description>List networks</description> - <message>Listing networks requires authorization</message> + <message>Listing networks or using network events requires authorization</message> <defaults> <allow_any>yes</allow_any> <allow_inactive>yes</allow_inactive> diff --git a/src/access/viraccessapicheck.c b/src/access/viraccessapicheck.c index 411d1910a..ea2cfed5b 100644 --- a/src/access/viraccessapicheck.c +++ b/src/access/viraccessapicheck.c @@ -99,7 +99,7 @@ int virConnectDomainEventRegisterEnsureACL(virConnectPtr conn) return -1; } - if ((rv = virAccessManagerCheckConnect(mgr, conn->driver->name, VIR_ACCESS_PERM_CONNECT_READ)) <= 0) { + if ((rv = virAccessManagerCheckConnect(mgr, conn->driver->name, VIR_ACCESS_PERM_CONNECT_SEARCH_DOMAINS)) <= 0) { virObjectUnref(mgr); if (rv == 0) virReportError(VIR_ERR_ACCESS_DENIED, NULL); @@ -109,6 +109,26 @@ int virConnectDomainEventRegisterEnsureACL(virConnectPtr conn) return 0; } +/* Returns: false on error/denied, true on allowed */ +bool virConnectDomainEventRegisterCheckACL(virConnectPtr conn, virDomainDefPtr domain) +{ + virAccessManagerPtr mgr; + int rv; + + if (!(mgr = virAccessManagerGetDefault())) { + virResetLastError(); + return false; + } + + if ((rv = virAccessManagerCheckDomain(mgr, conn->driver->name, domain, VIR_ACCESS_PERM_DOMAIN_GETATTR)) <= 0) { + virObjectUnref(mgr); + virResetLastError(); + return false; + } + virObjectUnref(mgr); + return true; +} + /* Returns: -1 on error/denied, 0 on allowed */ int virConnectDomainEventRegisterAnyEnsureACL(virConnectPtr conn) { @@ -119,7 +139,7 @@ int virConnectDomainEventRegisterAnyEnsureACL(virConnectPtr conn) return -1; } - if ((rv = virAccessManagerCheckConnect(mgr, conn->driver->name, VIR_ACCESS_PERM_CONNECT_READ)) <= 0) { + if ((rv = virAccessManagerCheckConnect(mgr, conn->driver->name, VIR_ACCESS_PERM_CONNECT_SEARCH_DOMAINS)) <= 0) { virObjectUnref(mgr); if (rv == 0) virReportError(VIR_ERR_ACCESS_DENIED, NULL); @@ -129,6 +149,26 @@ int virConnectDomainEventRegisterAnyEnsureACL(virConnectPtr conn) return 0; } +/* Returns: false on error/denied, true on allowed */ +bool virConnectDomainEventRegisterAnyCheckACL(virConnectPtr conn, virDomainDefPtr domain) +{ + virAccessManagerPtr mgr; + int rv; + + if (!(mgr = virAccessManagerGetDefault())) { + virResetLastError(); + return false; + } + + if ((rv = virAccessManagerCheckDomain(mgr, conn->driver->name, domain, VIR_ACCESS_PERM_DOMAIN_GETATTR)) <= 0) { + virObjectUnref(mgr); + virResetLastError(); + return false; + } + virObjectUnref(mgr); + return true; +} + /* Returns: -1 on error/denied, 0 on allowed */ int virConnectDomainXMLFromNativeEnsureACL(virConnectPtr conn) { @@ -1079,7 +1119,7 @@ int virConnectNetworkEventRegisterAnyEnsureACL(virConnectPtr conn) return -1; } - if ((rv = virAccessManagerCheckConnect(mgr, conn->driver->name, VIR_ACCESS_PERM_CONNECT_READ)) <= 0) { + if ((rv = virAccessManagerCheckConnect(mgr, conn->driver->name, VIR_ACCESS_PERM_CONNECT_SEARCH_NETWORKS)) <= 0) { virObjectUnref(mgr); if (rv == 0) virReportError(VIR_ERR_ACCESS_DENIED, NULL); @@ -1089,6 +1129,26 @@ int virConnectNetworkEventRegisterAnyEnsureACL(virConnectPtr conn) return 0; } +/* Returns: false on error/denied, true on allowed */ +bool virConnectNetworkEventRegisterAnyCheckACL(virConnectPtr conn, virNetworkDefPtr network) +{ + virAccessManagerPtr mgr; + int rv; + + if (!(mgr = virAccessManagerGetDefault())) { + virResetLastError(); + return false; + } + + if ((rv = virAccessManagerCheckNetwork(mgr, conn->driver->name, network, VIR_ACCESS_PERM_NETWORK_GETATTR)) <= 0) { + virObjectUnref(mgr); + virResetLastError(); + return false; + } + virObjectUnref(mgr); + return true; +} + /* Returns: -1 on error/denied, 0 on allowed */ int virConnectNumOfDefinedDomainsEnsureACL(virConnectPtr conn) { diff --git a/src/access/viraccessapicheck.h b/src/access/viraccessapicheck.h index 9963631dc..3adad6150 100644 --- a/src/access/viraccessapicheck.h +++ b/src/access/viraccessapicheck.h @@ -15,7 +15,9 @@ extern int virConnectCompareCPUEnsureACL(virConnectPtr conn); extern int virConnectDomainEventDeregisterEnsureACL(virConnectPtr conn); extern int virConnectDomainEventDeregisterAnyEnsureACL(virConnectPtr conn); extern int virConnectDomainEventRegisterEnsureACL(virConnectPtr conn); +extern bool virConnectDomainEventRegisterCheckACL(virConnectPtr conn, virDomainDefPtr domain); extern int virConnectDomainEventRegisterAnyEnsureACL(virConnectPtr conn); +extern bool virConnectDomainEventRegisterAnyCheckACL(virConnectPtr conn, virDomainDefPtr domain); extern int virConnectDomainXMLFromNativeEnsureACL(virConnectPtr conn); extern int virConnectDomainXMLToNativeEnsureACL(virConnectPtr conn); extern int virConnectFindStoragePoolSourcesEnsureACL(virConnectPtr conn); @@ -64,6 +66,7 @@ extern int virConnectListStoragePoolsEnsureACL(virConnectPtr conn); extern bool virConnectListStoragePoolsCheckACL(virConnectPtr conn, virStoragePoolDefPtr pool); extern int virConnectNetworkEventDeregisterAnyEnsureACL(virConnectPtr conn); extern int virConnectNetworkEventRegisterAnyEnsureACL(virConnectPtr conn); +extern bool virConnectNetworkEventRegisterAnyCheckACL(virConnectPtr conn, virNetworkDefPtr network); extern int virConnectNumOfDefinedDomainsEnsureACL(virConnectPtr conn); extern bool virConnectNumOfDefinedDomainsCheckACL(virConnectPtr conn, virDomainDefPtr domain); extern int virConnectNumOfDefinedInterfacesEnsureACL(virConnectPtr conn); diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h index fdc461b64..6d14f058c 100644 --- a/src/access/viraccessperm.h +++ b/src/access/viraccessperm.h @@ -1,7 +1,7 @@ /* * viraccessperm.h: access control permissions * - * Copyright (C) 2012-2013 Red Hat, Inc. + * Copyright (C) 2012-2014 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -47,14 +47,14 @@ typedef enum { /** * @desc: List domains - * @message: Listing domains requires authorization + * @message: Listing domains or using domain events requires authorization * @anonymous: 1 */ VIR_ACCESS_PERM_CONNECT_SEARCH_DOMAINS, /** * @desc: List networks - * @message: Listing networks requires authorization + * @message: Listing networks or using network events requires authorization * @anonymous: 1 */ VIR_ACCESS_PERM_CONNECT_SEARCH_NETWORKS, diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 35212ef45..f56aed37b 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -360,6 +360,30 @@ virDomainEventDeviceRemovedDispose(void *obj) } +/** + * virDomainEventFilter: + * @conn: pointer to the connection + * @event: the event to check + * @opaque: opaque data holding ACL filter to use + * + * Internal function to run ACL filtering before dispatching an event + */ +static bool +virDomainEventFilter(virConnectPtr conn, virObjectEventPtr event, void *opaque) +{ + virDomainDef dom; + virDomainObjListFilter filter = opaque; + + /* For now, we just create a virDomainDef with enough contents to + * satisfy what viraccessdriverpolkit.c references. This is a bit + * fragile, but I don't know of anything better. */ + dom.name = event->meta.name; + memcpy(dom.uuid, event->meta.uuid, VIR_UUID_BUFLEN); + + return (filter)(conn, &dom); +} + + static void * virDomainEventNew(virClassPtr klass, int eventID, @@ -1265,6 +1289,7 @@ cleanup: * virDomainEventStateRegister: * @conn: connection to associate with callback * @state: object event state + * @filter: optional ACL filter to limit which events can be sent * @callback: the callback to add * @opaque: data blob to pass to @callback * @freecb: callback to free @opaque @@ -1277,6 +1302,7 @@ cleanup: int virDomainEventStateRegister(virConnectPtr conn, virObjectEventStatePtr state, + virDomainObjListFilter filter, virConnectDomainEventCallback callback, void *opaque, virFreeCallback freecb) @@ -1285,10 +1311,11 @@ virDomainEventStateRegister(virConnectPtr conn, return -1; return virObjectEventStateRegisterID(conn, state, NULL, - virDomainEventClass, + filter ? virDomainEventFilter : NULL, + filter, virDomainEventClass, VIR_DOMAIN_EVENT_ID_LIFECYCLE, VIR_OBJECT_EVENT_CALLBACK(callback), - opaque, freecb, NULL); + opaque, freecb, NULL, false); } @@ -1296,6 +1323,7 @@ virDomainEventStateRegister(virConnectPtr conn, * virDomainEventStateRegisterID: * @conn: connection to associate with callback * @state: object event state + * @filter: optional ACL filter to limit which events can be sent * @dom: optional domain for filtering the event * @eventID: ID of the event type to register for * @cb: function to invoke when event fires @@ -1312,6 +1340,7 @@ virDomainEventStateRegister(virConnectPtr conn, int virDomainEventStateRegisterID(virConnectPtr conn, virObjectEventStatePtr state, + virDomainObjListFilter filter, virDomainPtr dom, int eventID, virConnectDomainEventGenericCallback cb, @@ -1323,9 +1352,10 @@ virDomainEventStateRegisterID(virConnectPtr conn, return -1; return virObjectEventStateRegisterID(conn, state, dom ? dom->uuid : NULL, - virDomainEventClass, eventID, + filter ? virDomainEventFilter : NULL, + filter, virDomainEventClass, eventID, VIR_OBJECT_EVENT_CALLBACK(cb), - opaque, freecb, callbackID); + opaque, freecb, callbackID, false); } diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index b2ea580e6..b39d5cda3 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -1,7 +1,7 @@ /* * domain_event.h: domain event queue processing helpers * - * Copyright (C) 2012 Red Hat, Inc. + * Copyright (C) 2012-2014 Red Hat, Inc. * Copyright (C) 2008 VirtualIron * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. * @@ -177,20 +177,24 @@ virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, int virDomainEventStateRegister(virConnectPtr conn, virObjectEventStatePtr state, + virDomainObjListFilter filter, virConnectDomainEventCallback callback, void *opaque, virFreeCallback freecb) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); + int virDomainEventStateRegisterID(virConnectPtr conn, virObjectEventStatePtr state, + virDomainObjListFilter filter, virDomainPtr dom, int eventID, virConnectDomainEventGenericCallback cb, void *opaque, virFreeCallback freecb, int *callbackID) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5); + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(6); + int virDomainEventStateDeregister(virConnectPtr conn, virObjectEventStatePtr state, diff --git a/src/conf/network_event.c b/src/conf/network_event.c index 3cd884d2f..f27b7e9e9 100644 --- a/src/conf/network_event.c +++ b/src/conf/network_event.c @@ -122,9 +122,35 @@ cleanup: /** + * virNetworkEventFilter: + * @conn: pointer to the connection + * @event: the event to check + * @opaque: opaque data holding ACL filter to use + * + * Internal function to run ACL filtering before dispatching an event + */ +static bool +virNetworkEventFilter(virConnectPtr conn, virObjectEventPtr event, + void *opaque) +{ + virNetworkDef net; + virNetworkObjListFilter filter = opaque; + + /* For now, we just create a virNetworkDef with enough contents to + * satisfy what viraccessdriverpolkit.c references. This is a bit + * fragile, but I don't know of anything better. */ + net.name = event->meta.name; + memcpy(net.uuid, event->meta.uuid, VIR_UUID_BUFLEN); + + return (filter)(conn, &net); +} + + +/** * virNetworkEventStateRegisterID: * @conn: connection to associate with callback * @state: object event state + * @filter: optional ACL filter to limit which events can be sent * @net: network to filter on or NULL for all networks * @eventID: ID of the event type to register for * @cb: function to invoke when event occurs @@ -141,6 +167,7 @@ cleanup: int virNetworkEventStateRegisterID(virConnectPtr conn, virObjectEventStatePtr state, + virNetworkObjListFilter filter, virNetworkPtr net, int eventID, virConnectNetworkEventGenericCallback cb, @@ -152,9 +179,49 @@ virNetworkEventStateRegisterID(virConnectPtr conn, return -1; return virObjectEventStateRegisterID(conn, state, net ? net->uuid : NULL, + filter ? virNetworkEventFilter : NULL, + filter, virNetworkEventClass, eventID, + VIR_OBJECT_EVENT_CALLBACK(cb), + opaque, freecb, callbackID, false); +} + + +/** + * virNetworkEventStateRegisterClient: + * @conn: connection to associate with callback + * @state: object event state + * @net: network to filter on or NULL for all networks + * @eventID: ID of the event type to register for + * @cb: function to invoke when event occurs + * @opaque: data blob to pass to @callback + * @freecb: callback to free @opaque + * @callbackID: filled with callback ID + * + * Register the function @cb with connection @conn, from @state, for + * events of type @eventID, and return the registration handle in + * @callbackID. This version is intended for use on the client side + * of RPC. + * + * Returns: the number of callbacks now registered, or -1 on error + */ +int +virNetworkEventStateRegisterClient(virConnectPtr conn, + virObjectEventStatePtr state, + virNetworkPtr net, + int eventID, + virConnectNetworkEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID) +{ + if (virNetworkEventsInitialize() < 0) + return -1; + + return virObjectEventStateRegisterID(conn, state, net ? net->uuid : NULL, + NULL, NULL, virNetworkEventClass, eventID, VIR_OBJECT_EVENT_CALLBACK(cb), - opaque, freecb, callbackID); + opaque, freecb, callbackID, true); } diff --git a/src/conf/network_event.h b/src/conf/network_event.h index 843faf9b7..0812752e6 100644 --- a/src/conf/network_event.h +++ b/src/conf/network_event.h @@ -24,6 +24,7 @@ #include "internal.h" #include "object_event.h" #include "object_event_private.h" +#include "network_conf.h" #ifndef __NETWORK_EVENT_H__ # define __NETWORK_EVENT_H__ @@ -31,12 +32,27 @@ int virNetworkEventStateRegisterID(virConnectPtr conn, virObjectEventStatePtr state, + virNetworkObjListFilter filter, virNetworkPtr net, int eventID, virConnectNetworkEventGenericCallback cb, void *opaque, virFreeCallback freecb, - int *callbackID); + int *callbackID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(6) + ATTRIBUTE_NONNULL(9); + +int +virNetworkEventStateRegisterClient(virConnectPtr conn, + virObjectEventStatePtr state, + virNetworkPtr net, + int eventID, + virConnectNetworkEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5) + ATTRIBUTE_NONNULL(8); virObjectEventPtr virNetworkEventLifecycleNew(const char *name, diff --git a/src/conf/object_event.c b/src/conf/object_event.c index b69387ad1..aff495661 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -66,8 +66,11 @@ struct _virObjectEventCallback { virClassPtr klass; int eventID; virConnectPtr conn; + int remoteID; bool uuid_filter; unsigned char uuid[VIR_UUID_BUFLEN]; + virObjectEventCallbackFilter filter; + void *filter_opaque; virConnectObjectEventGenericCallback cb; void *opaque; virFreeCallback freecb; @@ -148,19 +151,29 @@ virObjectEventCallbackListFree(virObjectEventCallbackListPtr list) * @cbList: the list * @klass: the base event class * @eventID: the event ID + * @uuid: optional uuid of per-object filtering + * @serverFilter: true if server supports object filtering * * Internal function to count how many callbacks remain registered for - * the given @eventID; knowing this allows the client side of the - * remote driver know when it must send an RPC to adjust the callbacks - * on the server. Note that this function intentionally ignores - * the legacy field, since RPC calls use only a single callback on - * the server to manage both legacy and modern domain lifecycle events. + * the given @eventID and @uuid; knowing this allows the client side + * of the remote driver know when it must send an RPC to adjust the + * callbacks on the server. When @serverFilter is false, this function + * returns a count that includes both global and per-object callbacks, + * since the remote side will use a single global event to feed both. + * When true, the count is limited to the callbacks with the same + * @uuid, and where a remoteID has already been set on the callback + * with virObjectEventStateSetRemote(). Note that this function + * intentionally ignores the legacy field, since RPC calls use only a + * single callback on the server to manage both legacy and modern + * global domain lifecycle events. */ static int virObjectEventCallbackListCount(virConnectPtr conn, virObjectEventCallbackListPtr cbList, virClassPtr klass, - int eventID) + int eventID, + unsigned char uuid[VIR_UUID_BUFLEN], + bool serverFilter) { size_t i; int ret = 0; @@ -171,7 +184,12 @@ virObjectEventCallbackListCount(virConnectPtr conn, if (cb->klass == klass && cb->eventID == eventID && cb->conn == conn && - !cb->deleted) + !cb->deleted && + (!serverFilter || + (cb->remoteID >= 0 && + ((uuid && cb->uuid_filter && + memcmp(cb->uuid, uuid, VIR_UUID_BUFLEN) == 0) || + (!uuid && !cb->uuid_filter))))) ret++; } return ret; @@ -196,17 +214,19 @@ virObjectEventCallbackListRemoveID(virConnectPtr conn, virObjectEventCallbackPtr cb = cbList->callbacks[i]; if (cb->callbackID == callbackID && cb->conn == conn) { - virClassPtr klass = cb->klass; - int eventID = cb->eventID; + int ret; + + ret = virObjectEventCallbackListCount(conn, cbList, cb->klass, + cb->eventID, + cb->uuid_filter ? cb->uuid : NULL, + cb->remoteID >= 0) - 1; if (cb->freecb) (*cb->freecb)(cb->opaque); virObjectUnref(cb->conn); VIR_FREE(cb); VIR_DELETE_ELEMENT(cbList->callbacks, i, cbList->count); - - return virObjectEventCallbackListCount(conn, cbList, klass, - eventID); + return ret; } } @@ -230,7 +250,9 @@ virObjectEventCallbackListMarkDeleteID(virConnectPtr conn, if (cb->callbackID == callbackID && cb->conn == conn) { cb->deleted = true; return virObjectEventCallbackListCount(conn, cbList, cb->klass, - cb->eventID); + cb->eventID, + cb->uuid_filter ? cb->uuid : NULL, + cb->remoteID >= 0); } } @@ -280,9 +302,13 @@ virObjectEventCallbackListPurgeMarked(virObjectEventCallbackListPtr cbList) * @eventID: the event ID * @callback: the callback to locate * @legacy: true if callback is tracked by function instead of callbackID + * @remoteID: optionally return a known remoteID * * Internal function to determine if @callback already has a - * callbackID in @cbList for the given @conn and other filters. + * callbackID in @cbList for the given @conn and other filters. If + * @remoteID is non-NULL, and another callback exists that can be + * serviced by the same remote event, then set it to that remote ID. + * * Return the id if found, or -1 with no error issued if not present. */ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) @@ -292,29 +318,33 @@ virObjectEventCallbackLookup(virConnectPtr conn, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback callback, - bool legacy) + bool legacy, + int *remoteID) { - int ret = -1; size_t i; + if (remoteID) + *remoteID = -1; + for (i = 0; i < cbList->count; i++) { virObjectEventCallbackPtr cb = cbList->callbacks[i]; if (cb->deleted) continue; - if (cb->cb == callback && - cb->klass == klass && + if (cb->klass == klass && cb->eventID == eventID && cb->conn == conn && cb->legacy == legacy && ((uuid && cb->uuid_filter && memcmp(cb->uuid, uuid, VIR_UUID_BUFLEN) == 0) || (!uuid && !cb->uuid_filter))) { - ret = cb->callbackID; - break; + if (remoteID) + *remoteID = cb->remoteID; + if (cb->cb == callback) + return cb->callbackID; } } - return ret; + return -1; } @@ -322,13 +352,16 @@ virObjectEventCallbackLookup(virConnectPtr conn, * virObjectEventCallbackListAddID: * @conn: pointer to the connection * @cbList: the list - * @uuid: the uuid of the object to filter on + * @uuid: the optional uuid of the object to filter on + * @filter: optional last-ditch filter callback + * @filter_opaque: opaque data to pass to @filter * @klass: the base event class * @eventID: the event ID * @callback: the callback to add * @opaque: opaque data to pass to @callback * @freecb: callback to free @opaque * @callbackID: filled with callback ID + * @serverFilter: true if server supports object filtering * * Internal function to add a callback from a virObjectEventCallbackListPtr */ @@ -336,19 +369,24 @@ static int virObjectEventCallbackListAddID(virConnectPtr conn, virObjectEventCallbackListPtr cbList, unsigned char uuid[VIR_UUID_BUFLEN], + virObjectEventCallbackFilter filter, + void *filter_opaque, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback callback, void *opaque, virFreeCallback freecb, - int *callbackID) + int *callbackID, + bool serverFilter) { virObjectEventCallbackPtr event; int ret = -1; + int remoteID = -1; - VIR_DEBUG("conn=%p cblist=%p uuid=%p " + VIR_DEBUG("conn=%p cblist=%p uuid=%p filter=%p filter_opaque=%p " "klass=%p eventID=%d callback=%p opaque=%p", - conn, cbList, uuid, klass, eventID, callback, opaque); + conn, cbList, uuid, filter, filter_opaque, + klass, eventID, callback, opaque); /* Check incoming */ if (!cbList) { @@ -358,7 +396,8 @@ virObjectEventCallbackListAddID(virConnectPtr conn, /* check if we already have this callback on our list */ if (virObjectEventCallbackLookup(conn, cbList, uuid, klass, eventID, callback, - !callbackID) != -1) { + !callbackID, + serverFilter ? &remoteID : NULL) != -1) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("event callback already tracked")); return -1; @@ -373,6 +412,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn, event->eventID = eventID; event->opaque = opaque; event->freecb = freecb; + event->remoteID = remoteID; /* Only need 'uuid' for matching; 'id' can change as domain * switches between running and shutoff, and 'name' can change in @@ -381,6 +421,8 @@ virObjectEventCallbackListAddID(virConnectPtr conn, event->uuid_filter = true; memcpy(event->uuid, uuid, VIR_UUID_BUFLEN); } + event->filter = filter; + event->filter_opaque = filter_opaque; if (callbackID) *callbackID = event->callbackID; @@ -390,7 +432,10 @@ virObjectEventCallbackListAddID(virConnectPtr conn, if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, event) < 0) goto cleanup; - ret = virObjectEventCallbackListCount(conn, cbList, klass, eventID); + ret = virObjectEventCallbackListCount(conn, cbList, klass, eventID, + uuid, serverFilter); + if (serverFilter && remoteID < 0) + ret++; cleanup: if (event) @@ -588,6 +633,7 @@ virObjectEventNew(virClassPtr klass, event->dispatch = dispatcher; event->eventID = eventID; + event->remoteID = -1; if (VIR_STRDUP(event->meta.name, name) < 0) { VIR_FREE(event); @@ -635,6 +681,11 @@ virObjectEventDispatchMatchCallback(virObjectEventPtr event, return false; if (cb->eventID != event->eventID) return false; + if (cb->remoteID != event->remoteID) + return false; + + if (cb->filter && !(cb->filter)(cb->conn, event, cb->filter_opaque)) + return false; if (cb->uuid_filter) { /* Deliberately ignoring 'id' for matching, since that @@ -692,17 +743,21 @@ virObjectEventStateQueueDispatch(virObjectEventStatePtr state, /** - * virObjectEventStateQueue: + * virObjectEventStateQueueRemote: * @state: the event state object * @event: event to add to the queue + * @remoteID: limit dispatch to callbacks with the same remote id * * Adds @event to the queue of events to be dispatched at the next * safe moment. The caller should no longer use @event after this - * call. + * call. If @remoteID is non-negative, the event will only be sent to + * callbacks where virObjectEventStateSetRemote() registered a remote + * id. */ void -virObjectEventStateQueue(virObjectEventStatePtr state, - virObjectEventPtr event) +virObjectEventStateQueueRemote(virObjectEventStatePtr state, + virObjectEventPtr event, + int remoteID) { if (state->timer < 0) { virObjectUnref(event); @@ -711,6 +766,7 @@ virObjectEventStateQueue(virObjectEventStatePtr state, virObjectEventStateLock(state); + event->remoteID = remoteID; if (virObjectEventQueuePush(state->queue, event) < 0) { VIR_DEBUG("Error adding event to queue"); virObjectUnref(event); @@ -722,6 +778,23 @@ virObjectEventStateQueue(virObjectEventStatePtr state, } +/** + * virObjectEventStateQueue: + * @state: the event state object + * @event: event to add to the queue + * + * Adds @event to the queue of events to be dispatched at the next + * safe moment. The caller should no longer use @event after this + * call. + */ +void +virObjectEventStateQueue(virObjectEventStatePtr state, + virObjectEventPtr event) +{ + virObjectEventStateQueueRemote(state, event, -1); +} + + static void virObjectEventStateFlush(virObjectEventStatePtr state) { @@ -761,23 +834,41 @@ virObjectEventStateFlush(virObjectEventStatePtr state) * @opaque: data blob to pass to @callback * @freecb: callback to free @opaque * @callbackID: filled with callback ID + * @serverFilter: true if server supports object filtering * * Register the function @cb with connection @conn, from @state, for * events of type @eventID, and return the registration handle in * @callbackID. * - * Returns: the number of callbacks now registered, or -1 on error + * The return value is only important when registering client-side + * mirroring of remote events (since the public API is documented to + * return the callbackID rather than a count). A return of 1 means + * that this is the first use of this type of event, so a remote event + * must be enabled; a return larger than 1 means that an existing + * remote event can already feed this callback. If @serverFilter is + * false, the return count assumes that a single global remote feeds + * both generic and per-object callbacks, and that the event queue + * will be fed with virObjectEventStateQueue(). If it is true, then + * the return count assumes that the remote side is capable of per- + * object filtering; the user must call virObjectEventStateSetRemote() + * to record the remote id, and queue events with + * virObjectEventStateQueueRemote(). + * + * Returns: the number of callbacks now registered, or -1 on error. */ int virObjectEventStateRegisterID(virConnectPtr conn, virObjectEventStatePtr state, unsigned char *uuid, + virObjectEventCallbackFilter filter, + void *filter_opaque, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback cb, void *opaque, virFreeCallback freecb, - int *callbackID) + int *callbackID, + bool serverFilter) { int ret = -1; @@ -795,9 +886,10 @@ virObjectEventStateRegisterID(virConnectPtr conn, } ret = virObjectEventCallbackListAddID(conn, state->callbacks, - uuid, klass, eventID, + uuid, filter, filter_opaque, + klass, eventID, cb, opaque, freecb, - callbackID); + callbackID, serverFilter); if (ret == -1 && state->callbacks->count == 0 && @@ -874,7 +966,7 @@ virObjectEventStateCallbackID(virConnectPtr conn, virObjectEventStateLock(state); ret = virObjectEventCallbackLookup(conn, state->callbacks, NULL, - klass, eventID, callback, true); + klass, eventID, callback, true, NULL); virObjectEventStateUnlock(state); if (ret < 0) @@ -890,16 +982,20 @@ virObjectEventStateCallbackID(virConnectPtr conn, * @conn: connection associated with the callback * @state: object event state * @callbackID: the callback to query + * @remoteID: optionally output remote ID of the callback * - * Query what event ID type is associated with the - * callback @callbackID for connection @conn + * Query what event ID type is associated with the callback + * @callbackID for connection @conn. If @remoteID is non-null, it + * will be set to the remote id previously registered with + * virObjectEventStateSetRemote(). * * Returns 0 on success, -1 on error */ int virObjectEventStateEventID(virConnectPtr conn, virObjectEventStatePtr state, - int callbackID) + int callbackID, + int *remoteID) { int ret = -1; size_t i; @@ -913,6 +1009,8 @@ virObjectEventStateEventID(virConnectPtr conn, continue; if (cb->callbackID == callbackID && cb->conn == conn) { + if (remoteID) + *remoteID = cb->remoteID; ret = cb->eventID; break; } @@ -925,3 +1023,39 @@ virObjectEventStateEventID(virConnectPtr conn, callbackID); return ret; } + + +/** + * virObjectEventStateSetRemote: + * @conn: connection associated with the callback + * @state: object event state + * @callbackID: the callback to adjust + * @remoteID: the remote ID to associate with the callback + * + * Update @callbackID for connection @conn to record that it is now + * tied to @remoteID, and will therefore only match events that are + * sent with virObjectEventStateQueueRemote() with the same remote ID. + * Silently does nothing if @callbackID is invalid. + */ +void +virObjectEventStateSetRemote(virConnectPtr conn, + virObjectEventStatePtr state, + int callbackID, + int remoteID) +{ + size_t i; + + virObjectEventStateLock(state); + for (i = 0; i < state->callbacks->count; i++) { + virObjectEventCallbackPtr cb = state->callbacks->callbacks[i]; + + if (cb->deleted) + continue; + + if (cb->callbackID == callbackID && cb->conn == conn) { + cb->remoteID = remoteID; + break; + } + } + virObjectEventStateUnlock(state); +} diff --git a/src/conf/object_event.h b/src/conf/object_event.h index 39e92d50c..7654799e2 100644 --- a/src/conf/object_event.h +++ b/src/conf/object_event.h @@ -67,27 +67,31 @@ void virObjectEventStateQueue(virObjectEventStatePtr state, virObjectEventPtr event) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int -virObjectEventStateRegisterID(virConnectPtr conn, - virObjectEventStatePtr state, - unsigned char *uuid, - virClassPtr klass, - int eventID, - virConnectObjectEventGenericCallback cb, - void *opaque, - virFreeCallback freecb, - int *callbackID) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) - ATTRIBUTE_NONNULL(6); + +void +virObjectEventStateQueueRemote(virObjectEventStatePtr state, + virObjectEventPtr event, + int remoteID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + int virObjectEventStateDeregisterID(virConnectPtr conn, virObjectEventStatePtr state, int callbackID) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + int virObjectEventStateEventID(virConnectPtr conn, virObjectEventStatePtr state, - int callbackID) + int callbackID, + int *remoteID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +void +virObjectEventStateSetRemote(virConnectPtr conn, + virObjectEventStatePtr state, + int callbackID, + int remoteID) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); #endif diff --git a/src/conf/object_event_private.h b/src/conf/object_event_private.h index 571fc40f7..8e265f94b 100644 --- a/src/conf/object_event_private.h +++ b/src/conf/object_event_private.h @@ -48,13 +48,44 @@ struct _virObjectEvent { virObject parent; int eventID; virObjectMeta meta; + int remoteID; virObjectEventDispatchFunc dispatch; }; +/** + * virObjectEventCallbackFilter: + * @conn: the connection pointer + * @event: the event about to be dispatched + * @opaque: opaque data registered with the filter + * + * Callback to do final filtering for a reason not tracked directly by + * virObjectEventStateRegisterID(). Return false if @event must not + * be sent to @conn. + */ +typedef bool (*virObjectEventCallbackFilter)(virConnectPtr conn, + virObjectEventPtr event, + void *opaque); + virClassPtr virClassForObjectEvent(void); int +virObjectEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + unsigned char *uuid, + virObjectEventCallbackFilter filter, + void *filter_opaque, + virClassPtr klass, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID, + bool remoteFilter) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(6) + ATTRIBUTE_NONNULL(8); + +int virObjectEventStateCallbackID(virConnectPtr conn, virObjectEventStatePtr state, virClassPtr klass, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3b3de15c3..91d130495 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -634,7 +634,6 @@ virObjectEventStateEventID; virObjectEventStateFree; virObjectEventStateNew; virObjectEventStateQueue; -virObjectEventStateRegisterID; # conf/secret_conf.h diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 61e35165f..4115fffe3 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3654,6 +3654,7 @@ libxlConnectDomainEventRegister(virConnectPtr conn, if (virDomainEventStateRegister(conn, driver->domainEventState, + virConnectDomainEventRegisterCheckACL, callback, opaque, freecb) < 0) return -1; @@ -4259,6 +4260,7 @@ libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eve if (virDomainEventStateRegisterID(conn, driver->domainEventState, + virConnectDomainEventRegisterAnyCheckACL, dom, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 7e56a5953..5ae4b6562 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1293,6 +1293,7 @@ lxcConnectDomainEventRegister(virConnectPtr conn, if (virDomainEventStateRegister(conn, driver->domainEventState, + virConnectDomainEventRegisterCheckACL, callback, opaque, freecb) < 0) return -1; @@ -1334,6 +1335,7 @@ lxcConnectDomainEventRegisterAny(virConnectPtr conn, if (virDomainEventStateRegisterID(conn, driver->domainEventState, + virConnectDomainEventRegisterAnyCheckACL, dom, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 95e4b658d..0b43a67e8 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2310,6 +2310,7 @@ networkConnectNetworkEventRegisterAny(virConnectPtr conn, goto cleanup; if (virNetworkEventStateRegisterID(conn, driver->networkEventState, + virConnectNetworkEventRegisterAnyCheckACL, net, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c index 0dbaa4a87..91b16f8ae 100644 --- a/src/openvz/openvz_conf.c +++ b/src/openvz/openvz_conf.c @@ -136,6 +136,7 @@ openvzParseBarrierLimit(const char* value, char *token; char *saveptr = NULL; char *str; + int ret = -1; if (VIR_STRDUP(str, value) < 0) goto error; @@ -158,10 +159,10 @@ openvzParseBarrierLimit(const char* value, goto error; } } - return 0; + ret = 0; error: VIR_FREE(str); - return -1; + return ret; } diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 32165ed20..3ff3006f9 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -1153,9 +1153,11 @@ phypConnectOpen(virConnectPtr conn, return VIR_DRV_OPEN_SUCCESS; failure: + VIR_FREE(managed_system); + if (phyp_driver != NULL) { virObjectUnref(phyp_driver->caps); - VIR_FREE(phyp_driver->managed_system); + virObjectUnref(phyp_driver->xmlopt); VIR_FREE(phyp_driver); } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1949abee9..ebb77dca0 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9959,6 +9959,7 @@ qemuConnectDomainEventRegister(virConnectPtr conn, if (virDomainEventStateRegister(conn, driver->domainEventState, + virConnectDomainEventRegisterCheckACL, callback, opaque, freecb) < 0) goto cleanup; @@ -10007,6 +10008,7 @@ qemuConnectDomainEventRegisterAny(virConnectPtr conn, if (virDomainEventStateRegisterID(conn, driver->domainEventState, + virConnectDomainEventRegisterAnyCheckACL, dom, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9331744fd..684893977 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -246,6 +246,17 @@ qemuConnectAgent(virQEMUDriverPtr driver, virDomainObjPtr vm) virObjectLock(vm); priv->agentStart = 0; + if (agent == NULL) + virObjectUnref(vm); + + if (!virDomainObjIsActive(vm)) { + qemuAgentClose(agent); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest crashed while connecting to the guest agent")); + ret = -2; + goto cleanup; + } + if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) { VIR_ERROR(_("Failed to clear security context for agent for %s"), @@ -253,13 +264,7 @@ qemuConnectAgent(virQEMUDriverPtr driver, virDomainObjPtr vm) goto cleanup; } - if (agent == NULL) - virObjectUnref(vm); - if (!virDomainObjIsActive(vm)) { - qemuAgentClose(agent); - goto cleanup; - } priv->agent = agent; if (priv->agent == NULL) { @@ -3118,6 +3123,7 @@ qemuProcessReconnect(void *opaque) int reason; virQEMUDriverConfigPtr cfg; size_t i; + int ret; memcpy(&oldjob, &data->oldjob, sizeof(oldjob)); @@ -3142,7 +3148,10 @@ qemuProcessReconnect(void *opaque) goto error; /* Failure to connect to agent shouldn't be fatal */ - if (qemuConnectAgent(driver, obj) < 0) { + if ((ret = qemuConnectAgent(driver, obj)) < 0) { + if (ret == -2) + goto error; + VIR_WARN("Cannot connect to QEMU guest agent for %s", obj->def->name); virResetLastError(); @@ -4016,7 +4025,10 @@ int qemuProcessStart(virConnectPtr conn, goto cleanup; /* Failure to connect to agent shouldn't be fatal */ - if (qemuConnectAgent(driver, vm) < 0) { + if ((ret = qemuConnectAgent(driver, vm)) < 0) { + if (ret == -2) + goto cleanup; + VIR_WARN("Cannot connect to QEMU guest agent for %s", vm->def->name); virResetLastError(); @@ -4476,6 +4488,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virCapsPtr caps = NULL; bool active = false; + int ret; VIR_DEBUG("Beginning VM attach process"); @@ -4590,7 +4603,10 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, goto error; /* Failure to connect to agent shouldn't be fatal */ - if (qemuConnectAgent(driver, vm) < 0) { + if ((ret = qemuConnectAgent(driver, vm)) < 0) { + if (ret == -2) + goto error; + VIR_WARN("Cannot connect to QEMU guest agent for %s", vm->def->name); virResetLastError(); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index da9c1c904..ca86e3c02 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -151,7 +151,7 @@ static void make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virSto static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src); static void make_nonnull_nwfilter(remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src); static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src); -static void remoteEventQueue(struct private_data *priv, virObjectEventPtr event); + /*----------------------------------------------------------------------*/ /* Helper functions for remoteOpen. */ @@ -2923,29 +2923,40 @@ remoteConnectNetworkEventRegisterAny(virConnectPtr conn, int rv = -1; struct private_data *priv = conn->privateData; remote_connect_network_event_register_any_args args; + remote_connect_network_event_register_any_ret ret; int callbackID; int count; + remote_nonnull_network network; remoteDriverLock(priv); - if ((count = virNetworkEventStateRegisterID(conn, priv->eventState, - net, eventID, callback, - opaque, freecb, - &callbackID)) < 0) + if ((count = virNetworkEventStateRegisterClient(conn, priv->eventState, + net, eventID, callback, + opaque, freecb, + &callbackID)) < 0) goto done; /* If this is the first callback for this eventID, we need to enable * events on the server */ if (count == 1) { args.eventID = eventID; + if (net) { + make_nonnull_network(&network, net); + args.net = &network; + } else { + args.net = NULL; + } + memset(&ret, 0, sizeof(ret)); if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY, (xdrproc_t) xdr_remote_connect_network_event_register_any_args, (char *) &args, - (xdrproc_t) xdr_void, (char *)NULL) == -1) { + (xdrproc_t) xdr_remote_connect_network_event_register_any_ret, (char *) &ret) == -1) { virObjectEventStateDeregisterID(conn, priv->eventState, callbackID); goto done; } + virObjectEventStateSetRemote(conn, priv->eventState, callbackID, + ret.callbackID); } rv = callbackID; @@ -2964,12 +2975,13 @@ remoteConnectNetworkEventDeregisterAny(virConnectPtr conn, int rv = -1; remote_connect_network_event_deregister_any_args args; int eventID; + int remoteID; int count; remoteDriverLock(priv); if ((eventID = virObjectEventStateEventID(conn, priv->eventState, - callbackID)) < 0) + callbackID, &remoteID)) < 0) goto done; if ((count = virObjectEventStateDeregisterID(conn, priv->eventState, @@ -2979,7 +2991,7 @@ remoteConnectNetworkEventDeregisterAny(virConnectPtr conn, /* If that was the last callback for this eventID, we need to disable * events on the server */ if (count == 0) { - args.eventID = eventID; + args.callbackID = remoteID; if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY, (xdrproc_t) xdr_remote_connect_network_event_deregister_any_args, (char *) &args, @@ -4415,7 +4427,7 @@ remoteConnectDomainEventRegister(virConnectPtr conn, remoteDriverLock(priv); - if ((count = virDomainEventStateRegister(conn, priv->eventState, + if ((count = virDomainEventStateRegister(conn, priv->eventState, NULL, callback, opaque, freecb)) < 0) goto done; @@ -4467,6 +4479,15 @@ done: static void +remoteEventQueue(struct private_data *priv, virObjectEventPtr event, + int remoteID) +{ + if (event) + virObjectEventStateQueueRemote(priv->eventState, event, remoteID); +} + + +static void remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque) @@ -4484,7 +4505,7 @@ remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventLifecycleNewFromDom(dom, msg->event, msg->detail); virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4506,7 +4527,7 @@ remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventRebootNewFromDom(dom); virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4528,7 +4549,7 @@ remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventRTCChangeNewFromDom(dom, msg->offset); virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4550,7 +4571,7 @@ remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, event = virDomainEventWatchdogNewFromDom(dom, msg->action); virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4575,7 +4596,7 @@ remoteDomainBuildEventIOError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, msg->action); virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4602,7 +4623,7 @@ remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog ATTRIBUTE_UNUSED virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } static void @@ -4625,7 +4646,7 @@ remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } static void @@ -4681,7 +4702,7 @@ remoteDomainBuildEventGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); return; error: @@ -4727,7 +4748,7 @@ remoteDomainBuildEventControlError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4754,7 +4775,7 @@ remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4779,7 +4800,7 @@ remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } static void @@ -4801,7 +4822,7 @@ remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } static void @@ -4823,7 +4844,7 @@ remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4845,7 +4866,7 @@ remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED event = virDomainEventBalloonChangeNewFromDom(dom, msg->actual); virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4868,7 +4889,7 @@ remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4891,7 +4912,7 @@ remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED virDomainFree(dom); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, -1); } @@ -4910,10 +4931,11 @@ remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, if (!net) return; - event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event, msg->detail); + event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event, + msg->detail); virNetworkFree(net); - remoteEventQueue(priv, event); + remoteEventQueue(priv, event, msg->callbackID); } @@ -5223,7 +5245,7 @@ remoteConnectDomainEventRegisterAny(virConnectPtr conn, remoteDriverLock(priv); - if ((count = virDomainEventStateRegisterID(conn, priv->eventState, + if ((count = virDomainEventStateRegisterID(conn, priv->eventState, NULL, dom, eventID, callback, opaque, freecb, &callbackID)) < 0) @@ -5264,7 +5286,7 @@ remoteConnectDomainEventDeregisterAny(virConnectPtr conn, remoteDriverLock(priv); if ((eventID = virObjectEventStateEventID(conn, priv->eventState, - callbackID)) < 0) + callbackID, NULL)) < 0) goto done; if ((count = virObjectEventStateDeregisterID(conn, priv->eventState, @@ -6798,12 +6820,6 @@ done: return rv; } -static void -remoteEventQueue(struct private_data *priv, virObjectEventPtr event) -{ - if (event) - virObjectEventStateQueue(priv->eventState, event); -} /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 563bf3c69..af5b83869 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -5951,6 +5951,8 @@ xdr_remote_connect_network_event_register_any_args (XDR *xdrs, remote_connect_ne if (!xdr_int (xdrs, &objp->eventID)) return FALSE; + if (!xdr_remote_network (xdrs, &objp->net)) + return FALSE; return TRUE; } @@ -5958,7 +5960,7 @@ bool_t xdr_remote_connect_network_event_register_any_ret (XDR *xdrs, remote_connect_network_event_register_any_ret *objp) { - if (!xdr_int (xdrs, &objp->cb_registered)) + if (!xdr_int (xdrs, &objp->callbackID)) return FALSE; return TRUE; } @@ -5967,16 +5969,7 @@ bool_t xdr_remote_connect_network_event_deregister_any_args (XDR *xdrs, remote_connect_network_event_deregister_any_args *objp) { - if (!xdr_int (xdrs, &objp->eventID)) - return FALSE; - return TRUE; -} - -bool_t -xdr_remote_connect_network_event_deregister_any_ret (XDR *xdrs, remote_connect_network_event_deregister_any_ret *objp) -{ - - if (!xdr_int (xdrs, &objp->cb_registered)) + if (!xdr_int (xdrs, &objp->callbackID)) return FALSE; return TRUE; } @@ -5985,6 +5978,8 @@ bool_t xdr_remote_network_event_lifecycle_msg (XDR *xdrs, remote_network_event_lifecycle_msg *objp) { + if (!xdr_int (xdrs, &objp->callbackID)) + return FALSE; if (!xdr_remote_nonnull_network (xdrs, &objp->net)) return FALSE; if (!xdr_int (xdrs, &objp->event)) diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index 7d8c5d20f..fbce91307 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -3411,25 +3411,22 @@ typedef struct remote_connect_get_cpu_model_names_ret remote_connect_get_cpu_mod struct remote_connect_network_event_register_any_args { int eventID; + remote_network net; }; typedef struct remote_connect_network_event_register_any_args remote_connect_network_event_register_any_args; struct remote_connect_network_event_register_any_ret { - int cb_registered; + int callbackID; }; typedef struct remote_connect_network_event_register_any_ret remote_connect_network_event_register_any_ret; struct remote_connect_network_event_deregister_any_args { - int eventID; + int callbackID; }; typedef struct remote_connect_network_event_deregister_any_args remote_connect_network_event_deregister_any_args; -struct remote_connect_network_event_deregister_any_ret { - int cb_registered; -}; -typedef struct remote_connect_network_event_deregister_any_ret remote_connect_network_event_deregister_any_ret; - struct remote_network_event_lifecycle_msg { + int callbackID; remote_nonnull_network net; int event; int detail; @@ -4269,7 +4266,6 @@ extern bool_t xdr_remote_connect_get_cpu_model_names_ret (XDR *, remote_connect extern bool_t xdr_remote_connect_network_event_register_any_args (XDR *, remote_connect_network_event_register_any_args*); extern bool_t xdr_remote_connect_network_event_register_any_ret (XDR *, remote_connect_network_event_register_any_ret*); extern bool_t xdr_remote_connect_network_event_deregister_any_args (XDR *, remote_connect_network_event_deregister_any_args*); -extern bool_t xdr_remote_connect_network_event_deregister_any_ret (XDR *, remote_connect_network_event_deregister_any_ret*); extern bool_t xdr_remote_network_event_lifecycle_msg (XDR *, remote_network_event_lifecycle_msg*); extern bool_t xdr_remote_procedure (XDR *, remote_procedure*); @@ -4783,7 +4779,6 @@ extern bool_t xdr_remote_connect_get_cpu_model_names_ret (); extern bool_t xdr_remote_connect_network_event_register_any_args (); extern bool_t xdr_remote_connect_network_event_register_any_ret (); extern bool_t xdr_remote_connect_network_event_deregister_any_args (); -extern bool_t xdr_remote_connect_network_event_deregister_any_ret (); extern bool_t xdr_remote_network_event_lifecycle_msg (); extern bool_t xdr_remote_procedure (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index c3d544fe2..f94a38a63 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3,7 +3,7 @@ * remote_internal driver and libvirtd. This protocol is * internal and may change at any time. * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1955,7 +1955,7 @@ struct remote_node_device_destroy_args { /* * Events Register/Deregister: - * It would seem rpcgen does not like both args, and ret + * It would seem rpcgen does not like both args and ret * to be null. It will not generate the prototype otherwise. * Pass back a redundant boolean to force prototype generation. */ @@ -2851,21 +2851,19 @@ struct remote_connect_get_cpu_model_names_ret { struct remote_connect_network_event_register_any_args { int eventID; + remote_network net; }; struct remote_connect_network_event_register_any_ret { - int cb_registered; + int callbackID; }; struct remote_connect_network_event_deregister_any_args { - int eventID; -}; - -struct remote_connect_network_event_deregister_any_ret { - int cb_registered; + int callbackID; }; struct remote_network_event_lifecycle_msg { + int callbackID; remote_nonnull_network net; int event; int detail; @@ -3644,7 +3642,8 @@ enum remote_procedure { /** * @generate: none * @priority: high - * @acl: connect:read + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER = 105, @@ -4076,7 +4075,8 @@ enum remote_procedure { /** * @generate: none * @priority: high - * @acl: connect:read + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER_ANY = 167, @@ -5047,7 +5047,8 @@ enum remote_procedure { /** * @generate: none * @priority: high - * @acl: connect:read + * @acl: connect:search_networks + * @aclfilter: network:getattr */ REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY = 313, diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 7373d6573..e58482e7f 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2330,17 +2330,16 @@ struct remote_connect_get_cpu_model_names_ret { }; struct remote_connect_network_event_register_any_args { int eventID; + remote_network net; }; struct remote_connect_network_event_register_any_ret { - int cb_registered; + int callbackID; }; struct remote_connect_network_event_deregister_any_args { - int eventID; -}; -struct remote_connect_network_event_deregister_any_ret { - int cb_registered; + int callbackID; }; struct remote_network_event_lifecycle_msg { + int callbackID; remote_nonnull_network net; int event; int detail; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index b724f82b0..4c277bdd3 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -6145,7 +6145,7 @@ testConnectDomainEventRegister(virConnectPtr conn, int ret = 0; testDriverLock(driver); - if (virDomainEventStateRegister(conn, driver->eventState, + if (virDomainEventStateRegister(conn, driver->eventState, NULL, callback, opaque, freecb) < 0) ret = -1; testDriverUnlock(driver); @@ -6183,7 +6183,7 @@ testConnectDomainEventRegisterAny(virConnectPtr conn, int ret; testDriverLock(driver); - if (virDomainEventStateRegisterID(conn, driver->eventState, + if (virDomainEventStateRegisterID(conn, driver->eventState, NULL, dom, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; @@ -6221,7 +6221,7 @@ testConnectNetworkEventRegisterAny(virConnectPtr conn, int ret; testDriverLock(driver); - if (virNetworkEventStateRegisterID(conn, driver->eventState, + if (virNetworkEventStateRegisterID(conn, driver->eventState, NULL, net, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index ad29ebfb7..31ebf4ab6 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2618,6 +2618,7 @@ umlConnectDomainEventRegister(virConnectPtr conn, umlDriverLock(driver); if (virDomainEventStateRegister(conn, driver->domainEventState, + virConnectDomainEventRegisterCheckACL, callback, opaque, freecb) < 0) ret = -1; umlDriverUnlock(driver); @@ -2662,6 +2663,7 @@ umlConnectDomainEventRegisterAny(virConnectPtr conn, umlDriverLock(driver); if (virDomainEventStateRegisterID(conn, driver->domainEventState, + virConnectDomainEventRegisterAnyCheckACL, dom, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; diff --git a/src/util/virxml.c b/src/util/virxml.c index 58523745c..dd530a692 100644 --- a/src/util/virxml.c +++ b/src/util/virxml.c @@ -1047,6 +1047,8 @@ virXMLExtractNamespaceXML(xmlNodePtr root, cleanup: if (doc) *doc = xmlstr; + else + VIR_FREE(xmlstr); xmlFreeNode(nodeCopy); return ret; } diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 0fcaf8e70..241eb5e47 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -7328,7 +7328,7 @@ vboxConnectDomainEventRegister(virConnectPtr conn, * later you can iterate over them */ - ret = virDomainEventStateRegister(conn, data->domainEvents, + ret = virDomainEventStateRegister(conn, data->domainEvents, NULL, callback, opaque, freecb); VIR_DEBUG("virObjectEventStateRegister (ret = %d) (conn: %p, " "callback: %p, opaque: %p, " @@ -7425,7 +7425,7 @@ static int vboxConnectDomainEventRegisterAny(virConnectPtr conn, * later you can iterate over them */ - if (virDomainEventStateRegisterID(conn, data->domainEvents, + if (virDomainEventStateRegisterID(conn, data->domainEvents, NULL, dom, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index c45d10f95..7a57624b6 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2323,6 +2323,7 @@ xenUnifiedConnectDomainEventRegister(virConnectPtr conn, } if (virDomainEventStateRegister(conn, priv->domainEvents, + virConnectDomainEventRegisterCheckACL, callback, opaque, freefunc) < 0) ret = -1; @@ -2382,6 +2383,7 @@ xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn, } if (virDomainEventStateRegisterID(conn, priv->domainEvents, + virConnectDomainEventRegisterAnyCheckACL, dom, eventID, callback, opaque, freefunc, &ret) < 0) ret = -1; |