Matthew Booth
2009-Aug-13 11:21 UTC
[Libguestfs] [PATCH] Don't assume grub is on a separate boot filesystem
Paths in grub.conf are relative to the filesystem containing it. grub parsing
currently assumes that it is on /boot, and will fail if it isn't, for
example
because a guest only has a single partition.
This patch makes grub parsing work harder to work out what grub paths are
relative to. Firstly, it looks for a previous detected 'linux-grub'
filesystem.
If this isn't found, it tries to work out which filesystem contains
/boot/grub/menu.lst and uses that.
---
perl/lib/Sys/Guestfs/Lib.pm | 56 +++++++++++++++++++++++++++++++++++++++++-
1 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm
index 72b0f7d..89f2aa6 100644
--- a/perl/lib/Sys/Guestfs/Lib.pm
+++ b/perl/lib/Sys/Guestfs/Lib.pm
@@ -1435,6 +1435,56 @@ sub _check_for_applications
$os->{apps} = \@apps;
}
+# Find the path which needs to be prepended to paths in grub.conf to make them
+# absolute
+sub _find_grub_prefix
+{
+ my ($g, $os) = @_;
+
+ my $fses = $os->{filesystems};
+ die("filesystems undefined") unless(defined($fses));
+
+ # Look for the filesystem which contains grub
+ my $grubdev;
+ foreach my $dev (keys(%$fses)) {
+ my $fsinfo = $fses->{$dev};
+ if(exists($fsinfo->{content}) && $fsinfo->{content} eq
"linux-grub") {
+ $grubdev = $dev;
+ last;
+ }
+ }
+
+ my $mounts = $os->{mounts};
+ die("mounts undefined") unless(defined($mounts));
+
+ # Find where the filesystem is mounted
+ if(defined($grubdev)) {
+ foreach my $mount (keys(%$mounts)) {
+ if($mounts->{$mount} eq $grubdev) {
+ return "" if($mount eq '/');
+ return $mount;
+ }
+ }
+
+ die("$grubdev defined in filesystems, but not in mounts");
+ }
+
+ # If we didn't find it, look for /boot/grub/menu.lst, then try to work
out
+ # what filesystem it's on. We use menu.lst rather than grub.conf
because
+ # debian only uses menu.lst, and anaconda creates a symlink for it.
+ die(__"Can't find grub on guest")
unless($g->exists('/boot/grub/menu.lst'));
+
+ # Look for the most specific mount point in mounts
+ foreach my $path qw(/boot/grub /boot /) {
+ if(exists($mounts->{$path})) {
+ return "" if($path eq '/');
+ return $path;
+ }
+ }
+
+ die("Couldn't determine which filesystem holds
/boot/grub/menu.lst");
+}
+
sub _check_for_kernels
{
my ($g, $os) = @_;
@@ -1443,6 +1493,8 @@ sub _check_for_kernels
# Iterate over entries in grub.conf, populating $os->{boot}
# For every kernel we find, inspect it and add to $os->{kernels}
+ my $grub = _find_grub_prefix($g, $os);
+
my @boot_configs;
# We want
@@ -1474,7 +1526,7 @@ sub _check_for_kernels
# Check we've got a kernel entry
if(defined($grub_kernel)) {
- my $path = "/boot$grub_kernel";
+ my $path = "$grub$grub_kernel";
# Reconstruct the kernel command line
my @args = ();
@@ -1508,7 +1560,7 @@ sub _check_for_kernels
unless($@) {
$config{initrd} -
_inspect_initrd($g, $os, "/boot$initrd",
+ _inspect_initrd($g, $os, "$grub$initrd",
$kernel->{version});
} else {
warn __x("Grub entry {title} does not specify an
".
--
1.6.2.5
Richard W.M. Jones
2009-Aug-13 11:39 UTC
[Libguestfs] [PATCH] Don't assume grub is on a separate boot filesystem
On Thu, Aug 13, 2009 at 12:21:16PM +0100, Matthew Booth wrote:> Paths in grub.conf are relative to the filesystem containing it. grub parsing > currently assumes that it is on /boot, and will fail if it isn't, for example > because a guest only has a single partition. > > This patch makes grub parsing work harder to work out what grub paths are > relative to. Firstly, it looks for a previous detected 'linux-grub' filesystem. > If this isn't found, it tries to work out which filesystem contains > /boot/grub/menu.lst and uses that. > --- > perl/lib/Sys/Guestfs/Lib.pm | 56 +++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 54 insertions(+), 2 deletions(-) > > diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm > index 72b0f7d..89f2aa6 100644 > --- a/perl/lib/Sys/Guestfs/Lib.pm > +++ b/perl/lib/Sys/Guestfs/Lib.pm > @@ -1435,6 +1435,56 @@ sub _check_for_applications > $os->{apps} = \@apps; > } > > +# Find the path which needs to be prepended to paths in grub.conf to make them > +# absolute > +sub _find_grub_prefix > +{ > + my ($g, $os) = @_; > + > + my $fses = $os->{filesystems}; > + die("filesystems undefined") unless(defined($fses)); > + > + # Look for the filesystem which contains grub > + my $grubdev; > + foreach my $dev (keys(%$fses)) { > + my $fsinfo = $fses->{$dev}; > + if(exists($fsinfo->{content}) && $fsinfo->{content} eq "linux-grub") { > + $grubdev = $dev; > + last; > + } > + } > + > + my $mounts = $os->{mounts}; > + die("mounts undefined") unless(defined($mounts)); > + > + # Find where the filesystem is mounted > + if(defined($grubdev)) { > + foreach my $mount (keys(%$mounts)) { > + if($mounts->{$mount} eq $grubdev) { > + return "" if($mount eq '/'); > + return $mount; > + } > + } > + > + die("$grubdev defined in filesystems, but not in mounts"); > + } > + > + # If we didn't find it, look for /boot/grub/menu.lst, then try to work out > + # what filesystem it's on. We use menu.lst rather than grub.conf because > + # debian only uses menu.lst, and anaconda creates a symlink for it. > + die(__"Can't find grub on guest") unless($g->exists('/boot/grub/menu.lst')); > + > + # Look for the most specific mount point in mounts > + foreach my $path qw(/boot/grub /boot /) { > + if(exists($mounts->{$path})) { > + return "" if($path eq '/'); > + return $path; > + } > + } > + > + die("Couldn't determine which filesystem holds /boot/grub/menu.lst"); > +} > + > sub _check_for_kernels > { > my ($g, $os) = @_; > @@ -1443,6 +1493,8 @@ sub _check_for_kernels > # Iterate over entries in grub.conf, populating $os->{boot} > # For every kernel we find, inspect it and add to $os->{kernels} > > + my $grub = _find_grub_prefix($g, $os); > + > my @boot_configs; > > # We want > @@ -1474,7 +1526,7 @@ sub _check_for_kernels > > # Check we've got a kernel entry > if(defined($grub_kernel)) { > - my $path = "/boot$grub_kernel"; > + my $path = "$grub$grub_kernel"; > > # Reconstruct the kernel command line > my @args = (); > @@ -1508,7 +1560,7 @@ sub _check_for_kernels > > unless($@) { > $config{initrd} > - _inspect_initrd($g, $os, "/boot$initrd", > + _inspect_initrd($g, $os, "$grub$initrd", > $kernel->{version}); > } else { > warn __x("Grub entry {title} does not specify an ". > -- > 1.6.2.5 > > _______________________________________________ > Libguestfs mailing list > Libguestfs at redhat.com > https://www.redhat.com/mailman/listinfo/libguestfsCan't see any problem with that, ACK. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/