[Libguestfs] [PATCH v3] appliance: extract UUID from QCOW2 disk image
Richard W.M. Jones
rjones at redhat.com
Thu Aug 13 09:03:56 UTC 2020
On Thu, Aug 13, 2020 at 07:48:52AM +0300, Andrey Shinkevich wrote:
> For the appliance of the QCOW2 format, the function get_root_uuid()
> fails to get the UUID of the disk image.
> In this case, let us read the first 256k bytes of the disk image with
> the 'qemu-img dd' command. Then pass the read block to the 'file'
> command.
>
> Suggested-by: Denis V. Lunev <den at openvz.org>
> Signed-off-by: Andrey Shinkevich <andrey.shinkevich at virtuozzo.com>
Thanks, I pushed this with a few minor adjustments to error
handling in the get_root_uuid function.
Rich.
> v3:
> 01: The code refactoring was made based on reviewers comments.
> The e-mail thread Message-Id:
> <1597246570-901723-1-git-send-email-andrey.shinkevich at virtuozzo.com>
>
> lib/appliance-kcmdline.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 67 insertions(+), 1 deletion(-)
>
> diff --git a/lib/appliance-kcmdline.c b/lib/appliance-kcmdline.c
> index fbeb4f4..e088fc0 100644
> --- a/lib/appliance-kcmdline.c
> +++ b/lib/appliance-kcmdline.c
> @@ -71,7 +71,7 @@ read_uuid (guestfs_h *g, void *retv, const char *line, size_t len)
> * The L<file(1)> command does the hard work.
> */
> static char *
> -get_root_uuid (guestfs_h *g, const char *appliance)
> +get_root_uuid_with_file (guestfs_h *g, const char *appliance)
> {
> CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
> char *ret = NULL;
> @@ -96,6 +96,72 @@ get_root_uuid (guestfs_h *g, const char *appliance)
> }
>
> /**
> + * Read the first 256k bytes of the in_file with L<qemu-img(1)> command
> + * and write them into the out_file. That may be useful to get UUID of
> + * the QCOW2 disk image with further L<file(1)> command.
> + * The function returns zero if successful, otherwise -1.
> + */
> +static int
> +run_qemu_img_dd (guestfs_h *g, const char *in_file, char *out_file)
> +{
> + CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
> + int r;
> +
> + guestfs_int_cmd_add_arg (cmd, "qemu-img");
> + guestfs_int_cmd_add_arg (cmd, "dd");
> + guestfs_int_cmd_add_arg_format (cmd, "if=%s", in_file);
> + guestfs_int_cmd_add_arg_format (cmd, "of=%s", out_file);
> + guestfs_int_cmd_add_arg (cmd, "bs=256k");
> + guestfs_int_cmd_add_arg (cmd, "count=1");
> +
> + r = guestfs_int_cmd_run (cmd);
> + if (r == -1) {
> + error (g, "Failed to run qemu-img");
> + return -1;
> + }
> + if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
> + guestfs_int_external_command_failed (g, r, "qemu-img dd", NULL);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * Get the UUID from the appliance disk image.
> + */
> +static char *
> +get_root_uuid (guestfs_h *g, const char *appliance)
> +{
> + char *uuid = NULL;
> + int ret;
> + CLEANUP_UNLINK_FREE char *tmpfile = NULL;
> +
> + uuid = get_root_uuid_with_file (g, appliance);
> + if (uuid) {
> + return uuid;
> + }
> +
> + tmpfile = guestfs_int_make_temp_path (g, "root", "raw");
> + if (!tmpfile) {
> + error (g, "get_root_uuid: failed to make temporary file");
> + return NULL;
> + }
> +
> + ret = run_qemu_img_dd (g, appliance, tmpfile);
> + if (ret < 0) {
> + return NULL;
> + }
> +
> + uuid = get_root_uuid_with_file (g, tmpfile);
> + if (!uuid) {
> + error (g, "Failed to get the appliance UUID");
> + }
> +
> + return uuid;
> +}
> +
> +/**
> * Construct the Linux command line passed to the appliance. This is
> * used by the C<direct> and C<libvirt> backends, and is simply
> * located in this file because it's a convenient place for this
> --
> 1.8.3.1
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine. Supports Linux and Windows.
http://people.redhat.com/~rjones/virt-df/
More information about the Libguestfs
mailing list