[libvirt] [PATCH v2 0/5] admin: Introduce APIs to get/set client-related limits

since v1: - symbols added to libvirt_remote.syms - APIs renamed - dropped some unwanted client-side flags checks - dropped unnecessary ifs before calling virAdmServerFree (because it handles NULL gracefully) - a man page entry virt-admin's commands created Erik Skultety (5): virnetserver: Introduce server's client-related limits getters admin: Introduce some public constants related to server's client limits admin: Introduce virAdmServerGetClientLimits admin: Introduce virAdmServerSetClientLimits virt-admin: Introduce commands srv-clients-info and srv-clients-set daemon/admin.c | 82 +++++++++++++++++++ daemon/admin_server.c | 76 ++++++++++++++++++ daemon/admin_server.h | 10 +++ include/libvirt/libvirt-admin.h | 52 ++++++++++++ src/admin/admin_protocol.x | 30 ++++++- src/admin/admin_remote.c | 74 +++++++++++++++++ src/admin_protocol-structs | 20 +++++ src/libvirt-admin.c | 85 ++++++++++++++++++++ src/libvirt_admin_private.syms | 3 + src/libvirt_admin_public.syms | 2 + src/libvirt_remote.syms | 4 + src/rpc/virnetserver.c | 83 +++++++++++++++++++ src/rpc/virnetserver.h | 9 +++ tools/virt-admin.c | 174 ++++++++++++++++++++++++++++++++++++++++ tools/virt-admin.pod | 38 +++++++++ 15 files changed, 741 insertions(+), 1 deletion(-) -- 2.5.5

