diff --git a/daemon/admin.c b/daemon/admin.c index 00e7dc3c00..fcbdee5fa3 100644 --- a/daemon/admin.c +++ b/daemon/admin.c @@ -81,6 +81,12 @@ remoteAdmClientInitHook(virNetServerClientPtr client ATTRIBUTE_UNUSED, /* Helpers */ +static virNetServerPtr +get_nonnull_server(virNetDaemonPtr dmn, admin_nonnull_server srv) +{ + return virNetDaemonGetServer(dmn, srv.name); +} + static void make_nonnull_server(admin_nonnull_server *srv_dst, virNetServerPtr srv_src) @@ -88,6 +94,15 @@ make_nonnull_server(admin_nonnull_server *srv_dst, ignore_value(VIR_STRDUP_QUIET(srv_dst->name, virNetServerGetName(srv_src))); } +static void +make_nonnull_client(admin_nonnull_client *clt_dst, + virNetServerClientPtr clt_src) +{ + clt_dst->id = virNetServerClientGetID(clt_src); + clt_dst->timestamp = virNetServerClientGetTimestamp(clt_src); + clt_dst->transport = virNetServerClientGetTransport(clt_src); +} + /* Functions */ static int adminDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED, diff --git a/daemon/admin_server.c b/daemon/admin_server.c index e39a9bd805..0bd142c435 100644 --- a/daemon/admin_server.c +++ b/daemon/admin_server.c @@ -178,3 +178,26 @@ adminServerSetThreadPoolParameters(virNetServerPtr srv, return 0; } + +int +adminServerListClients(virNetServerPtr srv, + virNetServerClientPtr **clients, + unsigned int flags) +{ + int ret = -1; + virNetServerClientPtr *clts; + + virCheckFlags(0, -1); + + if ((ret = virNetServerGetClients(srv, &clts)) < 0) + goto cleanup; + + if (clients) { + *clients = clts; + clts = NULL; + } + + cleanup: + virObjectListFreeCount(clts, ret); + return ret; +} diff --git a/daemon/admin_server.h b/daemon/admin_server.h index 756e049ff0..3e4786ebda 100644 --- a/daemon/admin_server.h +++ b/daemon/admin_server.h @@ -46,4 +46,8 @@ adminServerSetThreadPoolParameters(virNetServerPtr srv, int nparams, unsigned int flags); +int adminServerListClients(virNetServerPtr srv, + virNetServerClientPtr **clients, + unsigned int flags); + #endif /* __LIBVIRTD_ADMIN_SERVER_H__ */ diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index f83ac1c358..20768e218a 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -215,6 +215,10 @@ typedef enum { # endif } virClientTransport; +int virAdmServerListClients(virAdmServerPtr srv, + virAdmClientPtr **clients, + unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x index 2f302af3ab..e77ce9e455 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -39,6 +39,9 @@ const ADMIN_SERVER_LIST_MAX = 16384; /* Upper limit on number of threadpool parameters */ const ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX = 32; +/* Upper limit on list of clients */ +const ADMIN_CLIENT_LIST_MAX = 16384; + /* A long string, which may NOT be NULL. */ typedef string admin_nonnull_string; @@ -124,6 +127,17 @@ struct admin_server_set_threadpool_parameters_args { unsigned int flags; }; +struct admin_server_list_clients_args { + admin_nonnull_server srv; + unsigned int need_results; + unsigned int flags; +}; + +struct admin_server_list_clients_ret { /* insert@1 */ + admin_nonnull_client clients; + unsigned int ret; +}; + /* Define the program number, protocol version and procedure numbers here. */ const ADMIN_PROGRAM = 0x06900690; const ADMIN_PROTOCOL_VERSION = 1; @@ -179,5 +193,10 @@ enum admin_procedure { /** * @generate: none */ - ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS = 7 + ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS = 7, + + /** + * @generate: both + */ + ADMIN_PROC_SERVER_LIST_CLIENTS = 8 }; diff --git a/src/admin/admin_remote.c b/src/admin/admin_remote.c index 2dd692b342..b833ea4e15 100644 --- a/src/admin/admin_remote.c +++ b/src/admin/admin_remote.c @@ -55,6 +55,12 @@ get_nonnull_server(virAdmConnectPtr conn, admin_nonnull_server server) return virAdmGetServer(conn, server.name); } +static virAdmClientPtr +get_nonnull_client(virAdmServerPtr srv, admin_nonnull_client client) +{ + return virAdmGetClient(srv, client.id, client.timestamp, client.transport); +} + static void make_nonnull_server(admin_nonnull_server *srv_dst, virAdmServerPtr srv_src) { diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs index d4ccf9ec4d..055ddd5917 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -75,6 +75,18 @@ struct admin_server_set_threadpool_parameters_args { } params; u_int flags; }; +struct admin_server_list_clients_args { + admin_nonnull_server srv; + u_int need_results; + u_int flags; +}; +struct admin_server_list_clients_ret { + struct { + u_int clients_len; + admin_nonnull_client * clients_val; + } clients; + u_int ret; +}; enum admin_procedure { ADMIN_PROC_CONNECT_OPEN = 1, ADMIN_PROC_CONNECT_CLOSE = 2, @@ -83,4 +95,5 @@ enum admin_procedure { ADMIN_PROC_CONNECT_LOOKUP_SERVER = 5, ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS = 6, ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS = 7, + ADMIN_PROC_SERVER_LIST_CLIENTS = 8, }; diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index 0d39a79597..f8b5bd7df0 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -848,3 +848,44 @@ virAdmServerSetThreadPoolParameters(virAdmServerPtr srv, virDispatchError(NULL); return -1; } + +/** + * virAdmServerListClients: + * @srv: a valid server object reference + * @clients: pointer to a list to store an array containing objects or NULL + * if the list is not required (number of clients only) + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Collect list of all clients connected to daemon on server @srv. + * + * Returns the number of clients connected to daemon on server @srv -1 in case + * of a failure, setting @clients to NULL. There is a guaranteed extra element + * set to NULL in the @clients list returned to make the iteration easier, + * excluding this extra element from the final count. + * Caller is responsible to call virAdmClientFree() on each list element, + * followed by freeing @clients. + */ +int +virAdmServerListClients(virAdmServerPtr srv, + virAdmClientPtr **clients, + unsigned int flags) +{ + int ret = -1; + + VIR_DEBUG("srv=%p, clients=%p, flags=%x", srv, clients, flags); + + virResetLastError(); + virCheckFlagsGoto(0, error); + + if (clients) + *clients = NULL; + + virCheckAdmServerReturn(srv, -1); + if ((ret = remoteAdminServerListClients(srv, clients, flags)) < 0) + goto error; + + return ret; + error: + virDispatchError(NULL); + return -1; +} diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms index c407e6e5cf..621b502ddd 100644 --- a/src/libvirt_admin_private.syms +++ b/src/libvirt_admin_private.syms @@ -14,6 +14,8 @@ xdr_admin_connect_lookup_server_ret; xdr_admin_connect_open_args; xdr_admin_server_get_threadpool_parameters_args; xdr_admin_server_get_threadpool_parameters_ret; +xdr_admin_server_list_clients_args; +xdr_admin_server_list_clients_ret; xdr_admin_server_set_threadpool_parameters_args; # datatypes.h diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms index 7c4626e0c6..bf6643a19f 100644 --- a/src/libvirt_admin_public.syms +++ b/src/libvirt_admin_public.syms @@ -31,4 +31,5 @@ LIBVIRT_ADMIN_1.3.0 { virAdmServerFree; virAdmConnectLookupServer; virAdmServerSetThreadPoolParameters; + virAdmServerListClients; };