[PATCH 0/4] Xen: Add support for qemu commandline passthrough

This patch series introduces support for qemu commandline passthrough to the xen driver. ATM it uses the same schema extension as the qemu driver, but it could be changed to something like xmlns:xen='http://libvirt.org/schemas/domain/xen/1.0' if desired. I didn't see an immediate benefit to that, other than following the pattern used by qemu, bhyve, and lxc. Using the same namespace and schema could be a bit confusing to users, but on the other hand it is just qemu under the covers. Since Xen does not support passing environment vars or adjusting qemu's capabilities, the parser will flag attempts at setting those as errors. The patch to NEWS.rst is just a reminder for me to create a news entry and will need rebased once 6.6.0 is out. Thanks in advance for your comments! Regards, Jim Jim Fehlig (4): Expose virStringListCopy in libvirt_private.syms Xen: Add support for qemu command-line passthrough Xen: Add support for qemu commandline passthrough to config converter news: Mention support for qemu commandline passthrough in Xen NEWS.rst | 6 ++ docs/drvxen.html.in | 35 +++++++ src/libvirt_private.syms | 1 + src/libxl/libxl_conf.c | 11 ++- src/libxl/libxl_conf.h | 8 ++ src/libxl/libxl_domain.c | 99 ++++++++++++++++++++ src/libxl/libxl_domain.h | 1 + src/libxl/xen_xl.c | 88 +++++++++++++++++ tests/xlconfigdata/test-qemu-passthrough.cfg | 26 +++++ tests/xlconfigdata/test-qemu-passthrough.xml | 53 +++++++++++ tests/xlconfigtest.c | 4 + 11 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 tests/xlconfigdata/test-qemu-passthrough.cfg create mode 100644 tests/xlconfigdata/test-qemu-passthrough.xml -- 2.26.2

virStringListCopy is used by a subsequent patch. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libvirt_private.syms | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index eea31a736d..e1ddc9fc5b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3216,6 +3216,7 @@ virStringIsEmpty; virStringIsPrintable; virStringListAdd; virStringListAutoFree; +virStringListCopy; virStringListFree; virStringListFreeCount; virStringListGetFirstWithPrefix; -- 2.26.2

