From cdc89bb10ff584d3aaf07b70c264d659e5f416e3 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Mon, 12 Apr 2010 16:34:36 +0100 Subject: [PATCH] resize: Add --LV-expand option for expanding Linux LVs. --- tools/virt-resize | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/tools/virt-resize b/tools/virt-resize index 9ffceb3..b3185d3 100755 --- a/tools/virt-resize +++ b/tools/virt-resize @@ -383,6 +383,34 @@ You can give this option multiple times. =cut +my @lv_expand; + +=item B<--LV-expand logvol> + +This takes the logical volume and, as a final step, expands it to fill +all the space available in its volume group. A typical usage, +assuming a Linux guest with a single PV C and a root device +called C would be: + + virt-resize indisk outdisk \ + --expand /dev/sda2 --LV-expand /dev/vg_guest/lv_root + +This would first expand the partition (and PV), and then expand the +root device to fill the extra space in the PV. + +The contents of the LV are also resized if virt-resize knows how to do +that. You can stop virt-resize from trying to expand the content by +using the option C<--no-expand-content>. + +Use L to list the filesystems in +the guest. + +You can give this option multiple times, I it doesn't +make sense to do this unless the logical volumes you specify +are all in different volume groups. + +=cut + my $copy_boot_loader = 1; =item B<--no-copy-boot-loader> @@ -459,6 +487,7 @@ GetOptions ("help|?" => \$help, "shrink=s" => \$shrink, "ignore=s" => \@ignore, "delete=s" => \@delete, + "lv-expand=s" => \@lv_expand, "copy-boot-loader!" => \$copy_boot_loader, "extra-partition!" => \$extra_partition, "expand-content!" => \$expand_content, @@ -544,6 +573,8 @@ sub launch_guestfs my $sectsize = $g->blockdev_getss ("/dev/sdb"); +my $to_be_expanded = 0; + # Get the partitions on the source disk. my @partitions; my %partitions; @@ -638,6 +669,50 @@ if ($debug) { } } +# Examine the LVs (for --lv-expand option). +my @lvs = $g->lvs (); +my %lvs; +examine_lv ($_) foreach @lvs; +mark_lvs_to_expand (); + +sub examine_lv +{ + local $_ = shift; + + $lvs{$_}->{name} = $_; + + my $type = "unknown"; + eval { + $type = $g->vfs_type ($_); + }; + $lvs{$_}->{type} = $type; + + if ($expand_content) { + if ($type =~ /^ext[234]$/) { + $lvs{$_}->{can_expand_content} = 1; + $lvs{$_}->{expand_content_method} = "resize2fs"; + } elsif ($type eq "ntfs" && feature_available ($g, "ntfsprogs")) { + $lvs{$_}->{can_expand_content} = 1; + $lvs{$_}->{expand_content_method} = "ntfsresize"; + } + } +} + +sub mark_lvs_to_expand { + local $_; + + foreach (@lv_expand) { + die __x("virt-resize: no logical volume called {n}\n", + n => $_) + unless exists $lvs{$_}; + + if ($lvs{$_}->{can_expand_content}) { + $lvs{$_}->{will_expand_content} = 1; + $to_be_expanded++; + } + } +} + sub find_partition { local $_ = shift; @@ -685,8 +760,6 @@ sub do_delete } # Handle --resize and --resize-force. -my $to_be_expanded = 0; - do_resize ($_, 0, "--resize") foreach @resize; do_resize ($_, 1, "--resize-force") foreach @resize_force; @@ -871,6 +944,19 @@ sub print_summary } } + foreach my $lv (@lv_expand) { + print __x("{n}: LV will be expanded to maximum size\n", + n => $lv); + } + + foreach my $lv (@lvs) { + if ($lvs{$lv}->{will_expand_content}) { + print __x("{n}: content will be expanded using the '{meth}' method\n", + n => $lv, + meth => $lvs{$lv}->{expand_content_method}); + } + } + if ($surplus > 0) { print __x("There is a surplus of {spl} bytes ({h}).\n", spl => $surplus, @@ -1046,6 +1132,8 @@ sub copy_data if ($to_be_expanded > 0) { restart_appliance (); expand_partitions (); + expand_lvs (); + expand_lvs_content (); } sub restart_appliance @@ -1126,6 +1214,38 @@ sub expand_target_partition } } +sub expand_lvs +{ + local $_; + + foreach (@lv_expand) { + $g->lvresize_free ($_, 100); + } +} + +sub expand_lvs_content +{ + local $_; + + foreach (@lvs) { + if ($lvs{$_}->{will_expand_content}) { + my $method = $lvs{$_}->{expand_content_method}; + if (!$quiet && !$debug) { + print __x("Expanding {p} using the '{meth}' method\n", + p => $_, meth => $method); + } + if ($method eq "resize2fs") { + $g->e2fsck_f ($_); + $g->resize2fs ($_); + } elsif ($method eq "ntfsresize") { + $g->ntfsresize ($_); + } else { + die "internal error: unknown method: $method"; + } + } + } +} + # Sync disk and exit. $g->umount_all (); $g->sync (); -- 1.8.3.1