From 5ea43a9a97aef8d49057eaea5d64711646c4b271 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Tue, 29 Sep 2009 14:05:48 +0100 Subject: [PATCH] Update --- tools/virt-tools-get-key.pl | 2 +- tools/virt-tools-get-transport.pl | 316 ++++++++++++++++++++++++++++++++++++++ tools/virt-uname.pl | 6 +- 3 files changed, 321 insertions(+), 3 deletions(-) diff --git a/tools/virt-tools-get-key.pl b/tools/virt-tools-get-key.pl index 6885256..9691469 100755 --- a/tools/virt-tools-get-key.pl +++ b/tools/virt-tools-get-key.pl @@ -103,7 +103,7 @@ if ($version) { exit } -die __"no domain name or UUID listed on the command line\n" unless @ARGV == 1; +die __"no domain name listed on the command line\n" unless @ARGV == 1; my ($g, $conn, $dom); diff --git a/tools/virt-tools-get-transport.pl b/tools/virt-tools-get-transport.pl index 0b478b8..b6bf480 100755 --- a/tools/virt-tools-get-transport.pl +++ b/tools/virt-tools-get-transport.pl @@ -16,5 +16,321 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +use Sys::Virt; +use Sys::Guestfs; +use Sys::Guestfs::Lib qw(open_guest get_partitions); +use Pod::Usage; +use Getopt::Long; +use Locale::TextDomain 'virt-tools'; use Net::SNMP; +=encoding utf8 + +=head1 NAME + +virt-tools-get-transport - virt-tools helper to get the guest's transport + +=head1 SYNOPSIS + + virt-tools-get-transport [--options] domname + +=head1 DESCRIPTION + +This helper program is used by L to get the transport +that should be used to connect to the SNMP daemon inside the guest. +If you don't know anything about this, you probably want to start by +reading L. Otherwise read on. + +The single command line argument should be a libvirt domain name (see +C). + +=head2 TRANSPORTS + +Transports look somewhat like a URL, with a transport schema followed +by some specific details. Currently we have defined these transports: + +=over 4 + +=item udp:ip-address[:port] + +Connect via UDP to C, optionally on the non-default port +C (the usual SNMP port 161 is used otherwise). + +=item tcp:ip-address[:port] + +Connect via TCP to C, optionally on the non-default port +C (the usual SNMP port 161 is used otherwise). + +=item unix:path + +Connect via Unix domain socket C. This would be used in future +for vmchannel implementations, but it is not used at the moment. + +=back + +=head2 TRANSPORT CACHE + +The cache is described in detail in L. In brief, if +C<@localstatedir@/lib/virt-tools/transports/EUUIDE> exists +(where EUUIDE is the guest's UUID), then the contents of that +file are returned directly. Otherwise we will try to create this file +after reading the transport so that we don't have to determine the +guest's transport each time. + +=head1 OPTIONS + +=over 4 + +=cut + +my $help; + +=item B<--help> + +Display brief help. + +=cut + +my $version; + +=item B<--version> + +Display version number and exit. + +=cut + +my $uri; + +=item B<--connect URI> | B<-c URI> + +If using libvirt, connect to the given I. If omitted, then we +connect to the default libvirt hypervisor. + +=cut + +my $verbose; + +=item B<--verbose> | B<-v> + +Enable verbose messages, useful for debugging. + +=cut + +my $no_ping; + +=item B<--no-ping> | B<-n> + +Do not try to check that the transport is working by pinging the +guest. + +If this option is I given, then this program will expire the +cache entry for the guest if the transport from the cache doesn't +work, then it will try to determine the new transport, test that, and +fail if it still doesn't work. + +=back + +=cut + +GetOptions ("help|?" => \$help, + "version" => \$version, + "connect|c=s" => \$uri, + "verbose|v" => \$verbose, + "no-ping|n" => \$no_ping, + ) or pod2usage (2); +pod2usage (1) if $help; +if ($version) { + print "@PACKAGE_STRING@\n"; + exit +} + +die __"no domain name listed on the command line\n" unless @ARGV == 1; + +my ($g, $conn, $dom); + +if ($uri) { + ($g, $conn, $dom) = open_guest (\@ARGV, address => $uri); +} else { + ($g, $conn, $dom) = open_guest (\@ARGV); +} + +my $uuid = $dom->get_uuid_string (); +my $domname = $dom->get_name (); + +# See if the UUID exists in the cache already. +print STDERR "checking for UUID $uuid in the cache directory\n" if $verbose; + +my $cachedir = "@localstatedir@/lib/virt-tools/transports"; +if (-r "$cachedir/$uuid") { + print STDERR "$cachedir/$uuid exists\n" if $verbose; + open FILE, "$cachedir/$uuid" or die "$cachedir/$uuid: $!"; + my $transport = ; + chomp $transport; + close FILE; + + unless ($no_ping) { + # Test if it works. + if (!test_transport ($transport)) { + unlink "$cachedir/$uuid"; # allow this to fail + goto keep_looking; + } + } + + print $transport, "\n"; + + exit 0; +} + +print STDERR "$cachedir/$uuid not found, looking inside guest\n" if $verbose; + +keep_looking: +$g->launch (); + +# Do not care about mountpoints. Instead, just look for a +# directory with one of a selection of names on one of the +# partitions that we found. +my @partitions = get_partitions ($g); + +my ($transport, $key, $ip); + +foreach my $partition (@partitions) { + eval { + $g->mount_ro ($partition, "/"); + my $dir; + my @dirs = ("/var/lib/virt-tools", "/lib/virt-tools"); + foreach $dir (@dirs) { + if ($g->is_dir ($dir)) { + if ($g->is_file ("$dir/transport")) { + $transport = $g->cat ("$dir/transport"); + } + if ($g->is_file ("$dir/key")) { + $key = $g->cat ("$dir/key"); + } + if ($g->is_file ("$dir/ip-eth0")) { + $ip = $g->cat ("$dir/ip-eth0"); + } + } + } + }; + $g->umount_all (); + last if $transport || $key; +} + +undef $g; + +die __x("{n}: no transport or key found in guest.\nDoes it have the virt-tool-guest package installed?\n", + n => $ARGV[0]) + unless $transport && $key; + +if ($ip) { + if ($ip =~ m{inet (\S+)/}) { + $ip = $1; + } elsif ($ip =~ m{inet6 (\S+)/}) { + $ip = $1; + } else { + die __"could not parse the content of ip-eth0 file from the guest"; + } +} + +if ($transport =~ /^udp:(\d+)/) { + die __"UDP transport, but no IP address in guest" unless $ip; + $transport = "udp:$ip:$1"; +} +elsif ($transport =~ /^udp/) { + die __"UDP transport, but no IP address in guest" unless $ip; + $transport = "udp:$ip:161"; +} +elsif ($transport =~ /^tcp:(\d+)/) { + die __"TCP transport, but no IP address in guest" unless $ip; + $transport = "tcp:$ip:$1"; +} +elsif ($transport =~ /^tcp/) { + die __"TCP transport, but no IP address in guest" unless $ip; + $transport = "tcp:$ip:161"; +} +else { + die __x("unknown transport type: {t}", t => $transport); +} + +# Test the transport works. +die __x("transport {t} does not work", t => $transport) + unless test_transport ($transport, $key); + +print STDERR "try to write $transport to $cachedir/$uuid\n" if $verbose; + +if (open FILE, ">$cachedir/$uuid") { + print FILE $transport; + close FILE +} + +print $transport; + +exit 0; + +sub test_transport +{ + my $transport = shift; + my $key = shift; + + unless ($key) { + my $cmd = "virt-tools-get-key"; + $cmd .= " -v" if $verbose; + # XXX quoting + $cmd .= " -c '$uri'" if $uri; + $cmd .= " '$domname'"; + + print STDERR "$cmd\n" if $verbose; + + open PIPE, "$cmd |" or die "$cmd: $!"; + $key = ; + die __"no response from virt-tools-get-key\n" unless $key; + chomp $key; + close PIPE; + } + + print "XXX PING XXX\n"; + + 1; +} + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L, +L. + +=head1 AUTHORS + +=over 4 + +=item * + +Richard W.M. Jones (C) + +=item * + +Matthew Booth (C) + +=back + +=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. diff --git a/tools/virt-uname.pl b/tools/virt-uname.pl index 70bbd34..9a383bb 100755 --- a/tools/virt-uname.pl +++ b/tools/virt-uname.pl @@ -384,6 +384,8 @@ IP network. Other transports are possible, including "vmchannel" host-guest communication channels implemented in different ways by different hypervisors). +The transport is written to C<$GUESTCOMMSDIR/transport>. + =head1 HOST ARCHITECTURE On the host side, the host uses L to read the guest's @@ -459,7 +461,7 @@ sub get_key open PIPE, "$cmd |" or die "$cmd: $!"; my $line = ; - die "no response from virt-tools-get-key\n" unless $line; + die __"no response from virt-tools-get-key\n" unless $line; chomp $line; close PIPE; @@ -513,7 +515,7 @@ sub get_transport open PIPE, "$cmd |" or die "$cmd: $!"; my $line = ; - die "no response from virt-tools-get-transport\n" unless $line; + die __"no response from virt-tools-get-transport\n" unless $line; chomp $line; close PIPE; -- 1.8.3.1