From: "Daniel P. Berrange" <berrange(a)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(a)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 6077aa0..836a926 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1599,6 +1599,8 @@ virNetSocketNewConnectUNIX;
virNetSocketNewListenFD;
virNetSocketNewListenTCP;
virNetSocketNewListenUNIX;
+virNetSocketNewPostExecRestart;
+virNetSocketPreExecRestart;
virNetSocketRead;
virNetSocketRecvFD;
virNetSocketRemoteAddrString;
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 69c25bd..b9d1d97 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -741,6 +741,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 3750955..26ceac0 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;
@@ -81,6 +82,11 @@ int virNetSocketNewConnectSSH(const char *nodename,
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