This maps to XML like:
<network
xmlns:dnsmasq='http://libvirt.org/schemas/network/dnsmasq/1.0'>
...
<dnsmasq:options>
<dnsmasq:option value="foo=bar"/>
<dnsmasq:option
value="cname=*.foo.example.com,master.example.com"/>
</dnsmasq:options>
</network>
To dnsmasq config options
...
foo=bar
cname=*.foo.example.com,master.example.com
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
docs/schemas/network.rng | 11 ++
src/network/bridge_driver.c | 130 +++++++++++++++++-
src/network/bridge_driver.h | 12 ++
tests/Makefile.am | 14 +-
.../networkxml2confdata/dnsmasq-options.conf | 18 +++
tests/networkxml2confdata/dnsmasq-options.xml | 15 ++
tests/networkxml2conftest.c | 8 +-
tests/networkxml2xmlin/dnsmasq-options.xml | 15 ++
tests/networkxml2xmlout/dnsmasq-options.xml | 17 +++
tests/networkxml2xmltest.c | 11 +-
10 files changed, 239 insertions(+), 12 deletions(-)
create mode 100644 tests/networkxml2confdata/dnsmasq-options.conf
create mode 100644 tests/networkxml2confdata/dnsmasq-options.xml
create mode 100644 tests/networkxml2xmlin/dnsmasq-options.xml
create mode 100644 tests/networkxml2xmlout/dnsmasq-options.xml
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 2a6e3358fd..56937d6a4e 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -405,6 +405,17 @@
<zeroOrMore>
<ref name="route"/>
</zeroOrMore>
+
+ <!-- <dnsmasq:options> -->
+ <optional>
+ <element name="options"
ns="http://libvirt.org/schemas/network/dnsmasq/1.0">
+ <zeroOrMore>
+ <element name="option">
+ <attribute name='value'/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </optional>
</interleave>
</element>
</define>
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 1a4d6e7f7b..41fa89a4af 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -69,6 +69,8 @@
#include "virjson.h"
#include "virnetworkportdef.h"
+#include <libxml/xpathInternals.h>
+
#define VIR_FROM_THIS VIR_FROM_NETWORK
#define MAX_BRIDGE_ID 256
@@ -83,6 +85,8 @@
VIR_LOG_INIT("network.bridge_driver");
+#define DNSMASQ_NAMESPACE_HREF
"http://libvirt.org/schemas/network/dnsmasq/1.0"
+
static virNetworkDriverStatePtr network_driver;
@@ -136,10 +140,126 @@ networkDnsmasqCapsRefresh(virNetworkDriverStatePtr driver)
return 0;
}
-static virNetworkXMLOptionPtr
+
+static void
+networkDnsmasqDefNamespaceFree(void *nsdata)
+{
+ networkDnsmasqXmlNsDefPtr def = nsdata;
+ if (!def)
+ return;
+
+ virStringListFreeCount(def->options, def->noptions);
+
+ VIR_FREE(def);
+}
+
+
+static int
+networkDnsmasqDefNamespaceParseOptions(networkDnsmasqXmlNsDefPtr nsdef,
+ xmlXPathContextPtr ctxt)
+{
+ VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
+ ssize_t nnodes;
+ size_t i;
+
+ if ((nnodes = virXPathNodeSet("./dnsmasq:options/dnsmasq:option",
+ ctxt, &nodes)) < 0)
+ return -1;
+
+ if (nnodes == 0)
+ return 0;
+
+ if (VIR_ALLOC_N(nsdef->options, nnodes) < 0)
+ return -1;
+
+ for (i = 0; i < nnodes; i++) {
+ if (!(nsdef->options[nsdef->noptions++] = virXMLPropString(nodes[i],
"value"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("No dnsmasq options value specified"));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+networkDnsmasqDefNamespaceParse(xmlXPathContextPtr ctxt,
+ void **data)
+{
+ networkDnsmasqXmlNsDefPtr nsdata = NULL;
+ int ret = -1;
+
+ if (xmlXPathRegisterNs(ctxt, BAD_CAST "dnsmasq",
+ BAD_CAST DNSMASQ_NAMESPACE_HREF) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to register xml namespace '%s'"),
+ DNSMASQ_NAMESPACE_HREF);
+ return -1;
+ }
+
+ if (VIR_ALLOC(nsdata) < 0)
+ return -1;
+
+ if (networkDnsmasqDefNamespaceParseOptions(nsdata, ctxt))
+ goto cleanup;
+
+ if (nsdata->noptions > 0)
+ VIR_STEAL_PTR(*data, nsdata);
+
+ ret = 0;
+
+ cleanup:
+ networkDnsmasqDefNamespaceFree(nsdata);
+ return ret;
+}
+
+
+static int
+networkDnsmasqDefNamespaceFormatXML(virBufferPtr buf,
+ void *nsdata)
+{
+ networkDnsmasqXmlNsDefPtr def = nsdata;
+ size_t i;
+
+ if (!def->noptions)
+ return 0;
+
+ virBufferAddLit(buf, "<dnsmasq:options>\n");
+ virBufferAdjustIndent(buf, 2);
+
+ for (i = 0; i < def->noptions; i++) {
+ virBufferEscapeString(buf, "<dnsmasq:option
value='%s'/>\n",
+ def->options[i]);
+ }
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</dnsmasq:options>\n");
+
+ return 0;
+}
+
+
+static const char *
+networkDnsmasqDefNamespaceHref(void)
+{
+ return "xmlns:dnsmasq='" DNSMASQ_NAMESPACE_HREF "'";
+}
+
+
+virNetworkXMLNamespace networkDnsmasqXMLNamespace = {
+ .parse = networkDnsmasqDefNamespaceParse,
+ .free = networkDnsmasqDefNamespaceFree,
+ .format = networkDnsmasqDefNamespaceFormatXML,
+ .href = networkDnsmasqDefNamespaceHref,
+};
+
+
+virNetworkXMLOptionPtr
networkDnsmasqCreateXMLConf(void)
{
- return virNetworkXMLOptionNew(NULL);
+ return virNetworkXMLOptionNew(&networkDnsmasqXMLNamespace);
}
@@ -1480,6 +1600,12 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
}
}
+ if (def->namespaceData) {
+ networkDnsmasqXmlNsDefPtr dnsmasqxmlns = def->namespaceData;
+ for (i = 0; i < dnsmasqxmlns->noptions; i++)
+ virBufferAsprintf(&configbuf, "%s\n",
dnsmasqxmlns->options[i]);
+ }
+
if (!(*configstr = virBufferContentAndReset(&configbuf)))
goto cleanup;
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index 7357c1754c..b095388a0b 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -27,6 +27,18 @@
#include "virdnsmasq.h"
#include "virnetworkobj.h"
+extern virNetworkXMLNamespace networkDnsmasqXMLNamespace;
+
+typedef struct _networkDnsmasqXmlNsDef networkDnsmasqXmlNsDef;
+typedef networkDnsmasqXmlNsDef *networkDnsmasqXmlNsDefPtr;
+struct _networkDnsmasqXmlNsDef {
+ size_t noptions;
+ char **options;
+};
+
+virNetworkXMLOptionPtr
+networkDnsmasqCreateXMLConf(void);
+
int
networkRegister(void);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 107f2de859..65192bac8e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -331,13 +331,13 @@ test_programs += virjsontest
endif WITH_YAJL
test_programs += \
- networkxml2xmltest \
networkxml2xmlupdatetest \
virnetworkportxml2xmltest \
$(NULL)
if WITH_NETWORK
test_programs += \
+ networkxml2xmltest \
networkxml2conftest \
networkxml2firewalltest \
$(NULL)
@@ -806,11 +806,6 @@ EXTRA_DIST += \
bhyveargv2xmlmock.c
endif ! WITH_BHYVE
-networkxml2xmltest_SOURCES = \
- networkxml2xmltest.c \
- testutils.c testutils.h
-networkxml2xmltest_LDADD = $(LDADDS)
-
networkxml2xmlupdatetest_SOURCES = \
networkxml2xmlupdatetest.c \
testutils.c testutils.h
@@ -822,6 +817,11 @@ virnetworkportxml2xmltest_SOURCES = \
virnetworkportxml2xmltest_LDADD = $(LDADDS)
if WITH_NETWORK
+networkxml2xmltest_SOURCES = \
+ networkxml2xmltest.c \
+ testutils.c testutils.h
+networkxml2xmltest_LDADD = ../src/libvirt_driver_network_impl.la $(LDADDS)
+
networkxml2conftest_SOURCES = \
networkxml2conftest.c \
testutils.c testutils.h
@@ -833,7 +833,7 @@ networkxml2firewalltest_SOURCES = \
networkxml2firewalltest_LDADD = ../src/libvirt_driver_network_impl.la $(LDADDS)
else ! WITH_NETWORK
-EXTRA_DIST += networkxml2conftest.c
+EXTRA_DIST += networkxml2xmltest.c networkxml2conftest.c
endif ! WITH_NETWORK
if WITH_STORAGE_SHEEPDOG
diff --git a/tests/networkxml2confdata/dnsmasq-options.conf
b/tests/networkxml2confdata/dnsmasq-options.conf
new file mode 100644
index 0000000000..867f355c79
--- /dev/null
+++ b/tests/networkxml2confdata/dnsmasq-options.conf
@@ -0,0 +1,18 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,255.255.255.0
+dhcp-no-override
+dhcp-authoritative
+dhcp-lease-max=253
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+foo=bar
+cname=*.cloudapps.example.com,master.example.com
diff --git a/tests/networkxml2confdata/dnsmasq-options.xml
b/tests/networkxml2confdata/dnsmasq-options.xml
new file mode 100644
index 0000000000..35a87b8e3e
--- /dev/null
+++ b/tests/networkxml2confdata/dnsmasq-options.xml
@@ -0,0 +1,15 @@
+<network
xmlns:dnsmasq="http://libvirt.org/schemas/network/dnsmasq/1.0">
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <bridge name="virbr0"/>
+ <forward mode="nat" dev="eth1"/>
+ <ip address="192.168.122.1" netmask="255.255.255.0">
+ <dhcp>
+ <range start="192.168.122.2" end="192.168.122.254"/>
+ </dhcp>
+ </ip>
+ <dnsmasq:options>
+ <dnsmasq:option value="foo=bar"/>
+ <dnsmasq:option
value="cname=*.cloudapps.example.com,master.example.com"/>
+ </dnsmasq:options>
+</network>
diff --git a/tests/networkxml2conftest.c b/tests/networkxml2conftest.c
index c445551099..dcb99aad6e 100644
--- a/tests/networkxml2conftest.c
+++ b/tests/networkxml2conftest.c
@@ -25,8 +25,12 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf,
dnsmasqCapsPtr
virCommandPtr cmd = NULL;
char *pidfile = NULL;
dnsmasqContext *dctx = NULL;
+ virNetworkXMLOptionPtr xmlopt = NULL;
- if (!(def = virNetworkDefParseFile(inxml, NULL)))
+ if (!(xmlopt = networkDnsmasqCreateXMLConf()))
+ goto fail;
+
+ if (!(def = virNetworkDefParseFile(inxml, xmlopt)))
goto fail;
if (!(obj = virNetworkObjNew()))
@@ -63,6 +67,7 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf,
dnsmasqCapsPtr
VIR_FREE(actual);
VIR_FREE(pidfile);
virCommandFree(cmd);
+ virObjectUnref(xmlopt);
virNetworkObjEndAPI(&obj);
dnsmasqContextFree(dctx);
return ret;
@@ -141,6 +146,7 @@ mymain(void)
DO_TEST("dhcp6-nat-network", dhcpv6);
DO_TEST("dhcp6host-routed-network", dhcpv6);
DO_TEST("ptr-domains-auto", dhcpv6);
+ DO_TEST("dnsmasq-options", dhcpv6);
virObjectUnref(dhcpv6);
virObjectUnref(full);
diff --git a/tests/networkxml2xmlin/dnsmasq-options.xml
b/tests/networkxml2xmlin/dnsmasq-options.xml
new file mode 100644
index 0000000000..35a87b8e3e
--- /dev/null
+++ b/tests/networkxml2xmlin/dnsmasq-options.xml
@@ -0,0 +1,15 @@
+<network
xmlns:dnsmasq="http://libvirt.org/schemas/network/dnsmasq/1.0">
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <bridge name="virbr0"/>
+ <forward mode="nat" dev="eth1"/>
+ <ip address="192.168.122.1" netmask="255.255.255.0">
+ <dhcp>
+ <range start="192.168.122.2" end="192.168.122.254"/>
+ </dhcp>
+ </ip>
+ <dnsmasq:options>
+ <dnsmasq:option value="foo=bar"/>
+ <dnsmasq:option
value="cname=*.cloudapps.example.com,master.example.com"/>
+ </dnsmasq:options>
+</network>
diff --git a/tests/networkxml2xmlout/dnsmasq-options.xml
b/tests/networkxml2xmlout/dnsmasq-options.xml
new file mode 100644
index 0000000000..856a018f25
--- /dev/null
+++ b/tests/networkxml2xmlout/dnsmasq-options.xml
@@ -0,0 +1,17 @@
+<network
xmlns:dnsmasq='http://libvirt.org/schemas/network/dnsmasq/1.0'>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ </dhcp>
+ </ip>
+ <dnsmasq:options>
+ <dnsmasq:option value='foo=bar'/>
+ <dnsmasq:option
value='cname=*.cloudapps.example.com,master.example.com'/>
+ </dnsmasq:options>
+</network>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index cd76ce5375..3d90023445 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -10,6 +10,7 @@
#include "network_conf.h"
#include "testutilsqemu.h"
#include "virstring.h"
+#include "network/bridge_driver.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -29,15 +30,19 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml,
int ret;
testCompareNetXML2XMLResult result = TEST_COMPARE_NET_XML2XML_RESULT_SUCCESS;
virNetworkDefPtr dev = NULL;
+ virNetworkXMLOptionPtr xmlopt = NULL;
- if (!(dev = virNetworkDefParseFile(inxml, NULL))) {
+ if (!(xmlopt = networkDnsmasqCreateXMLConf()))
+ goto cleanup;
+
+ if (!(dev = virNetworkDefParseFile(inxml, xmlopt))) {
result = TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE;
goto cleanup;
}
if (expectResult == TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE)
goto cleanup;
- if (!(actual = virNetworkDefFormat(dev, NULL, flags))) {
+ if (!(actual = virNetworkDefFormat(dev, xmlopt, flags))) {
result = TEST_COMPARE_NET_XML2XML_RESULT_FAIL_FORMAT;
goto cleanup;
}
@@ -67,6 +72,7 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml,
VIR_FREE(actual);
virNetworkDefFree(dev);
+ virObjectUnref(xmlopt);
return ret;
}
@@ -158,6 +164,7 @@ mymain(void)
DO_TEST_PARSE_ERROR("passthrough-duplicate");
DO_TEST("metadata");
DO_TEST("set-mtu");
+ DO_TEST("dnsmasq-options");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
2.21.0