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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 04/01/2011 06:45 AM, Michal Novotny wrote:
Make: passed
Make check: passed
Make syntax-check: passed

Hi,
this is the patch to add support for DNS hosts definition in the
network XML description to generate the the hosts file. This patch
uses the addnhosts* APIs implemented to the src/util/dnsmasq.c by
part 2 of this patch series.

Also, tests for the XML to XML definition and command-line
regression tests has been added.

Michal

Same comments about the commit message - remove the testing comments, salutation, signature; add in a short example of the XML.

Signed-off-by: Michal Novotny<minovotn@xxxxxxxxxx>
---
  docs/formatnetwork.html.in                         |    7 +
  docs/schemas/network.rng                           |    8 ++
  src/conf/network_conf.c                            |  128 ++++++++++++++++++--
  src/conf/network_conf.h                            |    9 ++
  src/network/bridge_driver.c                        |   20 ++-
  .../networkxml2argvdata/nat-network-dns-hosts.argv |    1 +
  .../networkxml2argvdata/nat-network-dns-hosts.xml  |   19 +++
  tests/networkxml2argvtest.c                        |    1 +
  tests/networkxml2xmlin/nat-network-dns-hosts.xml   |   27 ++++
  tests/networkxml2xmlout/nat-network-dns-hosts.xml  |   27 ++++
  tests/networkxml2xmltest.c                         |    1 +
  11 files changed, 234 insertions(+), 14 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 5211ed2..5d18ed9 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -222,6 +222,13 @@
          separated by commas.
          <span class="since">Since 0.9.1</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 e27dace..05066a5 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -146,6 +146,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>

I think it would be better to simply call it "name" rather than "hostname" (since "host" is already implied by its parent being "<host>")

+</oneOrMore>
+</element>
+</zeroOrMore>

Also, this will move up a level along with the rest of <dns>.

                </element>
              </optional>
            </element>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index b7427d0..1f88649 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -435,6 +435,53 @@ virNetworkDHCPRangeDefParseXML(const char *networkName,
  }

  static int
