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><xen:commandline></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><xen:arg></code>sub-elements to
+ <code><xen:commandline></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>
+<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>
+ </pre>
+
<h2><a id="xmlconfig">Example domain XML config</a></h2>
<p>
<optional>
<ref name='bhyvecmdline'/>
</optional>
+ <optional>
+ <ref name='xencmdline'/>
+ </optional>
</interleave>
</element>
</define>
</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
-->
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;
}
libxlDomainDefParserConfig.priv = driver;
return virDomainXMLOptionNew(&libxlDomainDefParserConfig,
&libxlDomainXMLPrivateDataCallbacks,
- NULL, NULL, NULL);
+ &libxlDriverDomainXMLNamespace,
+ NULL, NULL);
}
uint32_t unused[10];
};
+
+typedef struct _libxlDomainXmlNsDef libxlDomainXmlNsDef;
+typedef libxlDomainXmlNsDef *libxlDomainXmlNsDefPtr;
+struct _libxlDomainXmlNsDef {
+ size_t num_args;
+ char **args;
+};
+
libxlDriverConfigPtr
libxlDriverConfigNew(void);
int
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",
+};
extern virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks;
extern virDomainDefParserConfig libxlDomainDefParserConfig;
+extern virXMLNamespace libxlDriverDomainXMLNamespace;
extern const struct libxl_event_hooks ev_hooks;
int