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(a)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