From: "Daniel P. Berrange" <berrange(a)redhat.com>
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(a)redhat.com>
---
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 24e20f8..a411060 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1196,6 +1196,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 7ea4b95..cdb9b57 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1526,6 +1526,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 4c3c17f..af1c40e 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