Richard W.M. Jones
2009-Jul-29 09:40 UTC
[Libguestfs] [PATCH / discussion only] Add kernel and userspace arch detection to virt-inspector
This patch isn't quite finished. I also need to modify the virt-inspector "query mode" so that it can display the architecture. Nevertheless, text and XML output works for both Linux and Windows guests. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 75 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora -------------- next part -------------->From f8bcd6b7cc1aa404afdfb0312e31c9848b9c6c28 Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at trick.home.annexia.org> Date: Wed, 29 Jul 2009 09:48:08 +0100 Subject: [PATCH] inspector: Determine guest architecture. This commit adds kernel and userspace architecture detection (fully for Linux, partially for Windows). It adds an architecture for each kernel detected, and an architecture for each root (ie. userspace) found. --- TODO | 16 ----------- inspector/virt-inspector.pl | 8 ++++- perl/lib/Sys/Guestfs/Lib.pm | 64 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/TODO b/TODO index 291d220..dbfc3c8 100644 --- a/TODO +++ b/TODO @@ -182,22 +182,6 @@ Swap space Allow swap space from the guest to be used. Is it a good idea? -Query guest architecture ------------------------- - -Need a way to query a binary or library file for its architecture. -Using objdump or readelf? -What about non-ELF files (eg. Windows, BSD). - -To do this properly requires some serious logic, eg. to cover Linux -and Windows we'd need objdump and i686-pc-mingw32-objdump, and more to -cover a.out, COFF and 64 bit Windows. Therefore this cannot be done -inside the daemon, and should be done by a separate, external program -similar to virt-inspector. - -Probably we should go all the way and have virt-inspector able to -determine kernel and userspace architectures of guests. - Other initrd-* commands ----------------------- diff --git a/inspector/virt-inspector.pl b/inspector/virt-inspector.pl index 9148a48..bf525b0 100755 --- a/inspector/virt-inspector.pl +++ b/inspector/virt-inspector.pl @@ -357,6 +357,7 @@ sub output_text_os 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 " "; @@ -415,7 +416,7 @@ sub output_text_os print __" Kernels:\n"; my @kernels = @{$os->{kernels}}; foreach (@kernels) { - print " $_->{version}\n"; + print " $_->{version} ($_->{arch})\n"; my @modules = @{$_->{modules}}; foreach (@modules) { print " $_\n"; @@ -450,6 +451,7 @@ sub output_xml_os foreach ( [ "name" => "os" ], [ "distro" => "distro" ], + [ "arch" => "arch" ], [ "major_version" => "major_version" ], [ "minor_version" => "minor_version" ], [ "package_format" => "package_format" ], @@ -531,7 +533,9 @@ sub output_xml_os $xml->startTag("kernels"); my @kernels = @{$os->{kernels}}; foreach (@kernels) { - $xml->startTag("kernel", "version" => $_->{version}); + $xml->startTag("kernel", + "version" => $_->{version}, + "arch" => $_->{arch}); $xml->startTag("modules"); my @modules = @{$_->{modules}}; foreach (@modules) { diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm index 081b4b9..1e5638e 100644 --- a/perl/lib/Sys/Guestfs/Lib.pm +++ b/perl/lib/Sys/Guestfs/Lib.pm @@ -876,6 +876,17 @@ sub _check_linux_root } $r->{fstab} = \@fstab if @fstab; } + + # Determine the architecture of this root. + my $arch; + foreach ("/bin/bash", "/bin/ls", "/bin/echo", "/bin/rm", "/bin/sh") { + if ($g->is_file ($_)) { + $arch = file_architecture ($g, $_); + last; + } + } + + $r->{arch} = $arch if defined $arch; } # We only support NT. The control file /boot.ini contains a list of @@ -914,13 +925,30 @@ sub _check_windows_root if (defined $systemroot) { $r->{systemroot} = resolve_windows_path ($g, "/$systemroot"); - if (defined $r->{systemroot} && $use_windows_registry) { - _check_windows_registry ($g, $r, $r->{systemroot}); + if (defined $r->{systemroot}) { + _check_windows_arch ($g, $r, $r->{systemroot}); + if ($use_windows_registry) { + _check_windows_registry ($g, $r, $r->{systemroot}); + } } } } } +# Find Windows userspace arch. + +sub _check_windows_arch +{ + local $_; + my $g = shift; + my $r = shift; + my $systemroot = shift; + + my $cmd_exe + resolve_windows_path ($g, $r->{systemroot} . "/system32/cmd.exe"); + $r->{arch} = file_architecture ($g, $cmd_exe) if $cmd_exe; +} + sub _check_windows_registry { local $_; @@ -1034,6 +1062,10 @@ The C<\%os> hash contains the following keys (any can be omitted): Operating system type, eg. "linux", "windows". +=item arch + +Operating system userspace architecture, eg. "i386", "x86_64". + =item distro Operating system distribution, eg. "debian". @@ -1118,6 +1150,7 @@ sub _get_os_version if exists $r->{root}->{package_format}; $r->{package_management} = $r->{root}->{package_management} if exists $r->{root}->{package_management}; + $r->{arch} = $r->{root}->{arch} if exists $r->{root}->{arch}; } sub _assign_mount_points @@ -1267,6 +1300,24 @@ List of applications. List of kernels. +This is a hash of kernel version =E<gt> a hash with the following keys: + +=over 4 + +=item version + +Kernel version. + +=item arch + +Kernel architecture (eg. C<x86-64>). + +=item modules + +List of modules. + +=back + =item modprobe_aliases (For Linux VMs). @@ -1359,14 +1410,21 @@ sub _check_for_kernels # List modules. my @modules; - foreach ($g->find ("/lib/modules/$_")) { + my $any_module; + my $prefix = "/lib/modules/$_"; + foreach ($g->find ($prefix)) { if (m,/([^/]+)\.ko$, || m,([^/]+)\.o$,) { + $any_module = "$prefix$_" unless defined $any_module; push @modules, $1; } } $kernel{modules} = \@modules; + # Determine kernel architecture by looking at the arch + # of any kernel module. + $kernel{arch} = file_architecture ($g, $any_module); + push @kernels, \%kernel; } } -- 1.6.2.5
Richard W.M. Jones
2009-Jul-29 11:33 UTC
[Libguestfs] [PATCH] Add kernel and userspace arch detection to virt-inspector
The final version of this patch. Example output: $ ./inspector/run-inspector-locally --query CentOS5x32 windows=no linux=yes rhel=no fedora=no debian=no fullvirt=yes xen_domU_kernel=no xen_pv_drivers=yes virtio_drivers=yes kernel_arch=i386 userspace_arch=i386 $ ./inspector/run-inspector-locally --query Debian5x64 unknown filesystem /dev/hdc windows=no linux=yes rhel=no fedora=no debian=yes fullvirt=yes xen_domU_kernel=no xen_pv_drivers=no virtio_drivers=yes kernel_arch=x86_64 userspace_arch=x86_64 $ ./inspector/run-inspector-locally --query Win2003x32 windows=yes linux=no rhel=no fedora=no debian=no fullvirt=no xen_domU_kernel=no xen_pv_drivers=no virtio_drivers=no userspace_arch=i386 $ ./inspector/run-inspector-locally --xml F10x32 <operatingsystems> <operatingsystem> <name>linux</name> <distro>fedora</distro> <arch>i386</arch> <major_version>10</major_version> <package_format>rpm</package_format> <package_management>yum</package_management> <root>/dev/VolGroup00/LogVol00</root> [...] Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html -------------- next part -------------->From 06df9ec2413d7f5ae366bfab1b2177d7b3929837 Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at trick.home.annexia.org> Date: Wed, 29 Jul 2009 09:48:08 +0100 Subject: [PATCH] inspector: Determine guest architecture. This commit adds kernel and userspace architecture detection (fully for Linux, partially for Windows). It adds an architecture for each kernel detected, and an architecture for each root (ie. userspace) found. --- TODO | 16 ----------- inspector/virt-inspector.pl | 54 +++++++++++++++++++++++++++++++++++- perl/lib/Sys/Guestfs/Lib.pm | 64 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 113 insertions(+), 21 deletions(-) diff --git a/TODO b/TODO index 291d220..dbfc3c8 100644 --- a/TODO +++ b/TODO @@ -182,22 +182,6 @@ Swap space Allow swap space from the guest to be used. Is it a good idea? -Query guest architecture ------------------------- - -Need a way to query a binary or library file for its architecture. -Using objdump or readelf? -What about non-ELF files (eg. Windows, BSD). - -To do this properly requires some serious logic, eg. to cover Linux -and Windows we'd need objdump and i686-pc-mingw32-objdump, and more to -cover a.out, COFF and 64 bit Windows. Therefore this cannot be done -inside the daemon, and should be done by a separate, external program -similar to virt-inspector. - -Probably we should go all the way and have virt-inspector able to -determine kernel and userspace architectures of guests. - Other initrd-* commands ----------------------- diff --git a/inspector/virt-inspector.pl b/inspector/virt-inspector.pl index 9148a48..d2acf06 100755 --- a/inspector/virt-inspector.pl +++ b/inspector/virt-inspector.pl @@ -357,6 +357,7 @@ sub output_text_os 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 " "; @@ -415,7 +416,7 @@ sub output_text_os print __" Kernels:\n"; my @kernels = @{$os->{kernels}}; foreach (@kernels) { - print " $_->{version}\n"; + print " $_->{version} ($_->{arch})\n"; my @modules = @{$_->{modules}}; foreach (@modules) { print " $_\n"; @@ -450,6 +451,7 @@ sub output_xml_os foreach ( [ "name" => "os" ], [ "distro" => "distro" ], + [ "arch" => "arch" ], [ "major_version" => "major_version" ], [ "minor_version" => "minor_version" ], [ "package_format" => "package_format" ], @@ -531,7 +533,9 @@ sub output_xml_os $xml->startTag("kernels"); my @kernels = @{$os->{kernels}}; foreach (@kernels) { - $xml->startTag("kernel", "version" => $_->{version}); + $xml->startTag("kernel", + "version" => $_->{version}, + "arch" => $_->{arch}); $xml->startTag("modules"); my @modules = @{$_->{modules}}; foreach (@modules) { @@ -591,6 +595,8 @@ sub output_query output_query_xen_domU_kernel (); output_query_xen_pv_drivers (); output_query_virtio_drivers (); + output_query_kernel_arch (); + output_query_userspace_arch (); } =item windows=(yes|no) @@ -763,6 +769,50 @@ sub output_query_virtio_drivers 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"; + } +} + +=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 SEE ALSO diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm index 081b4b9..1e5638e 100644 --- a/perl/lib/Sys/Guestfs/Lib.pm +++ b/perl/lib/Sys/Guestfs/Lib.pm @@ -876,6 +876,17 @@ sub _check_linux_root } $r->{fstab} = \@fstab if @fstab; } + + # Determine the architecture of this root. + my $arch; + foreach ("/bin/bash", "/bin/ls", "/bin/echo", "/bin/rm", "/bin/sh") { + if ($g->is_file ($_)) { + $arch = file_architecture ($g, $_); + last; + } + } + + $r->{arch} = $arch if defined $arch; } # We only support NT. The control file /boot.ini contains a list of @@ -914,13 +925,30 @@ sub _check_windows_root if (defined $systemroot) { $r->{systemroot} = resolve_windows_path ($g, "/$systemroot"); - if (defined $r->{systemroot} && $use_windows_registry) { - _check_windows_registry ($g, $r, $r->{systemroot}); + if (defined $r->{systemroot}) { + _check_windows_arch ($g, $r, $r->{systemroot}); + if ($use_windows_registry) { + _check_windows_registry ($g, $r, $r->{systemroot}); + } } } } } +# Find Windows userspace arch. + +sub _check_windows_arch +{ + local $_; + my $g = shift; + my $r = shift; + my $systemroot = shift; + + my $cmd_exe + resolve_windows_path ($g, $r->{systemroot} . "/system32/cmd.exe"); + $r->{arch} = file_architecture ($g, $cmd_exe) if $cmd_exe; +} + sub _check_windows_registry { local $_; @@ -1034,6 +1062,10 @@ The C<\%os> hash contains the following keys (any can be omitted): Operating system type, eg. "linux", "windows". +=item arch + +Operating system userspace architecture, eg. "i386", "x86_64". + =item distro Operating system distribution, eg. "debian". @@ -1118,6 +1150,7 @@ sub _get_os_version if exists $r->{root}->{package_format}; $r->{package_management} = $r->{root}->{package_management} if exists $r->{root}->{package_management}; + $r->{arch} = $r->{root}->{arch} if exists $r->{root}->{arch}; } sub _assign_mount_points @@ -1267,6 +1300,24 @@ List of applications. List of kernels. +This is a hash of kernel version =E<gt> a hash with the following keys: + +=over 4 + +=item version + +Kernel version. + +=item arch + +Kernel architecture (eg. C<x86-64>). + +=item modules + +List of modules. + +=back + =item modprobe_aliases (For Linux VMs). @@ -1359,14 +1410,21 @@ sub _check_for_kernels # List modules. my @modules; - foreach ($g->find ("/lib/modules/$_")) { + my $any_module; + my $prefix = "/lib/modules/$_"; + foreach ($g->find ($prefix)) { if (m,/([^/]+)\.ko$, || m,([^/]+)\.o$,) { + $any_module = "$prefix$_" unless defined $any_module; push @modules, $1; } } $kernel{modules} = \@modules; + # Determine kernel architecture by looking at the arch + # of any kernel module. + $kernel{arch} = file_architecture ($g, $any_module); + push @kernels, \%kernel; } } -- 1.6.2.5