Richard W.M. Jones
2011-Jan-28 19:36 UTC
[Libguestfs] [PATCH 0/8 v2 DISCUSSION ONLY] Connecting to live virtual machines
NOTE: This is HIGHLY EXPERIMENTAL and can eat babies ... Modify the guest libvirt XML to add the virtio-serial channel: <channel type='unix'> <source mode='bind' path='/tmp/socket'/> <target type='virtio' name='org.libguestfs.channel.0'/> </channel> In the guest, compile guestfsd and run it like this: sudo daemon/guestfsd -rv (XXX - should current directory be / ...?) In the host connect using: sudo guestfish -d GuestName --live ><fs> run ><fs> ll / etc. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/
Richard W.M. Jones
2011-Jan-28 19:36 UTC
[Libguestfs] [PATCH 1/8 v2 DISCUSSION ONLY] Move appliance launching to separate function.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw -------------- next part -------------->From 60e78e2ddcc38f752844a280ad3e29491402503e Mon Sep 17 00:00:00 2001From: Richard W.M. Jones <rjones at redhat.com> Date: Thu, 27 Jan 2011 10:12:34 +0000 Subject: [PATCH 1/8] lib: Move appliance launching to separate function. This is just code motion. --- src/launch.c | 38 ++++++++++++++++++++++++-------------- 1 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/launch.c b/src/launch.c index a7a86b9..775f7a6 100644 --- a/src/launch.c +++ b/src/launch.c @@ -70,6 +70,7 @@ #include "guestfs-internal-actions.h" #include "guestfs_protocol.h" +static int launch_appliance (guestfs_h *g); static int qemu_supports (guestfs_h *g, const char *option); /* Add a string to the current command line. */ @@ -350,32 +351,19 @@ static int is_openable (guestfs_h *g, const char *path, int flags); int guestfs__launch (guestfs_h *g) { - int r; - int wfd[2], rfd[2]; - char unixsock[256]; - struct sockaddr_un addr; - /* Configured? */ - if (!g->cmdline) { - error (g, _("you must call guestfs_add_drive before guestfs_launch")); - return -1; - } - if (g->state != CONFIG) { error (g, _("the libguestfs handle has already been launched")); return -1; } - /* Start the clock ... */ - gettimeofday (&g->launch_t, NULL); - /* Make the temporary directory. */ if (!g->tmpdir) { TMP_TEMPLATE_ON_STACK (dir_template); g->tmpdir = safe_strdup (g, dir_template); if (mkdtemp (g->tmpdir) == NULL) { perrorf (g, _("%s: cannot create temporary directory"), dir_template); - goto cleanup0; + return -1; } } @@ -386,6 +374,28 @@ guestfs__launch (guestfs_h *g) if (chmod (g->tmpdir, 0755) == -1) fprintf (stderr, "chmod: %s: %m (ignored)\n", g->tmpdir); + return launch_appliance (g); +} + +static int +launch_appliance (guestfs_h *g) +{ + int r; + int wfd[2], rfd[2]; + char unixsock[256]; + struct sockaddr_un addr; + + /* At present you must add drives before starting the appliance. In + * future when we enable hotplugging you won't need to do this. + */ + if (!g->cmdline) { + error (g, _("you must call guestfs_add_drive before guestfs_launch")); + return -1; + } + + /* Start the clock ... */ + gettimeofday (&g->launch_t, NULL); + /* Locate and/or build the appliance. */ char *kernel = NULL, *initrd = NULL, *appliance = NULL; if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1) -- 1.7.3.5
Richard W.M. Jones
2011-Jan-28 19:37 UTC
[Libguestfs] [PATCH 2/8 v2 DISCUSSION ONLY] New APIs: set-attach-method, get-attach-method.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org -------------- next part -------------->From d5411585bf02cb84136a523bb9a06db013fc3e24 Mon Sep 17 00:00:00 2001From: Richard W.M. Jones <rjones at redhat.com> Date: Thu, 27 Jan 2011 11:20:43 +0000 Subject: [PATCH 2/8] New APIs: set-attach-method, get-attach-method. These allow you to get and set the attach method. The format is one of: * appliance * unix:<path> It's stored broken out into an enum and a string in the handle. --- generator/generator_actions.ml | 30 ++++++++++++++++++++++++++ src/guestfs-internal.h | 6 +++++ src/guestfs.c | 45 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 0 deletions(-) diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 0ae8790..a2e7467 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -1368,6 +1368,36 @@ part of a set. Please read L<guestfs(3)/INSPECTION> for more details."); + ("set_attach_method", (RErr, [String "attachmethod"], []), -1, [FishAlias "attach-method"], + [], + "set the attach method", + "\ +Set the method that libguestfs uses to connect to the back end +guestfsd daemon. Possible methods are: + +=over 4 + +=item C<appliance> + +Launch an appliance and connect to it. This is the ordinary method +and the default. + +=item C<unix:I<path>> + +Connect to the Unix domain socket I<path>. + +This method lets you connect to an existing daemon or (using +virtio-serial) to a live guest. + +=back"); + + ("get_attach_method", (RString "attachmethod", [], []), -1, [], + [InitNone, Always, TestOutput ( + [["get_attach_method"]], "appliance")], + "get the attach method", + "\ +Return the current attach method. See C<guestfs_set_attach_method>."); + ] (* daemon_functions are any functions which cause some action diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 194c892..0eb395b 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -84,6 +84,9 @@ /* GuestFS handle and connection. */ enum state { CONFIG, LAUNCHING, READY, BUSY, NO_HANDLE }; +/* Attach method. */ +enum attach_method { ATTACH_METHOD_APPLIANCE = 0, ATTACH_METHOD_UNIX }; + struct guestfs_h { struct guestfs_h *next; /* Linked list of open handles. */ @@ -116,6 +119,9 @@ struct guestfs_h char *qemu; /* Qemu binary. */ char *append; /* Append to kernel command line. */ + enum attach_method attach_method; + char *attach_method_arg; + int memsize; /* Size of RAM (megabytes). */ int selinux; /* selinux enabled? */ diff --git a/src/guestfs.c b/src/guestfs.c index 79fc5bf..8b7ab4d 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -645,6 +645,51 @@ guestfs__get_network (guestfs_h *g) return g->enable_network; } +int +guestfs__set_attach_method (guestfs_h *g, const char *method) +{ + if (STREQ (method, "appliance")) { + g->attach_method = ATTACH_METHOD_APPLIANCE; + free (g->attach_method_arg); + g->attach_method_arg = NULL; + } + else if (STRPREFIX (method, "unix:") && strlen (method) > 5) { + g->attach_method = ATTACH_METHOD_UNIX; + free (g->attach_method_arg); + g->attach_method_arg = safe_strdup (g, method + 5); + /* Note that we don't check the path exists until launch is called. */ + } + else { + error (g, "invalid attach method: %s", method); + return -1; + } + + return 0; +} + +char * +guestfs__get_attach_method (guestfs_h *g) +{ + char *ret; + + switch (g->attach_method) { + case ATTACH_METHOD_APPLIANCE: + ret = safe_strdup (g, "appliance"); + break; + + case ATTACH_METHOD_UNIX: + ret = safe_malloc (g, strlen (g->attach_method_arg) + 5 + 1); + strcpy (ret, "unix:"); + strcat (ret, g->attach_method_arg); + break; + + default: /* keep GCC happy - this is not reached */ + abort (); + } + + return ret; +} + void guestfs_set_log_message_callback (guestfs_h *g, guestfs_log_message_cb cb, void *opaque) -- 1.7.3.5
Richard W.M. Jones
2011-Jan-28 19:37 UTC
[Libguestfs] [PATCH 3/8 v2 DISCUSSION ONLY] lib: Implement attach-method unix:<path>
-- 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 2001From: 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
Richard W.M. Jones
2011-Jan-28 19:37 UTC
[Libguestfs] [PATCH 4/8 v2 DISCUSSION ONLY] daemon: Allow -r option to run daemon standalone.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 80 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora -------------- next part -------------->From 5c5231800e53fc24f155a66effa768f30347f0eb Mon Sep 17 00:00:00 2001From: Richard W.M. Jones <rjones at redhat.com> Date: Thu, 27 Jan 2011 16:54:48 +0000 Subject: [PATCH 4/8] daemon: Allow -r option to run daemon standalone. This changes several aspects of the daemon. Currently: * sysroot will be "" (ie. operate directly on /) * CHROOT_IN/CHROOT_OUT are disabled * autosync doesn't try to unmount everything --- daemon/daemon.h | 22 ++++++++++++++-------- daemon/guestfsd.c | 16 ++++++++++++++-- daemon/sync.c | 5 +++-- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/daemon/daemon.h b/daemon/daemon.h index da991b1..4a686c0 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -33,6 +33,8 @@ /*-- in guestfsd.c --*/ extern int verbose; +extern int autosync_umount; + extern const char *sysroot; extern int sysroot_len; @@ -253,17 +255,21 @@ extern void notify_progress (uint64_t position, uint64_t total); */ #define CHROOT_IN \ do { \ - int __old_errno = errno; \ - if (chroot (sysroot) == -1) \ - perror ("CHROOT_IN: sysroot"); \ - errno = __old_errno; \ + if (sysroot_len > 0) { \ + int __old_errno = errno; \ + if (chroot (sysroot) == -1) \ + perror ("CHROOT_IN: sysroot"); \ + errno = __old_errno; \ + } \ } while (0) #define CHROOT_OUT \ do { \ - int __old_errno = errno; \ - if (chroot (".") == -1) \ - perror ("CHROOT_OUT: ."); \ - errno = __old_errno; \ + if (sysroot_len > 0) { \ + int __old_errno = errno; \ + if (chroot (".") == -1) \ + perror ("CHROOT_OUT: ."); \ + errno = __old_errno; \ + } \ } while (0) /* Marks functions which are not implemented. diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 8d950fa..94e4994 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -118,6 +118,9 @@ winsock_init (void) const char *sysroot = "/sysroot"; /* No trailing slash. */ int sysroot_len = 8; +/* If set (the default), do 'umount-all' when performing autosync. */ +int autosync_umount = 1; + /* Not used explicitly, but required by the gnulib 'error' module. */ const char *program_name = "guestfsd"; @@ -125,13 +128,13 @@ static void usage (void) { fprintf (stderr, - "guestfsd [-f|--foreground] [-v|--verbose]\n"); + "guestfsd [-f|--foreground] [-v|--verbose] [-r]\n"); } int main (int argc, char *argv[]) { - static const char *options = "fv?"; + static const char *options = "frv?"; static const struct option long_options[] = { { "foreground", 0, 0, 'f' }, { "help", 0, 0, '?' }, @@ -171,6 +174,15 @@ main (int argc, char *argv[]) dont_fork = 1; break; + /* The -r flag is used when running standalone. It changes + * several aspects of the daemon. + */ + case 'r': + sysroot = ""; + sysroot_len = 0; + autosync_umount = 0; + break; + case 'v': verbose = 1; break; diff --git a/daemon/sync.c b/daemon/sync.c index 25c7de8..8f5a461 100644 --- a/daemon/sync.c +++ b/daemon/sync.c @@ -51,9 +51,10 @@ do_sync (void) int do_internal_autosync (void) { - int r; + int r = 0; - r = do_umount_all (); + if (autosync_umount) + r = do_umount_all (); sync_disks (); -- 1.7.3.5
Richard W.M. Jones
2011-Jan-28 19:38 UTC
[Libguestfs] [PATCH 5/8 v2 DISCUSSION ONLY] daemon: Remove -f (don't fork) option.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw -------------- next part -------------->From cfc2bf061165079ed02eba3f42a63e65d4f555b8 Mon Sep 17 00:00:00 2001From: Richard W.M. Jones <rjones at redhat.com> Date: Fri, 28 Jan 2011 15:44:40 +0000 Subject: [PATCH 5/8] daemon: Remove -f (don't fork) option. This option was not being used. --- appliance/init | 2 +- daemon/guestfsd.c | 33 +++------------------------------ 2 files changed, 4 insertions(+), 31 deletions(-) diff --git a/appliance/init b/appliance/init index 4a9476d..1d31cd8 100755 --- a/appliance/init +++ b/appliance/init @@ -97,7 +97,7 @@ fi if ! grep -sq guestfs_rescue=1 /proc/cmdline; then # The host will kill qemu abruptly if guestfsd shuts down normally - guestfsd -f + guestfsd # Otherwise we try to clean up gracefully. For example, this ensures that a # core dump generated by the guest daemon will be written to disk. diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 94e4994..2d10c82 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,8 +18,6 @@ #include <config.h> -#define _BSD_SOURCE /* for daemon(3) */ - #ifdef HAVE_WINDOWS_H # include <windows.h> #endif @@ -87,17 +85,6 @@ static int print_arginfo (const struct printf_info *info, size_t n, int *argtype #ifdef WIN32 static int -daemon (int nochdir, int noclose) -{ - fprintf (stderr, - "On Windows the daemon does not support forking into the " - "background.\nYou *must* run the daemon with the -f option.\n"); - exit (EXIT_FAILURE); -} -#endif /* WIN32 */ - -#ifdef WIN32 -static int winsock_init (void) { int r; @@ -128,21 +115,19 @@ static void usage (void) { fprintf (stderr, - "guestfsd [-f|--foreground] [-v|--verbose] [-r]\n"); + "guestfsd [-r] [-v|--verbose]\n"); } int main (int argc, char *argv[]) { - static const char *options = "frv?"; + static const char *options = "rv?"; static const struct option long_options[] = { - { "foreground", 0, 0, 'f' }, { "help", 0, 0, '?' }, { "verbose", 0, 0, 'v' }, { 0, 0, 0, 0 } }; int c; - int dont_fork = 0; char *cmdline; if (winsock_init () == -1) @@ -170,10 +155,6 @@ main (int argc, char *argv[]) if (c == -1) break; switch (c) { - case 'f': - dont_fork = 1; - break; - /* The -r flag is used when running standalone. It changes * several aspects of the daemon. */ @@ -290,14 +271,6 @@ main (int argc, char *argv[]) xdr_destroy (&xdr); - /* Fork into the background. */ - if (!dont_fork) { - if (daemon (0, 1) == -1) { - perror ("daemon"); - exit (EXIT_FAILURE); - } - } - /* Enter the main loop, reading and performing actions. */ main_loop (sock); -- 1.7.3.5
Richard W.M. Jones
2011-Jan-28 19:38 UTC
[Libguestfs] [PATCH 6/8 v2 DISCUSSION ONLY] Add guestfs_add_domain 'live' flag.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 80 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora -------------- next part -------------->From 59d06155bf48f6656e5bc75dba99fc2b34515919 Mon Sep 17 00:00:00 2001From: Richard W.M. Jones <rjones at redhat.com> Date: Fri, 28 Jan 2011 13:19:52 +0000 Subject: [PATCH 6/8] Add guestfs_add_domain 'live' flag. This optional flag controls whether this API call will try to connect to a running virtual machine 'guestfsd' process. If the flag is given and the virtual machine is running, then the libvirt XML is parsed looking for a suitable <channel> element, and 'guestfs_set_attach_method' is called with the corresponding virtio-serial socket path. --- fish/fish.c | 2 +- generator/generator_actions.ml | 18 +++- src/virt.c | 192 ++++++++++++++++++++++++++++++++++----- 3 files changed, 183 insertions(+), 29 deletions(-) diff --git a/fish/fish.c b/fish/fish.c index 10f645f..eb7c8fe 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index a2e7467..192df77 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -1074,7 +1074,7 @@ Please read L<guestfs(3)/INSPECTION> for more details."); This returns the internal QEMU command line. 'debug' commands are not part of the formal API and can be removed or changed at any time."); - ("add_domain", (RInt "nrdisks", [String "dom"], [String "libvirturi"; Bool "readonly"; String "iface"]), -1, [FishAlias "domain"], + ("add_domain", (RInt "nrdisks", [String "dom"], [String "libvirturi"; Bool "readonly"; String "iface"; Bool "live"]), -1, [FishAlias "domain"], [], "add the disk(s) from a named libvirt domain", "\ @@ -1101,12 +1101,18 @@ we connect to the default libvirt URI (or one set through an environment variable, see the libvirt documentation for full details). +The optional C<live> flag controls whether this call will try +to connect to a running virtual machine C<guestfsd> process if +it sees a suitable E<lt>channelE<gt> element in the libvirt +XML definition. The default (if the flag is omitted) is never +to try. + The other optional parameters are passed directly through to C<guestfs_add_drive_opts>."); (* This interface is not quite baked yet. -- RWMJ 2010-11-11 - ("add_libvirt_dom", (RInt "nrdisks", [Pointer ("virDomainPtr", "dom")], [Bool "readonly"; String "iface"]), -1, [NotInFish], + ("add_libvirt_dom", (RInt "nrdisks", [Pointer ("virDomainPtr", "dom")], [Bool "readonly"; String "iface"; Bool "live"]), -1, [NotInFish], [], "add the disk(s) from a libvirt domain", "\ @@ -1129,7 +1135,13 @@ from a remote libvirt connection (see L<http://libvirt.org/remote.html>) will fail unless those disks are accessible via the same device path locally too. -The optional parameters are passed directly through to +The optional C<live> flag controls whether this call will try +to connect to a running virtual machine C<guestfsd> process if +it sees a suitable E<lt>channelE<gt> element in the libvirt +XML definition. The default (if the flag is omitted) is never +to try. + +The other optional parameters are passed directly through to C<guestfs_add_drive_opts>."); *) diff --git a/src/virt.c b/src/virt.c index 9f84908..4b66cc8 100644 --- a/src/virt.c +++ b/src/virt.c @@ -59,6 +59,8 @@ struct guestfs___add_libvirt_dom_argv { int readonly; #define GUESTFS___ADD_LIBVIRT_DOM_IFACE_BITMASK (UINT64_C(1)<<1) const char *iface; +#define GUESTFS___ADD_LIBVIRT_DOM_LIVE_BITMASK (UINT64_C(1)<<2) + int live; }; static int guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, const struct guestfs___add_libvirt_dom_argv *optargs); @@ -73,6 +75,7 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name, int r = -1; const char *libvirturi; int readonly; + int live; const char *iface; struct guestfs___add_libvirt_dom_argv optargs2 = { .bitmask = 0 }; @@ -82,6 +85,13 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name, ? optargs->readonly : 0; iface = optargs->bitmask & GUESTFS_ADD_DOMAIN_IFACE_BITMASK ? optargs->iface : NULL; + live = optargs->bitmask & GUESTFS_ADD_DOMAIN_LIVE_BITMASK + ? optargs->live : 0; + + if (live && readonly) { + error (g, _("you cannot set both live and readonly flags")); + return -1; + } /* Connect to libvirt, find the domain. */ conn = virConnectOpenReadOnly (libvirturi); @@ -108,6 +118,10 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name, optargs2.bitmask |= GUESTFS___ADD_LIBVIRT_DOM_IFACE_BITMASK; optargs2.iface = iface; } + if (live) { + optargs2.bitmask |= GUESTFS___ADD_LIBVIRT_DOM_LIVE_BITMASK; + optargs2.live = live; + } r = guestfs___add_libvirt_dom (g, dom, &optargs2); @@ -282,49 +296,63 @@ guestfs___for_each_disk (guestfs_h *g, return r; } -static int -add_disk (guestfs_h *g, const char *filename, const char *format, - void *optargs_vp) -{ - struct guestfs_add_drive_opts_argv *optargs = optargs_vp; - - if (format) { - optargs->bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; - optargs->format = format; - } else - optargs->bitmask &= ~GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; +/* This was proposed as an external API, but it's not quite baked yet. */ - return guestfs__add_drive_opts (g, filename, optargs); -} +static int add_disk (guestfs_h *g, const char *filename, const char *format, void *optargs_vp); +static int connect_live (guestfs_h *g, virDomainPtr dom); -/* This was proposed as an external API, but it's not quite baked yet. */ static int guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, const struct guestfs___add_libvirt_dom_argv *optargs) { - int r = -1; - virErrorPtr err; int cmdline_pos; + int r; + int readonly; + const char *iface; + int live; - cmdline_pos = guestfs___checkpoint_cmdline (g); - - int readonly + readonly optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_READONLY_BITMASK ? optargs->readonly : 0; - const char *iface + iface optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_IFACE_BITMASK ? optargs->iface : NULL; + live + optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_LIVE_BITMASK + ? optargs->live : 0; + + if (live && readonly) { + error (g, _("you cannot set both live and readonly flags")); + return -1; + } if (!readonly) { virDomainInfo info; + virErrorPtr err; + int vm_running; + if (virDomainGetInfo (dom, &info) == -1) { err = virGetLastError (); error (g, _("error getting domain info: %s"), err->message); - goto cleanup; + return -1; } - if (info.state != VIR_DOMAIN_SHUTOFF) { - error (g, _("error: domain is a live virtual machine.\nYou must use readonly access because write access to a running virtual machine\ncan cause disk corruption.")); - goto cleanup; + vm_running = info.state != VIR_DOMAIN_SHUTOFF; + + if (vm_running) { + /* If the caller specified the 'live' flag, then they want us to + * try to connect to guestfsd if the domain is running. Note + * that live readonly connections are not possible. + */ + if (live) + return connect_live (g, dom); + + /* Dangerous to modify the disks of a running VM. */ + error (g, _("error: domain is a live virtual machine.\n" + "Writing to the disks of a running virtual machine can cause disk corruption.\n" + "Either use read-only access, or if the guest is running the guestfsd daemon\n" + "specify live access. In most libguestfs tools these options are --ro or\n" + "--live respectively. Consult the documentation for further information.")); + return -1; } } @@ -339,10 +367,124 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, optargs2.iface = iface; } + /* Checkpoint the command line around the operation so that either + * all disks are added or none are added. + */ + cmdline_pos = guestfs___checkpoint_cmdline (g); r = guestfs___for_each_disk (g, dom, add_disk, &optargs2); + if (r == -1) + guestfs___rollback_cmdline (g, cmdline_pos); + + return r; +} + +static int +add_disk (guestfs_h *g, const char *filename, const char *format, + void *optargs_vp) +{ + struct guestfs_add_drive_opts_argv *optargs = optargs_vp; + + if (format) { + optargs->bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; + optargs->format = format; + } else + optargs->bitmask &= ~GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; + + return guestfs__add_drive_opts (g, filename, optargs); +} + +static int +connect_live (guestfs_h *g, virDomainPtr dom) +{ + int i, r = -1; + virErrorPtr err; + xmlDocPtr doc = NULL; + xmlXPathContextPtr xpathCtx = NULL; + xmlXPathObjectPtr xpathObj = NULL; + char *xml = NULL; + char *path = NULL; + char *attach_method = NULL; + + /* Domain XML. */ + xml = virDomainGetXMLDesc (dom, 0); + + if (!xml) { + err = virGetLastError (); + error (g, _("error reading libvirt XML information: %s"), + err->message); + goto cleanup; + } + + /* Parse XML to document. */ + doc = xmlParseMemory (xml, strlen (xml)); + if (doc == NULL) { + error (g, _("unable to parse XML information returned by libvirt")); + goto cleanup; + } + + xpathCtx = xmlXPathNewContext (doc); + if (xpathCtx == NULL) { + error (g, _("unable to create new XPath context")); + goto cleanup; + } + + /* This gives us a set of all the <channel> nodes related to the + * guestfsd virtio-serial channel. + */ + xpathObj = xmlXPathEvalExpression (BAD_CAST + "//devices/channel[@type=\"unix\" and " + "./source/@mode=\"bind\" and " + "./source/@path and " + "./target/@type=\"virtio\" and " + "./target/@name=\"org.libguestfs.channel.0\"]", + xpathCtx); + if (xpathObj == NULL) { + error (g, _("unable to evaluate XPath expression")); + goto cleanup; + } + + xmlNodeSetPtr nodes = xpathObj->nodesetval; + for (i = 0; i < nodes->nodeNr; ++i) { + xmlXPathObjectPtr xppath; + + /* See note in function above. */ + xpathCtx->node = nodes->nodeTab[i]; + + /* The path is in <source path=..> attribute. */ + xppath = xmlXPathEvalExpression (BAD_CAST "./source/@path", xpathCtx); + if (xppath == NULL || + xppath->nodesetval == NULL || + xppath->nodesetval->nodeNr == 0) { + xmlXPathFreeObject (xppath); + continue; /* no type attribute, skip it */ + } + assert (xppath->nodesetval->nodeTab[0]); + assert (xppath->nodesetval->nodeTab[0]->type == XML_ATTRIBUTE_NODE); + xmlAttrPtr attr = (xmlAttrPtr) xppath->nodesetval->nodeTab[0]; + path = (char *) xmlNodeListGetString (doc, attr->children, 1); + xmlXPathFreeObject (xppath); + break; + } + + if (path == NULL) { + error (g, _("this guest has no libvirt <channel> definition for guestfsd")); + goto cleanup; + } + + /* Got a path. */ + attach_method = safe_malloc (g, strlen (path) + 5 + 1); + strcpy (attach_method, "unix:"); + strcat (attach_method, path); + r = guestfs_set_attach_method (g, attach_method); cleanup: - if (r == -1) guestfs___rollback_cmdline (g, cmdline_pos); + free (path); + free (attach_method); + free (xml); + if (xpathObj) xmlXPathFreeObject (xpathObj); + if (xpathCtx) xmlXPathFreeContext (xpathCtx); + if (doc) xmlFreeDoc (doc); + return r; } -- 1.7.3.5
Richard W.M. Jones
2011-Jan-28 19:38 UTC
[Libguestfs] [PATCH 7/8 v2 DISCUSSION ONLY] Add documentation for attach method.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw -------------- next part -------------->From f07afe4767587dabf2a74da2c70509277267b0bb Mon Sep 17 00:00:00 2001From: Richard W.M. Jones <rjones at redhat.com> Date: Thu, 27 Jan 2011 22:45:50 +0000 Subject: [PATCH 7/8] Add documentation for attach method. --- generator/generator_actions.ml | 9 ++++-- src/guestfs.pod | 57 ++++++++++++++++++++++++++++++++++++++++ src/virt.c | 3 +- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 192df77..ca2dfe3 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -1105,7 +1105,8 @@ The optional C<live> flag controls whether this call will try to connect to a running virtual machine C<guestfsd> process if it sees a suitable E<lt>channelE<gt> element in the libvirt XML definition. The default (if the flag is omitted) is never -to try. +to try. See L<guestfs(3)/ATTACHING TO RUNNING DAEMONS> for more +information. The other optional parameters are passed directly through to C<guestfs_add_drive_opts>."); @@ -1139,7 +1140,8 @@ The optional C<live> flag controls whether this call will try to connect to a running virtual machine C<guestfsd> process if it sees a suitable E<lt>channelE<gt> element in the libvirt XML definition. The default (if the flag is omitted) is never -to try. +to try. See L<guestfs(3)/ATTACHING TO RUNNING DAEMONS> for more +information. The other optional parameters are passed directly through to C<guestfs_add_drive_opts>."); @@ -1399,7 +1401,8 @@ and the default. Connect to the Unix domain socket I<path>. This method lets you connect to an existing daemon or (using -virtio-serial) to a live guest. +virtio-serial) to a live guest. For more information, see +L<guestfs(3)/ATTACHING TO RUNNING DAEMONS>. =back"); diff --git a/src/guestfs.pod b/src/guestfs.pod index b8b8ca2..c031bcc 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -972,6 +972,63 @@ For example: Note that libguestfs also calls qemu with the -help and -version options in order to determine features. +=head2 ATTACHING TO RUNNING DAEMONS + +I<Note (1):> This is B<highly experimental> and has a tendency to eat +babies. Use with caution. + +I<Note (2):> This section explains how to attach to a running daemon +from a low level perspective. For most users, simply using virt tools +such as L<guestfish(1)> with the I<--live> option will "just work". + +=head3 Using guestfs_set_attach_method + +By calling L</guestfs_set_attach_method> you can change how the +library connects to the C<guestfsd> daemon in L</guestfs_launch> +(read L</ARCHITECTURE> for some background). + +The normal attach method is C<appliance>, where a small appliance is +created containing the daemon, and then the library connects to this. + +Setting attach method to C<unix:I<path>> (where I<path> is the path of +a Unix domain socket) causes L</guestfs_launch> to connect to an +existing daemon over the Unix domain socket. + +The normal use for this is to connect to a running virtual machine +that contains a C<guestfsd> daemon, and send commands so you can read +and write files inside the live virtual machine. + +=head3 Using guestfs_add_domain with live flag + +L</guestfs_add_domain> provides some help for getting the +correct attach method. If you pass the C<live> option to this +function, then (if the virtual machine is running) it will +examine the libvirt XML looking for a virtio-serial channel +to connect to: + + <domain> + ... + <devices> + ... + <channel type='unix'> + <source mode='bind' path='/path/to/socket'/> + <target type='virtio' name='org.libguestfs.channel.0'/> + </channel> + ... + </devices> + </domain> + +L</guestfs_add_domain> extracts C</path/to/socket> and sets the attach +method to C<unix:/path/to/socket>. + +Some of the libguestfs tools (including guestfish) support a I<--live> +option which is passed through to L</guestfs_add_domain> thus allowing +you to attach to and modify live virtual machines. + +The virtual machine needs to have been set up beforehand so that it +has the virtio-serial channel and so that guestfsd is running inside +it. + =head2 ABI GUARANTEE We guarantee the libguestfs ABI (binary interface), for public, diff --git a/src/virt.c b/src/virt.c index 4b66cc8..a23ac0a 100644 --- a/src/virt.c +++ b/src/virt.c @@ -467,7 +467,8 @@ connect_live (guestfs_h *g, virDomainPtr dom) } if (path == NULL) { - error (g, _("this guest has no libvirt <channel> definition for guestfsd")); + error (g, _("this guest has no libvirt <channel> definition for guestfsd\n" + "See ATTACHING TO RUNNING DAEMONS in guestfs(3) for further information.")); goto cleanup; } -- 1.7.3.5
Richard W.M. Jones
2011-Jan-28 19:39 UTC
[Libguestfs] [PATCH 8/8 v2 DISCUSSION ONLY] fish: Add guestfish --live, guestmount --live options.
-- 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 4891a885aa7058faba901c059f08ddfbc5d43159 Mon Sep 17 00:00:00 2001From: Richard W.M. Jones <rjones at redhat.com> Date: Fri, 28 Jan 2011 19:25:02 +0000 Subject: [PATCH 8/8] fish: Add guestfish --live, guestmount --live options. The other programs have the variable, but the flag is not enabled either because it doesn't make sense or because the implications are not well understood. --- cat/virt-cat.c | 2 ++ cat/virt-filesystems.c | 2 ++ cat/virt-ls.c | 2 ++ df/main.c | 2 ++ fish/fish.c | 5 +++++ fish/guestfish.pod | 5 +++++ fish/inspect.c | 6 ++++++ fish/options.h | 1 + fish/virt.c | 4 ++++ fuse/guestmount.c | 5 +++++ fuse/guestmount.pod | 5 +++++ inspector/virt-inspector.c | 2 ++ rescue/virt-rescue.c | 2 ++ 13 files changed, 43 insertions(+), 0 deletions(-) diff --git a/cat/virt-cat.c b/cat/virt-cat.c index 470c70c..834d490 100644 --- a/cat/virt-cat.c +++ b/cat/virt-cat.c @@ -34,6 +34,7 @@ guestfs_h *g; int read_only = 1; +int live = 0; int verbose = 0; int keys_from_stdin = 0; int echo_keys = 0; @@ -213,6 +214,7 @@ main (int argc, char *argv[]) */ assert (read_only == 1); assert (inspector == 1); + assert (live == 0); /* User must specify at least one filename on the command line. */ if (optind >= argc || argc - optind < 1) diff --git a/cat/virt-filesystems.c b/cat/virt-filesystems.c index cd991e8..7eca9eb 100644 --- a/cat/virt-filesystems.c +++ b/cat/virt-filesystems.c @@ -46,6 +46,7 @@ guestfs_h *g; int read_only = 1; +int live = 0; int verbose = 0; int keys_from_stdin = 0; int echo_keys = 0; @@ -301,6 +302,7 @@ main (int argc, char *argv[]) */ assert (read_only == 1); assert (inspector == 0); + assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) diff --git a/cat/virt-ls.c b/cat/virt-ls.c index 64bae46..315fb1f 100644 --- a/cat/virt-ls.c +++ b/cat/virt-ls.c @@ -35,6 +35,7 @@ guestfs_h *g; int read_only = 1; +int live = 0; int verbose = 0; int keys_from_stdin = 0; int echo_keys = 0; @@ -227,6 +228,7 @@ main (int argc, char *argv[]) */ assert (read_only == 1); assert (inspector == 1); + assert (live == 0); /* User must specify at least one directory name on the command line. */ if (optind >= argc || argc - optind < 1) diff --git a/df/main.c b/df/main.c index 7ac5a6c..174692f 100644 --- a/df/main.c +++ b/df/main.c @@ -41,6 +41,7 @@ guestfs_h *g; int read_only = 1; +int live = 0; int verbose = 0; int keys_from_stdin = 0; int echo_keys = 0; @@ -238,6 +239,7 @@ main (int argc, char *argv[]) */ assert (read_only == 1); assert (inspector == 0); + assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) diff --git a/fish/fish.c b/fish/fish.c index eb7c8fe..b62c098 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -74,6 +74,7 @@ static int override_progress_bars = -1; guestfs_h *g; int read_only = 0; +int live = 0; int quit = 0; int verbose = 0; int remote_control_listen = 0; @@ -124,6 +125,7 @@ usage (int status) " -i|--inspector Automatically mount filesystems\n" " --keys-from-stdin Read passphrases from stdin\n" " --listen Listen for remote commands\n" + " --live Connect to a live virtual machine\n" " -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n" " -n|--no-sync Don't autosync\n" " -N|--new type Create prepared disk (test1.img, ...)\n" @@ -173,6 +175,7 @@ main (int argc, char *argv[]) { "inspector", 0, 0, 'i' }, { "keys-from-stdin", 0, 0, 0 }, { "listen", 0, 0, 0 }, + { "live", 0, 0, 0 }, { "mount", 1, 0, 'm' }, { "new", 1, 0, 'N' }, { "no-dest-paths", 0, 0, 'D' }, @@ -277,6 +280,8 @@ main (int argc, char *argv[]) format = optarg; } else if (STREQ (long_options[option_index].name, "csh")) { remote_control_csh = 1; + } else if (STREQ (long_options[option_index].name, "live")) { + live = 1; } else { fprintf (stderr, _("%s: unknown long option: %s (%d)\n"), program_name, long_options[option_index].name, option_index); diff --git a/fish/guestfish.pod b/fish/guestfish.pod index 0f318f0..abf6d7a 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -294,6 +294,11 @@ to try to read passphrases from the user by opening C</dev/tty>. Fork into the background and listen for remote commands. See section L</REMOTE CONTROL GUESTFISH OVER A SOCKET> below. +=item B<--live> + +Connect to a live virtual machine. +(Experimental, see L<guestfs(3)/ATTACHING TO RUNNING DAEMONS>). + =item B<-m dev[:mountpoint]> =item B<--mount dev[:mountpoint]> diff --git a/fish/inspect.c b/fish/inspect.c index 713501e..5e1948c 100644 --- a/fish/inspect.c +++ b/fish/inspect.c @@ -73,6 +73,12 @@ compare_keys (const void *p1, const void *p2) void inspect_mount (void) { + if (live) { + fprintf (stderr, _("%s: don't use --live and -i options together\n"), + program_name); + exit (EXIT_FAILURE); + } + inspect_do_decrypt (); char **roots = guestfs_inspect_os (g); diff --git a/fish/options.h b/fish/options.h index 728df04..b755d90 100644 --- a/fish/options.h +++ b/fish/options.h @@ -67,6 +67,7 @@ /* Provided by guestfish or guestmount. */ extern guestfs_h *g; extern int read_only; +extern int live; extern int verbose; extern int inspector; extern int keys_from_stdin; diff --git a/fish/virt.c b/fish/virt.c index 13a6d12..b14cee2 100644 --- a/fish/virt.c +++ b/fish/virt.c @@ -43,6 +43,10 @@ add_libvirt_drives (const char *guest) optargs.bitmask |= GUESTFS_ADD_DOMAIN_READONLY_BITMASK; optargs.readonly = 1; } + if (live) { + optargs.bitmask |= GUESTFS_ADD_DOMAIN_LIVE_BITMASK; + optargs.live = 1; + } return guestfs_add_domain_argv (g, guest, &optargs); } diff --git a/fuse/guestmount.c b/fuse/guestmount.c index 3d3da39..6adf140 100644 --- a/fuse/guestmount.c +++ b/fuse/guestmount.c @@ -59,6 +59,7 @@ guestfs_h *g = NULL; int read_only = 0; +int live = 0; int verbose = 0; int inspector = 0; int keys_from_stdin = 0; @@ -879,6 +880,7 @@ usage (int status) " -i|--inspector Automatically mount filesystems\n" " --help Display help message and exit\n" " --keys-from-stdin Read passphrases from stdin\n" + " --live Connect to a live virtual machine\n" " -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n" " -n|--no-sync Don't autosync\n" " -o|--option opt Pass extra option to FUSE\n" @@ -917,6 +919,7 @@ main (int argc, char *argv[]) { "help", 0, 0, HELP_OPTION }, { "inspector", 0, 0, 'i' }, { "keys-from-stdin", 0, 0, 0 }, + { "live", 0, 0, 0 }, { "mount", 1, 0, 'm' }, { "no-sync", 0, 0, 'n' }, { "option", 1, 0, 'o' }, @@ -1017,6 +1020,8 @@ main (int argc, char *argv[]) keys_from_stdin = 1; } else if (STREQ (long_options[option_index].name, "echo-keys")) { echo_keys = 1; + } else if (STREQ (long_options[option_index].name, "live")) { + live = 1; } else { fprintf (stderr, _("%s: unknown long option: %s (%d)\n"), program_name, long_options[option_index].name, option_index); diff --git a/fuse/guestmount.pod b/fuse/guestmount.pod index 567a270..338af97 100644 --- a/fuse/guestmount.pod +++ b/fuse/guestmount.pod @@ -143,6 +143,11 @@ mounted on the real virtual machine. Read key or passphrase parameters from stdin. The default is to try to read passphrases from the user by opening C</dev/tty>. +=item B<--live> + +Connect to a live virtual machine. +(Experimental, see L<guestfs(3)/ATTACHING TO RUNNING DAEMONS>). + =item B<-m dev[:mnt]> | B<--mount dev[:mnt]> Mount the named partition or logical volume on the given mountpoint diff --git a/inspector/virt-inspector.c b/inspector/virt-inspector.c index 68f8b46..fda9787 100644 --- a/inspector/virt-inspector.c +++ b/inspector/virt-inspector.c @@ -38,6 +38,7 @@ guestfs_h *g; int read_only = 1; +int live = 0; int verbose = 0; int keys_from_stdin = 0; int echo_keys = 0; @@ -226,6 +227,7 @@ main (int argc, char *argv[]) */ assert (read_only == 1); assert (inspector == 1); + assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) diff --git a/rescue/virt-rescue.c b/rescue/virt-rescue.c index 6224ad7..58be96b 100644 --- a/rescue/virt-rescue.c +++ b/rescue/virt-rescue.c @@ -36,6 +36,7 @@ guestfs_h *g; int read_only = 0; +int live = 0; int verbose = 0; int keys_from_stdin = 0; int echo_keys = 0; @@ -239,6 +240,7 @@ main (int argc, char *argv[]) assert (inspector == 0); assert (keys_from_stdin == 0); assert (echo_keys == 0); + assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) -- 1.7.3.5
Daniel P. Berrange
2011-Feb-03 15:15 UTC
[Libguestfs] [PATCH 8/8 v2 DISCUSSION ONLY] fish: Add guestfish --live, guestmount --live options.
On Fri, Jan 28, 2011 at 07:39:09PM +0000, Richard W.M. Jones wrote:> > -- > 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> >From 4891a885aa7058faba901c059f08ddfbc5d43159 Mon Sep 17 00:00:00 2001 > From: Richard W.M. Jones <rjones at redhat.com> > Date: Fri, 28 Jan 2011 19:25:02 +0000 > Subject: [PATCH 8/8] fish: Add guestfish --live, guestmount --live options. > > The other programs have the variable, but the flag is not enabled > either because it doesn't make sense or because the implications are > not well understood. > --- > cat/virt-cat.c | 2 ++ > cat/virt-filesystems.c | 2 ++ > cat/virt-ls.c | 2 ++ > df/main.c | 2 ++I would have thought it was ok to support --live in these 4, since they're readonly apps in any case.> fish/fish.c | 5 +++++ > fish/guestfish.pod | 5 +++++ > fish/inspect.c | 6 ++++++ > fish/options.h | 1 + > fish/virt.c | 4 ++++ > fuse/guestmount.c | 5 +++++ > fuse/guestmount.pod | 5 +++++ > inspector/virt-inspector.c | 2 ++ > rescue/virt-rescue.c | 2 ++--live probably isn't useful for virt-rescue since if you need to rescue a machine it likely isn't running correctly & thus not have a guestfsd available. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Daniel P. Berrange
2011-Feb-03 15:17 UTC
[Libguestfs] [PATCH 0/8 v2 DISCUSSION ONLY] Connecting to live virtual machines
On Fri, Jan 28, 2011 at 07:36:34PM +0000, Richard W.M. Jones wrote:> > NOTE: This is HIGHLY EXPERIMENTAL and can eat babies ... > > Modify the guest libvirt XML to add the virtio-serial channel: > > <channel type='unix'> > <source mode='bind' path='/tmp/socket'/> > <target type='virtio' name='org.libguestfs.channel.0'/> > </channel> > > In the guest, compile guestfsd and run it like this: > > sudo daemon/guestfsd -rv > > (XXX - should current directory be / ...?)Yeah, I think it makes sense to have it chdir(/) so that it doesn't accidentally cause a random FS to remain busy.> In the host connect using: > > sudo guestfish -d GuestName --live > ><fs> run > ><fs> ll / > etc.I think this series all looks fine. Obviously the main implication you mentioned before is that we'll need to be strict about the RPC wire back-compat support from this point forward. Also need a init script (or systemd unit) to start the guestfsd if-only-if it sees the virtio socket present inside the guest. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Seemingly Similar Threads
- [PATCH febootstrap 0/8] Add support for building an ext2-based appliance
- [PATCH 0/5] 5 conservative changes to errno handling
- [PATCH 0/7] Add libvirt domain to core API
- [PATCH 0/9] Enhance virt-resize so it can really expand Linux and Windows guests
- [PATCH 0/13 v2] Prepare for adding write support to hivex (Windows registry) library