mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
launch: libvirt: Autodetect backing format for readonly drive overlays (RHBZ#1354335).
If the user doesn't specify a format (ie. they want autodetection),
and the drive is set to read-only, previously we created a qcow2
overlay to protect the drive but didn't set the backing_fmt field.
However libvirt disabled this so now libvirt doesn't work at all on
qcow2 files that have no backing_fmt field set.
We must therefore do autodetection in libguestfs and use that to set
the backing_fmt field.
We were already doing autodetection in the non-readonly case, so this
commit refactors that code into a new function
("get_source_format_or_autodetect") and uses it on the readonly path
too.
This commit is contained in:
@@ -162,6 +162,60 @@ static int check_bridge_exists (guestfs_h *g, const char *brname);
|
||||
static void selinux_warning (guestfs_h *g, const char *func, const char *selinux_op, const char *data);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return C<drv-E<gt>src.format>, but if it is C<NULL>, autodetect the
|
||||
* format.
|
||||
*
|
||||
* libvirt has disabled the feature of detecting the disk format,
|
||||
* unless the administrator sets C<allow_disk_format_probing=1> in
|
||||
* F</etc/libvirt/qemu.conf>. There is no way to detect if this
|
||||
* option is set, so we have to do format detection here using
|
||||
* C<qemu-img> and pass that to libvirt.
|
||||
*
|
||||
* This can still be a security issue, so in most cases it is
|
||||
* recommended the users pass the format to libguestfs which will
|
||||
* faithfully pass that straight through to libvirt without doing
|
||||
* autodetection.
|
||||
*
|
||||
* Caller must free the returned string. On error this function sets
|
||||
* the error in the handle and returns C<NULL>.
|
||||
*/
|
||||
static char *
|
||||
get_source_format_or_autodetect (guestfs_h *g, struct drive *drv)
|
||||
{
|
||||
if (drv->src.format)
|
||||
return safe_strdup (g, drv->src.format);
|
||||
|
||||
if (drv->src.protocol == drive_protocol_file) {
|
||||
char *format;
|
||||
|
||||
format = guestfs_disk_format (g, drv->src.u.path);
|
||||
if (!format)
|
||||
return NULL;
|
||||
|
||||
if (STREQ (format, "unknown")) {
|
||||
error (g, _("could not auto-detect the format.\n"
|
||||
"If the format is known, pass the format to libguestfs, eg. using the\n"
|
||||
"'--format' option, or via the optional 'format' argument to 'add-drive'."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
/* Non-file protocol. */
|
||||
error (g, _("could not auto-detect the format when using a non-file protocol.\n"
|
||||
"If the format is known, pass the format to libguestfs, eg. using the\n"
|
||||
"'--format' option, or via the optional 'format' argument to 'add-drive'."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a qcow2 format overlay, with the given C<backing_drive>
|
||||
* (file). The C<format> parameter, which must be non-NULL, is the
|
||||
* backing file format. This is used to create the appliance overlay,
|
||||
* and also for read-only drives.
|
||||
*/
|
||||
static char *
|
||||
make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
|
||||
const char *format)
|
||||
@@ -169,6 +223,8 @@ make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
|
||||
char *overlay;
|
||||
struct guestfs_disk_create_argv optargs;
|
||||
|
||||
assert (format != NULL);
|
||||
|
||||
if (guestfs_int_lazy_make_tmpdir (g) == -1)
|
||||
return NULL;
|
||||
|
||||
@@ -176,10 +232,8 @@ make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
|
||||
|
||||
optargs.bitmask = GUESTFS_DISK_CREATE_BACKINGFILE_BITMASK;
|
||||
optargs.backingfile = backing_drive;
|
||||
if (format) {
|
||||
optargs.bitmask |= GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK;
|
||||
optargs.backingformat = format;
|
||||
}
|
||||
optargs.bitmask |= GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK;
|
||||
optargs.backingformat = format;
|
||||
|
||||
if (guestfs_disk_create_argv (g, overlay, "qcow2", -1, &optargs) == -1) {
|
||||
free (overlay);
|
||||
@@ -196,13 +250,18 @@ create_cow_overlay_libvirt (guestfs_h *g, void *datav, struct drive *drv)
|
||||
struct backend_libvirt_data *data = datav;
|
||||
#endif
|
||||
CLEANUP_FREE char *backing_drive = NULL;
|
||||
CLEANUP_FREE char *format = NULL;
|
||||
char *overlay;
|
||||
|
||||
backing_drive = guestfs_int_drive_source_qemu_param (g, &drv->src);
|
||||
if (!backing_drive)
|
||||
return NULL;
|
||||
|
||||
overlay = make_qcow2_overlay (g, backing_drive, drv->src.format);
|
||||
format = get_source_format_or_autodetect (g, drv);
|
||||
if (!format)
|
||||
return NULL;
|
||||
|
||||
overlay = make_qcow2_overlay (g, backing_drive, format);
|
||||
if (!overlay)
|
||||
return NULL;
|
||||
|
||||
@@ -1480,36 +1539,9 @@ construct_libvirt_xml_disk (guestfs_h *g,
|
||||
if (construct_libvirt_xml_disk_target (g, xo, drv_index) == -1)
|
||||
return -1;
|
||||
|
||||
if (drv->src.format)
|
||||
format = safe_strdup (g, drv->src.format);
|
||||
else if (drv->src.protocol == drive_protocol_file) {
|
||||
/* libvirt has disabled the feature of detecting the disk format,
|
||||
* unless the administrator sets allow_disk_format_probing=1 in
|
||||
* qemu.conf. There is no way to detect if this option is set, so we
|
||||
* have to do format detection here using qemu-img and pass that to
|
||||
* libvirt.
|
||||
*
|
||||
* This is still a security issue, so in most cases it is recommended
|
||||
* the users pass the format to libguestfs which will faithfully pass
|
||||
* that to libvirt and this function won't be used.
|
||||
*/
|
||||
format = guestfs_disk_format (g, drv->src.u.path);
|
||||
if (!format)
|
||||
return -1;
|
||||
|
||||
if (STREQ (format, "unknown")) {
|
||||
error (g, _("could not auto-detect the format.\n"
|
||||
"If the format is known, pass the format to libguestfs, eg. using the\n"
|
||||
"'--format' option, or via the optional 'format' argument to 'add-drive'."));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error (g, _("could not auto-detect the format when using a non-file protocol.\n"
|
||||
"If the format is known, pass the format to libguestfs, eg. using the\n"
|
||||
"'--format' option, or via the optional 'format' argument to 'add-drive'."));
|
||||
format = get_source_format_or_autodetect (g, drv);
|
||||
if (!format)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (construct_libvirt_xml_disk_driver_qemu (g, data, drv, xo, format,
|
||||
drv->cachemode ? : "writeback",
|
||||
|
||||
Reference in New Issue
Block a user