mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
Added virt-inspector program from virt-v2v.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -43,6 +43,7 @@ html/recipes.html
|
||||
initramfs
|
||||
initramfs.timestamp
|
||||
initramfs.*.img
|
||||
inspector/virt-inspector.1
|
||||
install-sh
|
||||
java/api
|
||||
java/com_redhat_et_libguestfs_GuestFS.h
|
||||
|
||||
3
HACKING
3
HACKING
@@ -46,6 +46,9 @@ images/
|
||||
|
||||
Also contains some files used by the test suite.
|
||||
|
||||
inspector/
|
||||
Virtual machine image inspector (virt-inspector).
|
||||
|
||||
java/
|
||||
Java bindings.
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ endif
|
||||
if HAVE_JAVA
|
||||
SUBDIRS += java
|
||||
endif
|
||||
if HAVE_INSPECTOR
|
||||
SUBDIRS += inspector
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
make-initramfs.sh update-initramfs.sh \
|
||||
|
||||
21
configure.ac
21
configure.ac
@@ -376,6 +376,24 @@ AC_SUBST(JNI_VERSION_INFO)
|
||||
|
||||
AM_CONDITIONAL([HAVE_JAVA],[test -n "$JAVAC"])
|
||||
|
||||
dnl Check for Perl modules needed by the inspector.
|
||||
missing_perl_modules=no
|
||||
for pm in Pod::Usage Getopt::Long Sys::Virt Data::Dumper; do
|
||||
AC_MSG_CHECKING([for $pm])
|
||||
if ! perl -M$pm -e1 >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT([no])
|
||||
missing_perl_modules=yes
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
done
|
||||
if test "x$missing_perl_modules" = "xyes"; then
|
||||
AC_MSG_WARN([some Perl modules required to compile virt-inspector are missing])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([HAVE_INSPECTOR],
|
||||
[test "x$PERL" != "xno" -a "x$missing_perl_modules" != "xyes"])
|
||||
|
||||
dnl Run in subdirs.
|
||||
AC_CONFIG_SUBDIRS([daemon])
|
||||
|
||||
@@ -388,6 +406,7 @@ AC_CONFIG_FILES([Makefile src/Makefile fish/Makefile examples/Makefile
|
||||
python/Makefile
|
||||
ruby/Makefile ruby/Rakefile
|
||||
java/Makefile
|
||||
inspector/Makefile
|
||||
make-initramfs.sh update-initramfs.sh
|
||||
libguestfs.spec libguestfs.pc
|
||||
ocaml/META perl/Makefile.PL])
|
||||
@@ -415,6 +434,8 @@ echo -n "Ruby bindings ....................... "
|
||||
if test "x$HAVE_RUBY_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "Java bindings ....................... "
|
||||
if test "x$HAVE_JAVA_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "virt-inspector ...................... "
|
||||
if test "x$HAVE_INSPECTOR" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo
|
||||
echo "If any optional component is configured 'no' when you expected 'yes'"
|
||||
echo "then you should check the preceeding messages."
|
||||
|
||||
38
inspector/Makefile.am
Normal file
38
inspector/Makefile.am
Normal file
@@ -0,0 +1,38 @@
|
||||
# libguestfs virt-inspector
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
EXTRA_DIST = \
|
||||
virt-inspector.pl
|
||||
|
||||
CLEANFILES = *~
|
||||
|
||||
if HAVE_INSPECTOR
|
||||
|
||||
man_MANS = virt-inspector.1
|
||||
|
||||
virt-inspector.1: virt-inspector.pl
|
||||
$(POD2MAN) \
|
||||
--section 1 \
|
||||
-c "Virtualization Support" \
|
||||
--release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \
|
||||
$< > $@
|
||||
|
||||
install-data-hook:
|
||||
mkdir -p $(DESTDIR)$(bindir)
|
||||
install -m 0755 virt-inspector.pl $(DESTDIR)$(bindir)/virt-inspector
|
||||
|
||||
endif
|
||||
29
inspector/run-inspector-locally
Executable file
29
inspector/run-inspector-locally
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh -
|
||||
# libguestfs inspector
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# This script sets up the environment so you can run
|
||||
# virt-inspector from the top-level source directory
|
||||
# without needing to do 'make install' first.
|
||||
#
|
||||
# Use it like this:
|
||||
# ./inspector/run-inspector-locally [usual virt-inspector args ...]
|
||||
|
||||
export LD_LIBRARY_PATH=$(pwd)/src/.libs
|
||||
export LIBGUESTFS_PATH=$(pwd)
|
||||
export PERL5LIB=$(pwd)/perl/blib/lib:$(pwd)/perl/blib/arch
|
||||
perl ./inspector/virt-inspector.pl "$@"
|
||||
566
inspector/virt-inspector.pl
Executable file
566
inspector/virt-inspector.pl
Executable file
@@ -0,0 +1,566 @@
|
||||
#!/usr/bin/perl -w
|
||||
# virt-inspector
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Sys::Guestfs;
|
||||
use Pod::Usage;
|
||||
use Getopt::Long;
|
||||
use Data::Dumper;
|
||||
|
||||
# Optional:
|
||||
eval "use Sys::Virt;";
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
virt-inspector - Display OS version, kernel, drivers, mount points, applications, etc. in a virtual machine
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
virt-inspector [--connect URI] domname
|
||||
|
||||
virt-inspector guest.img [guest.img ...]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<virt-inspector> examines a virtual machine and tries to determine
|
||||
the version of the OS, the kernel version, what drivers are installed,
|
||||
whether the virtual machine is fully virtualized (FV) or
|
||||
para-virtualized (PV), what applications are installed and more.
|
||||
|
||||
Virt-inspector can produce output in several formats, including a
|
||||
readable text report, and XML for feeding into other programs.
|
||||
|
||||
Virt-inspector should only be run on I<inactive> virtual machines.
|
||||
The program tries to determine that the machine is inactive and will
|
||||
refuse to run if it thinks you are trying to inspect a running domain.
|
||||
|
||||
In the normal usage, use C<virt-inspector domname> where C<domname> is
|
||||
the libvirt domain (see: C<virsh list --all>).
|
||||
|
||||
You can also run virt-inspector directly on disk images from a single
|
||||
virtual machine. Use C<virt-inspector guest.img>. In rare cases a
|
||||
domain has several block devices, in which case you should list them
|
||||
one after another, with the first corresponding to the guest's
|
||||
C</dev/sda>, the second to the guest's C</dev/sdb> and so on.
|
||||
|
||||
Virt-inspector can only inspect and report upon I<one domain at a
|
||||
time>. To inspect several virtual machines, you have to run
|
||||
virt-inspector several times (for example, from a shell script
|
||||
for-loop).
|
||||
|
||||
Because virt-inspector needs direct access to guest images, it won't
|
||||
normally work over remote libvirt connections.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
my $help;
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Display brief help.
|
||||
|
||||
=cut
|
||||
|
||||
my $uri;
|
||||
|
||||
=item B<--connect URI> | B<-c URI>
|
||||
|
||||
If using libvirt, connect to the given I<URI>. If omitted,
|
||||
then we connect to the default libvirt hypervisor.
|
||||
|
||||
Libvirt is only used if you specify a C<domname> on the
|
||||
command line. If you specify guest block devices directly,
|
||||
then libvirt is not used at all.
|
||||
|
||||
=cut
|
||||
|
||||
my $force;
|
||||
|
||||
=item B<--force>
|
||||
|
||||
Force reading a particular guest even if it appears to
|
||||
be active, or if the guest image is writable. This is
|
||||
dangerous and can even corrupt the guest image.
|
||||
|
||||
=cut
|
||||
|
||||
my $output = "text";
|
||||
|
||||
=item B<--text> (default)
|
||||
|
||||
=item B<--xml>
|
||||
|
||||
=item B<--fish>
|
||||
|
||||
=item B<--ro-fish>
|
||||
|
||||
Select the output format. The default is a readable text report.
|
||||
|
||||
If you select I<--xml> then you get XML output which can be fed
|
||||
to other programs.
|
||||
|
||||
If you select I<--fish> then we print a L<guestfish(1)> command
|
||||
line which will automatically mount up the filesystems on the
|
||||
correct mount points. Try this for example:
|
||||
|
||||
eval `virt-inspector --fish guest.img`
|
||||
|
||||
I<--ro-fish> is the same, but the I<--ro> option is passed to
|
||||
guestfish so that the filesystems are mounted read-only.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
GetOptions ("help|?" => \$help,
|
||||
"connect|c=s" => \$uri,
|
||||
"force" => \$force,
|
||||
"xml" => sub { $output = "xml" },
|
||||
"fish" => sub { $output = "fish" },
|
||||
"guestfish" => sub { $output = "fish" },
|
||||
"ro-fish" => sub { $output = "ro-fish" },
|
||||
"ro-guestfish" => sub { $output = "ro-fish" })
|
||||
or pod2usage (2);
|
||||
pod2usage (1) if $help;
|
||||
pod2usage ("$0: no image or VM names given") if @ARGV == 0;
|
||||
|
||||
# Domain name or guest image(s)?
|
||||
|
||||
my @images;
|
||||
if (-e $ARGV[0]) {
|
||||
@images = @ARGV;
|
||||
|
||||
# Until we get an 'add_drive_ro' call, we must check that qemu
|
||||
# will only open this image in readonly mode.
|
||||
# XXX Remove this hack at some point ... or at least push it
|
||||
# into libguestfs.
|
||||
|
||||
foreach (@images) {
|
||||
if (! -r $_) {
|
||||
die "guest image $_ does not exist or is not readable\n"
|
||||
} elsif (-w $_ && !$force) {
|
||||
die ("guest image $_ is writable! REFUSING TO PROCEED.\n".
|
||||
"You can use --force to override this BUT that action\n".
|
||||
"MAY CORRUPT THE DISK IMAGE.\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
die "no libvirt support (install Sys::Virt)"
|
||||
unless exists $INC{"Sys/Virt.pm"};
|
||||
|
||||
pod2usage ("$0: too many domains listed on command line") if @ARGV > 1;
|
||||
|
||||
my $vmm;
|
||||
if (defined $uri) {
|
||||
$vmm = Sys::Virt->new (uri => $uri, readonly => 1);
|
||||
} else {
|
||||
$vmm = Sys::Virt->new (readonly => 1);
|
||||
}
|
||||
die "cannot connect to libvirt $uri\n" unless $vmm;
|
||||
|
||||
my @doms = $vmm->list_defined_domains ();
|
||||
my $dom;
|
||||
foreach (@doms) {
|
||||
if ($_->get_name () eq $ARGV[0]) {
|
||||
$dom = $_;
|
||||
last;
|
||||
}
|
||||
}
|
||||
die "$ARGV[0] is not the name of an inactive libvirt domain\n"
|
||||
unless $dom;
|
||||
|
||||
# Get the names of the image(s).
|
||||
my $xml = $dom->get_xml_description ();
|
||||
|
||||
my $p = new XML::XPath::XMLParser (xml => $xml);
|
||||
my $disks = $p->find ("//devices/disk");
|
||||
print "disks:\n";
|
||||
foreach ($disks->get_nodelist) {
|
||||
print XML::XPath::XMLParser::as_string($_);
|
||||
}
|
||||
|
||||
die "XXX"
|
||||
}
|
||||
|
||||
# We've now got the list of @images, so feed them to libguestfs.
|
||||
my $g = Sys::Guestfs->new ();
|
||||
$g->add_drive ($_) foreach @images;
|
||||
$g->launch ();
|
||||
$g->wait_ready ();
|
||||
|
||||
# We want to get the list of LVs and partitions (ie. anything that
|
||||
# could contain a filesystem). Discard any partitions which are PVs.
|
||||
my @partitions = $g->list_partitions ();
|
||||
my @pvs = $g->pvs ();
|
||||
sub is_pv {
|
||||
my $t = shift;
|
||||
foreach (@pvs) {
|
||||
return 1 if $_ eq $t;
|
||||
}
|
||||
0;
|
||||
}
|
||||
@partitions = grep { ! is_pv ($_) } @partitions;
|
||||
|
||||
my @lvs = $g->lvs ();
|
||||
|
||||
=head1 OUTPUT FORMAT
|
||||
|
||||
Operating system(s)
|
||||
-------------------
|
||||
Linux (distro + version)
|
||||
Windows (version)
|
||||
|
|
||||
|
|
||||
+--- Filesystems ---------- Installed apps --- Kernel & drivers
|
||||
----------- -------------- ----------------
|
||||
mount point => device List of apps Extra information
|
||||
mount point => device and versions about kernel(s)
|
||||
... and drivers
|
||||
swap => swap device
|
||||
(plus lots of extra information
|
||||
about each filesystem)
|
||||
|
||||
The output of virt-inspector is a complex two-level data structure.
|
||||
|
||||
At the top level is a list of the operating systems installed on the
|
||||
guest. (For the vast majority of guests, only a single OS is
|
||||
installed.) The data returned for the OS includes the name (Linux,
|
||||
Windows), the distribution and version.
|
||||
|
||||
The diagram above shows what we return for each OS.
|
||||
|
||||
With the I<--xml> option the output is mapped into an XML document.
|
||||
Unfortunately there is no clear schema for this document
|
||||
(contributions welcome) but you can get an idea of the format by
|
||||
looking at other documents and as a last resort the source for this
|
||||
program.
|
||||
|
||||
With the I<--fish> or I<--ro-fish> option the mount points are mapped to
|
||||
L<guestfish(1)> command line parameters, so that you can go in
|
||||
afterwards and inspect the guest with everything mounted in the
|
||||
right place. For example:
|
||||
|
||||
eval `virt-inspector --ro-fish guest.img`
|
||||
==> guestfish --ro -a guest.img -m /dev/VG/LV:/ -m /dev/sda1:/boot
|
||||
|
||||
=cut
|
||||
|
||||
# List of possible filesystems.
|
||||
my @devices = sort (@lvs, @partitions);
|
||||
|
||||
# Now query each one to build up a picture of what's in it.
|
||||
my %fses = map { $_ => check_fs ($_) } @devices;
|
||||
|
||||
# Now the complex checking code itself.
|
||||
# check_fs takes a device name (LV or partition name) and returns
|
||||
# a hashref containing everything we can find out about the device.
|
||||
sub check_fs {
|
||||
local $_;
|
||||
my $dev = shift; # LV or partition name.
|
||||
|
||||
my %r; # Result hash.
|
||||
|
||||
# First try 'file(1)' on it.
|
||||
my $file = $g->file ($dev);
|
||||
if ($file =~ /ext2 filesystem data/) {
|
||||
$r{fstype} = "ext2";
|
||||
$r{fsos} = "linux";
|
||||
} elsif ($file =~ /ext3 filesystem data/) {
|
||||
$r{fstype} = "ext3";
|
||||
$r{fsos} = "linux";
|
||||
} elsif ($file =~ /ext4 filesystem data/) {
|
||||
$r{fstype} = "ext4";
|
||||
$r{fsos} = "linux";
|
||||
} elsif ($file =~ m{Linux/i386 swap file}) {
|
||||
$r{fstype} = "swap";
|
||||
$r{fsos} = "linux";
|
||||
$r{is_swap} = 1;
|
||||
}
|
||||
|
||||
# If it's ext2/3/4, then we want the UUID and label.
|
||||
if (exists $r{fstype} && $r{fstype} =~ /^ext/) {
|
||||
$r{uuid} = $g->get_e2uuid ($dev);
|
||||
$r{label} = $g->get_e2label ($dev);
|
||||
}
|
||||
|
||||
# Try mounting it, fnarrr.
|
||||
if (!$r{is_swap}) {
|
||||
$r{is_mountable} = 1;
|
||||
eval { $g->mount_ro ($dev, "/") };
|
||||
if ($@) {
|
||||
# It's not mountable, probably empty or some format
|
||||
# we don't understand.
|
||||
$r{is_mountable} = 0;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
# Grub /boot?
|
||||
if ($g->is_file ("/grub/menu.lst") ||
|
||||
$g->is_file ("/grub/grub.conf")) {
|
||||
$r{content} = "linux-grub";
|
||||
check_grub (\%r);
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
# Linux root?
|
||||
if ($g->is_dir ("/etc") && $g->is_dir ("/bin") &&
|
||||
$g->is_file ("/etc/fstab")) {
|
||||
$r{content} = "linux-root";
|
||||
$r{is_root} = 1;
|
||||
check_linux_root (\%r);
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
# Linux /usr/local.
|
||||
if ($g->is_dir ("/etc") && $g->is_dir ("/bin") &&
|
||||
$g->is_dir ("/share") && !$g->exists ("/local") &&
|
||||
!$g->is_file ("/etc/fstab")) {
|
||||
$r{content} = "linux-usrlocal";
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
# Linux /usr.
|
||||
if ($g->is_dir ("/etc") && $g->is_dir ("/bin") &&
|
||||
$g->is_dir ("/share") && $g->exists ("/local") &&
|
||||
!$g->is_file ("/etc/fstab")) {
|
||||
$r{content} = "linux-usr";
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
# Windows root?
|
||||
if ($g->is_file ("/AUTOEXEC.BAT") ||
|
||||
$g->is_file ("/autoexec.bat") ||
|
||||
$g->is_dir ("/Program Files") ||
|
||||
$g->is_dir ("/WINDOWS") ||
|
||||
$g->is_file ("/ntldr")) {
|
||||
$r{fstype} = "ntfs"; # XXX this is a guess
|
||||
$r{fsos} = "windows";
|
||||
$r{content} = "windows-root";
|
||||
$r{is_root} = 1;
|
||||
check_windows_root (\%r);
|
||||
goto OUT;
|
||||
}
|
||||
}
|
||||
|
||||
OUT:
|
||||
$g->umount_all ();
|
||||
return \%r;
|
||||
}
|
||||
|
||||
sub check_linux_root
|
||||
{
|
||||
local $_;
|
||||
my $r = shift;
|
||||
|
||||
# Look into /etc to see if we recognise the operating system.
|
||||
if ($g->is_file ("/etc/redhat-release")) {
|
||||
$_ = $g->cat ("/etc/redhat-release");
|
||||
if (/Fedora release (\d+\.\d+)/) {
|
||||
$r->{osdistro} = "fedora";
|
||||
$r->{osversion} = "$1"
|
||||
} elsif (/(Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\d+).*Update (\d+)/) {
|
||||
$r->{osdistro} = "redhat";
|
||||
$r->{osversion} = "$2.$3";
|
||||
} elsif (/(Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\d+(?:\.(\d+))?)/) {
|
||||
$r->{osdistro} = "redhat";
|
||||
$r->{osversion} = "$2";
|
||||
} else {
|
||||
$r->{osdistro} = "redhat";
|
||||
}
|
||||
} elsif ($g->is_file ("/etc/debian_version")) {
|
||||
$_ = $g->cat ("/etc/debian_version");
|
||||
if (/(\d+\.\d+)/) {
|
||||
$r->{osdistro} = "debian";
|
||||
$r->{osversion} = "$1";
|
||||
} else {
|
||||
$r->{osdistro} = "debian";
|
||||
}
|
||||
}
|
||||
|
||||
# Parse the contents of /etc/fstab. This is pretty vital so
|
||||
# we can determine where filesystems are supposed to be mounted.
|
||||
eval "\$_ = \$g->cat ('/etc/fstab');";
|
||||
if (!$@ && $_) {
|
||||
my @lines = split /\n/;
|
||||
my @fstab;
|
||||
foreach (@lines) {
|
||||
my @fields = split /[ \t]+/;
|
||||
if (@fields >= 2) {
|
||||
my $spec = $fields[0]; # first column (dev/label/uuid)
|
||||
my $file = $fields[1]; # second column (mountpoint)
|
||||
if ($spec =~ m{^/} ||
|
||||
$spec =~ m{^LABEL=} ||
|
||||
$spec =~ m{^UUID=} ||
|
||||
$file eq "swap") {
|
||||
push @fstab, [$spec, $file]
|
||||
}
|
||||
}
|
||||
}
|
||||
$r->{fstab} = \@fstab if @fstab;
|
||||
}
|
||||
}
|
||||
|
||||
sub check_windows_root
|
||||
{
|
||||
local $_;
|
||||
my $r = shift;
|
||||
|
||||
# XXX Windows version.
|
||||
# List of applications.
|
||||
}
|
||||
|
||||
sub check_grub
|
||||
{
|
||||
local $_;
|
||||
my $r = shift;
|
||||
|
||||
# XXX Kernel versions, grub version.
|
||||
}
|
||||
|
||||
#print Dumper (\%fses);
|
||||
|
||||
# Now find out how many operating systems we've got. Usually just one.
|
||||
|
||||
my %oses = ();
|
||||
|
||||
foreach (sort keys %fses) {
|
||||
if ($fses{$_}->{is_root}) {
|
||||
my %r = (
|
||||
root => $fses{$_},
|
||||
root_device => $_
|
||||
);
|
||||
get_os_version (\%r);
|
||||
assign_mount_points (\%r);
|
||||
$oses{$_} = \%r;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_os_version
|
||||
{
|
||||
local $_;
|
||||
my $r = shift;
|
||||
|
||||
$r->{os} = $r->{root}->{fsos} if exists $r->{root}->{fsos};
|
||||
$r->{distro} = $r->{root}->{osdistro} if exists $r->{root}->{osdistro};
|
||||
$r->{version} = $r->{root}->{osversion} if exists $r->{root}->{osversion};
|
||||
}
|
||||
|
||||
sub assign_mount_points
|
||||
{
|
||||
local $_;
|
||||
my $r = shift;
|
||||
|
||||
$r->{mounts} = { "/" => $r->{root_device} };
|
||||
$r->{filesystems} = { $r->{root_device} => $r->{root} };
|
||||
|
||||
# Use /etc/fstab if we have it to mount the rest.
|
||||
if (exists $r->{root}->{fstab}) {
|
||||
my @fstab = @{$r->{root}->{fstab}};
|
||||
foreach (@fstab) {
|
||||
my ($spec, $file) = @$_;
|
||||
|
||||
my ($dev, $fs) = find_filesystem ($spec);
|
||||
if ($dev) {
|
||||
$r->{mounts}->{$file} = $dev;
|
||||
$r->{filesystems}->{$dev} = $fs;
|
||||
if (exists $fs->{used}) {
|
||||
$fs->{used}++
|
||||
} else {
|
||||
$fs->{used} = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Find filesystem by device name, LABEL=.. or UUID=..
|
||||
sub find_filesystem
|
||||
{
|
||||
local $_ = shift;
|
||||
|
||||
if (/^LABEL=(.*)/) {
|
||||
my $label = $1;
|
||||
foreach (sort keys %fses) {
|
||||
if (exists $fses{$_}->{label} &&
|
||||
$fses{$_}->{label} eq $label) {
|
||||
return ($_, $fses{$_});
|
||||
}
|
||||
}
|
||||
warn "unknown filesystem label $label\n";
|
||||
return ();
|
||||
} elsif (/^UUID=(.*)/) {
|
||||
my $uuid = $1;
|
||||
foreach (sort keys %fses) {
|
||||
if (exists $fses{$_}->{uuid} &&
|
||||
$fses{$_}->{uuid} eq $uuid) {
|
||||
return ($_, $fses{$_});
|
||||
}
|
||||
}
|
||||
warn "unknown filesystem UUID $uuid\n";
|
||||
return ();
|
||||
} else {
|
||||
return ($_, $fses{$_}) if exists $fses{$_};
|
||||
warn "unknown filesystem $_\n";
|
||||
return ();
|
||||
}
|
||||
}
|
||||
|
||||
print Dumper (\%oses);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
L<guestfish(1)>,
|
||||
L<Sys::Guestfs(3)>,
|
||||
L<Sys::Virt(3)>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 2009 Red Hat Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -48,6 +48,9 @@ BuildRequires: java >= 1.5.0
|
||||
BuildRequires: jpackage-utils
|
||||
BuildRequires: java-devel
|
||||
|
||||
# For virt-inspector:
|
||||
BuildRequires: perl-Sys-Virt
|
||||
|
||||
# Runtime requires:
|
||||
Requires: qemu >= 0.10-7
|
||||
|
||||
@@ -113,6 +116,22 @@ modifying virtual machine disk images from the command line and shell
|
||||
scripts.
|
||||
|
||||
|
||||
%package -n virt-inspector
|
||||
Summary: Display OS version, kernel, drivers, etc in a virtual machine
|
||||
Group: Development/Tools
|
||||
License: GPLv2+
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: guestfish
|
||||
Requires: perl-Sys-Virt
|
||||
|
||||
|
||||
%description -n virt-inspector
|
||||
Virt-inspector examines a virtual machine and tries to determine the
|
||||
version of the OS, the kernel version, what drivers are installed,
|
||||
whether the virtual machine is fully virtualized (FV) or
|
||||
para-virtualized (PV), what applications are installed and more.
|
||||
|
||||
|
||||
%package -n ocaml-%{name}
|
||||
Summary: OCaml bindings for %{name}
|
||||
Group: Development/Libraries
|
||||
@@ -332,6 +351,12 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_mandir}/man1/guestfish.1*
|
||||
|
||||
|
||||
%files -n virt-inspector
|
||||
%defattr(-,root,root,-)
|
||||
%{_bindir}/virt-inspector
|
||||
%{_mandir}/man1/virt-inspector.1*
|
||||
|
||||
|
||||
%files -n ocaml-%{name}
|
||||
%defattr(-,root,root,-)
|
||||
%doc README
|
||||
|
||||
Reference in New Issue
Block a user