[libvirt] [PATCH 5/9] remote: implement node device lifecycle event APIs

Cole Robinson crobinso at redhat.com
Tue Jul 26 19:35:17 UTC 2016


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




More information about the libvir-list mailing list