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/