Add JSON serialization of virNetSocketPtr objects for process re-exec()

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@redhat.com>
This commit is contained in:
Daniel P. Berrange 2012-08-09 12:54:54 +01:00
parent 8057c04e8d
commit c298145344
3 changed files with 116 additions and 0 deletions

View File

@ -1667,6 +1667,8 @@ virNetSocketNewConnectUNIX;
virNetSocketNewListenFD; virNetSocketNewListenFD;
virNetSocketNewListenTCP; virNetSocketNewListenTCP;
virNetSocketNewListenUNIX; virNetSocketNewListenUNIX;
virNetSocketNewPostExecRestart;
virNetSocketPreExecRestart;
virNetSocketRead; virNetSocketRead;
virNetSocketRecvFD; virNetSocketRecvFD;
virNetSocketRemoteAddrString; virNetSocketRemoteAddrString;

View File

@ -882,6 +882,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) void virNetSocketDispose(void *obj)
{ {
virNetSocketPtr sock = obj; virNetSocketPtr sock = obj;

View File

@ -31,6 +31,7 @@
# ifdef HAVE_SASL # ifdef HAVE_SASL
# include "virnetsaslcontext.h" # include "virnetsaslcontext.h"
# endif # endif
# include "json.h"
typedef struct _virNetSocket virNetSocket; typedef struct _virNetSocket virNetSocket;
typedef virNetSocket *virNetSocketPtr; typedef virNetSocket *virNetSocketPtr;
@ -93,6 +94,11 @@ int virNetSocketNewConnectLibSSH2(const char *host,
int virNetSocketNewConnectExternal(const char **cmdargv, int virNetSocketNewConnectExternal(const char **cmdargv,
virNetSocketPtr *addr); virNetSocketPtr *addr);
virNetSocketPtr virNetSocketNewPostExecRestart(virJSONValuePtr object);
virJSONValuePtr virNetSocketPreExecRestart(virNetSocketPtr sock);
int virNetSocketGetFD(virNetSocketPtr sock); int virNetSocketGetFD(virNetSocketPtr sock);
int virNetSocketDupFD(virNetSocketPtr sock, bool cloexec); int virNetSocketDupFD(virNetSocketPtr sock, bool cloexec);