diff options
author | Richard Jones <rjones@redhat.com> | 2010-08-23 11:12:29 +0100 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2010-08-23 16:00:39 +0100 |
commit | 5c31f6126ba4ea3e9056c34c300f6f5e332ab997 (patch) | |
tree | e1c7b237f3d5719804fca3031d26edb9a8027221 /src/launch.c | |
parent | 4b753c62089be663ac722e4a875bb061d259e87d (diff) | |
download | libguestfs-5c31f6126ba4ea3e9056c34c300f6f5e332ab997.tar.gz libguestfs-5c31f6126ba4ea3e9056c34c300f6f5e332ab997.tar.xz libguestfs-5c31f6126ba4ea3e9056c34c300f6f5e332ab997.zip |
Change to using ext2-based, cached supermin appliance.
This changes the method used to build the supermin appliance
to use the new ext2-based appliance supported by latest febootstrap.
The appliance can also be cached, so we avoid rebuilding it
each time it is used.
Mailing list discussion goes into the rationale and details:
https://www.redhat.com/archives/libguestfs/2010-August/msg00028.html
Requires febootstrap >= 2.8.
Diffstat (limited to 'src/launch.c')
-rw-r--r-- | src/launch.c | 210 |
1 files changed, 26 insertions, 184 deletions
diff --git a/src/launch.c b/src/launch.c index 9deb0cfa..f84a128b 100644 --- a/src/launch.c +++ b/src/launch.c @@ -224,53 +224,15 @@ guestfs__add_cdrom (guestfs_h *g, const char *filename) return guestfs__config (g, "-cdrom", filename); } -/* Returns true iff file is contained in dir. */ -static int -dir_contains_file (const char *dir, const char *file) -{ - int dirlen = strlen (dir); - int filelen = strlen (file); - int len = dirlen+filelen+2; - char path[len]; - - snprintf (path, len, "%s/%s", dir, file); - return access (path, F_OK) == 0; -} - -/* Returns true iff every listed file is contained in 'dir'. */ -static int -dir_contains_files (const char *dir, ...) -{ - va_list args; - const char *file; - - va_start (args, dir); - while ((file = va_arg (args, const char *)) != NULL) { - if (!dir_contains_file (dir, file)) { - va_end (args); - return 0; - } - } - va_end (args); - return 1; -} - -static int build_supermin_appliance (guestfs_h *g, const char *path, char **kernel, char **initrd); static int is_openable (guestfs_h *g, const char *path, int flags); static void print_cmdline (guestfs_h *g); -static const char *kernel_name = "vmlinuz." REPO "." host_cpu; -static const char *initrd_name = "initramfs." REPO "." host_cpu ".img"; - int guestfs__launch (guestfs_h *g) { - int r, pmore; - size_t len; + int r; int wfd[2], rfd[2]; int tries; - char *path, *pelem, *pend; - char *kernel = NULL, *initrd = NULL; int null_vmchannel_sock; char unixsock[256]; struct sockaddr_un addr; @@ -302,101 +264,17 @@ guestfs__launch (guestfs_h *g) } } - /* Allow anyone to read the temporary directory. There are no - * secrets in the kernel or initrd files. The socket in this + /* Allow anyone to read the temporary directory. The socket in this * directory won't be readable but anyone can see it exists if they * want. (RHBZ#610880). */ if (chmod (g->tmpdir, 0755) == -1) fprintf (stderr, "chmod: %s: %m (ignored)\n", g->tmpdir); - /* First search g->path for the supermin appliance, and try to - * synthesize a kernel and initrd from that. If it fails, we - * try the path search again looking for a backup ordinary - * appliance. - */ - pelem = path = safe_strdup (g, g->path); - do { - pend = strchrnul (pelem, ':'); - pmore = *pend == ':'; - *pend = '\0'; - len = pend - pelem; - - /* Empty element of "." means cwd. */ - if (len == 0 || (len == 1 && *pelem == '.')) { - if (g->verbose) - fprintf (stderr, - "looking for supermin appliance in current directory\n"); - if (dir_contains_files (".", - "supermin.d", "kmod.whitelist", NULL)) { - if (build_supermin_appliance (g, ".", &kernel, &initrd) == -1) - return -1; - break; - } - } - /* Look at <path>/supermin* etc. */ - else { - if (g->verbose) - fprintf (stderr, "looking for supermin appliance in %s\n", pelem); - - if (dir_contains_files (pelem, - "supermin.d", "kmod.whitelist", NULL)) { - if (build_supermin_appliance (g, pelem, &kernel, &initrd) == -1) - return -1; - break; - } - } - - pelem = pend + 1; - } while (pmore); - - free (path); - - if (kernel == NULL || initrd == NULL) { - /* Search g->path for the kernel and initrd. */ - pelem = path = safe_strdup (g, g->path); - do { - pend = strchrnul (pelem, ':'); - pmore = *pend == ':'; - *pend = '\0'; - len = pend - pelem; - - /* Empty element or "." means cwd. */ - if (len == 0 || (len == 1 && *pelem == '.')) { - if (g->verbose) - fprintf (stderr, - "looking for appliance in current directory\n"); - if (dir_contains_files (".", kernel_name, initrd_name, NULL)) { - kernel = safe_strdup (g, kernel_name); - initrd = safe_strdup (g, initrd_name); - break; - } - } - /* Look at <path>/kernel etc. */ - else { - if (g->verbose) - fprintf (stderr, "looking for appliance in %s\n", pelem); - - if (dir_contains_files (pelem, kernel_name, initrd_name, NULL)) { - kernel = safe_malloc (g, len + strlen (kernel_name) + 2); - initrd = safe_malloc (g, len + strlen (initrd_name) + 2); - sprintf (kernel, "%s/%s", pelem, kernel_name); - sprintf (initrd, "%s/%s", pelem, initrd_name); - break; - } - } - - pelem = pend + 1; - } while (pmore); - - free (path); - } - - if (kernel == NULL || initrd == NULL) { - error (g, _("cannot find %s or %s on LIBGUESTFS_PATH (current path = %s)"), - kernel_name, initrd_name, g->path); - goto cleanup0; - } + /* Locate and/or build the appliance. */ + char *kernel = NULL, *initrd = NULL, *appliance = NULL; + if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1) + return -1; if (g->verbose) guestfs___print_timestamped_message (g, "begin testing qemu features"); @@ -614,12 +492,29 @@ guestfs__launch (guestfs_h *g) g->append ? g->append : ""); add_cmdline (g, "-kernel"); - add_cmdline (g, (char *) kernel); + add_cmdline (g, kernel); add_cmdline (g, "-initrd"); - add_cmdline (g, (char *) initrd); + add_cmdline (g, initrd); add_cmdline (g, "-append"); add_cmdline (g, buf); + /* Add the ext2 appliance drive (last of all). */ + if (appliance) { + const char *cachemode = ""; + if (qemu_supports (g, "cache=")) { + if (qemu_supports (g, "unsafe")) + cachemode = ",cache=unsafe"; + else if (qemu_supports (g, "writeback")) + cachemode = ",cache=writeback"; + } + + char buf2[PATH_MAX + 64]; + add_cmdline (g, "-drive"); + snprintf (buf2, sizeof buf2, "file=%s,snapshot=on,if=" DRIVE_IF "%s", + appliance, cachemode); + add_cmdline (g, buf2); + } + /* Finish off the command line. */ incr_cmdline_size (g); g->cmdline[g->cmdline_size-1] = NULL; @@ -866,6 +761,7 @@ guestfs__launch (guestfs_h *g) g->state = CONFIG; free (kernel); free (initrd); + free (appliance); return -1; } @@ -913,60 +809,6 @@ print_cmdline (guestfs_h *g) fputc ('\n', stderr); } -/* This function does the hard work of building the supermin appliance - * on the fly. 'path' is the directory containing the control files. - * 'kernel' and 'initrd' are where we will return the names of the - * kernel and initrd (only initrd is built). The work is done by - * an external script. We just tell it where to put the result. - */ -static int -build_supermin_appliance (guestfs_h *g, const char *path, - char **kernel, char **initrd) -{ - char cmd[4096]; - int r, len; - - if (g->verbose) - print_timestamped_message (g, "begin building supermin appliance"); - - len = strlen (g->tmpdir); - *kernel = safe_malloc (g, len + 8); - snprintf (*kernel, len+8, "%s/kernel", g->tmpdir); - *initrd = safe_malloc (g, len + 8); - snprintf (*initrd, len+8, "%s/initrd", g->tmpdir); - - /* Set a sensible umask in the subprocess, so kernel and initrd - * output files are world-readable (RHBZ#610880). - */ - snprintf (cmd, sizeof cmd, - "umask 0002; " - "febootstrap-supermin-helper%s " - "-k '%s/kmod.whitelist' " - "'%s/supermin.d' " - host_cpu " " - "%s %s", - g->verbose ? " --verbose" : "", - path, - path, - *kernel, *initrd); - if (g->verbose) - print_timestamped_message (g, "%s", cmd); - - r = system (cmd); - if (r == -1 || WEXITSTATUS(r) != 0) { - error (g, _("external command failed: %s"), cmd); - free (*kernel); - free (*initrd); - *kernel = *initrd = NULL; - return -1; - } - - if (g->verbose) - print_timestamped_message (g, "finished building supermin appliance"); - - return 0; -} - /* Compute Y - X and return the result in milliseconds. * Approximately the same as this code: * http://www.mpp.mpg.de/~huber/util/timevaldiff.c |