On 07/20/2016 09:50 AM, Jovanka Gulicoska wrote:
---
daemon/libvirtd.h | 2 +
daemon/remote.c | 206 +++++++++++++++++++++++++++++++++++++++++++
src/remote/remote_driver.c | 139 +++++++++++++++++++++++++++++
src/remote/remote_protocol.x | 43 ++++++++-
src/remote_protocol-structs | 19 ++++
5 files changed, 408 insertions(+), 1 deletion(-)
diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index cc91266..09d505d 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -62,6 +62,8 @@ struct daemonClientPrivate {
size_t nqemuEventCallbacks;
daemonClientEventCallbackPtr *storageEventCallbacks;
size_t nstorageEventCallbacks;
+ daemonClientEventCallbackPtr *nodeDeviceEventCallbacks;
+ size_t nnodeDeviceEventCallbacks;
bool closeRegistered;
# if WITH_SASL
diff --git a/daemon/remote.c b/daemon/remote.c
index 4aa43c2..d07cacd 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -91,6 +91,7 @@ static virStorageVolPtr get_nonnull_storage_vol(virConnectPtr conn,
remote_nonnu
static virSecretPtr get_nonnull_secret(virConnectPtr conn, remote_nonnull_secret
secret);
static virNWFilterPtr get_nonnull_nwfilter(virConnectPtr conn, remote_nonnull_nwfilter
nwfilter);
static virDomainSnapshotPtr get_nonnull_domain_snapshot(virDomainPtr dom,
remote_nonnull_domain_snapshot snapshot);
+static virNodeDevicePtr get_nonnull_node_device(virConnectPtr conn,
remote_nonnull_node_device dev);
static void make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
static void make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr
net_src);
static void make_nonnull_interface(remote_nonnull_interface *interface_dst,
virInterfacePtr interface_src);
@@ -209,6 +210,32 @@ remoteRelayStoragePoolEventCheckACL(virNetServerClientPtr client,
}
static bool
+remoteRelayNodeDeviceEventCheckACL(virNetServerClientPtr client,
+ virConnectPtr conn,
+ virNodeDevicePtr dev)
+{
+ virNodeDeviceDef def;
+ virIdentityPtr identity = NULL;
+ bool ret = false;
+
+ /* For now, we just create a virNodeDeviceDef with enough contents to
+ * satisfy what viraccessdriverpolkit.c references. This is a bit
+ * fragile, but I don't know of anything better. */
+ def.name = dev->name;
+
+ if (!(identity = virNetServerClientGetIdentity(client)))
+ goto cleanup;
+ if (virIdentitySetCurrent(identity) < 0)
+ goto cleanup;
+ ret = virConnectNodeDeviceEventRegisterAnyCheckACL(conn, &def);
+
+ cleanup:
+ ignore_value(virIdentitySetCurrent(NULL));
+ virObjectUnref(identity);
+ return ret;
+}
+
+static bool
remoteRelayDomainQemuMonitorEventCheckACL(virNetServerClientPtr client,
virConnectPtr conn, virDomainPtr dom)
{
@@ -1329,6 +1356,44 @@ static virConnectStoragePoolEventGenericCallback
storageEventCallbacks[] = {
verify(ARRAY_CARDINALITY(storageEventCallbacks) == VIR_STORAGE_POOL_EVENT_ID_LAST);
+static int
+remoteRelayNodeDeviceEventLifecycle(virConnectPtr conn,
+ virNodeDevicePtr dev,
+ int event,
+ int detail,
+ void *opaque)
+{
+ daemonClientEventCallbackPtr callback = opaque;
+ remote_node_device_event_lifecycle_msg data;
+
+ if (callback->callbackID < 0 ||
+ !remoteRelayNodeDeviceEventCheckACL(callback->client, conn, dev))
+ return -1;
+
+ VIR_DEBUG("Relaying node device lifecycle event %d, detail %d, callback
%d",
+ event, detail, callback->callbackID);
+
+ /* build return data */
+ memset(&data, 0, sizeof(data));
+ make_nonnull_node_device(&data.dev, dev);
+ data.callbackID = callback->callbackID;
+ data.event = event;
+ data.detail = detail;
+
+ remoteDispatchObjectEventSend(callback->client, remoteProgram,
+ REMOTE_PROC_NODE_DEVICE_EVENT_LIFECYCLE,
+
(xdrproc_t)xdr_remote_node_device_event_lifecycle_msg,
+ &data);
+
+ return 0;
+}
+
+static virConnectNodeDeviceEventGenericCallback nodeDeviceEventCallbacks[] = {
+ VIR_NODE_DEVICE_EVENT_CALLBACK(remoteRelayNodeDeviceEventLifecycle),
+};
+
+verify(ARRAY_CARDINALITY(nodeDeviceEventCallbacks) == VIR_NODE_DEVICE_EVENT_ID_LAST);
+
static void
remoteRelayDomainQemuMonitorEvent(virConnectPtr conn,
virDomainPtr dom,
@@ -1451,6 +1516,21 @@ void remoteClientFreeFunc(void *data)
}
VIR_FREE(priv->storageEventCallbacks);
+ for (i = 0; i < priv->nnodeDeviceEventCallbacks; i++) {
+ int callbackID = priv->nodeDeviceEventCallbacks[i]->callbackID;
+ if (callbackID < 0) {
+ VIR_WARN("unexpected incomplete node device callback %zu",
i);
+ continue;
+ }
+ VIR_DEBUG("Deregistering remote node device event relay %d",
+ callbackID);
+ priv->nodeDeviceEventCallbacks[i]->callbackID = -1;
+ if (virConnectNodeDeviceEventDeregisterAny(priv->conn,
+ callbackID) < 0)
+ VIR_WARN("unexpected node device event deregister failure");
+ }
+ VIR_FREE(priv->nodeDeviceEventCallbacks);
+
for (i = 0; i < priv->nqemuEventCallbacks; i++) {
int callbackID = priv->qemuEventCallbacks[i]->callbackID;
if (callbackID < 0) {
@@ -5656,6 +5736,126 @@
remoteDispatchConnectStoragePoolEventDeregisterAny(virNetServerPtr server ATTRIB
return rv;
}
+static int
+remoteDispatchConnectNodeDeviceEventRegisterAny(virNetServerPtr server
ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr
ATTRIBUTE_UNUSED,
+
remote_connect_node_device_event_register_any_args *args,
+
remote_connect_node_device_event_register_any_ret *ret)
+{
+ int callbackID;
+ int rv = -1;
+ daemonClientEventCallbackPtr callback = NULL;
+ daemonClientEventCallbackPtr ref;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+ virNodeDevicePtr dev = NULL;
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not
open"));
+ goto cleanup;
+ }
+
+ virMutexLock(&priv->lock);
+
+ if (args->dev &&
+ !(dev = get_nonnull_node_device(priv->conn, *args->dev)))
+ goto cleanup;
+
+ if (args->eventID >= VIR_NODE_DEVICE_EVENT_ID_LAST || args->eventID < 0)
{
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unsupported storage pool event ID %d"),
args->eventID);
+ goto cleanup;
+ }
Error message mentions storage
Otherwise the rest looks fine to me
- Cole