[Libguestfs] [PATCHv2] New API: part_expand_gpt.

Richard W.M. Jones rjones at redhat.com
Tue Jan 19 16:26:15 UTC 2016


On Tue, Dec 01, 2015 at 06:28:44PM +0300, Maxim Perevedentsev wrote:
> This action moves second(backup) GPT header to the end of the disk.
> It is usable in in-place image expanding, since free space after
> second GPT header is unusable. To use additional space, we have
> to move second header. This is what sgdisk -e does.
> 
> However, sgdisk -e may perform additional actions if the partition
> table has unexpected params (e.g. if we call sgdisk -e /dev/sda1,
> it may fix partition table thus destroying the filesystem).
> To prevent such cases, we do a dry-run at first and fail if
> additional actions are scheduled.
> ---
>  daemon/parted.c                 | 33 ++++++++++++++++++++
>  generator/actions.ml            | 14 +++++++++
>  src/MAX_PROC_NR                 |  2 +-
>  tests/daemon/Makefile.am        |  3 +-
>  tests/daemon/test-expand-gpt.pl | 69 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 119 insertions(+), 2 deletions(-)
>  create mode 100755 tests/daemon/test-expand-gpt.pl
> 
> diff --git a/daemon/parted.c b/daemon/parted.c
> index df6b7e7..033c136 100644
> --- a/daemon/parted.c
> +++ b/daemon/parted.c
> @@ -928,3 +928,36 @@ do_part_get_mbr_part_type (const char *device, int partnum)
>    reply_with_error ("strdup failed");
>    return NULL;
>  }
> +
> +int
> +do_part_expand_gpt(const char *device)
> +{
> +  CLEANUP_FREE char *err = NULL;
> +
> +  /* If something is broken, sgdisk may try to correct it.
> +   * (e.g. recreate partition table and so on).
> +   * We do not want such behavior, so dry-run at first.*/
> +  int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
> +                    str_sgdisk, "--pretend", "-e", device, NULL);
> +
> +  if (r == -1) {
> +    reply_with_error ("%s --pretend -e %s: %s", str_sgdisk, device, err);
> +    return -1;
> +  }
> +  if (err && strlen(err) != 0) {
> +    /* Unexpected actions. */
> +    reply_with_error ("%s --pretend -e %s: %s", str_sgdisk, device, err);
> +    return -1;
> +  }

Need to call `free (err);' right here.  The CLEANUP_FREE macro only
frees the string at the end of the enclosing {} block.

> +  /* Now we can do a real run. */
> +  r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
> +                str_sgdisk, "-e", device, NULL);
> +
> +  if (r == -1) {
> +    reply_with_error ("%s -e %s: %s", str_sgdisk, device, err);
> +    return -1;
> +  }
> +
> +  return 0;
> +}
> diff --git a/generator/actions.ml b/generator/actions.ml
> index 7ab8ee4..3a14683 100644
> --- a/generator/actions.ml
> +++ b/generator/actions.ml
> @@ -12787,6 +12787,20 @@ See also L<ntfsresize(8)>, L<resize2fs(8)>, L<btrfs(8)>, L<xfs_info(8)>." };
>      longdesc = "\
>  This is the internal call which implements C<guestfs_feature_available>." };
> 
> +  { defaults with
> +    name = "part_expand_gpt"; added = (1, 31, 29);
> +    style = RErr, [Device "device"], [];
> +    proc_nr = Some 459;

Needs to be rebased on top of the current code.  This proc
number will change.

> +    optional = Some "gdisk";
> +    shortdesc = "move backup GPT header to the end of the disk";
> +    longdesc = "\
> +Move backup GPT data structures to the end of the disk.
> +This is useful in case of in-place image expand
> +since disk space after backup GPT header is not usable.
> +This is equivalent to C<sgdisk -e>.
> +
> +See also L<sgdisk(8)>." };
> +
>  ]
> 
>  (* Non-API meta-commands available only in guestfish.
> diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
> index c92ddb6..658bd78 100644
> --- a/src/MAX_PROC_NR
> +++ b/src/MAX_PROC_NR
> @@ -1 +1 @@
> -458
> +459
>
> diff --git a/tests/daemon/Makefile.am b/tests/daemon/Makefile.am
> index bb380c5..329b00c 100644
> --- a/tests/daemon/Makefile.am
> +++ b/tests/daemon/Makefile.am
> @@ -25,7 +25,8 @@ check_DATA = captive-daemon.pm
> 
>  TESTS = \
>  	test-daemon-start.pl \
> -	test-btrfs.pl
> +	test-btrfs.pl \
> +	test-expand-gpt.pl
> 
>  TESTS_ENVIRONMENT = $(top_builddir)/run --test $(VG)
> 
> diff --git a/tests/daemon/test-expand-gpt.pl b/tests/daemon/test-expand-gpt.pl
> new file mode 100755
> index 0000000..637b90e
> --- /dev/null
> +++ b/tests/daemon/test-expand-gpt.pl
> @@ -0,0 +1,69 @@
> +#!/usr/bin/env perl
> +# Copyright (C) 2015 Maxim Perevedentsev mperevedentsev at virtuozzo.com
> +#
> +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> +
> +use strict;
> +use warnings;
> +
> +use Sys::Guestfs;
> +
> +sub tests {
> +	my $g = Sys::Guestfs->new ();
> +
> +	foreach ("gpt", "mbr") {
> +		$g->disk_create ("disk_$_.img", "qcow2", 50 * 1024 * 1024);
> +		$g->add_drive ("disk_$_.img");
> +	}
> +
> +	$g->launch ();
> +
> +	$g->part_disk ("/dev/sda", "gpt");
> +	$g->part_disk ("/dev/sdb", "mbr");
> +
> +	$g->close ();
> +
> +	die if system ("qemu-img resize disk_gpt.img 100M &>/dev/null");
> +
> +	$g = Sys::Guestfs->new ();
> +
> +	foreach ("gpt", "mbr") {
> +		$g->add_drive ("disk_$_.img");
> +	}
> +
> +	$g->launch ();
> +	die if $g->part_expand_gpt ("/dev/sda");
> +
> +	my $output = $g->debug ("sh", ["sgdisk", "-p", "/dev/sda"]);
> +	die if $output eq "";
> +	$output =~ s/\n/ /g;
> +	$output =~ s/.*last usable sector is (\d+).*/$1/g;
> +
> +	my $end_sectors = 100 * 1024 * 2 - $output;
> +	die unless $end_sectors <= 34;
> +
> +	# Negative tests.
> +	eval { $g->part_expand_gpt ("/dev/sdb") };
> +	die unless $@;
> +	eval { $g->part_expand_gpt ("/dev/sda1") };
> +	die unless $@;
> +}
> +
> +eval { tests() };
> +system ("rm -f disk_*.img");
> +if ($@) {
> +    die;
> +}
> +exit 0

Looks fine to me apart from those two things.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v




More information about the Libguestfs mailing list