[4/5] network: wire up dnsmasq option xmlns

Message ID d44e76f50197e80016bdb8eedd0b31b2262f3b07.1563148979.git.crobinso@redhat.com
State Accepted
Commit fb9f6ce625322d10b2e2a7c3ce4faab780b97e8d
Headers show
Series
  • network: xmlns dnsmasq option passthrough
Related show

Commit Message

Cole Robinson July 15, 2019, 12:04 a.m.
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@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

-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Comments

Ján Tomko July 18, 2019, 1:08 p.m. | #1
On Sun, Jul 14, 2019 at 08:04:00PM -0400, Cole Robinson wrote:
>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@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

>

>+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;

>+    }


This breaks the build on Debian in Jenkins and Ubuntu 18 on travis:
https://ci.centos.org/view/libvirt/job/libvirt-build/systems=libvirt-debian-9/663/console
https://travis-ci.org/libvirt/libvirt/jobs/560399203

Jano
>+

>+    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;

>+}
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Patch

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;
 }