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" ]
+
+
+ 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>
+
+
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