resize: Refresh the examples in the documentation.
[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 Fcntl qw(S_ISREG SEEK_SET);
24 use POSIX qw(floor);
25 use Pod::Usage;
26 use Getopt::Long;
27 use Data::Dumper;
28 use Locale::TextDomain 'libguestfs';
29
30 $Data::Dumper::Sortkeys = 1;
31
32 die __"virt-resize: sorry this program does not work on a 32 bit host\n"
33     if ~1 == 4294967294;
34
35 =encoding utf8
36
37 =head1 NAME
38
39 virt-resize - Resize a virtual machine disk
40
41 =head1 SYNOPSIS
42
43  virt-resize [--resize /dev/sdaN=[+/-]<size>[%]] [--expand /dev/sdaN]
44    [--shrink /dev/sdaN] [--ignore /dev/sdaN] [--delete /dev/sdaN] [...]
45    indisk outdisk
46
47 =head1 DESCRIPTION
48
49 Virt-resize is a tool which can resize a virtual machine disk, making
50 it larger or smaller overall, and resizing or deleting any partitions
51 contained within.
52
53 Virt-resize B<cannot> resize disk images in-place.  Virt-resize
54 B<should not> be used on live virtual machines - for consistent
55 results, shut the virtual machine down before resizing it.
56
57 If you are not familiar with the associated tools:
58 L<virt-list-partitions(1)>,
59 L<virt-list-filesystems(1)> and
60 L<virt-df(1)>,
61 we recommend you go and read those manual pages first.
62
63 =head2 EXAMPLES
64
65 Copy C<olddisk> to C<newdisk>, extending one of the guest's partitions
66 to fill the extra 5GB of space.
67
68  virt-list-partitions -lh olddisk
69  # Make a new blank disk which is larger than the old disk file.
70  dd if=/dev/zero of=newdisk bs=1024k count=15000
71  # Note "/dev/sda2" is a partition inside the "olddisk" file.
72  virt-resize --expand /dev/sda2 olddisk newdisk
73
74 As above, but make the /boot partition 200MB bigger, while giving the
75 remaining space to /dev/sda2:
76
77  virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 olddisk newdisk
78
79 =head2 DETAILED USAGE
80
81 This describes the common case where you want to expand an image to
82 give your guest more space.  Shrinking images is considerably more
83 complicated (unfortunately).
84
85 =over 4
86
87 =item 1. Locate disk image
88
89 Locate the disk image that you want to resize.  It could be in a local
90 file or device.  If the guest is managed by libvirt, you can use
91 C<virsh dumpxml> like this to find the disk image name:
92
93  # virsh dumpxml guestname | xpath /domain/devices/disk/source
94  Found 1 nodes:
95  -- NODE --
96  <source dev="/dev/vg/lv_guest" />
97
98 =item 2. Look at current sizing
99
100 Use L<virt-list-partitions(1)> to display the current partitions and
101 sizes:
102
103  # virt-list-partitions -lh /dev/vg/lv_guest
104  /dev/sda1 ext3 101.9M
105  /dev/sda2 pv 7.9G
106
107 (This example is a virtual machine with an 8 GB disk which we would
108 like to expand up to 10 GB).
109
110 =item 3. Create destination disk
111
112 Virt-resize cannot do in-place disk modifications.  You have to have
113 space to store the resized destination disk.
114
115 To store the resized disk image in a file, create a file of a suitable
116 size:
117
118  # rm -f outdisk
119  # truncate -s 10G outdisk
120
121 Use L<lvcreate(1)> to create a logical volume:
122
123  # lvcreate -L 10G -n lv_name vg_name
124
125 Or use L<virsh(1)> vol-create-as to create a libvirt storage volume:
126
127  # virsh pool-list
128  # virsh vol-create-as poolname newvol 10G
129
130 =item 4. Resize
131
132  virt-resize indisk outdisk
133
134 This command just copies disk image C<indisk> to disk image C<outdisk>
135 I<without> resizing or changing any existing partitions.  If
136 C<outdisk> is larger, then an extra, empty partition is created at the
137 end of the disk covering the extra space.  If C<outdisk> is smaller,
138 then it will give an error.
139
140 To resize, you need to pass extra options (for the full list see the
141 L</OPTIONS> section below).
142
143 L</--expand> is the most useful option.  It expands the named
144 partition within the disk to fill any extra space:
145
146  virt-resize --expand /dev/sda2 indisk outdisk
147
148 (In this case, an extra partition is I<not> created at the end of the
149 disk, because there will be no unused space).
150
151 If /dev/sda2 in the image contains a filesystem or LVM PV, then
152 this content is B<not> automatically resized.  You can resize it
153 afterwards either using L<guestfish(1)> (offline) or using commands
154 inside the guest (online resizing).
155
156 L</--resize> is the other commonly used option.  The following would
157 increase the size of /dev/sda1 by 200M, and expand /dev/sda2
158 to fill the rest of the available space:
159
160  virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 \
161    indisk outdisk
162
163 Other options are covered below.
164
165 =item 5. Test
166
167 Thoroughly test the new disk image I<before> discarding the old one.
168
169 If you are using libvirt, edit the XML to point at the new disk:
170
171  # virsh edit guestname
172
173 Change E<lt>source ...E<gt>, see
174 L<http://libvirt.org/formatdomain.html#elementsDisks>
175
176 Then start up the domain with the new, resized disk:
177
178  # virsh start guestname
179
180 and check that it still works.
181
182 Note that to see the extra space in the guest, you may need to use
183 guest commands to resize PVs, LVs and/or filesystems to fit the extra
184 space available.  Three common guest commands for doing this for Linux
185 guests are L<pvresize(8)>, L<lvresize(8)> and L<resize2fs(8)>.  It is
186 also possible to do this offline (eg. for scripting changes) using
187 L<guestfish(1)>.
188
189 =back
190
191 =head1 OPTIONS
192
193 =over 4
194
195 =cut
196
197 my $help;
198
199 =item B<--help>
200
201 Display help.
202
203 =cut
204
205 my $version;
206
207 =item B<--version>
208
209 Display version number and exit.
210
211 =cut
212
213 my @resize;
214
215 =item B<--resize part=size>
216
217 Resize the named partition (expanding or shrinking it) so that it has
218 the given size.
219
220 C<size> can be expressed as an absolute number followed by
221 b/K/M/G/T/P/E to mean bytes, Kilobytes, Megabytes, Gigabytes,
222 Terabytes, Petabytes or Exabytes; or as a percentage of the current
223 size; or as a relative number or percentage.  For example:
224
225  --resize /dev/sda2=10G
226
227  --resize /dev/sda4=90%
228
229  --resize /dev/sda2=+1G
230
231  --resize /dev/sda2=-200M
232
233  --resize /dev/sda1=+128K
234
235  --resize /dev/sda1=+10%
236
237  --resize /dev/sda1=-10%
238
239 You can increase the size of any partition.
240
241 You can I<only> B<decrease> the size of partitions that contain
242 filesystems or PVs which have already been shrunk.  Virt-resize will
243 check this has been done before proceeding, or else will print an
244 error (see also C<--resize-force>).
245
246 You can give this option multiple times.
247
248 =cut
249
250 my @resize_force;
251
252 =item B<--resize-force part=size>
253
254 This is the same as C<--resize> except that it will let you decrease
255 the size of any partition.  Generally this means you will lose any
256 data which was at the end of the partition you shrink, but you may not
257 care about that (eg. if shrinking an unused partition, or if you can
258 easily recreate it such as a swap partition).
259
260 See also the C<--ignore> option.
261
262 =cut
263
264 my $expand;
265
266 =item B<--expand part>
267
268 Expand the named partition so it uses up all extra space (space left
269 over after any other resize changes that you request have been done).
270
271 Any filesystem inside the partition is I<not> expanded.  You will need
272 to expand the filesystem (or PV) to fit the extra space either using
273 L<guestfish(1)> (offline) or online guest tools.
274
275 Note that you cannot use C<--expand> and C<--shrink> together.
276
277 =cut
278
279 my $shrink;
280
281 =item B<--shrink part>
282
283 Shrink the named partition until the overall disk image fits in the
284 destination.  The named partition B<must> contain a filesystem or PV
285 which has already been shrunk using another tool (eg. L<guestfish(1)>
286 or other online tools).  Virt-resize will check this and give an error
287 if it has not been done.
288
289 The amount by which the overall disk must be shrunk (after carrying
290 out all other operations requested by the user) is called the
291 "deficit".  For example, a straight copy (assume no other operations)
292 from a 5GB disk image to a 4GB disk image results in a 1GB deficit.
293 In this case, virt-resize would give an error unless the user
294 specified a partition to shrink and that partition had more than a
295 gigabyte of free space.
296
297 Note that you cannot use C<--expand> and C<--shrink> together.
298
299 =cut
300
301 my @ignore;
302
303 =item B<--ignore part>
304
305 Ignore the named partition.  Effectively this means the partition is
306 allocated on the destination disk, but the content is not copied
307 across from the source disk.  The content of the partition will be
308 blank (all zero bytes).
309
310 You can give this option multiple times.
311
312 =cut
313
314 my @delete;
315
316 =item B<--delete part>
317
318 Delete the named partition.  It would be more accurate to describe
319 this as "don't copy it over", since virt-resize doesn't do in-place
320 changes and the original disk image is left intact.
321
322 Note that when you delete a partition, then anything contained in the
323 partition is also deleted.  Furthermore, this causes any partitions
324 that come after to be I<renumbered>, which can easily make your guest
325 unbootable.
326
327 You can give this option multiple times.
328
329 =cut
330
331 my $copy_boot_loader = 1;
332
333 =item B<--no-copy-boot-loader>
334
335 By default, virt-resize copies over some sectors at the start of the
336 disk (up to the beginning of the first partition).  Commonly these
337 sectors contain the Master Boot Record (MBR) and the boot loader, and
338 are required in order for the guest to boot correctly.
339
340 If you specify this flag, then this initial copy is not done.  You may
341 need to reinstall the boot loader in this case.
342
343 =cut
344
345 my $extra_partition = 1;
346 my $min_extra_partition = 10 * 1024 * 1024; # see below
347
348 =item B<--no-extra-partition>
349
350 By default, virt-resize creates an extra partition if there is any
351 extra, unused space after all resizing has happened.  Use this option
352 to prevent the extra partition from being created.  If you do this
353 then the extra space will be inaccessible until you run fdisk, parted,
354 or some other partitioning tool in the guest.
355
356 Note that if the surplus space is smaller than 10 MB, no extra
357 partition will be created.
358
359 =cut
360
361 my $debug;
362
363 =item B<-d> | B<--debug>
364
365 Enable debugging messages.
366
367 =cut
368
369 my $dryrun;
370
371 =item B<-n> | B<--dryrun>
372
373 Print a summary of what would be done, but don't do anything.
374
375 =cut
376
377 my $quiet;
378
379 =item B<-q> | B<--quiet>
380
381 Don't print the summary.
382
383 =back
384
385 =cut
386
387 GetOptions ("help|?" => \$help,
388             "version" => \$version,
389             "resize=s" => \@resize,
390             "resize-force=s" => \@resize_force,
391             "expand=s" => \$expand,
392             "shrink=s" => \$shrink,
393             "ignore=s" => \@ignore,
394             "delete=s" => \@delete,
395             "copy-boot-loader!" => \$copy_boot_loader,
396             "extra-partition!" => \$extra_partition,
397             "d|debug" => \$debug,
398             "n|dryrun" => \$dryrun,
399             "q|quiet" => \$quiet,
400     ) or pod2usage (2);
401 pod2usage (1) if $help;
402 if ($version) {
403     my $g = Sys::Guestfs->new ();
404     my %h = $g->version ();
405     print "$h{major}.$h{minor}.$h{release}$h{extra}\n";
406     exit
407 }
408
409 die "virt-resize [--options] indisk outdisk\n" unless @ARGV == 2;
410
411 # Check in and out images exist.
412 my $infile = $ARGV[0];
413 my $outfile = $ARGV[1];
414 die __x("virt-resize: {file}: does not exist or is not readable\n", file => $infile)
415     unless -r $infile;
416 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)
417     unless -w $outfile;
418
419 my @s;
420 @s = stat $infile;
421 my $insize = S_ISREG ($s[2]) ? $s[7] : host_blockdevsize ($infile);
422 @s = stat $outfile;
423 my $outsize = S_ISREG ($s[2]) ? $s[7] : host_blockdevsize ($outfile);
424
425 if ($debug) {
426     print "$infile size $insize bytes\n";
427     print "$outfile size $outsize bytes\n";
428 }
429
430 # In reality the number of sectors containing boot loader data will be
431 # less than this (although Windows 7 defaults to putting the first
432 # partition on sector 2048, and has quite a large boot loader).
433 #
434 # However make this large enough to be sure that we have copied over
435 # the boot loader.  We could also do this by looking for the sector
436 # offset of the first partition.
437 #
438 # It doesn't matter if we copy too much.
439 my $boot_sectors = 4096;
440
441 die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n",
442         file => $infile, sz => $insize)
443     if $insize < $boot_sectors * 512;
444 die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n",
445         file => $outfile, sz => $outsize)
446     if $outsize < $boot_sectors * 512;
447
448 # Copy the boot loader across.
449 do_copy_boot_loader () if $copy_boot_loader;
450
451 sub do_copy_boot_loader
452 {
453     print "copying boot loader ...\n" if $debug;
454     open IFILE, $infile or die "$infile: $!";
455     my $s;
456     my $r = sysread (IFILE, $s, $boot_sectors * 512) or die "$infile: $!";
457     die "$infile: short read" if $r < $boot_sectors * 512;
458     open OFILE, "+<$outfile" or die "$outfile: $!";
459     sysseek OFILE, 0, SEEK_SET or die "$outfile: seek: $!";
460     $r = syswrite (OFILE, $s, $boot_sectors * 512) or die "$outfile: $!";
461     die "$outfile: short write" if $r < $boot_sectors * 512;
462 }
463
464 # Add them to the handle and launch the appliance.
465 my $g;
466 launch_guestfs ();
467
468 sub launch_guestfs
469 {
470     $g = Sys::Guestfs->new ();
471     $g->set_trace (1) if $debug;
472     $g->add_drive_ro ($infile);
473     $g->add_drive ($outfile);
474     $g->launch ();
475 }
476
477 my $sectsize = $g->blockdev_getss ("/dev/sdb");
478
479 # Get the partitions on the source disk.
480 my @partitions;
481 my %partitions;
482 check_source_disk ();
483
484 sub check_source_disk
485 {
486     local $_;
487
488     # Partitions and PVs.
489     my @p = $g->part_list ("/dev/sda");
490     foreach (@p) {
491         my $name = "/dev/sda" . $_->{part_num};
492         push @partitions, $name;
493
494         my %h = %$_;
495         $h{name} = $name;
496         $h{bootable} = $g->part_get_bootable ("/dev/sda", $h{part_num});
497         eval { $h{mbr_id} = $g->part_get_mbr_id ("/dev/sda", $h{part_num}); };
498         $partitions{$name} = \%h;
499     }
500 }
501
502 # Examine each partition.
503 my @pvs_full = $g->pvs_full ();
504 examine_partition ($_) foreach @partitions;
505
506 sub examine_partition
507 {
508     local $_;
509     my $part = shift;
510
511     # What is it?
512     my $type = "unknown";
513     eval {
514         $type = $g->vfs_type ($part);
515     };
516     $partitions{$part}->{type} = $type;
517
518     # Can we get the actual size of this object (ie. to find out if it
519     # is smaller than the container for shrinking)?
520     my $fssize;
521     if ($type eq "LVM2_member") { # LVM PV
522         foreach (@pvs_full) {
523             $fssize = $_->{pv_size}
524               if canonicalize ($_->{pv_name}) eq $part;
525         }
526     } else {                    # Something mountable?
527         eval {
528             $g->mount_ro ($part, "/");
529
530             my %stat = $g->statvfs ("/");
531             $fssize = $stat{bsize} * $stat{blocks};
532         };
533
534         eval {
535             $g->umount_all ();
536         };
537     }
538
539     # This might be undef if we didn't successfully find the size.  In
540     # that case user won't be allowed to shrink this partition except
541     # by forcing it.
542     $partitions{$part}->{fssize} = $fssize;
543 }
544
545 if ($debug) {
546     print "partitions found: ", join (", ", @partitions), "\n";
547     foreach my $part (@partitions) {
548         print "$part:\n";
549         foreach (sort keys %{$partitions{$part}}) {
550             print("\t", $_, " = ",
551                   defined ($partitions{$part}->{$_})
552                   ? $partitions{$part}->{$_} : "undef",
553                   "\n");
554         }
555     }
556 }
557
558 sub find_partition
559 {
560     local $_ = shift;
561     my $option = shift;
562
563     $_ = "/dev/$_" unless $_ =~ m{^/dev};
564     $_ = canonicalize ($_);
565
566     unless (exists $partitions{$_}) {
567         die __x("{p}: partition not found in the source disk image, when using the '{opt}' command line option\n",
568                 p => $_,
569                 opt => $option)
570     }
571
572     if ($partitions{$_}->{ignore}) {
573         die __x("{p}: partition ignored, you cannot use it in another command line argument\n",
574                 p => $_)
575     }
576     if ($partitions{$_}->{delete}) {
577         die __x("{p}: partition deleted, you cannot use it in another command line argument\n",
578                 p => $_)
579     }
580
581     return $_;
582 }
583
584 # Handle --ignore.
585 do_ignore ($_) foreach @ignore;
586
587 sub do_ignore
588 {
589     local $_ = shift;
590     $_ = find_partition ($_, "--ignore");
591     $partitions{$_}->{ignore} = 1;
592 }
593
594 # Handle --delete.
595 do_delete ($_) foreach @delete;
596
597 sub do_delete
598 {
599     local $_ = shift;
600     $_ = find_partition ($_, "--delete");
601     $partitions{$_}->{delete} = 1;
602 }
603
604 # Handle --resize and --resize-force.
605 do_resize ($_, 0, "--resize") foreach @resize;
606 do_resize ($_, 1, "--resize-force") foreach @resize_force;
607
608 sub do_resize
609 {
610     local $_ = shift;
611     my $force = shift;
612     my $option = shift;
613
614     # Argument is "part=size" ...
615     my ($part, $sizefield) = split /=/, $_, 2;
616     $part = find_partition ($part, $option);
617
618     if (exists $partitions{$part}->{newsize}) {
619         die __x("{p}: this partition has already been marked for resizing\n",
620                 p => $part);
621     }
622
623     # Parse the size field.
624     my $oldsize = $partitions{$part}->{part_size};
625     my $newsize;
626     if (!defined ($sizefield) || $sizefield eq "") {
627         die __x("{p}: missing size field in {o} option\n",
628                 p => $part, o => $option);
629     } elsif ($sizefield =~ /^([.\d]+)([bKMGTPE])$/) {
630         $newsize = sizebytes ($1, $2);
631     } elsif ($sizefield =~ /^\+([.\d]+)([bKMGTPE])$/) {
632         my $incr = sizebytes ($1, $2);
633         $newsize = $oldsize + $incr;
634     } elsif ($sizefield =~ /^-([.\d]+)([bKMGTPE])$/) {
635         my $decr = sizebytes ($1, $2);
636         $newsize = $oldsize - $decr;
637     } elsif ($sizefield =~ /^([.\d]+)%$/) {
638         $newsize = $oldsize * $1 / 100;
639     } elsif ($sizefield =~ /^\+([.\d]+)%$/) {
640         $newsize = $oldsize + $oldsize * $1 / 100;
641     } elsif ($sizefield =~ /^-([.\d]+)%$/) {
642         $newsize = $oldsize - $oldsize * $1 / 100;
643     } else {
644         die __x("{p}: {f}: cannot parse size field\n",
645                 p => $part, f => $sizefield)
646     }
647
648     $newsize > 0 or
649         die __x("{p}: new size is zero or negative\n", p => $part);
650
651     mark_partition_for_resize ($part, $oldsize, $newsize, $force, $option);
652 }
653
654 sub mark_partition_for_resize
655 {
656     local $_;
657     my $part = shift;
658     my $oldsize = shift;
659     my $newsize = shift;
660     my $force = shift;
661     my $option = shift;
662
663     # Do nothing if the size is the same.
664     return if $oldsize == $newsize;
665
666     my $bigger = $newsize > $oldsize;
667
668     # Check there is space to shrink this.
669     unless ($bigger || $force) {
670         if (! $partitions{$part}->{fssize} ||
671             $partitions{$part}->{fssize} > $newsize) {
672             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",
673                     p => $part);
674         }
675     }
676
677     $partitions{$part}->{newsize} = $newsize;
678 }
679
680 # Handle --expand and --shrink.
681 my $surplus;
682 if (defined $expand && defined $shrink) {
683     die __"virt-resize: you cannot use options --expand and --shrink together\n"
684 }
685 if (defined $expand || defined $shrink) {
686     calculate_surplus ();
687
688     if ($debug) {
689         print "surplus before --expand or --shrink: $surplus (",
690           human_size ($surplus), ")\n";
691     }
692
693     do_expand () if $expand;
694     do_shrink () if $shrink;
695 }
696
697 # (Re-)calculate surplus after doing expand or shrink.
698 calculate_surplus ();
699
700 # Add up the total space required on the target so far, compared
701 # to the size of the target.  We end up with a surplus or deficit.
702 sub calculate_surplus
703 {
704     local $_;
705
706     # We need some overhead for partitioning.  Worst case would be for
707     # EFI partitioning + massive per-partition alignment.
708     my $overhead = $sectsize * (
709         2 * 64 +                   # GPT start and end
710         (64 * (@partitions + 1)) + # Maximum alignment
711         ($boot_sectors - 64)       # Boot loader
712         );
713
714     my $required = 0;
715     foreach (@partitions) {
716         if ($partitions{$_}->{newsize}) {
717             $required += $partitions{$_}->{newsize}
718         } else {
719             $required += $partitions{$_}->{part_size}
720         }
721     }
722
723     # Compare that to the actual target disk.
724     $surplus = $outsize - ($required + $overhead);
725 }
726
727 sub do_expand
728 {
729     local $_;
730
731     unless ($surplus > 0) {
732         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",
733                 h => human_size (-$surplus));
734     }
735
736     my $part = find_partition ($expand, "--expand");
737     my $oldsize = $partitions{$part}->{part_size};
738     mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus,
739                                0, "--expand");
740 }
741
742 sub do_shrink
743 {
744     local $_;
745
746     unless ($surplus < 0) {
747         die __"virt-resize: error: cannot use --shrink because there is no deficit\n(see 'deficit' in the virt-resize(1) man page)\n"
748     }
749
750     my $part = find_partition ($shrink, "--shrink");
751     my $oldsize = $partitions{$part}->{part_size};
752     mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus,
753                                0, "--shrink");
754 }
755
756 # Print summary.
757 print_summary () unless $quiet;
758
759 sub print_summary
760 {
761     local $_;
762     print __"Summary of changes:\n";
763
764     foreach my $part (@partitions) {
765         if ($partitions{$part}->{ignore}) {
766             print __x("{p}: partition will be ignored", p => $part);
767         } elsif ($partitions{$part}->{delete}) {
768             print __x("{p}: partition will be deleted", p => $part);
769         } elsif ($partitions{$part}->{newsize}) {
770             print __x("{p}: partition will be resized from {oldsize} to {newsize}",
771                       p => $part,
772                       oldsize => human_size ($partitions{$part}->{part_size}),
773                       newsize => human_size ($partitions{$part}->{newsize}));
774         } else {
775             print __x("{p}: partition will be left alone", p => $part);
776         }
777         print "\n"
778     }
779
780     if ($surplus > 0) {
781         print __x("There is a surplus of {spl} bytes ({h}).\n",
782                   spl => $surplus,
783                   h => human_size ($surplus));
784         if ($extra_partition) {
785             if ($surplus >= $min_extra_partition) {
786                 print __"An extra partition will be created for the surplus.\n";
787             } else {
788                 print __"The surplus space is not large enough for an extra partition to be created\nand so it will just be ignored.\n";
789             }
790         } else {
791             print __"The surplus space will be ignored.  Run a partitioning program in the guest\nto partition this extra space if you want.\n";
792         }
793     } elsif ($surplus < 0) {
794         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",
795                 def => -$surplus,
796                 h => human_size (-$surplus));
797     }
798 }
799
800 exit 0 if $dryrun;
801
802 # Repartition the target disk.
803 my $nextpart = 1;
804 my $parttype;
805 repartition ();
806
807 sub repartition
808 {
809     local $_;
810
811     if ($copy_boot_loader) {
812         $parttype = $g->part_get_parttype ("/dev/sdb");
813     } else {
814         $parttype = "efi";
815     }
816     print "partition table type: $parttype\n" if $debug;
817
818     # Delete any existing partitions on the destination disk,
819     # but leave the bootloader that we copied over intact.
820     if ($copy_boot_loader) {
821         # Delete in reverse as an easy way to deal with extended
822         # partitions.
823         foreach (sort { $b cmp $a } $g->list_partitions ()) {
824             if (m{^/dev/.db(\d+)$}) {
825                 $g->part_del ("/dev/sdb", $1);
826             }
827         }
828     } else {
829         # Didn't copy over the initial boot loader, so we need
830         # to make a new partition table here.
831         $g->part_init ("/dev/sdb", $parttype);
832     }
833
834     # Work out where to start the first partition.
835     die __"virt-resize: source disk does not have a first partition\n"
836         unless exists ($partitions{"/dev/sda1"});
837     my $start = $partitions{"/dev/sda1"}->{part_start} / $sectsize;
838
839     # Align to 64.
840     $start = ($start + 63) & ~63;
841
842     print "starting to partition from $start\n" if $debug;
843
844     # Create the new partitions.
845     foreach my $part (@partitions) {
846         unless ($partitions{$part}->{delete}) {
847             # Size in sectors.
848             my $size;
849             if ($partitions{$part}->{newsize}) {
850                 $size = ($partitions{$part}->{newsize} + $sectsize - 1)
851                     / $sectsize;
852             } else {
853                 $size = ($partitions{$part}->{part_size} + $sectsize - 1)
854                     / $sectsize;
855             }
856
857             # Create it.
858             my ($target, $end, $part_num) = add_partition ($start, $size);
859             $partitions{$part}->{target} = $target;
860
861             if ($partitions{$part}->{bootable}) {
862                 $g->part_set_bootable ("/dev/sdb", $part_num, 1);
863             }
864
865             if ($partitions{$part}->{mbr_id}) {
866                 $g->part_set_mbr_id ("/dev/sdb", $part_num,
867                                      $partitions{$part}->{mbr_id});
868             }
869
870             # Start of next partition + alignment.
871             $start = $end + 1;
872             $start = ($start + 63) & ~63;
873         }
874     }
875
876     # Create surplus partition.
877     if ($extra_partition && $surplus >= $min_extra_partition) {
878         add_partition ($start, $outsize / $sectsize - 64 - $start);
879     }
880 }
881
882 # Add a partition.
883 sub add_partition
884 {
885     local $_;
886     my $start = shift;
887     my $size = shift;
888
889     my ($target, $end, $part_num);
890
891     if ($nextpart <= 3 || $parttype ne "msdos") {
892         $target = "/dev/sdb$nextpart";
893         $end = $start + $size - 1;
894         $g->part_add ("/dev/sdb", "primary", $start, $end);
895         $part_num = $nextpart++;
896     } else {
897         if ($nextpart == 4) {
898             $g->part_add ("/dev/sdb", "extended", $start, -1);
899             $part_num = $nextpart++;
900             $start += 64;
901         }
902         $target = "/dev/sdb$nextpart";
903         $end = $start + $size - 1;
904         $g->part_add ("/dev/sdb", "logical", $start, $end);
905         $part_num = $nextpart++;
906     }
907
908     return ($target, $end, $part_num);
909 }
910
911 # Copy over the data.
912 copy_data ();
913
914 sub copy_data
915 {
916     foreach my $part (@partitions)
917     {
918         unless ($partitions{$part}->{ignore}) {
919             my $target = $partitions{$part}->{target};
920             if ($target) {
921                 my $oldsize = $partitions{$part}->{part_size};
922                 my $newsize;
923                 if ($partitions{$part}->{newsize}) {
924                     $newsize = $partitions{$part}->{newsize};
925                 } else {
926                     $newsize = $partitions{$part}->{part_size};
927                 }
928
929                 if (!$quiet && !$debug) {
930                     local $| = 1;
931                     print "Copying $part ...";
932                 }
933
934                 $g->copy_size ($part, $target,
935                                $newsize < $oldsize ? $newsize : $oldsize);
936
937                 if (!$quiet && !$debug) {
938                     print " done\n"
939                 }
940             }
941         }
942     }
943 }
944
945 # Sync disk and exit.
946 $g->umount_all ();
947 $g->sync ();
948 undef $g;
949
950 exit 0;
951
952 sub sizebytes
953 {
954     local $_ = shift;
955     my $unit = shift;
956
957     $_ *= 1024 if $unit =~ /[KMGTPE]/;
958     $_ *= 1024 if $unit =~ /[MGTPE]/;
959     $_ *= 1024 if $unit =~ /[GTPE]/;
960     $_ *= 1024 if $unit =~ /[TPE]/;
961     $_ *= 1024 if $unit =~ /[PE]/;
962     $_ *= 1024 if $unit =~ /[E]/;
963
964     return floor($_);
965 }
966
967 # Convert a number of bytes to a human-readable number.
968 sub human_size
969 {
970     local $_ = shift;
971
972     my $sgn = "";
973     if ($_ < 0) {
974         $sgn = "-";
975         $_ = -$_;
976     }
977
978     $_ /= 1024;
979
980     if ($_ < 1024) {
981         sprintf "%s%dK", $sgn, $_;
982     } elsif ($_ < 1024 * 1024) {
983         sprintf "%s%.1fM", $sgn, ($_ / 1024);
984     } else {
985         sprintf "%s%.1fG", $sgn, ($_ / 1024 / 1024);
986     }
987 }
988
989 # Return the size in bytes of a HOST block device.
990 sub host_blockdevsize
991 {
992     local $_;
993     my $dev = shift;
994
995     open BD, "PATH=/usr/sbin:/sbin:\$PATH blockdev --getsize64 $dev |"
996         or die "blockdev: $!";
997     $_ = <BD>;
998     chomp $_;
999     $_;
1000 }
1001
1002 # The reverse of device name translation, see
1003 # BLOCK DEVICE NAMING in guestfs(3).
1004 sub canonicalize
1005 {
1006     local $_ = shift;
1007
1008     if (m{^/dev/[hv]d([a-z]\d)$}) {
1009         return "/dev/sd$1";
1010     }
1011     $_;
1012 }
1013
1014 =head1 ALTERNATIVE TOOLS
1015
1016 There are several proprietary tools for resizing partitions.  We
1017 won't mention any here.
1018
1019 L<parted(8)> and its graphical shell gparted can do some types of
1020 resizing operations on disk images.  They can resize and move
1021 partitions, but I don't think they can do anything with the contents,
1022 and they certainly don't understand LVM.
1023
1024 L<guestfish(1)> can do everything that virt-resize can do and a lot
1025 more, but at a much lower level.  You will probably end up
1026 hand-calculating sector offsets, which is something that virt-resize
1027 was designed to avoid.  If you want to see the guestfish-equivalent
1028 commands that virt-resize runs, use the C<--debug> flag.
1029
1030 =head1 SEE ALSO
1031
1032 L<virt-list-partitions(1)>,
1033 L<virt-list-filesystems(1)>,
1034 L<virt-df(1)>,
1035 L<guestfs(3)>,
1036 L<guestfish(1)>,
1037 L<lvm(8)>,
1038 L<pvresize(8)>,
1039 L<lvresize(8)>,
1040 L<resize2fs(8)>,
1041 L<virsh(1)>,
1042 L<parted(8)>,
1043 L<Sys::Guestfs(3)>,
1044 L<http://libguestfs.org/>.
1045
1046 =head1 AUTHOR
1047
1048 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
1049
1050 =head1 COPYRIGHT
1051
1052 Copyright (C) 2010 Red Hat Inc.
1053
1054 This program is free software; you can redistribute it and/or modify
1055 it under the terms of the GNU General Public License as published by
1056 the Free Software Foundation; either version 2 of the License, or
1057 (at your option) any later version.
1058
1059 This program is distributed in the hope that it will be useful,
1060 but WITHOUT ANY WARRANTY; without even the implied warranty of
1061 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1062 GNU General Public License for more details.
1063
1064 You should have received a copy of the GNU General Public License
1065 along with this program; if not, write to the Free Software
1066 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.