[libvirt] [PATCH v2 3/9] admin: Introduce virAdmClient client-side object

Erik Skultety eskultet at redhat.com
Fri Apr 29 12:39:53 UTC 2016


Besides ID, the object also stores static data like connection transport and
connection timestamp, since once obtained a list of all clients connected to a
server, from user's perspective, it would be nice to know whether a given
client is remote or local only and when did it connect to the daemon.
Along with the object introduction, all necessary client-side methods necessary
to work with the object are added as well.

Signed-off-by: Erik Skultety <eskultet at redhat.com>
---
 include/libvirt/libvirt-admin.h | 23 +++++++++++
 src/admin/admin_protocol.x      |  8 ++++
 src/admin_protocol-structs      |  6 +++
 src/datatypes.c                 | 35 ++++++++++++++++
 src/datatypes.h                 | 47 +++++++++++++++++++++
 src/libvirt-admin.c             | 90 +++++++++++++++++++++++++++++++++++++++++
 src/libvirt_admin_private.syms  |  1 +
 src/libvirt_admin_public.syms   |  4 ++
 8 files changed, 214 insertions(+)

diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h
index bce6034..feb9473 100644
--- a/include/libvirt/libvirt-admin.h
+++ b/include/libvirt/libvirt-admin.h
@@ -51,6 +51,14 @@ typedef struct _virAdmConnect virAdmConnect;
 typedef struct _virAdmServer virAdmServer;
 
 /**
+ * virAdmClient:
+ *
+ * a virAdmClient is a private structure and client-side representation of
+ * a remote server's client object (as server sees clients connected to it)
+ */
+typedef struct _virAdmClient virAdmClient;
+
+/**
  * virAdmConnectPtr:
  *
  * a virAdmConnectPtr is pointer to a virAdmConnect private structure,
@@ -68,6 +76,15 @@ typedef virAdmConnect *virAdmConnectPtr;
  */
 typedef virAdmServer *virAdmServerPtr;
 
+/**
+ * virAdmClientPtr:
+ *
+ * a virAdmClientPtr is a pointer to a virAdmClient structure,
+ * this is the type used to reference client-side representation of a
+ * client object throughout all the APIs.
+ */
+typedef virAdmClient *virAdmClientPtr;
+
 virAdmConnectPtr virAdmConnectOpen(const char *name, unsigned int flags);
 int virAdmConnectClose(virAdmConnectPtr conn);
 int virAdmConnectRef(virAdmConnectPtr conn);
@@ -182,6 +199,12 @@ int virAdmServerSetThreadPoolParameters(virAdmServerPtr srv,
                                         int nparams,
                                         unsigned int flags);
 
+/* virAdmClient object accessors */
+unsigned long long virAdmClientGetID(virAdmClientPtr client);
+long long virAdmClientGetTimestamp(virAdmClientPtr client);
+int virAdmClientGetTransport(virAdmClientPtr client);
+int virAdmClientFree(virAdmClientPtr client);
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x
index c701698..2f302af 100644
--- a/src/admin/admin_protocol.x
+++ b/src/admin/admin_protocol.x
@@ -72,6 +72,14 @@ struct admin_nonnull_server {
     admin_nonnull_string name;
 };
 
