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