From 324945d99b9bf8436c62c1de557e69391657b5ed Mon Sep 17 00:00:00 2001 From: Erik Skultety Date: Wed, 13 Apr 2016 10:35:26 +0200 Subject: [PATCH] admin: Introduce virAdmClient client-side object 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 --- 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 bce6034d97..feb9473645 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -50,6 +50,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: * @@ -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 c701698e9c..2f302af3ab 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 650d31d06a..d4ccf9ec4d 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 696e8c0469..ff0c46fab0 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 92e686371b..8ccc7b02ec 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 df71649c2e..0d39a79597 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -599,6 +599,96 @@ int virAdmServerFree(virAdmServerPtr srv) return 0; } +/** + * 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 + * (this will be one of virClientTransport) or -1 in case of an error. + */ +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 diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms index b150d8a861..c407e6e5cf 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 0a16444816..7c4626e0c6 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;