+/* A client which may NOT be NULL */
+struct admin_nonnull_client {
+    admin_nonnull_server srv;
+    unsigned hyper id;
+    hyper timestamp;
+    unsigned int transport;
+};
+
 /*----- Protocol. -----*/
 
 struct admin_connect_open_args {
diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs
index 650d31d..d4ccf9e 100644
--- a/src/admin_protocol-structs
+++ b/src/admin_protocol-structs
@@ -27,6 +27,12 @@ struct admin_typed_param {
 struct admin_nonnull_server {
         admin_nonnull_string       name;
 };
+struct admin_nonnull_client {
+        admin_nonnull_server       srv;
+        uint64_t                   id;
+        int64_t                    timestamp;
+        u_int                      transport;
+};
 struct admin_connect_open_args {
         u_int                      flags;
 };
diff --git a/src/datatypes.c b/src/datatypes.c
index 696e8c0..ff0c46f 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -66,7 +66,9 @@ static void virAdmConnectDispose(void *obj);
 static void virAdmConnectCloseCallbackDataDispose(void *obj);
 
 virClassPtr virAdmServerClass;
+virClassPtr virAdmClientClass;
 static void virAdmServerDispose(void *obj);
+static void virAdmClientDispose(void *obj);
 
 static int
 virDataTypesOnceInit(void)
@@ -98,6 +100,7 @@ virDataTypesOnceInit(void)
     DECLARE_CLASS_LOCKABLE(virAdmConnect);
     DECLARE_CLASS_LOCKABLE(virAdmConnectCloseCallbackData);
     DECLARE_CLASS(virAdmServer);
+    DECLARE_CLASS(virAdmClient);
 
 #undef DECLARE_CLASS_COMMON
 #undef DECLARE_CLASS_LOCKABLE
@@ -962,3 +965,35 @@ virAdmServerDispose(void *obj)
     VIR_FREE(srv->name);
     virObjectUnref(srv->conn);
 }
+
+virAdmClientPtr
+virAdmGetClient(virAdmServerPtr srv, const unsigned long long id,
+                unsigned long long timestamp, unsigned int transport)
+{
+    virAdmClientPtr ret = NULL;
+
+    if (virDataTypesInitialize() < 0)
+        goto error;
+
+    if (!(ret = virObjectNew(virAdmClientClass)))
+        goto error;
+
+    ret->id = id;
+    ret->timestamp = timestamp;
+    ret->transport = transport;
+    ret->srv = virObjectRef(srv);
+
+    return ret;
+ error:
+    virObjectUnref(ret);
+    return NULL;
+}
+
+static void
+virAdmClientDispose(void *obj)
+{
+    virAdmClientPtr clt = obj;
+    VIR_DEBUG("release client clt=%p, id=%llu", clt, clt->id);
+
+    virObjectUnref(clt->srv);
+}
diff --git a/src/datatypes.h b/src/datatypes.h
index 92e6863..8ccc7b0 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -43,6 +43,7 @@ extern virClassPtr virStoragePoolClass;
 
 extern virClassPtr virAdmConnectClass;
 extern virClassPtr virAdmServerClass;
+extern virClassPtr virAdmClientClass;
 
 # define virCheckConnectReturn(obj, retval)                             \
     do {                                                                \
@@ -342,6 +343,32 @@ extern virClassPtr virAdmServerClass;
         }                                                               \
     } while (0);
 
+# define virCheckAdmClientReturn(obj, retval)                           \
+    do {                                                                \
+        virAdmClientPtr _clt = (obj);                                   \
+        if (!virObjectIsClass(_clt, virAdmClientClass) ||               \
+            !virObjectIsClass(_clt->srv, virAdmServerClass) ||          \
+            !virObjectIsClass(_clt->srv->conn, virAdmConnectClass)) {   \
+            virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INVALID_CONN,   \
+                                 __FILE__, __FUNCTION__, __LINE__,      \
+                                 __FUNCTION__);                         \
+            virDispatchError(NULL);                                     \
+            return retval;                                              \
+        }                                                               \
+    } while (0)
+# define virCheckAdmClientGoto(obj, label)                              \
+    do {                                                                \
+        virAdmClientPtr _clt = (obj);                                   \
+        if (!virObjectIsClass(_clt, virAdmClientClass) ||               \
+            !virObjectIsClass(_clt->srv, virAdmServerClass) ||          \
+            !virObjectIsClass(_clt->srv->conn, virAdmConnectClass)) {   \
+            virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INVALID_CONN,   \
+                                 __FILE__, __FUNCTION__, __LINE__,      \
+                                 __FUNCTION__);                         \
+            goto label;                                                 \
+        }                                                               \
+    } while (0);
+
 /**
  * VIR_DOMAIN_DEBUG:
  * @dom: domain
@@ -450,6 +477,21 @@ struct _virAdmServer {
     char *name;                     /* the server external name */
 };
 
