This improves logging and enables logging to the console.
Suggested-by: Anthony Heading ajrh@ajrh.net Signed-off-by: Michael Tremer michael.tremer@ipfire.org --- config/unbound/unbound-dhcp-leases-bridge | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index a2df5f101..ce0cb8614 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -30,27 +30,37 @@ import re import signal import stat import subprocess +import sys import tempfile
import inotify.adapters
LOCAL_TTL = 60
-def setup_logging(loglevel=logging.INFO): - log = logging.getLogger("dhcp") +log = logging.getLogger("dhcp") +log.setLevel(logging.DEBUG) + +def setup_logging(daemon=True, loglevel=logging.INFO): log.setLevel(loglevel)
+ # Log to syslog by default handler = logging.handlers.SysLogHandler(address="/dev/log", facility="daemon") - handler.setLevel(loglevel) + log.addHandler(handler)
+ # Format everything formatter = logging.Formatter("%(name)s[%(process)d]: %(message)s") handler.setFormatter(formatter)
- log.addHandler(handler) + handler.setLevel(loglevel)
- return log + # If we are running in foreground, we should write everything to the console, too + if not daemon: + handler = logging.StreamHandler() + log.addHandler(handler)
-log = logging.getLogger("dhcp") + handler.setLevel(loglevel) + + return log
def ip_address_to_reverse_pointer(address): parts = address.split(".") @@ -579,12 +589,12 @@ if __name__ == "__main__": elif args.verbose >= 2: loglevel = logging.DEBUG
- setup_logging(loglevel) + setup_logging(daemon=args.daemon, loglevel=loglevel)
bridge = UnboundDHCPLeasesBridge(args.dhcp_leases, args.fix_leases, args.unbound_leases, args.hosts)
- ctx = daemon.DaemonContext(detach_process=args.daemon) + ctx = daemon.DaemonContext(detach_process=args.daemon, stderr=sys.stderr) ctx.signal_map = { signal.SIGHUP : bridge.update_dhcp_leases, signal.SIGTERM : bridge.terminate,
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 | 70 +++++++++++++++-------- 1 file changed, 47 insertions(+), 23 deletions(-)
diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index ce0cb8614..c0e5977bf 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -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")
This saves some resources when we re-read the same configuration file too often.
Suggested-by: Anthony Heading ajrh@ajrh.net Signed-off-by: Michael Tremer michael.tremer@ipfire.org --- config/unbound/unbound-dhcp-leases-bridge | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index c0e5977bf..b098d98b4 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -22,6 +22,7 @@ import argparse import datetime import daemon +import functools import ipaddress import logging import logging.handlers @@ -444,6 +445,7 @@ class Lease(object): return "localdomain"
@staticmethod + @functools.cache def read_settings(filename): settings = {}
Signed-off-by: Michael Tremer michael.tremer@ipfire.org --- config/unbound/unbound-dhcp-leases-bridge | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index b098d98b4..50a0e516a 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -615,8 +615,6 @@ if __name__ == "__main__": elif args.verbose >= 2: loglevel = logging.DEBUG
- setup_logging(daemon=args.daemon, loglevel=loglevel) - bridge = UnboundDHCPLeasesBridge(args.dhcp_leases, args.fix_leases, args.unbound_leases, args.hosts)
@@ -627,4 +625,6 @@ if __name__ == "__main__": }
with ctx: + setup_logging(daemon=args.daemon, loglevel=loglevel) + bridge.run()
Signed-off-by: Michael Tremer michael.tremer@ipfire.org --- config/unbound/unbound-dhcp-leases-bridge | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index 50a0e516a..1446c88df 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -618,13 +618,14 @@ if __name__ == "__main__": bridge = UnboundDHCPLeasesBridge(args.dhcp_leases, args.fix_leases, args.unbound_leases, args.hosts)
- ctx = daemon.DaemonContext(detach_process=args.daemon, stderr=sys.stderr) - ctx.signal_map = { - signal.SIGHUP : bridge.update_dhcp_leases, - signal.SIGTERM : bridge.terminate, - } - - with ctx: + with daemon.DaemonContext( + detach_process=args.daemon, + stderr=None if args.daemon else sys.stderr, + signal_map = { + signal.SIGHUP : bridge.update_dhcp_leases, + signal.SIGTERM : bridge.terminate, + }, + ) as daemon: setup_logging(daemon=args.daemon, loglevel=loglevel)
bridge.run()