[libvirt] [PATCH 03/12] Add JSON serialization of virNetSocketPtr objects for process re-exec()

Daniel P. Berrange berrange at redhat.com
Wed Sep 12 16:28:56 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

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

As well as saving the state in JSON format, the second
method will disable the O_CLOEXEC flag so that the open
file descriptors are preserved across the process re-exec()

Since it is not possible to serialize SASL or TLS encryption
state, an error will be raised if attempting to perform
serialization on non-raw sockets

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/libvirt_private.syms |   2 +
 src/rpc/virnetsocket.c   | 108 +++++++++++++++++++++++++++++++++++++++++++++++
 src/rpc/virnetsocket.h   |   6 +++
 3 files changed, 116 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6c94584..73e89e0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1633,6 +1633,8 @@ virNetSocketNewConnectUNIX;
 virNetSocketNewListenFD;
 virNetSocketNewListenTCP;
 virNetSocketNewListenUNIX;
+virNetSocketNewPostExecRestart;
+virNetSocketPreExecRestart;
 virNetSocketRead;
 virNetSocketRecvFD;
 virNetSocketRemoteAddrString;
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 5a48300..6bff170 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -881,6 +881,114 @@ int virNetSocketNewConnectExternal(const char **cmdargv,
 }
 
 
+virNetSocketPtr virNetSocketNewPostExecRestart(virJSONValuePtr object)
+{
+    virSocketAddr localAddr;
+    virSocketAddr remoteAddr;
+    int fd, thepid, errfd;
+    bool isClient;
+
+    if (virJSONValueObjectGetNumberInt(object, "fd", &fd) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Missing fd data in JSON document"));
+        return NULL;
+    }
+
+    if (virJSONValueObjectGetNumberInt(object, "pid", &thepid) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Missing pid data in JSON document"));
+        return NULL;
+    }
+
+    if (virJSONValueObjectGetNumberInt(object, "errfd", &errfd) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Missing errfd data in JSON document"));
+        return NULL;
+    }
+    if (virJSONValueObjectGetBoolean(object, "isClient", &isClient) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Missing isClient data in JSON document"));
+        return NULL;
+    }
+
+    memset(&localAddr, 0, sizeof(localAddr));
+    memset(&remoteAddr, 0, sizeof(remoteAddr));
+
+    remoteAddr.len = sizeof(remoteAddr.data.stor);
+    if (getsockname(fd, &remoteAddr.data.sa, &remoteAddr.len) < 0) {
+        virReportSystemError(errno, "%s", _("Unable to get peer socket name"));
+        return NULL;
+    }
+
+    localAddr.len = sizeof(localAddr.data.stor);
+    if (getsockname(fd, &localAddr.data.sa, &localAddr.len) < 0) {
+        virReportSystemError(errno, "%s", _("Unable to get local socket name"));
+        return NULL;
+    }
+
+    return virNetSocketNew(&localAddr, &remoteAddr,
+                           isClient, fd, errfd, thepid);
+}
+
+
+virJSONValuePtr virNetSocketPreExecRestart(virNetSocketPtr sock)
+{
+    virJSONValuePtr object = NULL;
+
+    virMutexLock(&sock->lock);
+
+#if HAVE_SASL
+    if (sock->saslSession) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("Unable to save socket state when SASL session is active"));
+        goto error;
+    }
+#endif
+    if (sock->tlsSession) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("Unable to save socket state when TLS session is active"));
+        goto error;
+    }
+
+    if (!(object = virJSONValueNewObject()))
+        goto error;
+
+    if (virJSONValueObjectAppendNumberInt(object, "fd", sock->fd) < 0)
+        goto error;
+
+    if (virJSONValueObjectAppendNumberInt(object, "errfd", sock->errfd) < 0)
+        goto error;
+
+    if (virJSONValueObjectAppendNumberInt(object, "pid", sock->pid) < 0)
+        goto error;
+
+    if (virJSONValueObjectAppendBoolean(object, "isClient", sock->client) < 0)
+        goto error;
+
+    if (virSetInherit(sock->fd, true) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot disable close-on-exec flag on socket %d"),
+                             sock->fd);
+        goto error;
+    }
+    if (sock->errfd != -1 &&
+        virSetInherit(sock->errfd, true) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot disable close-on-exec flag on pipe %d"),
+                             sock->errfd);
+        goto error;
+    }
+
+    virMutexUnlock(&sock->lock);
+    return object;
+
+error:
+    virMutexUnlock(&sock->lock);
+    virJSONValueFree(object);
+    return NULL;
+}
+
+
 void virNetSocketDispose(void *obj)
 {
     virNetSocketPtr sock = obj;
diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h
index 75b66c5..604103b 100644
--- a/src/rpc/virnetsocket.h
+++ b/src/rpc/virnetsocket.h
@@ -31,6 +31,7 @@
 # ifdef HAVE_SASL
 #  include "virnetsaslcontext.h"
 # endif
+# include "json.h"
 
 typedef struct _virNetSocket virNetSocket;
 typedef virNetSocket *virNetSocketPtr;
@@ -93,6 +94,11 @@ int virNetSocketNewConnectLibSSH2(const char *host,
 int virNetSocketNewConnectExternal(const char **cmdargv,
                                    virNetSocketPtr *addr);
 
+
+virNetSocketPtr virNetSocketNewPostExecRestart(virJSONValuePtr object);
+
+virJSONValuePtr virNetSocketPreExecRestart(virNetSocketPtr sock);
+
 int virNetSocketGetFD(virNetSocketPtr sock);
 int virNetSocketDupFD(virNetSocketPtr sock, bool cloexec);
 
-- 
1.7.11.2




More information about the libvir-list mailing list