[libvirt] [PATCH v6 5/5] Network: Add support for DNS hosts definition to the network XML

Michal Novotny minovotn at redhat.com
Fri Jun 24 10:04:40 UTC 2011


This commit introduces names definition for the DNS hosts file using
the following syntax:

  <dns>
    <host ip="192.168.1.1">
      <name>alias1</name>
      <name>alias2</name>
    </host>
  </dns>

Some of the improvements and fixes were done by Laine Stump so
I'm putting him into the SOB clause again ;-)

Signed-off-by: Michal Novotny <minovotn at redhat.com>
Signed-off-by: Laine Stump <lstump at redhat.com>
---
 docs/formatnetwork.html.in                         |    9 +--
 docs/schemas/network.rng                           |    8 ++
 src/conf/network_conf.c                            |   94 ++++++++++++++++++++
 src/conf/network_conf.h                            |   10 ++
 src/network/bridge_driver.c                        |   28 ++++--
 .../networkxml2argvdata/nat-network-dns-hosts.argv |    1 +
 .../networkxml2argvdata/nat-network-dns-hosts.xml  |   14 +++
 tests/networkxml2argvtest.c                        |    1 +
 tests/networkxml2xmlin/nat-network-dns-hosts.xml   |   14 +++
 tests/networkxml2xmlout/nat-network-dns-hosts.xml  |   14 +++
 tests/networkxml2xmltest.c                         |    1 +
 11 files changed, 177 insertions(+), 17 deletions(-)
 create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv
 create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.xml
 create mode 100644 tests/networkxml2xmlin/nat-network-dns-hosts.xml
 create mode 100644 tests/networkxml2xmlout/nat-network-dns-hosts.xml

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index a036545..f17cc63 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -224,15 +224,8 @@
          to the DNS service. The IP address is identified by the <code>ip</code> attribute
          and the names for the IP addresses are identified in the <code>hostname</code>
          subelements of the <code>host</code> element.
-         <span class="since">Since 0.9.1</span>
+         <span class="since">Since 0.9.3</span>
        </dd>
-      <dt><code>host</code></dt>
-      <dd>The <code>host</code> element is the definition of DNS hosts to be passed
-        to the DNS service. The IP address is identified by the <code>ip</code> attribute
-        and the names for the IP addresses are identified in the <code>hostname</code>
-        subelements of the <code>host</code> element.
-        <span class="since">Since 0.9.1</span>
-      </dd>
     </dl>
 
     <h2><a name="examples">Example configuration</a></h2>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index c42382e..05f45e5 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -97,6 +97,14 @@
                   <attribute name="value"><text/></attribute>
                 </element>
               </zeroOrMore>
+              <zeroOrMore>
+                <element name="host">
+                  <attribute name="ip"><ref name="ipv4-addr"/></attribute>
+                  <oneOrMore>
+                    <element name="hostname"><text/></element>
+                  </oneOrMore>
+                </element>
+              </zeroOrMore>
             </element>
         </optional>
 
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index d8f1e25..d0860d8 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -114,6 +114,14 @@ static void virNetworkDNSDefFree(virNetworkDNSDefPtr def)
             }
             VIR_FREE(def->txtrecords);
         }
+        if (def->nhosts) {
+            while (def->nhosts--) {
+                while (def->hosts[def->nhosts].nnames--)
+                    VIR_FREE(def->hosts[def->nhosts].names[def->hosts[def->nhosts].nnames]);
+                VIR_FREE(def->hosts[def->nhosts].names);
+            }
+            VIR_FREE(def->hosts);
+        }
         VIR_FREE(def);
     }
 }
@@ -451,6 +459,71 @@ virNetworkDHCPRangeDefParseXML(const char *networkName,
 }
 
 static int
