Pino Toscano
2019-May-24 10:48 UTC
[Libguestfs] [PATCH 0/2] libvirt: fix check of custom QEMU
In case you configure libguestfs with a custom QEMU, e.g.: $ ./configure [...] QEMU=/path/to/qemu then the libvirt backend did not use to override it, launching the appliance with the default QEMU for libvirt. This does not change the manual emulator overriding using set-hv. Pino Toscano (2): launch: libvirt: get default QEMU from domcapabilities launch: libvirt: fix custom hypervisor check lib/launch-libvirt.c | 72 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 7 deletions(-) -- 2.21.0
Pino Toscano
2019-May-24 10:48 UTC
[Libguestfs] [PATCH 1/2] launch: libvirt: get default QEMU from domcapabilities
Parse the libvirt domain capabilities for the default emulator
capabilities, and get the path to the default QEMU executable.
---
lib/launch-libvirt.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c
index bc5978cc4..8ab1211c4 100644
--- a/lib/launch-libvirt.c
+++ b/lib/launch-libvirt.c
@@ -134,6 +134,7 @@ struct backend_libvirt_data {
size_t nr_secrets;
char *uefi_code; /* UEFI (firmware) code and variables. */
char *uefi_vars;
+ char *default_qemu; /* default qemu (from domcapabilities) */
char guestfsd_path[UNIX_PATH_MAX]; /* paths to sockets */
char console_path[UNIX_PATH_MAX];
};
@@ -153,6 +154,7 @@ struct libvirt_xml_params {
};
static int parse_capabilities (guestfs_h *g, const char *capabilities_xml,
struct backend_libvirt_data *data);
+static int parse_domcapabilities (guestfs_h *g, const char
*domcapabilities_xml, struct backend_libvirt_data *data);
static int add_secret (guestfs_h *g, virConnectPtr conn, struct
backend_libvirt_data *data, const struct drive *drv);
static int find_secret (guestfs_h *g, const struct backend_libvirt_data *data,
const struct drive *drv, const char **type, const char **uuid);
static int have_secret (guestfs_h *g, const struct backend_libvirt_data *data,
const struct drive *drv);
@@ -324,6 +326,7 @@ launch_libvirt (guestfs_h *g, void *datav, const char
*libvirt_uri)
CLEANUP_FREE void *buf = NULL;
unsigned long version_number;
int uefi_flags;
+ CLEANUP_FREE char *domcapabilities_xml = NULL;
params.current_proc_is_root = geteuid () == 0;
@@ -419,6 +422,20 @@ launch_libvirt (guestfs_h *g, void *datav, const char
*libvirt_uri)
if (parse_capabilities (g, capabilities_xml, data) == -1)
goto cleanup;
+ domcapabilities_xml = virConnectGetDomainCapabilities (conn, NULL, NULL,
NULL,
+ NULL, 0);
+ if (!domcapabilities_xml) {
+ libvirt_error (g, _("could not get libvirt domain
capabilities"));
+ goto cleanup;
+ }
+
+ /* Parse domcapabilities XML.
+ */
+ debug (g, "parsing domcapabilities XML");
+
+ if (parse_domcapabilities (g, domcapabilities_xml, data) == -1)
+ goto cleanup;
+
/* UEFI code and variables, on architectures where that is required. */
if (guestfs_int_get_uefi (g, &data->uefi_code,
&data->uefi_vars,
&uefi_flags) == -1)
@@ -819,6 +836,42 @@ parse_capabilities (guestfs_h *g, const char
*capabilities_xml,
return 0;
}
+static int
+parse_domcapabilities (guestfs_h *g, const char *domcapabilities_xml,
+ struct backend_libvirt_data *data)
+{
+ CLEANUP_XMLFREEDOC xmlDocPtr doc = NULL;
+ CLEANUP_XMLXPATHFREECONTEXT xmlXPathContextPtr xpathCtx = NULL;
+ CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpathObj = NULL;
+
+ doc = xmlReadMemory (domcapabilities_xml, strlen (domcapabilities_xml),
+ NULL, NULL, XML_PARSE_NONET);
+ if (doc == NULL) {
+ error (g, _("unable to parse domain capabilities XML returned by
libvirt"));
+ return -1;
+ }
+
+ xpathCtx = xmlXPathNewContext (doc);
+ if (xpathCtx == NULL) {
+ error (g, _("unable to create new XPath context"));
+ return -1;
+ }
+
+ /* This gives us the default QEMU. */
+#define XPATH_EXPR "string(/domainCapabilities/path/text())"
+ xpathObj = xmlXPathEvalExpression (BAD_CAST XPATH_EXPR, xpathCtx);
+ if (xpathObj == NULL) {
+ error (g, _("unable to evaluate XPath expression: %s"),
XPATH_EXPR);
+ return -1;
+ }
+#undef XPATH_EXPR
+
+ assert (xpathObj->type == XPATH_STRING);
+ data->default_qemu = safe_strdup (g, (char *) xpathObj->stringval);
+
+ return 0;
+}
+
static int
is_custom_hv (guestfs_h *g)
{
@@ -2014,6 +2067,9 @@ shutdown_libvirt (guestfs_h *g, void *datav, int
check_for_errors)
free (data->uefi_vars);
data->uefi_vars = NULL;
+ free (data->default_qemu);
+ data->default_qemu = NULL;
+
return ret;
}
--
2.21.0
Pino Toscano
2019-May-24 10:48 UTC
[Libguestfs] [PATCH 2/2] launch: libvirt: fix custom hypervisor check
Previously, is_custom_hv() used to compare the QEMU executable found
during configure to the hypervisor set to check whether it is a custom
one; however, the QEMU found at configure time can be different than
what libvirt was configured with.
This fixes the libvirt backend when libguestfs is configured with a
different QEMU, that now will be specified as emulator overriding the
libvirt one.
---
lib/launch-libvirt.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c
index 8ab1211c4..95aed8054 100644
--- a/lib/launch-libvirt.c
+++ b/lib/launch-libvirt.c
@@ -163,7 +163,7 @@ static void debug_appliance_permissions (guestfs_h *g);
static void debug_socket_permissions (guestfs_h *g);
static void libvirt_error (guestfs_h *g, const char *fs, ...)
__attribute__((format (printf,2,3)));
static void libvirt_debug (guestfs_h *g, const char *fs, ...)
__attribute__((format (printf,2,3)));
-static int is_custom_hv (guestfs_h *g);
+static int is_custom_hv (guestfs_h *g, struct backend_libvirt_data *data);
static int is_blk (const char *path);
static void ignore_errors (void *ignore, virErrorPtr ignore2);
static void set_socket_create_context (guestfs_h *g);
@@ -606,7 +606,7 @@ launch_libvirt (guestfs_h *g, void *datav, const char
*libvirt_uri)
params.appliance_index = g->nr_drives;
strcpy (params.appliance_dev, "/dev/sd");
guestfs_int_drive_name (params.appliance_index,
¶ms.appliance_dev[7]);
- params.enable_svirt = ! is_custom_hv (g);
+ params.enable_svirt = ! is_custom_hv (g, data);
xml = construct_libvirt_xml (g, ¶ms);
if (!xml)
@@ -873,13 +873,15 @@ parse_domcapabilities (guestfs_h *g, const char
*domcapabilities_xml,
}
static int
-is_custom_hv (guestfs_h *g)
+is_custom_hv (guestfs_h *g, struct backend_libvirt_data *data)
{
+ if (g->hv && STRNEQ (g->hv, data->default_qemu))
+ return 1;
#ifdef QEMU
- return g->hv && STRNEQ (g->hv, QEMU);
-#else
- return 1;
+ if (STRNEQ (data->default_qemu, QEMU))
+ return 1;
#endif
+ return 0;
}
#if HAVE_LIBSELINUX
@@ -1265,7 +1267,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
/* Path to hypervisor. Only write this if the user has changed the
* default, otherwise allow libvirt to choose the best one.
*/
- if (is_custom_hv (g))
+ if (is_custom_hv (g, params->data))
single_element ("emulator", g->hv);
#if defined(__arm__)
/* Hopefully temporary hack to make ARM work (otherwise libvirt
--
2.21.0
Richard W.M. Jones
2019-May-24 11:45 UTC
Re: [Libguestfs] [PATCH 2/2] launch: libvirt: fix custom hypervisor check
This looks good, ACK series Thanks, Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html