summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2014-01-16 22:33:43 +0100
committerGuido Günther <agx@sigxcpu.org>2014-01-16 22:33:43 +0100
commit22e83d797960efd261a6188c1ebe42b169fcbc86 (patch)
tree2d0dc63f3c54a1f91fdd3ff7f6e88c9160f642ab /src
parentfef0f8f1ad69b37558ffa8d80d43e8626817130c (diff)
New upstream version 1.2.1
Diffstat (limited to 'src')
-rw-r--r--src/access/org.libvirt.api.policy4
-rw-r--r--src/access/viraccessapicheck.c66
-rw-r--r--src/access/viraccessapicheck.h3
-rw-r--r--src/access/viraccessperm.h6
-rw-r--r--src/conf/domain_event.c38
-rw-r--r--src/conf/domain_event.h10
-rw-r--r--src/conf/network_event.c69
-rw-r--r--src/conf/network_event.h18
-rw-r--r--src/conf/object_event.c212
-rw-r--r--src/conf/object_event.h30
-rw-r--r--src/conf/object_event_private.h31
-rw-r--r--src/libvirt_private.syms1
-rw-r--r--src/libxl/libxl_driver.c2
-rw-r--r--src/lxc/lxc_driver.c2
-rw-r--r--src/network/bridge_driver.c1
-rw-r--r--src/openvz/openvz_conf.c5
-rw-r--r--src/phyp/phyp_driver.c4
-rw-r--r--src/qemu/qemu_driver.c2
-rw-r--r--src/qemu/qemu_process.c34
-rw-r--r--src/remote/remote_driver.c86
-rw-r--r--src/remote/remote_protocol.c17
-rw-r--r--src/remote/remote_protocol.h13
-rw-r--r--src/remote/remote_protocol.x23
-rw-r--r--src/remote_protocol-structs9
-rw-r--r--src/test/test_driver.c6
-rw-r--r--src/uml/uml_driver.c2
-rw-r--r--src/util/virxml.c2
-rw-r--r--src/vbox/vbox_tmpl.c4
-rw-r--r--src/xen/xen_driver.c2
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;