[libvirt] [PATCH v5 09/10] daemon: add connection close rpc

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Wed Feb 17 12:15:02 UTC 2016


Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
---
 daemon/libvirtd.h            |  1 +
 daemon/remote.c              | 85 ++++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_internal.h       |  5 +++
 src/remote/remote_driver.c   | 40 +++++++++++++++++++++
 src/remote/remote_protocol.x | 24 ++++++++++++-
 src/remote_protocol-structs  |  6 ++++
 6 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index efd4823..7271b0f 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -60,6 +60,7 @@ struct daemonClientPrivate {
     size_t nnetworkEventCallbacks;
     daemonClientEventCallbackPtr *qemuEventCallbacks;
     size_t nqemuEventCallbacks;
+    bool closeRegistered;
 
 # if WITH_SASL
     virNetSASLSessionPtr sasl;
diff --git a/daemon/remote.c b/daemon/remote.c
index ca692a9..04d8ada 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -1208,6 +1208,20 @@ remoteRelayDomainQemuMonitorEvent(virConnectPtr conn,
     VIR_FREE(details_p);
 }
 
+static
+void remoteRelayConnectionClosedEvent(virConnectPtr conn ATTRIBUTE_UNUSED, int reason, void *opaque)
+{
+    virNetServerClientPtr client = opaque;
+
+    VIR_DEBUG("Relaying connection closed event, reason %d", reason);
+
+    remote_connect_event_connection_closed_msg msg = { reason };
+    remoteDispatchObjectEventSend(client, remoteProgram,
+                                  REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED,
+                                  (xdrproc_t)xdr_remote_connect_event_connection_closed_msg,
+                                  &msg);
+}
+
 /*
  * You must hold lock for at least the client
  * We don't free stuff here, merely disconnect the client's
@@ -1270,6 +1284,12 @@ void remoteClientFreeFunc(void *data)
         }
         VIR_FREE(priv->qemuEventCallbacks);
 
+        if (priv->closeRegistered) {
+            if (virConnectUnregisterCloseCallback(priv->conn,
+                                                  remoteRelayConnectionClosedEvent) < 0)
+                VIR_WARN("unexpected close callback event deregister failure");
+        }
+
         virConnectClose(priv->conn);
 
         virIdentitySetCurrent(NULL);
@@ -3345,6 +3365,70 @@ remoteDispatchNodeDeviceGetParent(virNetServerPtr server ATTRIBUTE_UNUSED,
     return rv;
 }
 
+static int
+remoteDispatchConnectCloseCallbackRegister(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                           virNetServerClientPtr client,
+                                           virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                           virNetMessageErrorPtr rerr)
+{
+    int rv = -1;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    virMutexLock(&priv->lock);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    // on behalf of close callback
+    virObjectRef(client);
+    if (virConnectRegisterCloseCallback(priv->conn,
+                                        remoteRelayConnectionClosedEvent,
+                                        client, virObjectFreeCallback) < 0)
+        goto cleanup;
+
+    priv->closeRegistered = true;
+    rv = 0;
+
+ cleanup:
+    virMutexUnlock(&priv->lock);
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    return rv;
+}
+
+static int
+remoteDispatchConnectCloseCallbackUnregister(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                             virNetServerClientPtr client,
+                                             virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                             virNetMessageErrorPtr rerr)
+{
+    int rv = -1;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    virMutexLock(&priv->lock);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    if (virConnectUnregisterCloseCallback(priv->conn,
+                                          remoteRelayConnectionClosedEvent) < 0)
+        goto cleanup;
+
+    priv->closeRegistered = false;
+    rv = 0;
+
+ cleanup:
+    virMutexUnlock(&priv->lock);
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    return rv;
+}
 
 /***************************
  * Register / deregister events
@@ -4145,6 +4229,7 @@ static int remoteDispatchConnectSupportsFeature(virNetServerPtr server ATTRIBUTE
     switch (args->feature) {
     case VIR_DRV_FEATURE_FD_PASSING:
     case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+    case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
         supported = 1;
         break;
 
diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h
index 1313b58..96439d8 100644
--- a/src/libvirt_internal.h
+++ b/src/libvirt_internal.h
@@ -118,6 +118,11 @@ enum {
      * Support for server-side event filtering via callback ids in events.
      */
     VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK = 14,
+
+    /*
+     * Support for driver close callback rpc
+     */
+    VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK = 15,
 };
 
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 363c367..d84d2c1 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -94,6 +94,7 @@ struct private_data {
     char *hostname;             /* Original hostname */
     bool serverKeepAlive;       /* Does server support keepalive protocol? */
     bool serverEventFilter;     /* Does server support modern event filtering */
+    bool serverCloseCallback;   /* Does server support driver close callback */
 
     virObjectEventStatePtr eventState;
     virConnectCloseCallbackDataPtr closeCallback;
@@ -347,6 +348,11 @@ remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
                                  virNetClientPtr client ATTRIBUTE_UNUSED,
                                  void *evdata, void *opaque);
 
