Development

This commit is contained in:
Matthew Grotke 2026-05-27 04:21:09 -04:00
parent 08a0825345
commit f257070095
3 changed files with 59 additions and 15 deletions

View file

@ -1,4 +1,5 @@
import copy
import ipaddress
from flask import Blueprint, request, redirect, flash
from auth import require_level
@ -209,18 +210,52 @@ def networklayout_tablevlans_edit():
existing_gw = existing.get('dhcp_information', {}).get('explicit_overrides', {}).get('gateway', '')
dns_override = 'dns_server_override' in request.form
dns_raw = sanitize.ip(request.form.get('dns_server', ''))
if dns_override:
if not dns_raw:
flash('DNS server IP is required when override is enabled.', 'error')
dns_ips = []
for _line in request.form.get('dns_server', '').splitlines():
_line = _line.strip()
if not _line:
continue
_clean = sanitize.ip(_line)
if not _clean:
flash(f"'{_line}' is not a valid DNS server IP.", 'error')
return redirect(VIEW)
if dns_raw not in identity_ips:
flash(f"DNS server '{dns_raw}' must match one of the server identity IPs.", 'error')
dns_ips.append(_clean)
if dns_override and not dns_ips:
flash('At least one DNS server IP is required when override is enabled.', 'error')
return redirect(VIEW)
if dns_override and dns_ips:
_vlan_net = ipaddress.IPv4Network(f'{subnet}/{final_mask}', strict=False)
for _ip in dns_ips:
if ipaddress.IPv4Address(_ip) not in _vlan_net:
flash(f"DNS server '{_ip}' is not in the VLAN subnet ({subnet}/{final_mask}).", 'error')
return redirect(VIEW)
new_stored_dns = dns_ips if dns_override else []
_existing_dns = existing.get('dhcp_information', {}).get('explicit_overrides', {}).get('dns_server', [])
existing_dns = _existing_dns if isinstance(_existing_dns, list) else ([_existing_dns] if _existing_dns else [])
ntp_override = 'ntp_server_override' in request.form
ntp_ips = []
for _line in request.form.get('ntp_server', '').splitlines():
_line = _line.strip()
if not _line:
continue
_clean = sanitize.ip(_line)
if not _clean:
flash(f"'{_line}' is not a valid NTP server IP.", 'error')
return redirect(VIEW)
inferred_dns = (min(identity_ips, key=lambda ip: int(ip.split('.')[-1]))
if identity_ips else '')
new_stored_dns = dns_raw if (dns_override and dns_raw and dns_raw != inferred_dns) else ''
existing_dns = existing.get('dhcp_information', {}).get('explicit_overrides', {}).get('dns_server', '')
ntp_ips.append(_clean)
if ntp_override and not ntp_ips:
flash('At least one NTP server IP is required when override is enabled.', 'error')
return redirect(VIEW)
if ntp_override and ntp_ips:
_vlan_net = ipaddress.IPv4Network(f'{subnet}/{final_mask}', strict=False)
for _ip in ntp_ips:
if ipaddress.IPv4Address(_ip) not in _vlan_net:
flash(f"NTP server '{_ip}' is not in the VLAN subnet ({subnet}/{final_mask}).", 'error')
return redirect(VIEW)
new_stored_ntp = ntp_ips if ntp_override else []
_existing_ntp = existing.get('dhcp_information', {}).get('explicit_overrides', {}).get('ntp_server', [])
existing_ntp = _existing_ntp if isinstance(_existing_ntp, list) else ([_existing_ntp] if _existing_ntp else [])
_ids_unchanged = (
len(new_identities) == len(old_identities) and
@ -240,7 +275,8 @@ def networklayout_tablevlans_edit():
and sorted(use_blocklists) == sorted(existing.get('use_blocklists', []))
and _ids_unchanged
and new_stored_gw == existing_gw
and new_stored_dns == existing_dns):
and new_stored_dns == existing_dns
and new_stored_ntp == existing_ntp):
flash('No changes were made.', 'info')
return redirect(VIEW)
@ -265,6 +301,12 @@ def networklayout_tablevlans_edit():
dhcp_overrides['dns_server'] = new_stored_dns
else:
dhcp_overrides.pop('dns_server', None)
if new_stored_ntp:
dhcp_overrides['ntp_server'] = new_stored_ntp
else:
dhcp_overrides.pop('ntp_server', None)
if not dhcp_overrides:
existing.get('dhcp_information', {}).pop('explicit_overrides', None)
errors = validate.validate_config(cfg)
if errors:
for msg in errors:

View file

@ -325,9 +325,10 @@ def _config_datasource(name):
row['server_identity_gateway'] = (
v.get('dhcp_information', {}).get('explicit_overrides', {}).get('gateway', '')
)
row['server_identity_dns_server'] = (
v.get('dhcp_information', {}).get('explicit_overrides', {}).get('dns_server', '')
)
_dns = v.get('dhcp_information', {}).get('explicit_overrides', {}).get('dns_server', [])
row['server_identity_dns_server'] = '\n'.join(_dns) if isinstance(_dns, list) else str(_dns or '')
_ntp = v.get('dhcp_information', {}).get('explicit_overrides', {}).get('ntp_server', [])
row['server_identity_ntp_server'] = '\n'.join(_ntp) if isinstance(_ntp, list) else str(_ntp or '')
rows.append(row)
return rows

View file

@ -1589,7 +1589,8 @@
"pair_label2": "Hostname (Opt)",
"pair_validate2": "networkname",
"gateway_col": "server_identity_gateway",
"dns_col": "server_identity_dns_server"
"dns_col": "server_identity_dns_server",
"ntp_col": "server_identity_ntp_server"
},
{
"col": "radius_default",