+virNetworkDNSHostsDefParseXML(virNetworkDNSDefPtr def,
+                              xmlNodePtr node)
+{
+    xmlNodePtr cur;
+    char *ip;
+    virSocketAddr inaddr;
+    int ret = -1;
+
+    if (def->hosts == NULL) {
+        if (VIR_ALLOC(def->hosts) < 0) {
+            virReportOOMError();
+            goto error;
+        }
+        def->nhosts = 0;
+    }
+
+    if (!(ip = virXMLPropString(node, "ip")) ||
+        (virSocketParseAddr(ip, &inaddr, AF_UNSPEC) < 0)) {
+        virNetworkReportError(VIR_ERR_XML_DETAIL,
+                              _("Missing IP address in DNS host definition"));
+        VIR_FREE(ip);
+        goto error;
+    }
+    VIR_FREE(ip);
+
+    if (VIR_REALLOC_N(def->hosts, def->nhosts + 1) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+
+    def->hosts[def->nhosts].ip = inaddr;
+    def->hosts[def->nhosts].nnames = 0;
+
+    if (VIR_ALLOC(def->hosts[def->nhosts].names) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+
+    cur = node->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE &&
+            xmlStrEqual(cur->name, BAD_CAST "hostname")) {
+              if (cur->children != NULL) {
+                  if (VIR_REALLOC_N(def->hosts[def->nhosts].names, def->hosts[def->nhosts].nnames + 1) < 0) {
+                      virReportOOMError();
+                      goto error;
+                  }
+
+                  def->hosts[def->nhosts].names[def->hosts[def->nhosts].nnames] = strdup((char *)cur->children->content);
+                  def->hosts[def->nhosts].nnames++;
+              }
+        }
+
+        cur = cur->next;
+    }
+
+    def->nhosts++;
+
+    ret = 0;
+
+error:
+    return ret;
+}
+
+static int
 virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef,
                          xmlNodePtr node)
 {
@@ -496,6 +569,11 @@ virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef,
             def->ntxtrecords++;
             name = NULL;
             value = NULL;
+        } else if (cur->type == XML_ELEMENT_NODE &&
+            xmlStrEqual(cur->name, BAD_CAST "host")) {
+            ret = virNetworkDNSHostsDefParseXML(def, cur);
+            if (ret < 0)
+                goto error;
         }
 
         cur = cur->next;
@@ -854,6 +932,22 @@ virNetworkDNSDefFormat(virBufferPtr buf,
                               def->txtrecords[i].value);
     }
 
+    if (def->nhosts) {
+        int ii, j;
+
+        for (ii = 0 ; ii < def->nhosts; ii++) {
+            char *ip = virSocketFormatAddr(&def->hosts[ii].ip);
+
+            virBufferAsprintf(buf, "    <host ip='%s'>\n", ip);
+
+            for (j = 0; j < def->hosts[ii].nnames; j++)
+                virBufferAsprintf(buf, "      <hostname>%s</hostname>\n",
+                                               def->hosts[ii].names[j]);
+
+            virBufferAsprintf(buf, "    </host>\n");
+        }
+    }
+
     virBufferAddLit(buf, "  </dns>\n");
 out:
     return result;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index d0dac02..d7d2951 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -64,9 +64,19 @@ struct _virNetworkDNSTxtRecordsDef {
     char *value;
 };
 
+struct virNetworkDNSHostsDef {
+    virSocketAddr ip;
+    int nnames;
+    char **names;
+} virNetworkDNSHostsDef;
+
+typedef struct virNetworkDNSHostsDef *virNetworkDNSHostsDefPtr;
+
 struct virNetworkDNSDef {
     unsigned int ntxtrecords;
     virNetworkDNSTxtRecordsDefPtr txtrecords;
+    unsigned int nhosts;
+    virNetworkDNSHostsDefPtr hosts;
 } virNetworkDNSDef;
 
 typedef struct virNetworkDNSDef *virNetworkDNSDefPtr;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 448afbd..1b11132 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -435,10 +435,11 @@ networkShutdown(void) {
 
 static dnsmasqContext*
 networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef,
+                            virNetworkDNSDefPtr dnsdef,
                             char *name,
                             bool force)
 {
-    unsigned int i;
+    unsigned int i, j;
 
     dnsmasqContext *dctx = dnsmasqContextNew(name,
                                              DNSMASQ_STATE_DIR);
@@ -447,13 +448,22 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef,
         goto cleanup;
     }
 
-    if (! force && virFileExists(dctx->hostsfile->path))
-        return 0;
+    if (!(! force && virFileExists(dctx->hostsfile->path))) {
+        for (i = 0; i < ipdef->nhosts; i++) {
+            virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
+            if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip))
+                dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name);
+        }
+    }
 
-    for (i = 0; i < ipdef->nhosts; i++) {
-        virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
-        if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip))
-            dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name);
+    if (dnsdef) {
+        for (i = 0; i < dnsdef->nhosts; i++) {
+            virNetworkDNSHostsDefPtr host = &(dnsdef->hosts[i]);
+            if (VIR_SOCKET_HAS_ADDR(&host->ip)) {
+                for (j = 0; j < host->nnames; j++)
+                    dnsmasqAddHost(dctx, &host->ip, host->names[j]);
+            }
+        }
     }
 
     if (dnsmasqSave(dctx) < 0)
