]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - config/unbound/unbound-dhcp-leases-bridge
unbound-dhcp-bridge: Only update cache when lease was added/removed
[people/pmueller/ipfire-2.x.git] / config / unbound / unbound-dhcp-leases-bridge
index 70da1e03180e7650e95b5621a2e04bc4333b590f..4804dba2a1b0332ef50459f114832e5b92eeb40c 100644 (file)
@@ -123,6 +123,23 @@ class UnboundDHCPLeasesBridge(object):
                for lease in FixLeases(self.fix_leases_file):
                        leases.append(lease)
 
+               # Skip any leases that also are a static host
+               leases = [l for l in leases if not l.fqdn in self.hosts]
+
+               # Remove any inactive or expired leases
+               leases = [l for l in leases if l.active and not l.expired]
+
+               # Dump leases
+               if leases:
+                       log.debug("DHCP Leases:")
+                       for lease in leases:
+                               log.debug("  %s:" % lease.fqdn)
+                               log.debug("    State: %s" % lease.binding_state)
+                               log.debug("    Start: %s" % lease.time_starts)
+                               log.debug("    End  : %s" % lease.time_ends)
+                               if lease.expired:
+                                       log.debug("    Expired")
+
                self.unbound.update_dhcp_leases(leases)
 
        def read_static_hosts(self):
@@ -455,51 +472,15 @@ class UnboundConfigWriter(object):
        def __init__(self, path):
                self.path = path
 
-       @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] = reverse_pointer_to_ip_address(hostname)
-
-               return ret
+               self._cached_leases = []
 
        def update_dhcp_leases(self, leases):
-               # Cache all expired or inactive leases
-               expired_leases = [l for l in leases if l.expired or not l.active]
-
                # Find any leases that have expired or do not exist any more
                # but are still in the unbound local data
-               removed_leases = []
-               for fqdn, address in self.existing_leases.items():
-                       if fqdn in (l.fqdn for l in expired_leases):
-                               removed_leases += [fqdn, address]
-
-               # Strip all non-active or expired leases
-               leases = [l for l in leases if l.active and not l.expired]
+               removed_leases = [l for l in self._cached_leases if not l in leases]
 
                # Find any leases that have been added
-               new_leases = [l for l in leases
-                       if l.fqdn not in self.existing_leases]
+               new_leases = [l for l in leases if l not in self._cached_leases]
 
                # End here if nothing has changed
                if not new_leases and not removed_leases:
@@ -509,15 +490,33 @@ class UnboundConfigWriter(object):
                self.write_dhcp_leases(leases)
 
                # Update unbound about changes
-               for hostname in removed_leases:
-                       log.debug("Removing all records for %s" % hostname)
-                       self._control("local_data_remove", hostname)
+               for l in removed_leases:
+                       try:
+                               for name, ttl, type, content in l.rrset:
+                                       log.debug("Removing records for %s" % name)
+                                       self._control("local_data_remove", name)
+
+                       # If the lease cannot be removed we will try the next one
+                       except:
+                               continue
+
+                       # If the removal was successful, we will remove it from the cache
+                       else:
+                               self._cached_leases.remove(l)
 
                for l in new_leases:
-                       for rr in l.rrset:
-                               log.debug("Adding new record %s" % " ".join(rr))
-                               self._control("local_data", *rr)
+                       try:
+                               for rr in l.rrset:
+                                       log.debug("Adding new record %s" % " ".join(rr))
+                                       self._control("local_data", *rr)
 
+                       # If the lease cannot be added we will try the next one
+                       except:
+                               continue
+
+                       # Add lease to cache when successfully added
+                       else:
+                               self._cached_leases.append(l)
 
        def write_dhcp_leases(self, leases):
                with open(self.path, "w") as f:
@@ -530,13 +529,15 @@ class UnboundConfigWriter(object):
                command.extend(args)
 
                try:
-                       return subprocess.check_output(command)
+                       subprocess.check_output(command)
 
                # Log any errors
                except subprocess.CalledProcessError as e:
                        log.critical("Could not run %s, error code: %s: %s" % (
                                " ".join(command), e.returncode, e.output))
 
+                       raise
+
 
 if __name__ == "__main__":
        parser = argparse.ArgumentParser(description="Bridge for DHCP Leases and Unbound DNS")