[PATCH 2/4] Xen: Add support for qemu command-line passthrough

Jim Fehlig jfehlig at suse.com
Fri Jul 31 16:10:41 UTC 2020


Xen supports passing arbitrary arguments to the QEMU device model via
the 'extra' member of the public libxl_domain_build_info structure.
This patch uses QEMU namespace extensions already in place for the QEMU
driver to map arbitrary arguments to the 'extra' member. Only passthrough
of arguments is supported. Trying to pass environment variables or
capabilities adjustments is not supported and will result in an error.

Signed-off-by: Jim Fehlig <jfehlig at suse.com>
---
 docs/drvxen.html.in      | 35 ++++++++++++++
 src/libxl/libxl_conf.c   | 11 ++++-
 src/libxl/libxl_conf.h   |  8 ++++
 src/libxl/libxl_domain.c | 99 ++++++++++++++++++++++++++++++++++++++++
 src/libxl/libxl_domain.h |  1 +
 5 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/docs/drvxen.html.in b/docs/drvxen.html.in
index b2f41c1763..ffaf01fedb 100644
--- a/docs/drvxen.html.in
+++ b/docs/drvxen.html.in
@@ -141,6 +141,41 @@ 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><qemu: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/qemu/1.0</code>.
+      With the namespace in place, it is then possible to add
+      <code><qemu:arg></code>sub-elements to
+      <code><qemu:commandline></code> describing each argument passed to
+      the device model when starting the domain.
+    </p>
+    <p>
+      Note that although the schema is shared with the QEMU driver, only
+      command-line arguments are supported. Passing environment variables or
+      capabilities adjustments are not supported and will result in an error when
+      defining or creating 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:qemu="http://libvirt.org/schemas/domain/qemu/1.0">
+  ...
+  <qemu:commandline>
+    <qemu:arg value='-drive'/>
+    <qemu:arg value='file=/path/to/image,format=raw,if=none,id=drive-fdc0-0-0'/>
+    <qemu:arg value='-global'/>
+    <qemu:arg value='isa-fdc.driveA=drive-fdc0-0-0'/>
+  </qemu:commandline>
+</domain>
+    </pre>
+
     <h2><a id="xmlconfig">Example domain XML config</a></h2>
 
     <p>
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 8e63d40376..b163e39712 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -760,6 +760,14 @@ 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)
+            if (virStringListCopy(&b_info->extra, (const char **)nsdata->args) < 0)
+                return -1;
+    }
+
     return 0;
 }
 
@@ -2513,5 +2521,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..b67738061f 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -1573,3 +1573,102 @@ libxlDomainDefCheckABIStability(libxlDriverPrivatePtr driver,
     virDomainDefFree(migratableDefDst);
     return ret;
 }
+
+
+static void
+libxlDomainDefNamespaceFree(void *nsdata)
+{
+    libxlDomainXmlNsDefPtr def = nsdata;
+
+    if (!def)
+        return;
+
+    virStringListFreeCount(def->args, def->num_args);
+    VIR_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;
+
+    /* Only qemu args are supported in the libxl driver */
+    if ((nnodes = virXPathNodeSet("./qemu:commandline/qemu:env", ctxt, &nodes)) > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("libxl does not support setting qemu environment variables"));
+        return -1;
+    }
+    if ((nnodes = virXPathNodeSet("./qemu:capabilities", ctxt, &nodes)) > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("libxl does not support setting qemu capabilities"));
+        return -1;
+    }
+
+    if ((nnodes = virXPathNodeSet("./qemu:commandline/qemu:arg", ctxt, &nodes)) < 0)
+        return -1;
+
+    if (nnodes == 0)
+        return 0;
+
+    if (VIR_ALLOC(nsdata) < 0)
+        return -1;
+
+    if (VIR_ALLOC_N(nsdata->args, nnodes) < 0)
+        goto cleanup;
+
+    for (i = 0; i < nnodes; i++) {
+        if (!(nsdata->args[nsdata->num_args++] = virXMLPropString(nodes[i], "value"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("No qemu command-line argument specified"));
+            goto cleanup;
+        }
+    }
+
+    if (nsdata->num_args > 0)
+        *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, "<qemu:commandline>\n");
+    virBufferAdjustIndent(buf, 2);
+
+    for (i = 0; i < cmd->num_args; i++)
+        virBufferEscapeString(buf, "<qemu:arg value='%s'/>\n",
+                              cmd->args[i]);
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</qemu:commandline>\n");
+
+    return 0;
+}
+
+
+virXMLNamespace libxlDriverDomainXMLNamespace = {
+    .parse = libxlDomainDefNamespaceParse,
+    .free = libxlDomainDefNamespaceFree,
+    .format = libxlDomainDefNamespaceFormatXML,
+    .prefix = "qemu",
+    .uri = "http://libvirt.org/schemas/domain/qemu/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
-- 
2.26.2





More information about the libvir-list mailing list