diff --git a/daemon/admin.c b/daemon/admin.c index 03774d735d..c5c94e9a61 100644 --- a/daemon/admin.c +++ b/daemon/admin.c @@ -301,4 +301,48 @@ adminDispatchClientGetInfo(virNetServerPtr server ATTRIBUTE_UNUSED, virObjectUnref(srv); return rv; } + +static int +adminDispatchServerGetClientLimits(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, + admin_server_get_client_limits_args *args, + admin_server_get_client_limits_ret *ret) +{ + int rv = -1; + virNetServerPtr srv = NULL; + virTypedParameterPtr params = NULL; + int nparams = 0; + struct daemonAdmClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!(srv = virNetDaemonGetServer(priv->dmn, args->srv.name))) + goto cleanup; + + if (adminServerGetClientLimits(srv, ¶ms, &nparams, args->flags) < 0) + goto cleanup; + + if (nparams > ADMIN_SERVER_CLIENT_LIMITS_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of client processing parameters %d exceeds " + "max allowed limit: %d"), nparams, + ADMIN_SERVER_CLIENT_LIMITS_MAX); + goto cleanup; + } + + if (virTypedParamsSerialize(params, nparams, + (virTypedParameterRemotePtr *) &ret->params.params_val, + &ret->params.params_len, 0) < 0) + goto cleanup; + + rv = 0; + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + + virTypedParamsFree(params, nparams); + virObjectUnref(srv); + return rv; +} #include "admin_dispatch.h" diff --git a/daemon/admin_server.c b/daemon/admin_server.c index 9f4068824e..7b763a434a 100644 --- a/daemon/admin_server.c +++ b/daemon/admin_server.c @@ -311,3 +311,44 @@ int adminClientClose(virNetServerClientPtr client, virNetServerClientClose(client); return 0; } + +int +adminServerGetClientLimits(virNetServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + int ret = -1; + int maxparams = 0; + virTypedParameterPtr tmpparams = NULL; + + virCheckFlags(0, -1); + + if (virTypedParamsAddUInt(&tmpparams, nparams, &maxparams, + VIR_SERVER_CLIENTS_MAX, + virNetServerGetMaxClients(srv)) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, &maxparams, + VIR_SERVER_CLIENTS_CURRENT, + virNetServerGetCurrentClients(srv)) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, &maxparams, + VIR_SERVER_CLIENTS_UNAUTH_MAX, + virNetServerGetMaxUnauthClients(srv)) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, &maxparams, + VIR_SERVER_CLIENTS_UNAUTH_CURRENT, + virNetServerGetCurrentUnauthClients(srv)) < 0) + goto cleanup; + + *params = tmpparams; + tmpparams = NULL; + ret = 0; + + cleanup: + virTypedParamsFree(tmpparams, *nparams); + return ret; +} diff --git a/daemon/admin_server.h b/daemon/admin_server.h index 2953e108b6..109130c0b4 100644 --- a/daemon/admin_server.h +++ b/daemon/admin_server.h @@ -62,4 +62,9 @@ int adminClientGetInfo(virNetServerClientPtr client, int adminClientClose(virNetServerClientPtr client, unsigned int flags); +int adminServerGetClientLimits(virNetServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags); + #endif /* __LIBVIRTD_ADMIN_SERVER_H__ */ diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index 3cbadf9db7..3e37c78d57 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -393,6 +393,11 @@ int virAdmClientClose(virAdmClientPtr client, unsigned int flags); # define VIR_SERVER_CLIENTS_UNAUTH_CURRENT "nclients_unauth" +int virAdmServerGetClientLimits(virAdmServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x index 1da7f901ff..53867e3678 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -45,6 +45,9 @@ const ADMIN_CLIENT_LIST_MAX = 16384; /* Upper limit on number of client info parameters */ const ADMIN_CLIENT_INFO_PARAMETERS_MAX = 64; +/* Upper limit on number of client processing controls */ +const ADMIN_SERVER_CLIENT_LIMITS_MAX = 32; + /* A long string, which may NOT be NULL. */ typedef string admin_nonnull_string; @@ -165,6 +168,15 @@ struct admin_client_close_args { unsigned int flags; }; +struct admin_server_get_client_limits_args { + admin_nonnull_server srv; + unsigned int flags; +}; + +struct admin_server_get_client_limits_ret { + admin_typed_param params; +}; + /* Define the program number, protocol version and procedure numbers here. */ const ADMIN_PROGRAM = 0x06900690; const ADMIN_PROTOCOL_VERSION = 1; @@ -240,5 +252,10 @@ enum admin_procedure { /** * @generate: both */ - ADMIN_PROC_CLIENT_CLOSE = 11 + ADMIN_PROC_CLIENT_CLOSE = 11, + + /** + * @generate: none + */ + ADMIN_PROC_SERVER_GET_CLIENT_LIMITS = 12 }; diff --git a/src/admin/admin_remote.c b/src/admin/admin_remote.c index 632aaa86fb..1a002af1f5 100644 --- a/src/admin/admin_remote.c +++ b/src/admin/admin_remote.c @@ -355,3 +355,42 @@ remoteAdminClientGetInfo(virAdmClientPtr client, virObjectUnlock(priv); return rv; } + +static int +remoteAdminServerGetClientLimits(virAdmServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + int rv = -1; + admin_server_get_client_limits_args args; + admin_server_get_client_limits_ret ret; + remoteAdminPrivPtr priv = srv->conn->privateData; + args.flags = flags; + make_nonnull_server(&args.srv, srv); + + memset(&ret, 0, sizeof(ret)); + virObjectLock(priv); + + if (call(srv->conn, 0, ADMIN_PROC_SERVER_GET_CLIENT_LIMITS, + (xdrproc_t) xdr_admin_server_get_client_limits_args, + (char *) &args, + (xdrproc_t) xdr_admin_server_get_client_limits_ret, + (char *) &ret) == -1) + goto cleanup; + + if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val, + ret.params.params_len, + ADMIN_SERVER_CLIENT_LIMITS_MAX, + params, + nparams) < 0) + goto cleanup; + + rv = 0; + xdr_free((xdrproc_t) xdr_admin_server_get_client_limits_ret, + (char *) &ret); + + cleanup: + virObjectUnlock(priv); + return rv; +} diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs index b4db415bda..03b25ae8d1 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -109,6 +109,16 @@ struct admin_client_close_args { admin_nonnull_client clnt; u_int flags; }; +struct admin_server_get_client_limits_args { + admin_nonnull_server srv; + u_int flags; +}; +struct admin_server_get_client_limits_ret { + struct { + u_int params_len; + admin_typed_param * params_val; + } params; +}; enum admin_procedure { ADMIN_PROC_CONNECT_OPEN = 1, ADMIN_PROC_CONNECT_CLOSE = 2, @@ -121,4 +131,5 @@ enum admin_procedure { ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9, ADMIN_PROC_CLIENT_GET_INFO = 10, ADMIN_PROC_CLIENT_CLOSE = 11, + ADMIN_PROC_SERVER_GET_CLIENT_LIMITS = 12, }; diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index 9d5e5b99ff..07dc883e11 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -1000,3 +1000,44 @@ int virAdmClientClose(virAdmClientPtr client, virDispatchError(NULL); return -1; } + +/** + * virAdmServerGetClientLimits: + * @srv: a valid server object reference + * @params: pointer to client limits object + * (return value, allocated automatically) + * @nparams: pointer to number of parameters returned in @params + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Retrieve client limits from server @srv. These include: + * - current number of clients connected to @srv, + * - maximum number of clients connected to @srv, + * - current number of clients connected to @srv waiting for authentication, + * - maximum number of clients connected to @srv that can be wainting for + * authentication. + * + * Returns 0 on success, allocating @params to size returned in @nparams, or + * -1 in case of an error. Caller is responsible for deallocating @params. + */ +int +virAdmServerGetClientLimits(virAdmServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + int ret = -1; + + VIR_DEBUG("srv=%p, flags=%x", srv, flags); + virResetLastError(); + + virCheckAdmServerGoto(srv, error); + + if ((ret = remoteAdminServerGetClientLimits(srv, params, + nparams, 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 e55b91eafd..0c38844581 100644 --- a/src/libvirt_admin_private.syms +++ b/src/libvirt_admin_private.syms @@ -15,6 +15,8 @@ xdr_admin_connect_list_servers_ret; xdr_admin_connect_lookup_server_args; xdr_admin_connect_lookup_server_ret; xdr_admin_connect_open_args; +xdr_admin_server_get_client_limits_args; +xdr_admin_server_get_client_limits_ret; xdr_admin_server_get_threadpool_parameters_args; xdr_admin_server_get_threadpool_parameters_ret; xdr_admin_server_list_clients_args; diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms index 57df1f436b..707e084f0d 100644 --- a/src/libvirt_admin_public.syms +++ b/src/libvirt_admin_public.syms @@ -35,4 +35,5 @@ LIBVIRT_ADMIN_1.3.0 { virAdmServerListClients; virAdmClientGetInfo; virAdmClientClose; + virAdmServerGetClientLimits; };