From 8b1f04693d63461f5f0b181fc29b7ff657c2e209 Mon Sep 17 00:00:00 2001 From: Erik Skultety Date: Mon, 4 Apr 2016 14:24:52 +0200 Subject: [PATCH] admin: Introduce virAdmServerSetClientLimits 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 --- 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 c5c94e9a61..a3c8b896fc 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 7b763a434a..cb9079c1f3 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 109130c0b4..0baffa7ece 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 3e37c78d57..fa69de4b6a 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 53867e3678..5963233335 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; }; +struct admin_server_set_client_limits_args { + admin_nonnull_server srv; + admin_typed_param params; + 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 1a002af1f5..10a3b18b00 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 03b25ae8d1..1437d9e77b 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 07dc883e11..86120e4abf 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 client limits configuration on server @srv. + * + * Caller is responsible for allocating @params prior to calling this function. + * See 'Manage per-server client limits' in libvirt-admin.h for + * supported parameters in @params. + * + * Returns 0 if the limits 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); + virCheckNonNegativeArgGoto(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 0c38844581..8c173ab428 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 707e084f0d..53df5fc9c0 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 2cd1765128..4c4b144ac2 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 a08cab0944..38107b4c7a 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__ */