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