Maxim Perevedentsev
2016-Jan-18 16:29 UTC
[Libguestfs] [PATCH] New API: part_get_disk_guid and part_set_disk_guid.
Some OSes (e.g. Windows Server 2012 R2) fail to boot if the disk GPT GUID has changed. To preserve disk GUID e.g. during virt-resize, we need a way to get/set disk GUIDs. --- daemon/parted.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 37 ++++++++++++++++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/daemon/parted.c b/daemon/parted.c index b073bd8..40f9676 100644 --- a/daemon/parted.c +++ b/daemon/parted.c @@ -928,3 +928,63 @@ do_part_get_mbr_part_type (const char *device, int partnum) reply_with_error ("strdup failed"); return NULL; } + +char * +do_part_get_disk_guid (const char *device) +{ + const char *pattern = "Disk identifier (GUID):"; + size_t i; + + CLEANUP_FREE char *err = NULL; + int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, + str_sgdisk, device, "-p", NULL); + if (r == -1) { + reply_with_error ("%s %s -p: %s", str_sgdisk, device, err); + return NULL; + } + + CLEANUP_FREE_STRING_LIST char **lines = split_lines (err); + if (lines == NULL) { + reply_with_error ("'%s %s -p' returned no output", + str_sgdisk, device); + return NULL; + } + + for (i = 0; lines[i] != NULL; ++i) { + if (STRPREFIX (lines[i], pattern)) { + char *value = lines[i] + strlen (pattern); + + /* Skip any leading whitespace */ + value += strspn (value, " \t"); + + /* Extract the actual information from the field. */ + char *ret = extract_uuid (value); + if (ret == NULL) { + /* The extraction function already sends the error. */ + return NULL; + } + + return ret; + } + } + + /* If we got here it means we didn't find the field */ + reply_with_error ("sgdisk output did not contain disk GUID. " + "See LIBGUESTFS_DEBUG output for more details"); + return NULL; +} + +int +do_part_set_disk_guid (const char *device, const char *guid) +{ + CLEANUP_FREE char *err = NULL; + int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, + str_sgdisk, device, "-U", guid, NULL); + + if (r == -1) { + reply_with_error ("%s %s -U %s: %s", str_sgdisk, device, guid, err); + return -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 7f8e80b..62c4839 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12793,6 +12793,43 @@ 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_set_disk_guid"; added = (1, 33, 2); + style = RErr, [Device "device"; GUID "guid"], []; + proc_nr = Some 459; + optional = Some "gdisk"; + tests = [ + InitGPT, Always, TestLastFail ( + [["part_set_disk_guid"; "/dev/sda"; "f"]]), []; + InitGPT, Always, TestResultString ( + [["part_set_disk_guid"; "/dev/sda"; + "01234567-89AB-CDEF-0123-456789ABCDEF"]; + ["part_get_disk_guid"; "/dev/sda"]], + "01234567-89AB-CDEF-0123-456789ABCDEF"), []; + ]; + shortdesc = "set the GUID of a GPT-partitioned disk"; + longdesc = "\ +Set the disk identifier (GUID) of a GPT-partitioned C<device> to C<guid>. +Return an error if the partition table of C<device> isn't GPT, +or if C<guid> is not a valid GUID." }; + + { defaults with + name = "part_get_disk_guid"; added = (1, 33, 2); + style = RString "guid", [Device "device"], []; + proc_nr = Some 460; + optional = Some "gdisk"; + tests = [ + InitGPT, Always, TestResultString ( + [["part_set_disk_guid"; "/dev/sda"; + "01234567-89AB-CDEF-0123-456789ABCDEF"]; + ["part_get_disk_guid"; "/dev/sda"]], + "01234567-89AB-CDEF-0123-456789ABCDEF"), []; + ]; + shortdesc = "get the GUID of a GPT-partitioned disk"; + longdesc = "\ +Return the disk identifier (GUID) of a GPT-partitioned C<device>. +Behaviour is undefined for other partition types." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index c92ddb6..ccbd68f 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -458 +460 -- 1.8.3.1
Richard W.M. Jones
2016-Jan-18 16:47 UTC
Re: [Libguestfs] [PATCH] New API: part_get_disk_guid and part_set_disk_guid.
On Mon, Jan 18, 2016 at 07:29:58PM +0300, Maxim Perevedentsev wrote:> +int > +do_part_set_disk_guid (const char *device, const char *guid) > +{ > + CLEANUP_FREE char *err = NULL; > + int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, > + str_sgdisk, device, "-U", guid, NULL);The sgdisk command accepts 'R' to mean use a random GUID. I believe that because you declare the parameter in the generator as `GUID "guid"' that we will reject 'R' (which is a good thing). It'd perhaps be nice to add another API for setting the GUID to a random value (it could be called `guestfs_part_set_disk_guid_random'). The rest of the patch looks fine to me, and is ready to go upstream as far as I'm concerned. Pino -- any comment? 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
Reasonably Related Threads
- [PATCHv2 1/3] New API: part_get_disk_guid and part_set_disk_guid.
- [PATCHv2 0/3] Get/set disk GPT GUID API and support in virt-resize.
- [PATCH] Add support for getting and setting GPT partition type GUIDs
- [PATCHv2 2/3] New API: part_set_disk_guid_random.
- Re: OpenStack output workflow