]> xenbits.xensource.com Git - libvirt.git/commitdiff
bhyve: implement support for commandline args
authorRoman Bogorodskiy <bogorodskiy@gmail.com>
Thu, 17 Jan 2019 15:07:20 +0000 (19:07 +0400)
committerRoman Bogorodskiy <bogorodskiy@gmail.com>
Sun, 27 Jan 2019 10:54:52 +0000 (14:54 +0400)
Implement support for passing custom command line arguments
to bhyve using the 'bhyve:commandline' element:

  <bhyve:commandline>
    <bhyve:arg value='-newarg'/>
  </bhyve:commandline>

 * Define virDomainXMLNamespace for the bhyve driver, which
   at this point supports only the 'commandline' element
   described above,
 * Update command generation code to inject these command line
   arguments between driver-generated arguments and the vmname
   positional argument.

Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
12 files changed:
docs/schemas/domaincommon.rng
src/bhyve/bhyve_command.c
src/bhyve/bhyve_conf.c
src/bhyve/bhyve_conf.h
src/bhyve/bhyve_domain.c
src/bhyve/bhyve_domain.h
tests/bhyvexml2argvdata/bhyvexml2argv-commandline.args [new file with mode: 0644]
tests/bhyvexml2argvdata/bhyvexml2argv-commandline.ldargs [new file with mode: 0644]
tests/bhyvexml2argvdata/bhyvexml2argv-commandline.xml [new file with mode: 0644]
tests/bhyvexml2argvtest.c
tests/bhyvexml2xmloutdata/bhyvexml2xmlout-commandline.xml [new file with mode: 0644]
tests/bhyvexml2xmltest.c

index aa50eac424711d00f4536d403ae850c23bfbb47d..7672639cb6ea760d03f42cd1b7e8eacac88d5d15 100644 (file)
@@ -81,6 +81,9 @@
         <optional>
           <ref name='launchSecurity'/>
         </optional>
+        <optional>
+          <ref name='bhyvecmdline'/>
+        </optional>
       </interleave>
     </element>
   </define>
     </element>
   </define>
 
+  <!--
+       Optional hypervisor extensions in their own namespace:
+         Bhyve
+    -->
+  <define name="bhyvecmdline">
+    <element name="commandline" ns="http://libvirt.org/schemas/domain/bhyve/1.0">
+      <zeroOrMore>
+        <element name="arg">
+          <attribute name='value'/>
+        </element>
+      </zeroOrMore>
+    </element>
+  </define>
+
   <!--
        Type library
     -->
index 84fda0894359cd2529b9115aadc182f696327611..a1ae2026a07add2e06efc5c9af275cc1fb7683b5 100644 (file)
@@ -28,6 +28,7 @@
 #include "bhyve_capabilities.h"
 #include "bhyve_command.h"
 #include "bhyve_domain.h"
+#include "bhyve_conf.h"
 #include "bhyve_driver.h"
 #include "datatypes.h"
 #include "viralloc.h"
@@ -626,6 +627,14 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
     if (bhyveBuildConsoleArgStr(def, cmd) < 0)
         goto error;
 
+    if (def->namespaceData) {
+        bhyveDomainCmdlineDefPtr bhyvecmd;
+
+        bhyvecmd = def->namespaceData;
+        for (i = 0; i < bhyvecmd->num_args; i++)
+            virCommandAddArg(cmd, bhyvecmd->args[i]);
+    }
+
     virCommandAddArg(cmd, def->name);
 
     return cmd;
index 60baa2e8486accbd586151ef9c8e0f53c4b5e178..0cdb3b1d727c538a40e0aa32187fd6b64dd7869d 100644 (file)
@@ -25,6 +25,7 @@
 #include "virlog.h"
 #include "virstring.h"
 #include "bhyve_conf.h"
+#include "bhyve_domain.h"
 #include "configmake.h"
 
 #define VIR_FROM_THIS VIR_FROM_BHYVE
@@ -107,3 +108,18 @@ virBhyveDriverConfigDispose(void *obj)
 
     VIR_FREE(cfg->firmwareDir);
 }
+
+void
+bhyveDomainCmdlineDefFree(bhyveDomainCmdlineDefPtr def)
+{
+    size_t i;
+
+    if (!def)
+        return;
+
+    for (i = 0; i < def->num_args; i++)
+        VIR_FREE(def->args[i]);
+
+    VIR_FREE(def->args);
+    VIR_FREE(def);
+}
index 8da39fde7ab8162933e1af8dfb11c5a1eace5cd1..eb4a2e0fb8383b3a0f06b89a0e9b2b2593eeb9e0 100644 (file)
@@ -29,4 +29,13 @@ virBhyveDriverConfigPtr virBhyveDriverGetConfig(bhyveConnPtr driver);
 int virBhyveLoadDriverConfig(virBhyveDriverConfigPtr cfg,
                              const char *filename);
 
