]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
network: wire up dnsmasq option xmlns
authorCole Robinson <crobinso@redhat.com>
Sun, 14 Jul 2019 22:25:12 +0000 (18:25 -0400)
committerCole Robinson <crobinso@redhat.com>
Wed, 17 Jul 2019 21:18:56 +0000 (17:18 -0400)
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

Reviewed-by: Laine Stump <laine@laine.org>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
docs/schemas/network.rng
src/network/bridge_driver.c
src/network/bridge_driver.h
tests/Makefile.am
tests/networkxml2confdata/dnsmasq-options.conf [new file with mode: 0644]
tests/networkxml2confdata/dnsmasq-options.xml [new file with mode: 0644]
tests/networkxml2conftest.c
tests/networkxml2xmlin/dnsmasq-options.xml [new file with mode: 0644]
tests/networkxml2xmlout/dnsmasq-options.xml [new file with mode: 0644]
tests/networkxml2xmltest.c

index 2a6e3358fdf60e5149f88aaf45ef4c8fe4145306..56937d6a4e881a7a460025d6fdfa43dc15a1ef77 100644 (file)
         <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>
index 1a4d6e7f7baaf534c9bc5521bd2c6436cf0adfdb..41fa89a4afb18fe9fb33cd86a0efb8f6ec743fe4 100644 (file)
@@ -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;
 
index 7357c1754c9712e97660a9cd26e726e05e592130..b095388a0b2acea4db31a83eee957c48b3892acf 100644 (file)
 #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);
 
index 2cb78c131059f21f7c79109ad8ec79ba4863d088..f480e68e7d3a2a93e9e6f57798951cee19b83f45 100644 (file)
@@ -332,13 +332,13 @@ test_programs += virjsontest
 endif WITH_YAJL
 
 test_programs += \
-               networkxml2xmltest \
                networkxml2xmlupdatetest \
                virnetworkportxml2xmltest \
                $(NULL)
 
 if WITH_NETWORK
 test_programs += \
+               networkxml2xmltest \
                networkxml2conftest \
                networkxml2firewalltest \
                $(NULL)
@@ -807,11 +807,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
@@ -823,6 +818,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
@@ -834,7 +834,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 (file)
index 0000000..867f355
--- /dev/null
@@ -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 (file)
index 0000000..35a87b8
--- /dev/null
@@ -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>
index c44555109945ad504ad8440eaf0e0816da472992..dcb99aad6e7515060e409328a874aadfd0a8e39f 100644 (file)
@@ -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 (file)
index 0000000..35a87b8
--- /dev/null
@@ -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 (file)
index 0000000..856a018
--- /dev/null
@@ -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>
index cd76ce53752a340c05db411c74849dda690e817c..3d900234456c21237a50b6142a814d69f4698fba 100644 (file)
@@ -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;
 }