network: wire up dnsmasq option xmlns

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>
This commit is contained in:
Cole Robinson 2019-07-14 18:25:12 -04:00
parent 2dde2dbba1
commit fb9f6ce625
10 changed files with 239 additions and 12 deletions

View File

@ -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>

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

View File

@ -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);

View 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

View File

@ -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

View File

@ -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>

View 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);

View File

@ -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>

View File

@ -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>

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