3 # Copyright (C) 2009 Red Hat Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 use Sys::Guestfs::Lib qw(open_guest get_partitions);
31 use Locale::TextDomain 'libguestfs';
37 virt-df - Display free space on virtual filesystems
43 virt-df [--options] domname
45 virt-df [--options] disk.img [disk.img ...]
49 C<virt-df> is a command line tool to display free space on virtual
50 machine filesystems. Unlike other tools, it doesn't just display the
51 amount of space allocated to a virtual machine, but can look inside
52 the virtual machine to see how much space is really being used.
54 It is like the L<df(1)> command, but for virtual machines, except that
55 it also works for Windows virtual machines.
57 If used without any arguments, C<virt-df> checks with libvirt to get a
58 list of all active and inactive guests, and performs a C<df>-type
59 operation on each one in turn, printing out the results.
61 If used with any argument(s), C<virt-df> performs a C<df>-type
62 operation on either the single named libvirt domain, or on the disk
63 image(s) listed on the command line (which must all belong to a single
64 VM). In this mode (with arguments), C<virt-df> will I<only work for a
65 single guest>. If you want to run on multiple guests, then you have
66 to invoke C<virt-df> multiple times.
68 Use the C<--csv> option to get a format which can be easily parsed by
69 other programs. Other options are mostly similar to standard C<df>
70 options. See below for the complete list.
90 Display version number and exit.
96 =item B<--connect URI> | B<-c URI>
98 If using libvirt, connect to the given I<URI>. If omitted, then we
99 connect to the default libvirt hypervisor.
101 If you specify guest block devices directly, then libvirt is not used
110 Write out the results in CSV format (comma-separated values). This format
111 can be imported easily into databases and spreadsheets, but
112 read L</NOTE ABOUT CSV FORMAT> below.
118 =item B<--human-readable> | B<-h>
120 Print sizes in human-readable format.
122 You are not allowed to use I<-h> and I<--csv> at the same time.
128 =item B<--inodes> | B<-i>
130 Print inodes instead of blocks.
136 GetOptions ("help|?" => \$help,
137 "version" => \$version,
138 "connect|c=s" => \$uri,
140 "human-readable|human|h" => \$human,
141 "inodes|i" => \$inodes,
143 pod2usage (1) if $help;
145 my $g = Sys::Guestfs->new ();
146 my %h = $g->version ();
147 print "$h{major}.$h{minor}.$h{release}$h{extra}\n";
152 die __"virt-df: cannot use -h and --csv options together\n" if $human && $csv;
154 # Open the guest handle.
160 $conn = Sys::Virt->new (readonly => 1, address => $uri);
162 $conn = Sys::Virt->new (readonly => 1);
165 my @doms = $conn->list_defined_domains ();
166 push @doms, $conn->list_domains ();
168 # https://bugzilla.redhat.com/show_bug.cgi?id=538041
169 @doms = grep { $_->get_id () != 0 } @doms;
171 my @domnames = sort (map { $_->get_name () } @doms);
175 foreach (@domnames) {
176 eval { do_df ($_); };
190 $g = open_guest (\@_, address => $uri);
192 $g = open_guest (\@_);
197 my @partitions = get_partitions ($g);
199 # Think of a printable name for this domain. Just choose the
200 # first parameter passed to this function, which will work for
201 # most cases (it'll either be the domain name or the first disk
205 # Mount each partition in turn, and if mountable, do a statvfs on it.
206 foreach my $partition (@partitions) {
209 $g->mount_ro ($partition, "/");
210 %stat = $g->statvfs ("/");
213 print_stat ($domname, $partition, \%stat);
222 my $partition = shift;
225 my @cols = ($domname, $partition);
228 my $bsize = $stat->{bsize}; # block size
229 my $blocks = $stat->{blocks}; # total number of blocks
230 my $bfree = $stat->{bfree}; # blocks free (total)
231 my $bavail = $stat->{bavail}; # blocks free (for non-root users)
233 my $factor = $bsize / 1024;
235 push @cols, $blocks*$factor; # total 1K blocks
236 push @cols, ($blocks-$bfree)*$factor; # total 1K blocks used
237 push @cols, $bavail*$factor; # total 1K blocks available
239 push @cols, 100.0 - 100.0 * $bfree / $blocks;
242 $cols[2] = human_size ($cols[2]);
243 $cols[3] = human_size ($cols[3]);
244 $cols[4] = human_size ($cols[4]);
247 my $files = $stat->{files}; # total number of inodes
248 my $ffree = $stat->{ffree}; # inodes free (total)
249 my $favail = $stat->{favail}; # inodes free (for non-root users)
252 push @cols, $files-$ffree;
255 push @cols, 100.0 - 100.0 * $ffree / $files;
263 my @cols = (__"Virtual Machine", __"Filesystem");
266 push @cols, __"1K-blocks";
268 push @cols, __"Size";
270 push @cols, __"Used";
271 push @cols, __"Available";
272 push @cols, __"Use%";
274 push @cols, __"Inodes";
275 push @cols, __"IUsed";
276 push @cols, __"IFree";
277 push @cols, __"IUse%";
281 # ignore $cols[0] in this mode
282 printf "%-36s%10s %10s %10s %5s\n",
283 $cols[1], $cols[2], $cols[3], $cols[4], $cols[5];
285 print (join (",", @cols), "\n");
292 my $label = sprintf "%s:%s", $_[0], $_[1];
294 printf ("%-36s", $label);
295 print "\n"," "x36 if length ($label) > 36;
297 # Use 'ceil' on the percentage in order to emulate
298 # what df itself does.
299 my $percent = sprintf "%3d%%", ceil($_[5]);
301 printf ("%10s %10s %10s %5s\n", $_[2], $_[3], $_[4], $percent);
303 printf ("\"%s\",\"%s\",%d,%d,%d,%.1f%%\n", @_);
307 # Convert a number of 1K blocks to a human-readable number.
314 } elsif ($_ < 1024 * 1024) {
315 sprintf "%.1fM", ($_ / 1024);
317 sprintf "%.1fG", ($_ / 1024 / 1024);
321 =head1 NOTE ABOUT CSV FORMAT
323 Comma-separated values (CSV) is a deceptive format. It I<seems> like
324 it should be easy to parse, but it is definitely not easy to parse.
326 Myth: Just split fields at commas. Reality: This does I<not> work
327 reliably. This example has two columns:
331 Myth: Read the file one line at a time. Reality: This does I<not>
332 work reliably. This example has one row:
337 For shell scripts, use C<csvtool> (L<http://merjis.com/developers/csv>
338 also packaged in major Linux distributions).
340 For other languages, use a CSV processing library (eg. C<Text::CSV>
341 for Perl or Python's built-in csv library).
343 Most spreadsheets and databases can import CSV directly.
350 L<Sys::Guestfs::Lib(3)>,
352 L<http://libguestfs.org/>.
356 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
360 Copyright (C) 2009-2010 Red Hat Inc.
362 This program is free software; you can redistribute it and/or modify
363 it under the terms of the GNU General Public License as published by
364 the Free Software Foundation; either version 2 of the License, or
365 (at your option) any later version.
367 This program is distributed in the hope that it will be useful,
368 but WITHOUT ANY WARRANTY; without even the implied warranty of
369 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
370 GNU General Public License for more details.
372 You should have received a copy of the GNU General Public License
373 along with this program; if not, write to the Free Software
374 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.