[libvirt] [PATCH] leasetime support for <dhcp>

aruiz at gnome.org aruiz at gnome.org
Fri Jun 23 00:44:47 UTC 2017


From: Alberto Ruiz <aruiz at gnome.org>

Fixes #913446

This patch addresses a few problems found by the initial reviews:

* leaseTimeUnit RNG type renamed to timeUnit
* virNetworkDHCPDefGetLeaseTime() renamed to virNetworkDHCPLeaseTimeParseXML()
* consistent use of braces in if-else-if
* use %lu instead of PRId64
* use 0 as infinite lease
* add a leasetime_defined field to struct _virNetworkIPDef to describe whether the value was set in the xml configuration or not
* use uint32_t for the leasetime instead of int64_t
* fail on all invalid leasetime values
* squash all patches into one

---
 docs/schemas/basictypes.rng                        |  16 +++
 docs/schemas/network.rng                           |   8 ++
 src/conf/network_conf.c                            |  93 +++++++++++++++-
 src/conf/network_conf.h                            |   5 +-
 src/libvirt_private.syms                           |   1 +
 src/network/bridge_driver.c                        | 119 ++++++++++++++++-----
 src/network/bridge_driver.h                        |   1 +
 src/util/virdnsmasq.c                              | 106 +++++++++++-------
 src/util/virdnsmasq.h                              |   2 +
 .../dhcp6-nat-network.hostsfile                    |   7 ++
 tests/networkxml2confdata/dhcp6-network.hostsfile  |   5 +
 .../dhcp6host-routed-network.hostsfile             |   7 ++
 tests/networkxml2confdata/leasetime-days.conf      |  18 ++++
 tests/networkxml2confdata/leasetime-days.xml       |  18 ++++
 tests/networkxml2confdata/leasetime-hours.conf     |  18 ++++
 tests/networkxml2confdata/leasetime-hours.xml      |  18 ++++
 tests/networkxml2confdata/leasetime-infinite.conf  |  18 ++++
 tests/networkxml2confdata/leasetime-infinite.xml   |  18 ++++
 tests/networkxml2confdata/leasetime-minutes.conf   |  18 ++++
 tests/networkxml2confdata/leasetime-minutes.xml    |  18 ++++
 tests/networkxml2confdata/leasetime-seconds.conf   |  18 ++++
 tests/networkxml2confdata/leasetime-seconds.xml    |  18 ++++
 tests/networkxml2confdata/leasetime.conf           |  18 ++++
 tests/networkxml2confdata/leasetime.xml            |  18 ++++
 .../nat-network-dns-srv-record-minimal.hostsfile   |   2 +
 .../nat-network-dns-srv-record.hostsfile           |   2 +
 .../nat-network-dns-txt-record.hostsfile           |   2 +
 .../nat-network-name-with-quotes.hostsfile         |   2 +
 tests/networkxml2confdata/nat-network.hostsfile    |   2 +
 .../networkxml2confdata/ptr-domains-auto.hostsfile |   2 +
 tests/networkxml2conftest.c                        |  45 ++++++--
 31 files changed, 571 insertions(+), 72 deletions(-)
 create mode 100644 tests/networkxml2confdata/dhcp6-nat-network.hostsfile
 create mode 100644 tests/networkxml2confdata/dhcp6-network.hostsfile
 create mode 100644 tests/networkxml2confdata/dhcp6host-routed-network.hostsfile
 create mode 100644 tests/networkxml2confdata/leasetime-days.conf
 create mode 100644 tests/networkxml2confdata/leasetime-days.xml
 create mode 100644 tests/networkxml2confdata/leasetime-hours.conf
 create mode 100644 tests/networkxml2confdata/leasetime-hours.xml
 create mode 100644 tests/networkxml2confdata/leasetime-infinite.conf
 create mode 100644 tests/networkxml2confdata/leasetime-infinite.xml
 create mode 100644 tests/networkxml2confdata/leasetime-minutes.conf
 create mode 100644 tests/networkxml2confdata/leasetime-minutes.xml
 create mode 100644 tests/networkxml2confdata/leasetime-seconds.conf
 create mode 100644 tests/networkxml2confdata/leasetime-seconds.xml
 create mode 100644 tests/networkxml2confdata/leasetime.conf
 create mode 100644 tests/networkxml2confdata/leasetime.xml
 create mode 100644 tests/networkxml2confdata/nat-network-dns-srv-record-minimal.hostsfile
 create mode 100644 tests/networkxml2confdata/nat-network-dns-srv-record.hostsfile
 create mode 100644 tests/networkxml2confdata/nat-network-dns-txt-record.hostsfile
 create mode 100644 tests/networkxml2confdata/nat-network-name-with-quotes.hostsfile
 create mode 100644 tests/networkxml2confdata/nat-network.hostsfile
 create mode 100644 tests/networkxml2confdata/ptr-domains-auto.hostsfile

diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 1ea667cdf..9db19c7f0 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -564,4 +564,20 @@
     </element>
   </define>
 
+  <define name="timeUnit">
+    <choice>
+      <value>seconds</value>
+      <value>minutes</value>
+      <value>hours</value>
+      <value>days</value>
+    </choice>
+  </define>
+
+  <define name="leaseTime">
+    <data type="long">
+      <param name="minInclusive">-1</param>
+      <param name="maxInclusive">4294967295</param>
+    </data>
+  </define>
+
 </grammar>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 1048dabf3..a0d878e4a 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -357,6 +357,14 @@
                 <!-- Define the range(s) of IP addresses that the DHCP
                      server should hand out -->
                 <element name="dhcp">
+                <optional>
+                  <element name="leasetime">
+                    <optional>
+                      <attribute name="unit"><ref name="timeUnit"/></attribute>
+                    </optional>
+                    <ref name="leaseTime"/>
+                  </element>
+                </optional>
                   <interleave>
                     <zeroOrMore>
                       <element name="range">
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 3ebf67ff5..8431ee806 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -29,6 +29,8 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
 
 #include "virerror.h"
 #include "datatypes.h"
@@ -514,8 +516,92 @@ virNetworkDHCPHostDefParseXML(const char *networkName,
 
 
 static int
+virNetworkDHCPLeaseTimeParseXML (xmlNodePtr node,
+                                 xmlXPathContextPtr ctxt,
+                                 uint32_t *lease,
+                                 bool     *defined)
+{
+    int ret = 0;
+    uint32_t multiplier;
+    char *leaseString, *leaseUnit;
+    xmlNodePtr save;
+
+    *defined = 0;
+
+    save = ctxt->node;
+    ctxt->node = node;
+
+    leaseString = virXPathString ("string(./leasetime/text())", ctxt);
+    leaseUnit   = virXPathString ("string(./leasetime/@unit)", ctxt);
+
+    /* If value is not present we set the value to -2 */
+    if (leaseString == NULL) {
+        goto cleanup;
+    }
+    if (leaseString[0] == '-') {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("<leasetime> value (%s) cannot be negative"),
+                       leaseString);
+    }
+
+    *defined = 1;
+
+    if (leaseUnit == NULL || strcmp (leaseUnit, "seconds") == 0) {
+        multiplier = 1;
+    }
+    else if (strcmp (leaseUnit, "minutes") == 0) {
+        multiplier = 60;
+    }
+    else if (strcmp (leaseUnit, "hours") == 0) {
+        multiplier = 60 * 60;
+    }
+    else if (strcmp (leaseUnit, "days") == 0) {
+        multiplier = 60 * 60 * 24;
+    }
+    else {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("invalid value for unit parameter in <leasetime> element"
+                         "found in <dhcp> network, only 'seconds', 'minutes', "
+                         "'hours' or 'days' are valid: %s"),
+                       leaseUnit);
+        ret = -1;
+        goto cleanup;
+    }
+
+    errno = 0;
+    *lease = (uint32_t) strtoul((const char*)leaseString, NULL, 10);
+
+    /* Report any errors parsing the string */
+    if (errno != 0) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("<leasetime> value could not be converted to a signed integer: %s"),
+                      leaseString);
+        ret = -1;
+        goto cleanup;
+    }
+
+    if (*lease > (UINT32_MAX / multiplier)) {
+      virReportError (VIR_ERR_XML_ERROR,
+                      _("<leasetime> value %lu %s exceeds the maximum of %lu seconds"),
+                      (unsigned long)*lease, leaseUnit, (unsigned long)UINT32_MAX);
+      ret = -1;
+      goto cleanup;
+    }
+
+    *lease = *lease * multiplier;
+
+cleanup:
+    VIR_FREE(leaseString);
+    VIR_FREE(leaseUnit);
+    ctxt->node = save;
+    return ret;
+}
+
+
+static int
 virNetworkDHCPDefParseXML(const char *networkName,
                           xmlNodePtr node,
+                          xmlXPathContextPtr ctxt,
                           virNetworkIPDefPtr def)
 {
     int ret = -1;
@@ -526,6 +612,11 @@ virNetworkDHCPDefParseXML(const char *networkName,
     memset(&range, 0, sizeof(range));
     memset(&host, 0, sizeof(host));
 
+    if (virNetworkDHCPLeaseTimeParseXML (node, ctxt,
+                                         &def->leasetime,
+                                         &def->leasetime_defined))
+        goto cleanup;
+
     cur = node->children;
     while (cur != NULL) {
         if (cur->type == XML_ELEMENT_NODE &&
@@ -1104,7 +1195,7 @@ virNetworkIPDefParseXML(const char *networkName,
     }
 
     if ((dhcp = virXPathNode("./dhcp[1]", ctxt)) &&
-        virNetworkDHCPDefParseXML(networkName, dhcp, def) < 0)
+        virNetworkDHCPDefParseXML(networkName, dhcp, ctxt, def) < 0)
         goto cleanup;
 
     if (virXPathNode("./tftp[1]", ctxt)) {
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index e9a5baf5b..466220e81 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -175,7 +175,10 @@ struct _virNetworkIPDef {
     char *tftproot;
     char *bootfile;
     virSocketAddr bootserver;
-   };
+
+    uint32_t leasetime;
+    bool leasetime_defined;
+};
 
 typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
 typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c1e9471c5..5ef33dcfe 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1561,6 +1561,7 @@ dnsmasqCapsRefresh;
 dnsmasqContextFree;
 dnsmasqContextNew;
 dnsmasqDelete;
+dnsmasqDhcpHostsToString;
 dnsmasqReload;
 dnsmasqSave;
 
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 3ba70180b..cdb0230ab 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -41,6 +41,8 @@
 #include <sys/ioctl.h>
 #include <net/if.h>
 #include <dirent.h>
+#include <inttypes.h>
+#include <stdint.h>
 #if HAVE_SYS_SYSCTL_H
 # include <sys/sysctl.h>
 #endif
@@ -948,6 +950,62 @@ networkKillDaemon(pid_t pid, const char *daemonName, const char *networkName)
     return ret;
 }
 
+static int
+networkBuildDnsmasqHostsList(dnsmasqContext *dctx,
+                             virNetworkDNSDefPtr dnsdef)
+{
+    size_t i, j;
+
+    if (dnsdef) {
+        for (i = 0; i < dnsdef->nhosts; i++) {
+            virNetworkDNSHostDefPtr host = &(dnsdef->hosts[i]);
+            if (VIR_SOCKET_ADDR_VALID(&host->ip)) {
+                for (j = 0; j < host->nnames; j++)
+                    if (dnsmasqAddHost(dctx, &host->ip, host->names[j]) < 0)
+                        return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/* translates the leasetime value into a dnsmasq configuration string
+ * for dhcp-range/host */
+static char *
+networkDnsmasqConfLeaseValueToString (int64_t leasetime, bool defined)
+{
+    char *result = NULL;
+    virBuffer leasebuf = VIR_BUFFER_INITIALIZER;
+
+    /* Leasetime parameter set on the XML */
+
+    /* defined = FALSE means we fallback to dnsmasq defaults*/
+    if (defined == 0) {
+        virBufferAsprintf(&leasebuf, "%s", "");
+    }
+    /* 0 means no expiration */
+    else if (leasetime == 0) {
+        virBufferAsprintf(&leasebuf, ",infinite");
+    }
+    /* DHCP value for lease time is a unsigned four octect integer */
+    else if (leasetime <= UINT32_MAX) {
+        virBufferAsprintf(&leasebuf, ",%lu", (unsigned long)leasetime);
+    }
+    else {
+        if (leasetime < 120)
+          virReportError (VIR_ERR_CONFIG_UNSUPPORTED,
+                          _("lease time must be greater than 120 seconds"));
+        goto cleanup;
+    }
+
+    result = virBufferContentAndReset(&leasebuf);
+
+cleanup:
+    virBufferFreeAndReset (&leasebuf);
+    return result;
+}
+
 /* the following does not build a file, it builds a list
  * which is later saved into a file
  */
@@ -956,8 +1014,14 @@ static int
 networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
                                  virNetworkIPDefPtr ipdef)
 {
+    int ret = -1;
     size_t i;
     bool ipv6 = false;
+    char *leasetime = networkDnsmasqConfLeaseValueToString(ipdef->leasetime,
+                                                           ipdef->leasetime_defined);
+
+    if (!leasetime)
+        goto cleanup;
 
     if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
         ipv6 = true;
@@ -965,31 +1029,14 @@ networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
         virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
         if (VIR_SOCKET_ADDR_VALID(&host->ip))
             if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip,
-                                   host->name, host->id, ipv6) < 0)
-                return -1;
-    }
-
-    return 0;
-}
-
-static int
-networkBuildDnsmasqHostsList(dnsmasqContext *dctx,
-                             virNetworkDNSDefPtr dnsdef)
-{
-    size_t i, j;
-
-    if (dnsdef) {
-        for (i = 0; i < dnsdef->nhosts; i++) {
-            virNetworkDNSHostDefPtr host = &(dnsdef->hosts[i]);
-            if (VIR_SOCKET_ADDR_VALID(&host->ip)) {
-                for (j = 0; j < host->nnames; j++)
-                    if (dnsmasqAddHost(dctx, &host->ip, host->names[j]) < 0)
-                        return -1;
-            }
-        }
+                                   host->name, host->id, leasetime, ipv6) < 0)
+                goto cleanup;
     }
 
-    return 0;
+    ret = 0;
+cleanup:
+    VIR_FREE(leasetime);
+    return ret;
 }
 
 
