rpc: virnetserverclient: Identify clients by an integer ID

Admin API needs a way of addressing specific clients. Unlike servers, which we
are happy to address by names both because its name reflects its purpose (to
some extent) and we only have two of them (so far), naming clients doesn't make
any sense, since a) each client is an anonymous, i.e. not recognized after a
disconnect followed by a reconnect, b) we can't predict what kind of requests
it's going to send to daemon, and c) the are loads of them comming and going,
so the only viable option is to use an ID which is of a reasonably wide data
type.

Signed-off-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Erik Skultety 2016-04-13 20:54:40 +02:00
parent 6620cd1efc
commit 5841d64d25
19 changed files with 249 additions and 19 deletions

View File

@ -1389,7 +1389,7 @@ int main(int argc, char **argv) {
goto cleanup;
}
if (!(srv = virNetServerNew("libvirtd",
if (!(srv = virNetServerNew("libvirtd", 1,
config->min_workers,
config->max_workers,
config->prio_workers,
@ -1464,7 +1464,7 @@ int main(int argc, char **argv) {
goto cleanup;
}
if (!(srvAdm = virNetServerNew("admin",
if (!(srvAdm = virNetServerNew("admin", 1,
config->admin_min_workers,
config->admin_max_workers,
0,

View File

@ -105,6 +105,7 @@ virNetServerGetName;
virNetServerHasClients;
virNetServerNew;
virNetServerNewPostExecRestart;
virNetServerNextClientID;
virNetServerPreExecRestart;
virNetServerProcessClients;
virNetServerStart;

View File

@ -160,7 +160,7 @@ virLockDaemonNew(virLockDaemonConfigPtr config, bool privileged)
return NULL;
}
if (!(srv = virNetServerNew("virtlockd",
if (!(srv = virNetServerNew("virtlockd", 1,
1, 1, 0, config->max_clients,
config->max_clients, -1, 0,
NULL,

View File

@ -150,7 +150,7 @@ virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged)
return NULL;
}
if (!(logd->srv = virNetServerNew("virtlogd",
if (!(logd->srv = virNetServerNew("virtlogd", 1,
1, 1, 0, config->max_clients,
config->max_clients, -1, 0,
NULL,

View File

@ -934,7 +934,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
LXC_STATE_DIR, ctrl->name) < 0)
return -1;
if (!(srv = virNetServerNew("LXC",
if (!(srv = virNetServerNew("LXC", 1,
0, 0, 0, 1,
0, -1, 0,
NULL,

View File

@ -65,6 +65,7 @@ struct _virNetServer {
size_t nclients; /* Current clients count */
virNetServerClientPtr *clients; /* Clients */
unsigned long long next_client_id; /* next client ID */
size_t nclients_max; /* Max allowed clients count */
size_t nclients_unauth; /* Unauthenticated clients count */
size_t nclients_unauth_max; /* Max allowed unauth clients count */
@ -103,6 +104,16 @@ static int virNetServerOnceInit(void)
VIR_ONCE_GLOBAL_INIT(virNetServer)
unsigned long long virNetServerNextClientID(virNetServerPtr srv)
{
unsigned long long val;
virObjectLock(srv);
val = srv->next_client_id++;
virObjectUnlock(srv);
return val;
}
static int virNetServerProcessMsg(virNetServerPtr srv,
virNetServerClientPtr client,
@ -283,7 +294,8 @@ static int virNetServerDispatchNewClient(virNetServerServicePtr svc,
virNetServerPtr srv = opaque;
virNetServerClientPtr client;
if (!(client = virNetServerClientNew(clientsock,
if (!(client = virNetServerClientNew(virNetServerNextClientID(srv),
clientsock,
virNetServerServiceGetAuth(svc),
virNetServerServiceIsReadonly(svc),
virNetServerServiceGetMaxRequests(svc),
@ -307,6 +319,7 @@ static int virNetServerDispatchNewClient(virNetServerServicePtr svc,
virNetServerPtr virNetServerNew(const char *name,
unsigned long long next_client_id,
size_t min_workers,
size_t max_workers,
size_t priority_workers,
@ -338,6 +351,7 @@ virNetServerPtr virNetServerNew(const char *name,
if (VIR_STRDUP(srv->name, name) < 0)
goto error;
srv->next_client_id = next_client_id;
srv->nclients_max = max_clients;
srv->nclients_unauth_max = max_anonymous_clients;
srv->keepaliveInterval = keepaliveInterval;
@ -384,6 +398,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
unsigned int max_anonymous_clients;
unsigned int keepaliveInterval;
unsigned int keepaliveCount;
unsigned long long next_client_id;
const char *mdnsGroupName = NULL;
if (virJSONValueObjectGetNumberUint(object, "min_workers", &min_workers) < 0) {
@ -434,7 +449,13 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
goto error;
}
if (!(srv = virNetServerNew(name,
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,
min_workers, max_workers,
priority_workers, max_clients,
max_anonymous_clients,
@ -503,7 +524,8 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
clientPrivNewPostExecRestart,
clientPrivPreExecRestart,
clientPrivFree,
clientPrivOpaque)))
clientPrivOpaque,
srv)))
goto error;
if (virNetServerAddClient(srv, client) < 0) {
@ -573,6 +595,13 @@ virJSONValuePtr virNetServerPreExecRestart(virNetServerPtr srv)
goto error;
}
if (virJSONValueObjectAppendNumberUlong(object, "next_client_id",
srv->next_client_id) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot set next_client_id data in JSON document"));
goto error;
}
if (srv->mdnsGroupName &&
virJSONValueObjectAppendString(object, "mdnsGroupName", srv->mdnsGroupName) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",

View File

@ -35,6 +35,7 @@
virNetServerPtr virNetServerNew(const char *name,
unsigned long long next_client_id,
size_t min_workers,
size_t max_workers,
size_t priority_workers,
@ -102,4 +103,6 @@ int virNetServerSetThreadPoolParameters(virNetServerPtr srv,
long long int maxWorkers,
long long int prioWorkers);
unsigned long long virNetServerNextClientID(virNetServerPtr srv);
#endif /* __VIR_NET_SERVER_H__ */

View File

@ -28,6 +28,7 @@
# include <sasl/sasl.h>
#endif
#include "virnetserver.h"
#include "virnetserverclient.h"
#include "virlog.h"
@ -65,6 +66,7 @@ struct _virNetServerClient
{
virObjectLockable parent;
unsigned long long id;
bool wantClose;
bool delayedClose;
virNetSocketPtr sock;
@ -346,7 +348,8 @@ static void virNetServerClientSockTimerFunc(int timer,
static virNetServerClientPtr
virNetServerClientNewInternal(virNetSocketPtr sock,
virNetServerClientNewInternal(unsigned long long id,
virNetSocketPtr sock,
int auth,
#ifdef WITH_GNUTLS
virNetTLSContextPtr tls,
@ -362,6 +365,7 @@ virNetServerClientNewInternal(virNetSocketPtr sock,
if (!(client = virObjectLockableNew(virNetServerClientClass)))
return NULL;
client->id = id;
client->sock = virObjectRef(sock);
client->auth = auth;
client->readonly = readonly;
@ -395,7 +399,8 @@ virNetServerClientNewInternal(virNetSocketPtr sock,
}
virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock,
virNetServerClientPtr virNetServerClientNew(unsigned long long id,
virNetSocketPtr sock,
int auth,
bool readonly,
size_t nrequests_max,
@ -417,7 +422,7 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock,
#endif
);
if (!(client = virNetServerClientNewInternal(sock, auth,
if (!(client = virNetServerClientNewInternal(id, sock, auth,
#ifdef WITH_GNUTLS
tls,
#endif
@ -441,7 +446,8 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec
virNetServerClientPrivNewPostExecRestart privNew,
virNetServerClientPrivPreExecRestart privPreExecRestart,
virFreeCallback privFree,
void *privOpaque)
void *privOpaque,
void *opaque)
{
virJSONValuePtr child;
virNetServerClientPtr client = NULL;
@ -449,6 +455,7 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec
int auth;
bool readonly;
unsigned int nrequests_max;
unsigned long long id;
if (virJSONValueObjectGetNumberInt(object, "auth", &auth) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@ -473,12 +480,25 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec
return NULL;
}
if (!virJSONValueObjectHasKey(object, "id")) {
/* no ID found in, a new one must be generated */
id = virNetServerNextClientID((virNetServerPtr) opaque);
} else {
if (virJSONValueObjectGetNumberUlong(object, "id",
(unsigned long long *) &id) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Malformed id field in JSON state document"));
return NULL;
}
}
if (!(sock = virNetSocketNewPostExecRestart(child))) {
virObjectUnref(sock);
return NULL;
}
if (!(client = virNetServerClientNewInternal(sock,
if (!(client = virNetServerClientNewInternal(id,
sock,
auth,
#ifdef WITH_GNUTLS
NULL,
@ -521,6 +541,10 @@ virJSONValuePtr virNetServerClientPreExecRestart(virNetServerClientPtr client)
virObjectLock(client);
if (virJSONValueObjectAppendNumberUlong(object, "id",
client->id) < 0)
goto error;
if (virJSONValueObjectAppendNumberInt(object, "auth", client->auth) < 0)
goto error;
if (virJSONValueObjectAppendBoolean(object, "readonly", client->readonly) < 0)
@ -581,6 +605,10 @@ bool virNetServerClientGetReadonly(virNetServerClientPtr client)
return readonly;
}
unsigned long long virNetServerClientGetID(virNetServerClientPtr client)
{
return client->id;
}
#ifdef WITH_GNUTLS
bool virNetServerClientHasTLSSession(virNetServerClientPtr client)

View File

@ -49,7 +49,8 @@ typedef void *(*virNetServerClientPrivNewPostExecRestart)(virNetServerClientPtr
typedef void *(*virNetServerClientPrivNew)(virNetServerClientPtr client,
void *opaque);
virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock,
virNetServerClientPtr virNetServerClientNew(unsigned long long id,
virNetSocketPtr sock,
int auth,
bool readonly,
size_t nrequests_max,
@ -65,7 +66,8 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec
virNetServerClientPrivNewPostExecRestart privNew,
virNetServerClientPrivPreExecRestart privPreExecRestart,
virFreeCallback privFree,
void *privOpaque);
void *privOpaque,
void *opaque);
virJSONValuePtr virNetServerClientPreExecRestart(virNetServerClientPtr client);
@ -79,6 +81,7 @@ void virNetServerClientRemoveFilter(virNetServerClientPtr client,
int virNetServerClientGetAuth(virNetServerClientPtr client);
void virNetServerClientSetAuth(virNetServerClientPtr client, int auth);
bool virNetServerClientGetReadonly(virNetServerClientPtr client);
unsigned long long virNetServerClientGetID(virNetServerClientPtr client);
# ifdef WITH_GNUTLS
bool virNetServerClientHasTLSSession(virNetServerClientPtr client);

View File

@ -0,0 +1,68 @@
{
"servers": {
"testServer0": {
"min_workers": 10,
"max_workers": 50,
"priority_workers": 5,
"max_clients": 100,
"max_anonymous_clients": 10,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 5,
"services": [
{
"auth": 0,
"readonly": true,
"nrequests_client_max": 2,
"socks": [
{
"fd": 100,
"errfd": -1,
"pid": 0,
"isClient": false
}
]
},
{
"auth": 2,
"readonly": false,
"nrequests_client_max": 5,
"socks": [
{
"fd": 101,
"errfd": -1,
"pid": 0,
"isClient": false
}
]
}
],
"clients": [
{
"id": 2,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
"sock": {
"fd": 102,
"errfd": -1,
"pid": -1,
"isClient": true
}
},
{
"id": 3,
"auth": 2,
"readonly": true,
"nrequests_max": 66,
"sock": {
"fd": 103,
"errfd": -1,
"pid": -1,
"isClient": true
}
}
]
}
}
}

View File

@ -8,6 +8,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -38,6 +39,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -49,6 +51,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,
@ -69,6 +72,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -99,6 +103,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -110,6 +115,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,

View File

@ -8,6 +8,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -38,6 +39,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -49,6 +51,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,
@ -69,6 +72,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -99,6 +103,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -110,6 +115,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,

View File

@ -8,6 +8,7 @@
"max_anonymous_clients": 10,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -38,6 +39,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -49,6 +51,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,

View File

@ -0,0 +1,68 @@
{
"servers": {
"testServer0": {
"min_workers": 10,
"max_workers": 50,
"priority_workers": 5,
"max_clients": 100,
"max_anonymous_clients": 10,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 5,
"services": [
{
"auth": 0,
"readonly": true,
"nrequests_client_max": 2,
"socks": [
{
"fd": 100,
"errfd": -1,
"pid": 0,
"isClient": false
}
]
},
{
"auth": 2,
"readonly": false,
"nrequests_client_max": 5,
"socks": [
{
"fd": 101,
"errfd": -1,
"pid": 0,
"isClient": false
}
]
}
],
"clients": [
{
"id": 2,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
"sock": {
"fd": 102,
"errfd": -1,
"pid": -1,
"isClient": true
}
},
{
"id": 3,
"auth": 2,
"readonly": true,
"nrequests_max": 66,
"sock": {
"fd": 103,
"errfd": -1,
"pid": -1,
"isClient": true
}
}
]
}
}
}

View File

@ -8,6 +8,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -38,6 +39,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -49,6 +51,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,

View File

@ -8,6 +8,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"mdnsGroupName": "libvirtTest",
"services": [
{
@ -39,6 +40,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -50,6 +52,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,

View File

@ -8,6 +8,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -38,6 +39,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -49,6 +51,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,
@ -69,6 +72,7 @@
"max_anonymous_clients": 100,
"keepaliveInterval": 120,
"keepaliveCount": 5,
"next_client_id": 3,
"services": [
{
"auth": 0,
@ -99,6 +103,7 @@
],
"clients": [
{
"id": 1,
"auth": 1,
"readonly": true,
"nrequests_max": 15,
@ -110,6 +115,7 @@
}
},
{
"id": 2,
"auth": 2,
"readonly": true,
"nrequests_max": 66,

View File

@ -49,7 +49,7 @@ testCreateServer(const char *server_name, const char *host, int family)
goto cleanup;
}
if (!(srv = virNetServerNew(server_name,
if (!(srv = virNetServerNew(server_name, 1,
10, 50, 5, 100, 10,
120, 5,
mdns_group,
@ -93,7 +93,8 @@ testCreateServer(const char *server_name, const char *host, int family)
if (virNetSocketNewConnectSockFD(fdclient[1], &sk2) < 0)
goto error;
if (!(cln1 = virNetServerClientNew(sk1,
if (!(cln1 = virNetServerClientNew(virNetServerNextClientID(srv),
sk1,
VIR_NET_SERVER_SERVICE_AUTH_SASL,
true,
15,
@ -103,7 +104,8 @@ testCreateServer(const char *server_name, const char *host, int family)
NULL, NULL, NULL, NULL)))
goto error;
if (!(cln2 = virNetServerClientNew(sk2,
if (!(cln2 = virNetServerClientNew(virNetServerNextClientID(srv),
sk2,
VIR_NET_SERVER_SERVICE_AUTH_POLKIT,
true,
66,
@ -336,6 +338,7 @@ mymain(void)
EXEC_RESTART_TEST("admin-nomdns", 2);
EXEC_RESTART_TEST("admin-server-names", 2);
EXEC_RESTART_TEST("no-keepalive-required", 2);
EXEC_RESTART_TEST("client-ids", 1);
EXEC_RESTART_TEST_FAIL("anon-clients", 2);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;

View File

@ -52,7 +52,7 @@ static int testIdentity(const void *opaque ATTRIBUTE_UNUSED)
}
sv[0] = -1;
if (!(client = virNetServerClientNew(sock, 0, false, 1,
if (!(client = virNetServerClientNew(1, sock, 0, false, 1,
# ifdef WITH_GNUTLS
NULL,
# endif