From patchwork Fri Apr 26 15:09:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Tremer X-Patchwork-Id: 7763 Return-Path: Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by web04.haj.ipfire.org (Postfix) with ESMTPS id 4VQx2w5F3Bz3wyN for ; Fri, 26 Apr 2024 15:09:28 +0000 (UTC) Received: from mail02.haj.ipfire.org (mail02.haj.ipfire.org [172.28.1.201]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail02.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4VQx2t5Rq0z4X7; Fri, 26 Apr 2024 15:09:26 +0000 (UTC) Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4VQx2t4vM6z32fh; Fri, 26 Apr 2024 15:09:26 +0000 (UTC) Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4VQx2q6Gnmz32fh for ; Fri, 26 Apr 2024 15:09:23 +0000 (UTC) Received: from michael.haj.ipfire.org (michael.haj.ipfire.org [172.28.1.242]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384 client-signature ECDSA (secp384r1) client-digest SHA384) (Client CN "michael.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4VQx2n73Hyz1s4; Fri, 26 Apr 2024 15:09:21 +0000 (UTC) Received: by michael.haj.ipfire.org (Postfix, from userid 0) id 4VQx2n66ghzThrx; Fri, 26 Apr 2024 15:09:21 +0000 (UTC) From: Michael Tremer To: development@lists.ipfire.org Subject: [PATCH 1/3] unbound-dhcp-leases-bridge: Implement atomic file replacement Date: Fri, 26 Apr 2024 15:09:17 +0000 Message-Id: <20240426150919.3766772-1-michael.tremer@ipfire.org> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Message-ID-Hash: HUQUB2CSVQSTKCQ2DZWVW4J6GOKFCQKH X-Message-ID-Hash: HUQUB2CSVQSTKCQ2DZWVW4J6GOKFCQKH X-MailFrom: root@michael.haj.ipfire.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Michael Tremer X-Mailman-Version: 3.3.8 Precedence: list List-Id: IPFire development talk Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This change no longer renames the file, but removes the old link and creates a new link for the temporary file. That helps us to jump out of the code at any point without worrying about cleaning up the temporary file. Signed-off-by: Michael Tremer --- config/unbound/unbound-dhcp-leases-bridge | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index e9f022aff..5d5696af0 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -526,16 +526,22 @@ class UnboundConfigWriter(object): def write_dhcp_leases(self, leases): log.debug("Writing DHCP leases...") - with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: + with tempfile.NamedTemporaryFile(mode="w") as f: for l in leases: for rr in l.rrset: f.write("local-data: \"%s\"\n" % " ".join(rr)) + # Flush the file + f.flush() + # Make file readable for everyone os.fchmod(f.fileno(), stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IROTH) + # Remove the old file + os.unlink(self.path) + # Move the file to its destination - os.rename(f.name, self.path) + os.link(f.name, self.path) def _control(self, *args): command = ["unbound-control"] From patchwork Fri Apr 26 15:09:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Tremer X-Patchwork-Id: 7762 Return-Path: Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by web04.haj.ipfire.org (Postfix) with ESMTPS id 4VQx2v633bz3wwD for ; Fri, 26 Apr 2024 15:09:27 +0000 (UTC) Received: from mail02.haj.ipfire.org (mail02.haj.ipfire.org [172.28.1.201]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail02.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4VQx2s6zpKz4XD; Fri, 26 Apr 2024 15:09:25 +0000 (UTC) Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4VQx2s3Xz5z32vM; Fri, 26 Apr 2024 15:09:25 +0000 (UTC) Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4VQx2q5rgnz2y2N for ; Fri, 26 Apr 2024 15:09:23 +0000 (UTC) Received: from michael.haj.ipfire.org (michael.haj.ipfire.org [172.28.1.242]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "michael.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4VQx2p0GG1z2Pj; Fri, 26 Apr 2024 15:09:22 +0000 (UTC) Received: by michael.haj.ipfire.org (Postfix, from userid 0) id 4VQx2n6Bd5zTgR6; Fri, 26 Apr 2024 15:09:21 +0000 (UTC) From: Michael Tremer To: development@lists.ipfire.org Subject: [PATCH 2/3] unbound-dhcp-leases-bridge: Only reload if leases have actually changed Date: Fri, 26 Apr 2024 15:09:18 +0000 Message-Id: <20240426150919.3766772-2-michael.tremer@ipfire.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240426150919.3766772-1-michael.tremer@ipfire.org> References: <20240426150919.3766772-1-michael.tremer@ipfire.org> MIME-Version: 1.0 Message-ID-Hash: PGMCPBP3QMSLHK7UVREINKQ3U7NGV36H X-Message-ID-Hash: PGMCPBP3QMSLHK7UVREINKQ3U7NGV36H X-MailFrom: root@michael.haj.ipfire.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Michael Tremer , Nick Howitt X-Mailman-Version: 3.3.8 Precedence: list List-Id: IPFire development talk Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This patches changes that leases will always be written in alphanumerical order so that we can later compare the newly generated file with the previous version. If it has not changed, we skip reload Unbound. Suggested-by: Nick Howitt Signed-off-by: Michael Tremer --- config/unbound/unbound-dhcp-leases-bridge | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index 5d5696af0..80c8267e8 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 filecmp import functools import ipaddress import logging @@ -516,24 +517,29 @@ class UnboundConfigWriter(object): def update_dhcp_leases(self, leases): # Write out all leases - self.write_dhcp_leases(leases) + if self.write_dhcp_leases(leases): + log.debug("Reloading Unbound...") - log.debug("Reloading Unbound...") - - # Reload the configuration without dropping the cache - self._control("reload_keep_cache") + # Reload the configuration without dropping the cache + self._control("reload_keep_cache") def write_dhcp_leases(self, leases): log.debug("Writing DHCP leases...") with tempfile.NamedTemporaryFile(mode="w") as f: - for l in leases: + for l in sorted(leases, key=lambda x: x.ipaddr): for rr in l.rrset: f.write("local-data: \"%s\"\n" % " ".join(rr)) # Flush the file f.flush() + # Compare if the new leases file has changed from the previous version + if filecmp.cmp(f.name, self.path, shallow=False): + log.debug("The generated leases file has not changed") + + return False + # Make file readable for everyone os.fchmod(f.fileno(), stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IROTH) @@ -543,6 +549,8 @@ class UnboundConfigWriter(object): # Move the file to its destination os.link(f.name, self.path) + return True + def _control(self, *args): command = ["unbound-control"] command.extend(args) From patchwork Fri Apr 26 15:09:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Tremer X-Patchwork-Id: 7761 Return-Path: Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by web04.haj.ipfire.org (Postfix) with ESMTPS id 4VQx2t4ZqCz3wwD for ; Fri, 26 Apr 2024 15:09:26 +0000 (UTC) Received: from mail02.haj.ipfire.org (mail02.haj.ipfire.org [172.28.1.201]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail02.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4VQx2s2rr5z2VS; Fri, 26 Apr 2024 15:09:25 +0000 (UTC) Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4VQx2s2K9Nz32tD; Fri, 26 Apr 2024 15:09:25 +0000 (UTC) Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4VQx2q5Q1rz2y2N for ; Fri, 26 Apr 2024 15:09:23 +0000 (UTC) Received: from michael.haj.ipfire.org (michael.haj.ipfire.org [172.28.1.242]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature ECDSA (secp384r1)) (Client CN "michael.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4VQx2p0hfkz2QM; Fri, 26 Apr 2024 15:09:22 +0000 (UTC) Received: by michael.haj.ipfire.org (Postfix, from userid 0) id 4VQx2n6KrRzTk4r; Fri, 26 Apr 2024 15:09:21 +0000 (UTC) From: Michael Tremer To: development@lists.ipfire.org Subject: [PATCH 3/3] unbound-dhcp-leases-bridge: Make comparison work if old file does not exist Date: Fri, 26 Apr 2024 15:09:19 +0000 Message-Id: <20240426150919.3766772-3-michael.tremer@ipfire.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240426150919.3766772-1-michael.tremer@ipfire.org> References: <20240426150919.3766772-1-michael.tremer@ipfire.org> MIME-Version: 1.0 Message-ID-Hash: EHUEEUBXQISHPZ3KJV56BFBLJRI6ERKV X-Message-ID-Hash: EHUEEUBXQISHPZ3KJV56BFBLJRI6ERKV X-MailFrom: root@michael.haj.ipfire.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Michael Tremer X-Mailman-Version: 3.3.8 Precedence: list List-Id: IPFire development talk Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This patch catches any errors if the file did not previously exist and therefore skips the comparison. Signed-off-by: Michael Tremer --- config/unbound/unbound-dhcp-leases-bridge | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index 80c8267e8..7f89f620a 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -535,17 +535,22 @@ class UnboundConfigWriter(object): f.flush() # Compare if the new leases file has changed from the previous version - if filecmp.cmp(f.name, self.path, shallow=False): - log.debug("The generated leases file has not changed") + try: + if filecmp.cmp(f.name, self.path, shallow=False): + log.debug("The generated leases file has not changed") - return False + return False + + # Remove the old file + os.unlink(self.path) + + # If the previous file did not exist, just keep falling through + except FileNotFoundError: + pass # Make file readable for everyone os.fchmod(f.fileno(), stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IROTH) - # Remove the old file - os.unlink(self.path) - # Move the file to its destination os.link(f.name, self.path)