@@ -1034,6 +1081,7 @@ int
 networkDnsmasqConfContents(virNetworkObjPtr network,
                            const char *pidfile,
                            char **configstr,
+                           char **hostsfilestr,
                            dnsmasqContext *dctx,
                            dnsmasqCapsPtr caps ATTRIBUTE_UNUSED)
 {
@@ -1362,6 +1410,7 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
         }
         for (r = 0; r < ipdef->nranges; r++) {
             int thisRange;
+            char *leasestr;
 
             if (!(saddr = virSocketAddrFormat(&ipdef->ranges[r].start)) ||
                 !(eaddr = virSocketAddrFormat(&ipdef->ranges[r].end)))
@@ -1369,12 +1418,23 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
 
             virBufferAsprintf(&configbuf, "dhcp-range=%s,%s",
                               saddr, eaddr);
-            if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
+
+            /* Add ipv6 prefix length parameter if needed */
+            if (ipdef == ipv6def)
                 virBufferAsprintf(&configbuf, ",%d", prefix);
+
+            leasestr = networkDnsmasqConfLeaseValueToString (ipdef->leasetime,
+                                                             ipdef->leasetime_defined);
+            if (!leasestr)
+                goto cleanup;
+            virBufferAsprintf(&configbuf, "%s", leasestr);
+
+            /* Add the newline */
             virBufferAddLit(&configbuf, "\n");
 
             VIR_FREE(saddr);
             VIR_FREE(eaddr);
+            VIR_FREE(leasestr);
             thisRange = virSocketAddrGetRange(&ipdef->ranges[r].start,
                                               &ipdef->ranges[r].end,
                                               &ipdef->address,
@@ -1405,6 +1465,15 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
         if (networkBuildDnsmasqDhcpHostsList(dctx, ipdef) < 0)
             goto cleanup;
 
+        /* Return the contents of the hostsfile if requested */
+        if (hostsfilestr) {
+            *hostsfilestr = dnsmasqDhcpHostsToString (dctx->hostsfile->hosts,
+                                                      dctx->hostsfile->nhosts);
+
+            if (!hostsfilestr)
+                goto cleanup;
+        }
+
         /* Note: the following is IPv4 only */
         if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) {
             if (ipdef->nranges || ipdef->nhosts) {
@@ -1506,7 +1575,7 @@ networkBuildDhcpDaemonCommandLine(virNetworkDriverStatePtr driver,
 
     network->dnsmasqPid = -1;
 
-    if (networkDnsmasqConfContents(network, pidfile, &configstr,
+    if (networkDnsmasqConfContents(network, pidfile, &configstr, NULL,
                                    dctx, dnsmasq_caps) < 0)
         goto cleanup;
     if (!configstr)
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index 7832b6031..56329eb59 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -53,6 +53,7 @@ int networkGetActualType(virDomainNetDefPtr iface)
 int networkDnsmasqConfContents(virNetworkObjPtr network,
                         const char *pidfile,
                         char **configstr,
+                        char **hostsfilestr,
                         dnsmasqContext *dctx,
                         dnsmasqCapsPtr caps);
 
diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c
index 1b78c1fad..94c9a3bb1 100644
--- a/src/util/virdnsmasq.c
+++ b/src/util/virdnsmasq.c
@@ -308,52 +308,47 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile,
              virSocketAddr *ip,
              const char *name,
              const char *id,
+             const char *leasetime,
              bool ipv6)
 {
+    int ret = -1;
     char *ipstr = NULL;
+    virBuffer hostbuf = VIR_BUFFER_INITIALIZER;
+
     if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0)
         goto error;
 
     if (!(ipstr = virSocketAddrFormat(ip)))
-        return -1;
+        goto error;
 
     /* the first test determines if it is a dhcpv6 host */
     if (ipv6) {
-        if (name && id) {
-            if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host,
-                            "id:%s,%s,[%s]", id, name, ipstr) < 0)
-                goto error;
-        } else if (name && !id) {
-            if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host,
-                            "%s,[%s]", name, ipstr) < 0)
-                goto error;
-        } else if (!name && id) {
-            if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host,
-                            "id:%s,[%s]", id, ipstr) < 0)
-                goto error;
-        }
+        if (name && id)
+            virBufferAsprintf(&hostbuf, "id:%s,%s,[%s]", id, name, ipstr);
+        else if (name && !id)
+            virBufferAsprintf(&hostbuf, "%s,[%s]", name, ipstr);
+        else if (!name && id)
+            virBufferAsprintf(&hostbuf, "id:%s,[%s]", id, ipstr);
     } else if (name && mac) {
-        if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s,%s",
-                        mac, ipstr, name) < 0)
-            goto error;
+        virBufferAsprintf(&hostbuf, "%s,%s,%s", mac, ipstr, name);
     } else if (name && !mac) {
-        if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s",
-                        name, ipstr) < 0)
-            goto error;
+        virBufferAsprintf(&hostbuf, "%s,%s", name, ipstr);
     } else {
-        if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s",
-                        mac, ipstr) < 0)
-            goto error;
+        virBufferAsprintf(&hostbuf, "%s,%s", mac, ipstr);
     }
