Add JSON serialization of virNetServerClientPtr objects for process re-exec()

Add two new APIs virNetServerClientNewPostExecRestart and
virNetServerClientPreExecRestart which allow a virNetServerClientPtr
object to be created from a JSON object and saved to a
JSON object, for the purpose of re-exec'ing a process.

This includes serialization of the connected socket associated
with the client

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2012-08-09 12:54:54 +01:00
parent 0cc7925520
commit 3cfc3d7d2c
7 changed files with 159 additions and 0 deletions

View File

@ -1216,6 +1216,7 @@ int main(int argc, char **argv) {
!!config->keepalive_required,
config->mdns_adv ? config->mdns_name : NULL,
remoteClientInitHook,
NULL,
remoteClientFreeFunc,
NULL))) {
ret = VIR_DAEMON_ERR_INIT;

View File

@ -1594,6 +1594,8 @@ virNetServerClientIsSecure;
virNetServerClientLocalAddrString;
virNetServerClientNeedAuth;
virNetServerClientNew;
virNetServerClientNewPostExecRestart;
virNetServerClientPreExecRestart;
virNetServerClientRemoteAddrString;
virNetServerClientRemoveFilter;
virNetServerClientSendMessage;

View File

@ -609,6 +609,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
-1, 0, false,
NULL,
virLXCControllerClientPrivateNew,
NULL,
virLXCControllerClientPrivateFree,
ctrl)))
goto error;

View File

@ -105,6 +105,7 @@ struct _virNetServer {
void *autoShutdownOpaque;
virNetServerClientPrivNew clientPrivNew;
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
virFreeCallback clientPrivFree;
void *clientPrivOpaque;
};
@ -309,6 +310,7 @@ static int virNetServerDispatchNewClient(virNetServerServicePtr svc,
virNetServerServiceGetMaxRequests(svc),
virNetServerServiceGetTLSContext(svc),
srv->clientPrivNew,
srv->clientPrivPreExecRestart,
srv->clientPrivFree,
srv->clientPrivOpaque)))
return -1;
@ -360,6 +362,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
bool keepaliveRequired,
const char *mdnsGroupName,
virNetServerClientPrivNew clientPrivNew,
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart,
virFreeCallback clientPrivFree,
void *clientPrivOpaque)
{
@ -385,6 +388,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
srv->keepaliveRequired = keepaliveRequired;
srv->sigwrite = srv->sigread = -1;
srv->clientPrivNew = clientPrivNew;
srv->clientPrivPreExecRestart = clientPrivPreExecRestart;
srv->clientPrivFree = clientPrivFree;
srv->clientPrivOpaque = clientPrivOpaque;
srv->privileged = geteuid() == 0 ? true : false;

View File

@ -41,6 +41,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
bool keepaliveRequired,
const char *mdnsGroupName,
virNetServerClientPrivNew clientPrivNew,
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart,
virFreeCallback clientPrivFree,
void *clientPrivOpaque);

View File

