]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/commitdiff
unbound-dhcp-leases-bridge: Fix inotify handling
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 30 Mar 2022 09:56:32 +0000 (09:56 +0000)
committerPeter Müller <peter.mueller@ipfire.org>
Mon, 4 Apr 2022 20:07:15 +0000 (20:07 +0000)
This patch changes that the script will listen to changes to the
directory instead of the file which got complicated when files got
renamed.

It also processes all changes at the same time and tries finding out
what actions have to be performed in order to avoid unnecessary
iterations.

The script is also limited to process any changes only once every five
seconds to keep resource usage in check on busy systems.

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

index ce0cb86143025d6c1bf0bae814f8aa1995532bae..c0e5977bffb7fc4f939e76f9b05d6a8b993d5714 100644 (file)
@@ -32,6 +32,7 @@ import stat
 import subprocess
 import sys
 import tempfile
+import time
 
 import inotify.adapters
 
@@ -82,6 +83,12 @@ class UnboundDHCPLeasesBridge(object):
                self.fix_leases_file = fix_leases_file
                self.hosts_file = hosts_file
 
+               self.watches = {
+                       self.leases_file     : inotify.constants.IN_MODIFY,
+                       self.fix_leases_file : 0,
+                       self.hosts_file      : 0,
+               }
+
                self.unbound = UnboundConfigWriter(unbound_leases_file)
                self.running = False
 
@@ -89,37 +96,54 @@ class UnboundDHCPLeasesBridge(object):
                log.info("Unbound DHCP Leases Bridge started on %s" % self.leases_file)
                self.running = True
 
-               # Initial setup
-               self.hosts = self.read_static_hosts()
-               self.update_dhcp_leases()
+               i = inotify.adapters.Inotify()
 
-               i = inotify.adapters.Inotify([
-                       self.leases_file,
-                       self.fix_leases_file,
-                       self.hosts_file,
-               ])
+               # Add watches for the directories of every relevant file
+               for f, mask in self.watches.items():
+                       i.add_watch(
+                               os.path.dirname(f),
+                               mask | inotify.constants.IN_CLOSE_WRITE | inotify.constants.IN_MOVED_TO,
+                       )
 
-               for event in i.event_gen():
-                       # End if we are requested to terminate
-                       if not self.running:
-                               break
+               # Enabled so that we update hosts and leases on startup
+               update_hosts = update_leases = True
 
-                       if event is None:
-                               continue
+               while self.running:
+                       log.debug("Wakeup of main loop")
+
+                       # Process the entire inotify queue and identify what we need to do
+                       for event in i.event_gen():
+                               # Nothing to do
+                               if event is None:
+                                       break
+
+                               # Decode the event
+                               header, type_names, path, filename = event
 
-                       header, type_names, watch_path, filename = event
+                               file = os.path.join(path, filename)
 
-                       # Update leases after leases file has been modified
-                       if "IN_MODIFY" in type_names:
-                               # Reload hosts
-                               if watch_path == self.hosts_file:
-                                       self.hosts = self.read_static_hosts()
+                               log.debug("inotify event received for %s: %s", file, " ".join(type_names))
 
+                               # Did the hosts file change?
+                               if self.hosts_file == file:
+                                       update_hosts = True
+
+                               # We will need to update the leases on any change
+                               update_leases = True
+
+                       # Update hosts (if needed)
+                       if update_hosts:
+                               self.hosts = self.read_static_hosts()
+
+                       # Update leases (if needed)
+                       if update_leases:
                                self.update_dhcp_leases()
 
-                       # If the file is deleted, we re-add the watcher
-                       if "IN_IGNORED" in type_names:
-                               i.add_watch(watch_path)
+                       # Reset
+                       update_hosts = update_leases = False
+
+                       # Wait a moment before we start the next iteration
+                       time.sleep(5)
 
                log.info("Unbound DHCP Leases Bridge terminated")