-    VIR_FREE(ipstr);
 
-    hostsfile->nhosts++;
+    /* The leasetime string already includes comma if there's any value at all */
+    virBufferAsprintf(&hostbuf, "%s", leasetime);
 
-    return 0;
+    if (!(hostsfile->hosts[hostsfile->nhosts].host = virBufferContentAndReset (&hostbuf)))
+      goto error;
 
+    hostsfile->nhosts++;
+    ret = 0;
  error:
+    virBufferFreeAndReset(&hostbuf);
     VIR_FREE(ipstr);
-    return -1;
+    return ret;
 }
 
 static dnsmasqHostsfile *
@@ -391,10 +386,9 @@ hostsfileWrite(const char *path,
                dnsmasqDhcpHost *hosts,
                unsigned int nhosts)
 {
-    char *tmp;
+    char *tmp, *content = NULL;
     FILE *f;
     bool istmp = true;
-    size_t i;
     int rc = 0;
 
     /* even if there are 0 hosts, create a 0 length file, to allow
@@ -412,17 +406,21 @@ hostsfileWrite(const char *path,
         }
     }
 
-    for (i = 0; i < nhosts; i++) {
-        if (fputs(hosts[i].host, f) == EOF || fputc('\n', f) == EOF) {
-            rc = -errno;
-            VIR_FORCE_FCLOSE(f);
+    if (!(content = dnsmasqDhcpHostsToString(hosts, nhosts))) {
+        rc = -ENOMEM;
+        goto cleanup;
+    }
 
-            if (istmp)
-                unlink(tmp);
+    if (fputs(content, f) == EOF) {
+        rc = -errno;
+        VIR_FORCE_FCLOSE(f);
+
+        if (istmp)
+            unlink(tmp);
+
+        goto cleanup;
+     }
 
-            goto cleanup;
-        }
-    }
 
     if (VIR_FCLOSE(f) == EOF) {
         rc = -errno;
@@ -436,6 +434,7 @@ hostsfileWrite(const char *path,
     }
 
  cleanup:
+    VIR_FREE(content);
     VIR_FREE(tmp);
 
     return rc;
@@ -524,9 +523,10 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
                    virSocketAddr *ip,
                    const char *name,
                    const char *id,
+                   const char *leasetime,
                    bool ipv6)
 {
-    return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, ipv6);
+    return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, leasetime, ipv6);
 }
 
 /*
@@ -892,3 +892,31 @@ dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag)
 
     return caps && virBitmapIsBitSet(caps->flags, flag);
 }
+
+/** dnsmasqDhcpHostsToString:
+ *
+ *   Turns a vector of dnsmasqDhcpHost into the string that is ought to be
+ *   stored in the hostsfile, this functionality is split to make hostsfiles
+ *   testable. Returs NULL if nhosts is 0.
+ */
+char *
+dnsmasqDhcpHostsToString (dnsmasqDhcpHost *hosts,
+                          unsigned int nhosts)
+{
+    int i;
+    char *result = NULL;
+    virBuffer hostsfilebuf = VIR_BUFFER_INITIALIZER;
+
+    if (nhosts == 0)
+       goto cleanup;
+
+    for (i = 0; i < nhosts; i++) {
+        virBufferAsprintf(&hostsfilebuf, "%s\n", hosts[i].host);
+    }
+
+    result = virBufferContentAndReset(&hostsfilebuf);
+
+cleanup:
+    virBufferFreeAndReset(&hostsfilebuf);
+    return result;
+}
diff --git a/src/util/virdnsmasq.h b/src/util/virdnsmasq.h
index f47bea3ab..1795bc83b 100644
--- a/src/util/virdnsmasq.h
+++ b/src/util/virdnsmasq.h
@@ -88,6 +88,7 @@ int              dnsmasqAddDhcpHost(dnsmasqContext *ctx,
                                     virSocketAddr *ip,
                                     const char *name,
                                     const char *id,
+                                    const char *leastime,
                                     bool ipv6);
 int              dnsmasqAddHost(dnsmasqContext *ctx,
                                 virSocketAddr *ip,
@@ -105,6 +106,7 @@ int dnsmasqCapsRefresh(dnsmasqCapsPtr *caps, const char *binaryPath);
 bool dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag);
 const char *dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps);
 unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps);
