3 # Copyright (C) 2010 Red Hat Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 use Fcntl qw(S_ISREG SEEK_SET);
28 use Locale::TextDomain 'libguestfs';
30 $Data::Dumper::Sortkeys = 1;
32 die __"virt-resize: sorry this program does not work on a 32 bit host\n"
39 virt-resize - Resize a virtual machine disk
43 virt-resize [--resize /dev/sdaN=[+/-]<size>[%]] [--expand /dev/sdaN]
44 [--shrink /dev/sdaN] [--ignore /dev/sdaN] [--delete /dev/sdaN] [...]
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
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.
57 If you are not familiar with the associated tools:
58 L<virt-list-partitions(1)>,
59 L<virt-list-filesystems(1)> and
61 we recommend you go and read those manual pages first.
65 Copy C<olddisk> to C<newdisk>, extending one of the guest's partitions
66 to fill the extra 5GB of space.
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
74 As above, but make the /boot partition 200MB bigger, while giving the
75 remaining space to /dev/sda2:
77 virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 olddisk newdisk
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).
87 =item 1. Locate disk image
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:
93 # virsh dumpxml guestname | xpath /domain/devices/disk/source
96 <source dev="/dev/vg/lv_guest" />
98 =item 2. Look at current sizing
100 Use L<virt-list-partitions(1)> to display the current partitions and
103 # virt-list-partitions -lh /dev/vg/lv_guest
104 /dev/sda1 ext3 101.9M
107 (This example is a virtual machine with an 8 GB disk which we would
108 like to expand up to 10 GB).
110 =item 3. Create destination disk
112 Virt-resize cannot do in-place disk modifications. You have to have
113 space to store the resized destination disk.
115 To store the resized disk image in a file, create a file of a suitable
119 # truncate -s 10G outdisk
121 Use L<lvcreate(1)> to create a logical volume:
123 # lvcreate -L 10G -n lv_name vg_name
125 Or use L<virsh(1)> vol-create-as to create a libvirt storage volume:
128 # virsh vol-create-as poolname newvol 10G
132 virt-resize indisk outdisk
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.
140 To resize, you need to pass extra options (for the full list see the
141 L</OPTIONS> section below).
143 L</--expand> is the most useful option. It expands the named
144 partition within the disk to fill any extra space:
146 virt-resize --expand /dev/sda2 indisk outdisk
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).
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).
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:
160 virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 \
163 Other options are covered below.
167 Thoroughly test the new disk image I<before> discarding the old one.
169 If you are using libvirt, edit the XML to point at the new disk:
171 # virsh edit guestname
173 Change E<lt>source ...E<gt>, see
174 L<http://libvirt.org/formatdomain.html#elementsDisks>
176 Then start up the domain with the new, resized disk:
178 # virsh start guestname
180 and check that it still works.
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
209 Display version number and exit.
215 =item B<--resize part=size>
217 Resize the named partition (expanding or shrinking it) so that it has
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:
225 --resize /dev/sda2=10G
227 --resize /dev/sda4=90%
229 --resize /dev/sda2=+1G
231 --resize /dev/sda2=-200M
233 --resize /dev/sda1=+128K
235 --resize /dev/sda1=+10%
237 --resize /dev/sda1=-10%
239 You can increase the size of any partition.
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>).
246 You can give this option multiple times.
252 =item B<--resize-force part=size>
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).
260 See also the C<--ignore> option.
266 =item B<--expand part>
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).
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.
275 Note that you cannot use C<--expand> and C<--shrink> together.
281 =item B<--shrink part>
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.
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.
297 Note that you cannot use C<--expand> and C<--shrink> together.
303 =item B<--ignore part>
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).
310 You can give this option multiple times.
316 =item B<--delete part>
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.
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
327 You can give this option multiple times.
331 my $copy_boot_loader = 1;
333 =item B<--no-copy-boot-loader>
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.
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.
345 my $extra_partition = 1;
346 my $min_extra_partition = 10 * 1024 * 1024; # see below
348 =item B<--no-extra-partition>
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.
356 Note that if the surplus space is smaller than 10 MB, no extra
357 partition will be created.
363 =item B<-d> | B<--debug>
365 Enable debugging messages.
371 =item B<-n> | B<--dryrun>
373 Print a summary of what would be done, but don't do anything.
379 =item B<-q> | B<--quiet>
381 Don't print the summary.
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,
401 pod2usage (1) if $help;
403 my $g = Sys::Guestfs->new ();
404 my %h = $g->version ();
405 print "$h{major}.$h{minor}.$h{release}$h{extra}\n";
409 die "virt-resize [--options] indisk outdisk\n" unless @ARGV == 2;
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)
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)
421 my $insize = S_ISREG ($s[2]) ? $s[7] : host_blockdevsize ($infile);
423 my $outsize = S_ISREG ($s[2]) ? $s[7] : host_blockdevsize ($outfile);
426 print "$infile size $insize bytes\n";
427 print "$outfile size $outsize bytes\n";
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).
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.
438 # It doesn't matter if we copy too much.
439 my $boot_sectors = 4096;
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;
448 # Copy the boot loader across.
449 do_copy_boot_loader () if $copy_boot_loader;
451 sub do_copy_boot_loader
453 print "copying boot loader ...\n" if $debug;
454 open IFILE, $infile or die "$infile: $!";
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;
464 # Add them to the handle and launch the appliance.
470 $g = Sys::Guestfs->new ();
471 $g->set_trace (1) if $debug;
472 $g->add_drive_ro ($infile);
473 $g->add_drive ($outfile);
477 my $sectsize = $g->blockdev_getss ("/dev/sdb");
479 # Get the partitions on the source disk.
482 check_source_disk ();
484 sub check_source_disk
488 # Partitions and PVs.
489 my @p = $g->part_list ("/dev/sda");
491 my $name = "/dev/sda" . $_->{part_num};
492 push @partitions, $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;
502 # Examine each partition.
503 my @pvs_full = $g->pvs_full ();
504 examine_partition ($_) foreach @partitions;
506 sub examine_partition
512 my $type = "unknown";
514 $type = $g->vfs_type ($part);
516 $partitions{$part}->{type} = $type;
518 # Can we get the actual size of this object (ie. to find out if it
519 # is smaller than the container for shrinking)?
521 if ($type eq "LVM2_member") { # LVM PV
522 foreach (@pvs_full) {
523 $fssize = $_->{pv_size}
524 if canonicalize ($_->{pv_name}) eq $part;
526 } else { # Something mountable?
528 $g->mount_ro ($part, "/");
530 my %stat = $g->statvfs ("/");
531 $fssize = $stat{bsize} * $stat{blocks};
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
542 $partitions{$part}->{fssize} = $fssize;
546 print "partitions found: ", join (", ", @partitions), "\n";
547 foreach my $part (@partitions) {
549 foreach (sort keys %{$partitions{$part}}) {
550 print("\t", $_, " = ",
551 defined ($partitions{$part}->{$_})
552 ? $partitions{$part}->{$_} : "undef",
563 $_ = "/dev/$_" unless $_ =~ m{^/dev};
564 $_ = canonicalize ($_);
566 unless (exists $partitions{$_}) {
567 die __x("{p}: partition not found in the source disk image, when using the '{opt}' command line option\n",
572 if ($partitions{$_}->{ignore}) {
573 die __x("{p}: partition ignored, you cannot use it in another command line argument\n",
576 if ($partitions{$_}->{delete}) {
577 die __x("{p}: partition deleted, you cannot use it in another command line argument\n",
585 do_ignore ($_) foreach @ignore;
590 $_ = find_partition ($_, "--ignore");
591 $partitions{$_}->{ignore} = 1;
595 do_delete ($_) foreach @delete;
600 $_ = find_partition ($_, "--delete");
601 $partitions{$_}->{delete} = 1;
604 # Handle --resize and --resize-force.
605 do_resize ($_, 0, "--resize") foreach @resize;
606 do_resize ($_, 1, "--resize-force") foreach @resize_force;
614 # Argument is "part=size" ...
615 my ($part, $sizefield) = split /=/, $_, 2;
616 $part = find_partition ($part, $option);
618 if (exists $partitions{$part}->{newsize}) {
619 die __x("{p}: this partition has already been marked for resizing\n",
623 # Parse the size field.
624 my $oldsize = $partitions{$part}->{part_size};
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;
644 die __x("{p}: {f}: cannot parse size field\n",
645 p => $part, f => $sizefield)
649 die __x("{p}: new size is zero or negative\n", p => $part);
651 mark_partition_for_resize ($part, $oldsize, $newsize, $force, $option);
654 sub mark_partition_for_resize
663 # Do nothing if the size is the same.
664 return if $oldsize == $newsize;
666 my $bigger = $newsize > $oldsize;
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",
677 $partitions{$part}->{newsize} = $newsize;
680 # Handle --expand and --shrink.
682 if (defined $expand && defined $shrink) {
683 die __"virt-resize: you cannot use options --expand and --shrink together\n"
685 if (defined $expand || defined $shrink) {
686 calculate_surplus ();
689 print "surplus before --expand or --shrink: $surplus (",
690 human_size ($surplus), ")\n";
693 do_expand () if $expand;
694 do_shrink () if $shrink;
697 # (Re-)calculate surplus after doing expand or shrink.
698 calculate_surplus ();
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
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
715 foreach (@partitions) {
716 if ($partitions{$_}->{newsize}) {
717 $required += $partitions{$_}->{newsize}
719 $required += $partitions{$_}->{part_size}
723 # Compare that to the actual target disk.
724 $surplus = $outsize - ($required + $overhead);
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));
736 my $part = find_partition ($expand, "--expand");
737 my $oldsize = $partitions{$part}->{part_size};
738 mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus,
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"
750 my $part = find_partition ($shrink, "--shrink");
751 my $oldsize = $partitions{$part}->{part_size};
752 mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus,
757 print_summary () unless $quiet;
762 print __"Summary of changes:\n";
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}",
772 oldsize => human_size ($partitions{$part}->{part_size}),
773 newsize => human_size ($partitions{$part}->{newsize}));
775 print __x("{p}: partition will be left alone", p => $part);
781 print __x("There is a surplus of {spl} bytes ({h}).\n",
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";
788 print __"The surplus space is not large enough for an extra partition to be created\nand so it will just be ignored.\n";
791 print __"The surplus space will be ignored. Run a partitioning program in the guest\nto partition this extra space if you want.\n";
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",
796 h => human_size (-$surplus));
802 # Repartition the target disk.
811 if ($copy_boot_loader) {
812 $parttype = $g->part_get_parttype ("/dev/sdb");
816 print "partition table type: $parttype\n" if $debug;
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
823 foreach (sort { $b cmp $a } $g->list_partitions ()) {
824 if (m{^/dev/.db(\d+)$}) {
825 $g->part_del ("/dev/sdb", $1);
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);
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;
840 $start = ($start + 63) & ~63;
842 print "starting to partition from $start\n" if $debug;
844 # Create the new partitions.
845 foreach my $part (@partitions) {
846 unless ($partitions{$part}->{delete}) {
849 if ($partitions{$part}->{newsize}) {
850 $size = ($partitions{$part}->{newsize} + $sectsize - 1)
853 $size = ($partitions{$part}->{part_size} + $sectsize - 1)
858 my ($target, $end, $part_num) = add_partition ($start, $size);
859 $partitions{$part}->{target} = $target;
861 if ($partitions{$part}->{bootable}) {
862 $g->part_set_bootable ("/dev/sdb", $part_num, 1);
865 if ($partitions{$part}->{mbr_id}) {
866 $g->part_set_mbr_id ("/dev/sdb", $part_num,
867 $partitions{$part}->{mbr_id});
870 # Start of next partition + alignment.
872 $start = ($start + 63) & ~63;
876 # Create surplus partition.
877 if ($extra_partition && $surplus >= $min_extra_partition) {
878 add_partition ($start, $outsize / $sectsize - 64 - $start);
889 my ($target, $end, $part_num);
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++;
897 if ($nextpart == 4) {
898 $g->part_add ("/dev/sdb", "extended", $start, -1);
899 $part_num = $nextpart++;
902 $target = "/dev/sdb$nextpart";
903 $end = $start + $size - 1;
904 $g->part_add ("/dev/sdb", "logical", $start, $end);
905 $part_num = $nextpart++;
908 return ($target, $end, $part_num);
911 # Copy over the data.
916 foreach my $part (@partitions)
918 unless ($partitions{$part}->{ignore}) {
919 my $target = $partitions{$part}->{target};
921 my $oldsize = $partitions{$part}->{part_size};
923 if ($partitions{$part}->{newsize}) {
924 $newsize = $partitions{$part}->{newsize};
926 $newsize = $partitions{$part}->{part_size};
929 if (!$quiet && !$debug) {
931 print "Copying $part ...";
934 $g->copy_size ($part, $target,
935 $newsize < $oldsize ? $newsize : $oldsize);
937 if (!$quiet && !$debug) {
945 # Sync disk and exit.
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]/;
967 # Convert a number of bytes to a human-readable number.
981 sprintf "%s%dK", $sgn, $_;
982 } elsif ($_ < 1024 * 1024) {
983 sprintf "%s%.1fM", $sgn, ($_ / 1024);
985 sprintf "%s%.1fG", $sgn, ($_ / 1024 / 1024);
989 # Return the size in bytes of a HOST block device.
990 sub host_blockdevsize
995 open BD, "PATH=/usr/sbin:/sbin:\$PATH blockdev --getsize64 $dev |"
996 or die "blockdev: $!";
1002 # The reverse of device name translation, see
1003 # BLOCK DEVICE NAMING in guestfs(3).
1008 if (m{^/dev/[hv]d([a-z]\d)$}) {
1014 =head1 ALTERNATIVE TOOLS
1016 There are several proprietary tools for resizing partitions. We
1017 won't mention any here.
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.
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.
1032 L<virt-list-partitions(1)>,
1033 L<virt-list-filesystems(1)>,
1044 L<http://libguestfs.org/>.
1048 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
1052 Copyright (C) 2010 Red Hat Inc.
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.
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.
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.