mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
inspector: Rewrite virt-inspector (RHBZ#642930).
Rewrite virt-inspector: - remove old and unsupportable features - use the C inspection API - don't run programs from the guest The RNG has been updated to reflect the new XML-only output. The new example files show the new XML output.
This commit is contained in:
@@ -17,6 +17,10 @@
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
EXAMPLE_XML = \
|
||||
example1.xml example2.xml example3.xml \
|
||||
example4.xml example5.xml example6.xml
|
||||
|
||||
EXTRA_DIST = \
|
||||
run-inspector-locally \
|
||||
virt-inspector
|
||||
@@ -24,7 +28,7 @@ EXTRA_DIST = \
|
||||
docdir = @docdir@
|
||||
dist_doc_DATA = \
|
||||
virt-inspector.rng \
|
||||
example1.xml example2.xml example3.xml example4.xml
|
||||
$(EXAMPLE_XML)
|
||||
|
||||
if HAVE_INSPECTOR
|
||||
|
||||
@@ -52,7 +56,7 @@ $(top_builddir)/html/virt-inspector.1.html: virt-inspector
|
||||
|
||||
if HAVE_XMLLINT
|
||||
|
||||
TESTS = example1.xml example2.xml example3.xml example4.xml
|
||||
TESTS = $(EXAMPLE_XML)
|
||||
TESTS_ENVIRONMENT = $(XMLLINT) --noout --relaxng virt-inspector.rng
|
||||
|
||||
endif
|
||||
|
||||
10040
inspector/example1.xml
10040
inspector/example1.xml
File diff suppressed because it is too large
Load Diff
11691
inspector/example2.xml
11691
inspector/example2.xml
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,21 @@
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/vda2</root>
|
||||
<name>windows</name>
|
||||
<product_name>Microsoft Windows Server 2003</product_name>
|
||||
<arch>i386</arch>
|
||||
<major_version>5</major_version>
|
||||
<minor_version>2</minor_version>
|
||||
<root>/dev/sda1</root>
|
||||
<distro>windows</distro>
|
||||
<product_name>Windows 7 Enterprise</product_name>
|
||||
<major_version>6</major_version>
|
||||
<minor_version>1</minor_version>
|
||||
<windows_systemroot>/Windows</windows_systemroot>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda1">/</mountpoint>
|
||||
<mountpoint dev="/dev/vda2">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda1">
|
||||
<filesystem dev="/dev/vda2">
|
||||
<type>ntfs</type>
|
||||
<content>windows-root</content>
|
||||
<uuid>F2E8996AE8992E3B</uuid>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications></applications>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
|
||||
50
inspector/example5.xml
Normal file
50
inspector/example5.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/debian5x64.home.annexia.org/root</root>
|
||||
<name>linux</name>
|
||||
<arch>x86_64</arch>
|
||||
<distro>debian</distro>
|
||||
<product_name>5.0.6</product_name>
|
||||
<major_version>5</major_version>
|
||||
<minor_version>0</minor_version>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/debian5x64.home.annexia.org/root">/</mountpoint>
|
||||
<mountpoint dev="/dev/debian5x64.home.annexia.org/usr">/usr</mountpoint>
|
||||
<mountpoint dev="/dev/debian5x64.home.annexia.org/var">/var</mountpoint>
|
||||
<mountpoint dev="/dev/debian5x64.home.annexia.org/tmp">/tmp</mountpoint>
|
||||
<mountpoint dev="/dev/debian5x64.home.annexia.org/home">/home</mountpoint>
|
||||
<mountpoint dev="/dev/vda1">/boot</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/debian5x64.home.annexia.org/root">
|
||||
<type>ext3</type>
|
||||
<uuid>e15bda18-deca-40d1-beb4-ff31e4068741</uuid>
|
||||
</filesystem>
|
||||
<filesystem dev="/dev/vda1">
|
||||
<type>ext2</type>
|
||||
<uuid>b6590940-dc13-4fc5-b306-7c7bdf075f17</uuid>
|
||||
</filesystem>
|
||||
<filesystem dev="/dev/debian5x64.home.annexia.org/home">
|
||||
<type>ext3</type>
|
||||
<uuid>96b22229-3575-408e-8270-aeba18b3ebf1</uuid>
|
||||
</filesystem>
|
||||
<filesystem dev="/dev/debian5x64.home.annexia.org/tmp">
|
||||
<type>ext3</type>
|
||||
<uuid>241ea398-034e-4514-9854-eec667ebe9d9</uuid>
|
||||
</filesystem>
|
||||
<filesystem dev="/dev/debian5x64.home.annexia.org/usr">
|
||||
<type>ext3</type>
|
||||
<uuid>4645668c-60d1-44ea-9ad6-d283bd71e380</uuid>
|
||||
</filesystem>
|
||||
<filesystem dev="/dev/debian5x64.home.annexia.org/var">
|
||||
<type>ext3</type>
|
||||
<uuid>0eb2cef5-e765-440f-8be7-f40c46b93874</uuid>
|
||||
</filesystem>
|
||||
<filesystem dev="/dev/debian5x64.home.annexia.org/swap_1">
|
||||
<type>swap</type>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<package_format>dpkg</package_format>
|
||||
<package_management>apt</package_management>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
26
inspector/example6.xml
Normal file
26
inspector/example6.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/vda1</root>
|
||||
<name>linux</name>
|
||||
<arch>x86_64</arch>
|
||||
<distro>debian</distro>
|
||||
<product_name>squeeze/sid</product_name>
|
||||
<major_version>0</major_version>
|
||||
<minor_version>0</minor_version>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/vda1">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/vda1">
|
||||
<type>ext4</type>
|
||||
<uuid>09384d4f-df19-479b-85fc-6451e56d41aa</uuid>
|
||||
</filesystem>
|
||||
<filesystem dev="/dev/vda5">
|
||||
<type>swap</type>
|
||||
<uuid>c0d1b68f-c0f9-4497-a366-938b37532613</uuid>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<package_format>dpkg</package_format>
|
||||
<package_management>apt</package_management>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/perl -w
|
||||
# virt-inspector
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
# Copyright (C) 2010 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
|
||||
@@ -20,24 +20,19 @@ use warnings;
|
||||
use strict;
|
||||
|
||||
use Sys::Guestfs;
|
||||
use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path
|
||||
inspect_all_partitions inspect_partition
|
||||
inspect_operating_systems mount_operating_system inspect_in_detail);
|
||||
use Sys::Guestfs::Lib qw(open_guest);
|
||||
use Pod::Usage;
|
||||
use Getopt::Long;
|
||||
use Data::Dumper;
|
||||
use File::Temp qw/tempfile/;
|
||||
use File::Basename;
|
||||
use XML::Writer;
|
||||
use String::ShellQuote qw(shell_quote);
|
||||
use Locale::TextDomain 'libguestfs';
|
||||
|
||||
# Optional:
|
||||
eval "use YAML::Any;";
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
virt-inspector - Display OS version, kernel, drivers, mount points, applications, etc. in a virtual machine
|
||||
virt-inspector - Display operating system version and other information about a virtual machine
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
@@ -47,13 +42,11 @@ virt-inspector - Display OS version, kernel, drivers, mount points, applications
|
||||
|
||||
=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.
|
||||
B<virt-inspector> examines a virtual machine or disk image and tries
|
||||
to determine the version of the operating system and other information
|
||||
about the virtual machine.
|
||||
|
||||
Virt-inspector can produce output in several formats, including a
|
||||
readable text report, and XML for feeding into other programs.
|
||||
Virt-inspector produces XML output for feeding into other programs.
|
||||
|
||||
In the normal usage, use C<virt-inspector domname> where C<domname> is
|
||||
the libvirt domain (see: C<virsh list --all>).
|
||||
@@ -122,72 +115,6 @@ parameter is ignored.
|
||||
If working with untrusted raw-format guest disk images, you should
|
||||
ensure the format is always specified.
|
||||
|
||||
=cut
|
||||
|
||||
my $output = "text";
|
||||
|
||||
=back
|
||||
|
||||
The following options select the output format. Use only one of them.
|
||||
The default is a readable text report.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<--text> (default)
|
||||
|
||||
Plain text report.
|
||||
|
||||
=item B<--none>
|
||||
|
||||
Produce no output at all.
|
||||
|
||||
=item B<--xml>
|
||||
|
||||
If you select I<--xml> then you get XML output which can be fed
|
||||
to other programs.
|
||||
|
||||
=item B<--yaml>
|
||||
|
||||
If you select I<--yaml> then you get YAML output which can be fed
|
||||
to other programs.
|
||||
|
||||
=item B<--perl>
|
||||
|
||||
If you select I<--perl> then you get Perl structures output which
|
||||
can be used directly in another Perl program.
|
||||
|
||||
=item B<--fish>
|
||||
|
||||
=item B<--ro-fish>
|
||||
|
||||
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:
|
||||
|
||||
guestfish $(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.
|
||||
|
||||
=item B<--query>
|
||||
|
||||
In "query mode" we answer common questions about the guest, such
|
||||
as whether it is fullvirt or needs a Xen hypervisor to run.
|
||||
|
||||
See section I<QUERY MODE> below.
|
||||
|
||||
=cut
|
||||
|
||||
my $windows_registry;
|
||||
|
||||
=item B<--windows-registry>
|
||||
|
||||
This flag is ignored for compatibility with earlier releases of the
|
||||
software.
|
||||
|
||||
In this version, if L<Win::Hivex(3)> is available, then we attempt to
|
||||
parse information out of the Registry for any Windows guest.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
@@ -196,17 +123,6 @@ GetOptions ("help|?" => \$help,
|
||||
"version" => \$version,
|
||||
"connect|c=s" => \$uri,
|
||||
"format=s" => \$format,
|
||||
"text" => sub { $output = "text" },
|
||||
"none" => sub { $output = "none" },
|
||||
"xml" => sub { $output = "xml" },
|
||||
"yaml" => sub { $output = "yaml" },
|
||||
"perl" => sub { $output = "perl" },
|
||||
"fish" => sub { $output = "fish" },
|
||||
"guestfish" => sub { $output = "fish" },
|
||||
"ro-fish" => sub { $output = "ro-fish" },
|
||||
"ro-guestfish" => sub { $output = "ro-fish" },
|
||||
"query" => sub { $output = "query" },
|
||||
"windows-registry" => \$windows_registry,
|
||||
) or pod2usage (2);
|
||||
pod2usage (1) if $help;
|
||||
if ($version) {
|
||||
@@ -217,663 +133,220 @@ if ($version) {
|
||||
}
|
||||
pod2usage (__"virt-inspector: no image or VM names given") if @ARGV == 0;
|
||||
|
||||
my $rw = 0;
|
||||
|
||||
# XXX This is a bug: Originally we intended to open the guest with
|
||||
# rw=>1 in order to tell Sys::Guestfs::Lib that we should disallow
|
||||
# active domains. However this also has the effect of opening the
|
||||
# disk image in write mode, and in any case we don't use this option
|
||||
# in guestfish any more since we moved all the inspection code into
|
||||
# the core library. We should drop the fish output modes completely.
|
||||
$rw = 1 if $output eq "fish";
|
||||
|
||||
my $g;
|
||||
my @images;
|
||||
if ($uri) {
|
||||
my ($conn, $dom);
|
||||
($g, $conn, $dom, @images) =
|
||||
open_guest (\@ARGV, rw => $rw, address => $uri, format => $format);
|
||||
} else {
|
||||
my ($conn, $dom);
|
||||
($g, $conn, $dom, @images) =
|
||||
open_guest (\@ARGV, rw => $rw, format => $format);
|
||||
}
|
||||
my @args = (\@ARGV);
|
||||
push @args, address => $uri if defined $uri;
|
||||
push @args, format => $format if defined $format;
|
||||
my $g = open_guest (@args);
|
||||
|
||||
$g->launch ();
|
||||
|
||||
=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.
|
||||
There is a RELAX-NG schema for this XML in the file
|
||||
I<virt-inspector.rng> which normally ships with virt-inspector, or can
|
||||
be found in the source.
|
||||
|
||||
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:
|
||||
|
||||
guestfish $(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 @partitions = get_partitions ($g);
|
||||
|
||||
# Now query each one to build up a picture of what's in it.
|
||||
my %fses =
|
||||
inspect_all_partitions ($g, \@partitions);
|
||||
|
||||
#print "fses -----------\n";
|
||||
#print Dumper(\%fses);
|
||||
|
||||
my $oses = inspect_operating_systems ($g, \%fses);
|
||||
|
||||
#print "oses -----------\n";
|
||||
#print Dumper($oses);
|
||||
|
||||
# Mount up the disks so we can check for applications
|
||||
# and kernels. Skip this if the output is "*fish" because
|
||||
# we don't need to know.
|
||||
|
||||
if ($output !~ /.*fish$/) {
|
||||
my $root_dev;
|
||||
foreach $root_dev (sort keys %$oses) {
|
||||
my $os = $oses->{$root_dev};
|
||||
mount_operating_system ($g, $os);
|
||||
inspect_in_detail ($g, $os);
|
||||
$g->umount_all ();
|
||||
}
|
||||
my @roots = $g->inspect_os ();
|
||||
if (@roots == 0) {
|
||||
die __x("{prog}: 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 libguestfs.\n\nIf you feel this is an error, please file a bug report including as much\ninformation about the disk image as possible.\n",
|
||||
prog => basename ($0));
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Output.
|
||||
# Start the XML output.
|
||||
my $xml = new XML::Writer (DATA_MODE => 1, DATA_INDENT => 2);
|
||||
|
||||
if ($output eq "fish" || $output eq "ro-fish") {
|
||||
my @osdevs = keys %$oses;
|
||||
# This only works if there is a single OS.
|
||||
die __"--fish output is only possible with a single OS\n" if @osdevs != 1;
|
||||
$xml->startTag ("operatingsystems");
|
||||
|
||||
my $root_dev = $osdevs[0];
|
||||
|
||||
if ($output eq "ro-fish") {
|
||||
print "--ro ";
|
||||
my $root;
|
||||
foreach $root (@roots) {
|
||||
my %fses = $g->inspect_get_mountpoints ($root);
|
||||
my @fses = sort { length $a <=> length $b } keys %fses;
|
||||
foreach (@fses) {
|
||||
$g->mount_ro ($fses{$_}, $_);
|
||||
}
|
||||
|
||||
foreach (@images) {
|
||||
unless (defined $_->[1]) {
|
||||
printf "-a %s ", shell_quote ($_->[0]);
|
||||
} else {
|
||||
printf "--format %s -a %s ",
|
||||
shell_quote ($_->[1]), shell_quote ($_->[0]);
|
||||
}
|
||||
}
|
||||
$xml->startTag ("operatingsystem");
|
||||
|
||||
my $mounts = $oses->{$root_dev}->{mounts};
|
||||
# Have to mount / first. Luckily '/' is early in the ASCII
|
||||
# character set, so this should be OK.
|
||||
foreach (sort keys %$mounts) {
|
||||
if ($_ ne "swap" && $_ ne "none") {
|
||||
printf "-m %s ", shell_quote ("$mounts->{$_}:$_");
|
||||
}
|
||||
}
|
||||
print "\n"
|
||||
}
|
||||
# Basic OS fields.
|
||||
$xml->dataElement (root => $root);
|
||||
|
||||
# Perl output.
|
||||
elsif ($output eq "perl") {
|
||||
print Dumper(%$oses);
|
||||
}
|
||||
my ($s, $distro, $major_version);
|
||||
$s = $g->inspect_get_type ($root);
|
||||
$xml->dataElement (name => $s) if $s ne "unknown";
|
||||
$s = $g->inspect_get_arch ($root);
|
||||
$xml->dataElement (arch => $s) if $s ne "unknown";
|
||||
$distro = $g->inspect_get_distro ($root);
|
||||
$xml->dataElement (distro => $distro) if $distro ne "unknown";
|
||||
$s = $g->inspect_get_product_name ($root);
|
||||
$xml->dataElement (product_name => $s) if $s ne "unknown";
|
||||
$major_version = $g->inspect_get_major_version ($root);
|
||||
$xml->dataElement (major_version => $major_version);
|
||||
$s = $g->inspect_get_minor_version ($root);
|
||||
$xml->dataElement (minor_version => $s);
|
||||
|
||||
# YAML output
|
||||
elsif ($output eq "yaml") {
|
||||
die __"virt-inspector: no YAML support, try installing perl-YAML or libyaml-perl\n"
|
||||
unless exists $INC{"YAML/Any.pm"};
|
||||
eval {
|
||||
$s = $g->inspect_get_windows_systemroot ($root);
|
||||
$xml->dataElement (windows_systemroot => $s);
|
||||
};
|
||||
|
||||
print Dump(%$oses);
|
||||
}
|
||||
# Mountpoints.
|
||||
output_mountpoints ($root, \@fses, \%fses);
|
||||
|
||||
# Plain text output (the default).
|
||||
elsif ($output eq "text") {
|
||||
output_text ();
|
||||
}
|
||||
# Filesystems.
|
||||
output_filesystems ($root);
|
||||
|
||||
# XML output.
|
||||
elsif ($output eq "xml") {
|
||||
output_xml ();
|
||||
}
|
||||
|
||||
# Query mode.
|
||||
elsif ($output eq "query") {
|
||||
output_query ();
|
||||
}
|
||||
|
||||
sub output_text
|
||||
{
|
||||
output_text_os ($oses->{$_}) foreach sort keys %$oses;
|
||||
}
|
||||
|
||||
sub output_text_os
|
||||
{
|
||||
my $os = shift;
|
||||
|
||||
print $os->{os}, " " if exists $os->{os};
|
||||
print $os->{distro}, " " if exists $os->{distro};
|
||||
print $os->{arch}, " " if exists $os->{arch};
|
||||
print $os->{major_version} if exists $os->{major_version};
|
||||
print ".", $os->{minor_version} if exists $os->{minor_version};
|
||||
print " (", $os->{product_name}, ")" if exists $os->{product_name};
|
||||
print " ";
|
||||
print "on ", $os->{root_device}, ":\n";
|
||||
|
||||
print __" Mountpoints:\n";
|
||||
my $mounts = $os->{mounts};
|
||||
foreach (sort keys %$mounts) {
|
||||
printf " %-30s %s\n", $mounts->{$_}, $_
|
||||
}
|
||||
|
||||
print __" Filesystems:\n";
|
||||
my $filesystems = $os->{filesystems};
|
||||
foreach (sort keys %$filesystems) {
|
||||
print " $_:\n";
|
||||
print " label: $filesystems->{$_}{label}\n"
|
||||
if exists $filesystems->{$_}{label};
|
||||
print " UUID: $filesystems->{$_}{uuid}\n"
|
||||
if exists $filesystems->{$_}{uuid};
|
||||
print " type: $filesystems->{$_}{fstype}\n"
|
||||
if exists $filesystems->{$_}{fstype};
|
||||
print " content: $filesystems->{$_}{content}\n"
|
||||
if exists $filesystems->{$_}{content};
|
||||
}
|
||||
|
||||
if (exists $os->{modprobe_aliases}) {
|
||||
my %aliases = %{$os->{modprobe_aliases}};
|
||||
my @keys = sort keys %aliases;
|
||||
if (@keys) {
|
||||
print __" Modprobe aliases:\n";
|
||||
foreach (@keys) {
|
||||
printf " %-30s %s\n", $_, $aliases{$_}->{modulename}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exists $os->{initrd_modules}) {
|
||||
my %modvers = %{$os->{initrd_modules}};
|
||||
my @keys = sort keys %modvers;
|
||||
if (@keys) {
|
||||
print __" Initrd modules:\n";
|
||||
foreach (@keys) {
|
||||
my @modules = @{$modvers{$_}};
|
||||
print " $_:\n";
|
||||
print " $_\n" foreach @modules;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print __" Applications:\n";
|
||||
my @apps = @{$os->{apps}};
|
||||
foreach (@apps) {
|
||||
print " $_->{name} $_->{version}\n"
|
||||
}
|
||||
|
||||
if ($os->{kernels}) {
|
||||
print __" Kernels:\n";
|
||||
my @kernels = @{$os->{kernels}};
|
||||
foreach (@kernels) {
|
||||
print " $_->{version} ($_->{arch})\n";
|
||||
my @modules = @{$_->{modules}};
|
||||
foreach (@modules) {
|
||||
print " $_\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exists $os->{root}->{registry}) {
|
||||
print __" Windows Registry entries:\n";
|
||||
# These are just lumps of text - dump them out.
|
||||
foreach (@{$os->{root}->{registry}}) {
|
||||
print "$_\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub output_xml
|
||||
{
|
||||
my $xml = new XML::Writer(DATA_MODE => 1, DATA_INDENT => 2);
|
||||
|
||||
$xml->startTag("operatingsystems");
|
||||
output_xml_os ($oses->{$_}, $xml) foreach sort keys %$oses;
|
||||
$xml->endTag("operatingsystems");
|
||||
|
||||
$xml->end();
|
||||
}
|
||||
|
||||
sub output_xml_os
|
||||
{
|
||||
my ($os, $xml) = @_;
|
||||
|
||||
$xml->startTag("operatingsystem");
|
||||
|
||||
foreach ( [ "name" => "os" ],
|
||||
[ "distro" => "distro" ],
|
||||
[ "product_name" => "product_name" ],
|
||||
[ "arch" => "arch" ],
|
||||
[ "major_version" => "major_version" ],
|
||||
[ "minor_version" => "minor_version" ],
|
||||
[ "package_format" => "package_format" ],
|
||||
[ "package_management" => "package_management" ],
|
||||
[ "root" => "root_device" ] ) {
|
||||
$xml->dataElement($_->[0], $os->{$_->[1]}) if exists $os->{$_->[1]};
|
||||
}
|
||||
|
||||
$xml->startTag("mountpoints");
|
||||
my $mounts = $os->{mounts};
|
||||
foreach (sort keys %$mounts) {
|
||||
$xml->dataElement("mountpoint", $_, "dev" => $mounts->{$_});
|
||||
}
|
||||
$xml->endTag("mountpoints");
|
||||
|
||||
$xml->startTag("filesystems");
|
||||
my $filesystems = $os->{filesystems};
|
||||
foreach (sort keys %$filesystems) {
|
||||
$xml->startTag("filesystem", "dev" => $_);
|
||||
|
||||
foreach my $field ( [ "label" => "label" ],
|
||||
[ "uuid" => "uuid" ],
|
||||
[ "type" => "fstype" ],
|
||||
[ "content" => "content" ],
|
||||
[ "spec" => "spec" ] ) {
|
||||
$xml->dataElement($field->[0], $filesystems->{$_}{$field->[1]})
|
||||
if exists $filesystems->{$_}{$field->[1]};
|
||||
}
|
||||
|
||||
$xml->endTag("filesystem");
|
||||
}
|
||||
$xml->endTag("filesystems");
|
||||
|
||||
if (exists $os->{modprobe_aliases}) {
|
||||
my %aliases = %{$os->{modprobe_aliases}};
|
||||
my @keys = sort keys %aliases;
|
||||
if (@keys) {
|
||||
$xml->startTag("modprobealiases");
|
||||
foreach (@keys) {
|
||||
$xml->startTag("alias", "device" => $_);
|
||||
|
||||
foreach my $field ( [ "modulename" => "modulename" ],
|
||||
[ "augeas" => "augeas" ],
|
||||
[ "file" => "file" ] ) {
|
||||
$xml->dataElement($field->[0], $aliases{$_}->{$field->[1]});
|
||||
}
|
||||
|
||||
$xml->endTag("alias");
|
||||
}
|
||||
$xml->endTag("modprobealiases");
|
||||
}
|
||||
}
|
||||
|
||||
if (exists $os->{initrd_modules}) {
|
||||
my %modvers = %{$os->{initrd_modules}};
|
||||
my @keys = sort keys %modvers;
|
||||
if (@keys) {
|
||||
$xml->startTag("initrds");
|
||||
foreach (@keys) {
|
||||
my @modules = @{$modvers{$_}};
|
||||
$xml->startTag("initrd", "version" => $_);
|
||||
$xml->dataElement("module", $_) foreach @modules;
|
||||
$xml->endTag("initrd");
|
||||
}
|
||||
$xml->endTag("initrds");
|
||||
}
|
||||
}
|
||||
|
||||
$xml->startTag("applications");
|
||||
my @apps = @{$os->{apps}};
|
||||
foreach (@apps) {
|
||||
$xml->startTag("application");
|
||||
$xml->dataElement("name", $_->{name});
|
||||
$xml->dataElement("epoch", $_->{epoch}) if defined $_->{epoch};
|
||||
$xml->dataElement("version", $_->{version});
|
||||
$xml->dataElement("release", $_->{release});
|
||||
$xml->dataElement("arch", $_->{arch});
|
||||
$xml->endTag("application");
|
||||
}
|
||||
$xml->endTag("applications");
|
||||
|
||||
if(defined($os->{boot}) && defined($os->{boot}->{configs})) {
|
||||
my $default = $os->{boot}->{default};
|
||||
my $configs = $os->{boot}->{configs};
|
||||
|
||||
$xml->startTag("boot");
|
||||
for(my $i = 0; $i < scalar(@$configs); $i++) {
|
||||
my $config = $configs->[$i];
|
||||
|
||||
my @attrs = ();
|
||||
push(@attrs, ("default" => 1)) if($default == $i);
|
||||
$xml->startTag("config", @attrs);
|
||||
$xml->dataElement("title", $config->{title});
|
||||
$xml->dataElement("kernel", $config->{kernel}->{version})
|
||||
if(defined($config->{kernel}));
|
||||
$xml->dataElement("cmdline", $config->{cmdline})
|
||||
if(defined($config->{cmdline}));
|
||||
$xml->endTag("config");
|
||||
}
|
||||
$xml->endTag("boot");
|
||||
}
|
||||
|
||||
if ($os->{kernels}) {
|
||||
$xml->startTag("kernels");
|
||||
my @kernels = @{$os->{kernels}};
|
||||
foreach (@kernels) {
|
||||
$xml->startTag("kernel",
|
||||
"version" => $_->{version},
|
||||
"arch" => $_->{arch});
|
||||
$xml->startTag("modules");
|
||||
my @modules = @{$_->{modules}};
|
||||
foreach (@modules) {
|
||||
$xml->dataElement("module", $_);
|
||||
}
|
||||
$xml->endTag("modules");
|
||||
$xml->dataElement("path", $_->{path}) if(defined($_->{path}));
|
||||
$xml->dataElement("package", $_->{package}) if(defined($_->{package}));
|
||||
$xml->endTag("kernel");
|
||||
}
|
||||
$xml->endTag("kernels");
|
||||
}
|
||||
|
||||
if (exists $os->{root}->{registry}) {
|
||||
$xml->startTag("windowsregistryentries");
|
||||
# These are just lumps of text - dump them out.
|
||||
foreach (@{$os->{root}->{registry}}) {
|
||||
$xml->dataElement("windowsregistryentry", $_);
|
||||
}
|
||||
$xml->endTag("windowsregistryentries");
|
||||
}
|
||||
# Package format / management and applications.
|
||||
output_applications ($root, $distro, $major_version);
|
||||
|
||||
$xml->endTag("operatingsystem");
|
||||
|
||||
$g->umount_all ();
|
||||
}
|
||||
|
||||
=head1 QUERY MODE
|
||||
# End the XML output.
|
||||
$xml->endTag ("operatingsystems");
|
||||
$xml->end ();
|
||||
|
||||
When you use C<virt-inspector --query>, the output is a series of
|
||||
lines of the form:
|
||||
|
||||
windows=no
|
||||
linux=yes
|
||||
fullvirt=yes
|
||||
xen_pv_drivers=no
|
||||
|
||||
(each answer is usually C<yes> or C<no>, or the line is completely
|
||||
missing if we could not determine the answer at all).
|
||||
|
||||
If the guest is multiboot, you can get apparently conflicting answers
|
||||
(eg. C<windows=yes> and C<linux=yes>, or a guest which is both
|
||||
fullvirt and has a Xen PV kernel). This is normal, and just means
|
||||
that the guest can do both things, although it might require operator
|
||||
intervention such as selecting a boot option when the guest is
|
||||
booting.
|
||||
|
||||
This section describes the full range of answers possible.
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query
|
||||
sub output_mountpoints
|
||||
{
|
||||
output_query_windows ();
|
||||
output_query_linux ();
|
||||
output_query_rhel ();
|
||||
output_query_fedora ();
|
||||
output_query_debian ();
|
||||
output_query_fullvirt ();
|
||||
output_query_xen_domU_kernel ();
|
||||
output_query_xen_pv_drivers ();
|
||||
output_query_virtio_drivers ();
|
||||
output_query_kernel_arch ();
|
||||
output_query_userspace_arch ();
|
||||
}
|
||||
local $_;
|
||||
my $root = shift;
|
||||
my $fskeys = shift;
|
||||
my $fshash = shift;
|
||||
|
||||
=item windows=(yes|no)
|
||||
|
||||
Answer C<yes> if Microsoft Windows is installed in the guest.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_windows
|
||||
{
|
||||
my $windows = "no";
|
||||
foreach my $os (keys %$oses) {
|
||||
$windows="yes" if $oses->{$os}->{os} eq "windows";
|
||||
$xml->startTag ("mountpoints");
|
||||
foreach (@$fskeys) {
|
||||
$xml->dataElement ("mountpoint", $_, dev => $fshash->{$_});
|
||||
}
|
||||
print "windows=$windows\n";
|
||||
$xml->endTag ("mountpoints");
|
||||
}
|
||||
|
||||
=item linux=(yes|no)
|
||||
|
||||
Answer C<yes> if a Linux kernel is installed in the guest.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_linux
|
||||
sub output_filesystems
|
||||
{
|
||||
my $linux = "no";
|
||||
foreach my $os (keys %$oses) {
|
||||
$linux="yes" if $oses->{$os}->{os} eq "linux";
|
||||
local $_;
|
||||
my $root = shift;
|
||||
|
||||
$xml->startTag ("filesystems");
|
||||
|
||||
my @fses = $g->inspect_get_filesystems ($root);
|
||||
foreach (@fses) {
|
||||
$xml->startTag ("filesystem", dev => $_);
|
||||
|
||||
eval {
|
||||
my $type = $g->vfs_type ($_);
|
||||
$xml->dataElement (type => $type)
|
||||
if defined $type && $type ne "";
|
||||
};
|
||||
|
||||
eval {
|
||||
my $label = $g->vfs_label ($_);
|
||||
$xml->dataElement (label => $label)
|
||||
if defined $label && $label ne "";
|
||||
};
|
||||
|
||||
eval {
|
||||
my $uuid = $g->vfs_uuid ($_);
|
||||
$xml->dataElement (uuid => $uuid)
|
||||
if defined $uuid && $uuid ne "";
|
||||
};
|
||||
|
||||
$xml->endTag ("filesystem");
|
||||
}
|
||||
print "linux=$linux\n";
|
||||
|
||||
$xml->endTag ("filesystems");
|
||||
}
|
||||
|
||||
=item rhel=(yes|no)
|
||||
|
||||
Answer C<yes> if the guest contains Red Hat Enterprise Linux.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_rhel
|
||||
sub output_applications
|
||||
{
|
||||
my $rhel = "no";
|
||||
foreach my $os (keys %$oses) {
|
||||
$rhel="yes" if ($oses->{$os}->{os} eq "linux" &&
|
||||
$oses->{$os}->{distro} eq "rhel");
|
||||
}
|
||||
print "rhel=$rhel\n";
|
||||
}
|
||||
local $_;
|
||||
my $root = shift;
|
||||
my $distro = shift;
|
||||
my $major_version = shift;
|
||||
|
||||
=item fedora=(yes|no)
|
||||
|
||||
Answer C<yes> if the guest contains the Fedora Linux distribution.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_fedora
|
||||
{
|
||||
my $fedora = "no";
|
||||
foreach my $os (keys %$oses) {
|
||||
$fedora="yes" if $oses->{$os}->{os} eq "linux" && $oses->{$os}->{distro} eq "fedora";
|
||||
}
|
||||
print "fedora=$fedora\n";
|
||||
}
|
||||
|
||||
=item debian=(yes|no)
|
||||
|
||||
Answer C<yes> if the guest contains the Debian Linux distribution.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_debian
|
||||
{
|
||||
my $debian = "no";
|
||||
foreach my $os (keys %$oses) {
|
||||
$debian="yes" if $oses->{$os}->{os} eq "linux" && $oses->{$os}->{distro} eq "debian";
|
||||
}
|
||||
print "debian=$debian\n";
|
||||
}
|
||||
|
||||
=item fullvirt=(yes|no)
|
||||
|
||||
Answer C<yes> if there is at least one operating system kernel
|
||||
installed in the guest which runs fully virtualized. Such a guest
|
||||
would require a hypervisor which supports full system virtualization.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_fullvirt
|
||||
{
|
||||
# The assumption is full-virt, unless all installed kernels
|
||||
# are identified as paravirt.
|
||||
# XXX Fails on Windows guests.
|
||||
foreach my $os (keys %$oses) {
|
||||
foreach my $kernel (@{$oses->{$os}->{kernels}}) {
|
||||
my $is_pv = $kernel->{version} =~ m/xen/;
|
||||
unless ($is_pv) {
|
||||
print "fullvirt=yes\n";
|
||||
return;
|
||||
# Based on the distro, take a guess at the package format
|
||||
# and package management.
|
||||
my ($package_format, $package_management);
|
||||
if (defined $distro) {
|
||||
if ($distro eq "debian") {
|
||||
$package_format = "dpkg";
|
||||
$package_management = "apt";
|
||||
}
|
||||
elsif ($distro eq "fedora") {
|
||||
$package_format = "rpm";
|
||||
$package_management = "yum";
|
||||
}
|
||||
elsif ($distro =~ /redhat/ || $distro =~ /rhel/) {
|
||||
if ($major_version >= 5) {
|
||||
$package_format = "rpm";
|
||||
$package_management = "yum";
|
||||
} else {
|
||||
$package_format = "rpm";
|
||||
$package_management = "up2date";
|
||||
}
|
||||
}
|
||||
# else unknown.
|
||||
}
|
||||
|
||||
$xml->dataElement (package_format => $package_format)
|
||||
if defined $package_format;
|
||||
$xml->dataElement (package_management => $package_management)
|
||||
if defined $package_management;
|
||||
|
||||
# Do we know how to get a list of applications?
|
||||
if (defined $package_format) {
|
||||
if ($package_format eq "rpm") {
|
||||
output_applications_rpm ($root);
|
||||
}
|
||||
# else no we don't.
|
||||
}
|
||||
print "fullvirt=no\n";
|
||||
}
|
||||
|
||||
=item xen_domU_kernel=(yes|no)
|
||||
|
||||
Answer C<yes> if there is at least one Linux kernel installed in
|
||||
the guest which is compiled as a Xen DomU (a Xen paravirtualized
|
||||
guest).
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_xen_domU_kernel
|
||||
sub output_applications_rpm
|
||||
{
|
||||
foreach my $os (keys %$oses) {
|
||||
foreach my $kernel (@{$oses->{$os}->{kernels}}) {
|
||||
my $is_xen = $kernel->{version} =~ m/xen/;
|
||||
if ($is_xen) {
|
||||
print "xen_domU_kernel=yes\n";
|
||||
return;
|
||||
local $_;
|
||||
my $root = shift;
|
||||
|
||||
# Previous virt-inspector ran the 'rpm' program from the guest.
|
||||
# This is insecure, and unnecessary because we can get the same
|
||||
# information directly from the RPM database.
|
||||
|
||||
my @applications;
|
||||
|
||||
eval {
|
||||
my ($fh, $filename) = tempfile (UNLINK => 1);
|
||||
my $fddev = "/dev/fd/" . fileno ($fh);
|
||||
$g->download ("/var/lib/rpm/Name", $fddev);
|
||||
close $fh or die "close: $!";
|
||||
|
||||
# Read the database with the Berkeley DB dump tool.
|
||||
my $cmd = "db_dump -p '$filename'";
|
||||
open PIPE, "$cmd |" or die "close: $!";
|
||||
while (<PIPE>) {
|
||||
chomp;
|
||||
last if /^HEADER=END$/;
|
||||
}
|
||||
while (<PIPE>) {
|
||||
chomp;
|
||||
last if /^DATA=END$/;
|
||||
|
||||
# First character on each data line is a space.
|
||||
if (length $_ > 0 && substr ($_, 0, 1) eq ' ') {
|
||||
$_ = substr ($_, 1);
|
||||
}
|
||||
# Name should never contain non-printable chars.
|
||||
die "name contains non-printable chars" if /\\/;
|
||||
push @applications, $_;
|
||||
|
||||
$_ = <PIPE>; # discard value
|
||||
}
|
||||
}
|
||||
print "xen_domU_kernel=no\n";
|
||||
}
|
||||
|
||||
=item xen_pv_drivers=(yes|no)
|
||||
|
||||
Answer C<yes> if the guest has Xen paravirtualized drivers installed
|
||||
(usually the kernel itself will be fully virtualized, but the PV
|
||||
drivers have been installed by the administrator for performance
|
||||
reasons).
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_xen_pv_drivers
|
||||
{
|
||||
foreach my $os (keys %$oses) {
|
||||
foreach my $kernel (@{$oses->{$os}->{kernels}}) {
|
||||
foreach my $module (@{$kernel->{modules}}) {
|
||||
if ($module =~ m/xen-/) {
|
||||
print "xen_pv_drivers=yes\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
close PIPE or die "close: $!";
|
||||
};
|
||||
if (!$@ && @applications > 0) {
|
||||
@applications = sort @applications;
|
||||
$xml->startTag ("applications");
|
||||
foreach (@applications) {
|
||||
$xml->startTag ("application");
|
||||
$xml->dataElement (name => $_);
|
||||
$xml->endTag ("application");
|
||||
}
|
||||
}
|
||||
print "xen_pv_drivers=no\n";
|
||||
}
|
||||
|
||||
=item virtio_drivers=(yes|no)
|
||||
|
||||
Answer C<yes> if the guest has virtio paravirtualized drivers
|
||||
installed. Virtio drivers are commonly used to improve the
|
||||
performance of KVM.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_virtio_drivers
|
||||
{
|
||||
foreach my $os (keys %$oses) {
|
||||
foreach my $kernel (@{$oses->{$os}->{kernels}}) {
|
||||
foreach my $module (@{$kernel->{modules}}) {
|
||||
if ($module =~ m/virtio_/) {
|
||||
print "virtio_drivers=yes\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print "virtio_drivers=no\n";
|
||||
}
|
||||
|
||||
=item userspace_arch=(x86_64|...)
|
||||
|
||||
Print the architecture of userspace.
|
||||
|
||||
NB. For multi-boot VMs this can print several lines.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_userspace_arch
|
||||
{
|
||||
my %arches;
|
||||
|
||||
foreach my $os (keys %$oses) {
|
||||
$arches{$oses->{$os}->{arch}} = 1 if exists $oses->{$os}->{arch};
|
||||
}
|
||||
|
||||
foreach (sort keys %arches) {
|
||||
print "userspace_arch=$_\n";
|
||||
$xml->endTag ("applications");
|
||||
}
|
||||
}
|
||||
|
||||
=item kernel_arch=(x86_64|...)
|
||||
|
||||
Print the architecture of the kernel.
|
||||
|
||||
NB. For multi-boot VMs this can print several lines.
|
||||
|
||||
=cut
|
||||
|
||||
sub output_query_kernel_arch
|
||||
{
|
||||
my %arches;
|
||||
|
||||
foreach my $os (keys %$oses) {
|
||||
foreach my $kernel (@{$oses->{$os}->{kernels}}) {
|
||||
$arches{$kernel->{arch}} = 1 if exists $kernel->{arch};
|
||||
}
|
||||
}
|
||||
|
||||
foreach (sort keys %arches) {
|
||||
print "kernel_arch=$_\n";
|
||||
}
|
||||
}
|
||||
|
||||
=back
|
||||
|
||||
=head1 SHELL QUOTING
|
||||
|
||||
Libvirt guest names can contain arbitrary characters, some of which
|
||||
@@ -892,13 +365,21 @@ L<http://libguestfs.org/>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
|
||||
|
||||
=item *
|
||||
|
||||
Matthew Booth L<mbooth@redhat.com>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 2009 Red Hat Inc.
|
||||
Copyright (C) 2010 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
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<element name="operatingsystem">
|
||||
<interleave>
|
||||
|
||||
<!-- required fields for an operating system -->
|
||||
<optional><element name="root"><text/></element></optional>
|
||||
<element name="name">
|
||||
<choice>
|
||||
<value>linux</value>
|
||||
@@ -31,23 +31,18 @@
|
||||
</choice>
|
||||
</element>
|
||||
<element name="arch"><text/></element>
|
||||
<element name="root"><text/></element>
|
||||
|
||||
<!-- optional fields for an operating system -->
|
||||
<optional><element name="distro"><text/></element></optional>
|
||||
<optional><element name="product_name"><text/></element></optional>
|
||||
<optional><element name="major_version"><text/></element></optional>
|
||||
<optional><element name="minor_version"><text/></element></optional>
|
||||
<element name="major_version"><text/></element>
|
||||
<element name="minor_version"><text/></element>
|
||||
<optional><element name="windows_systemroot"><text/></element></optional>
|
||||
|
||||
<optional><element name="package_format"><text/></element></optional>
|
||||
<optional><element name="package_management"><text/></element></optional>
|
||||
|
||||
<ref name="mountpoints"/>
|
||||
<ref name="filesystems"/>
|
||||
<optional><ref name="applications"/></optional>
|
||||
<optional><ref name="modprobealiases"/></optional>
|
||||
<optional><ref name="initrds"/></optional>
|
||||
<optional><ref name="kernels"/></optional>
|
||||
<optional><ref name="boot"/></optional>
|
||||
|
||||
</interleave>
|
||||
</element>
|
||||
@@ -74,11 +69,9 @@
|
||||
<element name="filesystem">
|
||||
<attribute name="dev"><text/></attribute>
|
||||
<interleave>
|
||||
<element name="type"><text/></element>
|
||||
<optional><element name="content"><text/></element></optional>
|
||||
<optional><element name="type"><text/></element></optional>
|
||||
<optional><element name="label"><text/></element></optional>
|
||||
<optional><element name="uuid"><text/></element></optional>
|
||||
<optional><element name="spec"><text/></element></optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
@@ -91,79 +84,6 @@
|
||||
<zeroOrMore>
|
||||
<element name="application">
|
||||
<element name="name"><text/></element>
|
||||
<optional><element name="epoch"><text/></element></optional>
|
||||
<element name="version"><text/></element>
|
||||
<element name="release"><text/></element>
|
||||
<element name="arch"><text/></element>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- contents of /etc/modprobe* -->
|
||||
<define name="modprobealiases">
|
||||
<element name="modprobealiases">
|
||||
<zeroOrMore>
|
||||
<element name="alias">
|
||||
<attribute name="device"><text/></attribute>
|
||||
<interleave>
|
||||
<element name="modulename"><text/></element>
|
||||
<optional><element name="augeas"><text/></element></optional>
|
||||
<element name="file"><text/></element>
|
||||
</interleave>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- initrd images found -->
|
||||
<define name="initrds">
|
||||
<element name="initrds">
|
||||
<zeroOrMore>
|
||||
<element name="initrd">
|
||||
<attribute name="version"><text/></attribute>
|
||||
<zeroOrMore>
|
||||
<element name="module"><text/></element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- boot configurations -->
|
||||
<define name="boot">
|
||||
<element name="boot">
|
||||
<zeroOrMore>
|
||||
<element name="config">
|
||||
<optional>
|
||||
<attribute name="default"><value>1</value></attribute>
|
||||
</optional>
|
||||
<interleave>
|
||||
<element name="title"><text/></element>
|
||||
<element name="kernel"><text/></element>
|
||||
<element name="cmdline"><text/></element>
|
||||
</interleave>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- kernels -->
|
||||
<define name="kernels">
|
||||
<element name="kernels">
|
||||
<zeroOrMore>
|
||||
<element name="kernel">
|
||||
<attribute name="version"><text/></attribute>
|
||||
<attribute name="arch"><text/></attribute>
|
||||
<interleave>
|
||||
<element name="modules">
|
||||
<zeroOrMore>
|
||||
<element name="module"><text/></element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
<optional><element name="path"><text/></element></optional>
|
||||
<optional><element name="package"><text/></element></optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
|
||||
Reference in New Issue
Block a user