+typedef struct _bhyveDomainCmdlineDef bhyveDomainCmdlineDef;
+typedef bhyveDomainCmdlineDef *bhyveDomainCmdlineDefPtr;
+struct _bhyveDomainCmdlineDef {
+    size_t num_args;
+    char **args;
+};
+
+void bhyveDomainCmdlineDefFree(bhyveDomainCmdlineDefPtr def);
+
 #endif /* LIBVIRT_BHYVE_CONF_H */
index e54af75f4df83e85f5564e4f473d5fb41c6a9e2c..e422fffb37169d47167ee6671d5a889b85cb938b 100644 (file)
 
 #include <config.h>
 
+#include "bhyve_conf.h"
 #include "bhyve_device.h"
 #include "bhyve_domain.h"
 #include "bhyve_capabilities.h"
 #include "viralloc.h"
 #include "virlog.h"
 
+#include <libxml/xpathInternals.h>
+
 #define VIR_FROM_THIS VIR_FROM_BHYVE
 
 VIR_LOG_INIT("bhyve.bhyve_domain");
 
+#define BHYVE_NAMESPACE_HREF "http://libvirt.org/schemas/domain/bhyve/1.0"
+
 static void *
 bhyveDomainObjPrivateAlloc(void *opaque ATTRIBUTE_UNUSED)
 {
@@ -157,7 +162,8 @@ virBhyveDriverCreateXMLConf(bhyveConnPtr driver)
     virBhyveDriverDomainDefParserConfig.priv = driver;
     return virDomainXMLOptionNew(&virBhyveDriverDomainDefParserConfig,
                                  &virBhyveDriverPrivateDataCallbacks,
-                                 NULL, NULL, NULL);
+                                 &virBhyveDriverDomainXMLNamespace,
+                                 NULL, NULL);
 }
 
 virDomainDefParserConfig virBhyveDriverDomainDefParserConfig = {
@@ -165,3 +171,98 @@ virDomainDefParserConfig virBhyveDriverDomainDefParserConfig = {
     .domainPostParseCallback = bhyveDomainDefPostParse,
     .assignAddressesCallback = bhyveDomainDefAssignAddresses,
 };
+
+static void
+bhyveDomainDefNamespaceFree(void *nsdata)
+{
+    bhyveDomainCmdlineDefPtr cmd = nsdata;
+
+    bhyveDomainCmdlineDefFree(cmd);
+}
+
+static int
+bhyveDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
+                             xmlNodePtr root ATTRIBUTE_UNUSED,
+                             xmlXPathContextPtr ctxt,
+                             void **data)
+{
+    bhyveDomainCmdlineDefPtr cmd = NULL;
+    xmlNodePtr *nodes = NULL;
+    int n;
+    size_t i;
+    int ret = -1;
+
+    if (xmlXPathRegisterNs(ctxt, BAD_CAST "bhyve", BAD_CAST BHYVE_NAMESPACE_HREF) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to register xml namespace '%s'"),
+                       BHYVE_NAMESPACE_HREF);
+        return -1;
+    }
+
+    if (VIR_ALLOC(cmd) < 0)
+        return -1;
+
+    n = virXPathNodeSet("./bhyve:commandline/bhyve:arg", ctxt, &nodes);
+    if (n == 0)
+        ret = 0;
+    if (n <= 0)
+        goto cleanup;
+
+    if (VIR_ALLOC_N(cmd->args, n) < 0)
+        goto cleanup;
+
+    for (i = 0; i < n; i++) {
+        cmd->args[cmd->num_args] = virXMLPropString(nodes[i], "value");
+        if (cmd->args[cmd->num_args] == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("No bhyve command-line argument specified"));
+            goto cleanup;
+        }
+        cmd->num_args++;
+    }
+
+    VIR_STEAL_PTR(*data, cmd);
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(nodes);
+    bhyveDomainDefNamespaceFree(cmd);
+
+    return ret;
+}
+
+static int
+bhyveDomainDefNamespaceFormatXML(virBufferPtr buf ATTRIBUTE_UNUSED,
+                                void *nsdata)
+{
+    bhyveDomainCmdlineDefPtr cmd = nsdata;
+    size_t i;
+
+    if (!cmd->num_args)
+        return 0;
+
+    virBufferAddLit(buf, "<bhyve:commandline>\n");
+    virBufferAdjustIndent(buf, 2);
+
+    for (i = 0; i < cmd->num_args; i++)
+        virBufferEscapeString(buf, "<bhyve:arg value='%s'/>\n",
+                              cmd->args[i]);
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</bhyve:commandline>\n");
+
+    return 0;
+}
+
+static const char *
+bhyveDomainDefNamespaceHref(void)
+{
+    return "xmlns:bhyve='" BHYVE_NAMESPACE_HREF "'";
+}
+
+virDomainXMLNamespace virBhyveDriverDomainXMLNamespace = {
+    .parse = bhyveDomainDefNamespaceParse,
+    .free = bhyveDomainDefNamespaceFree,
+    .format = bhyveDomainDefNamespaceFormatXML,
+    .href = bhyveDomainDefNamespaceHref,
+};
index f34e5fe9676a7a11ef20530821086a337ebab67d..5f94038e89aae497c8c0fc129127fb12a08bd804 100644 (file)
@@ -39,5 +39,6 @@ virDomainXMLOptionPtr virBhyveDriverCreateXMLConf(bhyveConnPtr);
 
 extern virDomainXMLPrivateDataCallbacks virBhyveDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virBhyveDriverDomainDefParserConfig;