Add some trivial getters for client related attributes to virnetserver before any admin method can be introduced. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- src/libvirt_remote.syms | 4 ++++ src/rpc/virnetserver.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/rpc/virnetserver.h | 5 +++++ 3 files changed, 58 insertions(+) diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms index 6b098b4..1a88fff 100644 --- a/src/libvirt_remote.syms +++ b/src/libvirt_remote.syms @@ -103,6 +103,10 @@ virNetServerAddProgram; virNetServerAddService; virNetServerClose; virNetServerGetClients; +virNetServerGetCurrentClients; +virNetServerGetCurrentUnauthClients; +virNetServerGetMaxClients; +virNetServerGetMaxUnauthClients; virNetServerGetName; virNetServerHasClients; virNetServerNew; diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 60541cb..2cd1765 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -941,6 +941,55 @@ virNetServerSetThreadPoolParameters(virNetServerPtr srv, ret = virThreadPoolSetParameters(srv->workers, minWorkers, maxWorkers, prioWorkers); virObjectUnlock(srv); + + return ret; +} + +size_t +virNetServerGetMaxClients(virNetServerPtr srv) +{ + size_t ret; + + virObjectLock(srv); + ret = srv->nclients_max; + virObjectUnlock(srv); + + return ret; +} + +size_t +virNetServerGetCurrentClients(virNetServerPtr srv) +{ + size_t ret; + + virObjectLock(srv); + ret = srv->nclients; + virObjectUnlock(srv); + + return ret; +} + +size_t +virNetServerGetMaxUnauthClients(virNetServerPtr srv) +{ + size_t ret; + + virObjectLock(srv); + ret = srv->nclients_unauth_max; + virObjectUnlock(srv); + + return ret; +} + +size_t +virNetServerGetCurrentUnauthClients(virNetServerPtr srv) +{ + size_t ret; + + virObjectLock(srv); + ret = srv->nclients_unauth; + virObjectUnlock(srv); + return ret; } diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index 993bda7..a08cab0 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -111,4 +111,9 @@ virNetServerClientPtr virNetServerGetClient(virNetServerPtr srv, int virNetServerGetClients(virNetServerPtr srv, virNetServerClientPtr **clients); +size_t virNetServerGetMaxClients(virNetServerPtr srv); +size_t virNetServerGetCurrentClients(virNetServerPtr srv); +size_t virNetServerGetMaxUnauthClients(virNetServerPtr srv); +size_t virNetServerGetCurrentUnauthClients(virNetServerPtr srv); + #endif /* __VIR_NET_SERVER_H__ */ -- 2.5.5

In order for typed params validation to pass on daemon side, we should encourage users to use our exported constants with typed params to diminish to avoid any potential problems related to argument validity. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- include/libvirt/libvirt-admin.h | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index 4e6074e..245313e 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -351,6 +351,48 @@ int virAdmClientGetInfo(virAdmClientPtr client, int virAdmClientClose(virAdmClientPtr client, unsigned int flags); +/* Manage per-server client processing controls */ + +/** + * VIR_SERVER_CLIENTS_MAX: + * Macro for per-server nclients_max limit: represents the upper limit to + * number of clients connected to the server, as uint. + */ + +# define VIR_SERVER_CLIENTS_MAX "nclients_max" + +/** + * VIR_SERVER_CLIENTS_CURRENT: + * Macro for per-server nclients attribute: represents the current number of + * clients connected to the server, as VIR_TYPED_PARAM_UINT. + * + * NOTE: This attribute is read-only and any attempt to set it will be denied + * by daemon + */ + +# define VIR_SERVER_CLIENTS_CURRENT "nclients" + +/** + * VIR_SERVER_CLIENTS_UNAUTH_MAX: + * Macro for per-server nclients_unauth_max limit: represents the upper limit + * to number of clients connected to the server, but not authenticated yet, + * as VIR_TYPED_PARAM_UINT. + */ + +# define VIR_SERVER_CLIENTS_UNAUTH_MAX "nclients_unauth_max" + +/** + * VIR_SERVER_CLIENTS_UNAUTH_CURRENT: + * Macro for per-server nclients_unauth attribute: represents the current + * number of clients connected to the server, but not authenticated yet, + * as VIR_TYPED_PARAM_UINT. + * + * NOTE: This attribute is read-only and any attempt to set it will be denied + * by daemon + */ + +# define VIR_SERVER_CLIENTS_UNAUTH_CURRENT "nclients_unauth" + # ifdef __cplusplus } # endif -- 2.5.5

Enable retrieval of the number of maximum clients connected to all sockets combined, as well as the number of maximum clients waiting for authentication, in order to be successfully connected. These are the attributes configurable through libvirtd.conf, however, it could be handy to not only know values for these limits, but also the values for the current number of clients connected and number of clients currently waiting for authentication which are changing dynamically. This API does both, retrieves the limits as well as the current dynamic values. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- daemon/admin.c | 44 +++++++++++++++++++++++++++++++++++++++++ daemon/admin_server.c | 41 ++++++++++++++++++++++++++++++++++++++ daemon/admin_server.h | 5 +++++ include/libvirt/libvirt-admin.h | 5 +++++ src/admin/admin_protocol.x | 19 +++++++++++++++++- src/admin/admin_remote.c | 39 ++++++++++++++++++++++++++++++++++++ src/admin_protocol-structs | 11 +++++++++++ src/libvirt-admin.c | 41 ++++++++++++++++++++++++++++++++++++++ src/libvirt_admin_private.syms | 2 ++ src/libvirt_admin_public.syms | 1 + 10 files changed, 207 insertions(+), 1 deletion(-) diff --git a/daemon/admin.c b/daemon/admin.c index 03774d7..c5c94e9 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 9f40688..7b763a4 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 2953e10..109130c 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 245313e..19cdbed 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 1da7f90..53867e3 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<ADMIN_STRING_MAX>; @@ -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<ADMIN_SERVER_CLIENT_LIMITS_MAX>; +}; + /* 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 632aaa8..1a002af 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 b4db415..03b25ae 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 9d5e5b9..2237668 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 processing control limits. 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 e55b91e..0c38844 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 57df1f4..707e084 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; }; -- 2.5.5

Opposite operation to virAdmServerGetClientLimits. Understandably though, setting values for current number of clients connected or still waiting for authentication does not make sense, since changes to these values are event dependent, i.e. a client connects - counter is increased. Thus only the limits to maximum clients connected and waiting for authentication can be set. Should a request for other controls to be set arrive (provided such a setting will be first introduced to the config), the set of configuration controls can be later expanded (thanks to typed params). This patch also introduces a constraint that the maximum number of clients waiting for authentication has to be less than the overall maximum number of clients connected and any attempt to violate this constraint will be denied. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- daemon/admin.c | 38 +++++++++++++++++++++++++++++++++++ daemon/admin_server.c | 35 ++++++++++++++++++++++++++++++++ daemon/admin_server.h | 5 +++++ include/libvirt/libvirt-admin.h | 5 +++++ src/admin/admin_protocol.x | 13 +++++++++++- src/admin/admin_remote.c | 35 ++++++++++++++++++++++++++++++++ src/admin_protocol-structs | 9 +++++++++ src/libvirt-admin.c | 44 +++++++++++++++++++++++++++++++++++++++++ src/libvirt_admin_private.syms | 1 + src/libvirt_admin_public.syms | 1 + src/rpc/virnetserver.c | 34 +++++++++++++++++++++++++++++++ src/rpc/virnetserver.h | 4 ++++ 12 files changed, 223 insertions(+), 1 deletion(-) diff --git a/daemon/admin.c b/daemon/admin.c index c5c94e9..a3c8b89 100644 --- a/daemon/admin.c +++ b/daemon/admin.c @@ -345,4 +345,42 @@ adminDispatchServerGetClientLimits(virNetServerPtr server ATTRIBUTE_UNUSED, virObjectUnref(srv); return rv; } + +static int +adminDispatchServerSetClientLimits(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, + admin_server_set_client_limits_args *args) +{ + 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))) { + virReportError(VIR_ERR_NO_SERVER, + _("no server with matching name '%s' found"), + args->srv.name); + goto cleanup; + } + + if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val, + args->params.params_len, + ADMIN_SERVER_CLIENT_LIMITS_MAX, ¶ms, &nparams) < 0) + goto cleanup; + + if (adminServerSetClientLimits(srv, params, nparams, args->flags) < 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 7b763a4..cb9079c 100644 --- a/daemon/admin_server.c +++ b/daemon/admin_server.c @@ -352,3 +352,38 @@ adminServerGetClientLimits(virNetServerPtr srv, virTypedParamsFree(tmpparams, *nparams); return ret; } + +int +adminServerSetClientLimits(virNetServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + long long int maxClients = -1; + long long int maxClientsUnauth = -1; + virTypedParameterPtr param = NULL; + + virCheckFlags(0, -1); + + if (virTypedParamsValidate(params, nparams, + VIR_SERVER_CLIENTS_MAX, + VIR_TYPED_PARAM_UINT, + VIR_SERVER_CLIENTS_UNAUTH_MAX, + VIR_TYPED_PARAM_UINT, + NULL) < 0) + return -1; + + if ((param = virTypedParamsGet(params, nparams, + VIR_SERVER_CLIENTS_MAX))) + maxClients = param->value.ui; + + if ((param = virTypedParamsGet(params, nparams, + VIR_SERVER_CLIENTS_UNAUTH_MAX))) + maxClientsUnauth = param->value.ui; + + if (virNetServerSetClientProcessingControls(srv, maxClients, + maxClientsUnauth) < 0) + return -1; + + return 0; +} diff --git a/daemon/admin_server.h b/daemon/admin_server.h index 109130c..0baffa7 100644 --- a/daemon/admin_server.h +++ b/daemon/admin_server.h @@ -67,4 +67,9 @@ int adminServerGetClientLimits(virNetServerPtr srv, int *nparams, unsigned int flags); +int adminServerSetClientLimits(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 19cdbed..df629a2 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -398,6 +398,11 @@ int virAdmServerGetClientLimits(virAdmServerPtr srv, int *nparams, unsigned int flags); +int virAdmServerSetClientLimits(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 53867e3..5963233 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -177,6 +177,12 @@ struct admin_server_get_client_limits_ret { admin_typed_param params<ADMIN_SERVER_CLIENT_LIMITS_MAX>; }; +struct admin_server_set_client_limits_args { + admin_nonnull_server srv; + admin_typed_param params<ADMIN_SERVER_CLIENT_LIMITS_MAX>; + unsigned int flags; +}; + /* Define the program number, protocol version and procedure numbers here. */ const ADMIN_PROGRAM = 0x06900690; const ADMIN_PROTOCOL_VERSION = 1; @@ -257,5 +263,10 @@ enum admin_procedure { /** * @generate: none */ - ADMIN_PROC_SERVER_GET_CLIENT_LIMITS = 12 + ADMIN_PROC_SERVER_GET_CLIENT_LIMITS = 12, + + /** + * @generate: none + */ + ADMIN_PROC_SERVER_SET_CLIENT_LIMITS = 13 }; diff --git a/src/admin/admin_remote.c b/src/admin/admin_remote.c index 1a002af..10a3b18 100644 --- a/src/admin/admin_remote.c +++ b/src/admin/admin_remote.c @@ -394,3 +394,38 @@ remoteAdminServerGetClientLimits(virAdmServerPtr srv, virObjectUnlock(priv); return rv; } + +static int +remoteAdminServerSetClientLimits(virAdmServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + int rv = -1; + admin_server_set_client_limits_args args; + remoteAdminPrivPtr priv = srv->conn->privateData; + + args.flags = flags; + make_nonnull_server(&args.srv, srv); + + virObjectLock(priv); + + if (virTypedParamsSerialize(params, nparams, + (virTypedParameterRemotePtr *) &args.params.params_val, + &args.params.params_len, + 0) < 0) + goto cleanup; + + if (call(srv->conn, 0, ADMIN_PROC_SERVER_SET_CLIENT_LIMITS, + (xdrproc_t) xdr_admin_server_set_client_limits_args, + (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto cleanup; + + rv = 0; + cleanup: + virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val, + args.params.params_len); + virObjectUnlock(priv); + return rv; +} diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs index 03b25ae..1437d9e 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -119,6 +119,14 @@ struct admin_server_get_client_limits_ret { admin_typed_param * params_val; } params; }; +struct admin_server_set_client_limits_args { + admin_nonnull_server srv; + struct { + u_int params_len; + admin_typed_param * params_val; + } params; + u_int flags; +}; enum admin_procedure { ADMIN_PROC_CONNECT_OPEN = 1, ADMIN_PROC_CONNECT_CLOSE = 2, @@ -132,4 +140,5 @@ enum admin_procedure { ADMIN_PROC_CLIENT_GET_INFO = 10, ADMIN_PROC_CLIENT_CLOSE = 11, ADMIN_PROC_SERVER_GET_CLIENT_LIMITS = 12, + ADMIN_PROC_SERVER_SET_CLIENT_LIMITS = 13, }; diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index 2237668..ad48bdb 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -1041,3 +1041,47 @@ virAdmServerGetClientLimits(virAdmServerPtr srv, virDispatchError(NULL); return -1; } + +/** + * virAdmServerSetClientLimits: + * @srv: a valid server object reference + * @params: pointer to client limits object + * @nparams: number of parameters in @params + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Change limits of client processing controls configuration on server @srv. + * + * Caller is responsible for allocating @params prior to calling this function. + * See 'Manage per-server client processing controls' in libvirt-admin.h for + * supported parameters in @params. + * + * Returns 0 if the controls have been changed successfully or -1 in case of an + * error. + */ +int +virAdmServerSetClientLimits(virAdmServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + int ret = -1; + + VIR_DEBUG("srv=%p, params=%p, nparams=%d, flags=%x", srv, params, nparams, + flags); + VIR_TYPED_PARAMS_DEBUG(params, nparams); + + virResetLastError(); + + virCheckAdmServerGoto(srv, error); + virCheckNonNullArgGoto(params, error); + virCheckPositiveArgGoto(nparams, error); + + if ((ret = remoteAdminServerSetClientLimits(srv, params, nparams, + flags)) < 0) + goto error; + + return ret; + error: + virDispatchError(NULL); + return ret; +} diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms index 0c38844..8c173ab 100644 --- a/src/libvirt_admin_private.syms +++ b/src/libvirt_admin_private.syms @@ -23,6 +23,7 @@ xdr_admin_server_list_clients_args; xdr_admin_server_list_clients_ret; xdr_admin_server_lookup_client_args; xdr_admin_server_lookup_client_ret; +xdr_admin_server_set_client_limits_args; xdr_admin_server_set_threadpool_parameters_args; # datatypes.h diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms index 707e084..53df5fc 100644 --- a/src/libvirt_admin_public.syms +++ b/src/libvirt_admin_public.syms @@ -36,4 +36,5 @@ LIBVIRT_ADMIN_1.3.0 { virAdmClientGetInfo; virAdmClientClose; virAdmServerGetClientLimits; + virAdmServerSetClientLimits; }; diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 2cd1765..4c4b144 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -1044,3 +1044,37 @@ virNetServerGetClient(virNetServerPtr srv, _("No client with matching ID '%llu'"), id); return ret; } + +int +virNetServerSetClientProcessingControls(virNetServerPtr srv, + long long int maxClients, + long long int maxClientsUnauth) +{ + int ret = -1; + size_t max, max_unauth; + + virObjectLock(srv); + + max = maxClients >= 0 ? maxClients : srv->nclients_max; + max_unauth = maxClientsUnauth >= 0 ? + maxClientsUnauth : srv->nclients_unauth_max; + + if (max < max_unauth) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("The overall maximum number of clients must be " + "greater than the maximum number of clients waiting " + "for authentication")); + goto cleanup; + } + + if (maxClients >= 0) + srv->nclients_max = maxClients; + + if (maxClientsUnauth >= 0) + srv->nclients_unauth_max = maxClientsUnauth; + + ret = 0; + cleanup: + virObjectUnlock(srv); + return ret; +} diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index a08cab0..38107b4 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -116,4 +116,8 @@ size_t virNetServerGetCurrentClients(virNetServerPtr srv); size_t virNetServerGetMaxUnauthClients(virNetServerPtr srv); size_t virNetServerGetCurrentUnauthClients(virNetServerPtr srv); +int virNetServerSetClientProcessingControls(virNetServerPtr srv, + long long int maxClients, + long long int maxClientsUnauth); + #endif /* __VIR_NET_SERVER_H__ */ -- 2.5.5

Finally wire-up virAdmServer{Get,Set}ClientLimits APIs into virt-admin client. Update the virt-admin's man page accordingly. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- tools/virt-admin.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virt-admin.pod | 38 +++++++++++ 2 files changed, 212 insertions(+) diff --git a/tools/virt-admin.c b/tools/virt-admin.c index 90ad765..4acac65 100644 --- a/tools/virt-admin.c +++ b/tools/virt-admin.c @@ -809,6 +809,168 @@ cmdClientDisconnect(vshControl *ctl, const vshCmd *cmd) return ret; } +/* ------------------------ + * Command srv-clients-info + * ------------------------ + */ + +static const vshCmdInfo info_srv_clients_info[] = { + {.name = "help", + .data = N_("get server's client-related configuration limits") + }, + {.name = "desc", + .data = N_("Retrieve server's client-related configuration limits ") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_srv_clients_info[] = { + {.name = "server", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("Server to retrieve the client limits from."), + }, + {.name = NULL} +}; + +static bool +cmdSrvClientsInfo(vshControl *ctl, const vshCmd *cmd) +{ + bool ret = false; + virTypedParameterPtr params = NULL; + int nparams = 0; + size_t i; + const char *srvname = NULL; + virAdmServerPtr srv = NULL; + vshAdmControlPtr priv = ctl->privData; + + if (vshCommandOptStringReq(ctl, cmd, "server", &srvname) < 0) + return false; + + if (!(srv = virAdmConnectLookupServer(priv->conn, srvname, 0))) + goto cleanup; + + if (virAdmServerGetClientLimits(srv, ¶ms, &nparams, 0) < 0) { + vshError(ctl, "%s", _("Unable to retrieve client limits " + "from server's configuration")); + goto cleanup; + } + + for (i = 0; i < nparams; i++) + vshPrint(ctl, "%-20s: %d\n", params[i].field, params[i].value.ui); + + ret = true; + + cleanup: + virTypedParamsFree(params, nparams); + virAdmServerFree(srv); + return ret; +} + +/* ----------------------- + * Command srv-clients-set + * ----------------------- + */ + +static const vshCmdInfo info_srv_clients_set[] = { + {.name = "help", + .data = N_("set server's client-related configuration limits") + }, + {.name = "desc", + .data = N_("Tune server's client-related configuration limits. " + "See OPTIONS for currently supported attributes.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_srv_clients_set[] = { + {.name = "server", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("Server to alter the client-related configuration limits on."), + }, + {.name = "max-clients", + .type = VSH_OT_INT, + .help = N_("Change the upper limit to overall number of clients " + "connected to the server."), + }, + {.name = "max-unauth-clients", + .type = VSH_OT_INT, + .help = N_("Change the upper limit to number of clients waiting for " + "authentication to be connected to the server"), + }, + {.name = NULL} +}; + +static bool +cmdSrvClientsSet(vshControl *ctl, const vshCmd *cmd) +{ + bool ret = false; + int rv = 0; + unsigned int val, max, unauth_max; + int maxparams = 0; + int nparams = 0; + const char *srvname = NULL; + virAdmServerPtr srv = NULL; + virTypedParameterPtr params = NULL; + vshAdmControlPtr priv = ctl->privData; + + if (vshCommandOptStringReq(ctl, cmd, "server", &srvname) < 0) + return false; + +#define PARSE_CMD_TYPED_PARAM(NAME, FIELD) \ + if ((rv = vshCommandOptUInt(ctl, cmd, NAME, &val)) < 0) { \ + vshError(ctl, _("Unable to parse integer parameter '%s'"), NAME); \ + goto cleanup; \ + } else if (rv > 0) { \ + if (virTypedParamsAddUInt(¶ms, &nparams, &maxparams, \ + FIELD, val) < 0) \ + goto save_error; \ + } + + PARSE_CMD_TYPED_PARAM("max-clients", VIR_SERVER_CLIENTS_MAX); + PARSE_CMD_TYPED_PARAM("max-unauth-clients", VIR_SERVER_CLIENTS_UNAUTH_MAX); + +#undef PARSE_CMD_TYPED_PARAM + + if (!nparams) { + vshError(ctl, "%s", _("At least one of options --max-clients, " + "--max-unauth-clients is mandatory")); + goto cleanup; + } + + if (virTypedParamsGetUInt(params, nparams, + VIR_SERVER_CLIENTS_MAX, &max) && + virTypedParamsGetUInt(params, nparams, + VIR_SERVER_CLIENTS_UNAUTH_MAX, &unauth_max) && + unauth_max > max) { + vshError(ctl, "%s", _("--max-unauth-clients must be less than " + "--max-clients")); + goto cleanup; + } + + if (!(srv = virAdmConnectLookupServer(priv->conn, srvname, 0))) + goto cleanup; + + if (virAdmServerSetClientLimits(srv, params, nparams, 0) < 0) + goto error; + + ret = true; + + cleanup: + virTypedParamsFree(params, nparams); + virAdmServerFree(srv); + return ret; + + save_error: + vshSaveLibvirtError(); + + error: + vshError(ctl, "%s", _("Unable to change server's client-related " + "configuration limits")); + goto cleanup; +} + static void * vshAdmConnectionHandler(vshControl *ctl) { @@ -1126,6 +1288,12 @@ static const vshCmdDef monitoringCmds[] = { .info = info_client_info, .flags = 0 }, + {.name = "srv-clients-info", + .handler = cmdSrvClientsInfo, + .opts = opts_srv_clients_info, + .info = info_srv_clients_info, + .flags = 0 + }, {.name = NULL} }; @@ -1142,6 +1310,12 @@ static const vshCmdDef managementCmds[] = { .info = info_client_disconnect, .flags = 0 }, + {.name = "srv-clients-set", + .handler = cmdSrvClientsSet, + .opts = opts_srv_clients_set, + .info = info_srv_clients_set, + .flags = 0 + }, {.name = NULL} }; diff --git a/tools/virt-admin.pod b/tools/virt-admin.pod index b90f037..afc4689 100644 --- a/tools/virt-admin.pod +++ b/tools/virt-admin.pod @@ -227,6 +227,44 @@ information about transport type used on client's connection (supported transports include B<unix>, B<tcp>, and B<tls>), as well as providing information about client's connection time (system local time is used). +=item B<srv-clients-info> I<server> + +Get information about the current setting of limits regarding connections of new +clients. This information comprises of the limits to the maximum number of +clients connected to I<server>, maximum number of clients waiting for +authentication, in order to be connected to the server, as well as the current +runtime values, more specifically, the current number of clients connected to +I<server> and the current number of clients waiting for authentication. + +B<Example> + # virt-admin srv-clients-info libvirtd + nclients_max : 120 + nclients : 3 + nclients_unauth_max : 20 + nclients_unauth : 0 + +=item B<srv-clients-set> I<server> [I<--max-clients> B<count>] +[I<--max-unauth-clients> B<count>] + +Set new client-related limits on I<server>. + +=over 4 + +=item I<--max-clients> + +Change the upper limit of the maximum overall number of clients connected to +I<server> to value B<count>. The value for this limit has to be always greater +than the value of I<--max-unauth-clients>. + +=item I<--max-unauth-clients> + +Change the upper limit of the maximum number of clients waiting for +authentication, in order to be connected to I<server>, to value B<count>. +The value for this limit has to be always lower than the value of +I<--max-clients>. + +=back + =back =head1 CLIENT COMMANDS -- 2.5.5

On 11.05.2016 20:02, Erik Skultety wrote:
since v1: - symbols added to libvirt_remote.syms - APIs renamed - dropped some unwanted client-side flags checks - dropped unnecessary ifs before calling virAdmServerFree (because it handles NULL gracefully) - a man page entry virt-admin's commands created
Erik Skultety (5): virnetserver: Introduce server's client-related limits getters admin: Introduce some public constants related to server's client limits admin: Introduce virAdmServerGetClientLimits admin: Introduce virAdmServerSetClientLimits virt-admin: Introduce commands srv-clients-info and srv-clients-set
daemon/admin.c | 82 +++++++++++++++++++ daemon/admin_server.c | 76 ++++++++++++++++++ daemon/admin_server.h | 10 +++ include/libvirt/libvirt-admin.h | 52 ++++++++++++ src/admin/admin_protocol.x | 30 ++++++- src/admin/admin_remote.c | 74 +++++++++++++++++ src/admin_protocol-structs | 20 +++++ src/libvirt-admin.c | 85 ++++++++++++++++++++ src/libvirt_admin_private.syms | 3 + src/libvirt_admin_public.syms | 2 + src/libvirt_remote.syms | 4 + src/rpc/virnetserver.c | 83 +++++++++++++++++++ src/rpc/virnetserver.h | 9 +++ tools/virt-admin.c | 174 ++++++++++++++++++++++++++++++++++++++++ tools/virt-admin.pod | 38 +++++++++ 15 files changed, 741 insertions(+), 1 deletion(-)
ACK series. Michal

On 19/05/16 10:32, Michal Privoznik wrote:
On 11.05.2016 20:02, Erik Skultety wrote:
since v1: - symbols added to libvirt_remote.syms - APIs renamed - dropped some unwanted client-side flags checks - dropped unnecessary ifs before calling virAdmServerFree (because it handles NULL gracefully) - a man page entry virt-admin's commands created
Erik Skultety (5): virnetserver: Introduce server's client-related limits getters admin: Introduce some public constants related to server's client limits admin: Introduce virAdmServerGetClientLimits admin: Introduce virAdmServerSetClientLimits virt-admin: Introduce commands srv-clients-info and srv-clients-set
daemon/admin.c | 82 +++++++++++++++++++ daemon/admin_server.c | 76 ++++++++++++++++++ daemon/admin_server.h | 10 +++ include/libvirt/libvirt-admin.h | 52 ++++++++++++ src/admin/admin_protocol.x | 30 ++++++- src/admin/admin_remote.c | 74 +++++++++++++++++ src/admin_protocol-structs | 20 +++++ src/libvirt-admin.c | 85 ++++++++++++++++++++ src/libvirt_admin_private.syms | 3 + src/libvirt_admin_public.syms | 2 + src/libvirt_remote.syms | 4 + src/rpc/virnetserver.c | 83 +++++++++++++++++++ src/rpc/virnetserver.h | 9 +++ tools/virt-admin.c | 174 ++++++++++++++++++++++++++++++++++++++++ tools/virt-admin.pod | 38 +++++++++ 15 files changed, 741 insertions(+), 1 deletion(-)
ACK series.
Michal
Pushed, thank you for review. Erik
participants (2)
-
Erik Skultety
-
Michal Privoznik