Maros Zatko
2016-May-24 17:11 UTC
[Libguestfs] [PATCH] rescue: add --autosysroot option RHBZ#1183493
--autosysroot option uses suggestions to user on how to mount filesystems and change root suggested by --suggest option in virt-rescue. Commands are passed on kernel command line in format guestfs_command=command;. Command ends with a semicolon and there can be multiple commands specified. These are executed just before bash starts. On successfull run user is presented directly with bash in chroot environment. RFE: RHBZ#1183493 Depends on commit: utils: make guestfs_int_count_strings return 0 on NULL input Maros Zatko (1): rescue: add --autosysroot option RHBZ#1183493 appliance/init | 6 +++ rescue/rescue.c | 160 ++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 134 insertions(+), 32 deletions(-) -- 2.5.5
Maros Zatko
2016-May-24 17:11 UTC
[Libguestfs] [PATCH] rescue: add --autosysroot option RHBZ#1183493
--autosysroot option uses suggestions to user on how to mount filesystems and change root suggested by --suggest option in virt-rescue. Commands are passed on kernel command line in format guestfs_command=command;. Command ends with a semicolon and there can be multiple commands specified. These are executed just before bash starts. On successfull run user is presented directly with bash in chroot environment. RFE: RHBZ#1183493 Depends on commit: utils: make guestfs_int_count_strings return 0 on NULL input --- appliance/init | 6 +++ rescue/rescue.c | 160 ++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 134 insertions(+), 32 deletions(-) diff --git a/appliance/init b/appliance/init index 413a95f..82dac9f 100755 --- a/appliance/init +++ b/appliance/init @@ -182,6 +182,7 @@ else :> $HOME/.bashrc grep -Eo 'TERM=[^[:space:]]+' /proc/cmdline >> $HOME/.bashrc + echo "PS1='><rescue> '" >> $HOME/.bashrc echo "export TERM PS1" >> $HOME/.bashrc @@ -194,6 +195,11 @@ else echo "You have to mount the guest's partitions under /sysroot" echo "before you can examine them." echo + echo 'Executing commands from kernel cmdline' + + grep -Eo 'guestfs_command=([^;]+);[[:space:]]*' /proc/cmdline | sed -n 's/guestfs_command=\(.*;\)/\1/p' + eval $(grep -Eo 'guestfs_command=([^;]+);[[:space:]]*' /proc/cmdline | sed -n 's/guestfs_command=\(.*;\)/\1/p') + bash -i echo echo "virt-rescue: Syncing the disk now before exiting ..." diff --git a/rescue/rescue.c b/rescue/rescue.c index c46c775..9311d9e 100644 --- a/rescue/rescue.c +++ b/rescue/rescue.c @@ -37,7 +37,7 @@ #include "options.h" static void add_scratch_disks (int n, struct drv **drvs); -static void do_suggestion (struct drv *drvs); +static char ** do_suggestion (struct drv *drvs); /* Currently open libguestfs handle. */ guestfs_h *g; @@ -50,6 +50,8 @@ int echo_keys = 0; const char *libvirt_uri = NULL; int inspector = 0; +static void use_suggestions (char * *cmds); + static void __attribute__((noreturn)) usage (int status) { @@ -87,21 +89,27 @@ usage (int status) exit (status); } -int -main (int argc, char *argv[]) -{ - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEBASEDIR); - textdomain (PACKAGE); - - parse_config (); - + struct drv *drvs = NULL; + struct drv *drv; + char * *cmds = NULL; + const char *format = NULL; + bool format_consumed = true; + int c; + int option_index; + int network = 0; + char *append = NULL; + int memsize = 0; + int smp = 0; + int suggest = 0; + int autosysroot = 0; +void parse_opts(int argc, char * argv[]) { enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:m:rvVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "append", 1, 0, 0 }, + { "autosysroot", 0, 0, 0 }, { "connect", 1, 0, 'c' }, { "domain", 1, 0, 'd' }, { "format", 2, 0, 0 }, @@ -120,22 +128,10 @@ main (int argc, char *argv[]) { "version", 0, 0, 'V' }, { 0, 0, 0, 0 } }; - struct drv *drvs = NULL; - struct drv *drv; - const char *format = NULL; - bool format_consumed = true; - int c; - int option_index; - int network = 0; - const char *append = NULL; - int memsize = 0; - int smp = 0; - int suggest = 0; - g = guestfs_create (); - if (g == NULL) - error (EXIT_FAILURE, errno, "guestfs_create"); + option_index = 0; + optind = 0; for (;;) { c = getopt_long (argc, argv, options, long_options, &option_index); if (c == -1) break; @@ -150,7 +146,9 @@ main (int argc, char *argv[]) if (guestfs_set_selinux (g, 1) == -1) exit (EXIT_FAILURE); } else if (STREQ (long_options[option_index].name, "append")) { - append = optarg; + append = strdup (optarg); + } else if (STREQ (long_options[option_index].name, "autosysroot")) { + autosysroot = 1; } else if (STREQ (long_options[option_index].name, "network")) { network = 1; } else if (STREQ (long_options[option_index].name, "format")) { @@ -259,10 +257,67 @@ main (int argc, char *argv[]) } } +} + +int +main (int argc, char *argv[]) +{ + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEBASEDIR); + textdomain (PACKAGE); + + parse_config (); + g = guestfs_create (); + if (g == NULL) + error (EXIT_FAILURE, errno, "guestfs_create"); + + parse_opts (argc, argv); + /* --suggest flag */ if (suggest) { - do_suggestion (drvs); - exit (EXIT_SUCCESS); + cmds = do_suggestion (drvs); + if (!autosysroot) { + exit (EXIT_SUCCESS); + } else { + /* Shut down libguestfs so we can start a new one */ + guestfs_shutdown (g); + guestfs_close (g); + + /* remove --suggest flag */ + size_t newcount = argc; + for (int i = 0; i < argc; i++) { + if (strcmp (argv[i], "--suggest") == 0) { + newcount--; + } + } + + char ** args = malloc (sizeof (char*) * (newcount)); + for (int i = 0, j = 0; i < argc; i++) { + if (strcmp (argv[i], "--suggest") != 0) { + args[j] = strdup (argv[i]); + j++; + } + } + + /* clear options */ + drvs = NULL; + if (format) free(format); + format_consumed = true; + c = 0; + option_index = 0; + network = 0; + if (append) free(append); + memsize = 0; + smp = 0; + suggest = 0; + autosysroot = 0; + + /* Create new guestfs handle, this time for rescue instead of OS detection */ + g = guestfs_create (); + /* Parse options with --suggest flag removed */ + parse_opts (newcount, args); + argc = newcount; + } } /* These are really constants, but they have to be variables for the @@ -305,6 +360,11 @@ main (int argc, char *argv[]) } } + /* Now it's time to set suggestions. */ + if (autosysroot) { + use_suggestions (cmds); + } + /* Set other features. */ if (memsize > 0) if (guestfs_set_memsize (g, memsize) == -1) @@ -359,14 +419,33 @@ compare_keys_len (const void *p1, const void *p2) return strlen (key1) - strlen (key2); } +/* Use autodetected suggested filesystems */ +static void +use_suggestions (char * *cmds) +{ + size_t i; + if (cmds == NULL) return; + read_only = 0; + + /* Craft kernel command line from suggested commands */ + for (i = 0; cmds[i] != NULL; i++) { + char *old_append = append; + append = xasprintf ("%s guestfs_command=%s;", append == NULL? "" : append, cmds[i]); + if (old_append != NULL) + free (old_append); + } +} + /* virt-rescue --suggest flag does a kind of inspection on the * drives and suggests mount commands that you should use. */ -static void +static char ** do_suggestion (struct drv *drvs) { CLEANUP_FREE_STRING_LIST char **roots = NULL; size_t i; + char * *cmds = NULL; + /* For inspection, force add_drives to add the drives read-only. */ read_only = 1; @@ -393,7 +472,7 @@ do_suggestion (struct drv *drvs) if (roots[0] == NULL) { suggest_filesystems (); - return; + return NULL; } printf (_("This disk contains one or more operating systems. You can use these mount\n" @@ -428,10 +507,16 @@ do_suggestion (struct drv *drvs) qsort (mps, guestfs_int_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]); + /* First we save commands to mount system root. */ + for (j = 0; mps[j] != NULL; j += 2) { + int cnt = guestfs_int_count_strings (cmds); + cmds = realloc (cmds, sizeof (char *) * (cnt + 2)); - /* If it's Linux, print the bind-mounts and a chroot command. */ + cmds[cnt] = xasprintf ("mount %s /sysroot%s", mps[j+1], mps[j]); + cmds[cnt+1] = NULL; + } + + /* If it's Linux, print the bind-mounts and a chroot command and save them. */ if (type && STREQ (type, "linux")) { printf ("mount --rbind /dev /sysroot/dev\n"); printf ("mount --rbind /proc /sysroot/proc\n"); @@ -439,10 +524,21 @@ do_suggestion (struct drv *drvs) printf ("\n"); printf ("cd /sysroot\n"); printf ("chroot /sysroot\n"); + + int cnt = guestfs_int_count_strings (cmds); + cmds = realloc (cmds, sizeof (char *) * (cnt + 6)); + + cmds[cnt+0] = xasprintf ("mount --rbind /dev /sysroot/dev"); + cmds[cnt+1] = xasprintf ("mount --rbind /proc /sysroot/proc"); + cmds[cnt+2] = xasprintf ("mount --rbind /sys /sysroot/sys"); + cmds[cnt+3] = xasprintf ("cd /sysroot"); + cmds[cnt+4] = xasprintf ("chroot /sysroot"); + cmds[cnt+5] = NULL; } printf ("\n"); } + return cmds; } /* Inspection failed, so it doesn't contain any OS that we recognise. -- 2.5.5
Apparently Analagous Threads
- [PATCH v2] rescue: add --autosysroot option RHBZ#1183493
- Re: [PATCH v2] rescue: add --autosysroot option RHBZ#1183493
- [PATCH v2] rescue: add --autosysroot option RHBZ#1183493
- Re: [PATCH v2] rescue: add --autosysroot option RHBZ#1183493
- [PATCH v3 0/1] tools: add '--blocksize' option for C-based tools