[libvirt] [PATCH] leasetime support for

2017-06-22 Thread aruiz
From: Alberto Ruiz 

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 @@
 
   
 
+  
+
+  seconds
+  minutes
+  hours
+  days
+
+  
+
+  
+
+  -1
+  4294967295
+
+  
+
 
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 @@
 
 
+
+  
+
+  
+
+
+  
+
   
 
   
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 3ebf67ff5..8431ee806 

[libvirt] [PATCH 3/3] add reference tests for hostsfiles

2017-06-20 Thread aruiz
From: Alberto Ruiz 

---
 src/libvirt_private.syms   |  1 +
 src/network/bridge_driver.c| 12 -
 src/network/bridge_driver.h|  1 +
 src/util/virdnsmasq.c  | 54 +-
 src/util/virdnsmasq.h  |  1 +
 .../dhcp6-nat-network.hostsfile|  7 +++
 tests/networkxml2confdata/dhcp6-network.hostsfile  |  5 ++
 .../dhcp6host-routed-network.hostsfile |  7 +++
 .../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 +
 tests/networkxml2conftest.c| 39 
 14 files changed, 116 insertions(+), 21 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/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

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 923afd187..c93385958 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1497,6 +1497,7 @@ dnsmasqCapsRefresh;
 dnsmasqContextFree;
 dnsmasqContextNew;
 dnsmasqDelete;
+dnsmasqDhcpHostsToString;
 dnsmasqReload;
 dnsmasqSave;
 
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 1cffd4dcf..1d2ada208 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -952,6 +952,7 @@ int
 networkDnsmasqConfContents(virNetworkObjPtr network,
const char *pidfile,
char **configstr,
+   char **hostsfilestr,
dnsmasqContext *dctx,
dnsmasqCapsPtr caps ATTRIBUTE_UNUSED)
 {
@@ -1311,6 +1312,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(>address, AF_INET)) {
 if (ipdef->nranges || ipdef->nhosts)
@@ -1410,7 +1420,7 @@ 
networkBuildDhcpDaemonCommandLine(virNetworkDriverStatePtr driver,
 
 network->dnsmasqPid = -1;
 
-if (networkDnsmasqConfContents(network, pidfile, ,
+if (networkDnsmasqConfContents(network, pidfile, , NULL,
dctx, dnsmasq_caps) < 0)
 goto cleanup;
 if (!configstr)
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index ff7f921ed..c653c507f 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 92f834fe7..94c9a3bb1 100644
--- a/src/util/virdnsmasq.c
+++ b/src/util/virdnsmasq.c
@@ -386,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
@@ -407,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)
+

[libvirt] [PATCH 2/3] lease time support per host in dnsmasq

2017-06-20 Thread aruiz
From: Alberto Ruiz 

---
 src/network/bridge_driver.c | 56 ++---
 src/util/virdnsmasq.c   | 52 +++--
 src/util/virdnsmasq.h   |  1 +
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index e51e469c8..1cffd4dcf 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -861,30 +861,6 @@ networkKillDaemon(pid_t pid, const char *daemonName, const 
char *networkName)
 return ret;
 }
 
-/* the following does not build a file, it builds a list
- * which is later saved into a file
- */
-
-static int
-networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
- virNetworkIPDefPtr ipdef)
-{
-size_t i;
-bool ipv6 = false;
-
-if (VIR_SOCKET_ADDR_IS_FAMILY(>address, AF_INET6))
-ipv6 = true;
-for (i = 0; i < ipdef->nhosts; i++) {
-virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
-if (VIR_SOCKET_ADDR_VALID(>ip))
-if (dnsmasqAddDhcpHost(dctx, host->mac, >ip,
-   host->name, host->id, ipv6) < 0)
-return -1;
-}
-
-return 0;
-}
-
 static int
 networkBuildDnsmasqHostsList(dnsmasqContext *dctx,
  virNetworkDNSDefPtr dnsdef)
@@ -940,6 +916,38 @@ networkDnsmasqConfLeaseValueToString (int64_t leasetime)
 return result;
 }
 
