Refactor: Generalisierung der Konfiguration und atomares Schreiben der Zonefiles

This commit is contained in:
Gemini Bot
2025-12-09 16:20:11 +00:00
parent 573f387d84
commit 88bba9259c
5 changed files with 153 additions and 64 deletions

54
sync.py
View File

@@ -18,16 +18,16 @@ if not NETBOX_URL or not TOKEN:
sys.exit(1)
# Optionale Konfiguration mit Defaults
ZONE_NAME = os.getenv("ZONE_NAME", "klenzel.net")
REVERSE_ZONE_NAME = os.getenv("REVERSE_ZONE_NAME", "172.in-addr.arpa")
ZONE_NAME = os.getenv("ZONE_NAME", "example.com")
REVERSE_ZONE_NAME = os.getenv("REVERSE_ZONE_NAME", "1.168.192.in-addr.arpa")
REFRESH_INTERVAL = int(os.getenv("REFRESH_INTERVAL", "600"))
OUTPUT_FILE_FWD = os.getenv("OUTPUT_FILE_FWD", "/zones/db.klenzel.net")
OUTPUT_FILE_REV = os.getenv("OUTPUT_FILE_REV", "/zones/db.reverse.arpa")
OUTPUT_FILE_FWD = os.getenv("OUTPUT_FILE_FWD", "/zones/db.fwd")
OUTPUT_FILE_REV = os.getenv("OUTPUT_FILE_REV", "/zones/db.rev")
DEFAULT_TTL = os.getenv("DEFAULT_TTL", "3600")
# Fallback Konfiguration (wenn KEIN NS in NetBox gefunden wird)
FALLBACK_NS_HOSTNAME = os.getenv("FALLBACK_NS_HOSTNAME", "fks-01-cl-cdns")
FALLBACK_NS_IP = os.getenv("FALLBACK_NS_IP", "172.25.16.152")
FALLBACK_NS_HOSTNAME = os.getenv("FALLBACK_NS_HOSTNAME", "ns1")
FALLBACK_NS_IP = os.getenv("FALLBACK_NS_IP", "127.0.0.1")
HEADERS = {'Authorization': f'Token {TOKEN}', 'Accept': 'application/json'}
@@ -113,6 +113,28 @@ def get_ns_config(plugin_records, all_records):
return primary_ns, extra_header_lines
def write_atomic(filepath, content):
"""Schreibt Datei atomar: Erst in .tmp, dann move/replace."""
tmp_path = filepath + ".tmp"
try:
# Verzeichnis sicherstellen
os.makedirs(os.path.dirname(filepath), exist_ok=True)
with open(tmp_path, "w") as f:
f.write(content)
f.flush()
os.fsync(f.fileno())
os.replace(tmp_path, filepath)
return True
except Exception as e:
log(f"ERROR beim Schreiben von {filepath}: {e}")
if os.path.exists(tmp_path):
try:
os.remove(tmp_path)
except:
pass
raise e
def generate_zone_file_fwd(ipam_data, plugin_records):
"""Erstellt die Forward-Zone"""
@@ -152,11 +174,10 @@ def generate_zone_file_fwd(ipam_data, plugin_records):
header.extend(extra_headers)
header.append("")
with open(OUTPUT_FILE_FWD, "w") as f:
f.write("\n".join(header))
f.write("\n; --- Records ---\n")
f.write("\n".join(all_records))
f.write("\n")
content = "\n".join(header) + "\n; --- Records ---
" + "\n".join(all_records) + "\n"
write_atomic(OUTPUT_FILE_FWD, content)
log(f"SUCCESS: Forward Zone geschrieben ({len(all_records)} Records).")
def generate_zone_file_rev(ipam_data, plugin_records):
@@ -198,11 +219,10 @@ def generate_zone_file_rev(ipam_data, plugin_records):
header.append("")
with open(OUTPUT_FILE_REV, "w") as f:
f.write("\n".join(header))
f.write("\n; --- PTR Records ---\n")
f.write("\n".join(ptr_records))
f.write("\n")
content = "\n".join(header) + "\n; --- PTR Records ---
" + "\n".join(ptr_records) + "\n"
write_atomic(OUTPUT_FILE_REV, content)
log(f"SUCCESS: Reverse Zone geschrieben ({len(ptr_records)} Records).")
if __name__ == "__main__":
@@ -229,4 +249,4 @@ if __name__ == "__main__":
log(f"CRITICAL ERROR: Sync abgebrochen! Behalte alte Zone-Files. Grund: {e}")
log(f"Schlafe {REFRESH_INTERVAL} Sekunden...")
time.sleep(REFRESH_INTERVAL)
time.sleep(REFRESH_INTERVAL)