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__ */