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 <jfehlig@suse.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Jim Fehlig 2020-07-30 13:25:20 -06:00
parent 6738c79380
commit b0cad42ef2
6 changed files with 146 additions and 1 deletions

View File

@ -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" ]</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>&lt;xen:commandline&gt;</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/xen/1.0</code>.
With the namespace in place, it is then possible to add
<code>&lt;xen:arg&gt;</code>sub-elements to
<code>&lt;xen:commandline&gt;</code> describing each argument passed to
the device model when starting 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>
&lt;domain type="xen" xmlns:xen="http://libvirt.org/schemas/domain/xen/1.0"&gt;
...
&lt;xen:commandline&gt;
&lt;xen:arg value='-drive'/&gt;
&lt;xen:arg value='file=/path/to/image,format=raw,if=none,id=drive-fdc0-0-0'/&gt;
&lt;xen:arg value='-global'/&gt;
&lt;xen:arg value='isa-fdc.driveA=drive-fdc0-0-0'/&gt;
&lt;/xen:commandline&gt;
&lt;/domain&gt;
</pre>
<h2><a id="xmlconfig">Example domain XML config</a></h2>
<p>

View File

@ -87,6 +87,9 @@
<optional>
<ref name='bhyvecmdline'/>
</optional>
<optional>
<ref name='xencmdline'/>
</optional>
</interleave>
</element>
</define>
@ -6836,6 +6839,20 @@
</element>
</define>
<!--
Optional hypervisor extensions in their own namespace:
Xen
-->
<define name="xencmdline">
<element name="commandline" ns="http://libvirt.org/schemas/domain/xen/1.0">
<zeroOrMore>
<element name="arg">
<attribute name='value'/>
</element>
</zeroOrMore>
</element>
</define>
<!--
Type library
-->

View File

@ -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);
}

View File

@ -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

View File

@ -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, "<xen:commandline>\n");
virBufferAdjustIndent(buf, 2);
for (i = 0; i < cmd->num_args; i++)
virBufferEscapeString(buf, "<xen:arg value='%s'/>\n",
cmd->args[i]);
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</xen:commandline>\n");
return 0;
}
virXMLNamespace libxlDriverDomainXMLNamespace = {
.parse = libxlDomainDefNamespaceParse,
.free = libxlDomainDefNamespaceFree,
.format = libxlDomainDefNamespaceFormatXML,
.prefix = "xen",
.uri = "http://libvirt.org/schemas/domain/xen/1.0",
};

View File

@ -77,6 +77,7 @@ struct _libxlDomainObjPrivate {
extern virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks;
extern virDomainDefParserConfig libxlDomainDefParserConfig;
extern virXMLNamespace libxlDriverDomainXMLNamespace;
extern const struct libxl_event_hooks ev_hooks;
int