On 12.09.2012 18:28, Daniel P. Berrange wrote: > From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> > > 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@xxxxxxxxxx> > --- > src/libvirt_private.syms | 2 + > src/rpc/virnetsocket.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++ > src/rpc/virnetsocket.h | 6 +++ > 3 files changed, 116 insertions(+) ACK > > 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); > > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list