Andrey Shinkevich
2020-Aug-12 15:36 UTC
[Libguestfs] [PATCH v2] appliance: extract UUID from QCOW2 disk image
For the appliance of the QCOW2 format, get the UUID of the disk by
reading the first 256k bytes with 'qemu-img dd' command. Then pass the
read block to the 'file' command. In case of failure, run the
'file'
command again directly.
Suggested-by: Denis V. Lunev <den@openvz.org>
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
---
v2:
01: The order of the function calls to direct <file> command on the
appliance
and the indirect one (through the temporary file) has been swapped.
lib/appliance-kcmdline.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 69 insertions(+), 1 deletion(-)
diff --git a/lib/appliance-kcmdline.c b/lib/appliance-kcmdline.c
index fbeb4f4..c78524b 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)
+do_get_root_uuid (guestfs_h *g, const char *appliance)
{
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
char *ret = NULL;
@@ -96,6 +96,74 @@ 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;
+ char tmp_file[] = "/tmp/libguestfsXXXXXX";
+
+ uuid = do_get_root_uuid (g, appliance);
+ if (uuid) {
+ return uuid;
+ }
+
+ if (!mktemp (tmp_file)) {
+ error (g, "get_root_uuid: mktemp failed");
+ return NULL;
+ }
+
+ ret = run_qemu_img_dd (g, appliance, tmp_file);
+ if (ret == 0) {
+ uuid = do_get_root_uuid (g, tmp_file);
+ if (uuid) {
+ goto out;
+ }
+ }
+
+ /* We get here in case of failure to extract UUID from the temporary file. */
+ error (g, "Failed to get the appliance UUID");
+
+out:
+ unlink (tmp_file);
+ 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
Pino Toscano
2020-Aug-12 16:07 UTC
Re: [Libguestfs] [PATCH v2] appliance: extract UUID from QCOW2 disk image
On Wednesday, 12 August 2020 17:36:10 CEST Andrey Shinkevich wrote:> For the appliance of the QCOW2 format, get the UUID of the disk by > reading the first 256k bytes with 'qemu-img dd' command. Then pass the > read block to the 'file' command. In case of failure, run the 'file' > command again directly. > > Suggested-by: Denis V. Lunev <den@openvz.org> > Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com> > --- > v2: > 01: The order of the function calls to direct <file> command on the appliance > and the indirect one (through the temporary file) has been swapped. > > lib/appliance-kcmdline.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 69 insertions(+), 1 deletion(-) > > diff --git a/lib/appliance-kcmdline.c b/lib/appliance-kcmdline.c > index fbeb4f4..c78524b 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) > +do_get_root_uuid (guestfs_h *g, const char *appliance)get_root_uuid_with_file seems a better name, and gives less confusion than get_root_uuid & do_get_root_uuid.> { > CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g); > char *ret = NULL; > @@ -96,6 +96,74 @@ 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; > + char tmp_file[] = "/tmp/libguestfsXXXXXX";Please do not hardcode a location, and use the internal temporary directory instead. The internal guestfs_int_make_temp_path will do the right job. Thanks, -- Pino Toscano
Richard W.M. Jones
2020-Aug-12 16:23 UTC
Re: [Libguestfs] [PATCH v2] appliance: extract UUID from QCOW2 disk image
So the patch is generally fine now, but there's one thing I didn't spot in the earlier version:> +/** > + * Get the UUID from the appliance disk image. > + */ > +static char * > +get_root_uuid (guestfs_h *g, const char *appliance) > +{ > + char *uuid = NULL; > + int ret; > + char tmp_file[] = "/tmp/libguestfsXXXXXX"; > + > + uuid = do_get_root_uuid (g, appliance); > + if (uuid) { > + return uuid; > + } > + > + if (!mktemp (tmp_file)) { > + error (g, "get_root_uuid: mktemp failed"); > + return NULL; > + }mktemp isn't safe to use in modern code. Libguestfs already makes a temporary directory for handles to use so you can create a file in that directory like this: CLEANUP_FREE char *file = NULL; file = guestfs_int_make_temp_path (g, "root", "raw"); if (!file) return -1; Note you don't have to delete the file explicitly. Rich. -- 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/
Possibly Parallel Threads
- [PATCH v3] appliance: extract UUID from QCOW2 disk image
- [PATCH] appliance: extract UUID from QCOW2 disk image
- Re: [PATCH] appliance: extract UUID from QCOW2 disk image
- Re: [PATCH] appliance: extract UUID from QCOW2 disk image
- Re: [PATCH v3] appliance: extract UUID from QCOW2 disk image