2 # Copyright (C) 2009 Red Hat Inc.
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 package Sys::Guestfs::Lib;
26 eval "use Sys::Virt;";
27 eval "use XML::XPath;";
28 eval "use XML::XPath::XMLParser;";
34 Sys::Guestfs::Lib - Useful functions for using libguestfs from Perl
38 use Sys::Guestfs::Lib qw(#any symbols you want to use);
40 $g = open_guest ($name);
44 C<Sys::Guestfs::Lib> is an extra library of useful functions for using
45 the libguestfs API from Perl. It also provides tighter integration
48 The basic libguestfs API is not covered by this manpage. Please refer
49 instead to L<Sys::Guestfs(3)> and L<guestfs(3)>. The libvirt API is
50 also not covered. For that, see L<Sys::Virt(3)>.
52 =head1 BASIC FUNCTIONS
58 use vars qw(@EXPORT_OK @ISA);
61 @EXPORT_OK = qw(open_guest get_partitions resolve_windows_path
62 inspect_all_partitions inspect_partition
63 inspect_operating_systems mount_operating_system inspect_in_detail);
67 $g = open_guest ($name);
69 $g = open_guest ($name, rw => 1, ...);
71 $g = open_guest ($name, address => $uri, ...);
73 $g = open_guest ([$img1, $img2, ...], address => $uri, ...);
75 ($g, $conn, $dom) = open_guest ($name);
77 This function opens a libguestfs handle for either the libvirt domain
78 called C<$name>, or the disk image called C<$name>. Any disk images
79 found through libvirt or specified explicitly are attached to the
82 The C<Sys::Guestfs> handle C<$g> is returned, or if there was an error
83 it throws an exception. To catch errors, wrap the call in an eval
86 The first parameter is either a string referring to a libvirt domain
87 or a disk image, or (if a guest has several disk images) an arrayref
88 C<[$img1, $img2, ...]>.
90 The handle is I<read-only> by default. Use the optional parameter
91 C<rw =E<gt> 1> to open a read-write handle. However if you open a
92 read-write handle, this function will refuse to use active libvirt
95 The handle is still in the config state when it is returned, so you
96 have to call C<$g-E<gt>launch ()> and C<$g-E<gt>wait_ready>.
98 The optional C<address> parameter can be added to specify the libvirt
99 URI. In addition, L<Sys::Virt(3)> lists other parameters which are
100 passed through to C<Sys::Virt-E<gt>new> unchanged.
102 The implicit libvirt handle is closed after this function, I<unless>
103 you call the function in C<wantarray> context, in which case the
104 function returns a tuple of: the open libguestfs handle, the open
105 libvirt handle, and the open libvirt domain handle. (This is useful
106 if you want to do other things like pulling the XML description of the
107 guest). Note that if this is a straight disk image, then C<$conn> and
108 C<$dom> will be C<undef>.
110 If the C<Sys::Virt> module is not available, then libvirt is bypassed,
111 and this function can only open disk images.
120 my $readwrite = $params{rw};
123 if (ref ($first) eq "ARRAY") {
125 } elsif (ref ($first) eq "SCALAR") {
128 die "open_guest: first parameter must be a string or an arrayref"
135 die "guest image $_ does not exist or is not readable"
139 die "open_guest: no libvirt support (install Sys::Virt, XML::XPath and XML::XPath::XMLParser)"
140 unless exists $INC{"Sys/Virt.pm"} &&
141 exists $INC{"XML/XPath.pm"} &&
142 exists $INC{"XML/XPath/XMLParser.pm"};
144 die "open_guest: too many domains listed on command line"
147 $conn = Sys::Virt->new (readonly => 1, @_);
148 die "open_guest: cannot connect to libvirt" unless $conn;
150 my @doms = $conn->list_defined_domains ();
151 my $isitinactive = "an inactive libvirt domain";
152 unless ($readwrite) {
153 # In the case where we want read-only access to a domain,
154 # allow the user to specify an active domain too.
155 push @doms, $conn->list_domains ();
156 $isitinactive = "a libvirt domain";
159 if ($_->get_name () eq $images[0]) {
164 die "$images[0] is not the name of $isitinactive\n" unless $dom;
166 # Get the names of the image(s).
167 my $xml = $dom->get_xml_description ();
169 my $p = XML::XPath->new (xml => $xml);
170 my @disks = $p->findnodes ('//devices/disk/source/@dev');
171 @images = map { $_->getData } @disks;
174 # We've now got the list of @images, so feed them to libguestfs.
175 my $g = Sys::Guestfs->new ();
180 $g->add_drive_ro ($_);
184 return wantarray ? ($g, $conn, $dom) : $g
187 =head2 get_partitions
189 @partitions = get_partitions ($g);
191 This function takes an open libguestfs handle C<$g> and returns all
192 partitions and logical volumes found on it.
194 What is returned is everything that could contain a filesystem (or
195 swap). Physical volumes are excluded from the list, and so are any
196 devices which are partitioned (eg. C</dev/sda> would not be returned
197 if C</dev/sda1> exists).
205 my @partitions = $g->list_partitions ();
206 my @pvs = $g->pvs ();
207 @partitions = grep { ! is_pv ($_, @pvs) } @partitions;
209 my @lvs = $g->lvs ();
211 return sort (@lvs, @partitions);
219 return 1 if $_ eq $t;
224 =head2 resolve_windows_path
226 $path = resolve_windows_path ($g, $path);
228 $path = resolve_windows_path ($g, "/windows/system");
229 ==> "/WINDOWS/System"
230 or undef if no path exists
232 This function, which is specific to FAT/NTFS filesystems (ie. Windows
233 guests), lets you look up a case insensitive C<$path> in the
234 filesystem and returns the true, case sensitive path as required by
235 the underlying kernel or NTFS-3g driver.
237 If C<$path> does not exist then this function returns C<undef>.
239 The C<$path> parameter must begin with C</> character and be separated
240 by C</> characters. Do not use C<\>, drive names, etc.
244 sub resolve_windows_path
250 if (substr ($path, 0, 1) ne "/") {
251 warn "resolve_windows_path: path must start with a / character";
255 my @elems = split (/\//, $path);
258 # Start reconstructing the path at the top.
261 foreach my $dir (@elems) {
263 foreach ($g->ls ($path)) {
264 if (lc ($_) eq lc ($dir)) {
274 return undef unless $found;
280 =head1 OPERATING SYSTEM INSPECTION FUNCTIONS
282 The functions in this section can be used to inspect the operating
283 system(s) available inside a virtual machine image. For example, you
284 can find out if the VM is Linux or Windows, how the partitions are
285 meant to be mounted, and what applications are installed.
287 If you just want a simple command-line interface to this
288 functionality, use the L<virt-inspector(1)> tool. The documentation
289 below covers the case where you want to access this functionality from
292 Once you have the list of partitions (from C<get_partitions>) there
293 are several steps involved:
299 Look at each partition separately and find out what is on it.
301 The information you get back includes whether the partition contains a
302 filesystem or swapspace, what sort of filesystem (eg. ext3, ntfs), and
303 a first pass guess at the content of the filesystem (eg. Linux boot,
306 The result of this step is a C<%fs> hash of information, one hash for
309 See: C<inspect_partition>, C<inspect_all_partitions>
313 Work out the relationship between partitions.
315 In this step we work out how partitions are related to each other. In
316 the case of a single-boot VM, we work out how the partitions are
317 mounted in respect of each other (eg. C</dev/sda1> is mounted as
318 C</boot>). In the case of a multi-boot VM where there are several
319 roots, we may identify several operating system roots, and mountpoints
322 The result of this step is a single hash called C<%oses> which is
323 described in more detail below, but at the top level looks like:
326 '/dev/VG/Root1' => \%os1,
327 '/dev/VG/Root2' => \%os2,
333 '/' => '/dev/VG/Root1',
334 '/boot' => '/dev/sda1',
339 (example shows a multi-boot VM containing two root partitions).
341 See: C<inspect_operating_systems>
347 Previous to this point we've essentially been looking at each
348 partition in isolation. Now we construct a true guest filesystem by
349 mounting up all of the disks. Only once everything is mounted up can
350 we run commands in the OS context to do more detailed inspection.
352 See: C<mount_operating_system>
356 Check for kernels and applications.
358 This step now does more detailed inspection, where we can look for
359 kernels, applications and more installed in the guest.
361 The result of this is an enhanced C<%os> hash.
363 See: C<inspect_in_detail>
369 This library does not contain functions for generating output based on
370 the analysis steps above. Use a command line tool such as
371 L<virt-inspector(1)> to get useful output.
375 =head2 inspect_all_partitions
377 %fses = inspect_all_partitions ($g, \@partitions);
379 %fses = inspect_all_partitions ($g, \@partitions, use_windows_registry => 1);
381 This calls C<inspect_partition> for each partition in the list
384 The result is a hash which maps partition name to C<\%fs> hashref.
386 The contents of the C<%fs> hash and the meaning of the
387 C<use_windows_registry> flag are explained below.
391 sub inspect_all_partitions
397 return map { $_ => inspect_partition ($g, $_, @_) } @parts;
400 =head2 inspect_partition
402 \%fs = inspect_partition ($g, $partition);
404 \%fs = inspect_partition ($g, $partition, use_windows_registry => 1);
406 This function inspects the device named C<$partition> in isolation and
407 tries to determine what it is. It returns information such as whether
408 the partition is formatted, and with what, whether it is mountable,
409 and what it appears to contain (eg. a Windows root, or a Linux /usr).
411 If C<use_windows_registry> is set to 1, then we will try to download
412 and parse the content of the Windows registry (for Windows root
413 devices). However since this is an expensive and error-prone
414 operation, we don't do this by default. It also requires the external
415 program C<reged>, patched to remove numerous crashing bugs in the
418 The returned value is a hashref C<\%fs> which may contain the
419 following top-level keys (any key can be missing):
425 Filesystem type, eg. "ext2" or "ntfs"
429 Apparent filesystem OS, eg. "linux" or "windows"
433 If set, the partition is a swap partition.
445 If set, the partition could be mounted by libguestfs.
449 Filesystem content, if we could determine it. One of: "linux-grub",
450 "linux-root", "linux-usrlocal", "linux-usr", "windows-root".
454 (For Linux root partitions only).
455 Operating system distribution. One of: "fedora", "redhat",
460 (For root partitions only).
461 Operating system version.
465 (For Linux root partitions only).
466 The contents of the C</etc/fstab> file.
470 (For Windows root partitions only).
471 The contents of the C</boot.ini> (NTLDR) file.
475 The value is an arrayref, which is a list of Windows registry
476 file contents, in Windows C<.REG> format.
482 sub inspect_partition
486 my $dev = shift; # LV or partition name.
489 my $use_windows_registry = $params{use_windows_registry};
491 my %r; # Result hash.
493 # First try 'file(1)' on it.
494 my $file = $g->file ($dev);
495 if ($file =~ /ext2 filesystem data/) {
498 } elsif ($file =~ /ext3 filesystem data/) {
501 } elsif ($file =~ /ext4 filesystem data/) {
504 } elsif ($file =~ m{Linux/i386 swap file}) {
510 # If it's ext2/3/4, then we want the UUID and label.
511 if (exists $r{fstype} && $r{fstype} =~ /^ext/) {
512 $r{uuid} = $g->get_e2uuid ($dev);
513 $r{label} = $g->get_e2label ($dev);
516 # Try mounting it, fnarrr.
518 $r{is_mountable} = 1;
519 eval { $g->mount_ro ($dev, "/") };
521 # It's not mountable, probably empty or some format
522 # we don't understand.
523 $r{is_mountable} = 0;
528 if ($g->is_file ("/grub/menu.lst") ||
529 $g->is_file ("/grub/grub.conf")) {
530 $r{content} = "linux-grub";
531 check_grub ($g, \%r);
536 if ($g->is_dir ("/etc") && $g->is_dir ("/bin") &&
537 $g->is_file ("/etc/fstab")) {
538 $r{content} = "linux-root";
540 check_linux_root ($g, \%r);
545 if ($g->is_dir ("/etc") && $g->is_dir ("/bin") &&
546 $g->is_dir ("/share") && !$g->exists ("/local") &&
547 !$g->is_file ("/etc/fstab")) {
548 $r{content} = "linux-usrlocal";
553 if ($g->is_dir ("/etc") && $g->is_dir ("/bin") &&
554 $g->is_dir ("/share") && $g->exists ("/local") &&
555 !$g->is_file ("/etc/fstab")) {
556 $r{content} = "linux-usr";
561 if ($g->is_file ("/AUTOEXEC.BAT") ||
562 $g->is_file ("/autoexec.bat") ||
563 $g->is_dir ("/Program Files") ||
564 $g->is_dir ("/WINDOWS") ||
565 $g->is_file ("/boot.ini") ||
566 $g->is_file ("/ntldr")) {
567 $r{fstype} = "ntfs"; # XXX this is a guess
568 $r{fsos} = "windows";
569 $r{content} = "windows-root";
571 check_windows_root ($g, \%r, $use_windows_registry);
587 # Look into /etc to see if we recognise the operating system.
588 if ($g->is_file ("/etc/redhat-release")) {
589 $_ = $g->cat ("/etc/redhat-release");
590 if (/Fedora release (\d+\.\d+)/) {
591 $r->{osdistro} = "fedora";
592 $r->{osversion} = "$1"
593 } elsif (/(Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\d+).*Update (\d+)/) {
594 $r->{osdistro} = "redhat";
595 $r->{osversion} = "$2.$3";
596 } elsif (/(Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\d+(?:\.(\d+))?)/) {
597 $r->{osdistro} = "redhat";
598 $r->{osversion} = "$2";
600 $r->{osdistro} = "redhat";
602 } elsif ($g->is_file ("/etc/debian_version")) {
603 $_ = $g->cat ("/etc/debian_version");
605 $r->{osdistro} = "debian";
606 $r->{osversion} = "$1";
608 $r->{osdistro} = "debian";
612 # Parse the contents of /etc/fstab. This is pretty vital so
613 # we can determine where filesystems are supposed to be mounted.
614 eval "\$_ = \$g->cat ('/etc/fstab');";
616 my @lines = split /\n/;
619 my @fields = split /[ \t]+/;
621 my $spec = $fields[0]; # first column (dev/label/uuid)
622 my $file = $fields[1]; # second column (mountpoint)
623 if ($spec =~ m{^/} ||
624 $spec =~ m{^LABEL=} ||
625 $spec =~ m{^UUID=} ||
627 push @fstab, [$spec, $file]
631 $r->{fstab} = \@fstab if @fstab;
635 # We only support NT. The control file /boot.ini contains a list of
636 # Windows installations and their %systemroot%s in a simple text
639 # XXX We could parse this better. This won't work if /boot.ini is on
640 # a different drive from the %systemroot%, and in other unusual cases.
642 sub check_windows_root
647 my $use_windows_registry = shift;
649 my $boot_ini = resolve_windows_path ($g, "/boot.ini");
650 $r->{boot_ini} = $boot_ini;
652 if (defined $r->{boot_ini}) {
653 $_ = $g->cat ($boot_ini);
654 my @lines = split /\n/;
660 } elsif (m/^default=.*?\\(\w+)$/i) {
663 } elsif (m/\\(\w+)=/) {
669 if (defined $systemroot) {
670 $r->{systemroot} = resolve_windows_path ($g, "/$systemroot");
671 if (defined $r->{systemroot} && $use_windows_registry) {
672 check_windows_registry ($g, $r, $r->{systemroot});
678 sub check_windows_registry
683 my $systemroot = shift;
685 # Download the system registry files. Only download the
686 # interesting ones, and we don't bother with user profiles at all.
688 my $configdir = resolve_windows_path ($g, "$systemroot/system32/config");
689 if (defined $configdir) {
690 my $softwaredir = resolve_windows_path ($g, "$configdir/software");
691 if (defined $softwaredir) {
692 load_windows_registry ($g, $r, $softwaredir,
693 "HKEY_LOCAL_MACHINE\\SOFTWARE");
695 my $systemdir = resolve_windows_path ($g, "$configdir/system");
696 if (defined $systemdir) {
697 load_windows_registry ($g, $r, $systemdir,
698 "HKEY_LOCAL_MACHINE\\System");
703 sub load_windows_registry
711 my $dir = tempdir (CLEANUP => 1);
713 $g->download ($regfile, "$dir/reg");
715 # 'reged' command is particularly noisy. Redirect stdout and
716 # stderr to /dev/null temporarily.
717 open SAVEOUT, ">&STDOUT";
718 open SAVEERR, ">&STDERR";
719 open STDOUT, ">/dev/null";
720 open STDERR, ">/dev/null";
722 my @cmd = ("reged", "-x", "$dir/reg", "$prefix", "\\", "$dir/out");
723 my $res = system (@cmd);
727 open STDOUT, ">&SAVEOUT";
728 open STDERR, ">&SAVEERR";
733 warn "reged command failed: $?";
737 # Some versions of reged segfault on inputs. If that happens we
738 # may get no / partial output file. Anyway, if it exists, load
741 unless (open F, "$dir/out") {
742 warn "no output from reged command: $!";
745 { local $/ = undef; $content = <F>; }
749 @registry = @{$r->{registry}} if exists $r->{registry};
750 push @registry, $content;
751 $r->{registry} = \@registry;
760 # Grub version, if we care.
763 =head2 inspect_operating_systems
765 \%oses = inspect_operating_systems ($g, \%fses);
767 This function works out how partitions are related to each other. In
768 the case of a single-boot VM, we work out how the partitions are
769 mounted in respect of each other (eg. C</dev/sda1> is mounted as
770 C</boot>). In the case of a multi-boot VM where there are several
771 roots, we may identify several operating system roots, and mountpoints
774 This function returns a hashref C<\%oses> which at the top level looks
778 '/dev/VG/Root' => \%os,
781 (There can be multiple roots for a multi-boot VM).
783 The C<\%os> hash contains the following keys (any can be omitted):
789 Operating system type, eg. "linux", "windows".
793 Operating system distribution, eg. "debian".
797 Operating system version, eg. "4.0".
801 The value is a reference to the root partition C<%fs> hash.
805 The value is the name of the root partition (as a string).
810 The value is a hashref like this:
813 '/' => '/dev/VG/Root',
814 '/boot' => '/dev/sda1',
819 Filesystems (including swap devices and unmounted partitions).
820 The value is a hashref like this:
824 '/dev/VG/Root' => \%fs,
825 '/dev/VG/Swap' => \%fs,
832 sub inspect_operating_systems
840 foreach (sort keys %$fses) {
841 if ($fses->{$_}->{is_root}) {
846 get_os_version ($g, \%r);
847 assign_mount_points ($g, $fses, \%r);
861 $r->{os} = $r->{root}->{fsos} if exists $r->{root}->{fsos};
862 $r->{distro} = $r->{root}->{osdistro} if exists $r->{root}->{osdistro};
863 $r->{version} = $r->{root}->{osversion} if exists $r->{root}->{osversion};
866 sub assign_mount_points
873 $r->{mounts} = { "/" => $r->{root_device} };
874 $r->{filesystems} = { $r->{root_device} => $r->{root} };
876 # Use /etc/fstab if we have it to mount the rest.
877 if (exists $r->{root}->{fstab}) {
878 my @fstab = @{$r->{root}->{fstab}};
880 my ($spec, $file) = @$_;
882 my ($dev, $fs) = find_filesystem ($g, $fses, $spec);
884 $r->{mounts}->{$file} = $dev;
885 $r->{filesystems}->{$dev} = $fs;
886 if (exists $fs->{used}) {
897 # Find filesystem by device name, LABEL=.. or UUID=..
906 foreach (sort keys %$fses) {
907 if (exists $fses->{$_}->{label} &&
908 $fses->{$_}->{label} eq $label) {
909 return ($_, $fses->{$_});
912 warn "unknown filesystem label $label\n";
914 } elsif (/^UUID=(.*)/) {
916 foreach (sort keys %$fses) {
917 if (exists $fses->{$_}->{uuid} &&
918 $fses->{$_}->{uuid} eq $uuid) {
919 return ($_, $fses->{$_});
922 warn "unknown filesystem UUID $uuid\n";
925 return ($_, $fses->{$_}) if exists $fses->{$_};
927 # The following is to handle the case where an fstab entry specifies a
928 # specific device rather than its label or uuid, and the libguestfs
929 # appliance has named the device differently due to the use of a
931 # This will work as long as the underlying drivers recognise devices in
933 if (m{^/dev/hd(.*)} && exists $fses->{"/dev/sd$1"}) {
934 return ("/dev/sd$1", $fses->{"/dev/sd$1"});
936 if (m{^/dev/xvd(.*)} && exists $fses->{"/dev/sd$1"}) {
937 return ("/dev/sd$1", $fses->{"/dev/sd$1"});
939 if (m{^/dev/mapper/(.*)-(.*)$} && exists $fses->{"/dev/$1/$2"}) {
940 return ("/dev/$1/$2", $fses->{"/dev/$1/$2"});
943 return () if m{/dev/cdrom};
945 warn "unknown filesystem $_\n";
950 =head2 mount_operating_system
952 mount_operating_system ($g, \%os);
954 This function mounts the operating system described in the
955 C<%os> hash according to the C<mounts> table in that hash (see
956 C<inspect_operating_systems>).
958 The partitions are mounted read-only.
960 To reverse the effect of this call, use the standard
961 libguestfs API call C<$g-E<gt>umount_all ()>.
965 sub mount_operating_system
971 my $mounts = $os->{mounts};
973 # Have to mount / first. Luckily '/' is early in the ASCII
974 # character set, so this should be OK.
975 foreach (sort keys %$mounts) {
976 $g->mount_ro ($mounts->{$_}, $_)
977 if $_ ne "swap" && $_ ne "none" && ($_ eq '/' || $g->is_dir ($_));
981 =head2 inspect_in_detail
983 mount_operating_system ($g, \%os);
984 inspect_in_detail ($g, \%os);
987 The C<inspect_in_detail> function inspects the mounted operating
988 system for installed applications, installed kernels, kernel modules
991 It adds extra keys to the existing C<%os> hash reflecting what it
992 finds. These extra keys are:
998 List of applications.
1004 =item modprobe_aliases
1007 The contents of the modprobe configuration.
1009 =item initrd_modules
1012 The kernel modules installed in the initrd. The value is
1013 a hashref of kernel version to list of modules.
1019 sub inspect_in_detail
1025 check_for_applications ($g, $os);
1026 check_for_kernels ($g, $os);
1027 if ($os->{os} eq "linux") {
1028 check_for_modprobe_aliases ($g, $os);
1029 check_for_initrd ($g, $os);
1033 sub check_for_applications
1041 my $osn = $os->{os};
1042 if ($osn eq "linux") {
1043 my $distro = $os->{distro};
1044 if (defined $distro && ($distro eq "redhat" || $distro eq "fedora")) {
1045 my @lines = $g->command_lines
1048 "--qf", "%{name} %{epoch} %{version} %{release} %{arch}\n"]);
1050 if (m/^(.*) (.*) (.*) (.*) (.*)$/) {
1052 $epoch = "" if $epoch eq "(none)";
1064 } elsif ($osn eq "windows") {
1066 # I worked out a general plan for this, but haven't
1067 # implemented it yet. We can iterate over /Program Files
1068 # looking for *.EXE files, which we download, then use
1069 # i686-pc-mingw32-windres on, to find the VERSIONINFO
1070 # section, which has a lot of useful information.
1073 $os->{apps} = \@apps;
1076 sub check_for_kernels
1084 my $osn = $os->{os};
1085 if ($osn eq "linux") {
1086 # Installed kernels will have a corresponding /lib/modules/<version>
1087 # directory, which is the easiest way to find out what kernels
1088 # are installed, and what modules are available.
1089 foreach ($g->ls ("/lib/modules")) {
1090 if ($g->is_dir ("/lib/modules/$_")) {
1092 $kernel{version} = $_;
1096 foreach ($g->find ("/lib/modules/$_")) {
1097 if (m,/([^/]+)\.ko$, || m,([^/]+)\.o$,) {
1102 $kernel{modules} = \@modules;
1104 push @kernels, \%kernel;
1108 } elsif ($osn eq "windows") {
1112 $os->{kernels} = \@kernels;
1115 # Check /etc/modprobe.conf to see if there are any specified
1116 # drivers associated with network (ethX) or hard drives. Normally
1117 # one might find something like:
1120 # alias scsi_hostadapter xenblk
1122 # XXX This doesn't look beyond /etc/modprobe.conf, eg. in /etc/modprobe.d/
1124 sub check_for_modprobe_aliases
1132 $success = $g->aug_init("/", 16);
1134 # Register /etc/modules.conf and /etc/conf.modules to the Modprobe lens
1136 @results = $g->aug_match("/augeas/load/Modprobe/incl");
1138 # Calculate the next index of /augeas/load/Modprobe/incl
1140 foreach ( @results ) {
1141 next unless m{/augeas/load/Modprobe/incl\[(\d*)]};
1142 $i = $1 + 1 if ($1 == $i);
1145 $success = $g->aug_set("/augeas/load/Modprobe/incl[$i]",
1146 "/etc/modules.conf");
1148 $success = $g->aug_set("/augeas/load/Modprobe/incl[$i]",
1149 "/etc/conf.modules");
1151 # Make augeas reload
1152 $success = $g->aug_load();
1154 my %modprobe_aliases;
1156 for my $pattern qw(/files/etc/conf.modules/alias
1157 /files/etc/modules.conf/alias
1158 /files/etc/modprobe.conf/alias
1159 /files/etc/modprobe.d/*/alias) {
1160 @results = $g->aug_match($pattern);
1162 for my $path ( @results ) {
1163 $path =~ m{^/files(.*)/alias(?:\[\d*\])?$}
1164 or die("$path doesn't match augeas pattern");
1168 $alias = $g->aug_get($path);
1171 $modulename = $g->aug_get($path.'/modulename');
1174 $aliasinfo{modulename} = $modulename;
1175 $aliasinfo{augeas} = $path;
1176 $aliasinfo{file} = $file;
1178 $modprobe_aliases{$alias} = \%aliasinfo;
1182 $os->{modprobe_aliases} = \%modprobe_aliases;
1185 # Get a listing of device drivers in any initrd corresponding to a
1186 # kernel. This is an indication of what can possibly be booted.
1188 sub check_for_initrd
1196 foreach my $initrd ($g->ls ("/boot")) {
1197 if ($initrd =~ m/^initrd-(.*)\.img$/ && $g->is_file ("/boot/$initrd")) {
1202 @modules = $g->initrd_list ("/boot/$initrd");
1205 @modules = grep { m,([^/]+)\.ko$, || m,([^/]+)\.o$, } @modules;
1206 $initrd_modules{$version} = \@modules
1208 warn "/boot/$initrd: could not read initrd format"
1213 $os->{initrd_modules} = \%initrd_modules;
1221 Copyright (C) 2009 Red Hat Inc.
1225 Please see the file COPYING.LIB for the full license.
1229 L<virt-inspector(1)>,
1232 L<http://libguestfs.org/>,
1234 L<http://libvirt.org/>,