
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