On a Friday in 2020, Jim Fehlig wrote:
virStringListCopy is used by a subsequent patch.
g_strdupv is the Glib equivalent, so this patch should not be necessary. Jano
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libvirt_private.syms | 1 + 1 file changed, 1 insertion(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index eea31a736d..e1ddc9fc5b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3216,6 +3216,7 @@ virStringIsEmpty; virStringIsPrintable; virStringListAdd; virStringListAutoFree; +virStringListCopy; virStringListFree; virStringListFreeCount; virStringListGetFirstWithPrefix; -- 2.26.2

Xen supports passing arbitrary arguments to the QEMU device model via the 'extra' member of the public libxl_domain_build_info structure. This patch uses QEMU namespace extensions already in place for the QEMU driver to map arbitrary arguments to the 'extra' member. Only passthrough of arguments is supported. Trying to pass environment variables or capabilities adjustments is not supported and will result in an error. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- docs/drvxen.html.in | 35 ++++++++++++++ src/libxl/libxl_conf.c | 11 ++++- src/libxl/libxl_conf.h | 8 ++++ src/libxl/libxl_domain.c | 99 ++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 1 + 5 files changed, 153 insertions(+), 1 deletion(-) diff --git a/docs/drvxen.html.in b/docs/drvxen.html.in index b2f41c1763..ffaf01fedb 100644 --- a/docs/drvxen.html.in +++ b/docs/drvxen.html.in @@ -141,6 +141,41 @@ vnclisten = "0.0.0.0" disk = [ "tap:aio:/var/lib/xen/images/rhel5pv.img,xvda,w", "tap:qcow:/root/qcow1-xen.img,xvdd,w" ] vif = [ "mac=00:16:3e:60:36:ba,bridge=virbr0,script=vif-bridge,vifname=vif5.0" ]</pre> + <h2><a id="xencommand">Pass-through of arbitrary command-line arguments + to the qemu device model</a></h2> + + <p><span class="since">Since 6.7.0</span>, the Xen driver supports passing + arbitrary command-line arguments to the qemu device model used by Xen with + the <code><qemu:commandline></code> element under <code>domain</code>. + In order to use command-line pass-through, an XML namespace request must be + issued that pulls in <code>http://libvirt.org/schemas/domain/qemu/1.0</code>. + With the namespace in place, it is then possible to add + <code><qemu:arg></code>sub-elements to + <code><qemu:commandline></code> describing each argument passed to + the device model when starting the domain. + </p> + <p> + Note that although the schema is shared with the QEMU driver, only + command-line arguments are supported. Passing environment variables or + capabilities adjustments are not supported and will result in an error when + defining or creating the domain. + </p> + <p>The following example illustrates passing agruments to the QEMU device + model that define a floppy drive, which Xen does not support through its + public APIs: + </p> + <pre> +<domain type="xen" xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0"> + ... + <qemu:commandline> + <qemu:arg value='-drive'/> + <qemu:arg value='file=/path/to/image,format=raw,if=none,id=drive-fdc0-0-0'/> + <qemu:arg value='-global'/> + <qemu:arg value='isa-fdc.driveA=drive-fdc0-0-0'/> + </qemu:commandline> +</domain> + </pre> + <h2><a id="xmlconfig">Example domain XML config</a></h2> <p> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 8e63d40376..b163e39712 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -760,6 +760,14 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus); + if (def->namespaceData) { + libxlDomainXmlNsDefPtr nsdata = def->namespaceData; + + if (nsdata->num_args > 0) + if (virStringListCopy(&b_info->extra, (const char **)nsdata->args) < 0) + return -1; + } + return 0; } @@ -2513,5 +2521,6 @@ libxlCreateXMLConf(libxlDriverPrivatePtr driver) libxlDomainDefParserConfig.priv = driver; return virDomainXMLOptionNew(&libxlDomainDefParserConfig, &libxlDomainXMLPrivateDataCallbacks, - NULL, NULL, NULL); + &libxlDriverDomainXMLNamespace, + NULL, NULL); } diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index b057a9e4ba..fc652df61e 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -168,6 +168,14 @@ struct _libxlSavefileHeader { uint32_t unused[10]; }; + +typedef struct _libxlDomainXmlNsDef libxlDomainXmlNsDef; +typedef libxlDomainXmlNsDef *libxlDomainXmlNsDefPtr; +struct _libxlDomainXmlNsDef { + size_t num_args; + char **args; +}; + libxlDriverConfigPtr libxlDriverConfigNew(void); int diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index d9fcde4364..b67738061f 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -1573,3 +1573,102 @@ libxlDomainDefCheckABIStability(libxlDriverPrivatePtr driver, virDomainDefFree(migratableDefDst); return ret; } + + +static void +libxlDomainDefNamespaceFree(void *nsdata) +{ + libxlDomainXmlNsDefPtr def = nsdata; + + if (!def) + return; + + virStringListFreeCount(def->args, def->num_args); + VIR_FREE(def); +} + + +static int +libxlDomainDefNamespaceParse(xmlXPathContextPtr ctxt, + void **data) +{ + libxlDomainXmlNsDefPtr nsdata = NULL; + g_autofree xmlNodePtr *nodes = NULL; + ssize_t nnodes; + size_t i; + int ret = -1; + + /* Only qemu args are supported in the libxl driver */ + if ((nnodes = virXPathNodeSet("./qemu:commandline/qemu:env", ctxt, &nodes)) > 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxl does not support setting qemu environment variables")); + return -1; + } + if ((nnodes = virXPathNodeSet("./qemu:capabilities", ctxt, &nodes)) > 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxl does not support setting qemu capabilities")); + return -1; + } + + if ((nnodes = virXPathNodeSet("./qemu:commandline/qemu:arg", ctxt, &nodes)) < 0) + return -1; + + if (nnodes == 0) + return 0; + + if (VIR_ALLOC(nsdata) < 0) + return -1; + + if (VIR_ALLOC_N(nsdata->args, nnodes) < 0) + goto cleanup; + + for (i = 0; i < nnodes; i++) { + if (!(nsdata->args[nsdata->num_args++] = virXMLPropString(nodes[i], "value"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No qemu command-line argument specified")); + goto cleanup; + } + } + + if (nsdata->num_args > 0) + *data = g_steal_pointer(&nsdata); + + ret = 0; + + cleanup: + libxlDomainDefNamespaceFree(nsdata); + return ret; +} + + +static int +libxlDomainDefNamespaceFormatXML(virBufferPtr buf, + void *nsdata) +{ + libxlDomainXmlNsDefPtr cmd = nsdata; + size_t i; + + if (!cmd->num_args) + return 0; + + virBufferAddLit(buf, "<qemu:commandline>\n"); + virBufferAdjustIndent(buf, 2); + + for (i = 0; i < cmd->num_args; i++) + virBufferEscapeString(buf, "<qemu:arg value='%s'/>\n", + cmd->args[i]); + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</qemu:commandline>\n"); + + return 0; +} + + +virXMLNamespace libxlDriverDomainXMLNamespace = { + .parse = libxlDomainDefNamespaceParse, + .free = libxlDomainDefNamespaceFree, + .format = libxlDomainDefNamespaceFormatXML, + .prefix = "qemu", + .uri = "http://libvirt.org/schemas/domain/qemu/1.0", +}; diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 7e28093722..00682546e0 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -77,6 +77,7 @@ struct _libxlDomainObjPrivate { extern virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks; extern virDomainDefParserConfig libxlDomainDefParserConfig; +extern virXMLNamespace libxlDriverDomainXMLNamespace; extern const struct libxl_event_hooks ev_hooks; int -- 2.26.2

On a Friday in 2020, Jim Fehlig wrote:
Xen supports passing arbitrary arguments to the QEMU device model via the 'extra' member of the public libxl_domain_build_info structure. This patch uses QEMU namespace extensions already in place for the QEMU driver to map arbitrary arguments to the 'extra' member. Only passthrough of arguments is supported. Trying to pass environment variables or capabilities adjustments is not supported and will result in an error.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- docs/drvxen.html.in | 35 ++++++++++++++ src/libxl/libxl_conf.c | 11 ++++- src/libxl/libxl_conf.h | 8 ++++ src/libxl/libxl_domain.c | 99 ++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 1 + 5 files changed, 153 insertions(+), 1 deletion(-)
diff --git a/docs/drvxen.html.in b/docs/drvxen.html.in index b2f41c1763..ffaf01fedb 100644 --- a/docs/drvxen.html.in +++ b/docs/drvxen.html.in @@ -141,6 +141,41 @@ vnclisten = "0.0.0.0" disk = [ "tap:aio:/var/lib/xen/images/rhel5pv.img,xvda,w", "tap:qcow:/root/qcow1-xen.img,xvdd,w" ] vif = [ "mac=00:16:3e:60:36:ba,bridge=virbr0,script=vif-bridge,vifname=vif5.0" ]</pre>
+ <h2><a id="xencommand">Pass-through of arbitrary command-line arguments + to the qemu device model</a></h2> + + <p><span class="since">Since 6.7.0</span>, the Xen driver supports passing + arbitrary command-line arguments to the qemu device model used by Xen with + the <code><qemu:commandline></code> element under <code>domain</code>. + In order to use command-line pass-through, an XML namespace request must be + issued that pulls in <code>http://libvirt.org/schemas/domain/qemu/1.0</code>.
IIUC the 'qemu' namespace prefix comes from the name of the 'qemu' driver, not the executable it invokes, so this should use 'libxl' or something unique.
+ With the namespace in place, it is then possible to add + <code><qemu:arg></code>sub-elements to + <code><qemu:commandline></code> describing each argument passed to + the device model when starting the domain. + </p> + <p> + Note that although the schema is shared with the QEMU driver, only + command-line arguments are supported. Passing environment variables or + capabilities adjustments are not supported and will result in an error when + defining or creating the domain. + </p> + <p>The following example illustrates passing agruments to the QEMU device + model that define a floppy drive, which Xen does not support through its + public APIs: + </p> + <pre> +<domain type="xen" xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0"> + ... + <qemu:commandline> + <qemu:arg value='-drive'/> + <qemu:arg value='file=/path/to/image,format=raw,if=none,id=drive-fdc0-0-0'/> + <qemu:arg value='-global'/> + <qemu:arg value='isa-fdc.driveA=drive-fdc0-0-0'/> + </qemu:commandline> +</domain> + </pre> + <h2><a id="xmlconfig">Example domain XML config</a></h2>
<p> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 8e63d40376..b163e39712 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -760,6 +760,14 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus);
+ if (def->namespaceData) { + libxlDomainXmlNsDefPtr nsdata = def->namespaceData; + + if (nsdata->num_args > 0) + if (virStringListCopy(&b_info->extra, (const char **)nsdata->args) < 0)
Please use g_strdupv instead.
+ return -1; + } + return 0; }
@@ -2513,5 +2521,6 @@ libxlCreateXMLConf(libxlDriverPrivatePtr driver) libxlDomainDefParserConfig.priv = driver; return virDomainXMLOptionNew(&libxlDomainDefParserConfig, &libxlDomainXMLPrivateDataCallbacks, - NULL, NULL, NULL); + &libxlDriverDomainXMLNamespace, + NULL, NULL); } diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index b057a9e4ba..fc652df61e 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -168,6 +168,14 @@ struct _libxlSavefileHeader { uint32_t unused[10]; };
+ +typedef struct _libxlDomainXmlNsDef libxlDomainXmlNsDef; +typedef libxlDomainXmlNsDef *libxlDomainXmlNsDefPtr; +struct _libxlDomainXmlNsDef { + size_t num_args; + char **args; +}; + libxlDriverConfigPtr libxlDriverConfigNew(void); int diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index d9fcde4364..b67738061f 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -1573,3 +1573,102 @@ libxlDomainDefCheckABIStability(libxlDriverPrivatePtr driver, virDomainDefFree(migratableDefDst); return ret; } + + +static void +libxlDomainDefNamespaceFree(void *nsdata) +{ + libxlDomainXmlNsDefPtr def = nsdata; + + if (!def) + return; + + virStringListFreeCount(def->args, def->num_args); + VIR_FREE(def);
g_strfreev(def->args); g_free(def);
+} + + +static int +libxlDomainDefNamespaceParse(xmlXPathContextPtr ctxt, + void **data) +{ + libxlDomainXmlNsDefPtr nsdata = NULL; + g_autofree xmlNodePtr *nodes = NULL; + ssize_t nnodes; + size_t i; + int ret = -1; + + /* Only qemu args are supported in the libxl driver */ + if ((nnodes = virXPathNodeSet("./qemu:commandline/qemu:env", ctxt, &nodes)) > 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxl does not support setting qemu environment variables")); + return -1; + } + if ((nnodes = virXPathNodeSet("./qemu:capabilities", ctxt, &nodes)) > 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxl does not support setting qemu capabilities")); + return -1; + } + + if ((nnodes = virXPathNodeSet("./qemu:commandline/qemu:arg", ctxt, &nodes)) < 0) + return -1; + + if (nnodes == 0) + return 0; + + if (VIR_ALLOC(nsdata) < 0) + return -1; +
nsdata = g_new0(libxlDomainXmlNsDef, 1);
+ if (VIR_ALLOC_N(nsdata->args, nnodes) < 0) + goto cleanup; +
nsdata->args = g_new0(char *, nnodes + 1);
+ for (i = 0; i < nnodes; i++) { + if (!(nsdata->args[nsdata->num_args++] = virXMLPropString(nodes[i], "value"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No qemu command-line argument specified")); + goto cleanup; + } + } +
Jano

On 8/2/20 5:16 AM, Ján Tomko wrote:
On a Friday in 2020, Jim Fehlig wrote:
Xen supports passing arbitrary arguments to the QEMU device model via the 'extra' member of the public libxl_domain_build_info structure. This patch uses QEMU namespace extensions already in place for the QEMU driver to map arbitrary arguments to the 'extra' member. Only passthrough of arguments is supported. Trying to pass environment variables or capabilities adjustments is not supported and will result in an error.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- docs/drvxen.html.in | 35 ++++++++++++++ src/libxl/libxl_conf.c | 11 ++++- src/libxl/libxl_conf.h | 8 ++++ src/libxl/libxl_domain.c | 99 ++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 1 + 5 files changed, 153 insertions(+), 1 deletion(-)
diff --git a/docs/drvxen.html.in b/docs/drvxen.html.in index b2f41c1763..ffaf01fedb 100644 --- a/docs/drvxen.html.in +++ b/docs/drvxen.html.in @@ -141,6 +141,41 @@ vnclisten = "0.0.0.0" disk = [ "tap:aio:/var/lib/xen/images/rhel5pv.img,xvda,w", "tap:qcow:/root/qcow1-xen.img,xvdd,w" ] vif = [ "mac=00:16:3e:60:36:ba,bridge=virbr0,script=vif-bridge,vifname=vif5.0" ]</pre>
+ <h2><a id="xencommand">Pass-through of arbitrary command-line arguments + to the qemu device model</a></h2> + + <p><span class="since">Since 6.7.0</span>, the Xen driver supports passing + arbitrary command-line arguments to the qemu device model used by Xen with + the <code><qemu:commandline></code> element under <code>domain</code>. + In order to use command-line pass-through, an XML namespace request must be + issued that pulls in <code>http://libvirt.org/schemas/domain/qemu/1.0</code>.
IIUC the 'qemu' namespace prefix comes from the name of the 'qemu' driver, not the executable it invokes, so this should use 'libxl' or something unique.
Thanks for the review! I've changed this to 'xen' and used more glib as you suggested (old habits are hard to break). V2 of the series has been sent https://www.redhat.com/archives/libvir-list/2020-August/msg00238.html Regards, Jim

Support qemu commandline passthrough in the domXML to native config converter. Add tests to check the conversion. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- I had to add a small hack to xlconfigtest.c to set def->ns after parsing the xl.cfg file to virDomainDef object. The hack could also be added to xenParseXL in src/libxl/xen_xl.c, where the virDomainDef object is created. Opinions much welcomed :-). src/libxl/xen_xl.c | 88 ++++++++++++++++++++ tests/xlconfigdata/test-qemu-passthrough.cfg | 26 ++++++ tests/xlconfigdata/test-qemu-passthrough.xml | 53 ++++++++++++ tests/xlconfigtest.c | 4 + 4 files changed, 171 insertions(+) diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c index f9dc18ab18..a5d70d4039 100644 --- a/src/libxl/xen_xl.c +++ b/src/libxl/xen_xl.c @@ -32,6 +32,7 @@ #include "virstoragefile.h" #include "xen_xl.h" #include "libxl_capabilities.h" +#include "libxl_conf.h" #include "cpu/cpu.h" #define VIR_FROM_THIS VIR_FROM_XENXL @@ -1158,6 +1159,40 @@ xenParseXLChannel(virConfPtr conf, virDomainDefPtr def) return -1; } +static int +xenParseXLNamespaceData(virConfPtr conf, virDomainDefPtr def) +{ + virConfValuePtr list = virConfGetValue(conf, "device_model_args"); + VIR_AUTOSTRINGLIST args = NULL; + size_t nargs; + libxlDomainXmlNsDefPtr nsdata = NULL; + + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) { + list = list->next; + continue; + } + + virStringListAdd(&args, list->str); + list = list->next; + } + } + + nargs = virStringListLength((const char **)args); + if (nargs > 0) { + if (VIR_ALLOC(nsdata) < 0) + return -1; + + nsdata->args = g_steal_pointer(&args); + nsdata->num_args = nargs; + def->namespaceData = nsdata; + } + + return 0; +} + virDomainDefPtr xenParseXL(virConfPtr conf, virCapsPtr caps, @@ -1207,6 +1242,9 @@ xenParseXL(virConfPtr conf, if (xenParseXLChannel(conf, def) < 0) goto cleanup; + if (xenParseXLNamespaceData(conf, def) < 0) + goto cleanup; + if (virDomainDefPostParse(def, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE, xmlopt, NULL) < 0) goto cleanup; @@ -2165,6 +2203,53 @@ xenFormatXLDomainChannels(virConfPtr conf, virDomainDefPtr def) return -1; } +static int +xenFormatXLDomainNamespaceData(virConfPtr conf, virDomainDefPtr def) +{ + libxlDomainXmlNsDefPtr nsdata = def->namespaceData; + virConfValuePtr args = NULL; + size_t i; + + if (!nsdata) + return 0; + + if (nsdata->num_args == 0) + return 0; + + if (VIR_ALLOC(args) < 0) + return -1; + + args->type = VIR_CONF_LIST; + args->list = NULL; + + for (i = 0; i < nsdata->num_args; i++) { + virConfValuePtr val, tmp; + + if (VIR_ALLOC(val) < 0) + goto error; + + val->type = VIR_CONF_STRING; + val->str = g_strdup(nsdata->args[i]); + tmp = args->list; + while (tmp && tmp->next) + tmp = tmp->next; + if (tmp) + tmp->next = val; + else + args->list = val; + } + + if (args->list != NULL) + if (virConfSetValue(conf, "device_model_args", args) < 0) + goto error; + + return 0; + + error: + virConfFreeValue(args); + return -1; +} + virConfPtr xenFormatXL(virDomainDefPtr def, virConnectPtr conn) { @@ -2208,5 +2293,8 @@ xenFormatXL(virDomainDefPtr def, virConnectPtr conn) if (xenFormatXLDomainChannels(conf, def) < 0) return NULL; + if (xenFormatXLDomainNamespaceData(conf, def) < 0) + return NULL; + return g_steal_pointer(&conf); } diff --git a/tests/xlconfigdata/test-qemu-passthrough.cfg b/tests/xlconfigdata/test-qemu-passthrough.cfg new file mode 100644 index 0000000000..42aad92205 --- /dev/null +++ b/tests/xlconfigdata/test-qemu-passthrough.cfg @@ -0,0 +1,26 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +viridian = 0 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000" ] +parallel = "none" +serial = "none" +builder = "hvm" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2" ] +device_model_args = [ "-debugcon", "file:/tmp/debug.log", "-global", "isa-debugcon.iobase=0x402" ] diff --git a/tests/xlconfigdata/test-qemu-passthrough.xml b/tests/xlconfigdata/test-qemu-passthrough.xml new file mode 100644 index 0000000000..c7174cab06 --- /dev/null +++ b/tests/xlconfigdata/test-qemu-passthrough.xml @@ -0,0 +1,53 @@ +<domain type='xen' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='variable' adjustment='0' basis='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/images/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='xenbus' index='0'/> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + <memballoon model='xen'/> + </devices> + <qemu:commandline> + <qemu:arg value='-debugcon'/> + <qemu:arg value='file:/tmp/debug.log'/> + <qemu:arg value='-global'/> + <qemu:arg value='isa-debugcon.iobase=0x402'/> + </qemu:commandline> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index b2e045dfa5..82b640f768 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -145,6 +145,9 @@ testCompareFormatXML(const char *xlcfg, const char *xml, bool replaceVars) if (!(def = xenParseXL(conf, cfg->caps, driver->xmlopt))) goto fail; + /* Set def->ns before formating to XML */ + def->ns = *(virDomainXMLOptionGetNamespace(driver->xmlopt)); + if (!(gotxml = virDomainDefFormat(def, driver->xmlopt, VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE))) @@ -304,6 +307,7 @@ mymain(void) #ifdef LIBXL_HAVE_CREATEINFO_PASSTHROUGH DO_TEST("fullvirt-hypervisor-features"); #endif + DO_TEST("qemu-passthrough"); testXLFreeDriver(driver); -- 2.26.2

On a Friday in 2020, Jim Fehlig wrote:
Support qemu commandline passthrough in the domXML to native config converter. Add tests to check the conversion.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
I had to add a small hack to xlconfigtest.c to set def->ns after parsing the xl.cfg file to virDomainDef object. The hack could also be added to xenParseXL in src/libxl/xen_xl.c, where the virDomainDef object is created. Opinions much welcomed :-).
Yes, it should be filled by whatever is creating the config, not just before formatting.
src/libxl/xen_xl.c | 88 ++++++++++++++++++++
tests/xlconfigdata/test-qemu-passthrough.cfg | 26 ++++++ tests/xlconfigdata/test-qemu-passthrough.xml | 53 ++++++++++++
Why do all the test files in this directory have a 'test-' prefix?
tests/xlconfigtest.c | 4 + 4 files changed, 171 insertions(+)
diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c index f9dc18ab18..a5d70d4039 100644 --- a/src/libxl/xen_xl.c +++ b/src/libxl/xen_xl.c @@ -32,6 +32,7 @@ #include "virstoragefile.h" #include "xen_xl.h" #include "libxl_capabilities.h" +#include "libxl_conf.h" #include "cpu/cpu.h"
#define VIR_FROM_THIS VIR_FROM_XENXL @@ -1158,6 +1159,40 @@ xenParseXLChannel(virConfPtr conf, virDomainDefPtr def) return -1; }
+static int +xenParseXLNamespaceData(virConfPtr conf, virDomainDefPtr def) +{ + virConfValuePtr list = virConfGetValue(conf, "device_model_args"); + VIR_AUTOSTRINGLIST args = NULL; + size_t nargs; + libxlDomainXmlNsDefPtr nsdata = NULL; + + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) { + list = list->next; + continue; + } + + virStringListAdd(&args, list->str);
I'm not aware of a GLib equivalent for virStringListAdd
+ list = list->next; + } + } + + nargs = virStringListLength((const char **)args);
g_strv_length
+ if (nargs > 0) { + if (VIR_ALLOC(nsdata) < 0) + return -1;
g_new0
+ + nsdata->args = g_steal_pointer(&args); + nsdata->num_args = nargs; + def->namespaceData = nsdata; + } + + return 0; +} + virDomainDefPtr xenParseXL(virConfPtr conf, virCapsPtr caps,
Jano

Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- For now this is just a reminder to add a news entry for the new feature. Will need rebased once 6.6.0 is released. NEWS.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 8b53d21b8a..d2508709bc 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -24,6 +24,12 @@ v6.6.0 (unreleased) MAC addresses that would generate a new one if they were in its OUI (00:0c:29). + * xen: Add support for qemu command-line passthrough + + Xen supports passing arbitrary arguments to the QEMU device model using + the ``device_model_args`` setting in xl.cfg(5). The libvirt xen driver now + supports this using ``<qemu:commandline/>`` XML extensions. + * **Improvements** * esx: Change the NIC limit for recent virtualHW versions -- 2.26.2
participants (2)
-
Jim Fehlig
-
Ján Tomko