@@ -604,7 +614,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
         if (ipdef->nranges || ipdef->nhosts)
             virCommandAddArg(cmd, "--dhcp-no-override");
 
-            if ((dctx = networkSaveDnsmasqHostsfile(ipdef, network->def->name, false))) {
+            if ((dctx = networkSaveDnsmasqHostsfile(ipdef, network->def->dns, network->def->name, false))) {
                 if (dctx->hostsfile->nhosts)
                     virCommandAddArgPair(cmd, "--dhcp-hostsfile",
                                          dctx->hostsfile->path);
@@ -2239,7 +2249,7 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
         }
     }
     if (ipv4def) {
-        dnsmasqContext* dctx = networkSaveDnsmasqHostsfile(ipv4def, network->def->name, true);
+        dnsmasqContext* dctx = networkSaveDnsmasqHostsfile(ipv4def, network->def->dns, network->def->name, true);
         if (dctx == NULL)
             goto cleanup;
         dnsmasqContextFree(dctx);
diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
new file mode 100644
index 0000000..d240bf4
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
@@ -0,0 +1 @@
+/usr/sbin/dnsmasq --strict-order --bind-interfaces --conf-file= --except-interface lo --listen-address 192.168.122.1 --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
\ No newline at end of file
diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.xml b/tests/networkxml2argvdata/nat-network-dns-hosts.xml
new file mode 100644
index 0000000..9a83fed
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-hosts.xml
@@ -0,0 +1,14 @@
+<network>
+  <name>default</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9c</uuid>
+  <forward dev='eth0' mode='nat'/>
+  <bridge name='virbr0' stp='on' delay='0' />
+  <dns>
+    <host ip='192.168.122.1'>
+      <hostname>host</hostname>
+      <hostname>gateway</hostname>
+    </host>
+  </dns>
+  <ip address='192.168.122.1' netmask='255.255.255.0'>
+  </ip>
+</network>
diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c
index 98c84ad..16d57a9 100644
--- a/tests/networkxml2argvtest.c
+++ b/tests/networkxml2argvtest.c
@@ -101,6 +101,7 @@ mymain(void)
     DO_TEST("netboot-network");
     DO_TEST("netboot-proxy-network");
     DO_TEST("nat-network-dns-txt-record");
+    DO_TEST("nat-network-dns-hosts");
 
     return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
diff --git a/tests/networkxml2xmlin/nat-network-dns-hosts.xml b/tests/networkxml2xmlin/nat-network-dns-hosts.xml
new file mode 100644
index 0000000..9a83fed
--- /dev/null
+++ b/tests/networkxml2xmlin/nat-network-dns-hosts.xml
@@ -0,0 +1,14 @@
+<network>
+  <name>default</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9c</uuid>
+  <forward dev='eth0' mode='nat'/>
+  <bridge name='virbr0' stp='on' delay='0' />
+  <dns>
+    <host ip='192.168.122.1'>
+      <hostname>host</hostname>
+      <hostname>gateway</hostname>
+    </host>
+  </dns>
+  <ip address='192.168.122.1' netmask='255.255.255.0'>
+  </ip>
+</network>
diff --git a/tests/networkxml2xmlout/nat-network-dns-hosts.xml b/tests/networkxml2xmlout/nat-network-dns-hosts.xml
new file mode 100644
index 0000000..9a83fed
--- /dev/null
+++ b/tests/networkxml2xmlout/nat-network-dns-hosts.xml
@@ -0,0 +1,14 @@
+<network>
+  <name>default</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9c</uuid>
+  <forward dev='eth0' mode='nat'/>
+  <bridge name='virbr0' stp='on' delay='0' />
+  <dns>
+    <host ip='192.168.122.1'>
+      <hostname>host</hostname>
+      <hostname>gateway</hostname>
+    </host>
+  </dns>
+  <ip address='192.168.122.1' netmask='255.255.255.0'>
+  </ip>
+</network>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index 2cc8e56..065166d 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -87,6 +87,7 @@ mymain(void)
     DO_TEST("netboot-network");
     DO_TEST("netboot-proxy-network");
     DO_TEST("nat-network-dns-txt-record");
+    DO_TEST("nat-network-dns-hosts");
 
     return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
-- 
1.7.3.2




More information about the libvir-list mailing list