[libvirt] [v3 31/32] Add network events to the remote driver

Cédric Bosdonnat cbosdonnat at suse.com
Mon Dec 2 16:39:49 UTC 2013


---
 daemon/libvirtd.h            |   1 +
 daemon/remote.c              | 140 +++++++++++++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c   | 127 +++++++++++++++++++++++++++++++++++++++
 src/remote/remote_protocol.x |  46 +++++++++++++-
 4 files changed, 313 insertions(+), 1 deletion(-)

diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index d0afdc8..47f2589 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -50,6 +50,7 @@ struct daemonClientPrivate {
     virMutex lock;
 
     int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST];
+    int networkEventCallbackID[VIR_NETWORK_EVENT_ID_LAST];
 
 # if WITH_SASL
     virNetSASLSessionPtr sasl;
diff --git a/daemon/remote.c b/daemon/remote.c
index f060006..d14b0f3 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -49,6 +49,7 @@
 #include "qemu_protocol.h"
 #include "lxc_protocol.h"
 #include "virstring.h"
+#include "object_event.h"
 
 #define VIR_FROM_THIS VIR_FROM_RPC
 
@@ -653,6 +654,37 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
 
+static int remoteRelayNetworkEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                           virNetworkPtr net,
+                                           int event,
+                                           void *opaque)
+{
+    virNetServerClientPtr client = opaque;
+    remote_network_event_lifecycle_msg data;
+
+    if (!client)
+        return -1;
+
+    VIR_DEBUG("Relaying network lifecycle event %d", event);
+
+    /* build return data */
+    memset(&data, 0, sizeof(data));
+    make_nonnull_network(&data.net, net);
+    data.event = event;
+
+    remoteDispatchObjectEventSend(client, remoteProgram,
+                                  REMOTE_PROC_NETWORK_EVENT_LIFECYCLE,
+                                  (xdrproc_t)xdr_remote_network_event_lifecycle_msg, &data);
+
+    return 0;
+}
+
+static virConnectNetworkEventGenericCallback networkEventCallbacks[] = {
+    VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle),
+};
+
+verify(ARRAY_CARDINALITY(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST);
+
 /*
  * You must hold lock for at least the client
  * We don't free stuff here, merely disconnect the client's
@@ -680,6 +712,15 @@ void remoteClientFreeFunc(void *data)
             priv->domainEventCallbackID[i] = -1;
         }
 
+        for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++) {
+            if (priv->networkEventCallbackID[i] != -1) {
+                VIR_DEBUG("Deregistering to relay remote events %zu", i);
+                virConnectNetworkEventDeregisterAny(priv->conn,
+                                                    priv->networkEventCallbackID[i]);
+            }
+            priv->networkEventCallbackID[i] = -1;
+        }
+
         virConnectClose(priv->conn);
 
         virIdentitySetCurrent(NULL);
@@ -716,6 +757,9 @@ void *remoteClientInitHook(virNetServerClientPtr client,
     for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++)
         priv->domainEventCallbackID[i] = -1;
 
+    for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++)
+        priv->networkEventCallbackID[i] = -1;
+
     virNetServerClientSetCloseHook(client, remoteClientCloseFunc);
     return priv;
 }
@@ -5216,6 +5260,102 @@ cleanup:
 }
 
 
+static int
+remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                             virNetServerClientPtr client ATTRIBUTE_UNUSED,
+                                             virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                             virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED,
+                                             remote_connect_network_event_register_any_args *args,
+                                             remote_connect_network_event_register_any_ret *ret ATTRIBUTE_UNUSED)
+{
+    int callbackID;
+    int rv = -1;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    virMutexLock(&priv->lock);
+
+    if ((args->eventID & 0xFF) >= VIR_NETWORK_EVENT_ID_LAST ||
+        ((args->eventID & 0xFF00) >> 8) != VIR_EVENT_NAMESPACE_NETWORK) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID);
+        goto cleanup;
+    }
+
+    if (priv->networkEventCallbackID[args->eventID & 0xFF] != -1)  {
+        virReportError(VIR_ERR_INTERNAL_ERROR, _("network event %d already registered"), args->eventID);
+        goto cleanup;
+    }
+
+    if ((callbackID = virConnectNetworkEventRegisterAny(priv->conn,
+                                                        NULL,
+                                                        args->eventID,
+                                                        networkEventCallbacks[args->eventID & 0xFF],
+                                                        client, NULL)) < 0)
+        goto cleanup;
+
+    priv->networkEventCallbackID[args->eventID & 0xFF] = callbackID;
+
+    rv = 0;
+
+cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    virMutexUnlock(&priv->lock);
+    return rv;
+}
+
+
+static int
+remoteDispatchConnectNetworkEventDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                               virNetServerClientPtr client ATTRIBUTE_UNUSED,
+                                               virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                               virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED,
+                                               remote_connect_network_event_deregister_any_args *args,
+                                               remote_connect_network_event_deregister_any_ret *ret ATTRIBUTE_UNUSED)
+{
+    int callbackID = -1;
+    int rv = -1;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    virMutexLock(&priv->lock);
+
+    if ((args->eventID & 0xFF) >= VIR_NETWORK_EVENT_ID_LAST ||
+        ((args->eventID & 0xFF00) >> 8) != VIR_EVENT_NAMESPACE_NETWORK) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID);
+        goto cleanup;
+    }
+
+    callbackID = priv->networkEventCallbackID[args->eventID & 0xFF];
+    if (callbackID < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, _("network event %d not registered"), args->eventID);
+        goto cleanup;
+    }
+
+    if (virConnectNetworkEventDeregisterAny(priv->conn, callbackID) < 0)
+        goto cleanup;
+
+    priv->networkEventCallbackID[args->eventID & 0xFF] = -1;
+
+    rv = 0;
+
+cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    virMutexUnlock(&priv->lock);
+    return rv;
+}
+
 
 /*----- Helpers. -----*/
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 4a84a52..046f424 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -33,6 +33,7 @@
 #include "virlog.h"
 #include "datatypes.h"
 #include "domain_event.h"
+#include "network_event.h"
 #include "driver.h"
 #include "virbuffer.h"
 #include "remote_driver.h"
@@ -273,6 +274,11 @@ remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog,
                                     virNetClientPtr client,
                                     void *evdata, void *opaque);
 
