[libvirt] [PATCH 15/23] Add JSON serialization of virNetServerClientPtr objects for process re-exec()

Daniel P. Berrange berrange at redhat.com
Thu Aug 9 15:20:20 UTC 2012


From: "Daniel P. Berrange" <berrange at 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 at 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




More information about the libvir-list mailing list