+/**
+ * _virAdmClient:
+ *
+ * Internal structure associated to a client connected to daemon
+ */
+struct _virAdmClient {
+    virObject object;
+    virAdmServerPtr srv;            /* pointer to the server client is
+                                     * connected to, which also holds a
+                                     * reference back to the admin connection
+                                     */
+    unsigned long long id;          /* client's ID */
+    long long timestamp;            /* connection timestamp */
+    unsigned int transport;         /* connection type as virClientTransport */
+};
 
 /**
 * _virDomain:
@@ -637,6 +679,11 @@ virAdmConnectPtr virAdmConnectNew(void);
 virAdmServerPtr virAdmGetServer(virAdmConnectPtr conn,
                                 const char *name);
 
+virAdmClientPtr virAdmGetClient(virAdmServerPtr srv,
+                                unsigned long long id,
+                                unsigned long long timestamp,
+                                unsigned int transport);
+
 virConnectCloseCallbackDataPtr virNewConnectCloseCallbackData(void);
 void virConnectCloseCallbackDataRegister(virConnectCloseCallbackDataPtr close,
                                          virConnectPtr conn,
diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c
index df71649..b45da72 100644
--- a/src/libvirt-admin.c
+++ b/src/libvirt-admin.c
@@ -600,6 +600,96 @@ int virAdmServerFree(virAdmServerPtr srv)
 }
 
 /**
+ * virAdmClientGetID:
+ * @client: a client object
+ *
+ * Get client's unique numeric ID.
+ *
+ * Returns numeric value used for client's ID or -1 in case of an error.
+ */
+unsigned long long
+virAdmClientGetID(virAdmClientPtr client)
+{
+    VIR_DEBUG("client=%p", client);
+
+    virResetLastError();
+    virCheckAdmClientReturn(client, -1);
+    return client->id;
+}
+
+/**
+ * virAdmClientGetTimestamp:
+ * @client: a client object
+ *
+ * Get client's connection time.
+ * A situation may happen, that some clients had connected prior to the update
+ * to admin API, thus, libvirt assigns these clients epoch time to express that
+ * it doesn't know when the client connected.
+ *
+ * Returns client's connection timestamp (seconds from epoch in UTC) or 0
+ * (epoch time) if libvirt doesn't have any information about client's
+ * connection time, or -1 in case of an error.
+ */
+long long
+virAdmClientGetTimestamp(virAdmClientPtr client)
+{
+    VIR_DEBUG("client=%p", client);
+
+    virResetLastError();
+    virCheckAdmClientReturn(client, -1);
+    return client->timestamp;
+}
+
+/**
+ * virAdmClientGetTransport:
+ * @client: a client object
+ *
+ * Get client's connection transport type. This information can be helpful to
+ * differentiate between clients connected locally or remotely. An exception to
+ * this would be SSH which is one of libvirt's supported transports.
+ * Although SSH creates a channel between two (preferably) remote endpoints,
+ * the client process libvirt spawns automatically on the remote side will
+ * still connect to a UNIX socket, thus becoming indistinguishable from any
+ * other locally connected clients.
+ *
+ * Returns integer representation of the connection transport used by client
+ * @client, this will be one of virClientTransport.
+ */
+int
+virAdmClientGetTransport(virAdmClientPtr client)
+{
+    VIR_DEBUG("client=%p", client);
+
+    virResetLastError();
+    virCheckAdmClientReturn(client, -1);
+    return client->transport;
+}
+
+/**
+ * virAdmClientFree:
+ * @client: a client object
+ *
+ * Release the client object. The running instance is kept alive. The data
+ * structure is freed and should not be used thereafter.
+ *
+ * Returns 0 in success, -1 on failure.
+ */
+int virAdmClientFree(virAdmClientPtr client)
+{
+    VIR_DEBUG("client=%p", client);
+
+    virResetLastError();
+
+    if (!client)
+        return 0;
+
+    virCheckAdmClientReturn(client, -1);
+
+    virObjectUnref(client);
+    return 0;
+}
+
+/**
  * virAdmConnectListServers:
  * @conn: daemon connection reference
  * @servers: Pointer to a list to store an array containing objects or NULL
diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms
index b150d8a..c407e6e 100644
--- a/src/libvirt_admin_private.syms
+++ b/src/libvirt_admin_private.syms
@@ -17,6 +17,7 @@ xdr_admin_server_get_threadpool_parameters_ret;
 xdr_admin_server_set_threadpool_parameters_args;
 
 # datatypes.h
+virAdmClientClass;
 virAdmConnectClass;
 virAdmGetServer;
 virAdmServerClass;
diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms
index 0a16444..7c4626e 100644
--- a/src/libvirt_admin_public.syms
+++ b/src/libvirt_admin_public.syms
@@ -12,6 +12,10 @@
 #
 LIBVIRT_ADMIN_1.3.0 {
     global:
+        virAdmClientFree;
+        virAdmClientGetID;
+        virAdmClientGetTimestamp;
+        virAdmClientGetTransport;
         virAdmConnectOpen;
         virAdmConnectClose;
         virAdmConnectRef;
-- 
2.4.11




More information about the libvir-list mailing list