+static void
+remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                                 virNetClientPtr client ATTRIBUTE_UNUSED,
+                                 void *evdata, void *opaque);
+
 static virNetClientProgramEvent remoteDomainEvents[] = {
     { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
       remoteDomainBuildEventRTCChange,
@@ -338,6 +344,10 @@ static virNetClientProgramEvent remoteDomainEvents[] = {
       remoteDomainBuildEventDeviceRemoved,
       sizeof(remote_domain_event_device_removed_msg),
       (xdrproc_t)xdr_remote_domain_event_device_removed_msg },
+    { REMOTE_PROC_NETWORK_EVENT_LIFECYCLE,
+      remoteNetworkBuildEventLifecycle,
+      sizeof(remote_network_event_lifecycle_msg),
+      (xdrproc_t)xdr_remote_network_event_lifecycle_msg },
 };
 
 enum virDrvOpenRemoteFlags {
@@ -2902,6 +2912,99 @@ done:
 }
 
 static int
+remoteConnectNetworkEventRegisterAny(virConnectPtr conn,
+                                     virNetworkPtr net,
+                                     int eventID,
+                                     virConnectNetworkEventGenericCallback callback,
+                                     void *opaque,
+                                     virFreeCallback freecb)
+{
+    int rv = -1;
+    struct private_data *priv = conn->privateData;
+    remote_connect_network_event_register_any_args args;
+    int callbackID;
+    int count;
+
+    remoteDriverLock(priv);
+
+    if ((count = virNetworkEventStateRegisterID(conn,
+                                               priv->domainEventState,
+                                               net, eventID,
+                                               VIR_OBJECT_EVENT_CALLBACK(callback),
+                                               opaque, freecb,
+                                               &callbackID)) < 0) {
+        virReportError(VIR_ERR_RPC, "%s", _("adding cb to list"));
+        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 (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) {
+            virObjectEventStateDeregisterID(conn,
+                                            priv->domainEventState,
+                                            callbackID);
+            goto done;
+        }
+    }
+
+    rv = callbackID;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+
+static int
+remoteConnectNetworkEventDeregisterAny(virConnectPtr conn,
+                                       int callbackID)
+{
+    struct private_data *priv = conn->privateData;
+    int rv = -1;
+    remote_connect_network_event_deregister_any_args args;
+    int eventID;
+    int count;
+
+    remoteDriverLock(priv);
+
+    if ((eventID = virObjectEventStateEventID(conn,
+                                              priv->domainEventState,
+                                              callbackID)) < 0) {
+        virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
+        goto done;
+    }
+
+    if ((count = virObjectEventStateDeregisterID(conn,
+                                                 priv->domainEventState,
+                                                 callbackID)) < 0) {
+        virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
+        goto done;
+    }
+
+    /* If that was the last callback for this eventID, we need to disable
+     * events on the server */
+    if (count == 0) {
+        args.eventID = eventID;
+
+        if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY,
+                 (xdrproc_t) xdr_remote_connect_network_event_deregister_any_args, (char *) &args,
+                 (xdrproc_t) xdr_void, (char *) NULL) == -1)
+            goto done;
+    }
+
+    rv = 0;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static int
 remoteConnectListAllInterfaces(virConnectPtr conn,
                                virInterfacePtr **ifaces,
                                unsigned int flags)
@@ -4800,6 +4903,28 @@ remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED
 }
 
 
