[Libguestfs] [PATCH 3/8 v2 DISCUSSION ONLY] lib: Implement attach-method unix:<path>
Richard W.M. Jones
rjones at redhat.com
Fri Jan 28 19:37:41 UTC 2011
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
-------------- next part --------------
>From 1f20f266b7a1d63a53dc1782adedb9bcaef97d83 Mon Sep 17 00:00:00 2001
From: Richard W.M. Jones <rjones at redhat.com>
Date: Thu, 27 Jan 2011 15:54:33 +0000
Subject: [PATCH 3/8] lib: Implement attach-method unix:<path>
Allow connections to a Unix domain socket which is connected
(via virtio-serial) to a guestfsd running free in an existing
guest.
In order to use this you have to add the following element
to the libvirt XML:
<channel type='unix'>
<source mode='bind' path='/tmp/socket'/>
<target type='virtio' name='org.libguestfs.channel.0'/>
</channel>
(or perform the equivalent on the qemu command line).
Then in guestfish, you can do:
guestfish -n \
attach-method unix:/tmp/socket : \
run : \
ll /
(or any other commands as desired).
Note the '-n' option is necessary to stop autosync, which would
try to unmount all of the guest's disks.
---
src/launch.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/proto.c | 19 +++++++-----
2 files changed, 95 insertions(+), 9 deletions(-)
diff --git a/src/launch.c b/src/launch.c
index 775f7a6..e50985d 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -71,6 +71,7 @@
#include "guestfs_protocol.h"
static int launch_appliance (guestfs_h *g);
+static int connect_unix_socket (guestfs_h *g, const char *sock);
static int qemu_supports (guestfs_h *g, const char *option);
/* Add a string to the current command line. */
@@ -374,7 +375,17 @@ guestfs__launch (guestfs_h *g)
if (chmod (g->tmpdir, 0755) == -1)
fprintf (stderr, "chmod: %s: %m (ignored)\n", g->tmpdir);
- return launch_appliance (g);
+ /* Launch the appliance or attach to an existing daemon. */
+ switch (g->attach_method) {
+ case ATTACH_METHOD_APPLIANCE:
+ return launch_appliance (g);
+
+ case ATTACH_METHOD_UNIX:
+ return connect_unix_socket (g, g->attach_method_arg);
+
+ default:
+ abort ();
+ }
}
static int
@@ -778,6 +789,78 @@ launch_appliance (guestfs_h *g)
return -1;
}
+/* Alternate attach method: instead of launching the appliance,
+ * connect to an existing unix socket.
+ */
+static int
+connect_unix_socket (guestfs_h *g, const char *sockpath)
+{
+ int r;
+ struct sockaddr_un addr;
+
+ /* Start the clock ... */
+ gettimeofday (&g->launch_t, NULL);
+
+ /* Set these to nothing so we don't try to kill random processes or
+ * read from random file descriptors.
+ */
+ g->pid = 0;
+ g->recoverypid = 0;
+ g->fd[0] = -1;
+ g->fd[1] = -1;
+
+ if (g->verbose)
+ guestfs___print_timestamped_message (g, "connecting to %s", sockpath);
+
+ g->sock = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (g->sock == -1) {
+ perrorf (g, "socket");
+ return -1;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strncpy (addr.sun_path, sockpath, UNIX_PATH_MAX);
+ addr.sun_path[UNIX_PATH_MAX-1] = '\0';
+
+ g->state = LAUNCHING;
+
+ if (connect (g->sock, &addr, sizeof addr) == -1) {
+ perrorf (g, "bind");
+ goto cleanup;
+ }
+
+ if (fcntl (g->sock, F_SETFL, O_NONBLOCK) == -1) {
+ perrorf (g, "fcntl");
+ goto cleanup;
+ }
+
+ uint32_t size;
+ void *buf = NULL;
+ r = guestfs___recv_from_daemon (g, &size, &buf);
+ free (buf);
+
+ if (r == -1) return -1;
+
+ if (size != GUESTFS_LAUNCH_FLAG) {
+ error (g, _("guestfs_launch failed, unexpected initial message from guestfsd"));
+ goto cleanup;
+ }
+
+ if (g->verbose)
+ guestfs___print_timestamped_message (g, "connected");
+
+ if (g->state != READY) {
+ error (g, _("contacted guestfsd, but state != READY"));
+ goto cleanup;
+ }
+
+ return 0;
+
+ cleanup:
+ close (g->sock);
+ return -1;
+}
+
/* Return the location of the tmpdir (eg. "/tmp") and allow users
* to override it at runtime using $TMPDIR.
* http://www.pathname.com/fhs/pub/fhs-2.3.html#TMPTEMPORARYFILES
diff --git a/src/proto.c b/src/proto.c
index 0d63af6..549734b 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -183,8 +183,8 @@ child_cleanup (guestfs_h *g)
if (g->recoverypid > 0) kill (g->recoverypid, 9);
waitpid (g->pid, NULL, 0);
if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0);
- close (g->fd[0]);
- close (g->fd[1]);
+ if (g->fd[0] >= 0) close (g->fd[0]);
+ if (g->fd[1] >= 0) close (g->fd[1]);
close (g->sock);
g->fd[0] = -1;
g->fd[1] = -1;
@@ -381,7 +381,8 @@ guestfs___send_to_daemon (guestfs_h *g, const void *v_buf, size_t n)
FD_ZERO (&rset);
FD_ZERO (&wset);
- FD_SET (g->fd[1], &rset); /* Read qemu stdout for log messages & EOF. */
+ if (g->fd[1] >= 0) /* Read qemu stdout for log messages & EOF. */
+ FD_SET (g->fd[1], &rset);
FD_SET (g->sock, &rset); /* Read socket for cancellation & EOF. */
FD_SET (g->sock, &wset); /* Write to socket to send the data. */
@@ -398,7 +399,7 @@ guestfs___send_to_daemon (guestfs_h *g, const void *v_buf, size_t n)
return -1;
}
- if (FD_ISSET (g->fd[1], &rset2)) {
+ if (g->fd[1] >= 0 && FD_ISSET (g->fd[1], &rset2)) {
if (read_log_message_or_eof (g, g->fd[1], 0) == -1)
return -1;
}
@@ -460,7 +461,8 @@ guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
FD_ZERO (&rset);
- FD_SET (g->fd[1], &rset); /* Read qemu stdout for log messages & EOF. */
+ if (g->fd[1] >= 0) /* Read qemu stdout for log messages & EOF. */
+ FD_SET (g->fd[1], &rset);
FD_SET (g->sock, &rset); /* Read socket for data & EOF. */
int max_fd = MAX (g->sock, g->fd[1]);
@@ -492,7 +494,7 @@ guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
return -1;
}
- if (FD_ISSET (g->fd[1], &rset2)) {
+ if (g->fd[1] >= 0 && FD_ISSET (g->fd[1], &rset2)) {
if (read_log_message_or_eof (g, g->fd[1], 0) == -1) {
free (*buf_rtn);
*buf_rtn = NULL;
@@ -650,7 +652,8 @@ guestfs___accept_from_daemon (guestfs_h *g)
FD_ZERO (&rset);
- FD_SET (g->fd[1], &rset); /* Read qemu stdout for log messages & EOF. */
+ if (g->fd[1] >= 0) /* Read qemu stdout for log messages & EOF. */
+ FD_SET (g->fd[1], &rset);
FD_SET (g->sock, &rset); /* Read socket for accept. */
int max_fd = MAX (g->sock, g->fd[1]);
@@ -674,7 +677,7 @@ guestfs___accept_from_daemon (guestfs_h *g)
return -1;
}
- if (FD_ISSET (g->fd[1], &rset2)) {
+ if (g->fd[1] >= 0 && FD_ISSET (g->fd[1], &rset2)) {
if (read_log_message_or_eof (g, g->fd[1], 1) == -1)
return -1;
}
--
1.7.3.5
More information about the Libguestfs
mailing list