提交 c6da5913 编写于 作者: P Peter Krempa

qemu: Add support for controling qemu capabilities via the qemu XML namespace

Similarly how we allow adding arbitrary command line arguments and
environment variables this patch introduces the ability to control
libvirt's perception of the qemu process by tweaking the capability bits
for testing purposes.

The idea is to allow developers and users either test a new feature by
enabling it early or disabling it to see whether it introduced
regressions.

This feature is not meant for production use though, so users should
handle it with care.
Signed-off-by: NPeter Krempa <pkrempa@redhat.com>
Reviewed-by: NJán Tomko <jtomko@redhat.com>
上级 ca62170e
...@@ -519,6 +519,36 @@ mount -t cgroup none /dev/cgroup -o devices ...@@ -519,6 +519,36 @@ mount -t cgroup none /dev/cgroup -o devices
&lt;qemu:env name='QEMU_ENV' value='VAL'/&gt; &lt;qemu:env name='QEMU_ENV' value='VAL'/&gt;
&lt;/qemu:commandline&gt; &lt;/qemu:commandline&gt;
&lt;/domain&gt; &lt;/domain&gt;
</pre>
<h2><a id="xmlnsfeatures">QEMU feature configuration for testing</a></h2>
<p>
In some cases e.g. when developing a new feature or for testing it may
be required to control a given qemu feature (or qemu capability) to test
it before it's complete or disable it for debugging purposes.
<span class="since">Since 5.5.0</span> it's possible to use the same
special qemu namespace as above
(<code>http://libvirt.org/schemas/domain/qemu/1.0</code>) and use
<code>&lt;qemu:capabilities&gt;</code> element to add
(<code>&lt;qemu:add capability="capname"/&gt;</code>) or remove
(<code>&lt;qemu:del capability="capname"/&gt;</code>) capability bits.
The naming of the feature bits is the same libvirt uses in the status
XML. Note that this feature is meant for experiments only and should
_not_ be used in production.
</p>
<p>Example:</p><pre>
&lt;domain type='qemu' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'&gt;
&lt;name&gt;testvm&lt;/name&gt;
[...]
&lt;qemu:capabilities&gt;
&lt;qemu:add capability='blockdev'/&gt;
&lt;qemu:del capability='drive'/&gt;
&lt;/qemu:capabilities&gt;
&lt;/domain&gt;
</pre> </pre>
<h2><a id="xmlconfig">Example domain XML config</a></h2> <h2><a id="xmlconfig">Example domain XML config</a></h2>
......
...@@ -72,6 +72,9 @@ ...@@ -72,6 +72,9 @@
<optional> <optional>
<ref name='qemucmdline'/> <ref name='qemucmdline'/>
</optional> </optional>
<optional>
<ref name='qemucapabilities'/>
</optional>
<optional> <optional>
<ref name='lxcsharens'/> <ref name='lxcsharens'/>
</optional> </optional>
...@@ -6197,6 +6200,22 @@ ...@@ -6197,6 +6200,22 @@
</element> </element>
</define> </define>
<define name="qemucapabilities">
<element name="capabilities" ns="http://libvirt.org/schemas/domain/qemu/1.0">
<zeroOrMore>
<element name="add">
<attribute name="capability"/>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="del">
<attribute name="capability"/>
</element>
</zeroOrMore>
</element>
</define>
<!-- <!--
Optional hypervisor extensions in their own namespace: Optional hypervisor extensions in their own namespace:
LXC LXC
......
...@@ -3096,6 +3096,8 @@ qemuDomainXmlNsDefFree(qemuDomainXmlNsDefPtr def) ...@@ -3096,6 +3096,8 @@ qemuDomainXmlNsDefFree(qemuDomainXmlNsDefPtr def)
virStringListFreeCount(def->args, def->num_args); virStringListFreeCount(def->args, def->num_args);
virStringListFreeCount(def->env_name, def->num_env); virStringListFreeCount(def->env_name, def->num_env);
virStringListFreeCount(def->env_value, def->num_env); virStringListFreeCount(def->env_value, def->num_env);
virStringListFreeCount(def->capsadd, def->ncapsadd);
virStringListFreeCount(def->capsdel, def->ncapsdel);
VIR_FREE(def); VIR_FREE(def);
} }
...@@ -3195,6 +3197,50 @@ qemuDomainDefNamespaceParseCommandlineEnv(qemuDomainXmlNsDefPtr nsdef, ...@@ -3195,6 +3197,50 @@ qemuDomainDefNamespaceParseCommandlineEnv(qemuDomainXmlNsDefPtr nsdef,
} }
static int
qemuDomainDefNamespaceParseCaps(qemuDomainXmlNsDefPtr nsdef,
xmlXPathContextPtr ctxt)
{
VIR_AUTOFREE(xmlNodePtr *) nodesadd = NULL;
ssize_t nnodesadd;
VIR_AUTOFREE(xmlNodePtr *) nodesdel = NULL;
ssize_t nnodesdel;
size_t i;
if ((nnodesadd = virXPathNodeSet("./qemu:capabilities/qemu:add", ctxt, &nodesadd)) < 0 ||
(nnodesdel = virXPathNodeSet("./qemu:capabilities/qemu:del", ctxt, &nodesdel)) < 0)
return -1;
if (nnodesadd > 0) {
if (VIR_ALLOC_N(nsdef->capsadd, nnodesadd) < 0)
return -1;
for (i = 0; i < nnodesadd; i++) {
if (!(nsdef->capsadd[nsdef->ncapsadd++] = virXMLPropString(nodesadd[i], "capability"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing capability name"));
return -1;
}
}
}
if (nnodesdel > 0) {
if (VIR_ALLOC_N(nsdef->capsdel, nnodesdel) < 0)
return -1;
for (i = 0; i < nnodesdel; i++) {
if (!(nsdef->capsdel[nsdef->ncapsdel++] = virXMLPropString(nodesdel[i], "capability"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing capability name"));
return -1;
}
}
}
return 0;
}
static int static int
qemuDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED, qemuDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
xmlNodePtr root ATTRIBUTE_UNUSED, xmlNodePtr root ATTRIBUTE_UNUSED,
...@@ -3215,10 +3261,12 @@ qemuDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED, ...@@ -3215,10 +3261,12 @@ qemuDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
return -1; return -1;
if (qemuDomainDefNamespaceParseCommandlineArgs(nsdata, ctxt) < 0 || if (qemuDomainDefNamespaceParseCommandlineArgs(nsdata, ctxt) < 0 ||
qemuDomainDefNamespaceParseCommandlineEnv(nsdata, ctxt) < 0) qemuDomainDefNamespaceParseCommandlineEnv(nsdata, ctxt) < 0 ||
qemuDomainDefNamespaceParseCaps(nsdata, ctxt) < 0)
goto cleanup; goto cleanup;
if (nsdata->num_args > 0 || nsdata->num_env > 0) if (nsdata->num_args > 0 || nsdata->num_env > 0 ||
nsdata->ncapsadd > 0 || nsdata->ncapsdel > 0)
VIR_STEAL_PTR(*data, nsdata); VIR_STEAL_PTR(*data, nsdata);
ret = 0; ret = 0;
...@@ -3256,6 +3304,29 @@ qemuDomainDefNamespaceFormatXMLCommandline(virBufferPtr buf, ...@@ -3256,6 +3304,29 @@ qemuDomainDefNamespaceFormatXMLCommandline(virBufferPtr buf,
} }
static void
qemuDomainDefNamespaceFormatXMLCaps(virBufferPtr buf,
qemuDomainXmlNsDefPtr xmlns)
{
size_t i;
if (!xmlns->ncapsadd && !xmlns->ncapsdel)
return;
virBufferAddLit(buf, "<qemu:capabilities>\n");
virBufferAdjustIndent(buf, 2);
for (i = 0; i < xmlns->ncapsadd; i++)
virBufferEscapeString(buf, "<qemu:add capability='%s'/>\n", xmlns->capsadd[i]);
for (i = 0; i < xmlns->ncapsdel; i++)
virBufferEscapeString(buf, "<qemu:del capability='%s'/>\n", xmlns->capsdel[i]);
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</qemu:capabilities>\n");
}
static int static int
qemuDomainDefNamespaceFormatXML(virBufferPtr buf, qemuDomainDefNamespaceFormatXML(virBufferPtr buf,
void *nsdata) void *nsdata)
...@@ -3263,6 +3334,7 @@ qemuDomainDefNamespaceFormatXML(virBufferPtr buf, ...@@ -3263,6 +3334,7 @@ qemuDomainDefNamespaceFormatXML(virBufferPtr buf,
qemuDomainXmlNsDefPtr cmd = nsdata; qemuDomainXmlNsDefPtr cmd = nsdata;
qemuDomainDefNamespaceFormatXMLCommandline(buf, cmd); qemuDomainDefNamespaceFormatXMLCommandline(buf, cmd);
qemuDomainDefNamespaceFormatXMLCaps(buf, cmd);
return 0; return 0;
} }
......
...@@ -539,6 +539,12 @@ struct _qemuDomainXmlNsDef { ...@@ -539,6 +539,12 @@ struct _qemuDomainXmlNsDef {
unsigned int num_env; unsigned int num_env;
char **env_name; char **env_name;
char **env_value; char **env_value;
size_t ncapsadd;
char **capsadd;
size_t ncapsdel;
char **capsdel;
}; };
......
...@@ -27,4 +27,9 @@ ...@@ -27,4 +27,9 @@
<qemu:env name='NS' value='ns'/> <qemu:env name='NS' value='ns'/>
<qemu:env name='BAR'/> <qemu:env name='BAR'/>
</qemu:commandline> </qemu:commandline>
<qemu:capabilities>
<qemu:add capability="vnc-colon"/>
<qemu:add capability="drive"/>
<qemu:del capability="name"/>
</qemu:capabilities>
</domain> </domain>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册