+static void
+remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                                 virNetClientPtr client ATTRIBUTE_UNUSED,
+                                 void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    struct private_data *priv = conn->privateData;
+    remote_network_event_lifecycle_msg *msg = evdata;
+    virNetworkPtr net;
+    virObjectEventPtr event = NULL;
+
+    net = get_nonnull_network(conn, msg->net);
+    if (!net)
+        return;
+
+    event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event);
+    virNetworkFree(net);
+
+    remoteDomainEventQueue(priv, event);
+}
+
+
 static virDrvOpenStatus ATTRIBUTE_NONNULL(1)
 remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
                  unsigned int flags)
@@ -7035,6 +7160,8 @@ static virNetworkDriver network_driver = {
     .connectNumOfDefinedNetworks = remoteConnectNumOfDefinedNetworks, /* 0.3.0 */
     .connectListDefinedNetworks = remoteConnectListDefinedNetworks, /* 0.3.0 */
     .connectListAllNetworks = remoteConnectListAllNetworks, /* 0.10.2 */
+    .connectNetworkEventDeregisterAny = remoteConnectNetworkEventDeregisterAny, /* 1.2.1 */
+    .connectNetworkEventRegisterAny = remoteConnectNetworkEventRegisterAny, /* 1.2.1 */
     .networkLookupByUUID = remoteNetworkLookupByUUID, /* 0.3.0 */
     .networkLookupByName = remoteNetworkLookupByName, /* 0.3.0 */
     .networkCreateXML = remoteNetworkCreateXML, /* 0.3.0 */
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index f942670..c3d544f 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2849,6 +2849,30 @@ struct remote_connect_get_cpu_model_names_ret {
     int ret;
 };
 
+struct remote_connect_network_event_register_any_args {
+    int eventID;
+};
+
+struct remote_connect_network_event_register_any_ret {
+    int cb_registered;
+};
+
+struct remote_connect_network_event_deregister_any_args {
+    int eventID;
+};
+
+struct remote_connect_network_event_deregister_any_ret {
+    int cb_registered;
+};
+
+struct remote_network_event_lifecycle_msg {
+    remote_nonnull_network net;
+    int event;
+    int detail;
+};
+
+
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -5018,5 +5042,25 @@ enum remote_procedure {
      * @generate: none
      * @acl: connect:read
      */
-    REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312
+    REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312,
+
+    /**
+     * @generate: none
+     * @priority: high
+     * @acl: connect:read
+     */
+    REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY = 313,
+
+    /**
+     * @generate: none
+     * @priority: high
+     * @acl: connect:read
+     */
+    REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY = 314,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315
 };
-- 
1.8.4.4




More information about the libvir-list mailing list