+virNetworkDNSHostsDefParseXML(virNetworkIpDefPtr def,

(will be virNetworkDefPtr def...)

+                              xmlNodePtr node,
+                              virSocketAddr ip)
+{
+    xmlNodePtr cur;
+    int result = -1;
+
+    if (def->dns->hosts == NULL) {
+        if (VIR_ALLOC(def->dns->hosts)<  0)
+            goto oom_error;
+        def->dns->nhosts = 0;
+    }
+
+    cur = node->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE&&
+            xmlStrEqual(cur->name, BAD_CAST "hostname")) {

Again, s/hostname/name/

+              if (cur->children != NULL) {
+                  char *hostname;
+
+                  hostname = strdup((char *)cur->children->content);
+
+                  if (VIR_REALLOC_N(def->dns->hosts, def->dns->nhosts + 1)<  0) {
+                      VIR_FREE(hostname);
+                      result = -1;
+                      goto oom_error;
+                  }
+
+                  def->dns->hosts[def->dns->nhosts].name = strdup(hostname);

Rather than strduping hostname, then freeing it, just assign the original directly into the struct.

+                  def->dns->hosts[def->dns->nhosts].ip = ip;
+                  def->dns->nhosts++;
+
+                  VIR_FREE(hostname);
+              }
+        }
+
+        cur = cur->next;
+    }
+
+    return 0;
+
+oom_error:
+    virReportOOMError();
+    return result;
+}
+
+static int
  virNetworkDNSDefParseXML(virNetworkIpDefPtr def,
                           xmlNodePtr node)
  {
@@ -476,6 +523,27 @@ virNetworkDNSDefParseXML(virNetworkIpDefPtr def,

              VIR_FREE(name);
              VIR_FREE(value);
+        } else if (cur->type == XML_ELEMENT_NODE&&
+            xmlStrEqual(cur->name, BAD_CAST "host")) {
+            char *ip;
+            virSocketAddr inaddr;
+            memset(&inaddr, 0, sizeof(inaddr));
+
+            if (!(ip = virXMLPropString(cur, "ip"))) {
+                cur = cur->next;
+                continue;
+            }
+            if ((ip == NULL) ||
+                (virSocketParseAddr(ip,&inaddr, AF_UNSPEC)<  0)) {
+                virNetworkReportError(VIR_ERR_XML_DETAIL,
+                                      _("Missing IP address in DNS host definition"));

"Missing/incorrect". Also, since def will end up being virNetworkDefPtr, you can add the name of the network, as well as the string that was given for ip. That will help in finding the source of the error.

+                VIR_FREE(ip);
+                goto error;
+            }
+            VIR_FREE(ip);
+            result = virNetworkDNSHostsDefParseXML(def, cur, inaddr);
+            if (result)
+                goto error;
          }

          cur = cur->next;
@@ -485,6 +553,7 @@ virNetworkDNSDefParseXML(virNetworkIpDefPtr def,

  oom_error:
      virReportOOMError();
+error:
      return result;
  }

@@ -888,17 +957,60 @@ virNetworkIpDefFormat(virBufferPtr buf,

          virBufferAddLit(buf, "</dhcp>\n");
      }
-    if ((def->dns != NULL)&&  (def->dns->ntxtrecords)) {
-        int ii;
-
+    if (def->dns != NULL) {
          virBufferAddLit(buf, "<dns>\n");
-        for (ii = 0 ; ii<  def->dns->ntxtrecords ; ii++) {
-            virBufferVSprintf(buf, "<txt-record name='%s' value='%s' />\n",
-                              def->dns->txtrecords[ii].name,
-                              def->dns->txtrecords[ii].value);
+
+        if (def->dns->ntxtrecords) {

This if() should have been in the patch for <txt>. That way this patch wouldn't be polluted with diffs unrelated to the new feature introduced in this patch.


+            int ii;
+
+            for (ii = 0 ; ii<  def->dns->ntxtrecords; ii++) {
+                virBufferVSprintf(buf, "<txt-record name='%s' value='%s' />\n",
+                                  def->dns->txtrecords[ii].name,
+                                  def->dns->txtrecords[ii].value);
+            }
+        }
+        if (def->dns->nhosts) {
+            int ii, j;
+            char **iplist = NULL;
+            int iplist_size = 0;
+            bool in_list;
+
+            if (VIR_ALLOC(iplist)<  0)
+                goto error;
+
+            for (ii = 0 ; ii<  def->dns->nhosts; ii++) {
+                char *ip = virSocketFormatAddr(&def->dns->hosts[ii].ip);
+                in_list = false;
+                for (j = 0; j<  iplist_size; j++)
+                    if (STREQ(iplist[j], ip))
+                        in_list = true;
+
+                if (!in_list) {
+                    virBufferVSprintf(buf, "<host ip='%s'>\n", ip);
+
+                    for (j = 0 ; j<  def->dns->nhosts; j++) {
+                        char *thisip = virSocketFormatAddr(&def->dns->hosts[j].ip);
+                        if (STREQ(ip, thisip))
+                            virBufferVSprintf(buf, "<hostname>%s</hostname>\n",
+                                              def->dns->hosts[j].name);
+                    }
+                    virBufferVSprintf(buf, "</host>\n");
+
+                    if (VIR_REALLOC_N(iplist, iplist_size + 1)<  0)
+                       goto error;
+
+                    iplist[iplist_size] = strdup(ip);
+                    iplist_size++;
+                }
+            }
+
+            for (j = 0; j<  iplist_size; j++)
+                VIR_FREE(iplist[j]);
+            VIR_FREE(iplist);


It would make more sense if virNetworkDNSHostsDef->name was char** and had an array of names, as you did in PATCH 4/5. That would make the object a more direct representation of the XML data, and eliminate all of this complicated code dealing with "iplist" and nested loops.


          }
+
          virBufferAddLit(buf, "</dns>\n");
-    }
+   }

      virBufferAddLit(buf, "</ip>\n");

diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 5f47595..305ef0f 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -64,9 +64,18 @@ struct _virNetworkDNSTxtRecordsDef {
      char *value;
  };

+struct virNetworkDNSHostsDef {
+    virSocketAddr ip;
+    char *name;

Again - make name char** as you did in PATCH 4/5.

+} virNetworkDNSHostsDef;
+
+typedef struct virNetworkDNSHostsDef *virNetworkDNSHostsDefPtr;
+
  struct virNetworkDNSDef {
      unsigned int ntxtrecords;
+    unsigned int nhosts;
      virNetworkDNSTxtRecordsDefPtr txtrecords;
+    virNetworkDNSHostsDefPtr hosts;
  } virNetworkDNSDef;

  typedef struct virNetworkDNSDef *virNetworkDNSDefPtr;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 4ad3143..99a61b0 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -434,13 +434,20 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef,

This function is going to also need a virNetworkDefPtr arg if dns moves up a level.

          goto cleanup;
      }

-    if (! force&&  virFileExists(dctx->hostsfile->path))
-        return 0;
+    if (!(! force&&  virFileExists(dctx->hostsfile->path))) {

That is much easier to understand if written as:

    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 (ipdef->dns) {
+        for (i = 0; i<  ipdef->dns->nhosts; i++) {
+            virNetworkDNSHostsDefPtr host =&(ipdef->dns->hosts[i]);
+            if (VIR_SOCKET_HAS_ADDR(&host->ip))
+                dnsmasqAddHost(dctx,&host->ip, host->name);


If you change the virNetworkDNSHostDefPtr to contain char **name instead of char *name, and dnsmasqAddHost to accept char** rather than char*, this can remain pretty much unchanged.


+        }
      }

      if (dnsmasqSave(dctx)<  0)
@@ -589,6 +596,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
              if (dctx->hostsfile->nhosts)
                  virCommandAddArgPair(cmd, "--dhcp-hostsfile",
                                       dctx->hostsfile->path);
+            VIR_DEBUG("ADDN HOSTS: %d =>  %p", dctx->addnhostsfile->nhosts, ipdef->dns);


Did you mean to leave this DEBUG in?


              if (dctx->addnhostsfile->nhosts)
                  virCommandAddArgPair(cmd, "--addn-hosts",
                                       dctx->addnhostsfile->path);
diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
new file mode 100644
index 0000000..99dc724
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
@@ -0,0 +1 @@
+/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.xml b/tests/networkxml2argvdata/nat-network-dns-hosts.xml
new file mode 100644
index 0000000..35ee151
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-hosts.xml
@@ -0,0 +1,19 @@
+<network>
+<name>default</name>
+<uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+<forward dev='eth1' mode='nat'/>
+<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' />
+<host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+<host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+</dhcp>
+<dns>
+<host ip='192.168.122.1'>
+<hostname>host</hostname>
+<hostname>gateway</hostname>
+</host>
+</dns>
+</ip>
+</network>
diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c
index e3a8bb4..ce09206 100644
--- a/tests/networkxml2argvtest.c
+++ b/tests/networkxml2argvtest.c
@@ -112,6 +112,7 @@ mymain(int argc, char **argv)
      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..fe545cf
--- /dev/null
+++ b/tests/networkxml2xmlin/nat-network-dns-hosts.xml
@@ -0,0 +1,27 @@
+<network>
+<name>default</name>
+<uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+<forward dev='eth1' mode='nat'/>
+<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' />
+<host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+<host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+</dhcp>
+<dns>
+<host ip='192.168.122.1'>
+<hostname>host</hostname>
+<hostname>gateway</hostname>
+</host>
+</dns>
+</ip>
+<ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+</ip>
+<ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+</ip>
+<ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+</ip>
+<ip family='ipv4' address='10.24.10.1'>
+</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..fe545cf
--- /dev/null
+++ b/tests/networkxml2xmlout/nat-network-dns-hosts.xml
@@ -0,0 +1,27 @@
+<network>
+<name>default</name>
+<uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+<forward dev='eth1' mode='nat'/>
+<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' />
+<host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+<host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+</dhcp>
+<dns>
+<host ip='192.168.122.1'>
+<hostname>host</hostname>
+<hostname>gateway</hostname>
+</host>
+</dns>
+</ip>
+<ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+</ip>
+<ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+</ip>
+<ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+</ip>
+<ip family='ipv4' address='10.24.10.1'>
+</ip>
+</network>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index beb00ef..f5c5715 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -91,6 +91,7 @@ mymain(int argc, char **argv)
      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);
  }

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


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]