link and flake cleanup
This commit is contained in:
+66
-13
@@ -1,13 +1,23 @@
|
||||
"""DNS update helper and pure asyncio worker for heartbeat daemon."""
|
||||
|
||||
from __future__ import annotations
|
||||
import subprocess
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
from typing import Optional
|
||||
import asyncio
|
||||
|
||||
|
||||
def create_nsupdate_payload(hostname: str, newip: str, dyndomain: str, dnsttl: str = "5") -> str:
|
||||
D = {"domain": dyndomain, "fqdn": f"{hostname}.dy.{dyndomain}", "dnsttl": dnsttl, "newip": newip, "ts": __import__("time").strftime("%Y-%m-%d.%H:%M:%S", __import__("time").gmtime())}
|
||||
def create_nsupdate_payload(
|
||||
hostname: str, newip: str, dyndomain: str, dnsttl: str = "5"
|
||||
) -> str:
|
||||
D = {
|
||||
"domain": dyndomain,
|
||||
"fqdn": f"{hostname}.dy.{dyndomain}",
|
||||
"dnsttl": dnsttl,
|
||||
"newip": newip,
|
||||
"ts": __import__("time").strftime(
|
||||
"%Y-%m-%d.%H:%M:%S", __import__("time").gmtime()
|
||||
),
|
||||
}
|
||||
if ":" in newip:
|
||||
nsup = (
|
||||
"""update delete %(fqdn)s AAAA
|
||||
@@ -17,7 +27,8 @@ update add %(fqdn)s %(dnsttl)s TXT "Created: %(ts)s"
|
||||
send
|
||||
answer
|
||||
|
||||
""" % D
|
||||
"""
|
||||
% D
|
||||
)
|
||||
else:
|
||||
nsup = (
|
||||
@@ -28,12 +39,19 @@ update add %(fqdn)s %(dnsttl)s TXT "Created: %(ts)s"
|
||||
send
|
||||
answer
|
||||
|
||||
""" % D
|
||||
"""
|
||||
% D
|
||||
)
|
||||
return nsup
|
||||
|
||||
|
||||
def nsupdate(hostname: str, newip: str, dyndomain: str, nsupdate_bin: str = "/usr/local/bin/nsupdate", rndc_key: str = "/etc/dhcpc/rndc-key") -> Optional[str]:
|
||||
def nsupdate(
|
||||
hostname: str,
|
||||
newip: str,
|
||||
dyndomain: str,
|
||||
nsupdate_bin: str = "/usr/local/bin/nsupdate",
|
||||
rndc_key: str = "/etc/dhcpc/rndc-key",
|
||||
) -> Optional[str]:
|
||||
"""Perform DNS update via nsupdate command.
|
||||
|
||||
Returns None on success, else returns combined stdout/stderr as a string.
|
||||
@@ -54,7 +72,14 @@ def nsupdate(hostname: str, newip: str, dyndomain: str, nsupdate_bin: str = "/us
|
||||
return out
|
||||
|
||||
|
||||
async def dns_update_worker(hbdclass, cfg: dict, async_queue=None, log: Optional[callable] = None, pushmsg: Optional[callable] = None, loop: Optional[asyncio.AbstractEventLoop] = None):
|
||||
async def dns_update_worker(
|
||||
hbdclass,
|
||||
cfg: dict,
|
||||
async_queue=None,
|
||||
log: Optional[callable] = None,
|
||||
pushmsg: Optional[callable] = None,
|
||||
loop: Optional[asyncio.AbstractEventLoop] = None,
|
||||
):
|
||||
"""Pure async DNS worker that processes updates from asyncio.Queue.
|
||||
|
||||
Exits when it receives a None sentinel.
|
||||
@@ -66,7 +91,9 @@ async def dns_update_worker(hbdclass, cfg: dict, async_queue=None, log: Optional
|
||||
if not dnsq:
|
||||
if log:
|
||||
try:
|
||||
await loop.run_in_executor(None, log, None, "dns_update_worker: no queue available")
|
||||
await loop.run_in_executor(
|
||||
None, log, None, "dns_update_worker: no queue available"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
@@ -77,7 +104,9 @@ async def dns_update_worker(hbdclass, cfg: dict, async_queue=None, log: Optional
|
||||
except Exception as e:
|
||||
if log:
|
||||
try:
|
||||
await loop.run_in_executor(None, log, None, f"dns_update_worker: error getting item: {e}")
|
||||
await loop.run_in_executor(
|
||||
None, log, None, f"dns_update_worker: error getting item: {e}"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
break
|
||||
@@ -96,12 +125,25 @@ async def dns_update_worker(hbdclass, cfg: dict, async_queue=None, log: Optional
|
||||
|
||||
m = f"changed address to {addr}"
|
||||
for dyndomain in cfg.get("dyndomains", []):
|
||||
err = await loop.run_in_executor(None, nsupdate, name, addr, dyndomain, cfg.get("nsupdate_bin", "/usr/local/bin/nsupdate"), cfg.get("rndc_key", "/etc/dhcpc/rndc-key"))
|
||||
err = await loop.run_in_executor(
|
||||
None,
|
||||
nsupdate,
|
||||
name,
|
||||
addr,
|
||||
dyndomain,
|
||||
cfg.get("nsupdate_bin", "/usr/local/bin/nsupdate"),
|
||||
cfg.get("rndc_key", "/etc/dhcpc/rndc-key"),
|
||||
)
|
||||
if err:
|
||||
m += f", DNS update failed: {err}"
|
||||
if pushmsg:
|
||||
try:
|
||||
await loop.run_in_executor(None, pushmsg, "error: nsupdate failed", f"{name}.dy.{dyndomain}: {m}")
|
||||
await loop.run_in_executor(
|
||||
None,
|
||||
pushmsg,
|
||||
"error: nsupdate failed",
|
||||
f"{name}.dy.{dyndomain}: {m}",
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
@@ -125,7 +167,13 @@ async def dns_update_worker(hbdclass, cfg: dict, async_queue=None, log: Optional
|
||||
pass
|
||||
|
||||
|
||||
def start_dns_worker(hbdclass, cfg: dict, log: Optional[callable] = None, pushmsg: Optional[callable] = None, loop: Optional[asyncio.AbstractEventLoop] = None):
|
||||
def start_dns_worker(
|
||||
hbdclass,
|
||||
cfg: dict,
|
||||
log: Optional[callable] = None,
|
||||
pushmsg: Optional[callable] = None,
|
||||
loop: Optional[asyncio.AbstractEventLoop] = None,
|
||||
):
|
||||
"""Start the async DNS worker and return the Task.
|
||||
|
||||
Replaces Host.dnsQ with an asyncio.Queue wrapped in a thread-safe bridge
|
||||
@@ -139,6 +187,7 @@ def start_dns_worker(hbdclass, cfg: dict, log: Optional[callable] = None, pushms
|
||||
|
||||
class _QueueBridge:
|
||||
"""Thread-safe wrapper around asyncio.Queue for synchronous callers."""
|
||||
|
||||
def __init__(self, loop, aq):
|
||||
self._loop = loop
|
||||
self._aq = aq
|
||||
@@ -167,5 +216,9 @@ def start_dns_worker(hbdclass, cfg: dict, log: Optional[callable] = None, pushms
|
||||
bridge = _QueueBridge(loop, async_q)
|
||||
hbdclass.Host.dnsQ = bridge
|
||||
|
||||
task = loop.create_task(dns_update_worker(hbdclass, cfg, async_queue=async_q, log=log, pushmsg=pushmsg, loop=loop))
|
||||
task = loop.create_task(
|
||||
dns_update_worker(
|
||||
hbdclass, cfg, async_queue=async_q, log=log, pushmsg=pushmsg, loop=loop
|
||||
)
|
||||
)
|
||||
return task
|
||||
|
||||
Reference in New Issue
Block a user