From b308fb2a8d31f5439793b908bbf2e8414ee97897 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 3 Mar 2017 13:52:31 +0000 Subject: [PATCH 05/10] rescue: Implement -m and -i options. `virt-rescue -a disk -i' does the right thing. `-m' was previously an alternate form of `--memsize'. By sniffing the parameter we can make `-m MB' continue to work, while also allowing `-m' to be used as a short form for the `--mount' option. This also removes most of the description of `--suggest' from the man page, since it is no longer needed. (cherry picked from commit 33d2ae796119ae5dd38e2afcbf1ba4216bd99846) --- appliance/init | 12 +++++-- rescue/Makefile.am | 3 +- rescue/rescue.c | 87 +++++++++++++++++++++++++++++++++++++------------- rescue/virt-rescue.pod | 80 ++++++++++++++++++++++++++++------------------ 4 files changed, 126 insertions(+), 56 deletions(-) diff --git a/appliance/init b/appliance/init index 810f84d22..968429c4b 100755 --- a/appliance/init +++ b/appliance/init @@ -180,6 +180,10 @@ else # We need a daemon, even in virt-rescue. $cmd & + # XXX This gives a bit of time for virt-rescue to connect to the + # daemon and mount any filesystems. + sleep 2 + # Get name of the serial port, from console= passed by libguestfs. guestfs_serial=$(grep -Eo 'console=[^[:space:]]+' /proc/cmdline | sed s/console=//) @@ -208,8 +212,12 @@ else echo "Welcome to virt-rescue, the libguestfs rescue shell." echo echo "Note: The contents of / (root) are the rescue appliance." - echo "You have to mount the guest's partitions under /sysroot" - echo "before you can examine them." + if ! test -d "/sysroot/dev"; then + echo "You have to mount the guest's partitions under /sysroot" + echo "before you can examine them." + else + echo "Use 'cd /sysroot' or 'chroot /sysroot' to see guest filesystems." + fi echo run_bash_with_ctty echo diff --git a/rescue/Makefile.am b/rescue/Makefile.am index 99d4b79ae..c83c43458 100644 --- a/rescue/Makefile.am +++ b/rescue/Makefile.am @@ -35,7 +35,7 @@ virt_rescue_CPPFLAGS = \ -I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \ -I$(top_srcdir)/lib -I$(top_builddir)/lib \ -I$(top_srcdir)/common/options -I$(top_builddir)/common/options \ - -I$(top_srcdir)/fish \ + -I$(top_srcdir)/common/windows -I$(top_builddir)/common/windows \ -I$(srcdir)/../gnulib/lib -I../gnulib/lib virt_rescue_CFLAGS = \ @@ -43,6 +43,7 @@ virt_rescue_CFLAGS = \ $(LIBXML2_CFLAGS) virt_rescue_LDADD = \ + $(top_builddir)/common/windows/libwindows.la \ $(top_builddir)/common/options/liboptions.la \ $(top_builddir)/common/utils/libutils.la \ $(top_builddir)/lib/libguestfs.la \ diff --git a/rescue/rescue.c b/rescue/rescue.c index b145dcd40..2b461378d 100644 --- a/rescue/rescue.c +++ b/rescue/rescue.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -37,9 +36,11 @@ #include "full-write.h" #include "getprogname.h" #include "ignore-value.h" +#include "nonblocking.h" #include "xvasprintf.h" #include "guestfs.h" +#include "windows.h" #include "options.h" #include "display-options.h" @@ -87,7 +88,9 @@ usage (int status) " -d|--domain guest Add disks from libvirt guest\n" " --format[=raw|..] Force disk format for -a option\n" " --help Display brief help\n" - " -m|--memsize MB Set memory size in megabytes\n" + " -i|--inspector Automatically mount filesystems\n" + " -m|--mount dev[:mnt[:opts[:fstype]] Mount dev on mnt (if omitted, /)\n" + " --memsize MB Set memory size in megabytes\n" " --network Enable network\n" " -r|--ro Access read-only\n" " --scratch[=N] Add scratch disk(s)\n" @@ -116,7 +119,7 @@ main (int argc, char *argv[]) enum { HELP_OPTION = CHAR_MAX + 1 }; - static const char options[] = "a:c:d:m:rvVwx"; + static const char options[] = "a:c:d:im:rvVwx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "append", 1, 0, 0 }, @@ -124,8 +127,10 @@ main (int argc, char *argv[]) { "domain", 1, 0, 'd' }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, + { "inspector", 0, 0, 'i' }, { "long-options", 0, 0, 0 }, - { "memsize", 1, 0, 'm' }, + { "mount", 1, 0, 'm' }, + { "memsize", 1, 0, 0 }, { "network", 0, 0, 0 }, { "ro", 0, 0, 'r' }, { "rw", 0, 0, 'w' }, @@ -140,13 +145,16 @@ main (int argc, char *argv[]) }; struct drv *drvs = NULL; struct drv *drv; + struct mp *mps = NULL; + struct mp *mp; + char *p; const char *format = NULL; bool format_consumed = true; int c; int option_index; int network = 0; const char *append = NULL; - int memsize = 0; + int memsize = 0, m; int smp = 0; int suggest = 0; char *append_full; @@ -196,6 +204,10 @@ main (int argc, char *argv[]) _("--scratch parameter '%s' should be >= 1"), optarg); add_scratch_disks (n, &drvs); } + } else if (STREQ (long_options[option_index].name, "memsize")) { + if (sscanf (optarg, "%d", &memsize) != 1) + error (EXIT_FAILURE, 0, + _("could not parse memory size '%s'"), optarg); } else error (EXIT_FAILURE, 0, _("unknown long option: %s (%d)"), @@ -214,10 +226,19 @@ main (int argc, char *argv[]) OPTION_d; break; + case 'i': + OPTION_i; + break; + case 'm': - if (sscanf (optarg, "%d", &memsize) != 1) - error (EXIT_FAILURE, 0, - _("could not parse memory size '%s'"), optarg); + /* For backwards compatibility with virt-rescue <= 1.36, we + * must handle -m as a synonym for --memsize. + */ + if (sscanf (optarg, "%d", &m) == 1) + memsize = m; + else { + OPTION_m; + } break; case 'r': @@ -288,7 +309,6 @@ main (int argc, char *argv[]) * options parsing code. Assert here that they have known-good * values. */ - assert (inspector == 0); assert (keys_from_stdin == 0); assert (echo_keys == 0); assert (live == 0); @@ -332,12 +352,6 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); free (append_full); - /* Add drives. */ - add_drives (drvs); - - /* Free up data structures, no longer needed after this point. */ - free_drives (drvs); - /* Add an event handler to print "log messages". These will be the * output of the appliance console during launch and shutdown. * After launch, we will read the console messages directly from the @@ -347,21 +361,50 @@ main (int argc, char *argv[]) GUESTFS_EVENT_APPLIANCE, 0, NULL) == -1) exit (EXIT_FAILURE); - /* Run the appliance. */ + /* Do the guest drives and mountpoints. */ + add_drives (drvs); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); + if (inspector) + inspect_mount (); + mount_mps (mps); + + free_drives (drvs); + free_mps (mps); + + /* Also bind-mount /dev etc under /sysroot, if -i was given. */ + if (inspector) { + CLEANUP_FREE_STRING_LIST char **roots; + int windows; + + roots = guestfs_inspect_get_roots (g); + windows = roots && roots[0] && is_windows (g, roots[0]); + if (!windows) { + const char *cmd[5] = { "mount", "--rbind", NULL, NULL, NULL }; + char *r; + + cmd[2] = "/dev"; cmd[3] = "/sysroot/dev"; + r = guestfs_debug (g, "sh", (char **) cmd); + free (r); + + cmd[2] = "/proc"; cmd[3] = "/sysroot/proc"; + r = guestfs_debug (g, "sh", (char **) cmd); + free (r); + + cmd[2] = "/sys"; cmd[3] = "/sysroot/sys"; + r = guestfs_debug (g, "sh", (char **) cmd); + free (r); + } + } sock = guestfs_internal_get_console_socket (g); if (sock == -1) exit (EXIT_FAILURE); /* Try to set all sockets to non-blocking. */ - if (fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) - perror ("could not set stdin to non-blocking"); - if (fcntl (STDOUT_FILENO, F_SETFL, O_NONBLOCK) == -1) - perror ("could not set stdout to non-blocking"); - if (fcntl (sock, F_SETFL, O_NONBLOCK) == -1) - perror ("could not set console socket to non-blocking"); + ignore_value (set_nonblocking_flag (STDIN_FILENO, 1)); + ignore_value (set_nonblocking_flag (STDOUT_FILENO, 1)); + ignore_value (set_nonblocking_flag (sock, 1)); /* Save the initial state of the tty so we always have the original * state to go back to. diff --git a/rescue/virt-rescue.pod b/rescue/virt-rescue.pod index b8aa32637..b651f84e7 100644 --- a/rescue/virt-rescue.pod +++ b/rescue/virt-rescue.pod @@ -6,9 +6,7 @@ virt-rescue - Run a rescue shell on a virtual machine virt-rescue [--options] -d domname - virt-rescue [--options] -a disk.img [-a disk.img ...] - - virt-rescue --suggest (-d domname | -a disk.img ...) + virt-rescue [--options] -a disk.img [-a disk.img ...] [-i] Old style: @@ -26,13 +24,13 @@ machine or disk image. You can run virt-rescue on any virtual machine known to libvirt, or directly on disk image(s): - virt-rescue -d GuestName + virt-rescue -d GuestName -i - virt-rescue --ro -a /path/to/disk.img + virt-rescue --ro -a /path/to/disk.img -i virt-rescue -a /dev/sdc -For live VMs you I use the --ro option. +For live VMs you I use the I<--ro> option. When you run virt-rescue on a virtual machine or disk image, you are placed in an interactive bash shell where you can use many ordinary @@ -41,26 +39,10 @@ rescue appliance. You must mount the virtual machine's filesystems by hand. There is an empty directory called F where you can mount filesystems. -You can get virt-rescue to suggest mount commands for you by using the -I<--suggest> option (in another terminal): - - $ virt-rescue --suggest -d Fedora15 - Inspecting the virtual machine or disk image ... - - This disk contains one or more operating systems. You can use these - mount commands in virt-rescue (at the > prompt) to mount the - filesystems. - - # /dev/vg_f15x32/lv_root is the root of a linux operating system - # type: linux, distro: fedora, version: 15.0 - # Fedora release 15 (Lovelock) - - mount /dev/vg_f15x32/lv_root /sysroot/ - mount /dev/vda1 /sysroot/boot - mount --bind /dev /sysroot/dev - mount --bind /dev/pts /sysroot/dev/pts - mount --bind /proc /sysroot/proc - mount --bind /sys /sysroot/sys +To automatically mount the virtual machine's filesystems under +F use the I<-i> option. This uses libguestfs inspection to +find the filesystems and mount them in the right place. You can also +mount filesystems individually using the I<-m> option. Another way is to list the logical volumes (with L) and partitions (with L) and mount them by hand: @@ -170,7 +152,15 @@ If you have untrusted raw-format guest disk images, you should use this option to specify the disk format. This avoids a possible security problem with malicious guests (CVE-2010-3851). -=item B<-m> MB +=item B<-i> + +=item B<--inspector> + +Using L code, inspect the disks looking for +an operating system and mount filesystems as they would be +mounted on the real virtual machine. + +The filesystems are mounted on F in the rescue environment. =item B<--memsize> MB @@ -179,6 +169,33 @@ default is set by libguestfs and is small but adequate for running system tools. The occasional program might need more memory. The parameter is specified in megabytes. +=item B<-m> dev[:mountpoint[:options[:fstype]]] + +=item B<--mount> dev[:mountpoint[:options[:fstype]]] + +Mount the named partition or logical volume on the given mountpoint +B (this has nothing to do with mountpoints in the host). + +If the mountpoint is omitted, it defaults to F. You have to mount +something on F. + +The filesystems are mounted under F in the rescue environment. + +The third (and rarely used) part of the mount parameter is the list of +mount options used to mount the underlying filesystem. If this is not +given, then the mount options are either the empty string or C +(the latter if the I<--ro> flag is used). By specifying the mount +options, you override this default choice. Probably the only time you +would use this is to enable ACLs and/or extended attributes if the +filesystem can support them: + + -m /dev/sda1:/:acl,user_xattr + +The fourth part of the parameter is the filesystem driver to use, such +as C or C. This is rarely needed, but can be useful if +multiple drivers are valid for a filesystem (eg: C and C), +or if libguestfs misidentifies a filesystem. + =item B<--network> Enable QEMU user networking in the guest. See L. @@ -217,9 +234,10 @@ Enable N E 2 virtual CPUs in the rescue appliance. =item B<--suggest> -Inspect the disk image and suggest what mount commands should be used -to mount the disks. You should use the I<--suggest> option in a -second terminal, then paste the commands into another virt-rescue. +This option was used in older versions of virt-rescue to suggest what +commands you could use to mount filesystems under F. For +the current version of virt-rescue, it is easier to use the I<-i> +option instead. This option implies I<--ro> and is safe to use even if the guest is up or if another virt-rescue is running. @@ -240,7 +258,7 @@ Display version number and exit. =item B<--rw> -This changes the I<-a> and I<-d> options so that disks are +This changes the I<-a>, I<-d> and I<-m> options so that disks are added and mounts are done read-write. See L. -- 2.13.2