+char *dnsmasqDhcpHostsToString(dnsmasqDhcpHost *hosts, unsigned int nhosts);
 
 # define DNSMASQ_DHCPv6_MAJOR_REQD 2
 # define DNSMASQ_DHCPv6_MINOR_REQD 64
diff --git a/tests/networkxml2confdata/dhcp6-nat-network.hostsfile b/tests/networkxml2confdata/dhcp6-nat-network.hostsfile
new file mode 100644
index 000000000..de659b98c
--- /dev/null
+++ b/tests/networkxml2confdata/dhcp6-nat-network.hostsfile
@@ -0,0 +1,7 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
+id:0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63,[2001:db8:ac10:fd01::1:20]
+paul,[2001:db8:ac10:fd01::1:21]
+id:0:3:0:1:0:16:3e:11:22:33,peter.xyz,[2001:db8:ac10:fd01::1:22]
+id:0:3:0:1:0:16:3e:44:55:33,[2001:db8:ac10:fd01::1:23]
+id:0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66,badbob,[2001:db8:ac10:fd01::1:24]
diff --git a/tests/networkxml2confdata/dhcp6-network.hostsfile b/tests/networkxml2confdata/dhcp6-network.hostsfile
new file mode 100644
index 000000000..9dfb172ce
--- /dev/null
+++ b/tests/networkxml2confdata/dhcp6-network.hostsfile
@@ -0,0 +1,5 @@
+id:0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63,[2001:db8:ac10:fd01::1:20]
+paul,[2001:db8:ac10:fd01::1:21]
+id:0:3:0:1:0:16:3e:11:22:33,peter.xyz,[2001:db8:ac10:fd01::1:22]
+id:0:3:0:1:0:16:3e:44:55:33,[2001:db8:ac10:fd01::1:23]
+id:0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66,badbob,[2001:db8:ac10:fd01::1:24]
diff --git a/tests/networkxml2confdata/dhcp6host-routed-network.hostsfile b/tests/networkxml2confdata/dhcp6host-routed-network.hostsfile
new file mode 100644
index 000000000..de659b98c
--- /dev/null
+++ b/tests/networkxml2confdata/dhcp6host-routed-network.hostsfile
@@ -0,0 +1,7 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
+id:0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63,[2001:db8:ac10:fd01::1:20]
+paul,[2001:db8:ac10:fd01::1:21]
+id:0:3:0:1:0:16:3e:11:22:33,peter.xyz,[2001:db8:ac10:fd01::1:22]
+id:0:3:0:1:0:16:3e:44:55:33,[2001:db8:ac10:fd01::1:23]
+id:0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66,badbob,[2001:db8:ac10:fd01::1:24]
diff --git a/tests/networkxml2confdata/leasetime-days.conf b/tests/networkxml2confdata/leasetime-days.conf
new file mode 100644
index 000000000..d227be67a
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-days.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,86400
+dhcp-no-override
+dhcp-authoritative
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,86400
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-days.xml b/tests/networkxml2confdata/leasetime-days.xml
new file mode 100644
index 000000000..b990b4d68
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-days.xml
@@ -0,0 +1,18 @@
+<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>
+      <leasetime unit="days">1</leasetime>
+      <range start='192.168.122.2' end='192.168.122.254'/>
+    </dhcp>
+  </ip>
+  <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+    <dhcp>
+      <leasetime unit="days">1</leasetime>
+      <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff'/>
+    </dhcp>
+  </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-hours.conf b/tests/networkxml2confdata/leasetime-hours.conf
new file mode 100644
index 000000000..e5e8c19cd
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-hours.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,3600
+dhcp-no-override
+dhcp-authoritative
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,3600
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-hours.xml b/tests/networkxml2confdata/leasetime-hours.xml
new file mode 100644
index 000000000..3b9609601
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-hours.xml
@@ -0,0 +1,18 @@
+<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>
+      <leasetime unit="hours">1</leasetime>
+      <range start='192.168.122.2' end='192.168.122.254'/>
+    </dhcp>
+  </ip>
+  <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+    <dhcp>
+      <leasetime unit="hours">1</leasetime>
+      <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff'/>
+    </dhcp>
+  </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-infinite.conf b/tests/networkxml2confdata/leasetime-infinite.conf
new file mode 100644
index 000000000..52f4798e5
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-infinite.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,infinite
+dhcp-no-override
+dhcp-authoritative
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,infinite
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-infinite.xml b/tests/networkxml2confdata/leasetime-infinite.xml
new file mode 100644
index 000000000..d855978a1
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-infinite.xml
@@ -0,0 +1,18 @@
+<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>
+      <leasetime>0</leasetime>
+      <range start='192.168.122.2' end='192.168.122.254'/>
+    </dhcp>
+  </ip>
+  <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+    <dhcp>
+      <leasetime>0</leasetime>
+      <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff'/>
+    </dhcp>
+  </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-minutes.conf b/tests/networkxml2confdata/leasetime-minutes.conf
new file mode 100644
index 000000000..37da5702f
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-minutes.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,300
+dhcp-no-override
+dhcp-authoritative
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,300
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-minutes.xml b/tests/networkxml2confdata/leasetime-minutes.xml
new file mode 100644
index 000000000..e7a27afe6
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-minutes.xml
@@ -0,0 +1,18 @@
+<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>
+      <leasetime unit="minutes">5</leasetime>
+      <range start='192.168.122.2' end='192.168.122.254'/>
+    </dhcp>
+  </ip>
+  <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+    <dhcp>
+      <leasetime unit="minutes">5</leasetime>
+      <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff'/>
+    </dhcp>
+  </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-seconds.conf b/tests/networkxml2confdata/leasetime-seconds.conf
new file mode 100644
index 000000000..ea0845e21
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-seconds.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,125
+dhcp-no-override
+dhcp-authoritative
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,125
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-seconds.xml b/tests/networkxml2confdata/leasetime-seconds.xml
new file mode 100644
index 000000000..56b07f8ae
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-seconds.xml
@@ -0,0 +1,18 @@
+<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>
+      <leasetime unit="seconds">125</leasetime>
+      <range start='192.168.122.2' end='192.168.122.254'/>
+    </dhcp>
+  </ip>
+  <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+    <dhcp>
+      <leasetime unit="seconds">125</leasetime>
+      <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff'/>
+    </dhcp>
+  </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime.conf b/tests/networkxml2confdata/leasetime.conf
new file mode 100644
index 000000000..b754c3ffb
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime.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,122
+dhcp-no-override
+dhcp-authoritative
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,121
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime.xml b/tests/networkxml2confdata/leasetime.xml
new file mode 100644
index 000000000..fdbb15fc0
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime.xml
@@ -0,0 +1,18 @@
+<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>
+      <leasetime>122</leasetime>
+      <range start='192.168.122.2' end='192.168.122.254'/>
+    </dhcp>
+  </ip>
+  <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+    <dhcp>
+      <leasetime>121</leasetime>
+      <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff'/>
+    </dhcp>
+  </ip>
+</network>
diff --git a/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.hostsfile b/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.hostsfile
new file mode 100644
index 000000000..deb3f00ac
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network-dns-srv-record.hostsfile b/tests/networkxml2confdata/nat-network-dns-srv-record.hostsfile
new file mode 100644
index 000000000..deb3f00ac
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-srv-record.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network-dns-txt-record.hostsfile b/tests/networkxml2confdata/nat-network-dns-txt-record.hostsfile
new file mode 100644
index 000000000..deb3f00ac
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-txt-record.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network-name-with-quotes.hostsfile b/tests/networkxml2confdata/nat-network-name-with-quotes.hostsfile
new file mode 100644
index 000000000..deb3f00ac
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-name-with-quotes.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network.hostsfile b/tests/networkxml2confdata/nat-network.hostsfile
new file mode 100644
index 000000000..deb3f00ac
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/ptr-domains-auto.hostsfile b/tests/networkxml2confdata/ptr-domains-auto.hostsfile
new file mode 100644
index 000000000..deb3f00ac
--- /dev/null
+++ b/tests/networkxml2confdata/ptr-domains-auto.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2conftest.c b/tests/networkxml2conftest.c
index ab3c13aa0..15f783fb1 100644
--- a/tests/networkxml2conftest.c
+++ b/tests/networkxml2conftest.c
@@ -19,9 +19,13 @@
 #define VIR_FROM_THIS VIR_FROM_NONE
 
 static int
-testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr caps)
+testCompareXMLToConfFiles(const char *inxml,
+                          const char *outconf,
+                          const char *outhostsfile,
+                          dnsmasqCapsPtr caps)
 {
-    char *actual = NULL;
+    char *actualconf = NULL;
+    char *actualhosts = NULL;
     int ret = -1;
     virNetworkDefPtr dev = NULL;
     virNetworkObjPtr obj = NULL;
@@ -41,7 +45,11 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr
     if (dctx == NULL)
         goto fail;
 
-    if (networkDnsmasqConfContents(obj, pidfile, &actual, dctx, caps) < 0)
+    if (networkDnsmasqConfContents(obj, pidfile, &actualconf, &actualhosts,
+                        dctx, caps) < 0)
+        goto fail;
+
+    if (virTestCompareToFile(actualconf, outconf) < 0)
         goto fail;
 
     /* Any changes to this function ^^ should be reflected here too. */
@@ -57,13 +65,27 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr
     tmp = NULL;
 #endif
 
-    if (virTestCompareToFile(actual, outconf) < 0)
+    if (virFileExists(outhostsfile)) {
+        if (!actualhosts) {
+            fprintf(stderr,
+                    "%s: hostsfile exists but the configuration did not specify any host",
+                    outhostsfile);
+            goto fail;
+        } else if (virTestCompareToFile(actualhosts, outhostsfile) < 0) {
+            goto fail;
+        }
+    } else if (actualhosts) {
+        fprintf(stderr,
+                "%s: file does not exist but actual data was expected",
+                outhostsfile);
         goto fail;
+    }
 
     ret = 0;
 
  fail:
-    VIR_FREE(actual);
+    VIR_FREE(actualconf);
+    VIR_FREE(actualhosts);
     VIR_FREE(pidfile);
     virCommandFree(cmd);
     virObjectUnref(obj);
@@ -83,19 +105,23 @@ testCompareXMLToConfHelper(const void *data)
     const testInfo *info = data;
     char *inxml = NULL;
     char *outconf = NULL;
+    char *outhostsfile = NULL;
 
     if (virAsprintf(&inxml, "%s/networkxml2confdata/%s.xml",
                     abs_srcdir, info->name) < 0 ||
         virAsprintf(&outconf, "%s/networkxml2confdata/%s.conf",
+                    abs_srcdir, info->name) < 0 ||
+        virAsprintf(&outhostsfile, "%s/networkxml2confdata/%s.hostsfile",
                     abs_srcdir, info->name) < 0) {
         goto cleanup;
     }
 
-    result = testCompareXMLToConfFiles(inxml, outconf, info->caps);
+    result = testCompareXMLToConfFiles(inxml, outconf, outhostsfile, info->caps);
 
  cleanup:
     VIR_FREE(inxml);
     VIR_FREE(outconf);
+    VIR_FREE(outhostsfile);
 
     return result;
 }
@@ -143,6 +169,13 @@ mymain(void)
     DO_TEST("dhcp6-nat-network", dhcpv6);
     DO_TEST("dhcp6host-routed-network", dhcpv6);
     DO_TEST("ptr-domains-auto", dhcpv6);
+    DO_TEST("leasetime", dhcpv6);
+    DO_TEST("leasetime-seconds", dhcpv6);
+    DO_TEST("leasetime-hours", dhcpv6);
+    DO_TEST("leasetime-minutes", dhcpv6);
+    DO_TEST("leasetime-hours", dhcpv6);
+    DO_TEST("leasetime-days", dhcpv6);
+    DO_TEST("leasetime-infinite", dhcpv6);
 
     virObjectUnref(dhcpv6);
     virObjectUnref(full);
-- 
2.13.0




More information about the libvir-list mailing list