+static void
+remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                                         virNetClientPtr client ATTRIBUTE_UNUSED,
+                                         void *evdata, void *opaque);
+
 static virNetClientProgramEvent remoteEvents[] = {
     { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
       remoteDomainBuildEventLifecycle,
@@ -509,8 +515,23 @@ static virNetClientProgramEvent remoteEvents[] = {
       remoteDomainBuildEventCallbackMigrationIteration,
       sizeof(remote_domain_event_callback_migration_iteration_msg),
       (xdrproc_t)xdr_remote_domain_event_callback_migration_iteration_msg },
+    { REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED,
+      remoteConnectNotifyEventConnectionClosed,
+      sizeof(remote_connect_event_connection_closed_msg),
+      (xdrproc_t)xdr_remote_connect_event_connection_closed_msg },
 };
 
+static void
+remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                                         virNetClientPtr client ATTRIBUTE_UNUSED,
+                                         void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    struct private_data *priv = conn->privateData;
+    remote_connect_event_connection_closed_msg *msg = evdata;
+
+    virConnectCloseCallbackDataCall(priv->closeCallback, msg->reason);
+}
 
 static void
 remoteDomainBuildQemuMonitorEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
@@ -1067,6 +1088,13 @@ doRemoteOpen(virConnectPtr conn,
                  "supported by the server");
     }
 
+    priv->serverCloseCallback = remoteConnectSupportsFeatureUnlocked(conn,
+                                    priv, VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK);
+    if (!priv->serverCloseCallback) {
+        VIR_INFO("Close callback registering isn't supported "
+                 "by the remote side.");
+    }
+
     /* Successful. */
     retcode = VIR_DRV_OPEN_SUCCESS;
 
@@ -7908,6 +7936,12 @@ remoteConnectRegisterCloseCallback(virConnectPtr conn,
         goto cleanup;
     }
 
+    if (priv->serverCloseCallback &&
+        call(conn, priv, 0, REMOTE_PROC_CONNECT_CLOSE_CALLBACK_REGISTER,
+             (xdrproc_t) xdr_void, (char *) NULL,
+             (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        goto cleanup;
+
     virConnectCloseCallbackDataRegister(priv->closeCallback, conn, cb,
                                         opaque, freecb);
     ret = 0;
@@ -7933,6 +7967,12 @@ remoteConnectUnregisterCloseCallback(virConnectPtr conn,
         goto cleanup;
     }
 
+    if (priv->serverCloseCallback &&
+        call(conn, priv, 0, REMOTE_PROC_CONNECT_CLOSE_CALLBACK_UNREGISTER,
+             (xdrproc_t) xdr_void, (char *) NULL,
+             (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        goto cleanup;
+
     virConnectCloseCallbackDataUnregister(priv->closeCallback, cb);
     ret = 0;
 
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index bfdbce7..c6dd51e 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3045,6 +3045,10 @@ struct remote_domain_event_callback_device_added_msg {
     remote_nonnull_string devAlias;
 };
 
+struct remote_connect_event_connection_closed_msg {
+    int reason;
+};
+
 struct remote_connect_get_cpu_model_names_args {
     remote_nonnull_string arch;
     int need_results;
@@ -5706,5 +5710,23 @@ enum remote_procedure {
      * @generate: both
      * @acl: none
      */
-    REMOTE_PROC_DOMAIN_EVENT_CALLBACK_MIGRATION_ITERATION = 359
+    REMOTE_PROC_DOMAIN_EVENT_CALLBACK_MIGRATION_ITERATION = 359,
+
+    /**
+     * @generate: none
+     * @acl: none
+     */
+    REMOTE_PROC_CONNECT_CLOSE_CALLBACK_REGISTER = 360,
+
+    /**
+     * @generate: none
+     * @acl: none
+     */
+    REMOTE_PROC_CONNECT_CLOSE_CALLBACK_UNREGISTER = 361,
+
+    /**
+     * @generate: none
+     * @acl: none
+     */
+    REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED = 362
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index dff54e8..11048b7 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2502,6 +2502,9 @@ struct remote_domain_event_callback_device_added_msg {
         remote_nonnull_domain      dom;
         remote_nonnull_string      devAlias;
 };
+struct remote_connect_event_connection_closed_msg {
+    int reason;
+};
 struct remote_connect_get_cpu_model_names_args {
         remote_nonnull_string      arch;
         int                        need_results;
@@ -3057,4 +3060,7 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_SET_USER_PASSWORD = 357,
         REMOTE_PROC_DOMAIN_RENAME = 358,
         REMOTE_PROC_DOMAIN_EVENT_CALLBACK_MIGRATION_ITERATION = 359,
+        REMOTE_PROC_CONNECT_CLOSE_CALLBACK_REGISTER = 360,
+        REMOTE_PROC_CONNECT_CLOSE_CALLBACK_UNREGISTER = 361,
+        REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED = 362,
 };
-- 
1.8.3.1




More information about the libvir-list mailing list