+extern virDomainXMLNamespace virBhyveDriverDomainXMLNamespace;
 
 #endif /* LIBVIRT_BHYVE_DOMAIN_H */
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.args b/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.args
new file mode 100644 (file)
index 0000000..cb21b99
--- /dev/null
@@ -0,0 +1,9 @@
+/usr/sbin/bhyve \
+-c 1 \
+-m 214 \
+-u \
+-H \
+-P \
+-s 0:0,hostbridge \
+-s 2:0,ahci,hd:/tmp/freebsd.img \
+-s 3:0,virtio-net,faketapdev,mac=52:54:00:b9:94:02 ARGUMENT1 ARGUMENT2 bhyve
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.ldargs b/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.ldargs
new file mode 100644 (file)
index 0000000..32538b5
--- /dev/null
@@ -0,0 +1,3 @@
+/usr/sbin/bhyveload \
+-m 214 \
+-d /tmp/freebsd.img bhyve
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.xml b/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.xml
new file mode 100644 (file)
index 0000000..0b222e4
--- /dev/null
@@ -0,0 +1,27 @@
+<domain type='bhyve' xmlns:bhyve="http://libvirt.org/schemas/domain/bhyve/1.0">
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory>219136</memory>
+  <vcpu>1</vcpu>
+  <os>
+    <type>hvm</type>
+  </os>
+  <devices>
+    <disk type='file'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+      <address type='drive' controller='0' bus='0' target='2' unit='0'/>
+    </disk>
+    <interface type='bridge'>
+      <mac address='52:54:00:b9:94:02'/>
+      <model type='virtio'/>
+      <source bridge="virbr0"/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </interface>
+  </devices>
+  <bhyve:commandline>
+    <bhyve:arg value='ARGUMENT1'/>
+    <bhyve:arg value='ARGUMENT2'/>
+  </bhyve:commandline>
+</domain>
index d1b486fa64d30bda2586c55d9c329227981b661f..4a7f65a8e21ae52676e301aa60b00908cefe09af 100644 (file)
@@ -210,6 +210,7 @@ mymain(void)
     DO_TEST("vnc-autoport");
     DO_TEST("cputopology");
     DO_TEST_FAILURE("cputopology-nvcpu-mismatch");
+    DO_TEST("commandline");
 
     /* Address allocation tests */
     DO_TEST("addr-single-sata-disk");
diff --git a/tests/bhyvexml2xmloutdata/bhyvexml2xmlout-commandline.xml b/tests/bhyvexml2xmloutdata/bhyvexml2xmlout-commandline.xml
new file mode 100644 (file)
index 0000000..7e6b0e4
--- /dev/null
@@ -0,0 +1,37 @@
+<domain type='bhyve' xmlns:bhyve='http://libvirt.org/schemas/domain/bhyve/1.0'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <disk type='file' device='disk'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+      <address type='drive' controller='0' bus='0' target='2' unit='0'/>
+    </disk>
+    <controller type='pci' index='0' model='pci-root'/>
+    <controller type='sata' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+    </controller>
+    <interface type='bridge'>
+      <mac address='52:54:00:b9:94:02'/>
+      <source bridge='virbr0'/>
+      <model type='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </interface>
+  </devices>
+  <bhyve:commandline>
+    <bhyve:arg value='ARGUMENT1'/>
+    <bhyve:arg value='ARGUMENT2'/>
+  </bhyve:commandline>
+</domain>
index 6aaeab741ecff5f100f06ea40ee27080f876a964..ed421b883931fc79f87c3570ddce995a6e7725dd 100644 (file)
@@ -110,6 +110,7 @@ mymain(void)
     DO_TEST_DIFFERENT("vnc-vgaconf-off");
     DO_TEST_DIFFERENT("vnc-vgaconf-io");
     DO_TEST_DIFFERENT("vnc-autoport");
+    DO_TEST_DIFFERENT("commandline");
 
     /* Address allocation tests */
     DO_TEST_DIFFERENT("addr-single-sata-disk");