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@xxxxxxxxx> --- docs/schemas/domaincommon.rng | 17 +++ src/bhyve/bhyve_command.c | 9 ++ src/bhyve/bhyve_conf.c | 15 +++ src/bhyve/bhyve_conf.h | 9 ++ src/bhyve/bhyve_domain.c | 107 +++++++++++++++++- src/bhyve/bhyve_domain.h | 1 + .../bhyvexml2argv-commandline.args | 9 ++ .../bhyvexml2argv-commandline.ldargs | 3 + .../bhyvexml2argv-commandline.xml | 27 +++++ tests/bhyvexml2argvtest.c | 1 + .../bhyvexml2xmlout-commandline.xml | 37 ++++++ tests/bhyvexml2xmltest.c | 1 + 12 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-commandline.args create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-commandline.ldargs create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-commandline.xml create mode 100644 tests/bhyvexml2xmloutdata/bhyvexml2xmlout-commandline.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index aa50eac424..7672639cb6 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -81,6 +81,9 @@ <optional> <ref name='launchSecurity'/> </optional> + <optional> + <ref name='bhyvecmdline'/> + </optional> </interleave> </element> </define> @@ -6127,6 +6130,20 @@ </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 --> diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index 84fda08943..a1ae2026a0 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -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; diff --git a/src/bhyve/bhyve_conf.c b/src/bhyve/bhyve_conf.c index 60baa2e848..75709801c7 100644 --- a/src/bhyve/bhyve_conf.c +++ b/src/bhyve/bhyve_conf.c @@ -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,17 @@ 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); +} diff --git a/src/bhyve/bhyve_conf.h b/src/bhyve/bhyve_conf.h index 8da39fde7a..eb4a2e0fb8 100644 --- a/src/bhyve/bhyve_conf.h +++ b/src/bhyve/bhyve_conf.h @@ -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 */ diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c index e54af75f4d..554188ebeb 100644 --- a/src/bhyve/bhyve_domain.c +++ b/src/bhyve/bhyve_domain.c @@ -20,16 +20,21 @@ #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,102 @@ 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; + bool uses_bhyve_ns = false; + xmlNodePtr *nodes = NULL; + int n; + size_t i; + + 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) + goto error; + uses_bhyve_ns = n > 0; + + if (n && VIR_ALLOC_N(cmd->args, n) < 0) + goto error; + + 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 error; + } + cmd->num_args++; + } + + VIR_FREE(nodes); + + if (uses_bhyve_ns) + *data = cmd; + else + VIR_FREE(cmd); + + return 0; + + error: + VIR_FREE(nodes); + bhyveDomainDefNamespaceFree(cmd); + return -1; +} + +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, +}; diff --git a/src/bhyve/bhyve_domain.h b/src/bhyve/bhyve_domain.h index f34e5fe967..5f94038e89 100644 --- a/src/bhyve/bhyve_domain.h +++ b/src/bhyve/bhyve_domain.h @@ -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 index 0000000000..cb21b99cd6 --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.args @@ -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 index 0000000000..32538b558e --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.ldargs @@ -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 index 0000000000..0b222e4f8f --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-commandline.xml @@ -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> diff --git a/tests/bhyvexml2argvtest.c b/tests/bhyvexml2argvtest.c index d1b486fa64..4a7f65a8e2 100644 --- a/tests/bhyvexml2argvtest.c +++ b/tests/bhyvexml2argvtest.c @@ -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 index 0000000000..7e6b0e430f --- /dev/null +++ b/tests/bhyvexml2xmloutdata/bhyvexml2xmlout-commandline.xml @@ -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> diff --git a/tests/bhyvexml2xmltest.c b/tests/bhyvexml2xmltest.c index 6aaeab741e..ed421b8839 100644 --- a/tests/bhyvexml2xmltest.c +++ b/tests/bhyvexml2xmltest.c @@ -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"); -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list