]> git.ipfire.org Git - ipfire-2.x.git/commitdiff
unbound+DHCP: Read existing leases from unbound
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 14 Sep 2016 14:54:36 +0000 (15:54 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 14 Sep 2016 14:54:36 +0000 (15:54 +0100)
This allows us to restart unbound and all DHCP leases
will be re-imported even if the unbound-dhcp-leases-bridge is
not restarted.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
config/unbound/unbound-dhcp-leases-bridge

index 06bff2eda266beafbde3305c09937f70c4767b6f..a3e16616efd35fa92952693ab783b7fd99fe8993 100644 (file)
@@ -257,10 +257,10 @@ class Lease(object):
        def rrset(self):
                return [
                        # Forward record
-                       (self.fqdn, LOCAL_TTL, "IN A", self.ipaddr),
+                       (self.fqdn, "%s" % LOCAL_TTL, "IN A", self.ipaddr),
 
                        # Reverse record
-                       (self.ipaddr, LOCAL_TTL, "IN PTR", self.fqdn),
+                       (self.ipaddr, "%s" % LOCAL_TTL, "IN PTR", self.fqdn),
                ]
 
 
@@ -268,33 +268,63 @@ class UnboundConfigWriter(object):
        def __init__(self, path):
                self.path = path
 
-               self._cached_leases = []
+       @property
+       def existing_leases(self):
+               local_data = self._control("list_local_data")
+               ret = {}
+
+               for line in local_data.splitlines():
+                       try:
+                               hostname, ttl, x, record_type, content = line.split("\t")
+                       except ValueError:
+                               continue
+
+                       # Ignore everything that is not A or PTR
+                       if not record_type in ("A", "PTR"):
+                               continue
+
+                       if hostname.endswith("."):
+                               hostname = hostname[:-1]
+
+                       if content.endswith("."):
+                               content = content[:-1]
+
+                       if record_type == "A":
+                               ret[hostname] = content
+                       elif record_type == "PTR":
+                               ret[content] = hostname
+
+               return ret
 
        def update_dhcp_leases(self, leases):
                # Strip all non-active or expired leases
                leases = [l for l in leases if l.active and not l.expired]
 
                # Find any leases that have expired or do not exist any more 
-               removed_leases = [l for l in self._cached_leases if l.expired or l not in leases]
+               removed_leases = []
+               for fqdn, address in self.existing_leases.items():
+                       if not fqdn in (l.fqdn for l in leases):
+                               removed_leases += [fqdn, address]
 
                # Find any leases that have been added
-               new_leases = [l for l in leases if l not in self._cached_leases]
+               new_leases = [l for l in leases
+                       if l.fqdn not in self.existing_leases]
 
                # End here if nothing has changed
                if not new_leases and not removed_leases:
                        return
 
-               self._cached_leases = leases
-
                # Write out all leases
                self.write_dhcp_leases(leases)
 
                # Update unbound about changes
-               for l in removed_leases:
-                       self._control("local_data_remove", l.fqdn)
+               for hostname in removed_leases:
+                       log.debug("Removing all records for %s" % hostname)
+                       self._control("local_data_remove", hostname)
 
                for l in new_leases:
                        for rr in l.rrset:
+                               log.debug("Adding new record %s" % " ".join(rr))
                                self._control("local_data", *rr)
 
 
@@ -305,11 +335,11 @@ class UnboundConfigWriter(object):
                                        f.write("local-data: \"%s\"\n" % " ".join(rr))
 
        def _control(self, *args):
-               command = ["unbound-control", "-q"]
+               command = ["unbound-control"]
                command.extend(args)
 
                try:
-                       subprocess.check_call(command)
+                       return subprocess.check_output(command)
 
                # Log any errors
                except subprocess.CalledProcessError as e: