[PATCH V2 1/3] Xen: Add support for qemu command-line passthrough

Jim Fehlig jfehlig at suse.com
Tue Aug 4 22:13:07 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 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 at suse.com>
---
 docs/drvxen.html.in           | 29 ++++++++++++
 docs/schemas/domaincommon.rng | 17 +++++++
 src/libxl/libxl_conf.c        | 10 ++++-
 src/libxl/libxl_conf.h        |  8 ++++
 src/libxl/libxl_domain.c      | 84 +++++++++++++++++++++++++++++++++++
 src/libxl/libxl_domain.h      |  1 +
 6 files changed, 148 insertions(+), 1 deletion(-)

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" ]</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>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 0d0dcbc5ce..7954696dce 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -87,6 +87,9 @@
         <optional>
           <ref name='bhyvecmdline'/>
         </optional>
+        <optional>
+          <ref name='xencmdline'/>
+        </optional>
       </interleave>
     </element>
   </define>
@@ -6799,6 +6802,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
     -->
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..f6bc8211b3 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -1573,3 +1573,87 @@ 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;
+        }
+    }
+
+    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, "<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",
+};
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