Version 1.5.26.
[libguestfs.git] / tools / virt-resize
1 #!/usr/bin/perl -w
2 # virt-resize
3 # Copyright (C) 2010 Red Hat Inc.
4 #
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.
9 #
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.
14 #
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.
18
19 use warnings;
20 use strict;
21
22 use Sys::Guestfs;
23 use Sys::Guestfs::Lib qw(feature_available);
24 use Fcntl qw(S_ISREG SEEK_SET);
25 use POSIX qw(floor);
26 use Pod::Usage;
27 use Getopt::Long;
28 use Data::Dumper;
29 use Locale::TextDomain 'libguestfs';
30
31 $Data::Dumper::Sortkeys = 1;
32
33 die __"virt-resize: sorry this program does not work on a 32 bit host\n"
34     if ~1 == 4294967294;
35
36 $| = 1;
37
38 =encoding utf8
39
40 =head1 NAME
41
42 virt-resize - Resize a virtual machine disk
43
44 =head1 SYNOPSIS
45
46  virt-resize [--resize /dev/sdaN=[+/-]<size>[%]]
47    [--expand /dev/sdaN] [--shrink /dev/sdaN]
48    [--ignore /dev/sdaN] [--delete /dev/sdaN] [...] indisk outdisk
49
50 =head1 DESCRIPTION
51
52 Virt-resize is a tool which can resize a virtual machine disk, making
53 it larger or smaller overall, and resizing or deleting any partitions
54 contained within.
55
56 Virt-resize B<cannot> resize disk images in-place.  Virt-resize
57 B<should not> be used on live virtual machines - for consistent
58 results, shut the virtual machine down before resizing it.
59
60 If you are not familiar with the associated tools:
61 L<virt-list-partitions(1)>,
62 L<virt-list-filesystems(1)> and
63 L<virt-df(1)>,
64 we recommend you go and read those manual pages first.
65
66 =head1 EXAMPLES
67
68 Copy C<olddisk> to C<newdisk>, extending one of the guest's partitions
69 to fill the extra 5GB of space.
70
71  truncate -r olddisk newdisk; truncate -s +5G newdisk
72  virt-list-partitions -lht olddisk
73  # Note "/dev/sda2" is a partition inside the "olddisk" file.
74  virt-resize --expand /dev/sda2 olddisk newdisk
75
76 As above, but make the /boot partition 200MB bigger, while giving the
77 remaining space to /dev/sda2:
78
79  virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 olddisk newdisk
80
81 As above, but the output format will be uncompressed qcow2:
82
83  qemu-img create -f qcow2 newdisk.qcow2 15G
84  virt-resize --expand /dev/sda2 olddisk newdisk.qcow2
85
86 =head1 DETAILED USAGE
87
88 =head2 EXPANDING A VIRTUAL MACHINE DISK
89
90 =over 4
91
92 =item 1. Shut down the virtual machine
93
94 =item 2. Locate input disk image
95
96 Locate the input disk image (ie. the file or device on the host
97 containing the guest's disk).  If the guest is managed by libvirt, you
98 can use C<virsh dumpxml> like this to find the disk image name:
99
100  # virsh dumpxml guestname | xpath /domain/devices/disk/source
101  Found 1 nodes:
102  -- NODE --
103  <source dev="/dev/vg/lv_guest" />
104
105 =item 3. Look at current sizing
106
107 Use L<virt-list-partitions(1)> to display the current partitions and
108 sizes:
109
110  # virt-list-partitions -lht /dev/vg/lv_guest
111  /dev/sda1 ext3 101.9M
112  /dev/sda2 pv 7.9G
113  /dev/sda device 8.0G
114
115 (This example is a virtual machine with an 8 GB disk which we would
116 like to expand up to 10 GB).
117
118 =item 4. Create output disk
119
120 Virt-resize cannot do in-place disk modifications.  You have to have
121 space to store the resized output disk.
122
123 To store the resized disk image in a file, create a file of a suitable
124 size:
125
126  # rm -f outdisk
127  # truncate -s 10G outdisk
128
129 Or use L<lvcreate(1)> to create a logical volume:
130
131  # lvcreate -L 10G -n lv_name vg_name
132
133 Or use L<virsh(1)> vol-create-as to create a libvirt storage volume:
134
135  # virsh pool-list
136  # virsh vol-create-as poolname newvol 10G
137
138 =item 5. Resize
139
140 virt-resize takes two mandatory parameters, the input disk (eg. device
141 or file) and the output disk.  The output disk is the one created in
142 the previous step.
143
144  # virt-resize indisk outdisk
145
146 This command just copies disk image C<indisk> to disk image C<outdisk>
147 I<without> resizing or changing any existing partitions.  If
148 C<outdisk> is larger, then an extra, empty partition is created at the
149 end of the disk covering the extra space.  If C<outdisk> is smaller,
150 then it will give an error.
151
152 More realistically you'd want to expand existing partitions in the
153 disk image by passing extra options (for the full list see the
154 L</OPTIONS> section below).
155
156 L</--expand> is the most useful option.  It expands the named
157 partition within the disk to fill any extra space:
158
159  # virt-resize --expand /dev/sda2 indisk outdisk
160
161 (In this case, an extra partition is I<not> created at the end of the
162 disk, because there will be no unused space).
163
164 L</--resize> is the other commonly used option.  The following would
165 increase the size of /dev/sda1 by 200M, and expand /dev/sda2
166 to fill the rest of the available space:
167
168  # virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 \
169      indisk outdisk
170
171 If the expanded partition in the image contains a filesystem or LVM
172 PV, then if virt-resize knows how, it will resize the contents, the
173 equivalent of calling a command such as L<pvresize(8)>,
174 L<resize2fs(8)> or L<ntfsresize(8)>.  However virt-resize does not
175 know how to resize some filesystems, so you would have to online
176 resize them after booting the guest.  And virt-resize also does not
177 resize anything inside an LVM PV, it just resizes the PV itself and
178 leaves the user to resize any LVs inside that PV as desired.
179
180 Other options are covered below.
181
182 =item 6. Test
183
184 Thoroughly test the new disk image I<before> discarding the old one.
185
186 If you are using libvirt, edit the XML to point at the new disk:
187
188  # virsh edit guestname
189
190 Change E<lt>source ...E<gt>, see
191 L<http://libvirt.org/formatdomain.html#elementsDisks>
192
193 Then start up the domain with the new, resized disk:
194
195  # virsh start guestname
196
197 and check that it still works.  See also the L</NOTES> section below
198 for additional information.
199
200 =item 7. Resize LVs etc inside the guest
201
202 (This can also be done offline using L<guestfish(1)>)
203
204 Once the guest has booted you should see the new space available, at
205 least for filesystems that virt-resize knows how to resize, and for
206 PVs.  The user may need to resize LVs inside PVs, and also resize
207 filesystem types that virt-resize does not know how to expand.
208
209 =back
210
211 =head2 SHRINKING A VIRTUAL MACHINE DISK
212
213 Shrinking is somewhat more complex than expanding, and only an
214 overview is given here.
215
216 Firstly virt-resize will not attempt to shrink any partition content
217 (PVs, filesystems).  The user has to shrink content before passing the
218 disk image to virt-resize, and virt-resize will check that the content
219 has been shrunk properly.
220
221 (Shrinking can also be done offline using L<guestfish(1)>)
222
223 After shrinking PVs and filesystems, shut down the guest, and proceed
224 with steps 3 and 4 above to allocate a new disk image.
225
226 Then run virt-resize with any of the C<--shrink> and/or C<--resize>
227 options.
228
229 =head2 IGNORING OR DELETING PARTITIONS
230
231 virt-resize also gives a convenient way to ignore or delete partitions
232 when copying from the input disk to the output disk.  Ignoring a
233 partition speeds up the copy where you don't care about the existing
234 contents of a partition.  Deleting a partition removes it completely,
235 but note that it also renumbers any partitions after the one which is
236 deleted, which can leave some guests unbootable.
237
238 =head2 QCOW2 AND NON-SPARSE RAW FORMATS
239
240 If the input disk is in qcow2 format, then you may prefer that the
241 output is in qcow2 format as well.  Alternately, virt-resize can
242 convert the format on the fly.  The output format is simply determined
243 by the format of the empty output container that you provide.  Thus to
244 create qcow2 output, use:
245
246  qemu-img create [-c] -f qcow2 outdisk [size]
247
248 instead of the truncate command (use C<-c> for a compressed disk).
249
250 Similarly, to get non-sparse raw output use:
251
252  fallocate -l size outdisk
253
254 (on older systems that don't have the L<fallocate(1)> command use
255 C<dd if=/dev/zero of=outdisk bs=1M count=..>)
256
257 =head1 OPTIONS
258
259 =over 4
260
261 =cut
262
263 my $help;
264
265 =item B<--help>
266
267 Display help.
268
269 =cut
270
271 my $version;
272
273 =item B<--version>
274
275 Display version number and exit.
276
277 =cut
278
279 my @resize;
280
281 =item B<--resize part=size>
282
283 Resize the named partition (expanding or shrinking it) so that it has
284 the given size.
285
286 C<size> can be expressed as an absolute number followed by
287 b/K/M/G/T/P/E to mean bytes, Kilobytes, Megabytes, Gigabytes,
288 Terabytes, Petabytes or Exabytes; or as a percentage of the current
289 size; or as a relative number or percentage.  For example:
290
291  --resize /dev/sda2=10G
292
293  --resize /dev/sda4=90%
294
295  --resize /dev/sda2=+1G
296
297  --resize /dev/sda2=-200M
298
299  --resize /dev/sda1=+128K
300
301  --resize /dev/sda1=+10%
302
303  --resize /dev/sda1=-10%
304
305 You can increase the size of any partition.  Virt-resize will expand
306 the direct content of the partition if it knows how (see C<--expand>
307 below).
308
309 You can only I<decrease> the size of partitions that contain
310 filesystems or PVs which have already been shrunk.  Virt-resize will
311 check this has been done before proceeding, or else will print an
312 error (see also C<--resize-force>).
313
314 You can give this option multiple times.
315
316 =cut
317
318 my @resize_force;
319
320 =item B<--resize-force part=size>
321
322 This is the same as C<--resize> except that it will let you decrease
323 the size of any partition.  Generally this means you will lose any
324 data which was at the end of the partition you shrink, but you may not
325 care about that (eg. if shrinking an unused partition, or if you can
326 easily recreate it such as a swap partition).
327
328 See also the C<--ignore> option.
329
330 =cut
331
332 my $expand;
333
334 =item B<--expand part>
335
336 Expand the named partition so it uses up all extra space (space left
337 over after any other resize changes that you request have been done).
338
339 If virt-resize knows how, it will expand the direct content of the
340 partition.  For example, if the partition is an LVM PV, it will expand
341 the PV to fit (like calling L<pvresize(8)>).  Virt-resize leaves any
342 other content it doesn't know about alone.
343
344 Currently virt-resize can resize:
345
346 =over 4
347
348 =item *
349
350 ext2, ext3 and ext4 filesystems when they are contained
351 directly inside a partition.
352
353 =item *
354
355 NTFS filesystems contained directly in a partition, if libguestfs was
356 compiled with support for NTFS.
357
358 The filesystem must have been shut down consistently last time it was
359 used.  Additionally, L<ntfsresize(8)> marks the resized filesystem as
360 requiring a consistency check, so at the first boot after resizing
361 Windows will check the disk.
362
363 =item *
364
365 LVM PVs (physical volumes).  However virt-resize does I<not>
366 resize anything inside the PV.  The user will have to resize
367 LVs as desired.
368
369 =back
370
371 Note that you cannot use C<--expand> and C<--shrink> together.
372
373 =cut
374
375 my $shrink;
376
377 =item B<--shrink part>
378
379 Shrink the named partition until the overall disk image fits in the
380 destination.  The named partition B<must> contain a filesystem or PV
381 which has already been shrunk using another tool (eg. L<guestfish(1)>
382 or other online tools).  Virt-resize will check this and give an error
383 if it has not been done.
384
385 The amount by which the overall disk must be shrunk (after carrying
386 out all other operations requested by the user) is called the
387 "deficit".  For example, a straight copy (assume no other operations)
388 from a 5GB disk image to a 4GB disk image results in a 1GB deficit.
389 In this case, virt-resize would give an error unless the user
390 specified a partition to shrink and that partition had more than a
391 gigabyte of free space.
392
393 Note that you cannot use C<--expand> and C<--shrink> together.
394
395 =cut
396
397 my @ignore;
398
399 =item B<--ignore part>
400
401 Ignore the named partition.  Effectively this means the partition is
402 allocated on the destination disk, but the content is not copied
403 across from the source disk.  The content of the partition will be
404 blank (all zero bytes).
405
406 You can give this option multiple times.
407
408 =cut
409
410 my @delete;
411
412 =item B<--delete part>
413
414 Delete the named partition.  It would be more accurate to describe
415 this as "don't copy it over", since virt-resize doesn't do in-place
416 changes and the original disk image is left intact.
417
418 Note that when you delete a partition, then anything contained in the
419 partition is also deleted.  Furthermore, this causes any partitions
420 that come after to be I<renumbered>, which can easily make your guest
421 unbootable.
422
423 You can give this option multiple times.
424
425 =cut
426
427 my @lv_expand;
428
429 =item B<--LV-expand logvol>
430
431 This takes the logical volume and, as a final step, expands it to fill
432 all the space available in its volume group.  A typical usage,
433 assuming a Linux guest with a single PV C</dev/sda2> and a root device
434 called C</dev/vg_guest/lv_root> would be:
435
436  virt-resize indisk outdisk \
437    --expand /dev/sda2 --LV-expand /dev/vg_guest/lv_root
438
439 This would first expand the partition (and PV), and then expand the
440 root device to fill the extra space in the PV.
441
442 The contents of the LV are also resized if virt-resize knows how to do
443 that.  You can stop virt-resize from trying to expand the content by
444 using the option C<--no-expand-content>.
445
446 Use L<virt-list-filesystems(1)> to list the filesystems in
447 the guest.
448
449 You can give this option multiple times, I<but> it doesn't
450 make sense to do this unless the logical volumes you specify
451 are all in different volume groups.
452
453 =cut
454
455 my $copy_boot_loader = 1;
456
457 =item B<--no-copy-boot-loader>
458
459 By default, virt-resize copies over some sectors at the start of the
460 disk (up to the beginning of the first partition).  Commonly these
461 sectors contain the Master Boot Record (MBR) and the boot loader, and
462 are required in order for the guest to boot correctly.
463
464 If you specify this flag, then this initial copy is not done.  You may
465 need to reinstall the boot loader in this case.
466
467 =cut
468
469 my $extra_partition = 1;
470 my $min_extra_partition = 10 * 1024 * 1024; # see below
471
472 =item B<--no-extra-partition>
473
474 By default, virt-resize creates an extra partition if there is any
475 extra, unused space after all resizing has happened.  Use this option
476 to prevent the extra partition from being created.  If you do this
477 then the extra space will be inaccessible until you run fdisk, parted,
478 or some other partitioning tool in the guest.
479
480 Note that if the surplus space is smaller than 10 MB, no extra
481 partition will be created.
482
483 =cut
484
485 my $expand_content = 1;
486
487 =item B<--no-expand-content>
488
489 By default, virt-resize will try to expand the direct contents
490 of partitions, if it knows how (see C<--expand> option above).
491
492 If you give the C<--no-expand-content> option then virt-resize
493 will not attempt this.
494
495 =cut
496
497 my $debug;
498
499 =item B<-d> | B<--debug>
500
501 Enable debugging messages.
502
503 =cut
504
505 my $dryrun;
506
507 =item B<-n> | B<--dryrun>
508
509 Print a summary of what would be done, but don't do anything.
510
511 =cut
512
513 my $quiet;
514
515 =item B<-q> | B<--quiet>
516
517 Don't print the summary.
518
519 =cut
520
521 my $format;
522
523 =item B<--format> raw
524
525 Specify the format of the input disk image.  If this flag is not
526 given then it is auto-detected from the image itself.
527
528 If working with untrusted raw-format guest disk images, you should
529 ensure the format is always specified.
530
531 Note that this option I<does not> affect the output format.
532 See L</QCOW2 AND NON-SPARSE RAW FORMATS>.
533
534 =cut
535
536 my $output_format;
537
538 =item B<--output-format> raw
539
540 Specify the format of the output disk image.  If this flag is not
541 given then it is auto-detected from the image itself.
542
543 If working with untrusted raw-format guest disk images, you should
544 ensure the format is always specified.
545
546 Note that you still need to create the output disk with the right
547 format.  See L</QCOW2 AND NON-SPARSE RAW FORMATS>.
548
549 =back
550
551 =cut
552
553 GetOptions ("help|?" => \$help,
554             "version" => \$version,
555             "resize=s" => \@resize,
556             "resize-force=s" => \@resize_force,
557             "expand=s" => \$expand,
558             "shrink=s" => \$shrink,
559             "ignore=s" => \@ignore,
560             "delete=s" => \@delete,
561             "lv-expand=s" => \@lv_expand,
562             "copy-boot-loader!" => \$copy_boot_loader,
563             "extra-partition!" => \$extra_partition,
564             "expand-content!" => \$expand_content,
565             "d|debug" => \$debug,
566             "n|dryrun|dry-run" => \$dryrun,
567             "q|quiet" => \$quiet,
568             "format=s" => \$format,
569             "output-format=s" => \$output_format,
570     ) or pod2usage (2);
571 pod2usage (1) if $help;
572 if ($version) {
573     my $g = Sys::Guestfs->new ();
574     my %h = $g->version ();
575     print "$h{major}.$h{minor}.$h{release}$h{extra}\n";
576     exit
577 }
578
579 die "virt-resize [--options] indisk outdisk\n" unless @ARGV == 2;
580
581 # Check in and out images exist.
582 my $infile = $ARGV[0];
583 my $outfile = $ARGV[1];
584 die __x("virt-resize: {file}: does not exist or is not readable\n", file => $infile)
585     unless -r $infile;
586 die __x("virt-resize: {file}: does not exist or is not writable\nYou have to create the destination disk before running this program.\nPlease read the virt-resize(1) manpage for more information.\n", file => $outfile)
587     unless -w $outfile;
588
589 # Add them to the handle and launch the appliance.
590 my $g;
591 launch_guestfs ();
592
593 sub launch_guestfs
594 {
595     $g = Sys::Guestfs->new ();
596     $g->set_trace (1) if $debug;
597     my @args = ($infile);
598     push @args, readonly => 1;
599     push @args, format => $format if defined $format;
600     $g->add_drive_opts (@args);
601     @args = ($outfile);
602     push @args, format => $output_format if defined $output_format;
603     $g->add_drive_opts (@args);
604     $g->set_progress_callback (\&progress_callback) unless $quiet;
605     $g->launch ();
606 }
607
608 my $sectsize = $g->blockdev_getss ("/dev/sdb");
609
610 # Get the size in bytes of each disk.
611 #
612 # Originally we computed this by looking at the same of the host file,
613 # but of course this failed for qcow2 images (RHBZ#633096).  The right
614 # way to do it is with $g->blockdev_getsize64.
615 my $insize = $g->blockdev_getsize64 ("/dev/sda");
616 my $outsize = $g->blockdev_getsize64 ("/dev/sdb");
617
618 if ($debug) {
619     print "$infile size $insize bytes\n";
620     print "$outfile size $outsize bytes\n";
621 }
622
623 # Create a partition table.
624 #
625 # We *must* do this before copying the bootloader across, and copying
626 # the bootloader must be careful not to disturb this partition table
627 # (RHBZ#633766).  There are two reasons for this:
628 #
629 # (1) The 'parted' library is stupid and broken.  In many ways.  In
630 # this particular instance the stupid and broken bit is that it
631 # overwrites the whole boot sector when initializating a partition
632 # table.  (Upstream don't consider this obvious problem to be a bug).
633 #
634 # (2) GPT has a backup partition table located at the end of the disk.
635 # It's non-movable, because the primary GPT contains fixed references
636 # to both the size of the disk and the backup partition table at the
637 # end.  This would be a problem for any resize that didn't either
638 # carefully move the backup GPT (and rewrite those references) or
639 # recreate the whole partition table from scratch.
640
641 my $parttype;
642 create_partition_table ();
643
644 sub create_partition_table
645 {
646     local $_;
647
648     $parttype = $g->part_get_parttype ("/dev/sda");
649     print "partition table type: $parttype\n" if $debug;
650
651     $g->part_init ("/dev/sdb", $parttype);
652 }
653
654 # In reality the number of sectors containing boot loader data will be
655 # less than this (although Windows 7 defaults to putting the first
656 # partition on sector 2048, and has quite a large boot loader).
657 #
658 # However make this large enough to be sure that we have copied over
659 # the boot loader.  We could also do this by looking for the sector
660 # offset of the first partition.
661 #
662 # It doesn't matter if we copy too much.
663 my $max_bootloader = 4096 * 512;
664
665 die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n",
666         file => $infile, sz => $insize)
667     if $insize < $max_bootloader;
668 die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n",
669         file => $outfile, sz => $outsize)
670     if $outsize < $max_bootloader;
671
672 # Copy the boot loader across.
673 do_copy_boot_loader () if $copy_boot_loader;
674
675 sub do_copy_boot_loader
676 {
677     print "copying boot loader ...\n" if $debug;
678
679     # Don't disturb the partition table that we just wrote.
680     # https://secure.wikimedia.org/wikipedia/en/wiki/Master_Boot_Record
681     # https://secure.wikimedia.org/wikipedia/en/wiki/GUID_Partition_Table
682
683     my $bootsect = $g->pread_device ("/dev/sda", 446, 0);
684     die __"virt-resize: short read" if length ($bootsect) < 446;
685
686     $g->pwrite_device ("/dev/sdb", $bootsect, 0);
687
688     my $start = 512;
689     if ($parttype eq "gpt") {
690         # XXX With 4K sectors does GPT just fit more entries in a
691         # sector, or does it always use 34 sectors?
692         $start = 17408;
693     }
694
695     my $loader = $g->pread_device ("/dev/sda", $max_bootloader, $start);
696     die __"virt-resize: short read" if length ($loader) < $max_bootloader;
697
698     $g->pwrite_device ("/dev/sdb", $loader, $start);
699 }
700
701 my $to_be_expanded = 0;
702
703 # Get the partitions on the source disk.
704 my @partitions;
705 my %partitions;
706 check_source_disk ();
707
708 sub check_source_disk
709 {
710     local $_;
711
712     # Partitions and PVs.
713     my @p = $g->part_list ("/dev/sda");
714     foreach (@p) {
715         my $name = "/dev/sda" . $_->{part_num};
716         push @partitions, $name;
717
718         my %h = %$_;
719         $h{name} = $name;
720         $h{bootable} = $g->part_get_bootable ("/dev/sda", $h{part_num});
721         eval { $h{mbr_id} = $g->part_get_mbr_id ("/dev/sda", $h{part_num}); };
722         $partitions{$name} = \%h;
723     }
724 }
725
726 # Examine each partition.
727 my @pvs_full = $g->pvs_full ();
728 examine_partition ($_) foreach @partitions;
729
730 sub examine_partition
731 {
732     local $_;
733     my $part = shift;
734
735     # What is it?
736     my $type = "unknown";
737     eval {
738         $type = $g->vfs_type ($part);
739     };
740     $partitions{$part}->{type} = $type;
741
742     # Can we get the actual size of this object (ie. to find out if it
743     # is smaller than the container for shrinking)?
744     my $fssize;
745     if ($type eq "LVM2_member") { # LVM PV
746         foreach (@pvs_full) {
747             $fssize = $_->{pv_size}
748               if canonicalize ($_->{pv_name}) eq $part;
749         }
750     } else {                    # Something mountable?
751         eval {
752             $g->mount_ro ($part, "/");
753
754             my %stat = $g->statvfs ("/");
755             $fssize = $stat{bsize} * $stat{blocks};
756         };
757
758         eval {
759             $g->umount_all ();
760         };
761     }
762
763     # This might be undef if we didn't successfully find the size.  In
764     # that case user won't be allowed to shrink this partition except
765     # by forcing it.
766     $partitions{$part}->{fssize} = $fssize;
767
768     # Is it partition content that we know how to expand?
769     $partitions{$part}->{can_expand_content} = 0;
770     if ($expand_content) {
771         if ($type eq "LVM2_member") {
772             $partitions{$part}->{can_expand_content} = 1;
773             $partitions{$part}->{expand_content_method} = "pvresize";
774         } elsif ($type =~ /^ext[234]$/) {
775             $partitions{$part}->{can_expand_content} = 1;
776             $partitions{$part}->{expand_content_method} = "resize2fs";
777         } elsif ($type eq "ntfs" && feature_available ($g, "ntfsprogs")) {
778             $partitions{$part}->{can_expand_content} = 1;
779             $partitions{$part}->{expand_content_method} = "ntfsresize";
780         }
781     }
782 }
783
784 if ($debug) {
785     print "partitions found: ", join (", ", @partitions), "\n";
786     foreach my $part (@partitions) {
787         print "$part:\n";
788         foreach (sort keys %{$partitions{$part}}) {
789             print("\t", $_, " = ",
790                   defined ($partitions{$part}->{$_})
791                   ? $partitions{$part}->{$_} : "undef",
792                   "\n");
793         }
794     }
795 }
796
797 # Examine the LVs (for --lv-expand option).
798 my @lvs = $g->lvs ();
799 my %lvs;
800 examine_lv ($_) foreach @lvs;
801 mark_lvs_to_expand ();
802
803 sub examine_lv
804 {
805     local $_ = shift;
806
807     $lvs{$_}->{name} = $_;
808
809     my $type = "unknown";
810     eval {
811         $type = $g->vfs_type ($_);
812     };
813     $lvs{$_}->{type} = $type;
814
815     if ($expand_content) {
816         if ($type =~ /^ext[234]$/) {
817             $lvs{$_}->{can_expand_content} = 1;
818             $lvs{$_}->{expand_content_method} = "resize2fs";
819         } elsif ($type eq "ntfs" && feature_available ($g, "ntfsprogs")) {
820             $lvs{$_}->{can_expand_content} = 1;
821             $lvs{$_}->{expand_content_method} = "ntfsresize";
822         }
823     }
824 }
825
826 sub mark_lvs_to_expand {
827     local $_;
828
829     foreach (@lv_expand) {
830         die __x("virt-resize: no logical volume called {n}\n",
831                 n => $_)
832             unless exists $lvs{$_};
833
834         if ($lvs{$_}->{can_expand_content}) {
835             $lvs{$_}->{will_expand_content} = 1;
836             $to_be_expanded++;
837         }
838     }
839 }
840
841 sub find_partition
842 {
843     local $_ = shift;
844     my $option = shift;
845
846     $_ = "/dev/$_" unless $_ =~ m{^/dev};
847     $_ = canonicalize ($_);
848
849     unless (exists $partitions{$_}) {
850         die __x("{p}: partition not found in the source disk image, when using the '{opt}' command line option\n",
851                 p => $_,
852                 opt => $option)
853     }
854
855     if ($partitions{$_}->{ignore}) {
856         die __x("{p}: partition ignored, you cannot use it in another command line argument\n",
857                 p => $_)
858     }
859     if ($partitions{$_}->{delete}) {
860         die __x("{p}: partition deleted, you cannot use it in another command line argument\n",
861                 p => $_)
862     }
863
864     return $_;
865 }
866
867 # Handle --ignore.
868 do_ignore ($_) foreach @ignore;
869
870 sub do_ignore
871 {
872     local $_ = shift;
873     $_ = find_partition ($_, "--ignore");
874     $partitions{$_}->{ignore} = 1;
875 }
876
877 # Handle --delete.
878 do_delete ($_) foreach @delete;
879
880 sub do_delete
881 {
882     local $_ = shift;
883     $_ = find_partition ($_, "--delete");
884     $partitions{$_}->{delete} = 1;
885 }
886
887 # Handle --resize and --resize-force.
888 do_resize ($_, 0, "--resize") foreach @resize;
889 do_resize ($_, 1, "--resize-force") foreach @resize_force;
890
891 sub do_resize
892 {
893     local $_ = shift;
894     my $force = shift;
895     my $option = shift;
896
897     # Argument is "part=size" ...
898     my ($part, $sizefield) = split /=/, $_, 2;
899     $part = find_partition ($part, $option);
900
901     if (exists $partitions{$part}->{newsize}) {
902         die __x("{p}: this partition has already been marked for resizing\n",
903                 p => $part);
904     }
905
906     # Parse the size field.
907     my $oldsize = $partitions{$part}->{part_size};
908     my $newsize;
909     if (!defined ($sizefield) || $sizefield eq "") {
910         die __x("{p}: missing size field in {o} option\n",
911                 p => $part, o => $option);
912     } elsif ($sizefield =~ /^([.\d]+)([bKMGTPE])$/) {
913         $newsize = sizebytes ($1, $2);
914     } elsif ($sizefield =~ /^\+([.\d]+)([bKMGTPE])$/) {
915         my $incr = sizebytes ($1, $2);
916         $newsize = $oldsize + $incr;
917     } elsif ($sizefield =~ /^-([.\d]+)([bKMGTPE])$/) {
918         my $decr = sizebytes ($1, $2);
919         $newsize = $oldsize - $decr;
920     } elsif ($sizefield =~ /^([.\d]+)%$/) {
921         $newsize = $oldsize * $1 / 100;
922     } elsif ($sizefield =~ /^\+([.\d]+)%$/) {
923         $newsize = $oldsize + $oldsize * $1 / 100;
924     } elsif ($sizefield =~ /^-([.\d]+)%$/) {
925         $newsize = $oldsize - $oldsize * $1 / 100;
926     } else {
927         die __x("{p}: {f}: cannot parse size field\n",
928                 p => $part, f => $sizefield)
929     }
930
931     $newsize > 0 or
932         die __x("{p}: new size is zero or negative\n", p => $part);
933
934     mark_partition_for_resize ($part, $oldsize, $newsize, $force, $option);
935 }
936
937 sub mark_partition_for_resize
938 {
939     local $_;
940     my $part = shift;
941     my $oldsize = shift;
942     my $newsize = shift;
943     my $force = shift;
944     my $option = shift;
945
946     # Do nothing if the size is the same.
947     return if $oldsize == $newsize;
948
949     my $bigger = $newsize > $oldsize;
950
951     # Check there is space to shrink this.
952     unless ($bigger || $force) {
953         if (! $partitions{$part}->{fssize} ||
954             $partitions{$part}->{fssize} > $newsize) {
955             die __x("{p}: cannot make this partition smaller because it contains a\nfilesystem, physical volume or other content that is larger than the new size.\nYou have to resize the content first, see virt-resize(1).\n",
956                     p => $part);
957         }
958     }
959
960     $partitions{$part}->{newsize} = $newsize;
961
962     if ($partitions{$part}->{can_expand_content} && $bigger) {
963         $partitions{$part}->{will_expand_content} = 1;
964         $to_be_expanded++;
965     }
966 }
967
968 # Handle --expand and --shrink.
969 my $surplus;
970 if (defined $expand && defined $shrink) {
971     die __"virt-resize: you cannot use options --expand and --shrink together\n"
972 }
973 if (defined $expand || defined $shrink) {
974     calculate_surplus ();
975
976     if ($debug) {
977         print "surplus before --expand or --shrink: $surplus (",
978           human_size ($surplus), ")\n";
979     }
980
981     do_expand () if $expand;
982     do_shrink () if $shrink;
983 }
984
985 # (Re-)calculate surplus after doing expand or shrink.
986 calculate_surplus ();
987
988 # Add up the total space required on the target so far, compared
989 # to the size of the target.  We end up with a surplus or deficit.
990 sub calculate_surplus
991 {
992     local $_;
993
994     # We need some overhead for partitioning.  Worst case would be for
995     # EFI partitioning + massive per-partition alignment.
996     my $overhead = $sectsize * (
997         2 * 64 +                   # GPT start and end
998         (64 * (@partitions + 1))   # Maximum alignment
999         ) +
1000         ($max_bootloader - 64 * 512); # boot loader
1001
1002     my $required = 0;
1003     foreach (@partitions) {
1004         if ($partitions{$_}->{newsize}) {
1005             $required += $partitions{$_}->{newsize}
1006         } else {
1007             $required += $partitions{$_}->{part_size}
1008         }
1009     }
1010
1011     # Compare that to the actual target disk.
1012     $surplus = $outsize - ($required + $overhead);
1013 }
1014
1015 sub do_expand
1016 {
1017     local $_;
1018
1019     unless ($surplus > 0) {
1020         die __x("virt-resize: error: cannot use --expand when there is no surplus space to\nexpand into.  You need to make the target disk larger by at least {h}.\n",
1021                 h => human_size (-$surplus));
1022     }
1023
1024     my $part = find_partition ($expand, "--expand");
1025     my $oldsize = $partitions{$part}->{part_size};
1026     mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus,
1027                                0, "--expand");
1028 }
1029
1030 sub do_shrink
1031 {
1032     local $_;
1033
1034     unless ($surplus < 0) {
1035         die __"virt-resize: error: cannot use --shrink because there is no deficit\n(see 'deficit' in the virt-resize(1) man page)\n"
1036     }
1037
1038     my $part = find_partition ($shrink, "--shrink");
1039     my $oldsize = $partitions{$part}->{part_size};
1040     mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus,
1041                                0, "--shrink");
1042 }
1043
1044 # Print summary.
1045 print_summary () unless $quiet;
1046
1047 sub print_summary
1048 {
1049     local $_;
1050     print __"Summary of changes:\n";
1051
1052     foreach my $part (@partitions) {
1053         if ($partitions{$part}->{ignore}) {
1054             print __x("{p}: partition will be ignored\n", p => $part);
1055         } elsif ($partitions{$part}->{delete}) {
1056             print __x("{p}: partition will be deleted\n", p => $part);
1057         } elsif ($partitions{$part}->{newsize}) {
1058             print __x("{p}: partition will be resized from {oldsize} to {newsize}\n",
1059                       p => $part,
1060                       oldsize => human_size ($partitions{$part}->{part_size}),
1061                       newsize => human_size ($partitions{$part}->{newsize}));
1062             if ($partitions{$part}->{will_expand_content}) {
1063                 print __x("{p}: content will be expanded using the '{meth}' method\n",
1064                           p => $part,
1065                           meth => $partitions{$part}->{expand_content_method});
1066             }
1067         } else {
1068             print __x("{p}: partition will be left alone\n", p => $part);
1069         }
1070     }
1071
1072     foreach my $lv (@lv_expand) {
1073         print __x("{n}: LV will be expanded to maximum size\n",
1074                   n => $lv);
1075     }
1076
1077     foreach my $lv (@lvs) {
1078         if ($lvs{$lv}->{will_expand_content}) {
1079             print __x("{n}: content will be expanded using the '{meth}' method\n",
1080                       n => $lv,
1081                       meth => $lvs{$lv}->{expand_content_method});
1082         }
1083     }
1084
1085     if ($surplus > 0) {
1086         print __x("There is a surplus of {spl} bytes ({h}).\n",
1087                   spl => $surplus,
1088                   h => human_size ($surplus));
1089         if ($extra_partition) {
1090             if ($surplus >= $min_extra_partition) {
1091                 print __"An extra partition will be created for the surplus.\n";
1092             } else {
1093                 print __"The surplus space is not large enough for an extra partition to be created\nand so it will just be ignored.\n";
1094             }
1095         } else {
1096             print __"The surplus space will be ignored.  Run a partitioning program in the guest\nto partition this extra space if you want.\n";
1097         }
1098     } elsif ($surplus < 0) {
1099         die __x("virt-resize: error: there is a deficit of {def} bytes ({h}).\nYou need to make the target disk larger by at least this amount,\nor adjust your resizing requests.\n",
1100                 def => -$surplus,
1101                 h => human_size (-$surplus));
1102     }
1103 }
1104
1105 exit 0 if $dryrun;
1106
1107 # Repartition the target disk.
1108 my $nextpart = 1;
1109 repartition ();
1110
1111 sub repartition
1112 {
1113     local $_;
1114
1115     # Work out where to start the first partition.
1116     die __"virt-resize: source disk does not have a first partition\n"
1117         unless exists ($partitions{"/dev/sda1"});
1118     my $start = $partitions{"/dev/sda1"}->{part_start} / $sectsize;
1119
1120     # Align to 64.
1121     $start = ($start + 63) & ~63;
1122
1123     print "starting to partition from $start\n" if $debug;
1124
1125     # Create the new partitions.
1126     foreach my $part (@partitions) {
1127         unless ($partitions{$part}->{delete}) {
1128             # Size in sectors.
1129             my $size;
1130             if ($partitions{$part}->{newsize}) {
1131                 $size = ($partitions{$part}->{newsize} + $sectsize - 1)
1132                     / $sectsize;
1133             } else {
1134                 $size = ($partitions{$part}->{part_size} + $sectsize - 1)
1135                     / $sectsize;
1136             }
1137
1138             # Create it.
1139             my ($target, $end, $part_num) = add_partition ($start, $size);
1140             $partitions{$part}->{target} = $target;
1141
1142             if ($partitions{$part}->{bootable}) {
1143                 $g->part_set_bootable ("/dev/sdb", $part_num, 1);
1144             }
1145
1146             if ($partitions{$part}->{mbr_id}) {
1147                 $g->part_set_mbr_id ("/dev/sdb", $part_num,
1148                                      $partitions{$part}->{mbr_id});
1149             }
1150
1151             # Start of next partition + alignment.
1152             $start = $end + 1;
1153             $start = ($start + 63) & ~63;
1154         }
1155     }
1156
1157     # Create surplus partition.
1158     if ($extra_partition && $surplus >= $min_extra_partition) {
1159         add_partition ($start, $outsize / $sectsize - 64 - $start);
1160     }
1161 }
1162
1163 # Add a partition.
1164 sub add_partition
1165 {
1166     local $_;
1167     my $start = shift;
1168     my $size = shift;
1169
1170     my ($target, $end, $part_num);
1171
1172     if ($nextpart <= 3 || $parttype ne "msdos") {
1173         $target = "/dev/sdb$nextpart";
1174         $end = $start + $size - 1;
1175         $g->part_add ("/dev/sdb", "primary", $start, $end);
1176         $part_num = $nextpart++;
1177     } else {
1178         if ($nextpart == 4) {
1179             $g->part_add ("/dev/sdb", "extended", $start, -1);
1180             $part_num = $nextpart++;
1181             $start += 64;
1182         }
1183         $target = "/dev/sdb$nextpart";
1184         $end = $start + $size - 1;
1185         $g->part_add ("/dev/sdb", "logical", $start, $end);
1186         $part_num = $nextpart++;
1187     }
1188
1189     return ($target, $end, $part_num);
1190 }
1191
1192 # Copy over the data.
1193 copy_data ();
1194
1195 sub copy_data
1196 {
1197     foreach my $part (@partitions)
1198     {
1199         unless ($partitions{$part}->{ignore}) {
1200             my $target = $partitions{$part}->{target};
1201             if ($target) {
1202                 my $oldsize = $partitions{$part}->{part_size};
1203                 my $newsize;
1204                 if ($partitions{$part}->{newsize}) {
1205                     $newsize = $partitions{$part}->{newsize};
1206                 } else {
1207                     $newsize = $partitions{$part}->{part_size};
1208                 }
1209
1210                 if (!$quiet && !$debug) {
1211                     print __x("Copying {p} ...\n", p => $part);
1212                 }
1213
1214                 $g->copy_size ($part, $target,
1215                                $newsize < $oldsize ? $newsize : $oldsize);
1216             }
1217         }
1218     }
1219 }
1220
1221 # After copying the data over we must shut down and restart the
1222 # appliance in order to expand the content.  The reason for this may
1223 # not be obvious, but it's because otherwise we'll have duplicate VGs
1224 # (the old VG(s) and the new VG(s)) which breaks LVM.
1225 #
1226 # The restart is only required if we're going to expand something.
1227
1228 if ($to_be_expanded > 0) {
1229     restart_appliance ();
1230     expand_partitions ();
1231     expand_lvs ();
1232     expand_lvs_content ();
1233 }
1234
1235 sub restart_appliance
1236 {
1237     # Sync disk and exit.
1238     $g->umount_all ();
1239     $g->sync ();
1240     undef $g;
1241
1242     $g = Sys::Guestfs->new ();
1243     $g->set_trace (1) if $debug;
1244     my @args = ($outfile);
1245     push @args, format => $output_format if defined $output_format;
1246     $g->add_drive_opts (@args);
1247     $g->launch ();
1248
1249     # Target partitions have changed from /dev/sdb to /dev/sda,
1250     # so change them.
1251     foreach my $part (@partitions)
1252     {
1253         my $target = $partitions{$part}->{target};
1254         if ($target) {
1255             if ($target =~ m{/dev/(.)db(.*)}) {
1256                 $partitions{$part}->{target} = "/dev/$1da$2";
1257             } else {
1258                 die "internal error: unexpected partition target: $target";
1259             }
1260         }
1261     }
1262 }
1263
1264 sub expand_partitions
1265 {
1266     foreach my $part (@partitions)
1267     {
1268         unless ($partitions{$part}->{ignore}) {
1269             my $target = $partitions{$part}->{target};
1270             if ($target) {
1271                 # Expand if requested.
1272                 if ($partitions{$part}->{will_expand_content}) {
1273                     if (!$quiet && !$debug) {
1274                         print __x("Expanding {p} using the '{meth}' method\n",
1275                                   p => $part,
1276                                   meth => $partitions{$part}->{expand_content_method});
1277                     }
1278                     expand_target_partition ($part)
1279                 }
1280             }
1281         }
1282     }
1283 }
1284
1285 sub expand_target_partition
1286 {
1287     local $_;
1288     my $part = shift;
1289
1290     # Assertions.
1291     die unless $part;
1292     die unless $partitions{$part}->{can_expand_content};
1293     die unless $partitions{$part}->{will_expand_content};
1294     die unless $partitions{$part}->{expand_content_method};
1295     die unless $partitions{$part}->{target};
1296     die unless $expand_content;
1297
1298     my $target = $partitions{$part}->{target};
1299     my $method = $partitions{$part}->{expand_content_method};
1300     if ($method eq "pvresize") {
1301         $g->pvresize ($target);
1302     }
1303     elsif ($method eq "resize2fs") {
1304         $g->e2fsck_f ($target);
1305         $g->resize2fs ($target);
1306     }
1307     elsif ($method eq "ntfsresize") {
1308         $g->ntfsresize ($target);
1309     }
1310     else {
1311         die "internal error: unknown method: $method";
1312     }
1313 }
1314
1315 sub expand_lvs
1316 {
1317     local $_;
1318
1319     foreach (@lv_expand) {
1320         $g->lvresize_free ($_, 100);
1321     }
1322 }
1323
1324 sub expand_lvs_content
1325 {
1326     local $_;
1327
1328     foreach (@lvs) {
1329         if ($lvs{$_}->{will_expand_content}) {
1330             my $method = $lvs{$_}->{expand_content_method};
1331             if (!$quiet && !$debug) {
1332                 print __x("Expanding {p} using the '{meth}' method\n",
1333                           p => $_, meth => $method);
1334                     }
1335             if ($method eq "resize2fs") {
1336                 $g->e2fsck_f ($_);
1337                 $g->resize2fs ($_);
1338             } elsif ($method eq "ntfsresize") {
1339                 $g->ntfsresize ($_);
1340             } else {
1341                 die "internal error: unknown method: $method";
1342             }
1343         }
1344     }
1345 }
1346
1347 # Sync disk and exit.
1348 $g->umount_all ();
1349 $g->sync ();
1350 undef $g;
1351
1352 exit 0;
1353
1354 sub sizebytes
1355 {
1356     local $_ = shift;
1357     my $unit = shift;
1358
1359     $_ *= 1024 if $unit =~ /[KMGTPE]/;
1360     $_ *= 1024 if $unit =~ /[MGTPE]/;
1361     $_ *= 1024 if $unit =~ /[GTPE]/;
1362     $_ *= 1024 if $unit =~ /[TPE]/;
1363     $_ *= 1024 if $unit =~ /[PE]/;
1364     $_ *= 1024 if $unit =~ /[E]/;
1365
1366     return floor($_);
1367 }
1368
1369 # Convert a number of bytes to a human-readable number.
1370 sub human_size
1371 {
1372     local $_ = shift;
1373
1374     my $sgn = "";
1375     if ($_ < 0) {
1376         $sgn = "-";
1377         $_ = -$_;
1378     }
1379
1380     $_ /= 1024;
1381
1382     if ($_ < 1024) {
1383         sprintf "%s%dK", $sgn, $_;
1384     } elsif ($_ < 1024 * 1024) {
1385         sprintf "%s%.1fM", $sgn, ($_ / 1024);
1386     } else {
1387         sprintf "%s%.1fG", $sgn, ($_ / 1024 / 1024);
1388     }
1389 }
1390
1391 # The reverse of device name translation, see
1392 # BLOCK DEVICE NAMING in guestfs(3).
1393 sub canonicalize
1394 {
1395     local $_ = shift;
1396
1397     if (m{^/dev/[hv]d([a-z]\d)$}) {
1398         return "/dev/sd$1";
1399     }
1400     $_;
1401 }
1402
1403 # Not as sophisticated as the guestfish progress bar, because
1404 # I intend to use an external library for this at some point (XXX).
1405 sub progress_callback
1406 {
1407     my $proc_nr = shift;
1408     my $serial = shift;
1409     my $position = shift;
1410     my $total = shift;
1411
1412     my $ratio = $position / $total;
1413     if ($ratio < 0) { $ratio = 0 }
1414     elsif ($ratio > 1) { $ratio = 1 }
1415
1416     my $dots = int ($ratio * 76);
1417
1418     print "[", "#"x$dots, "-"x(76-$dots), "]\r";
1419     print "\n" if $ratio == 1;
1420 }
1421
1422 =head1 NOTES
1423
1424 =head2 "Partition 1 does not end on cylinder boundary."
1425
1426 Virt-resize aligns partitions to multiples of 64 sectors.  Usually
1427 this means the partitions will not be aligned to the ancient CHS
1428 geometry.  However CHS geometry is meaningless for disks manufactured
1429 since the early 1990s, and doubly so for virtual hard drives.
1430 Alignment of partitions to cylinders is not required by any modern
1431 operating system.
1432
1433 =head2 RESIZING WINDOWS VIRTUAL MACHINES
1434
1435 In Windows Vista and later versions, Microsoft switched to using a
1436 separate boot partition.  In these VMs, typically C</dev/sda1> is the
1437 boot partition and C</dev/sda2> is the main (C:) drive.  We have not
1438 had any luck resizing the boot partition.  Doing so seems to break the
1439 guest completely.  However expanding the second partition (ie. C:
1440 drive) should work.
1441
1442 Windows may initiate a lengthy "chkdsk" on first boot after a resize,
1443 if NTFS partitions have been expanded.  This is just a safety check
1444 and (unless it find errors) is nothing to worry about.
1445
1446 =head2 GUEST BOOT STUCK AT "GRUB"
1447
1448 If a Linux guest does not boot after resizing, and the boot is stuck
1449 after printing C<GRUB> on the console, try reinstalling grub.  This
1450 sometimes happens on older (RHEL 5-era) guests, for reasons we don't
1451 fully understand, although we think is to do with partition alignment.
1452
1453  guestfish -i -a newdisk
1454  ><fs> cat /boot/grub/device.map
1455  # check the contents of this file are sensible or
1456  # edit the file if necessary
1457  ><fs> grub-install / /dev/vda
1458  ><fs> exit
1459
1460 For more flexible guest reconfiguration, including if you need to
1461 specify other parameters to grub-install, use L<virt-rescue(1)>.
1462
1463 =head1 ALTERNATIVE TOOLS
1464
1465 There are several proprietary tools for resizing partitions.  We
1466 won't mention any here.
1467
1468 L<parted(8)> and its graphical shell gparted can do some types of
1469 resizing operations on disk images.  They can resize and move
1470 partitions, but I don't think they can do anything with the contents,
1471 and they certainly don't understand LVM.
1472
1473 L<guestfish(1)> can do everything that virt-resize can do and a lot
1474 more, but at a much lower level.  You will probably end up
1475 hand-calculating sector offsets, which is something that virt-resize
1476 was designed to avoid.  If you want to see the guestfish-equivalent
1477 commands that virt-resize runs, use the C<--debug> flag.
1478
1479 =head1 SHELL QUOTING
1480
1481 Libvirt guest names can contain arbitrary characters, some of which
1482 have meaning to the shell such as C<#> and space.  You may need to
1483 quote or escape these characters on the command line.  See the shell
1484 manual page L<sh(1)> for details.
1485
1486 =head1 SEE ALSO
1487
1488 L<virt-list-partitions(1)>,
1489 L<virt-list-filesystems(1)>,
1490 L<virt-df(1)>,
1491 L<guestfs(3)>,
1492 L<guestfish(1)>,
1493 L<lvm(8)>,
1494 L<pvresize(8)>,
1495 L<lvresize(8)>,
1496 L<resize2fs(8)>,
1497 L<ntfsresize(8)>,
1498 L<virsh(1)>,
1499 L<parted(8)>,
1500 L<truncate(1)>,
1501 L<fallocate(1)>,
1502 L<grub(8)>,
1503 L<grub-install(8)>,
1504 L<virt-rescue(1)>,
1505 L<Sys::Guestfs(3)>,
1506 L<http://libguestfs.org/>.
1507
1508 =head1 AUTHOR
1509
1510 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
1511
1512 =head1 COPYRIGHT
1513
1514 Copyright (C) 2010 Red Hat Inc.
1515
1516 This program is free software; you can redistribute it and/or modify
1517 it under the terms of the GNU General Public License as published by
1518 the Free Software Foundation; either version 2 of the License, or
1519 (at your option) any later version.
1520
1521 This program is distributed in the hope that it will be useful,
1522 but WITHOUT ANY WARRANTY; without even the implied warranty of
1523 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1524 GNU General Public License for more details.
1525
1526 You should have received a copy of the GNU General Public License
1527 along with this program; if not, write to the Free Software
1528 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.