From b0cad42ef24ad379e2d7bc47cd8cd39dba5f35fa Mon Sep 17 00:00:00 2001 From: Jim Fehlig Date: Thu, 30 Jul 2020 13:25:20 -0600 Subject: [PATCH] Xen: Add support for qemu command-line passthrough Xen supports passing arbitrary arguments to the QEMU device model via the 'extra' member of the public libxl_domain_build_info structure. This patch adds a 'xen' namespace extension, similar to the QEMU and bhyve drivers, to map arbitrary arguments to the 'extra' member. Only passthrough of arguments is supported. Passthrough of environment variables or capabilities adjustments is not supported. Signed-off-by: Jim Fehlig Reviewed-by: Michal Privoznik --- docs/drvxen.html.in | 29 +++++++++++++ docs/schemas/domaincommon.rng | 17 ++++++++ src/libxl/libxl_conf.c | 10 ++++- src/libxl/libxl_conf.h | 8 ++++ src/libxl/libxl_domain.c | 82 +++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 1 + 6 files changed, 146 insertions(+), 1 deletion(-) diff --git a/docs/drvxen.html.in b/docs/drvxen.html.in index b2f41c1763..45a9329fcf 100644 --- a/docs/drvxen.html.in +++ b/docs/drvxen.html.in @@ -141,6 +141,35 @@ 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" ] +

Pass-through of arbitrary command-line arguments + to the qemu device model

+ +

Since 6.7.0, the Xen driver supports passing + arbitrary command-line arguments to the qemu device model used by Xen with + the <xen:commandline> element under domain. + In order to use command-line pass-through, an XML namespace request must be + issued that pulls in http://libvirt.org/schemas/domain/xen/1.0. + With the namespace in place, it is then possible to add + <xen:arg>sub-elements to + <xen:commandline> describing each argument passed to + the device model when starting the domain. +

+

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: +

+
+<domain type="xen" xmlns:xen="http://libvirt.org/schemas/domain/xen/1.0">
+  ...
+  <xen:commandline>
+    <xen:arg value='-drive'/>
+    <xen:arg value='file=/path/to/image,format=raw,if=none,id=drive-fdc0-0-0'/>
+    <xen:arg value='-global'/>
+    <xen:arg value='isa-fdc.driveA=drive-fdc0-0-0'/>
+  </xen:commandline>
+</domain>
+    
+

Example domain XML config

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index c933c71035..0d8a0caaf6 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -87,6 +87,9 @@ + + + @@ -6836,6 +6839,20 @@ + + + + + + + + + + + diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 7c2c015015..e7c7022b69 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -760,6 +760,13 @@ 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) + b_info->extra = g_strdupv(nsdata->args); + } + return 0; } @@ -2513,5 +2520,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..de2059fa24 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -1573,3 +1573,85 @@ libxlDomainDefCheckABIStability(libxlDriverPrivatePtr driver, virDomainDefFree(migratableDefDst); return ret; } + + +static void +libxlDomainDefNamespaceFree(void *nsdata) +{ + libxlDomainXmlNsDefPtr def = nsdata; + + if (!def) + return; + + 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; + + if ((nnodes = virXPathNodeSet("./xen:commandline/xen:arg", ctxt, &nodes)) < 0) + return -1; + + if (nnodes == 0) + return 0; + + nsdata = g_new0(libxlDomainXmlNsDef, 1); + 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 device model command-line argument specified")); + goto cleanup; + } + } + + *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, "\n"); + virBufferAdjustIndent(buf, 2); + + for (i = 0; i < cmd->num_args; i++) + virBufferEscapeString(buf, "\n", + cmd->args[i]); + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + + return 0; +} + + +virXMLNamespace libxlDriverDomainXMLNamespace = { + .parse = libxlDomainDefNamespaceParse, + .free = libxlDomainDefNamespaceFree, + .format = libxlDomainDefNamespaceFormatXML, + .prefix = "xen", + .uri = "http://libvirt.org/schemas/domain/xen/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