From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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@xxxxxxxxxx> --- daemon/libvirtd.c | 1 + src/libvirt_private.syms | 2 + src/lxc/lxc_controller.c | 1 + src/rpc/virnetserver.c | 4 ++ src/rpc/virnetserver.h | 1 + src/rpc/virnetserverclient.c | 135 +++++++++++++++++++++++++++++++++++++++++++ src/rpc/virnetserverclient.h | 15 +++++ 7 files changed, 159 insertions(+) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 6973df6..5696073 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -1204,6 +1204,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; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b847f46..004a8da 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1560,6 +1560,8 @@ virNetServerClientIsSecure; virNetServerClientLocalAddrString; virNetServerClientNeedAuth; virNetServerClientNew; +virNetServerClientNewPostExecRestart; +virNetServerClientPreExecRestart; virNetServerClientRemoteAddrString; virNetServerClientRemoveFilter; virNetServerClientSendMessage; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index e5aea11..74bf7ac 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -616,6 +616,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) -1, 0, false, NULL, virLXCControllerClientPrivateNew, + NULL, virLXCControllerClientPrivateFree, ctrl))) goto error; diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 0a6ecdc..902c34e 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -105,6 +105,7 @@ struct _virNetServer { void *autoShutdownOpaque; virNetServerClientPrivNew clientPrivNew; + virNetServerClientPrivPreExecRestart clientPrivPreExecRestart; virFreeCallback clientPrivFree; void *clientPrivOpaque; }; @@ -312,6 +313,7 @@ static int virNetServerDispatchNewClient(virNetServerServicePtr svc, virNetServerServiceGetMaxRequests(svc), virNetServerServiceGetTLSContext(svc), srv->clientPrivNew, + srv->clientPrivPreExecRestart, srv->clientPrivFree, srv->clientPrivOpaque))) return -1; @@ -363,6 +365,7 @@ virNetServerPtr virNetServerNew(size_t min_workers, bool keepaliveRequired, const char *mdnsGroupName, virNetServerClientPrivNew clientPrivNew, + virNetServerClientPrivPreExecRestart clientPrivPreExecRestart, virFreeCallback clientPrivFree, void *clientPrivOpaque) { @@ -388,6 +391,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; diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index 9188072..778b069 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -41,6 +41,7 @@ virNetServerPtr virNetServerNew(size_t min_workers, bool keepaliveRequired, const char *mdnsGroupName, virNetServerClientPrivNew clientPrivNew, + virNetServerClientPrivPreExecRestart clientPrivPreExecRestart, virFreeCallback clientPrivFree, void *clientPrivOpaque); diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c index acd2b4d..661242a 100644 --- a/src/rpc/virnetserverclient.c +++ b/src/rpc/virnetserverclient.c @@ -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; diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h index f950c61..2a2413b 100644 --- a/src/rpc/virnetserverclient.h +++ b/src/rpc/virnetserverclient.h @@ -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); -- 1.7.11.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list