2010-12-01 16:36:40 +00:00
|
|
|
/*
|
|
|
|
* virnetserver.c: generic network RPC server
|
|
|
|
*
|
2015-03-16 15:02:41 +01:00
|
|
|
* Copyright (C) 2006-2015 Red Hat, Inc.
|
2010-12-01 16:36:40 +00:00
|
|
|
* Copyright (C) 2006 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 16:30:55 -06:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 18:06:23 +08:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2010-12-01 16:36:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "virnetserver.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-13 15:49:48 +00:00
|
|
|
#include "virthread.h"
|
2012-12-13 15:39:07 +00:00
|
|
|
#include "virthreadpool.h"
|
2013-05-03 14:47:53 +02:00
|
|
|
#include "virstring.h"
|
2020-03-07 19:31:00 +08:00
|
|
|
#include "virutil.h"
|
2012-04-19 21:41:27 -06:00
|
|
|
|
2010-12-01 16:36:40 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_RPC
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("rpc.netserver");
|
|
|
|
|
2010-12-01 16:36:40 +00:00
|
|
|
|
|
|
|
typedef struct _virNetServerJob virNetServerJob;
|
|
|
|
struct _virNetServerJob {
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient *client;
|
|
|
|
virNetMessage *msg;
|
|
|
|
virNetServerProgram *prog;
|
2010-12-01 16:36:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _virNetServer {
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectLockable parent;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2016-03-01 15:34:15 +01:00
|
|
|
char *name;
|
|
|
|
|
2018-07-03 13:37:33 +02:00
|
|
|
/* Immutable pointer, self-locking APIs */
|
2021-03-11 08:16:13 +01:00
|
|
|
virThreadPool *workers;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
|
|
|
size_t nservices;
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerService **services;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
|
|
|
size_t nprograms;
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerProgram **programs;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2014-03-04 15:37:27 +01:00
|
|
|
size_t nclients; /* Current clients count */
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient **clients; /* Clients */
|
2016-04-13 20:54:40 +02:00
|
|
|
unsigned long long next_client_id; /* next client ID */
|
2014-03-04 15:37:27 +01:00
|
|
|
size_t nclients_max; /* Max allowed clients count */
|
|
|
|
size_t nclients_unauth; /* Unauthenticated clients count */
|
2014-03-04 18:55:24 +01:00
|
|
|
size_t nclients_unauth_max; /* Max allowed unauth clients count */
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2011-08-24 15:33:34 +02:00
|
|
|
int keepaliveInterval;
|
|
|
|
unsigned int keepaliveCount;
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetTLSContext *tls;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2012-08-09 12:31:34 +01:00
|
|
|
virNetServerClientPrivNew clientPrivNew;
|
2012-08-09 12:54:54 +01:00
|
|
|
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
|
2012-08-09 12:31:34 +01:00
|
|
|
virFreeCallback clientPrivFree;
|
|
|
|
void *clientPrivOpaque;
|
2010-12-01 16:36:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
static virClass *virNetServerClass;
|
2012-07-11 14:35:52 +01:00
|
|
|
static void virNetServerDispose(void *obj);
|
2021-03-11 08:16:13 +01:00
|
|
|
static void virNetServerUpdateServicesLocked(virNetServer *srv,
|
2013-07-25 13:27:42 +02:00
|
|
|
bool enabled);
|
2021-03-11 08:16:13 +01:00
|
|
|
static inline size_t virNetServerTrackPendingAuthLocked(virNetServer *srv);
|
|
|
|
static inline size_t virNetServerTrackCompletedAuthLocked(virNetServer *srv);
|
2012-07-11 14:35:52 +01:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
static int
|
|
|
|
virNetServerOnceInit(void)
|
2012-07-11 14:35:52 +01:00
|
|
|
{
|
2018-04-17 17:42:33 +02:00
|
|
|
if (!VIR_CLASS_NEW(virNetServer, virClassForObjectLockable()))
|
2012-07-11 14:35:52 +01:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-20 12:23:29 -05:00
|
|
|
VIR_ONCE_GLOBAL_INIT(virNetServer);
|
2012-07-11 14:35:52 +01:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
unsigned long long
|
|
|
|
virNetServerNextClientID(virNetServer *srv)
|
2016-04-13 20:54:40 +02:00
|
|
|
{
|
|
|
|
unsigned long long val;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
val = srv->next_client_id++;
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
2012-07-11 14:35:52 +01:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
static int
|
|
|
|
virNetServerProcessMsg(virNetServer *srv,
|
|
|
|
virNetServerClient *client,
|
|
|
|
virNetServerProgram *prog,
|
|
|
|
virNetMessage *msg)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2012-03-15 18:18:07 +00:00
|
|
|
if (!prog) {
|
2011-10-06 10:58:05 +01:00
|
|
|
/* Only send back an error for type == CALL. Other
|
|
|
|
* message types are not expecting replies, so we
|
|
|
|
* must just log it & drop them
|
|
|
|
*/
|
2012-03-15 18:18:07 +00:00
|
|
|
if (msg->header.type == VIR_NET_CALL ||
|
|
|
|
msg->header.type == VIR_NET_CALL_WITH_FDS) {
|
|
|
|
if (virNetServerProgramUnknownError(client,
|
|
|
|
msg,
|
|
|
|
&msg->header) < 0)
|
2019-10-21 15:19:01 -03:00
|
|
|
return -1;
|
2011-10-06 10:58:05 +01:00
|
|
|
} else {
|
2017-09-08 16:28:38 +02:00
|
|
|
VIR_INFO("Dropping client message, unknown program %d version %d type %d proc %d",
|
2012-03-15 18:18:07 +00:00
|
|
|
msg->header.prog, msg->header.vers,
|
|
|
|
msg->header.type, msg->header.proc);
|
2011-10-06 10:58:05 +01:00
|
|
|
/* Send a dummy reply to free up 'msg' & unblock client rx */
|
2012-03-15 18:18:07 +00:00
|
|
|
virNetMessageClear(msg);
|
|
|
|
msg->header.type = VIR_NET_REPLY;
|
|
|
|
if (virNetServerClientSendMessage(client, msg) < 0)
|
2019-10-21 15:19:01 -03:00
|
|
|
return -1;
|
2011-10-06 10:58:05 +01:00
|
|
|
}
|
2019-10-21 15:19:01 -03:00
|
|
|
return 0;
|
2011-10-06 10:41:28 +01:00
|
|
|
}
|
|
|
|
|
2012-03-15 18:18:07 +00:00
|
|
|
if (virNetServerProgramDispatch(prog,
|
2010-12-01 16:36:40 +00:00
|
|
|
srv,
|
2012-03-15 18:18:07 +00:00
|
|
|
client,
|
|
|
|
msg) < 0)
|
2019-10-21 15:19:01 -03:00
|
|
|
return -1;
|
2012-03-15 18:18:07 +00:00
|
|
|
|
2019-10-21 15:19:01 -03:00
|
|
|
return 0;
|
2012-03-15 18:18:07 +00:00
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
virNetServerHandleJob(void *jobOpaque,
|
|
|
|
void *opaque)
|
2012-03-15 18:18:07 +00:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServer *srv = opaque;
|
|
|
|
virNetServerJob *job = jobOpaque;
|
2012-03-15 18:18:07 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("server=%p client=%p message=%p prog=%p",
|
|
|
|
srv, job->client, job->msg, job->prog);
|
|
|
|
|
|
|
|
if (virNetServerProcessMsg(srv, job->client, job->prog, job->msg) < 0)
|
2010-12-01 16:36:40 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-07-11 14:35:52 +01:00
|
|
|
virObjectUnref(job->prog);
|
|
|
|
virObjectUnref(job->client);
|
2010-12-01 16:36:40 +00:00
|
|
|
VIR_FREE(job);
|
|
|
|
return;
|
|
|
|
|
2014-03-25 07:52:31 +01:00
|
|
|
error:
|
2012-07-11 14:35:52 +01:00
|
|
|
virObjectUnref(job->prog);
|
2010-12-01 16:36:40 +00:00
|
|
|
virNetMessageFree(job->msg);
|
|
|
|
virNetServerClientClose(job->client);
|
2012-07-11 14:35:52 +01:00
|
|
|
virObjectUnref(job->client);
|
2011-08-12 14:04:31 +02:00
|
|
|
VIR_FREE(job);
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2019-11-14 18:44:23 +01:00
|
|
|
/**
|
|
|
|
* virNetServerGetProgramLocked:
|
|
|
|
* @srv: server (must be locked by the caller)
|
|
|
|
* @msg: message
|
|
|
|
*
|
|
|
|
* Searches @srv for the right program for a given message @msg.
|
|
|
|
*
|
|
|
|
* Returns a pointer to the server program or NULL if not found.
|
|
|
|
*/
|
2021-03-11 08:16:13 +01:00
|
|
|
static virNetServerProgram *
|
|
|
|
virNetServerGetProgramLocked(virNetServer *srv,
|
|
|
|
virNetMessage *msg)
|
2019-11-14 18:44:23 +01:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < srv->nprograms; i++) {
|
|
|
|
if (virNetServerProgramMatches(srv->programs[i], msg))
|
|
|
|
return srv->programs[i];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-07-03 13:37:33 +02:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2018-07-03 13:37:33 +02:00
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerDispatchNewMessage(virNetServerClient *client,
|
|
|
|
virNetMessage *msg,
|
2018-07-03 13:37:33 +02:00
|
|
|
void *opaque)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServer *srv = opaque;
|
|
|
|
virNetServerProgram *prog = NULL;
|
2011-08-12 14:04:31 +02:00
|
|
|
unsigned int priority = 0;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("server=%p client=%p message=%p",
|
|
|
|
srv, client, msg);
|
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectLock(srv);
|
2019-11-14 18:44:23 +01:00
|
|
|
prog = virNetServerGetProgramLocked(srv, msg);
|
2018-07-03 13:37:33 +02:00
|
|
|
/* we can unlock @srv since @prog can only become invalid in case
|
|
|
|
* of disposing @srv, but let's grab a ref first to ensure nothing
|
|
|
|
* disposes of it before we use it. */
|
|
|
|
virObjectRef(srv);
|
|
|
|
virObjectUnlock(srv);
|
2011-08-12 14:04:31 +02:00
|
|
|
|
2018-08-07 13:38:00 +02:00
|
|
|
if (virThreadPoolGetMaxWorkers(srv->workers) > 0) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerJob *job;
|
2012-03-15 18:18:07 +00:00
|
|
|
|
2020-09-24 20:58:46 +02:00
|
|
|
job = g_new0(virNetServerJob, 1);
|
2011-08-12 14:04:31 +02:00
|
|
|
|
2019-11-14 18:44:19 +01:00
|
|
|
job->client = virObjectRef(client);
|
2012-03-15 18:18:07 +00:00
|
|
|
job->msg = msg;
|
|
|
|
|
|
|
|
if (prog) {
|
2017-04-03 10:24:39 +02:00
|
|
|
job->prog = virObjectRef(prog);
|
2012-03-15 18:18:07 +00:00
|
|
|
priority = virNetServerProgramGetPriority(prog, msg->header.proc);
|
|
|
|
}
|
2011-08-12 14:04:31 +02:00
|
|
|
|
2018-03-06 16:44:34 +00:00
|
|
|
if (virThreadPoolSendJob(srv->workers, priority, job) < 0) {
|
2018-03-06 16:07:35 +00:00
|
|
|
virObjectUnref(client);
|
2012-03-15 18:18:07 +00:00
|
|
|
VIR_FREE(job);
|
2012-07-11 14:35:52 +01:00
|
|
|
virObjectUnref(prog);
|
2018-03-06 16:44:34 +00:00
|
|
|
goto error;
|
2012-03-15 18:18:07 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-03-06 16:44:34 +00:00
|
|
|
if (virNetServerProcessMsg(srv, client, prog, msg) < 0)
|
|
|
|
goto error;
|
2011-08-12 14:04:31 +02:00
|
|
|
}
|
2012-03-15 18:18:07 +00:00
|
|
|
|
2018-07-03 13:37:33 +02:00
|
|
|
virObjectUnref(srv);
|
2018-03-06 16:44:34 +00:00
|
|
|
return;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2018-03-06 16:44:34 +00:00
|
|
|
error:
|
|
|
|
virNetMessageFree(msg);
|
|
|
|
virNetServerClientClose(client);
|
2018-07-03 13:37:33 +02:00
|
|
|
virObjectUnref(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
|
|
|
|
2018-07-03 13:37:33 +02:00
|
|
|
|
2016-07-20 10:17:19 +02:00
|
|
|
/**
|
|
|
|
* virNetServerCheckLimits:
|
|
|
|
* @srv: server to check limits on
|
|
|
|
*
|
|
|
|
* Check if limits like max_clients or max_anonymous_clients
|
2016-07-20 10:36:06 +02:00
|
|
|
* are satisfied. If so, re-enable accepting new clients. If these are violated
|
|
|
|
* however, temporarily disable accepting new clients.
|
2016-07-20 10:17:19 +02:00
|
|
|
* The @srv must be locked when this function is called.
|
|
|
|
*/
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerCheckLimits(virNetServer *srv)
|
2016-07-20 10:17:19 +02:00
|
|
|
{
|
2021-10-12 09:55:38 +02:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < srv->nservices; i++) {
|
|
|
|
if (virNetServerServiceTimerActive(srv->services[i])) {
|
|
|
|
VIR_DEBUG("Skipping client-related limits evaluation");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-20 10:36:06 +02:00
|
|
|
VIR_DEBUG("Checking client-related limits to re-enable or temporarily "
|
|
|
|
"suspend services: nclients=%zu nclients_max=%zu "
|
2016-07-20 10:17:19 +02:00
|
|
|
"nclients_unauth=%zu nclients_unauth_max=%zu",
|
|
|
|
srv->nclients, srv->nclients_max,
|
|
|
|
srv->nclients_unauth, srv->nclients_unauth_max);
|
2016-07-20 10:36:06 +02:00
|
|
|
|
|
|
|
/* Check the max_anonymous_clients and max_clients limits so that we can
|
|
|
|
* decide whether the services should be temporarily suspended, thus not
|
|
|
|
* accepting any more clients for a while or re-enabling the previously
|
|
|
|
* suspended services in order to accept new clients again.
|
|
|
|
* A new client can only be accepted if both max_clients and
|
|
|
|
* max_anonymous_clients wouldn't get overcommitted by accepting it.
|
|
|
|
*/
|
|
|
|
if (srv->nclients >= srv->nclients_max ||
|
|
|
|
(srv->nclients_unauth_max &&
|
|
|
|
srv->nclients_unauth >= srv->nclients_unauth_max)) {
|
|
|
|
/* Temporarily stop accepting new clients */
|
|
|
|
VIR_INFO("Temporarily suspending services");
|
|
|
|
virNetServerUpdateServicesLocked(srv, false);
|
|
|
|
} else if (srv->nclients < srv->nclients_max &&
|
|
|
|
(!srv->nclients_unauth_max ||
|
|
|
|
srv->nclients_unauth < srv->nclients_unauth_max)) {
|
2016-07-20 10:17:19 +02:00
|
|
|
/* Now it makes sense to accept() a new client. */
|
|
|
|
VIR_INFO("Re-enabling services");
|
|
|
|
virNetServerUpdateServicesLocked(srv, true);
|
|
|
|
}
|
|
|
|
}
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
int
|
|
|
|
virNetServerAddClient(virNetServer *srv,
|
|
|
|
virNetServerClient *client)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectLock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
|
|
|
if (virNetServerClientInit(client) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(srv->clients, srv->nclients, 1);
|
2017-04-03 10:24:39 +02:00
|
|
|
srv->clients[srv->nclients-1] = virObjectRef(client);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2017-12-21 15:29:03 +01:00
|
|
|
virObjectLock(client);
|
2017-12-21 15:29:05 +01:00
|
|
|
if (virNetServerClientIsAuthPendingLocked(client))
|
2014-03-04 15:37:27 +01:00
|
|
|
virNetServerTrackPendingAuthLocked(srv);
|
2017-12-21 15:29:03 +01:00
|
|
|
virObjectUnlock(client);
|
2014-03-04 15:37:27 +01:00
|
|
|
|
2016-07-20 10:36:06 +02:00
|
|
|
virNetServerCheckLimits(srv);
|
2013-07-25 13:27:42 +02:00
|
|
|
|
2010-12-01 16:36:40 +00:00
|
|
|
virNetServerClientSetDispatcher(client,
|
|
|
|
virNetServerDispatchNewMessage,
|
|
|
|
srv);
|
|
|
|
|
2020-05-05 11:29:13 +02:00
|
|
|
if (virNetServerClientInitKeepAlive(client, srv->keepaliveInterval,
|
|
|
|
srv->keepaliveCount) < 0)
|
|
|
|
goto error;
|
2011-08-24 15:33:34 +02:00
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-03-25 07:52:31 +01:00
|
|
|
error:
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
static int
|
|
|
|
virNetServerDispatchNewClient(virNetServerService *svc,
|
|
|
|
virNetSocket *clientsock,
|
|
|
|
void *opaque)
|
2012-08-09 12:35:43 +01:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServer *srv = opaque;
|
2021-11-26 17:21:46 +01:00
|
|
|
g_autoptr(virNetServerClient) client = NULL;
|
2012-08-09 12:35:43 +01:00
|
|
|
|
2016-04-13 20:54:40 +02:00
|
|
|
if (!(client = virNetServerClientNew(virNetServerNextClientID(srv),
|
|
|
|
clientsock,
|
2012-08-09 12:35:43 +01:00
|
|
|
virNetServerServiceGetAuth(svc),
|
|
|
|
virNetServerServiceIsReadonly(svc),
|
|
|
|
virNetServerServiceGetMaxRequests(svc),
|
|
|
|
virNetServerServiceGetTLSContext(svc),
|
|
|
|
srv->clientPrivNew,
|
2012-08-09 12:54:54 +01:00
|
|
|
srv->clientPrivPreExecRestart,
|
2012-08-09 12:35:43 +01:00
|
|
|
srv->clientPrivFree,
|
|
|
|
srv->clientPrivOpaque)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virNetServerAddClient(srv, client) < 0) {
|
|
|
|
virNetServerClientClose(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
virNetServer *
|
|
|
|
virNetServerNew(const char *name,
|
|
|
|
unsigned long long next_client_id,
|
|
|
|
size_t min_workers,
|
|
|
|
size_t max_workers,
|
|
|
|
size_t priority_workers,
|
|
|
|
size_t max_clients,
|
|
|
|
size_t max_anonymous_clients,
|
|
|
|
int keepaliveInterval,
|
|
|
|
unsigned int keepaliveCount,
|
|
|
|
virNetServerClientPrivNew clientPrivNew,
|
|
|
|
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart,
|
|
|
|
virFreeCallback clientPrivFree,
|
|
|
|
void *clientPrivOpaque)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2021-11-26 17:21:46 +01:00
|
|
|
g_autoptr(virNetServer) srv = NULL;
|
2021-11-26 17:23:03 +01:00
|
|
|
g_autofree char *jobName = g_strdup_printf("rpc-%s", name);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2012-07-11 14:35:52 +01:00
|
|
|
if (virNetServerInitialize() < 0)
|
2010-12-01 16:36:40 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
if (!(srv = virObjectLockableNew(virNetServerClass)))
|
2012-07-11 14:35:52 +01:00
|
|
|
return NULL;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2020-02-14 11:20:10 +00:00
|
|
|
if (!(srv->workers = virThreadPoolNewFull(min_workers, max_workers,
|
|
|
|
priority_workers,
|
|
|
|
virNetServerHandleJob,
|
2021-11-26 17:23:03 +01:00
|
|
|
jobName,
|
2021-10-26 11:04:24 +02:00
|
|
|
NULL,
|
2020-02-14 11:20:10 +00:00
|
|
|
srv)))
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
srv->name = g_strdup(name);
|
2016-03-01 15:34:15 +01:00
|
|
|
|
2016-04-13 20:54:40 +02:00
|
|
|
srv->next_client_id = next_client_id;
|
2010-12-01 16:36:40 +00:00
|
|
|
srv->nclients_max = max_clients;
|
2014-03-04 18:55:24 +01:00
|
|
|
srv->nclients_unauth_max = max_anonymous_clients;
|
2011-08-24 15:33:34 +02:00
|
|
|
srv->keepaliveInterval = keepaliveInterval;
|
|
|
|
srv->keepaliveCount = keepaliveCount;
|
2012-08-09 12:31:34 +01:00
|
|
|
srv->clientPrivNew = clientPrivNew;
|
2012-08-09 12:54:54 +01:00
|
|
|
srv->clientPrivPreExecRestart = clientPrivPreExecRestart;
|
2012-08-09 12:31:34 +01:00
|
|
|
srv->clientPrivFree = clientPrivFree;
|
|
|
|
srv->clientPrivOpaque = clientPrivOpaque;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2021-11-26 17:21:46 +01:00
|
|
|
return g_steal_pointer(&srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
virNetServer *
|
|
|
|
virNetServerNewPostExecRestart(virJSONValue *object,
|
|
|
|
const char *name,
|
|
|
|
virNetServerClientPrivNew clientPrivNew,
|
|
|
|
virNetServerClientPrivNewPostExecRestart clientPrivNewPostExecRestart,
|
|
|
|
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart,
|
|
|
|
virFreeCallback clientPrivFree,
|
|
|
|
void *clientPrivOpaque)
|
2012-08-09 12:54:54 +01:00
|
|
|
{
|
2021-11-26 17:21:46 +01:00
|
|
|
g_autoptr(virNetServer) srv = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virJSONValue *clients;
|
|
|
|
virJSONValue *services;
|
2012-08-09 12:54:54 +01:00
|
|
|
size_t i;
|
|
|
|
unsigned int min_workers;
|
|
|
|
unsigned int max_workers;
|
|
|
|
unsigned int priority_workers;
|
|
|
|
unsigned int max_clients;
|
2014-03-04 18:55:24 +01:00
|
|
|
unsigned int max_anonymous_clients;
|
2012-08-09 12:54:54 +01:00
|
|
|
unsigned int keepaliveInterval;
|
|
|
|
unsigned int keepaliveCount;
|
2016-04-13 20:54:40 +02:00
|
|
|
unsigned long long next_client_id;
|
2012-08-09 12:54:54 +01:00
|
|
|
|
|
|
|
if (virJSONValueObjectGetNumberUint(object, "min_workers", &min_workers) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing min_workers data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
if (virJSONValueObjectGetNumberUint(object, "max_workers", &max_workers) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing max_workers data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
if (virJSONValueObjectGetNumberUint(object, "priority_workers", &priority_workers) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing priority_workers data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
if (virJSONValueObjectGetNumberUint(object, "max_clients", &max_clients) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing max_clients data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
2014-03-18 11:04:27 +01:00
|
|
|
if (virJSONValueObjectHasKey(object, "max_anonymous_clients")) {
|
|
|
|
if (virJSONValueObjectGetNumberUint(object, "max_anonymous_clients",
|
|
|
|
&max_anonymous_clients) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Malformed max_anonymous_clients data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2014-03-18 11:04:27 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
max_anonymous_clients = max_clients;
|
2014-03-04 18:55:24 +01:00
|
|
|
}
|
2012-08-09 12:54:54 +01:00
|
|
|
if (virJSONValueObjectGetNumberUint(object, "keepaliveInterval", &keepaliveInterval) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing keepaliveInterval data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
if (virJSONValueObjectGetNumberUint(object, "keepaliveCount", &keepaliveCount) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing keepaliveCount data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
2016-04-13 20:54:40 +02:00
|
|
|
if (virJSONValueObjectGetNumberUlong(object, "next_client_id",
|
|
|
|
&next_client_id) < 0) {
|
|
|
|
VIR_WARN("Missing next_client_id data in JSON document");
|
|
|
|
next_client_id = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(srv = virNetServerNew(name, next_client_id,
|
2016-03-01 15:34:15 +01:00
|
|
|
min_workers, max_workers,
|
2012-08-09 12:54:54 +01:00
|
|
|
priority_workers, max_clients,
|
2014-03-04 18:55:24 +01:00
|
|
|
max_anonymous_clients,
|
2012-08-09 12:54:54 +01:00
|
|
|
keepaliveInterval, keepaliveCount,
|
|
|
|
clientPrivNew, clientPrivPreExecRestart,
|
|
|
|
clientPrivFree, clientPrivOpaque)))
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
|
|
|
|
if (!(services = virJSONValueObjectGet(object, "services"))) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing services data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:29:02 -04:00
|
|
|
if (!virJSONValueIsArray(services)) {
|
2012-08-09 12:54:54 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2018-04-19 17:29:02 -04:00
|
|
|
_("Malformed services array"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:29:02 -04:00
|
|
|
for (i = 0; i < virJSONValueArraySize(services); i++) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerService *service;
|
|
|
|
virJSONValue *child = virJSONValueArrayGet(services, i);
|
2012-08-09 12:54:54 +01:00
|
|
|
if (!child) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing service data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(service = virNetServerServiceNewPostExecRestart(child)))
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
|
2019-06-19 15:19:23 +01:00
|
|
|
if (virNetServerAddService(srv, service) < 0) {
|
2012-08-09 12:54:54 +01:00
|
|
|
virObjectUnref(service);
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!(clients = virJSONValueObjectGet(object, "clients"))) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing clients data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:29:02 -04:00
|
|
|
if (!virJSONValueIsArray(clients)) {
|
2012-08-09 12:54:54 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2018-04-19 17:29:02 -04:00
|
|
|
_("Malformed clients array"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:29:02 -04:00
|
|
|
for (i = 0; i < virJSONValueArraySize(clients); i++) {
|
2021-11-26 17:21:46 +01:00
|
|
|
g_autoptr(virNetServerClient) client = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virJSONValue *child = virJSONValueArrayGet(clients, i);
|
2012-08-09 12:54:54 +01:00
|
|
|
if (!child) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing client data in JSON document"));
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
2018-01-19 17:41:13 +00:00
|
|
|
if (!(client = virNetServerClientNewPostExecRestart(srv,
|
|
|
|
child,
|
2012-08-09 12:54:54 +01:00
|
|
|
clientPrivNewPostExecRestart,
|
|
|
|
clientPrivPreExecRestart,
|
|
|
|
clientPrivFree,
|
2018-01-19 17:41:13 +00:00
|
|
|
clientPrivOpaque)))
|
2021-11-26 17:21:46 +01:00
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
|
2021-11-26 17:21:46 +01:00
|
|
|
if (virNetServerAddClient(srv, client) < 0)
|
|
|
|
return NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
2021-11-26 17:21:46 +01:00
|
|
|
return g_steal_pointer(&srv);
|
2012-08-09 12:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
virJSONValue *
|
|
|
|
virNetServerPreExecRestart(virNetServer *srv)
|
2012-08-09 12:54:54 +01:00
|
|
|
{
|
2021-02-11 18:29:40 +01:00
|
|
|
g_autoptr(virJSONValue) object = virJSONValueNewObject();
|
|
|
|
g_autoptr(virJSONValue) clients = virJSONValueNewArray();
|
|
|
|
g_autoptr(virJSONValue) services = virJSONValueNewArray();
|
2012-08-09 12:54:54 +01:00
|
|
|
size_t i;
|
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectLock(srv);
|
2012-08-09 12:54:54 +01:00
|
|
|
|
|
|
|
if (virJSONValueObjectAppendNumberUint(object, "min_workers",
|
2021-02-11 20:32:00 +01:00
|
|
|
virThreadPoolGetMinWorkers(srv->workers)) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
|
|
|
if (virJSONValueObjectAppendNumberUint(object, "max_workers",
|
2021-02-11 20:32:00 +01:00
|
|
|
virThreadPoolGetMaxWorkers(srv->workers)) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
|
|
|
if (virJSONValueObjectAppendNumberUint(object, "priority_workers",
|
2021-02-11 20:32:00 +01:00
|
|
|
virThreadPoolGetPriorityWorkers(srv->workers)) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
2021-02-11 20:32:00 +01:00
|
|
|
|
|
|
|
if (virJSONValueObjectAppendNumberUint(object, "max_clients", srv->nclients_max) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
2014-03-04 18:55:24 +01:00
|
|
|
if (virJSONValueObjectAppendNumberUint(object, "max_anonymous_clients",
|
2021-02-11 20:32:00 +01:00
|
|
|
srv->nclients_unauth_max) < 0)
|
2014-03-04 18:55:24 +01:00
|
|
|
goto error;
|
2021-02-11 20:32:00 +01:00
|
|
|
|
|
|
|
if (virJSONValueObjectAppendNumberUint(object, "keepaliveInterval", srv->keepaliveInterval) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
2021-02-11 20:32:00 +01:00
|
|
|
if (virJSONValueObjectAppendNumberUint(object, "keepaliveCount", srv->keepaliveCount) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
|
|
|
|
2016-04-13 20:54:40 +02:00
|
|
|
if (virJSONValueObjectAppendNumberUlong(object, "next_client_id",
|
2021-02-11 20:32:00 +01:00
|
|
|
srv->next_client_id) < 0)
|
2016-04-13 20:54:40 +02:00
|
|
|
goto error;
|
|
|
|
|
2013-05-21 15:59:54 +08:00
|
|
|
for (i = 0; i < srv->nservices; i++) {
|
2021-02-11 18:29:40 +01:00
|
|
|
g_autoptr(virJSONValue) child = NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
if (!(child = virNetServerServicePreExecRestart(srv->services[i])))
|
|
|
|
goto error;
|
|
|
|
|
2021-02-11 17:57:45 +01:00
|
|
|
if (virJSONValueArrayAppend(services, &child) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2021-02-11 17:57:45 +01:00
|
|
|
if (virJSONValueObjectAppend(object, "services", &services) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
|
|
|
|
2013-05-21 15:59:54 +08:00
|
|
|
for (i = 0; i < srv->nclients; i++) {
|
2021-02-11 18:29:40 +01:00
|
|
|
g_autoptr(virJSONValue) child = NULL;
|
2012-08-09 12:54:54 +01:00
|
|
|
if (!(child = virNetServerClientPreExecRestart(srv->clients[i])))
|
|
|
|
goto error;
|
|
|
|
|
2021-02-11 17:57:45 +01:00
|
|
|
if (virJSONValueArrayAppend(clients, &child) < 0)
|
2012-08-09 12:54:54 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2021-02-11 17:57:45 +01:00
|
|
|
if (virJSONValueObjectAppend(object, "clients", &clients) < 0)
|
2021-02-11 18:29:40 +01:00
|
|
|
goto error;
|
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2012-08-09 12:54:54 +01:00
|
|
|
|
2021-02-11 18:29:40 +01:00
|
|
|
return g_steal_pointer(&object);
|
2012-08-09 12:54:54 +01:00
|
|
|
|
2014-03-25 07:52:31 +01:00
|
|
|
error:
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2012-08-09 12:54:54 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
int
|
|
|
|
virNetServerAddService(virNetServer *srv,
|
|
|
|
virNetServerService *svc)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectLock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(srv->services, srv->nservices, 1);
|
2017-04-03 10:24:39 +02:00
|
|
|
srv->services[srv->nservices-1] = virObjectRef(svc);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
|
|
|
virNetServerServiceSetDispatcher(svc,
|
|
|
|
virNetServerDispatchNewClient,
|
|
|
|
srv);
|
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-25 16:33:36 +01:00
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerAddServiceActivation(virNetServer *srv,
|
|
|
|
virSystemdActivation *act,
|
2019-06-25 16:33:36 +01:00
|
|
|
const char *actname,
|
|
|
|
int auth,
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetTLSContext *tls,
|
2019-06-25 16:33:36 +01:00
|
|
|
bool readonly,
|
|
|
|
size_t max_queued_clients,
|
|
|
|
size_t nrequests_client_max)
|
|
|
|
{
|
2022-03-02 17:22:05 +08:00
|
|
|
g_autofree int *fds = NULL;
|
2019-06-25 16:33:36 +01:00
|
|
|
size_t nfds;
|
|
|
|
|
|
|
|
if (act == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
virSystemdActivationClaimFDs(act, actname, &fds, &nfds);
|
|
|
|
|
|
|
|
if (nfds) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerService *svc;
|
2019-06-25 16:33:36 +01:00
|
|
|
|
|
|
|
svc = virNetServerServiceNewFDs(fds,
|
|
|
|
nfds,
|
|
|
|
false,
|
|
|
|
auth,
|
|
|
|
tls,
|
|
|
|
readonly,
|
|
|
|
max_queued_clients,
|
|
|
|
nrequests_client_max);
|
|
|
|
if (!svc)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virNetServerAddService(srv, svc) < 0) {
|
|
|
|
virObjectUnref(svc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Intentionally return 1 any time activation is present,
|
|
|
|
* even if we didn't find any sockets with the matching
|
|
|
|
* name. The user needs to be free to disable some of the
|
|
|
|
* services via unit files without causing us to fallback
|
|
|
|
* to creating the service manually.
|
|
|
|
*/
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
int
|
|
|
|
virNetServerAddServiceTCP(virNetServer *srv,
|
|
|
|
virSystemdActivation *act,
|
|
|
|
const char *actname,
|
|
|
|
const char *nodename,
|
|
|
|
const char *service,
|
|
|
|
int family,
|
|
|
|
int auth,
|
|
|
|
virNetTLSContext *tls,
|
|
|
|
bool readonly,
|
|
|
|
size_t max_queued_clients,
|
|
|
|
size_t nrequests_client_max)
|
2019-06-25 16:33:36 +01:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerService *svc = NULL;
|
2019-06-25 16:33:36 +01:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = virNetServerAddServiceActivation(srv, act, actname,
|
|
|
|
auth,
|
|
|
|
tls,
|
|
|
|
readonly,
|
|
|
|
max_queued_clients,
|
|
|
|
nrequests_client_max);
|
|
|
|
if (ret < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (ret == 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!(svc = virNetServerServiceNewTCP(nodename,
|
|
|
|
service,
|
|
|
|
family,
|
|
|
|
auth,
|
|
|
|
tls,
|
|
|
|
readonly,
|
|
|
|
max_queued_clients,
|
|
|
|
nrequests_client_max)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virNetServerAddService(srv, svc) < 0) {
|
|
|
|
virObjectUnref(svc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectUnref(svc);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
int
|
|
|
|
virNetServerAddServiceUNIX(virNetServer *srv,
|
|
|
|
virSystemdActivation *act,
|
|
|
|
const char *actname,
|
|
|
|
const char *path,
|
|
|
|
mode_t mask,
|
|
|
|
gid_t grp,
|
|
|
|
int auth,
|
|
|
|
virNetTLSContext *tls,
|
|
|
|
bool readonly,
|
|
|
|
size_t max_queued_clients,
|
|
|
|
size_t nrequests_client_max)
|
2019-06-25 16:33:36 +01:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerService *svc = NULL;
|
2019-06-25 16:33:36 +01:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = virNetServerAddServiceActivation(srv, act, actname,
|
|
|
|
auth,
|
|
|
|
tls,
|
|
|
|
readonly,
|
|
|
|
max_queued_clients,
|
|
|
|
nrequests_client_max);
|
|
|
|
if (ret < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (ret == 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!(svc = virNetServerServiceNewUNIX(path,
|
|
|
|
mask,
|
|
|
|
grp,
|
|
|
|
auth,
|
|
|
|
tls,
|
|
|
|
readonly,
|
|
|
|
max_queued_clients,
|
|
|
|
nrequests_client_max)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virNetServerAddService(srv, svc) < 0) {
|
|
|
|
virObjectUnref(svc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectUnref(svc);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
int
|
|
|
|
virNetServerAddProgram(virNetServer *srv,
|
|
|
|
virNetServerProgram *prog)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectLock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(srv->programs, srv->nprograms, 1);
|
2012-07-11 14:35:52 +01:00
|
|
|
srv->programs[srv->nprograms-1] = virObjectRef(prog);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
int
|
|
|
|
virNetServerSetTLSContext(virNetServer *srv,
|
|
|
|
virNetTLSContext *tls)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2012-07-11 14:35:48 +01:00
|
|
|
srv->tls = virObjectRef(tls);
|
2010-12-01 16:36:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-21 15:29:05 +01:00
|
|
|
/**
|
|
|
|
* virNetServerSetClientAuthCompletedLocked:
|
|
|
|
* @srv: server must be locked by the caller
|
|
|
|
* @client: client must be locked by the caller
|
|
|
|
*
|
|
|
|
* If the client authentication was pending, clear that pending and
|
|
|
|
* update the server tracking.
|
|
|
|
*/
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerSetClientAuthCompletedLocked(virNetServer *srv,
|
|
|
|
virNetServerClient *client)
|
2017-12-21 15:29:05 +01:00
|
|
|
{
|
|
|
|
if (virNetServerClientIsAuthPendingLocked(client)) {
|
|
|
|
virNetServerClientSetAuthPendingLocked(client, false);
|
|
|
|
virNetServerTrackCompletedAuthLocked(srv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-21 15:29:04 +01:00
|
|
|
/**
|
|
|
|
* virNetServerSetClientAuthenticated:
|
|
|
|
* @srv: server must be unlocked
|
|
|
|
* @client: client must be unlocked
|
|
|
|
*
|
|
|
|
* Mark @client as authenticated and tracks on @srv that the
|
|
|
|
* authentication of this @client has been completed. Also it checks
|
|
|
|
* the limits of @srv.
|
|
|
|
*/
|
|
|
|
void
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerSetClientAuthenticated(virNetServer *srv,
|
|
|
|
virNetServerClient *client)
|
2017-12-21 15:29:04 +01:00
|
|
|
{
|
|
|
|
virObjectLock(srv);
|
|
|
|
virObjectLock(client);
|
|
|
|
virNetServerClientSetAuthLocked(client, VIR_NET_SERVER_SERVICE_AUTH_NONE);
|
2017-12-21 15:29:05 +01:00
|
|
|
virNetServerSetClientAuthCompletedLocked(srv, client);
|
2017-12-21 15:29:04 +01:00
|
|
|
virNetServerCheckLimits(srv);
|
|
|
|
virObjectUnlock(client);
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-25 13:27:42 +02:00
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerUpdateServicesLocked(virNetServer *srv,
|
2013-07-25 13:27:42 +02:00
|
|
|
bool enabled)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/rpc/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 15:09:33 +01:00
|
|
|
size_t i;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2013-05-21 15:59:54 +08:00
|
|
|
for (i = 0; i < srv->nservices; i++)
|
2010-12-01 16:36:40 +00:00
|
|
|
virNetServerServiceToggle(srv->services[i], enabled);
|
2013-07-25 13:27:42 +02:00
|
|
|
}
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2013-07-25 13:27:42 +02:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
void
|
|
|
|
virNetServerUpdateServices(virNetServer *srv,
|
|
|
|
bool enabled)
|
2013-07-25 13:27:42 +02:00
|
|
|
{
|
|
|
|
virObjectLock(srv);
|
|
|
|
virNetServerUpdateServicesLocked(srv, enabled);
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
void
|
|
|
|
virNetServerDispose(void *obj)
|
2010-12-01 16:36:40 +00:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServer *srv = obj;
|
Convert 'int i' to 'size_t i' in src/rpc/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 15:09:33 +01:00
|
|
|
size_t i;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2021-02-03 15:14:57 -05:00
|
|
|
g_free(srv->name);
|
2016-03-01 15:34:15 +01:00
|
|
|
|
2010-12-01 16:36:40 +00:00
|
|
|
virThreadPoolFree(srv->workers);
|
|
|
|
|
2013-05-21 15:59:54 +08:00
|
|
|
for (i = 0; i < srv->nservices; i++)
|
2012-07-11 14:35:52 +01:00
|
|
|
virObjectUnref(srv->services[i]);
|
2021-02-03 15:14:57 -05:00
|
|
|
g_free(srv->services);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2013-05-21 15:59:54 +08:00
|
|
|
for (i = 0; i < srv->nprograms; i++)
|
2012-07-11 14:35:52 +01:00
|
|
|
virObjectUnref(srv->programs[i]);
|
2021-02-03 15:14:57 -05:00
|
|
|
g_free(srv->programs);
|
2010-12-01 16:36:40 +00:00
|
|
|
|
2017-12-20 17:36:10 +01:00
|
|
|
for (i = 0; i < srv->nclients; i++)
|
2012-07-11 14:35:52 +01:00
|
|
|
virObjectUnref(srv->clients[i]);
|
2021-02-03 15:14:57 -05:00
|
|
|
g_free(srv->clients);
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
2011-08-04 16:54:58 +08:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
|
|
|
void
|
|
|
|
virNetServerClose(virNetServer *srv)
|
2011-08-04 16:54:58 +08:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/rpc/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 15:09:33 +01:00
|
|
|
size_t i;
|
2011-08-04 16:54:58 +08:00
|
|
|
|
|
|
|
if (!srv)
|
|
|
|
return;
|
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectLock(srv);
|
2011-08-04 16:54:58 +08:00
|
|
|
|
2014-11-13 15:29:21 +01:00
|
|
|
for (i = 0; i < srv->nservices; i++)
|
2011-08-04 16:54:58 +08:00
|
|
|
virNetServerServiceClose(srv->services[i]);
|
|
|
|
|
2017-12-20 17:36:10 +01:00
|
|
|
for (i = 0; i < srv->nclients; i++)
|
|
|
|
virNetServerClientClose(srv->clients[i]);
|
|
|
|
|
2020-07-23 09:50:25 +03:00
|
|
|
virThreadPoolStop(srv->workers);
|
|
|
|
|
2013-01-09 21:27:28 +00:00
|
|
|
virObjectUnlock(srv);
|
2011-08-04 16:54:58 +08:00
|
|
|
}
|
2011-08-24 15:33:34 +02:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2020-07-23 09:50:25 +03:00
|
|
|
void
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerShutdownWait(virNetServer *srv)
|
2020-07-23 09:50:25 +03:00
|
|
|
{
|
|
|
|
virThreadPoolDrain(srv->workers);
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2014-03-04 15:37:27 +01:00
|
|
|
static inline size_t
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerTrackPendingAuthLocked(virNetServer *srv)
|
2014-03-04 15:37:27 +01:00
|
|
|
{
|
|
|
|
return ++srv->nclients_unauth;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2014-03-04 15:37:27 +01:00
|
|
|
static inline size_t
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerTrackCompletedAuthLocked(virNetServer *srv)
|
2014-03-04 15:37:27 +01:00
|
|
|
{
|
|
|
|
return --srv->nclients_unauth;
|
|
|
|
}
|
|
|
|
|
2015-03-16 15:02:41 +01:00
|
|
|
|
|
|
|
bool
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerHasClients(virNetServer *srv)
|
2015-03-16 15:02:41 +01:00
|
|
|
{
|
|
|
|
bool ret;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
ret = !!srv->nclients;
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2015-03-16 15:02:41 +01:00
|
|
|
void
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerProcessClients(virNetServer *srv)
|
2015-03-16 15:02:41 +01:00
|
|
|
{
|
|
|
|
size_t i;
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient *client;
|
2015-03-16 15:02:41 +01:00
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
|
|
|
|
reprocess:
|
|
|
|
for (i = 0; i < srv->nclients; i++) {
|
2017-12-21 15:29:03 +01:00
|
|
|
client = srv->clients[i];
|
|
|
|
virObjectLock(client);
|
|
|
|
if (virNetServerClientWantCloseLocked(client))
|
|
|
|
virNetServerClientCloseLocked(client);
|
|
|
|
|
|
|
|
if (virNetServerClientIsClosedLocked(client)) {
|
2015-03-16 15:02:41 +01:00
|
|
|
VIR_DELETE_ELEMENT(srv->clients, i, srv->nclients);
|
|
|
|
|
2017-12-21 15:29:05 +01:00
|
|
|
/* Update server authentication tracking */
|
|
|
|
virNetServerSetClientAuthCompletedLocked(srv, client);
|
2017-12-21 15:29:03 +01:00
|
|
|
virObjectUnlock(client);
|
2015-03-16 15:02:41 +01:00
|
|
|
|
|
|
|
virNetServerCheckLimits(srv);
|
|
|
|
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
virObjectUnref(client);
|
|
|
|
virObjectLock(srv);
|
|
|
|
|
|
|
|
goto reprocess;
|
2017-12-21 15:29:03 +01:00
|
|
|
} else {
|
|
|
|
virObjectUnlock(client);
|
2015-03-16 15:02:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2016-03-01 15:34:15 +01:00
|
|
|
const char *
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerGetName(virNetServer *srv)
|
2016-03-01 15:34:15 +01:00
|
|
|
{
|
|
|
|
return srv->name;
|
|
|
|
}
|
2015-11-23 12:41:32 +01:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2015-11-23 12:41:32 +01:00
|
|
|
int
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerGetThreadPoolParameters(virNetServer *srv,
|
2015-11-23 12:41:32 +01:00
|
|
|
size_t *minWorkers,
|
|
|
|
size_t *maxWorkers,
|
|
|
|
size_t *nWorkers,
|
|
|
|
size_t *freeWorkers,
|
|
|
|
size_t *nPrioWorkers,
|
|
|
|
size_t *jobQueueDepth)
|
|
|
|
{
|
|
|
|
virObjectLock(srv);
|
|
|
|
|
|
|
|
*minWorkers = virThreadPoolGetMinWorkers(srv->workers);
|
|
|
|
*maxWorkers = virThreadPoolGetMaxWorkers(srv->workers);
|
|
|
|
*freeWorkers = virThreadPoolGetFreeWorkers(srv->workers);
|
|
|
|
*nWorkers = virThreadPoolGetCurrentWorkers(srv->workers);
|
|
|
|
*nPrioWorkers = virThreadPoolGetPriorityWorkers(srv->workers);
|
|
|
|
*jobQueueDepth = virThreadPoolGetJobQueueDepth(srv->workers);
|
|
|
|
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
return 0;
|
|
|
|
}
|
admin: Introduce virAdmServerSetThreadPoolParameters
Since threadpool increments the current number of threads according to current
load, i.e. how many jobs are waiting in the queue. The count however, is
constrained by max and min limits of workers. The logic of this new API works
like this:
1) setting the minimum
a) When the limit is increased, depending on the current number of
threads, new threads are possibly spawned if the current number of
threads is less than the new minimum limit
b) Decreasing the minimum limit has no possible effect on the current
number of threads
2) setting the maximum
a) Icreasing the maximum limit has no immediate effect on the current
number of threads, it only allows the threadpool to spawn more
threads when new jobs, that would otherwise end up queued, arrive.
b) Decreasing the maximum limit may affect the current number of
threads, if the current number of threads is less than the new
maximum limit. Since there may be some ongoing time-consuming jobs
that would effectively block this API from killing any threads.
Therefore, this API is asynchronous with best-effort execution,
i.e. the necessary number of workers will be terminated once they
finish their previous job, unless other workers had already
terminated, decreasing the limit to the requested value.
3) setting priority workers
- both increase and decrease in count of these workers have an
immediate impact on the current number of workers, new ones will be
spawned or some of them get terminated respectively.
Signed-off-by: Erik Skultety <eskultet@redhat.com>
2016-02-22 14:24:04 +01:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
admin: Introduce virAdmServerSetThreadPoolParameters
Since threadpool increments the current number of threads according to current
load, i.e. how many jobs are waiting in the queue. The count however, is
constrained by max and min limits of workers. The logic of this new API works
like this:
1) setting the minimum
a) When the limit is increased, depending on the current number of
threads, new threads are possibly spawned if the current number of
threads is less than the new minimum limit
b) Decreasing the minimum limit has no possible effect on the current
number of threads
2) setting the maximum
a) Icreasing the maximum limit has no immediate effect on the current
number of threads, it only allows the threadpool to spawn more
threads when new jobs, that would otherwise end up queued, arrive.
b) Decreasing the maximum limit may affect the current number of
threads, if the current number of threads is less than the new
maximum limit. Since there may be some ongoing time-consuming jobs
that would effectively block this API from killing any threads.
Therefore, this API is asynchronous with best-effort execution,
i.e. the necessary number of workers will be terminated once they
finish their previous job, unless other workers had already
terminated, decreasing the limit to the requested value.
3) setting priority workers
- both increase and decrease in count of these workers have an
immediate impact on the current number of workers, new ones will be
spawned or some of them get terminated respectively.
Signed-off-by: Erik Skultety <eskultet@redhat.com>
2016-02-22 14:24:04 +01:00
|
|
|
int
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerSetThreadPoolParameters(virNetServer *srv,
|
admin: Introduce virAdmServerSetThreadPoolParameters
Since threadpool increments the current number of threads according to current
load, i.e. how many jobs are waiting in the queue. The count however, is
constrained by max and min limits of workers. The logic of this new API works
like this:
1) setting the minimum
a) When the limit is increased, depending on the current number of
threads, new threads are possibly spawned if the current number of
threads is less than the new minimum limit
b) Decreasing the minimum limit has no possible effect on the current
number of threads
2) setting the maximum
a) Icreasing the maximum limit has no immediate effect on the current
number of threads, it only allows the threadpool to spawn more
threads when new jobs, that would otherwise end up queued, arrive.
b) Decreasing the maximum limit may affect the current number of
threads, if the current number of threads is less than the new
maximum limit. Since there may be some ongoing time-consuming jobs
that would effectively block this API from killing any threads.
Therefore, this API is asynchronous with best-effort execution,
i.e. the necessary number of workers will be terminated once they
finish their previous job, unless other workers had already
terminated, decreasing the limit to the requested value.
3) setting priority workers
- both increase and decrease in count of these workers have an
immediate impact on the current number of workers, new ones will be
spawned or some of them get terminated respectively.
Signed-off-by: Erik Skultety <eskultet@redhat.com>
2016-02-22 14:24:04 +01:00
|
|
|
long long int minWorkers,
|
|
|
|
long long int maxWorkers,
|
|
|
|
long long int prioWorkers)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
ret = virThreadPoolSetParameters(srv->workers, minWorkers,
|
|
|
|
maxWorkers, prioWorkers);
|
|
|
|
virObjectUnlock(srv);
|
2016-04-09 19:07:11 +02:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2016-04-09 19:07:11 +02:00
|
|
|
size_t
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerGetMaxClients(virNetServer *srv)
|
2016-04-09 19:07:11 +02:00
|
|
|
{
|
|
|
|
size_t ret;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
ret = srv->nclients_max;
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2016-04-09 19:07:11 +02:00
|
|
|
size_t
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerGetCurrentClients(virNetServer *srv)
|
2016-04-09 19:07:11 +02:00
|
|
|
{
|
|
|
|
size_t ret;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
ret = srv->nclients;
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2016-04-09 19:07:11 +02:00
|
|
|
size_t
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerGetMaxUnauthClients(virNetServer *srv)
|
2016-04-09 19:07:11 +02:00
|
|
|
{
|
|
|
|
size_t ret;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
ret = srv->nclients_unauth_max;
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2016-04-09 19:07:11 +02:00
|
|
|
size_t
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerGetCurrentUnauthClients(virNetServer *srv)
|
2016-04-09 19:07:11 +02:00
|
|
|
{
|
|
|
|
size_t ret;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
ret = srv->nclients_unauth;
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
admin: Introduce virAdmServerSetThreadPoolParameters
Since threadpool increments the current number of threads according to current
load, i.e. how many jobs are waiting in the queue. The count however, is
constrained by max and min limits of workers. The logic of this new API works
like this:
1) setting the minimum
a) When the limit is increased, depending on the current number of
threads, new threads are possibly spawned if the current number of
threads is less than the new minimum limit
b) Decreasing the minimum limit has no possible effect on the current
number of threads
2) setting the maximum
a) Icreasing the maximum limit has no immediate effect on the current
number of threads, it only allows the threadpool to spawn more
threads when new jobs, that would otherwise end up queued, arrive.
b) Decreasing the maximum limit may affect the current number of
threads, if the current number of threads is less than the new
maximum limit. Since there may be some ongoing time-consuming jobs
that would effectively block this API from killing any threads.
Therefore, this API is asynchronous with best-effort execution,
i.e. the necessary number of workers will be terminated once they
finish their previous job, unless other workers had already
terminated, decreasing the limit to the requested value.
3) setting priority workers
- both increase and decrease in count of these workers have an
immediate impact on the current number of workers, new ones will be
spawned or some of them get terminated respectively.
Signed-off-by: Erik Skultety <eskultet@redhat.com>
2016-02-22 14:24:04 +01:00
|
|
|
return ret;
|
|
|
|
}
|
2016-04-15 00:21:05 +02:00
|
|
|
|
2019-06-25 17:04:47 +01:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
bool
|
|
|
|
virNetServerNeedsAuth(virNetServer *srv,
|
|
|
|
int auth)
|
2019-06-25 17:04:47 +01:00
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
for (i = 0; i < srv->nservices; i++) {
|
|
|
|
if (virNetServerServiceGetAuth(srv->services[i]) == auth)
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2016-04-15 00:21:05 +02:00
|
|
|
int
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerGetClients(virNetServer *srv,
|
|
|
|
virNetServerClient ***clts)
|
2016-04-15 00:21:05 +02:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
size_t nclients = 0;
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient **list = NULL;
|
2016-04-15 00:21:05 +02:00
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
|
|
|
|
for (i = 0; i < srv->nclients; i++) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient *client = virObjectRef(srv->clients[i]);
|
2021-08-03 14:14:20 +02:00
|
|
|
VIR_APPEND_ELEMENT(list, nclients, client);
|
2016-04-15 00:21:05 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 14:58:29 +01:00
|
|
|
*clts = g_steal_pointer(&list);
|
2016-04-15 00:21:05 +02:00
|
|
|
|
|
|
|
virObjectUnlock(srv);
|
2021-08-04 11:36:31 +02:00
|
|
|
|
|
|
|
return nclients;
|
2016-04-15 00:21:05 +02:00
|
|
|
}
|
2016-04-22 09:47:09 +02:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient *
|
|
|
|
virNetServerGetClient(virNetServer *srv,
|
2016-04-22 09:47:09 +02:00
|
|
|
unsigned long long id)
|
|
|
|
{
|
|
|
|
size_t i;
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient *ret = NULL;
|
2016-04-22 09:47:09 +02:00
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
|
|
|
|
for (i = 0; i < srv->nclients; i++) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerClient *client = srv->clients[i];
|
2016-04-22 09:47:09 +02:00
|
|
|
if (virNetServerClientGetID(client) == id)
|
|
|
|
ret = virObjectRef(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
virReportError(VIR_ERR_NO_CLIENT,
|
|
|
|
_("No client with matching ID '%llu'"), id);
|
|
|
|
return ret;
|
|
|
|
}
|
2016-04-04 14:24:52 +02:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2016-04-04 14:24:52 +02:00
|
|
|
int
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerSetClientLimits(virNetServer *srv,
|
2016-07-20 09:32:20 +02:00
|
|
|
long long int maxClients,
|
|
|
|
long long int maxClientsUnauth)
|
2016-04-04 14:24:52 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2016-07-20 12:10:29 +02:00
|
|
|
virNetServerCheckLimits(srv);
|
|
|
|
|
2016-04-04 14:24:52 +02:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
return ret;
|
|
|
|
}
|
2020-03-07 19:31:00 +08:00
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
static virNetTLSContext *
|
|
|
|
virNetServerGetTLSContext(virNetServer *srv)
|
2020-03-07 19:31:00 +08:00
|
|
|
{
|
|
|
|
size_t i;
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetTLSContext *ctxt = NULL;
|
|
|
|
virNetServerService *svc = NULL;
|
2020-03-07 19:31:00 +08:00
|
|
|
|
|
|
|
/* find svcTLS from srv, get svcTLS->tls */
|
|
|
|
for (i = 0; i < srv->nservices; i++) {
|
|
|
|
svc = srv->services[i];
|
|
|
|
ctxt = virNetServerServiceGetTLSContext(svc);
|
|
|
|
if (ctxt != NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ctxt;
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:58:07 +01:00
|
|
|
|
2020-03-07 19:31:00 +08:00
|
|
|
int
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetServerUpdateTlsFiles(virNetServer *srv)
|
2020-03-07 19:31:00 +08:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
virNetTLSContext *ctxt = NULL;
|
2020-05-05 08:05:18 +02:00
|
|
|
bool privileged = geteuid() == 0;
|
2020-03-07 19:31:00 +08:00
|
|
|
|
|
|
|
ctxt = virNetServerGetTLSContext(srv);
|
|
|
|
if (!ctxt) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("no tls service found, unable to update tls files"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virObjectLock(srv);
|
|
|
|
virObjectLock(ctxt);
|
|
|
|
|
|
|
|
if (virNetTLSContextReloadForServer(ctxt, !privileged)) {
|
|
|
|
VIR_DEBUG("failed to reload server's tls context");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("update tls files success");
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnlock(ctxt);
|
|
|
|
virObjectUnlock(srv);
|
|
|
|
return ret;
|
|
|
|
}
|