+/* the following does not build a file, it builds a list
+ * which is later saved into a file
+ */
+
+static int
+networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
+ virNetworkIPDefPtr ipdef)
+{
+int ret = -1;
+size_t i;
+bool ipv6 = false;
+char *leasetime = networkDnsmasqConfLeaseValueToString(ipdef->leasetime);
+
+if (!leasetime)
+goto cleanup;
+
+if (VIR_SOCKET_ADDR_IS_FAMILY(>address, AF_INET6))
+ipv6 = true;
+for (i = 0; i < ipdef->nhosts; i++) {
+virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
+if (VIR_SOCKET_ADDR_VALID(>ip))
+if (dnsmasqAddDhcpHost(dctx, host->mac, >ip,
+   host->name, host->id, leasetime, ipv6) < 0)
+goto cleanup;
+}
+
+ret = 0;
+cleanup:
+VIR_FREE(leasetime);
+return ret;
+}
+
 int
 networkDnsmasqConfContents(virNetworkObjPtr network,
const char *pidfile,
diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c
index 1b78c1fad..92f834fe7 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(>hosts[hostsfile->nhosts].host,
-"id:%s,%s,[%s]", id, name, ipstr) < 0)
-goto error;
-} else if (name && !id) {
-if (virAsprintf(>hosts[hostsfile->nhosts].host,
-"%s,[%s]", name, ipstr) < 0)
-goto error;
-} else if (!name && id) {
-if (virAsprintf(>hosts[hostsfile->nhosts].host,
-"id:%s,[%s]", id, ipstr) < 0)
-goto error;
-}
+if (name && id)
+virBufferAsprintf(, "id:%s,%s,[%s]", id, name, ipstr);
+else if (name && !id)
+virBufferAsprintf(, "%s,[%s]", name, ipstr);
+else if (!name && id)
+virBufferAsprintf(, "id:%s,[%s]", id, ipstr);
 } else if (name && mac) {
-if (virAsprintf(>hosts[hostsfile->nhosts].host, "%s,%s,%s",
-mac, ipstr, name) < 0)
-goto error;
+virBufferAsprintf(, "%s,%s,%s", mac, ipstr, name);
 } else if (name && !mac) {
-if (virAsprintf(>hosts[hostsfile->nhosts].host, "%s,%s",
-name, ipstr) < 0)
-goto error;
+virBufferAsprintf(, "%s,%s", name, ipstr);
 } else {
-if (virAsprintf(>hosts[hostsfile->nhosts].host, "%s,%s",
-mac, ipstr) < 0)
-goto error;
+virBufferAsprintf(, "%s,%s", mac, ipstr);
 }
-VIR_FREE(ipstr);
 
-hostsfile->nhosts++;
+/* The leasetime string already includes comma if there's any value at all 
*/
+virBufferAsprintf(, "%s", leasetime);
 
-return 0;
+if (!(hostsfile->hosts[hostsfile->nhosts].host = virBufferContentAndReset 
()))
+  goto 

[libvirt] [PATCH 1/3] leasetime support for globally

2017-06-20 Thread aruiz
From: Alberto Ruiz 

---
 docs/schemas/basictypes.rng   | 16 +
 docs/schemas/network.rng  |  8 +++
 src/conf/network_conf.c   | 78 ++-
 src/conf/network_conf.h   |  3 +-
 src/network/bridge_driver.c   | 49 +-
 tests/networkxml2confdata/leasetime-days.conf | 17 +
 tests/networkxml2confdata/leasetime-days.xml  | 18 ++
 tests/networkxml2confdata/leasetime-hours.conf| 17 +
 tests/networkxml2confdata/leasetime-hours.xml | 18 ++
 tests/networkxml2confdata/leasetime-infinite.conf | 17 +
 tests/networkxml2confdata/leasetime-infinite.xml  | 18 ++
 tests/networkxml2confdata/leasetime-minutes.conf  | 17 +
 tests/networkxml2confdata/leasetime-minutes.xml   | 18 ++
 tests/networkxml2confdata/leasetime-seconds.conf  | 17 +
 tests/networkxml2confdata/leasetime-seconds.xml   | 18 ++
 tests/networkxml2confdata/leasetime.conf  | 17 +
 tests/networkxml2confdata/leasetime.xml   | 18 ++
 tests/networkxml2conftest.c   |  7 ++
 18 files changed, 368 insertions(+), 3 deletions(-)
 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

diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 1b4f980e7..8a76c235a 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -518,4 +518,20 @@
 
   
 
+  
+
+  seconds
+  minutes
+  hours
+  days
+
+  
+
+  
+
+  -1
+  4294967295
+
+  
+
 
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 1a18e64b2..4b8056ab6 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -340,6 +340,14 @@
   
   
+
+  
+
+  
+
+
+  
+
 
   
 
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index aa397768c..6f051493f 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -30,6 +30,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "virerror.h"
 #include "datatypes.h"
@@ -1031,12 +1033,82 @@ virNetworkDHCPHostDefParseXML(const char *networkName,
 return ret;
 }
 
+static int64_t
+virNetworkDHCPDefGetLeaseTime (xmlNodePtr node,
+   xmlXPathContextPtr ctxt,
+   bool *error)
+{
+int64_t multiplier, result = -1;
+char *leaseString, *leaseUnit;
+xmlNodePtr save;
+
+*error = 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) {
+result = -2;
+goto cleanup;
+}
+
+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  
element found in  network, "
+ "only 'seconds', 'minutes', 'hours' or 'days' are 
valid: %s"),
+   leaseUnit);
+*error = 1;
+goto cleanup;
+}
+
+errno = 0;
+result = (int64_t) strtoll((const char*)leaseString, NULL, 10);
+
+/* Report any errors parsing the string */
+if (errno != 0) {
+virReportError(VIR_ERR_XML_ERROR,
+   _(" value could not be converted to a signed 
integer: %s"),
+  leaseString);
+*error = 1;
+goto cleanup;
+}
+
+result = result * multiplier;
+
+if (result > UINT32_MAX) {
+virReportError(VIR_ERR_XML_ERROR,
+   _(" value