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