psss / rpms / libguestfs

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