inspect: Add drive naming hints

We currently use a heuristic to guess how drive names we find
referenced in the guest map to drive names in the appliance. If this
heuristic fails it can cause inspection to fail.

This change adds a new 'name' option to add_drive_opts, which allows
the user to explicitly pass the name of a drive to libguestfs if it is
known. This change also updates the fstab-parsing inspection code to
use this information if it is available.
This commit is contained in:
Matthew Booth
2011-10-18 11:01:01 +01:00
committed by Richard W.M. Jones
parent 1f615fddaf
commit a1df33eac2
6 changed files with 86 additions and 26 deletions

View File

@@ -1007,7 +1007,7 @@ be mountable but require special options. Filesystems may
not all belong to a single logical operating system
(use C<guestfs_inspect_os> to look for OSes).");
("add_drive_opts", (RErr, [String "filename"], [Bool "readonly"; String "format"; String "iface"]), -1, [FishAlias "add"],
("add_drive_opts", (RErr, [String "filename"], [Bool "readonly"; String "format"; String "iface"; String "name"]), -1, [FishAlias "add"],
[],
"add an image to examine or modify",
"\
@@ -1050,6 +1050,11 @@ this security hole.
This rarely-used option lets you emulate the behaviour of the
deprecated C<guestfs_add_drive_with_if> call (q.v.)
=item C<name>
The name the drive had in the original guest, e.g. /dev/sdb. This is used as a
hint to the guest inspection process if it is available.
=back");
("inspect_get_windows_systemroot", (RString "systemroot", [Device "root"], []), -1, [],

View File

@@ -49,15 +49,11 @@ $guestfish -a test1.img <<'EOF'
upload test.fstab /etc/fstab
EOF
rm test.fstab
# This will give a warning, but should not fail.
$guestfish -a test1.img -i <<'EOF' | sort > test.output
inspect-get-mountpoints /dev/VG/Root
EOF
rm test1.img
if [ "$(cat test.output)" != "/: /dev/VG/Root
/boot: /dev/vda1
/nosuchfile: /dev/VG/LV1
@@ -67,4 +63,36 @@ if [ "$(cat test.output)" != "/: /dev/VG/Root
exit 1
fi
# Test device name hints
cat <<'EOF' > test.fstab
/dev/VG/Root / ext2 default 0 0
# Device name which requires a hint
/dev/xvdg1 /boot ext2 default 0 0
EOF
$guestfish -a test1.img <<'EOF'
run
mount-options "" /dev/VG/Root /
upload test.fstab /etc/fstab
EOF
$guestfish <<'EOF' > test.output
add-drive-opts test1.img readonly:true name:xvdg
run
inspect-os
inspect-get-mountpoints /dev/VG/Root
EOF
if [ "$(cat test.output)" != "/dev/VG/Root
/: /dev/VG/Root
/boot: /dev/vda1" ]; then
echo "$0: error: unexpected output from inspect-get-mountpoints command"
cat test.output
exit 1
fi
rm test.fstab
rm test1.img
rm test.output

View File

@@ -158,6 +158,7 @@ struct drive {
int readonly;
char *format;
char *iface;
char *name;
int use_cache_off;
};

View File

@@ -1008,6 +1008,7 @@ guestfs___free_drives (struct drive **drives)
free (i->path);
free (i->format);
free (i->iface);
free (i->name);
free (i);
i = next;

View File

@@ -107,7 +107,7 @@ compile_regexps (void)
"Scientific Linux.*release (\\d+)", 0);
COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0);
COMPILE (re_aug_seq, "/\\d+$", 0);
COMPILE (re_xdev, "^/dev/(?:h|s|v|xv)d([a-z]+)(\\d*)$", 0);
COMPILE (re_xdev, "^/dev/(h|s|v|xv)d([a-z]+)(\\d*)$", 0);
COMPILE (re_freebsd, "^/dev/ad(\\d+)s(\\d+)([a-z])$", 0);
COMPILE (re_netbsd, "^NetBSD (\\d+)\\.(\\d+)", 0);
}
@@ -817,7 +817,7 @@ static char *
resolve_fstab_device (guestfs_h *g, const char *spec)
{
char *device = NULL;
char *slice, *disk, *part;
char *type, *slice, *disk, *part;
if (STRPREFIX (spec, "/dev/mapper/")) {
/* LVM2 does some strange munging on /dev/mapper paths for VGs and
@@ -832,33 +832,50 @@ resolve_fstab_device (guestfs_h *g, const char *spec)
*/
device = guestfs_lvm_canonical_lv_name (g, spec);
}
else if (match2 (g, spec, re_xdev, &disk, &part)) {
/* disk: ([a-z]+)
else if (match3 (g, spec, re_xdev, &type, &disk, &part)) {
/* type: (h|s|v|xv)
* disk: ([a-z]+)
* part: (\d*) */
char **devices = guestfs_list_devices (g);
if (devices == NULL)
return NULL;
/* Count how many disks the libguestfs appliance has */
size_t count;
for (count = 0; devices[count] != NULL; count++)
;
/* Check any hints we were passed for a non-heuristic mapping */
char *name = safe_asprintf (g, "%sd%s", type, disk);
size_t i = 0;
struct drive *drive = g->drives;
while (drive) {
if (drive->name && STREQ(drive->name, name)) {
device = safe_asprintf (g, "%s%s", devices[i], part);
break;
}
/* Calculate the numerical index of the disk */
size_t i = disk[0] - 'a';
for (char *p = disk + 1; *p != '\0'; p++) {
i += 1; i *= 26;
i += *p - 'a';
}
/* Check the index makes sense wrt the number of disks the appliance has.
* If it does, map it to an appliance disk. */
if (i < count) {
size_t len = strlen (devices[i]) + strlen (part) + 1;
device = safe_malloc (g, len);
snprintf (device, len, "%s%s", devices[i], part);
i++; drive = drive->next;
}
free (name);
/* Guess the appliance device name if we didn't find a matching hint */
if (!device) {
/* Count how many disks the libguestfs appliance has */
size_t count;
for (count = 0; devices[count] != NULL; count++)
;
/* Calculate the numerical index of the disk */
i = disk[0] - 'a';
for (char *p = disk + 1; *p != '\0'; p++) {
i += 1; i *= 26;
i += *p - 'a';
}
/* Check the index makes sense wrt the number of disks the appliance has.
* If it does, map it to an appliance disk. */
if (i < count) {
device = safe_asprintf (g, "%s%s", devices[i], part);
}
}
free (type);
free (disk);
free (part);
guestfs___free_string_list (devices);

View File

@@ -289,6 +289,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
int readonly;
char *format;
char *iface;
char *name;
int use_cache_off;
if (strchr (filename, ',') != NULL) {
@@ -302,12 +303,15 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
? safe_strdup (g, optargs->format) : NULL;
iface = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_IFACE_BITMASK
? safe_strdup (g, optargs->iface) : safe_strdup (g, DRIVE_IF);
name = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_NAME_BITMASK
? safe_strdup (g, optargs->name) : NULL;
if (format && !valid_format_iface (format)) {
error (g, _("%s parameter is empty or contains disallowed characters"),
"format");
free (format);
free (iface);
free (name);
return -1;
}
if (!valid_format_iface (iface)) {
@@ -315,6 +319,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
"iface");
free (format);
free (iface);
free (name);
return -1;
}
@@ -326,6 +331,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
if (use_cache_off == -1) {
free (format);
free (iface);
free (name);
return -1;
}
@@ -334,6 +340,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
perrorf (g, "%s", filename);
free (format);
free (iface);
free (name);
return -1;
}
}
@@ -347,6 +354,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
(*i)->readonly = readonly;
(*i)->format = format;
(*i)->iface = iface;
(*i)->name = name;
(*i)->use_cache_off = use_cache_off;
return 0;