X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=tools%2Fvirt-resize;h=a70492e846acb9e60f96a11ac5064122a85b0106;hb=HEAD;hp=1c4006ae50e8b442b2a925d8683eabedd4088074;hpb=def627e4daf2d32cebf91f5e01f44a0b7e512129;p=libguestfs.git diff --git a/tools/virt-resize b/tools/virt-resize deleted file mode 100644 index 1c4006a..0000000 --- a/tools/virt-resize +++ /dev/null @@ -1,983 +0,0 @@ -#!/usr/bin/perl -w -# virt-resize -# Copyright (C) 2010 Red Hat Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -use warnings; -use strict; - -use Sys::Guestfs; -use Fcntl qw(S_ISREG SEEK_SET); -use POSIX qw(floor); -use Pod::Usage; -use Getopt::Long; -use Data::Dumper; -use Locale::TextDomain 'libguestfs'; - -$Data::Dumper::Sortkeys = 1; - -die __"virt-resize: sorry this program does not work on a 32 bit host\n" - if ~1 == 4294967294; - -=encoding utf8 - -=head1 NAME - -virt-resize - Resize a virtual machine disk - -=head1 SYNOPSIS - - virt-resize [--resize /dev/sdaN=[+/-][%]] [--expand /dev/sdaN] - [--shrink /dev/sdaN] [--ignore /dev/sdaN] [--delete /dev/sdaN] [...] - indisk outdisk - -=head1 DESCRIPTION - -Virt-resize is a tool which can resize a virtual machine disk, making -it larger or smaller overall, and resizing or deleting any partitions -contained within. - -Virt-resize B resize disk images in-place. Virt-resize -B be used on live virtual machines - for consistent -results, shut the virtual machine down before resizing it. - -If you are not familiar with the associated tools: -L, -L and -L, -we recommend you go and read those manual pages first. - -=head2 BASIC USAGE - -This describes the common case where you want to expand an image to -give your guest more space. Shrinking images is considerably more -complicated (unfortunately). - -=over 4 - -=item 1. Locate disk image - -Locate the disk image that you want to resize. It could be in a local -file or device. If the guest is managed by libvirt, you can use -C like this to find the disk image name: - - # virsh dumpxml guestname | xpath /domain/devices/disk/source - Found 1 nodes: - -- NODE -- - - -=item 2. Look at current sizing - -Use L to display the current partitions and -sizes: - - # virt-list-partitions -lh /dev/vg/lv_guest - /dev/sda1 ext3 101.9M - /dev/sda2 pv 7.9G - -(This example is a virtual machine with an 8 GB disk which we would -like to expand up to 10 GB). - -=item 3. Create destination disk - -Virt-resize cannot do in-place disk modifications. You have to have -space to store the resized destination disk. - -To store the resized disk image in a file, create a file of a suitable -size: - - # rm -f outdisk - # truncate -s 10G outdisk - -Use L to create a logical volume: - - # lvcreate -L 10G -n lv_name vg_name - -Or use L vol-create-as to create a libvirt storage volume: - - # virsh pool-list - # virsh vol-create-as poolname newvol 10G - -=item 4. Resize - - virt-resize indisk outdisk - -This command just copies disk image C to disk image C -I resizing or changing any existing partitions. If -C is larger, then an extra, empty partition is created at the -end of the disk covering the extra space. If C is smaller, -then it will give an error. - -To resize, you need to pass extra options (for the full list see the -L section below). - -L is the most useful option. It expands the named -partition within the disk to fill any extra space: - - virt-resize --expand /dev/sda2 indisk outdisk - -(In this case, an extra partition is I created at the end of the -disk, because there will be no unused space). - -If /dev/sda2 in the image contains a filesystem or LVM PV, then -this content is B automatically resized. You can resize it -afterwards either using L (offline) or using commands -inside the guest (online resizing). - -L is the other commonly used option. The following would -increase the size of /dev/sda1 by 200M, and expand /dev/sda2 -to fill the rest of the available space: - - virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 \ - indisk outdisk - -Other options are covered below. - -=item 5. Test - -Thoroughly test the new disk image I discarding the old one. - -If you are using libvirt, edit the XML to point at the new disk: - - # virsh edit guestname - -Change Esource ...E, see -L - -Then start up the domain with the new, resized disk: - - # virsh start guestname - -and check that it still works. - -Note that to see the extra space in the guest, you may need to use -guest commands to resize PVs, LVs and/or filesystems to fit the extra -space available. Three common guest commands for doing this for Linux -guests are L, L and L. It is -also possible to do this offline (eg. for scripting changes) using -L. - -=back - -=head1 OPTIONS - -=over 4 - -=cut - -my $help; - -=item B<--help> - -Display help. - -=cut - -my $version; - -=item B<--version> - -Display version number and exit. - -=cut - -my @resize; - -=item B<--resize part=size> - -Resize the named partition (expanding or shrinking it) so that it has -the given size. - -C can be expressed as an absolute number followed by -b/K/M/G/T/P/E to mean bytes, Kilobytes, Megabytes, Gigabytes, -Terabytes, Petabytes or Exabytes; or as a percentage of the current -size; or as a relative number or percentage. For example: - - --resize /dev/sda2=10G - - --resize /dev/sda4=90% - - --resize /dev/sda2=+1G - - --resize /dev/sda2=-200M - - --resize /dev/sda1=+128K - - --resize /dev/sda1=+10% - - --resize /dev/sda1=-10% - -You can increase the size of any partition. - -You can I B the size of partitions that contain -filesystems or PVs which have already been shrunk. Virt-resize will -check this has been done before proceeding, or else will print an -error (see also C<--resize-force>). - -You can give this option multiple times. - -=cut - -my @resize_force; - -=item B<--resize-force part=size> - -This is the same as C<--resize> except that it will let you decrease -the size of any partition. Generally this means you will lose any -data which was at the end of the partition you shrink, but you may not -care about that (eg. if shrinking an unused partition, or if you can -easily recreate it such as a swap partition). - -See also the C<--ignore> option. - -=cut - -my $expand; - -=item B<--expand part> - -Expand the named partition so it uses up all extra space (space left -over after any other resize changes that you request have been done). - -Any filesystem inside the partition is I expanded. You will need -to expand the filesystem (or PV) to fit the extra space either using -L (offline) or online guest tools. - -Note that you cannot use C<--expand> and C<--shrink> together. - -=cut - -my $shrink; - -=item B<--shrink part> - -Shrink the named partition until the overall disk image fits in the -destination. The named partition B contain a filesystem or PV -which has already been shrunk using another tool (eg. L -or other online tools). Virt-resize will check this and give an error -if it has not been done. - -The amount by which the overall disk must be shrunk (after carrying -out all other operations requested by the user) is called the -"deficit". For example, a straight copy (assume no other operations) -from a 5GB disk image to a 4GB disk image results in a 1GB deficit. -In this case, virt-resize would give an error unless the user -specified a partition to shrink and that partition had more than a -gigabyte of free space. - -Note that you cannot use C<--expand> and C<--shrink> together. - -=cut - -my @ignore; - -=item B<--ignore part> - -Ignore the named partition. Effectively this means the partition is -allocated on the destination disk, but the content is not copied -across from the source disk. The content of the partition will be -blank (all zero bytes). - -You can give this option multiple times. - -=cut - -my @delete; - -=item B<--delete part> - -Delete the named partition. It would be more accurate to describe -this as "don't copy it over", since virt-resize doesn't do in-place -changes and the original disk image is left intact. - -Note that when you delete a partition, then anything contained in the -partition is also deleted. Furthermore, this causes any partitions -that come after to be I, which can easily make your guest -unbootable. - -You can give this option multiple times. - -=cut - -my $copy_boot_loader = 1; - -=item B<--no-copy-boot-loader> - -By default, virt-resize copies over some sectors at the start of the -disk (up to the beginning of the first partition). Commonly these -sectors contain the Master Boot Record (MBR) and the boot loader, and -are required in order for the guest to boot correctly. - -If you specify this flag, then this initial copy is not done. You may -need to reinstall the boot loader in this case. - -=cut - -my $extra_partition = 1; -my $min_extra_partition = 10 * 1024 * 1024; # see below - -=item B<--no-extra-partition> - -By default, virt-resize creates an extra partition if there is any -extra, unused space after all resizing has happened. Use this option -to prevent the extra partition from being created. If you do this -then the extra space will be inaccessible until you run fdisk, parted, -or some other partitioning tool in the guest. - -Note that if the surplus space is smaller than 10 MB, no extra -partition will be created. - -=cut - -my $debug; - -=item B<-d> | B<--debug> - -Enable debugging messages. - -=cut - -my $dryrun; - -=item B<-n> | B<--dryrun> - -Print a summary of what would be done, but don't do anything. - -=cut - -my $quiet; - -=item B<-q> | B<--quiet> - -Don't print the summary. - -=back - -=cut - -GetOptions ("help|?" => \$help, - "version" => \$version, - "resize=s" => \@resize, - "resize-force=s" => \@resize_force, - "expand=s" => \$expand, - "shrink=s" => \$shrink, - "ignore=s" => \@ignore, - "delete=s" => \@delete, - "copy-boot-loader!" => \$copy_boot_loader, - "extra-partition!" => \$extra_partition, - "d|debug" => \$debug, - "n|dryrun" => \$dryrun, - "q|quiet" => \$quiet, - ) or pod2usage (2); -pod2usage (1) if $help; -if ($version) { - my $g = Sys::Guestfs->new (); - my %h = $g->version (); - print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; - exit -} - -die "virt-resize [--options] indisk outdisk\n" unless @ARGV == 2; - -# Check in and out images exist. -my $infile = $ARGV[0]; -my $outfile = $ARGV[1]; -die __x("virt-resize: {file}: does not exist or is not readable\n", file => $infile) - unless -r $infile; -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) - unless -w $outfile; - -my @s; -@s = stat $infile; -my $insize = S_ISREG ($s[2]) ? $s[7] : host_blockdevsize ($infile); -@s = stat $outfile; -my $outsize = S_ISREG ($s[2]) ? $s[7] : host_blockdevsize ($outfile); - -if ($debug) { - print "$infile size $insize bytes\n"; - print "$outfile size $outsize bytes\n"; -} - -die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n", - file => $infile, sz => $insize) - if $insize < 64 * 512; -die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n", - file => $outfile, sz => $outsize) - if $outsize < 64 * 512; - -# Copy the boot loader across. -do_copy_boot_loader () if $copy_boot_loader; - -sub do_copy_boot_loader -{ - print "copying boot loader ...\n" if $debug; - open IFILE, $infile or die "$infile: $!"; - my $s; - my $r = sysread (IFILE, $s, 64 * 512) or die "$infile: $!"; - die "$infile: short read" if $r < 64 * 512; - open OFILE, "+<$outfile" or die "$outfile: $!"; - sysseek OFILE, 0, SEEK_SET or die "$outfile: seek: $!"; - $r = syswrite (OFILE, $s, 64 * 512) or die "$outfile: $!"; - die "$outfile: short write" if $r < 64 * 512; -} - -# Add them to the handle and launch the appliance. -my $g; -launch_guestfs (); - -sub launch_guestfs -{ - $g = Sys::Guestfs->new (); - $g->set_trace (1) if $debug; - $g->add_drive_ro ($infile); - $g->add_drive ($outfile); - $g->launch (); -} - -my $sectsize = $g->blockdev_getss ("/dev/sdb"); - -# Get the partitions on the source disk. -my @partitions; -my %partitions; -check_source_disk (); - -sub check_source_disk -{ - local $_; - - # Partitions and PVs. - my @p = $g->part_list ("/dev/sda"); - foreach (@p) { - my $name = "/dev/sda" . $_->{part_num}; - push @partitions, $name; - - my %h = %$_; - $h{name} = $name; - $partitions{$name} = \%h; - } -} - -# Examine each partition. -my @pvs_full = $g->pvs_full (); -examine_partition ($_) foreach @partitions; - -sub examine_partition -{ - local $_; - my $part = shift; - - # What is it? - my $type = "unknown"; - eval { - $type = $g->vfs_type ($part); - }; - $partitions{$part}->{type} = $type; - - # Can we get the actual size of this object (ie. to find out if it - # is smaller than the container for shrinking)? - my $fssize; - if ($type eq "LVM2_member") { # LVM PV - foreach (@pvs_full) { - $fssize = $_->{pv_size} - if canonicalize ($_->{pv_name}) eq $part; - } - } else { # Something mountable? - eval { - $g->mount_ro ($part, "/"); - - my %stat = $g->statvfs ("/"); - $fssize = $stat{bsize} * $stat{blocks}; - }; - - eval { - $g->umount_all (); - }; - } - - # This might be undef if we didn't successfully find the size. In - # that case user won't be allowed to shrink this partition except - # by forcing it. - $partitions{$part}->{fssize} = $fssize; -} - -if ($debug) { - print "partitions found: ", join (", ", @partitions), "\n"; - foreach my $part (@partitions) { - print "$part:\n"; - foreach (sort keys %{$partitions{$part}}) { - print("\t", $_, " = ", - defined ($partitions{$part}->{$_}) - ? $partitions{$part}->{$_} : "undef", - "\n"); - } - } -} - -sub find_partition -{ - local $_ = shift; - my $option = shift; - - $_ = "/dev/$_" unless $_ =~ m{^/dev}; - $_ = canonicalize ($_); - - unless (exists $partitions{$_}) { - die __x("{p}: partition not found in the source disk image, when using the '{opt}' command line option\n", - p => $_, - opt => $option) - } - - if ($partitions{$_}->{ignore}) { - die __x("{p}: partition ignored, you cannot use it in another command line argument\n", - p => $_) - } - if ($partitions{$_}->{delete}) { - die __x("{p}: partition deleted, you cannot use it in another command line argument\n", - p => $_) - } - - return $_; -} - -# Handle --ignore. -do_ignore ($_) foreach @ignore; - -sub do_ignore -{ - local $_ = shift; - $_ = find_partition ($_, "--ignore"); - $partitions{$_}->{ignore} = 1; -} - -# Handle --delete. -do_delete ($_) foreach @delete; - -sub do_delete -{ - local $_ = shift; - $_ = find_partition ($_, "--delete"); - $partitions{$_}->{delete} = 1; -} - -# Handle --resize and --resize-force. -do_resize ($_, 0, "--resize") foreach @resize; -do_resize ($_, 1, "--resize-force") foreach @resize_force; - -sub do_resize -{ - local $_ = shift; - my $force = shift; - my $option = shift; - - # Argument is "part=size" ... - my ($part, $sizefield) = split /=/, $_, 2; - $part = find_partition ($part, $option); - - if (exists $partitions{$part}->{newsize}) { - die __x("{p}: this partition has already been marked for resizing\n", - p => $part); - } - - # Parse the size field. - my $oldsize = $partitions{$part}->{part_size}; - my $newsize; - if (!defined ($sizefield) || $sizefield eq "") { - die __x("{p}: missing size field in {o} option\n", - p => $part, o => $option); - } elsif ($sizefield =~ /^([.\d]+)([bKMGTPE])$/) { - $newsize = sizebytes ($1, $2); - } elsif ($sizefield =~ /^\+([.\d]+)([bKMGTPE])$/) { - my $incr = sizebytes ($1, $2); - $newsize = $oldsize + $incr; - } elsif ($sizefield =~ /^-([.\d]+)([bKMGTPE])$/) { - my $decr = sizebytes ($1, $2); - $newsize = $oldsize - $decr; - } elsif ($sizefield =~ /^([.\d]+)%$/) { - $newsize = $oldsize * $1 / 100; - } elsif ($sizefield =~ /^\+([.\d]+)%$/) { - $newsize = $oldsize + $oldsize * $1 / 100; - } elsif ($sizefield =~ /^-([.\d]+)%$/) { - $newsize = $oldsize - $oldsize * $1 / 100; - } else { - die __x("{p}: {f}: cannot parse size field\n", - p => $part, f => $sizefield) - } - - $newsize > 0 or - die __x("{p}: new size is zero or negative\n", p => $part); - - mark_partition_for_resize ($part, $oldsize, $newsize, $force, $option); -} - -sub mark_partition_for_resize -{ - local $_; - my $part = shift; - my $oldsize = shift; - my $newsize = shift; - my $force = shift; - my $option = shift; - - # Do nothing if the size is the same. - return if $oldsize == $newsize; - - my $bigger = $newsize > $oldsize; - - # Check there is space to shrink this. - unless ($bigger || $force) { - if (! $partitions{$part}->{fssize} || - $partitions{$part}->{fssize} > $newsize) { - 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", - p => $part); - } - } - - $partitions{$part}->{newsize} = $newsize; -} - -# Handle --expand and --shrink. -my $surplus; -if (defined $expand && defined $shrink) { - die __"virt-resize: you cannot use options --expand and --shrink together\n" -} -if (defined $expand || defined $shrink) { - calculate_surplus (); - - if ($debug) { - print "surplus before --expand or --shrink: $surplus (", - human_size ($surplus), ")\n"; - } - - do_expand () if $expand; - do_shrink () if $shrink; -} - -# (Re-)calculate surplus after doing expand or shrink. -calculate_surplus (); - -# Add up the total space required on the target so far, compared -# to the size of the target. We end up with a surplus or deficit. -sub calculate_surplus -{ - local $_; - - # We need some overhead for partitioning. Worst case would be for - # EFI partitioning + massive per-partition alignment. - my $overhead = $sectsize * (2 * 64 + (64 * (@partitions + 1)) + 128); - - my $required = 0; - foreach (@partitions) { - if ($partitions{$_}->{newsize}) { - $required += $partitions{$_}->{newsize} - } else { - $required += $partitions{$_}->{part_size} - } - } - - # Compare that to the actual target disk. - $surplus = $outsize - ($required + $overhead); -} - -sub do_expand -{ - local $_; - - unless ($surplus > 0) { - 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", - h => human_size (-$surplus)); - } - - my $part = find_partition ($expand, "--expand"); - my $oldsize = $partitions{$part}->{part_size}; - mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus, - 0, "--expand"); -} - -sub do_shrink -{ - local $_; - - unless ($surplus < 0) { - die __"virt-resize: error: cannot use --shrink because there is no deficit\n(see 'deficit' in the virt-resize(1) man page)\n" - } - - my $part = find_partition ($shrink, "--shrink"); - my $oldsize = $partitions{$part}->{part_size}; - mark_partition_for_resize ($part, $oldsize, $oldsize + $surplus, - 0, "--shrink"); -} - -# Print summary. -print_summary () unless $quiet; - -sub print_summary -{ - local $_; - print __"Summary of changes:\n"; - - foreach my $part (@partitions) { - if ($partitions{$part}->{ignore}) { - print __x("{p}: partition will be ignored", p => $part); - } elsif ($partitions{$part}->{delete}) { - print __x("{p}: partition will be deleted", p => $part); - } elsif ($partitions{$part}->{newsize}) { - print __x("{p}: partition will be resized from {oldsize} to {newsize}", - p => $part, - oldsize => human_size ($partitions{$part}->{part_size}), - newsize => human_size ($partitions{$part}->{newsize})); - } else { - print __x("{p}: partition will be left alone", p => $part); - } - print "\n" - } - - if ($surplus > 0) { - print __x("There is a surplus of {spl} bytes ({h}).\n", - spl => $surplus, - h => human_size ($surplus)); - if ($extra_partition) { - if ($surplus >= $min_extra_partition) { - print __"An extra partition will be created for the surplus.\n"; - } else { - print __"The surplus space is not large enough for an extra partition to be created\nand so it will just be ignored.\n"; - } - } else { - print __"The surplus space will be ignored. Run a partitioning program in the guest\nto partition this extra space if you want.\n"; - } - } elsif ($surplus < 0) { - 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", - def => -$surplus, - h => human_size (-$surplus)); - } -} - -exit 0 if $dryrun; - -# Repartition the target disk. -my $nextpart = 1; -my $parttype; -repartition (); - -sub repartition -{ - local $_; - - if ($copy_boot_loader) { - $parttype = $g->part_get_parttype ("/dev/sdb"); - print "partition table type: $parttype\n" if $debug; - } else { - # Didn't copy over the initial boot loader, so we need - # to make a new partition type here. - $parttype = "efi"; - } - - # Delete any existing partitions on the destination disk. - $g->part_init ("/dev/sdb", $parttype); - - my $start = 64; - - # Create the new partitions. - foreach my $part (@partitions) { - unless ($partitions{$part}->{delete}) { - # Size in sectors. - my $size; - if ($partitions{$part}->{newsize}) { - $size = ($partitions{$part}->{newsize} + $sectsize - 1) - / $sectsize; - } else { - $size = ($partitions{$part}->{part_size} + $sectsize - 1) - / $sectsize; - } - - # Create it. - my ($target, $end) = add_partition ($start, $size); - $partitions{$part}->{target} = $target; - - # Start of next partition + alignment. - $start = $end + 1; - $start = ($start + 63) & ~63; - } - } - - # Create surplus partition. - if ($extra_partition && $surplus >= $min_extra_partition) { - add_partition ($start, $outsize / $sectsize - 64 - $start); - } -} - -# Add a partition. -sub add_partition -{ - local $_; - my $start = shift; - my $size = shift; - - my ($target, $end); - - if ($nextpart <= 3 || $parttype ne "msdos") { - $target = "/dev/sdb$nextpart"; - $end = $start + $size - 1; - $g->part_add ("/dev/sdb", "primary", $start, $end); - $nextpart++; - } else { - if ($nextpart == 4) { - $g->part_add ("/dev/sdb", "extended", $start, -1); - $nextpart++; - $start += 64; - } - $target = "/dev/sdb$nextpart"; - $end = $start + $size - 1; - $g->part_add ("/dev/sdb", "logical", $start, $end); - $nextpart++; - } - - return ($target, $end); -} - -# Copy over the data. -copy_data (); - -sub copy_data -{ - foreach my $part (@partitions) - { - unless ($partitions{$part}->{ignore}) { - my $target = $partitions{$part}->{target}; - if ($target) { - my $oldsize = $partitions{$part}->{part_size}; - my $newsize; - if ($partitions{$part}->{newsize}) { - $newsize = $partitions{$part}->{newsize}; - } else { - $newsize = $partitions{$part}->{part_size}; - } - - if (!$quiet && !$debug) { - local $| = 1; - print "Copying $part ..."; - } - - $g->copy_size ($part, $target, - $newsize < $oldsize ? $newsize : $oldsize); - - if (!$quiet && !$debug) { - print " done\n" - } - } - } - } -} - -exit 0; - -sub sizebytes -{ - local $_ = shift; - my $unit = shift; - - $_ *= 1024 if $unit =~ /[KMGTPE]/; - $_ *= 1024 if $unit =~ /[MGTPE]/; - $_ *= 1024 if $unit =~ /[GTPE]/; - $_ *= 1024 if $unit =~ /[TPE]/; - $_ *= 1024 if $unit =~ /[PE]/; - $_ *= 1024 if $unit =~ /[E]/; - - return floor($_); -} - -# Convert a number of bytes to a human-readable number. -sub human_size -{ - local $_ = shift; - - my $sgn = ""; - if ($_ < 0) { - $sgn = "-"; - $_ = -$_; - } - - $_ /= 1024; - - if ($_ < 1024) { - sprintf "%s%dK", $sgn, $_; - } elsif ($_ < 1024 * 1024) { - sprintf "%s%.1fM", $sgn, ($_ / 1024); - } else { - sprintf "%s%.1fG", $sgn, ($_ / 1024 / 1024); - } -} - -# Return the size in bytes of a HOST block device. -sub host_blockdevsize -{ - local $_; - my $dev = shift; - - open BD, "PATH=/usr/sbin:/sbin:\$PATH blockdev --getsize64 $dev |" - or die "blockdev: $!"; - $_ = ; - chomp $_; - $_; -} - -# The reverse of device name translation, see -# BLOCK DEVICE NAMING in guestfs(3). -sub canonicalize -{ - local $_ = shift; - - if (m{^/dev/[hv]d([a-z]\d)$}) { - return "/dev/sd$1"; - } - $_; -} - -=head1 SEE ALSO - -L, -L, -L, -L, -L, -L, -L, -L, -L, -L, -L, -L. - -=head1 AUTHOR - -Richard W.M. Jones L - -=head1 COPYRIGHT - -Copyright (C) 2010 Red Hat Inc. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.