mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
rescue: Add --suggest option to suggest mount commands.
This commit is contained in:
@@ -36,6 +36,8 @@
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
|
||||
static void do_suggestion (struct drv *drvs);
|
||||
|
||||
/* Currently open libguestfs handle. */
|
||||
guestfs_h *g;
|
||||
|
||||
@@ -78,6 +80,7 @@ usage (int status)
|
||||
" -r|--ro Access read-only\n"
|
||||
" --selinux Enable SELinux\n"
|
||||
" --smp N Enable SMP with N >= 2 virtual CPUs\n"
|
||||
" --suggest Suggest mount commands for this guest\n"
|
||||
" -v|--verbose Verbose messages\n"
|
||||
" -V|--version Display version and exit\n"
|
||||
" -w|--rw Mount read-write\n"
|
||||
@@ -117,6 +120,7 @@ main (int argc, char *argv[])
|
||||
{ "rw", 0, 0, 'w' },
|
||||
{ "selinux", 0, 0, 0 },
|
||||
{ "smp", 1, 0, 0 },
|
||||
{ "suggest", 0, 0, 0 },
|
||||
{ "verbose", 0, 0, 'v' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ 0, 0, 0, 0 }
|
||||
@@ -131,6 +135,7 @@ main (int argc, char *argv[])
|
||||
char *append_full;
|
||||
int memsize = 0;
|
||||
int smp = 0;
|
||||
int suggest = 0;
|
||||
|
||||
g = guestfs_create ();
|
||||
if (g == NULL) {
|
||||
@@ -168,6 +173,8 @@ main (int argc, char *argv[])
|
||||
program_name, optarg);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
} else if (STREQ (long_options[option_index].name, "suggest")) {
|
||||
suggest = 1;
|
||||
} else {
|
||||
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
|
||||
program_name, long_options[option_index].name, option_index);
|
||||
@@ -259,6 +266,12 @@ main (int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* --suggest flag */
|
||||
if (suggest) {
|
||||
do_suggestion (drvs);
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* These are really constants, but they have to be variables for the
|
||||
* options parsing code. Assert here that they have known-good
|
||||
* values.
|
||||
@@ -315,6 +328,159 @@ main (int argc, char *argv[])
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void suggest_filesystems (void);
|
||||
|
||||
static int
|
||||
compare_keys_len (const void *p1, const void *p2)
|
||||
{
|
||||
const char *key1 = * (char * const *) p1;
|
||||
const char *key2 = * (char * const *) p2;
|
||||
return strlen (key1) - strlen (key2);
|
||||
}
|
||||
|
||||
static size_t
|
||||
count_strings (char *const *argv)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; argv[i]; ++i)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* virt-rescue --suggest flag does a kind of inspection on the
|
||||
* drives and suggests mount commands that you should use.
|
||||
*/
|
||||
static void
|
||||
do_suggestion (struct drv *drvs)
|
||||
{
|
||||
char **roots;
|
||||
size_t i, j;
|
||||
char *type, *distro, *product_name;
|
||||
int major, minor;
|
||||
char **mps;
|
||||
|
||||
/* For inspection, force add_drives to add the drives read-only. */
|
||||
read_only = 1;
|
||||
|
||||
/* Add drives. */
|
||||
add_drives (drvs, 'a');
|
||||
|
||||
/* Free up data structures, no longer needed after this point. */
|
||||
free_drives (drvs);
|
||||
|
||||
printf (_("Inspecting the virtual machine or disk image ...\n\n"));
|
||||
fflush (stdout);
|
||||
|
||||
if (guestfs_launch (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Don't use inspect_mount, since for virt-rescue we should allow
|
||||
* arbitrary disks and disks with more than one OS on them. Let's
|
||||
* do this using the basic API instead.
|
||||
*/
|
||||
roots = guestfs_inspect_os (g);
|
||||
if (roots == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if (roots[0] == NULL) {
|
||||
suggest_filesystems ();
|
||||
return;
|
||||
}
|
||||
|
||||
printf (_("This disk contains one or more operating systems. You can use these mount\n"
|
||||
"commands in virt-rescue (at the ><rescue> prompt) to mount the filesystems.\n\n"));
|
||||
|
||||
for (i = 0; roots[i] != NULL; ++i) {
|
||||
type = guestfs_inspect_get_type (g, roots[i]);
|
||||
distro = guestfs_inspect_get_distro (g, roots[i]);
|
||||
product_name = guestfs_inspect_get_product_name (g, roots[i]);
|
||||
major = guestfs_inspect_get_major_version (g, roots[i]);
|
||||
minor = guestfs_inspect_get_minor_version (g, roots[i]);
|
||||
|
||||
printf (_("# %s is the root of a %s operating system\n"
|
||||
"# type: %s, distro: %s, version: %d.%d\n"
|
||||
"# %s\n\n"),
|
||||
roots[i], type ? : "unknown",
|
||||
type ? : "unknown", distro ? : "unknown", major, minor,
|
||||
product_name ? : "");
|
||||
|
||||
mps = guestfs_inspect_get_mountpoints (g, roots[i]);
|
||||
if (mps == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Sort by key length, shortest key first, so that we end up
|
||||
* mounting the filesystems in the correct order.
|
||||
*/
|
||||
qsort (mps, count_strings (mps) / 2, 2 * sizeof (char *),
|
||||
compare_keys_len);
|
||||
|
||||
for (j = 0; mps[j] != NULL; j += 2) {
|
||||
printf ("mount %s /sysroot%s\n", mps[j+1], mps[j]);
|
||||
free (mps[j]);
|
||||
free (mps[j+1]);
|
||||
}
|
||||
|
||||
/* If it's Linux, print the bind-mounts. */
|
||||
if (type && STREQ (type, "linux")) {
|
||||
printf ("mount --bind /dev /sysroot/dev\n");
|
||||
printf ("mount --bind /dev/pts /sysroot/dev/pts\n");
|
||||
printf ("mount --bind /proc /sysroot/proc\n");
|
||||
printf ("mount --bind /sys /sysroot/sys\n");
|
||||
}
|
||||
|
||||
printf ("\n");
|
||||
|
||||
free (type);
|
||||
free (distro);
|
||||
free (product_name);
|
||||
free (roots[i]);
|
||||
}
|
||||
|
||||
free (roots);
|
||||
}
|
||||
|
||||
/* Inspection failed, so it doesn't contain any OS that we recognise.
|
||||
* However there might still be filesystems so print some suggestions
|
||||
* for those.
|
||||
*/
|
||||
static void
|
||||
suggest_filesystems (void)
|
||||
{
|
||||
char **fses;
|
||||
size_t i;
|
||||
|
||||
fses = guestfs_list_filesystems (g);
|
||||
if (fses == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if (fses[0] == NULL) {
|
||||
printf (_("This disk contains no filesystems that we recognize.\n\n"
|
||||
"However you can still use virt-rescue on the disk image, to try to mount\n"
|
||||
"filesystems that are not recognized by libguestfs, or to create partitions,\n"
|
||||
"logical volumes and filesystems on a blank disk.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
printf (_("This disk contains one or more filesystems, but we don't recognize any\n"
|
||||
"operating system. You can use these mount commands in virt-rescue (at the\n"
|
||||
"><rescue> prompt) to mount these filesystems.\n\n"));
|
||||
|
||||
for (i = 0; fses[i] != NULL; i += 2) {
|
||||
printf (_("# %s has type '%s'\n"), fses[i], fses[i+1]);
|
||||
|
||||
if (STRNEQ (fses[i+1], "swap") && STRNEQ (fses[i+1], "unknown"))
|
||||
printf ("mount %s /sysroot\n", fses[i]);
|
||||
|
||||
printf ("\n");
|
||||
|
||||
free (fses[i]);
|
||||
free (fses[i+1]);
|
||||
}
|
||||
free (fses);
|
||||
}
|
||||
|
||||
|
||||
/* The following was a nice idea, but in fact it doesn't work. This is
|
||||
* because qemu has some (broken) pty emulation itself.
|
||||
*/
|
||||
|
||||
@@ -10,6 +10,8 @@ virt-rescue - Run a rescue shell on a virtual machine
|
||||
|
||||
virt-rescue [--options] -a disk.img [-a disk.img ...]
|
||||
|
||||
virt-rescue --suggest (-d domname | -a disk.img ...)
|
||||
|
||||
Old style:
|
||||
|
||||
virt-rescue [--options] domname
|
||||
@@ -51,19 +53,45 @@ rescue appliance. You must mount the virtual machine's filesystems by
|
||||
hand. There is an empty directory called C</sysroot> where you can
|
||||
mount filesystems.
|
||||
|
||||
In the example below, we list logical volumes, then choose one to
|
||||
mount under C</sysroot>:
|
||||
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 ><rescue> 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
|
||||
|
||||
Another way is to list the logical volumes (with L<lvs(8)>) and
|
||||
partitions (with L<parted(8)>) and mount them by hand:
|
||||
|
||||
><rescue> lvs
|
||||
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
|
||||
lv_root vg_f11x64 -wi-a- 8.83G
|
||||
lv_swap vg_f11x64 -wi-a- 992.00M
|
||||
><rescue> mount /dev/vg_f11x64/lv_root /sysroot
|
||||
lv_root vg_f15x32 -wi-a- 8.83G
|
||||
lv_swap vg_f15x32 -wi-a- 992.00M
|
||||
><rescue> mount /dev/vg_f15x32/lv_root /sysroot
|
||||
><rescue> mount /dev/vda1 /sysroot/boot
|
||||
><rescue> ls /sysroot
|
||||
|
||||
If you don't know what filesystems are available on the virtual
|
||||
machine then you can use commands such as L<parted(8)> and L<lvs(8)>
|
||||
to find out.
|
||||
Another command to list available filesystems is
|
||||
L<virt-filesystems(1)>.
|
||||
|
||||
To run commands in a Linux guest (for example, grub), you should
|
||||
chroot into the /sysroot directory first:
|
||||
|
||||
><rescue> chroot /sysroot
|
||||
|
||||
=head2 NOTES
|
||||
|
||||
@@ -179,6 +207,15 @@ L<guestfs(3)/SELINUX> before using this option.
|
||||
|
||||
Enable N E<ge> 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 implies I<--ro> and is safe to use even if the guest is up
|
||||
or if another virt-rescue is running.
|
||||
|
||||
=item B<-v>
|
||||
|
||||
=item B<--verbose>
|
||||
@@ -291,6 +328,7 @@ L<guestfs(3)>,
|
||||
L<guestfish(1)>,
|
||||
L<virt-cat(1)>,
|
||||
L<virt-edit(1)>,
|
||||
L<virt-filesystems(1)>,
|
||||
L<http://libguestfs.org/>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Reference in New Issue
Block a user