[PATCH 1/7] mount: Add mount_vfs_nochroot This is significantly reworked from before. umount is gone as discussed, and variable motion is minimised. [PATCH 2/7] btrfs: Update btrfs_subvolume_list to take Already provisionally ACKed. Previous comment was that cleanup could be tidier. I looked into creating a new cleanup function for fs_buf, but it isn't possible (or simple, anyway) in this case for 2 reasons: 1. You'd need 2 arguments passed to the cleanup function, not one. Without fs->type you don't know whether fs_buf has been mounted or not. 2. You can't catch and report an error. [PATCH 3/7] mountable: Make list-filesystems return btrfsvols Already provisionally ACKed. [PATCH 4/7] New internal API: internal_parse_mountable [PATCH 5/7] inspect: Update inspect_os to use mountables [PATCH 6/7] btrfs: Make a stub Fedora btrfs guest for inspection [PATCH 7/7] mountable: Test inspection of fedora image Not previously reviewed.
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 1/7] mount: Add mount_vfs_nochroot
This internal function allows mounting a mountable outside /sysroot. --- daemon/daemon.h | 6 ++++++ daemon/mount.c | 14 +++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/daemon/daemon.h b/daemon/daemon.h index 67adec0..d343dfd 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -65,6 +65,12 @@ extern int xread (int sock, void *buf, size_t len) extern char *mountable_to_string (const mountable_t *mountable); +/*-- in mount.c --*/ + +extern int mount_vfs_nochroot (const char *options, const char *vfstype, + const mountable_t *mountable, + const char *mp, const char *user_mp); + /* Growable strings buffer. */ struct stringsbuf { char **argv; diff --git a/daemon/mount.c b/daemon/mount.c index 7e1199f..452b938 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -126,9 +126,7 @@ int do_mount_vfs (const char *options, const char *vfstype, const mountable_t *mountable, const char *mountpoint) { - int r; CLEANUP_FREE char *mp = NULL; - CLEANUP_FREE char *error = NULL; struct stat statbuf; ABS_PATH (mountpoint, , return -1); @@ -149,6 +147,14 @@ do_mount_vfs (const char *options, const char *vfstype, return -1; } + return mount_vfs_nochroot (options, vfstype, mountable, mp, mountpoint); +} + +int +mount_vfs_nochroot (const char *options, const char *vfstype, + const mountable_t *mountable, + const char *mp, const char *user_mp) +{ CLEANUP_FREE char *options_plus = NULL; const char *device = mountable->device; if (mountable->type == MOUNTABLE_BTRFSVOL) { @@ -169,6 +175,8 @@ do_mount_vfs (const char *options, const char *vfstype, } } + CLEANUP_FREE char *error = NULL; + int r; if (vfstype) r = command (NULL, &error, str_mount, "-o", options_plus ? options_plus : options, @@ -179,7 +187,7 @@ do_mount_vfs (const char *options, const char *vfstype, device, mp, NULL); if (r == -1) { reply_with_error ("%s on %s (options: '%s'): %s", - device, mountpoint, options, error); + device, user_mp, options, error); return -1; } -- 1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 2/7] btrfs: Update btrfs_subvolume_list to take Mountable_or_Path
btrfs_subvolume_list can now take either the path of a mounted btrfs filesystem, or a mountable describing the location of a btrfs filesystem, or one of its volumes. In the latter case, the filesystem will be automatically mounted outside of /sysroot before running the btrfs tool, and unmounted afterwards. --- daemon/btrfs.c | 71 ++++++++++++++++++++++++++++++++++++++++++++-------- generator/actions.ml | 2 +- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 81ce5f5..c3247ac 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -34,6 +34,7 @@ GUESTFSD_EXT_CMD(str_btrfs, btrfs); GUESTFSD_EXT_CMD(str_btrfstune, btrfstune); GUESTFSD_EXT_CMD(str_btrfsck, btrfsck); GUESTFSD_EXT_CMD(str_mkfs_btrfs, mkfs.btrfs); +GUESTFSD_EXT_CMD(str_umount, umount); int optgroup_btrfs_available (void) @@ -307,16 +308,47 @@ do_btrfs_subvolume_create (const char *dest) } guestfs_int_btrfssubvolume_list * -do_btrfs_subvolume_list (const char *fs) +do_btrfs_subvolume_list (const mountable_t *fs) { char **lines; /* Execute 'btrfs subvolume list <fs>', and split the output into lines */ { - CLEANUP_FREE char *fs_buf = sysroot_path (fs); - if (fs_buf == NULL) { - reply_with_perror ("malloc"); - return NULL; + CLEANUP_FREE char *fs_buf = NULL; + + if (fs->type == MOUNTABLE_PATH) { + fs_buf = sysroot_path (fs->device); + if (fs_buf == NULL) { + reply_with_perror ("malloc"); + + cmderror: + if (fs->type != MOUNTABLE_PATH && fs_buf) { + CLEANUP_FREE char *err = NULL; + if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) + fprintf (stderr, "%s\n", err); + + if (rmdir (fs_buf) == -1 && errno != ENOENT) + fprintf (stderr, "rmdir: %m\n"); + } + return NULL; + } + } + + else { + fs_buf = strdup ("/tmp/btrfs.XXXXXX"); + if (fs_buf == NULL) { + reply_with_perror ("strdup"); + goto cmderror; + } + + if (mkdtemp (fs_buf) == NULL) { + reply_with_perror ("mkdtemp"); + goto cmderror; + } + + if (mount_vfs_nochroot ("", NULL, fs, fs_buf, "<internal>") == -1) { + goto cmderror; + } } size_t i = 0; @@ -328,16 +360,33 @@ do_btrfs_subvolume_list (const char *fs) ADD_ARG (argv, i, fs_buf); ADD_ARG (argv, i, NULL); - CLEANUP_FREE char *out = NULL, *err = NULL; - int r = commandv (&out, &err, argv); + CLEANUP_FREE char *out = NULL, *errout = NULL; + int r = commandv (&out, &errout, argv); + + if (fs->type != MOUNTABLE_PATH) { + CLEANUP_FREE char *err = NULL; + if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) { + reply_with_error ("%s", err ? err : "malloc"); + goto cmderror; + } + + if (rmdir (fs_buf) == -1 && errno != ENOENT) { + reply_with_error ("rmdir: %m\n"); + goto cmderror; + } + } + if (r == -1) { - reply_with_error ("%s: %s", fs, err); - return NULL; + CLEANUP_FREE char *fs_desc = mountable_to_string (fs); + if (fs_desc == NULL) { + fprintf (stderr, "malloc: %m"); + } + reply_with_error ("%s: %s", fs_desc ? fs_desc : "malloc", errout); + goto cmderror; } lines = split_lines (out); - if (!lines) - return NULL; + if (!lines) return NULL; } /* Output is: diff --git a/generator/actions.ml b/generator/actions.ml index 6a42bca..f17cb6a 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -9519,7 +9519,7 @@ directory and the name of the snapshot, in the form C</path/to/dest/name>." }; { defaults with name = "btrfs_subvolume_list"; - style = RStructList ("subvolumes", "btrfssubvolume"), [Pathname "fs"], []; + style = RStructList ("subvolumes", "btrfssubvolume"), [Mountable_or_Path "fs"], []; proc_nr = Some 325; optional = Some "btrfs"; camel_name = "BTRFSSubvolumeList"; tests = [] (* tested in tests/btrfs *); -- 1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 3/7] mountable: Make list-filesystems return btrfsvols
--- src/listfs.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/listfs.c b/src/listfs.c index 4bcdf51..3e4f28e 100644 --- a/src/listfs.c +++ b/src/listfs.c @@ -136,6 +136,20 @@ remove_from_list (char **list, const char *item) } } +static void +add_vfs(guestfs_h *g, char *mountable, char *vfs_type, + char ***ret, size_t *ret_size) +{ + /* Extend the return array. */ + size_t i = *ret_size; + *ret_size += 2; + *ret = safe_realloc (g, *ret, (*ret_size + 1) * sizeof (char *)); + + (*ret)[i] = mountable; + (*ret)[i+1] = vfs_type; + (*ret)[i+2] = NULL; +} + /* Use vfs-type to look for a filesystem of some sort on 'dev'. * Apart from some types which we ignore, add the result to the * 'ret' string list. @@ -157,6 +171,21 @@ check_with_vfs_type (guestfs_h *g, const char *device, v = safe_strdup (g, "unknown"); free (vfs_type); } + else if (STREQ (vfs_type, "btrfs")) { + struct guestfs_btrfssubvolume_list *vols + guestfs_btrfs_subvolume_list (g, device); + + for (size_t i = 0; i < vols->len; i++) { + struct guestfs_btrfssubvolume *this = &vols->val[i]; + char *mountable = safe_asprintf (g, "btrfsvol:%s/%s", + device, this->btrfssubvolume_path); + add_vfs (g, mountable, safe_strdup (g, "btrfs"), ret, ret_size); + } + + guestfs_free_btrfssubvolume_list (vols); + + v = safe_strdup (g, "btrfs"); + } else { /* Ignore all "*_member" strings. In libblkid these are returned * for things which are members of some RAID or LVM set, most @@ -177,13 +206,7 @@ check_with_vfs_type (guestfs_h *g, const char *device, v = vfs_type; } - /* Extend the return array. */ - size_t i = *ret_size; - *ret_size += 2; - *ret = safe_realloc (g, *ret, (*ret_size + 1) * sizeof (char *)); - (*ret)[i] = safe_strdup (g, device); - (*ret)[i+1] = v; - (*ret)[i+2] = NULL; + add_vfs (g, safe_strdup (g, device), v, ret, ret_size); } /* We should ignore partitions that have MBR type byte 0x42, because -- 1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 4/7] New internal API: internal_parse_mountable
This API allows the library to parse a mountable string. This change also moves the mountable_type_t enum into mountable.h in the library, and includes it automatically for code defining GUESTFS_PRIVATE. As mountable.h is not installed, this will mean that GUESTFS_PRIVATE will not be usable outside a build tree. --- .gitignore | 2 + Makefile.am | 1 + configure.ac | 1 + daemon/Makefile.am | 21 ++-- daemon/daemon.h | 6 +- daemon/mountable.c | 60 +++++++++ generator/actions.ml | 9 ++ generator/c.ml | 2 + generator/structs.ml | 10 ++ po/POTFILES | 1 + src/MAX_PROC_NR | 2 +- src/mountable.h | 36 ++++++ tests/mountable/Makefile.am | 38 ++++++ tests/mountable/test-internal_parse_mountable.c | 156 ++++++++++++++++++++++++ 14 files changed, 328 insertions(+), 17 deletions(-) create mode 100644 daemon/mountable.c create mode 100644 src/mountable.h create mode 100644 tests/mountable/Makefile.am create mode 100644 tests/mountable/test-internal_parse_mountable.c diff --git a/.gitignore b/.gitignore index 8b88abd..5e543e9 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ Makefile.in /daemon/guestfs_protocol.h /daemon/install-sh /daemon/missing +/daemon/mountable.h /daemon/names.c /daemon/optgroups.c /daemon/optgroups.h @@ -436,6 +437,7 @@ Makefile.in /tests/guests/ubuntu.img /tests/guests/windows.img /tests/mount-local/test-parallel-mount-local +/tests/mountable/test-internal_parse_mountable /tests/parallel/test-parallel /tests/regressions/rhbz501893 /tests/regressions/rhbz790721 diff --git a/Makefile.am b/Makefile.am index 842008a..73a46f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,6 +36,7 @@ endif # Tests - order is important. if ENABLE_APPLIANCE +SUBDIRS += tests/mountable SUBDIRS += tests/qemu SUBDIRS += tests/guests SUBDIRS += tests/c-api diff --git a/configure.ac b/configure.ac index be713f6..7ee04a8 100644 --- a/configure.ac +++ b/configure.ac @@ -1546,6 +1546,7 @@ AC_CONFIG_FILES([Makefile tests/lvm/Makefile tests/md/Makefile tests/mount-local/Makefile + tests/mountable/Makefile tests/ntfsclone/Makefile tests/parallel/Makefile tests/protocol/Makefile diff --git a/daemon/Makefile.am b/daemon/Makefile.am index a1e5e68..fa5343a 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -26,26 +26,23 @@ generator_built = \ stubs.c \ names.c -BUILT_SOURCES = \ - $(generator_built) \ +shared_with_library = \ guestfs_protocol.c \ guestfs_protocol.h \ - errnostring-gperf.c \ errnostring-gperf.gperf \ errnostring.c \ - errnostring.h + errnostring.h \ + mountable.h + +BUILT_SOURCES = \ + $(generator_built) \ + $(shared_with_library) \ + errnostring-gperf.c EXTRA_DIST = \ $(BUILT_SOURCES) \ guestfsd.pod -shared_with_library = \ - guestfs_protocol.c \ - guestfs_protocol.h \ - errnostring-gperf.gperf \ - errnostring.c \ - errnostring.h - $(shared_with_library): %: $(libsrcdir)/% rm -f $@ ln $< $@ @@ -144,6 +141,8 @@ guestfsd_SOURCES = \ mktemp.c \ modprobe.c \ mount.c \ + mountable.c \ + mountable.h \ names.c \ ntfs.c \ ntfsclone.c \ diff --git a/daemon/daemon.h b/daemon/daemon.h index d343dfd..bb11fe9 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -34,11 +34,7 @@ /* Mountables */ -typedef enum { - MOUNTABLE_DEVICE, /* A bare device */ - MOUNTABLE_BTRFSVOL, /* A btrfs subvolume: device + volume */ - MOUNTABLE_PATH /* An already mounted path: device = path */ -} mountable_type_t; +#include "mountable.h" typedef struct { mountable_type_t type; diff --git a/daemon/mountable.c b/daemon/mountable.c new file mode 100644 index 0000000..170e579 --- /dev/null +++ b/daemon/mountable.c @@ -0,0 +1,60 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2009 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "daemon.h" +#include "actions.h" +#include "guestfs_protocol.h" + +guestfs_int_mountable_internal * +do_internal_parse_mountable (const mountable_t *mountable) +{ + guestfs_int_mountable_internal *ret = calloc (1, sizeof *ret); + if (ret == NULL) { + reply_with_perror ("calloc"); + return NULL; + } + + ret->type = mountable->type; + if (mountable->device) { + ret->device = strdup (mountable->device); + if (!ret->device) { + reply_with_perror ("strdup"); + free (ret); + return NULL; + } + } + + if (mountable->volume) { + ret->volume = strdup (mountable->volume); + if (!ret->volume) { + reply_with_perror ("strdup"); + free (ret->device); + free (ret); + return NULL; + } + } + + fprintf (stderr, "!!!!!!=======!!!!!!!! %i %s %s\n", ret->type, ret->device, ret->volume); + return ret; +} diff --git a/generator/actions.ml b/generator/actions.ml index f17cb6a..cd6f9c4 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -10726,6 +10726,15 @@ you are better to use C<guestfs_mv> instead." }; This returns C<true> if and only if C<device> refers to a whole block device. That is, not a partition or a logical device." }; + { defaults with + name = "internal_parse_mountable"; + style = RStruct ("ret", "mountable_internal"), [Mountable "mountable"], []; + visibility = VInternal; + proc_nr = Some 396; + shortdesc = "parse a mountable string"; + longdesc = "\ +Parse a mountable string." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/generator/c.ml b/generator/c.ml index e2ecb8a..8e8033b 100644 --- a/generator/c.ml +++ b/generator/c.ml @@ -709,6 +709,8 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private (guestfs_h *g, const char * * they are used by some of the language bindings. */ +#include \"mountable.h\" + /* Private functions. */ extern GUESTFS_DLL_PUBLIC int guestfs___for_each_disk (guestfs_h *g, /* virDomainPtr */ void *dom, int (*)(guestfs_h *g, const char *filename, const char *format, int readonly, void *data), void *data); diff --git a/generator/structs.ml b/generator/structs.ml index 82d5b7f..353d83b 100644 --- a/generator/structs.ml +++ b/generator/structs.ml @@ -360,6 +360,16 @@ let structs = [ "hivex_value_h", FInt64; ]; s_camel_name = "HivexValue" }; + { defaults with + s_name = "mountable_internal"; + s_internal = true; + s_cols = [ + "type", FInt32; + "device", FString; + "volume", FString; + ]; + s_camel_name = "MountableInternal"; + }; ] (* end of structs *) let lookup_struct name diff --git a/po/POTFILES b/po/POTFILES index 7ceb594..0686966 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -64,6 +64,7 @@ daemon/mknod.c daemon/mktemp.c daemon/modprobe.c daemon/mount.c +daemon/mountable.c daemon/names.c daemon/ntfs.c daemon/ntfsclone.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index e537bfe..4391a33 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -395 +396 diff --git a/src/mountable.h b/src/mountable.h new file mode 100644 index 0000000..f95f3c9 --- /dev/null +++ b/src/mountable.h @@ -0,0 +1,36 @@ +/* libguestfs + * + * Copyright (C) 2013 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef GUESTFS_MOUNTABLE_H_ +#define GUESTFS_MOUNTABLE_H_ + +/* The type field of a parsed mountable. + * + * This is used both by mountable_t in the daemon, and + * struct guestfs_int_mountable_internal in the library. + */ + +typedef enum { + MOUNTABLE_DEVICE, /* A bare device */ + MOUNTABLE_BTRFSVOL, /* A btrfs subvolume: device + volume */ + MOUNTABLE_PATH /* An already mounted path: device = path */ +} mountable_type_t; + +#endif /* GUESTFS_MOUNTABLE_H_ */ diff --git a/tests/mountable/Makefile.am b/tests/mountable/Makefile.am new file mode 100644 index 0000000..d50947f --- /dev/null +++ b/tests/mountable/Makefile.am @@ -0,0 +1,38 @@ +# libguestfs +# Copyright (C) 2012 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +include $(top_srcdir)/subdir-rules.mk + +TESTS_ENVIRONMENT = $(top_builddir)/run --test + +TESTS=test-internal_parse_mountable +check_PROGRAMS = test-internal_parse_mountable + +test_internal_parse_mountable_SOURCES = test-internal_parse_mountable.c +test_internal_parse_mountable_CFLAGS = \ + -DGUESTFS_WARN_DEPRECATED=1 \ + -DGUESTFS_PRIVATE=1 \ + -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ + -I$(top_srcdir)/src -I$(top_builddir)/src \ + $(WARN_CFLAGS) $(WERROR_CFLAGS) \ + $(GPROF_CFLAGS) $(GCOV_CFLAGS) +test_internal_parse_mountable_LDADD = \ + $(top_builddir)/src/libguestfs.la \ + $(top_builddir)/gnulib/lib/libgnu.la + +check-slow: + $(MAKE) TESTS="test-parallel" check diff --git a/tests/mountable/test-internal_parse_mountable.c b/tests/mountable/test-internal_parse_mountable.c new file mode 100644 index 0000000..0e7593d --- /dev/null +++ b/tests/mountable/test-internal_parse_mountable.c @@ -0,0 +1,156 @@ +/* libguestfs + * Copyright (C) 2012 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "guestfs.h" + +#define STREQ(a,b) (strcmp((a),(b)) == 0) + +#define IMG "test.img" + +int +main (int argc, char *argv[]) +{ + int fd = open (IMG, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd == -1) { + perror ("open " IMG); + exit (EXIT_FAILURE); + } + + int r = posix_fallocate (fd, 0, 1024*1024*1024); + if (r != 0) { + fprintf (stderr, "posix_fallocate " IMG " 1G: %s\n", strerror (r)); + unlink (IMG); + exit (EXIT_FAILURE); + } + + if (close (fd) == -1) { + perror ("close " IMG); + unlink (IMG); + exit (EXIT_FAILURE); + } + + guestfs_h *g = guestfs_create (); + if (g == NULL) { + fprintf (stderr, "guestfs_create: %s\n", guestfs_last_error (g)); + exit (EXIT_FAILURE); + } + + if (guestfs_add_drive_opts (g, IMG, + GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", + GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, + -1) == -1) { + fprintf (stderr, "guestfs_add_drive_opts: %s\n", guestfs_last_error (g)); + + error: + guestfs_close (g); + unlink (IMG); + exit (EXIT_FAILURE); + } + + if (guestfs_launch (g) == -1) { + fprintf (stderr, "guestfs_launch: %s\n", guestfs_last_error (g)); + goto error; + } + + if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) { + fprintf (stderr, "guestfs_part_disk: %s\n", guestfs_last_error (g)); + goto error; + } + + if (guestfs_pvcreate (g, "/dev/sda1") == -1) { + fprintf (stderr, "guestfs_pvcreate: %s\n", guestfs_last_error (g)); + goto error; + } + + const char *pvs[] = { "/dev/sda1", NULL }; + if (guestfs_vgcreate (g, "VG", (char **) pvs) == -1) { + fprintf (stderr, "guestfs_vgcreate: %s\n", guestfs_last_error (g)); + goto error; + } + + if (guestfs_lvcreate (g, "LV", "VG", 900) == -1) { + fprintf (stderr, "guestfs_lvcreate: %s\n", guestfs_last_error (g)); + goto error; + } + + const char *devices[] = { "/dev/VG/LV", NULL }; + if (guestfs_mkfs_btrfs (g, (char * const *)devices, -1) == -1) { + fprintf (stderr, "guestfs_mkfs_btrfs: %s\n", guestfs_last_error (g)); + goto error; + } + + if (guestfs_mount (g, "/dev/VG/LV", "/") == -1) { + fprintf (stderr, "guestfs_mount: %s\n", guestfs_last_error (g)); + goto error; + } + + if (guestfs_btrfs_subvolume_create (g, "/sv") == -1) { + fprintf (stderr, "guestfs_btrfs_subvolume_create: %s\n", + guestfs_last_error (g)); + goto error; + } + + #if 0 + struct guestfs_mountable_internal *mountable + guestfs_internal_parse_mountable (g, "/dev/VG/LV"); + if (mountable == NULL) { + fprintf (stderr, "guestfs_mountable_internal /dev/VG/LV: %s\n", + guestfs_last_error (g)); + goto error; + } + + if (mountable->type != MOUNTABLE_DEVICE || + !STREQ ("/dev/VG/LV", mountable->device)) + { + fprintf (stderr, "incorrectly parsed /dev/VG/LV"); + goto error; + } + + guestfs_free_mountable_internal (mountable); + #endif + + struct guestfs_mountable_internal *mountable + guestfs_internal_parse_mountable (g, "btrfsvol:/dev/VG/LV/sv"); + if (mountable == NULL) { + fprintf (stderr, "guestfs_mountable_internal /dev/VG/LV/sv: %s\n", + guestfs_last_error (g)); + goto error; + } + + if (mountable->type != MOUNTABLE_BTRFSVOL || + !STREQ ("/dev/VG/LV", mountable->device) || + !STREQ ("sv", mountable->volume)) + { + fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv"); + goto error; + } + guestfs_free_mountable_internal (mountable); + + guestfs_close (g); + unlink (IMG); + + exit (EXIT_SUCCESS); +} -- 1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 5/7] inspect: Update inspect_os to use mountables
This fixes inspection of guests which use btrfs subvolumes. --- src/guestfs-internal.h | 7 +-- src/inspect-fs-cd.c | 2 +- src/inspect-fs-unix.c | 144 +++++++++++++++++++++++++++---------------------- src/inspect-fs.c | 53 +++++++++--------- src/inspect.c | 12 ++--- 5 files changed, 118 insertions(+), 100 deletions(-) diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index bd7c802..c52b9a5 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -391,7 +391,7 @@ enum inspect_os_package_management { struct inspect_fs { int is_root; - char *device; + char *mountable; enum inspect_os_type type; enum inspect_os_distro distro; enum inspect_os_package_format package_format; @@ -414,7 +414,7 @@ struct inspect_fs { }; struct inspect_fstab_entry { - char *device; + char *mountable; char *mountpoint; }; @@ -524,7 +524,8 @@ extern struct inspect_fs *guestfs___search_for_root (guestfs_h *g, const char *r /* inspect-fs.c */ extern int guestfs___is_file_nocase (guestfs_h *g, const char *); extern int guestfs___is_dir_nocase (guestfs_h *g, const char *); -extern int guestfs___check_for_filesystem_on (guestfs_h *g, const char *device); +extern int guestfs___check_for_filesystem_on (guestfs_h *g, + const char *mountable); extern int guestfs___parse_unsigned_int (guestfs_h *g, const char *str); extern int guestfs___parse_unsigned_int_ignore_trailing (guestfs_h *g, const char *str); extern int guestfs___parse_major_minor (guestfs_h *g, struct inspect_fs *fs); diff --git a/src/inspect-fs-cd.c b/src/inspect-fs-cd.c index e4f257f..407e4f8 100644 --- a/src/inspect-fs-cd.c +++ b/src/inspect-fs-cd.c @@ -503,7 +503,7 @@ guestfs___check_installer_iso (guestfs_h *g, struct inspect_fs *fs, return 0; /* Otherwise we matched an ISO, so fill in the fs fields. */ - fs->device = safe_strdup (g, device); + fs->mountable = safe_strdup (g, device); fs->is_root = 1; fs->format = OS_FORMAT_INSTALLER; fs->type = osinfo->type; diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c index 40f797d..26c7579 100644 --- a/src/inspect-fs-unix.c +++ b/src/inspect-fs-unix.c @@ -160,8 +160,7 @@ static int check_hostname_redhat (guestfs_h *g, struct inspect_fs *fs); static int check_hostname_freebsd (guestfs_h *g, struct inspect_fs *fs); static int check_fstab (guestfs_h *g, struct inspect_fs *fs); static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs, - const char *spec, const char *mp, - Hash_table *md_map); + const char *mountable, const char *mp); static char *resolve_fstab_device (guestfs_h *g, const char *spec, Hash_table *md_map); static int inspect_with_augeas (guestfs_h *g, struct inspect_fs *fs, const char **configfiles, int (*f) (guestfs_h *, struct inspect_fs *)); @@ -870,17 +869,13 @@ check_hostname_freebsd (guestfs_h *g, struct inspect_fs *fs) static int check_fstab (guestfs_h *g, struct inspect_fs *fs) { - CLEANUP_FREE_STRING_LIST char **entries = NULL; - char **entry; - char augpath[256]; - int r; - CLEANUP_HASH_FREE Hash_table *md_map; - /* Generate a map of MD device paths listed in /etc/mdadm.conf to MD device * paths in the guestfs appliance */ + CLEANUP_HASH_FREE Hash_table *md_map = NULL; if (map_md_devices (g, &md_map) == -1) return -1; - entries = guestfs_aug_match (g, "/files/etc/fstab/*[label() != '#comment']"); + CLEANUP_FREE_STRING_LIST char **entries + guestfs_aug_match (g, "/files/etc/fstab/*[label() != '#comment']"); if (entries == NULL) return -1; @@ -889,20 +884,81 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs) return -1; } - for (entry = entries; *entry != NULL; entry++) { - snprintf (augpath, sizeof augpath, "%s/spec", *entry); - CLEANUP_FREE char *spec = guestfs_aug_get (g, augpath); - if (spec == NULL) - return -1; + for (char **entry = entries; *entry != NULL; entry++) { + char augpath[256]; snprintf (augpath, sizeof augpath, "%s/file", *entry); CLEANUP_FREE char *mp = guestfs_aug_get (g, augpath); - if (mp == NULL) - return -1; + if (mp == NULL) return -1; + + /* Ignore certain mountpoints. */ + if (STRPREFIX (mp, "/dev/") || + STREQ (mp, "/dev") || + STRPREFIX (mp, "/media/") || + STRPREFIX (mp, "/proc/") || + STREQ (mp, "/proc") || + STRPREFIX (mp, "/selinux/") || + STREQ (mp, "/selinux") || + STRPREFIX (mp, "/sys/") || + STREQ (mp, "/sys")) + continue; - r = add_fstab_entry (g, fs, spec, mp, md_map); - if (r == -1) - return -1; + snprintf (augpath, sizeof augpath, "%s/spec", *entry); + CLEANUP_FREE char *spec = guestfs_aug_get (g, augpath); + if (spec == NULL) return -1; + + /* Ignore /dev/fd (floppy disks) (RHBZ#642929) and CD-ROM drives. */ + if ((STRPREFIX (spec, "/dev/fd") && c_isdigit (spec[7])) || + STREQ (spec, "/dev/floppy") || + STREQ (spec, "/dev/cdrom")) + continue; + + /* Resolve UUID= and LABEL= to the actual device. */ + CLEANUP_FREE char *mountable = NULL; + if (STRPREFIX (spec, "UUID=")) + mountable = guestfs_findfs_uuid (g, &spec[5]); + else if (STRPREFIX (spec, "LABEL=")) + mountable = guestfs_findfs_label (g, &spec[6]); + /* Ignore "/.swap" (Pardus) and pseudo-devices like "tmpfs". */ + else if (STREQ (spec, "/dev/root")) + /* Resolve /dev/root to the current device. */ + mountable = safe_strdup (g, fs->mountable); + else if (STRPREFIX (spec, "/dev/")) + /* Resolve guest block device names. */ + mountable = resolve_fstab_device (g, spec, md_map); + + /* If we haven't resolved the device successfully by this point, + * we don't care, just ignore it. + */ + if (mountable == NULL) + continue; + + snprintf (augpath, sizeof augpath, "%s/vfstype", *entry); + CLEANUP_FREE char *vfstype = guestfs_aug_get (g, augpath); + if (vfstype == NULL) return -1; + + if (STREQ (vfstype, "btrfs")) { + snprintf (augpath, sizeof augpath, "%s/opt", *entry); + CLEANUP_FREE_STRING_LIST char **opts = guestfs_aug_match (g, augpath); + if (opts == NULL) return -1; + + for (char **opt = opts; *opt; opt++) { + CLEANUP_FREE char *optname = guestfs_aug_get (g, augpath); + if (optname == NULL) return -1; + + if (STREQ (optname, "subvol")) { + snprintf (augpath, sizeof augpath, "%s/value", *opt); + CLEANUP_FREE char *subvol = guestfs_aug_get (g, augpath); + if (subvol == NULL) return -1; + + char *new = safe_asprintf (g, "btrfsvol:%s/%s", mountable, subvol); + free (mountable); + mountable = new; + } + } + } + + if (add_fstab_entry (g, fs, mountable, mp) == -1) return -1; } return 0; @@ -918,48 +974,8 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs) */ static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs, - const char *spec, const char *mp, Hash_table *md_map) + const char *mountable, const char *mountpoint) { - /* Ignore certain mountpoints. */ - if (STRPREFIX (mp, "/dev/") || - STREQ (mp, "/dev") || - STRPREFIX (mp, "/media/") || - STRPREFIX (mp, "/proc/") || - STREQ (mp, "/proc") || - STRPREFIX (mp, "/selinux/") || - STREQ (mp, "/selinux") || - STRPREFIX (mp, "/sys/") || - STREQ (mp, "/sys")) - return 0; - - /* Ignore /dev/fd (floppy disks) (RHBZ#642929) and CD-ROM drives. */ - if ((STRPREFIX (spec, "/dev/fd") && c_isdigit (spec[7])) || - STREQ (spec, "/dev/floppy") || - STREQ (spec, "/dev/cdrom")) - return 0; - - /* Resolve UUID= and LABEL= to the actual device. */ - char *device = NULL; - if (STRPREFIX (spec, "UUID=")) - device = guestfs_findfs_uuid (g, &spec[5]); - else if (STRPREFIX (spec, "LABEL=")) - device = guestfs_findfs_label (g, &spec[6]); - /* Ignore "/.swap" (Pardus) and pseudo-devices like "tmpfs". */ - else if (STREQ (spec, "/dev/root")) - /* Resolve /dev/root to the current device. */ - device = safe_strdup (g, fs->device); - else if (STRPREFIX (spec, "/dev/")) - /* Resolve guest block device names. */ - device = resolve_fstab_device (g, spec, md_map); - - /* If we haven't resolved the device successfully by this point, - * we don't care, just ignore it. - */ - if (device == NULL) - return 0; - - char *mountpoint = safe_strdup (g, mp); - /* Add this to the fstab entry in 'fs'. * Note these are further filtered by guestfs_inspect_get_mountpoints * and guestfs_inspect_get_filesystems. @@ -970,8 +986,6 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs, p = realloc (fs->fstab, n * sizeof (struct inspect_fstab_entry)); if (p == NULL) { perrorf (g, "realloc"); - free (device); - free (mountpoint); return -1; } @@ -979,10 +993,10 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs, fs->nr_fstab = n; /* These are owned by the handle and freed by guestfs___free_inspect_info. */ - fs->fstab[n-1].device = device; - fs->fstab[n-1].mountpoint = mountpoint; + fs->fstab[n-1].mountable = safe_strdup (g, mountable); + fs->fstab[n-1].mountpoint = safe_strdup (g, mountpoint); - debug (g, "fstab: device=%s mountpoint=%s", device, mountpoint); + debug (g, "fstab: mountable=%s mountpoint=%s", mountable, mountpoint); return 0; } diff --git a/src/inspect-fs.c b/src/inspect-fs.c index be22eb0..8a88822 100644 --- a/src/inspect-fs.c +++ b/src/inspect-fs.c @@ -79,7 +79,8 @@ free_regexps (void) pcre_free (re_major_minor); } -static int check_filesystem (guestfs_h *g, const char *device, +static int check_filesystem (guestfs_h *g, const char *mountable, + const struct guestfs_mountable_internal *m, int whole_device); static int extend_fses (guestfs_h *g); @@ -87,7 +88,7 @@ static int extend_fses (guestfs_h *g); * another entry in g->fses. */ int -guestfs___check_for_filesystem_on (guestfs_h *g, const char *device) +guestfs___check_for_filesystem_on (guestfs_h *g, const char *mountable) { CLEANUP_FREE char *vfs_type = NULL; int is_swap, r; @@ -98,25 +99,31 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char *device) * temporarily replace the error handler with a null one. */ guestfs_push_error_handler (g, NULL, NULL); - vfs_type = guestfs_vfs_type (g, device); + vfs_type = guestfs_vfs_type (g, mountable); guestfs_pop_error_handler (g); is_swap = vfs_type && STREQ (vfs_type, "swap"); debug (g, "check_for_filesystem_on: %s (%s)", - device, vfs_type ? vfs_type : "failed to get vfs type"); + mountable, vfs_type ? vfs_type : "failed to get vfs type"); if (is_swap) { if (extend_fses (g) == -1) return -1; fs = &g->fses[g->nr_fses-1]; - fs->device = safe_strdup (g, device); + fs->mountable = safe_strdup (g, mountable); return 0; } + struct guestfs_mountable_internal *m + guestfs_internal_parse_mountable (g, mountable); + /* If it's a whole device, see if it is an install ISO. */ - int whole_device = guestfs_is_whole_device (g, device); - if (whole_device == -1) { - return -1; + int whole_device = 0; + if (m->type == MOUNTABLE_DEVICE) { + whole_device = guestfs_is_whole_device (g, m->device); + if (whole_device == -1) { + return -1; + } } if (whole_device) { @@ -124,7 +131,7 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char *device) return -1; fs = &g->fses[g->nr_fses-1]; - r = guestfs___check_installer_iso (g, fs, device); + r = guestfs___check_installer_iso (g, fs, m->device); if (r == -1) { /* Fatal error. */ g->nr_fses--; return -1; @@ -140,19 +147,19 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char *device) guestfs_push_error_handler (g, NULL, NULL); if (vfs_type && STREQ (vfs_type, "ufs")) { /* Hack for the *BSDs. */ /* FreeBSD fs is a variant of ufs called ufs2 ... */ - r = guestfs_mount_vfs (g, "ro,ufstype=ufs2", "ufs", device, "/"); + r = guestfs_mount_vfs (g, "ro,ufstype=ufs2", "ufs", mountable, "/"); if (r == -1) /* while NetBSD and OpenBSD use another variant labeled 44bsd */ - r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs", device, "/"); + r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs", mountable, "/"); } else { - r = guestfs_mount_ro (g, device, "/"); + r = guestfs_mount_ro (g, mountable, "/"); } guestfs_pop_error_handler (g); if (r == -1) return 0; /* Do the rest of the checks. */ - r = check_filesystem (g, device, whole_device); + r = check_filesystem (g, mountable, m, whole_device); /* Unmount the filesystem. */ if (guestfs_umount_all (g) == -1) @@ -161,28 +168,24 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char *device) return r; } -/* is_block and is_partnum are just hints: is_block is true if the - * filesystem is a whole block device (eg. /dev/sda). is_partnum - * is > 0 if the filesystem is a direct partition, and in this case - * it is the partition number counting from 1 - * (eg. /dev/sda1 => is_partnum == 1). - */ static int -check_filesystem (guestfs_h *g, const char *device, int whole_device) +check_filesystem (guestfs_h *g, const char *mountable, + const struct guestfs_mountable_internal *m, + int whole_device) { if (extend_fses (g) == -1) return -1; int partnum = -1; - if (!whole_device) { + if (!whole_device && m->type == MOUNTABLE_DEVICE) { guestfs_push_error_handler (g, NULL, NULL); - partnum = guestfs_part_to_partnum (g, device); + partnum = guestfs_part_to_partnum (g, m->device); guestfs_pop_error_handler (g); } struct inspect_fs *fs = &g->fses[g->nr_fses-1]; - fs->device = safe_strdup (g, device); + fs->mountable = safe_strdup (g, mountable); /* Optimize some of the tests by avoiding multiple tests of the same thing. */ int is_dir_etc = guestfs_is_dir (g, "/etc") > 0; @@ -203,7 +206,7 @@ check_filesystem (guestfs_h *g, const char *device, int whole_device) * that is probably /dev/sda5 (see: * http://www.freebsd.org/doc/handbook/disk-organization.html) */ - if (match (g, device, re_first_partition)) + if (m->type == MOUNTABLE_DEVICE && match (g, m->device, re_first_partition)) return 0; fs->is_root = 1; @@ -219,7 +222,7 @@ check_filesystem (guestfs_h *g, const char *device, int whole_device) * that is probably /dev/sda5 (see: * http://www.freebsd.org/doc/handbook/disk-organization.html) */ - if (match (g, device, re_first_partition)) + if (m->type == MOUNTABLE_DEVICE && match (g, m->device, re_first_partition)) return 0; fs->is_root = 1; diff --git a/src/inspect.c b/src/inspect.c index ae746cb..f031434 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -107,7 +107,7 @@ guestfs__inspect_get_roots (guestfs_h *g) count = 0; for (i = 0; i < g->nr_fses; ++i) { if (g->fses[i].is_root) { - ret[count] = safe_strdup (g, g->fses[i].device); + ret[count] = safe_strdup (g, g->fses[i].mountable); count++; } } @@ -347,7 +347,7 @@ guestfs__inspect_get_mountpoints (guestfs_h *g, const char *root) for (i = 0; i < nr; ++i) if (CRITERION (fs, i)) { ret[2*count] = safe_strdup (g, fs->fstab[i].mountpoint); - ret[2*count+1] = safe_strdup (g, fs->fstab[i].device); + ret[2*count+1] = safe_strdup (g, fs->fstab[i].mountable); count++; } #undef CRITERION @@ -379,7 +379,7 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char *root) } for (i = 0; i < nr; ++i) - ret[i] = safe_strdup (g, fs->fstab[i].device); + ret[i] = safe_strdup (g, fs->fstab[i].mountable); return ret; } @@ -485,7 +485,7 @@ guestfs___free_inspect_info (guestfs_h *g) { size_t i; for (i = 0; i < g->nr_fses; ++i) { - free (g->fses[i].device); + free (g->fses[i].mountable); free (g->fses[i].product_name); free (g->fses[i].product_variant); free (g->fses[i].arch); @@ -494,7 +494,7 @@ guestfs___free_inspect_info (guestfs_h *g) free (g->fses[i].windows_current_control_set); size_t j; for (j = 0; j < g->fses[i].nr_fstab; ++j) { - free (g->fses[i].fstab[j].device); + free (g->fses[i].fstab[j].mountable); free (g->fses[i].fstab[j].mountpoint); } free (g->fses[i].fstab); @@ -608,7 +608,7 @@ guestfs___search_for_root (guestfs_h *g, const char *root) struct inspect_fs *fs; for (i = 0; i < g->nr_fses; ++i) { fs = &g->fses[i]; - if (fs->is_root && STREQ (root, fs->device)) + if (fs->is_root && STREQ (root, fs->mountable)) return fs; } -- 1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 6/7] btrfs: Make a stub Fedora btrfs guest for inspection testing
--- .gitignore | 1 + tests/guests/Makefile.am | 5 ++ tests/guests/guest-aux/make-fedora-img.pl | 81 +++++++++++++++++++++++-------- 3 files changed, 66 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 5e543e9..0c9545b 100644 --- a/.gitignore +++ b/.gitignore @@ -429,6 +429,7 @@ Makefile.in /tests/data/test.iso /tests/guests/debian.img /tests/guests/fedora.img +/tests/guests/fedora-btrfs.img /tests/guests/fedora-md1.img /tests/guests/fedora-md2.img /tests/guests/guest-aux/fedora-name.db diff --git a/tests/guests/Makefile.am b/tests/guests/Makefile.am index 347aef5..d2291c5 100644 --- a/tests/guests/Makefile.am +++ b/tests/guests/Makefile.am @@ -58,6 +58,11 @@ stamp-fedora-md.img: guest-aux/make-fedora-img.pl \ SRCDIR=$(srcdir) LAYOUT=partitions-md $(top_builddir)/run --test $< touch $@ +fedora-btrfs.img: guest-aux/make-fedora-img.pl \ + guest-aux/fedora-name.db \ + guest-aux/fedora-packages.db + SRCDIR=$(srcdir) LAYOUT=btrfs $(top_builddir)/run --test $< + guest-aux/fedora-name.db: guest-aux/fedora-name.db.txt rm -f $@ $@-t mkdir -p guest-aux diff --git a/tests/guests/guest-aux/make-fedora-img.pl b/tests/guests/guest-aux/make-fedora-img.pl index 3272d4c..1875602 100755 --- a/tests/guests/guest-aux/make-fedora-img.pl +++ b/tests/guests/guest-aux/make-fedora-img.pl @@ -31,7 +31,6 @@ my @images; my $g = Sys::Guestfs->new (); my $bootdev; -my $rootdev; foreach ('LAYOUT', 'SRCDIR') { defined ($ENV{$_}) or die "Missing environment variable: $_"; @@ -48,7 +47,6 @@ EOF close ($fstab) or die; $bootdev = '/dev/sda1'; - $rootdev = '/dev/sda2'; open (my $img, '>', "fedora.img.tmp.$$") or die; truncate ($img, 512*1024*1024) or die; @@ -60,6 +58,8 @@ EOF $g->part_init ('/dev/sda', 'mbr'); $g->part_add ('/dev/sda', 'p', 64, 524287); $g->part_add ('/dev/sda', 'p', 524288, -64); + + init_lvm_root ('/dev/sda2'); } elsif ($ENV{LAYOUT} eq 'partitions-md') { @@ -73,7 +73,6 @@ EOF close ($fstab) or die; $bootdev = '/dev/md/boot'; - $rootdev = '/dev/md/root'; foreach my $img (@images) { open (my $fh, '>', $img) or die; @@ -110,6 +109,41 @@ EOF } close ($mdadm) or die; + + init_lvm_root ('/dev/md/root'); +} + +elsif ($ENV{LAYOUT} eq 'btrfs') { + push (@images, "fedora-btrfs.img.tmp.$$"); + + open (my $fstab, '>', "fstab.tmp.$$") or die; + print $fstab <<EOF; +LABEL=BOOT /boot ext2 default 0 0 +LABEL=ROOT / btrfs subvol=root 0 0 +LABEL=ROOT /home btrfs subvol=home 0 0 +EOF + close ($fstab) or die; + + $bootdev = '/dev/sda1'; + + open (my $img, '>', "fedora-btrfs.img.tmp.$$") or die; + truncate ($img, 512*1024*1024) or die; + close ($img) or die; + + $g->add_drive ("fedora-btrfs.img.tmp.$$"); + $g->launch (); + + $g->part_init ('/dev/sda', 'mbr'); + $g->part_add ('/dev/sda', 'p', 64, 524287); + $g->part_add ('/dev/sda', 'p', 524288, -64); + + $g->mkfs_btrfs (['/dev/sda2'], label => 'ROOT'); + $g->mount ('/dev/sda2', '/'); + $g->btrfs_subvolume_create ('/root'); + $g->btrfs_subvolume_create ('/home'); + $g->umount ('/'); + + $g->mount ('btrfsvol:/dev/sda2/root', '/'); } else { @@ -117,25 +151,36 @@ else { exit 1; } -$g->pvcreate ($rootdev); -$g->vgcreate ('VG', [$rootdev]); -$g->lvcreate ('Root', 'VG', 32); -$g->lvcreate ('LV1', 'VG', 32); -$g->lvcreate ('LV2', 'VG', 32); -$g->lvcreate ('LV3', 'VG', 64); +sub init_lvm_root { + my ($rootdev) = @_; + + $g->pvcreate ($rootdev); + $g->vgcreate ('VG', [$rootdev]); + $g->lvcreate ('Root', 'VG', 32); + $g->lvcreate ('LV1', 'VG', 32); + $g->lvcreate ('LV2', 'VG', 32); + $g->lvcreate ('LV3', 'VG', 64); + + # Phony root filesystem. + $g->mkfs ('ext2', '/dev/VG/Root', blocksize => 4096); + $g->set_label ('/dev/VG/Root', 'ROOT'); + $g->set_e2uuid ('/dev/VG/Root', '01234567-0123-0123-0123-012345678902'); + + # Other filesystems. + # Note that these should be empty, for testing virt-df. + $g->mkfs ('ext2', '/dev/VG/LV1', blocksize => 4096); + $g->mkfs ('ext2', '/dev/VG/LV2', blocksize => 1024); + $g->mkfs ('ext2', '/dev/VG/LV3', blocksize => 2048); + + $g->mount ('/dev/VG/Root', '/'); +} # Phony /boot filesystem $g->mkfs ('ext2', $bootdev, blocksize => 4096); $g->set_label ($bootdev, 'BOOT'); $g->set_e2uuid ($bootdev, '01234567-0123-0123-0123-012345678901'); -# Phony root filesystem. -$g->mkfs ('ext2', '/dev/VG/Root', blocksize => 4096); -$g->set_label ('/dev/VG/Root', 'ROOT'); -$g->set_e2uuid ('/dev/VG/Root', '01234567-0123-0123-0123-012345678902'); - # Enough to fool inspection API. -$g->mount ('/dev/VG/Root', '/'); $g->mkdir ('/boot'); $g->mount ($bootdev, '/boot'); $g->mkdir ('/bin'); @@ -188,12 +233,6 @@ $g->ln_s ('/bin/test1', '/bin/test5'); $g->mkfifo (0777, '/bin/test6'); $g->mknod (0777, 10, 10, '/bin/test7'); -# Other filesystems. -# Note that these should be empty, for testing virt-df. -$g->mkfs ('ext2', '/dev/VG/LV1', blocksize => 4096); -$g->mkfs ('ext2', '/dev/VG/LV2', blocksize => 1024); -$g->mkfs ('ext2', '/dev/VG/LV3', blocksize => 2048); - # Cleanup $g->shutdown (); $g->close (); -- 1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 7/7] mountable: Test inspection of fedora image
--- tests/mountable/Makefile.am | 2 +- tests/mountable/test-inspect.sh | 57 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100755 tests/mountable/test-inspect.sh diff --git a/tests/mountable/Makefile.am b/tests/mountable/Makefile.am index d50947f..f4b6e01 100644 --- a/tests/mountable/Makefile.am +++ b/tests/mountable/Makefile.am @@ -19,7 +19,7 @@ include $(top_srcdir)/subdir-rules.mk TESTS_ENVIRONMENT = $(top_builddir)/run --test -TESTS=test-internal_parse_mountable +TESTS=test-internal_parse_mountable test-inspect.sh check_PROGRAMS = test-internal_parse_mountable test_internal_parse_mountable_SOURCES = test-internal_parse_mountable.c diff --git a/tests/mountable/test-inspect.sh b/tests/mountable/test-inspect.sh new file mode 100755 index 0000000..2ad3c1b --- /dev/null +++ b/tests/mountable/test-inspect.sh @@ -0,0 +1,57 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2013 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +set -e +export LANG=C + +guestfish=../../fish/guestfish +canonical="sed s,/dev/vd,/dev/sd,g" + +rm -f test.qcow2 test.output + +# Start with the regular (good) fedora image, modify /etc/fstab +# and then inspect it. +qemu-img create -F raw -b ../guests/fedora-btrfs.img -f qcow2 test.qcow2 + +# Test that basic inspection works and the expected filesystems are +# found +$guestfish -a test.qcow2 -i <<'EOF' | sort | $canonical > test.output + inspect-get-mountpoints btrfsvol:/dev/sda2/root +EOF + +if [ "$(cat test.output)" != "/: btrfsvol:/dev/sda2/root +/boot: /dev/sda1 +/home: btrfsvol:/dev/sda2/home" ]; then + echo "$0: error #1: unexpected output from inspect-get-mountpoints" + cat test.output + exit 1 +fi + +# Additional sanity check: did we get the release name right? +$guestfish -a test.qcow2 -i <<'EOF' > test.output + inspect-get-product-name btrfsvol:/dev/sda2/root +EOF + +if [ "$(cat test.output)" != "Fedora release 14 (Phony)"]; then + echo "$0: error #2: unexpected output from inspect-get-product-name" + cat test.output + exit 1 +fi + +rm test.qcow2 +rm test.output -- 1.8.1.2
Seemingly Similar Threads
- [PATCH 01/12] generator: Add new Mountable argument type
- [PATCH v10 00/10] Reimplement inspection in the daemon.
- [PATCH v9 00/11] Reimplement inspection in the daemon.
- [PATCH v12 00/11] Reimplement inspection in the daemon.
- [PATCH v11 00/10] Reimplement inspection in the daemon.