@ -98,6 +98,7 @@ struct _virNetServerClient
void *privateData;
virFreeCallback privateDataFreeFunc;
virNetServerClientPrivPreExecRestart privateDataPreExecRestart;
virNetServerClientCloseFunc privateDataCloseFunc;
virKeepAlivePtr keepalive;
@ -395,6 +396,7 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock,
size_t nrequests_max,
virNetTLSContextPtr tls,
virNetServerClientPrivNew privNew,
virNetServerClientPrivPreExecRestart privPreExecRestart,
virFreeCallback privFree,
void *privOpaque)
{
@ -411,12 +413,145 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock,
return NULL;
}
client->privateDataFreeFunc = privFree;
client->privateDataPreExecRestart = privPreExecRestart;
}
return client;
}
virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr object,
virNetServerClientPrivNewPostExecRestart privNew,
virNetServerClientPrivPreExecRestart privPreExecRestart,
virFreeCallback privFree,
void *privOpaque)
{
virJSONValuePtr child;
virNetServerClientPtr client = NULL;
virNetSocketPtr sock;
const char *identity = NULL;
int auth;
bool readonly;
unsigned int nrequests_max;
if (virJSONValueObjectGetNumberInt(object, "auth", &auth) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing auth field in JSON state document"));
return NULL;
}
if (virJSONValueObjectGetBoolean(object, "readonly", &readonly) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing readonly field in JSON state document"));
return NULL;
}
if (virJSONValueObjectGetNumberUint(object, "nrequests_max",
(unsigned int *)&nrequests_max) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing nrequests_client_max field in JSON state document"));
return NULL;
}
if (virJSONValueObjectHasKey(object, "identity") &&
(!(identity = virJSONValueObjectGetString(object, "identity")))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing identity field in JSON state document"));
return NULL;
}
if (!(child = virJSONValueObjectGet(object, "sock"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing sock field in JSON state document"));
return NULL;
}
if (!(sock = virNetSocketNewPostExecRestart(child))) {
virObjectUnref(sock);
return NULL;
}
if (!(client = virNetServerClientNewInternal(sock,
auth,
readonly,
nrequests_max,
NULL))) {
virObjectUnref(sock);
return NULL;
}
virObjectUnref(sock);
if (identity &&
virNetServerClientSetIdentity(client, identity) < 0)
goto error;
if (privNew) {
if (!(child = virJSONValueObjectGet(object, "privateData"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing privateData field in JSON state document"));
goto error;
}
if (!(client->privateData = privNew(client, child, privOpaque))) {
goto error;
}
client->privateDataFreeFunc = privFree;
client->privateDataPreExecRestart = privPreExecRestart;
}
return client;
error:
virObjectUnref(client);
return NULL;
}
virJSONValuePtr virNetServerClientPreExecRestart(virNetServerClientPtr client)
{
virJSONValuePtr object = virJSONValueNewObject();
virJSONValuePtr child;
if (!object)
return NULL;
virNetServerClientLock(client);
if (virJSONValueObjectAppendNumberInt(object, "auth", client->auth) < 0)
goto error;
if (virJSONValueObjectAppendBoolean(object, "readonly", client->readonly) < 0)
goto error;
if (virJSONValueObjectAppendNumberUint(object, "nrequests_max", client->nrequests_max) < 0)
goto error;
if (client->identity &&
virJSONValueObjectAppendString(object, "identity", client->identity) < 0)
goto error;
if (!(child = virNetSocketPreExecRestart(client->sock)))
goto error;
if (virJSONValueObjectAppend(object, "sock", child) < 0) {
virJSONValueFree(child);
goto error;
}
if (client->privateData && client->privateDataPreExecRestart &&
!(child = client->privateDataPreExecRestart(client, client->privateData)))
goto error;
if (virJSONValueObjectAppend(object, "privateData", child) < 0) {
virJSONValueFree(child);
goto error;
}
virNetServerClientUnlock(client);
return object;
error:
virNetServerClientUnlock(client);
virJSONValueFree(object);
return NULL;
}
int virNetServerClientGetAuth(virNetServerClientPtr client)
{
int auth;

View File

@ -27,6 +27,7 @@
# include "virnetsocket.h"
# include "virnetmessage.h"
# include "virobject.h"
# include "json.h"
typedef struct _virNetServerClient virNetServerClient;
typedef virNetServerClient *virNetServerClientPtr;
@ -39,6 +40,11 @@ typedef int (*virNetServerClientFilterFunc)(virNetServerClientPtr client,
virNetMessagePtr msg,
void *opaque);
typedef virJSONValuePtr (*virNetServerClientPrivPreExecRestart)(virNetServerClientPtr client,
void *data);
typedef void *(*virNetServerClientPrivNewPostExecRestart)(virNetServerClientPtr client,
virJSONValuePtr object,
void *opaque);
typedef void *(*virNetServerClientPrivNew)(virNetServerClientPtr client,
void *opaque);
@ -48,9 +54,18 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock,
size_t nrequests_max,
virNetTLSContextPtr tls,
virNetServerClientPrivNew privNew,
virNetServerClientPrivPreExecRestart privPreExecRestart,
virFreeCallback privFree,
void *privOpaque);
virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr object,
virNetServerClientPrivNewPostExecRestart privNew,
virNetServerClientPrivPreExecRestart privPreExecRestart,
virFreeCallback privFree,
void *privOpaque);
virJSONValuePtr virNetServerClientPreExecRestart(virNetServerClientPtr client);
int virNetServerClientAddFilter(virNetServerClientPtr client,
virNetServerClientFilterFunc func,
void *opaque);