Add rollback logic when db update fails after DNS changes
This commit is contained in:
@@ -452,14 +452,29 @@ class DDNSRequestHandler(BaseHTTPRequestHandler):
|
||||
|
||||
return hostname
|
||||
|
||||
def _rollback_dns(self, hostname, old_ip, record_type):
|
||||
"""Roll back a DNS record to its previous value."""
|
||||
try:
|
||||
if old_ip:
|
||||
self.app.dns_service.update_record(
|
||||
hostname.hostname, hostname.zone,
|
||||
old_ip, hostname.dns_ttl)
|
||||
else:
|
||||
self.app.dns_service.delete_record(
|
||||
hostname.hostname, hostname.zone, record_type)
|
||||
except Exception as e:
|
||||
logging.error(f"DNS rollback failed ({record_type}): {e}")
|
||||
|
||||
def _process_ip_update(self, client_ip, user, hostname, ipv4, ipv6, notify_change):
|
||||
"""Process IP update for hostname."""
|
||||
now = now_utc()
|
||||
|
||||
old_ipv4 = hostname.last_ipv4
|
||||
old_ipv6 = hostname.last_ipv6
|
||||
ipv4_changed = False
|
||||
ipv6_changed = False
|
||||
|
||||
if ipv4:
|
||||
hostname.last_ipv4_update = now
|
||||
if ipv4 != hostname.last_ipv4:
|
||||
# Update DNS IPv4 record
|
||||
try:
|
||||
@@ -469,10 +484,8 @@ class DDNSRequestHandler(BaseHTTPRequestHandler):
|
||||
ipv4,
|
||||
hostname.dns_ttl
|
||||
)
|
||||
hostname.last_ipv4 = ipv4
|
||||
ipv4_changed = True
|
||||
except Exception as e:
|
||||
hostname.save()
|
||||
logging.error(f"DNS error: {e}")
|
||||
raise DDNSError(
|
||||
"Update failed",
|
||||
@@ -484,7 +497,6 @@ class DDNSRequestHandler(BaseHTTPRequestHandler):
|
||||
)
|
||||
|
||||
if ipv6:
|
||||
hostname.last_ipv6_update = now
|
||||
if ipv6 != hostname.last_ipv6:
|
||||
# Update DNS IPv6 record
|
||||
try:
|
||||
@@ -494,11 +506,12 @@ class DDNSRequestHandler(BaseHTTPRequestHandler):
|
||||
ipv6,
|
||||
hostname.dns_ttl
|
||||
)
|
||||
hostname.last_ipv6 = ipv6
|
||||
ipv6_changed = True
|
||||
except Exception as e:
|
||||
hostname.save()
|
||||
logging.error(f"DNS error: {e}")
|
||||
# Roll back IPv4 DNS if it was changed
|
||||
if ipv4_changed:
|
||||
self._rollback_dns(hostname, old_ipv4, "A")
|
||||
raise DDNSError(
|
||||
"Update failed",
|
||||
STATUS_DNSERR,
|
||||
@@ -508,8 +521,32 @@ class DDNSRequestHandler(BaseHTTPRequestHandler):
|
||||
ipv6=ipv6
|
||||
)
|
||||
|
||||
if ipv4_changed:
|
||||
hostname.last_ipv4 = ipv4
|
||||
hostname.last_ipv4_update = now
|
||||
if ipv6_changed:
|
||||
hostname.last_ipv6 = ipv6
|
||||
hostname.last_ipv6_update = now
|
||||
|
||||
# Update database
|
||||
hostname.save()
|
||||
try:
|
||||
hostname.save()
|
||||
except DatabaseError as e:
|
||||
logging.error(
|
||||
f"DB save failed after retries: hostname={hostname.hostname} "
|
||||
f"zone={hostname.zone}: {e}"
|
||||
)
|
||||
if ipv4_changed:
|
||||
self._rollback_dns(hostname, old_ipv4, "A")
|
||||
if ipv6_changed:
|
||||
self._rollback_dns(hostname, old_ipv6, "AAAA")
|
||||
raise DDNSError(
|
||||
"Update failed",
|
||||
STATUS_DNSERR,
|
||||
client=client_ip,
|
||||
hostname=hostname.hostname,
|
||||
zone=hostname.zone
|
||||
)
|
||||
|
||||
changed_addrs = ""
|
||||
if ipv4_changed:
|
||||
|
||||
Reference in New Issue
Block a user