X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=tools%2Fvirt-df;h=6ec1c1a723cb07bee1ee1f8b9785def9db16e338;hp=d9ef8f9a98777a01000a9dc4912876cf098a090f;hb=a0f85ba643990da25b6afe6a2bbd2407cf312c73;hpb=f7475ec577b7ca810185e0fd70a39ac9adaae620 diff --git a/tools/virt-df b/tools/virt-df index d9ef8f9..6ec1c1a 100755 --- a/tools/virt-df +++ b/tools/virt-df @@ -112,6 +112,23 @@ read L below. =cut +my $format; + +=item B<--format> raw + +Specify the format of disk images given on the command line. If this +is omitted then the format is autodetected from the content of the +disk image. + +If disk images are requested from libvirt, then this program asks +libvirt for this information. In this case, the value of the format +parameter is ignored. + +If working with untrusted raw-format guest disk images, you should +ensure the format is always specified. + +=cut + my $human; =item B<--human-readable> | B<-h> @@ -156,6 +173,20 @@ guests. =back +=cut + +my $uuid; + +=item B<--uuid> + +Print UUIDs instead of names. This is useful for following +a guest even when the guest is migrated or renamed, or when +two guests happen to have the same name. + +Note that only domains that we fetch from libvirt come with UUIDs. +For disk images, we still print the disk image name even when +this option is specified. + =back =cut @@ -164,9 +195,11 @@ GetOptions ("help|?" => \$help, "version" => \$version, "connect|c=s" => \$uri, "csv" => \$csv, + "format=s" => \$format, "human-readable|human|h" => \$human, "inodes|i" => \$inodes, "one-per-guest" => \$one_per_guest, + "uuid" => \$uuid, ) or pod2usage (2); pod2usage (1) if $help; if ($version) { @@ -224,12 +257,13 @@ if (@ARGV == 0) { # No params, use libvirt. my @disks = get_disks_from_libvirt ($dom); push @domains, { dom => $dom, name => $dom->get_name (), + uuid => $dom->get_uuid_string (), disks => \@disks } } } elsif (@ARGV == 1) { # One param, could be disk image or domname. if (-e $ARGV[0]) { push @domains, { name => basename ($ARGV[0]), - disks => [ $ARGV[0] ] } + disks => [ [ $ARGV[0], $format ] ] } } else { my $conn; @@ -245,11 +279,13 @@ if (@ARGV == 0) { # No params, use libvirt. my @disks = get_disks_from_libvirt ($dom); push @domains, { dom => $dom, name => $dom->get_name (), + uuid => $dom->get_uuid_string (), disks => \@disks } } } else { # >= 2 params, all disk images. + my @disks = map { [ $_, $format ] } @ARGV; push @domains, { name => basename ($ARGV[0]), - disks => \@ARGV } + disks => \@disks } } sub get_disks_from_libvirt @@ -258,12 +294,29 @@ sub get_disks_from_libvirt my $xml = $dom->get_xml_description (); my $p = XML::XPath->new (xml => $xml); - my @disks = $p->findnodes ('//devices/disk/source/@dev'); - push (@disks, $p->findnodes ('//devices/disk/source/@file')); + my $nodes = $p->find ('//devices/disk'); + + my @disks; + my $node; + foreach $node ($nodes->get_nodelist) { + # The filename can be in dev or file attribute, hence: + my $filename = $p->find ('./source/@dev', $node); + unless ($filename) { + $filename = $p->find ('./source/@file', $node); + next unless $filename; + } + $filename = $filename->to_literal; + + # Get the disk format (may not be set). + my $format = $p->find ('./driver/@type', $node); + $format = $format->to_literal if $format; + + push @disks, [ $filename, $format ]; + } # Code in Sys::Guestfs::Lib dies here if there are no disks at all. - return map { $_->getData } @disks; + return @disks; } # Sort the domains by name for display. @@ -312,7 +365,12 @@ sub multi_df foreach $d (@_) { foreach $disk (@{$d->{disks}}) { - $g->add_drive_ro ($disk); + my $filename = $disk->[0]; + my $format = $disk->[1]; + my @args = ($filename); + push @args, readonly => 1; + push @args, format => $format if defined $format; + $g->add_drive_opts (@args); } } @@ -325,6 +383,7 @@ sub multi_df my $n = 0; foreach $d (@_) { my $name = $d->{name}; + my $uuid = $d->{uuid}; my $nr_disks = @{$d->{disks}}; # Filter LVM to only the devices applying to the original domain. @@ -335,14 +394,14 @@ sub multi_df # contain mountable filesystems. Stat those which are # mountable, and ignore the others. foreach (@devs) { - try_df ($name, $g, $_, canonical_dev ($_, $n)); + try_df ($name, $uuid, $g, $_, canonical_dev ($_, $n)); } foreach (filter_partitions (\@devs, @partitions)) { - try_df ($name, $g, $_, canonical_dev ($_, $n)); + try_df ($name, $uuid, $g, $_, canonical_dev ($_, $n)); } if ($has_lvm2) { foreach ($g->lvs ()) { - try_df ($name, $g, $_); + try_df ($name, $uuid, $g, $_); } } @@ -392,6 +451,7 @@ sub try_df { local $_; my $domname = shift; + my $domuuid = shift; my $g = shift; my $dev = shift; my $display = shift || $dev; @@ -402,7 +462,7 @@ sub try_df %stat = $g->statvfs ("/"); }; if (!$@) { - print_stat ($domname, $display, \%stat); + print_stat ($domname, $domuuid, $display, \%stat); } $g->umount_all (); } @@ -410,10 +470,17 @@ sub try_df sub print_stat { my $domname = shift; + my $domuuid = shift; my $dev = shift; my $stat = shift; - my @cols = ($domname, $dev); + my @cols; + if (!$uuid || !defined $domuuid) { + push @cols, $domname; + } else { + push @cols, $domuuid; + } + push @cols, $dev; if (!$inodes) { my $bsize = $stat->{bsize}; # block size