Rely on new augeas lens for modules.conf and conf.modules
[libguestfs.git] / perl / lib / Sys / Guestfs / Lib.pm
index 5428b10..128f7c9 100644 (file)
@@ -1,5 +1,5 @@
 # Sys::Guestfs::Lib
-# Copyright (C) 2009 Red Hat Inc.
+# Copyright (C) 2009-2010 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
@@ -20,6 +20,13 @@ package Sys::Guestfs::Lib;
 use strict;
 use warnings;
 
+# The minor part of this version number is incremented when some
+# change is made to this module.  The major part is incremented if we
+# make a change which is not backwards compatible.  It is not related
+# to the libguestfs version number.
+use vars qw($VERSION);
+$VERSION = '0.2';
+
 use Carp qw(croak);
 
 use Sys::Guestfs;
@@ -260,16 +267,27 @@ This function takes an open libguestfs handle C<$g> and returns all
 partitions and logical volumes found on it.
 
 What is returned is everything that could contain a filesystem (or
-swap).  Physical volumes are excluded from the list, and so are any
-devices which are partitioned (eg. C</dev/sda> would not be returned
-if C</dev/sda1> exists).
+swap).  Physical volumes are not normally included from the list
+except if they contain a filesystem directly.  Nor are devices which
+are partitioned (eg. C</dev/sda> would not be returned if C</dev/sda1>
+exists).
 
 =cut
 
 sub get_partitions
 {
+    local $_;
     my $g = shift;
 
+    # Look to see if any devices directly contain filesystems (RHBZ#590167).
+    my @devices = $g->list_devices ();
+    my @fses_on_device = ();
+    foreach (@devices) {
+        eval { $g->mount_ro ($_, "/"); };
+        push @fses_on_device, $_ unless $@;
+        $g->umount_all ();
+    }
+
     my @partitions = $g->list_partitions ();
     my @pvs = $g->pvs ();
     @partitions = grep { ! _is_pv ($_, @pvs) } @partitions;
@@ -277,7 +295,7 @@ sub get_partitions
     my @lvs;
     @lvs = $g->lvs () if feature_available ($g, "lvm2");
 
-    return sort (@lvs, @partitions);
+    return sort (@fses_on_device, @lvs, @partitions);
 }
 
 sub _is_pv {
@@ -1101,7 +1119,8 @@ like:
    '/dev/VG/Root' => \%os,
  }
 
-(There can be multiple roots for a multi-boot VM).
+There can be multiple roots for a multi-boot VM, but this function
+will throw an error if no roots (ie. OSes) could be found.
 
 The C<\%os> hash contains the following keys (any can be omitted):
 
@@ -1184,6 +1203,11 @@ sub inspect_operating_systems
         }
     }
 
+    # If we didn't find any operating systems then it's an error (RHBZ#591142).
+    if (0 == keys %oses) {
+        die __"No operating system could be detected inside this disk image.\n\nThis may be because the file is not a disk image, or is not a virtual machine\nimage, or because the OS type is not understood by virt-inspector.\n\nIf you feel this is an error, please file a bug report including as much\ninformation about the disk image as possible.\n";
+    }
+
     return \%oses;
 }
 
@@ -1463,10 +1487,16 @@ sub _check_for_applications
     if ($osn eq "linux") {
         my $package_format = $os->{package_format};
         if (defined $package_format && $package_format eq "rpm") {
-            my @lines = $g->command_lines
-                (["rpm",
-                  "-q", "-a",
-                  "--qf", "%{name} %{epoch} %{version} %{release} %{arch}\n"]);
+            my @lines = ();
+            eval {
+                @lines = $g->command_lines
+                    (["rpm",
+                      "-q", "-a", "--qf",
+                      "%{name} %{epoch} %{version} %{release} %{arch}\n"]);
+            };
+
+            warn(__x("Error running rpm -qa: {error}", error => $@)) if ($@);
+
             @lines = sort @lines;
             foreach (@lines) {
                 if (m/^(.*) (.*) (.*) (.*) (.*)$/) {
@@ -1483,10 +1513,16 @@ sub _check_for_applications
                 }
             }
         } elsif (defined $package_format && $package_format eq "deb") {
-            my @lines = $g->command_lines
-                (["dpkg-query",
-                  "-f", '${Package} ${Version} ${Architecture} ${Status}\n',
-                  "-W"]);
+            my @lines = ();
+            eval {
+                @lines = $g->command_lines
+                    (["dpkg-query",
+                      "-f", '${Package} ${Version} ${Architecture} ${Status}\n',
+                      "-W"]);
+            };
+
+            warn(__x("Error running dpkg-query: {error}", error => $@)) if ($@);
+
             @lines = sort @lines;
             foreach (@lines) {
                 if (m/^(.*) (.*) (.*) (.*) (.*) (.*)$/) {
@@ -1631,8 +1667,14 @@ sub _check_for_kernels
                 }
                 $config{cmdline} = join(' ', @args) if(scalar(@args) > 0);
 
-                my $kernel =
-                    inspect_linux_kernel($g, $path, $os->{package_format});
+                my $kernel;
+                if ($g->exists($path)) {
+                    $kernel =
+                        inspect_linux_kernel($g, $path, $os->{package_format});
+                } else {
+                    warn __x("grub refers to {path}, which doesn't exist\n",
+                             path => $path);
+                }
 
                 # Check the kernel was recognised
                 if(defined($kernel)) {
@@ -1778,13 +1820,6 @@ sub _find_modprobe_aliases
     # Initialise augeas
     $g->aug_init("/", 16);
 
-    # Register additional paths to the Modprobe lens
-    $g->aug_set("/augeas/load/Modprobe/incl[last()+1]", "/etc/modules.conf");
-    $g->aug_set("/augeas/load/Modprobe/incl[last()+1]", "/etc/conf.modules");
-
-    # Make augeas reload
-    $g->aug_load();
-
     my %modprobe_aliases;
 
     for my $pattern qw(/files/etc/conf.modules/alias
@@ -1825,7 +1860,7 @@ sub _inspect_initrd
     # Disregard old-style compressed ext2 files and only work with real
     # compressed cpio files, since cpio takes ages to (fail to) process anything
     # else.
-    if ($g->file ($path) =~ /cpio/) {
+    if ($g->exists($path) && $g->file($path) =~ /cpio/) {
         eval {
             @modules = $g->initrd_list ($path);
         };