Development
This commit is contained in:
parent
22b18897b6
commit
7da1630ab3
3 changed files with 24 additions and 6 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# factory.py — JSON content-type renderer
|
# factory.py: JSON content-type renderer
|
||||||
# Converts content.json item trees into HTML strings.
|
# Converts content.json item trees into HTML strings.
|
||||||
# Pure type processing: no data loading, no routing, no layout.
|
# Pure type processing: no data loading, no routing, no layout.
|
||||||
from flask import session
|
from flask import session
|
||||||
|
|
@ -46,7 +46,7 @@ def _prefix_to_dotted(n):
|
||||||
|
|
||||||
|
|
||||||
def apply_tokens(text, tokens):
|
def apply_tokens(text, tokens):
|
||||||
"""Substitute %TOKEN% placeholders. Values are NOT auto-escaped — callers
|
"""Substitute %TOKEN% placeholders. Values are NOT auto-escaped. Callers
|
||||||
that use results in HTML attribute or text context must call e() themselves."""
|
that use results in HTML attribute or text context must call e() themselves."""
|
||||||
return re.sub(r'%([A-Z_]+)%', lambda m: str(tokens.get(m.group(1), m.group(0))), text)
|
return re.sub(r'%([A-Z_]+)%', lambda m: str(tokens.get(m.group(1), m.group(0))), text)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"label": "Hostname",
|
"label": "Hostname",
|
||||||
"field": "hostname"
|
"field": "hostname",
|
||||||
|
"render": "raw_html"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "IP Address",
|
"label": "IP Address",
|
||||||
|
|
|
||||||
|
|
@ -177,11 +177,17 @@ def _dnsmasq_start_time(vlan_name):
|
||||||
def live_dhcp_leases():
|
def live_dhcp_leases():
|
||||||
rows = []
|
rows = []
|
||||||
now = int(datetime.now(tz=timezone.utc).timestamp())
|
now = int(datetime.now(tz=timezone.utc).timestamp())
|
||||||
vlans = load_config().get('vlans', [])
|
cfg = load_config()
|
||||||
|
vlans = cfg.get('vlans', [])
|
||||||
vlan_lease_secs = {
|
vlan_lease_secs = {
|
||||||
v['name']: _parse_lease_secs(v.get('dhcp', {}).get('lease_time', ''))
|
v['name']: _parse_lease_secs(v.get('dhcp_information', {}).get('lease_time', ''))
|
||||||
for v in vlans if v.get('name')
|
for v in vlans if v.get('name')
|
||||||
}
|
}
|
||||||
|
mac_to_res = {
|
||||||
|
r['mac'].lower(): r['hostname']
|
||||||
|
for r in cfg.get('dhcp_reservations', [])
|
||||||
|
if r.get('mac') and r.get('hostname')
|
||||||
|
}
|
||||||
for leases_file in glob.glob('/var/lib/misc/dnsmasq-routlin-*.leases'):
|
for leases_file in glob.glob('/var/lib/misc/dnsmasq-routlin-*.leases'):
|
||||||
stem = os.path.basename(leases_file)
|
stem = os.path.basename(leases_file)
|
||||||
vlan_name = stem[len('dnsmasq-routlin-'):-len('.leases')]
|
vlan_name = stem[len('dnsmasq-routlin-'):-len('.leases')]
|
||||||
|
|
@ -200,8 +206,19 @@ def live_dhcp_leases():
|
||||||
obtained = relative_time(obtained_ts) if obtained_ts else '-'
|
obtained = relative_time(obtained_ts) if obtained_ts else '-'
|
||||||
recent = (obtained_ts is not None and restart_time is not None
|
recent = (obtained_ts is not None and restart_time is not None
|
||||||
and obtained_ts >= restart_time)
|
and obtained_ts >= restart_time)
|
||||||
|
mac_norm = parts[1].lower()
|
||||||
|
device_h = parts[3] if parts[3] != '*' else None
|
||||||
|
res_h = mac_to_res.get(mac_norm)
|
||||||
|
if res_h and device_h and device_h.lower() != res_h.lower():
|
||||||
|
hostname_html = f'<strong>{e(res_h)}</strong><br/>({e(device_h)})'
|
||||||
|
elif res_h:
|
||||||
|
hostname_html = f'<strong>{e(res_h)}</strong>'
|
||||||
|
elif device_h:
|
||||||
|
hostname_html = e(device_h)
|
||||||
|
else:
|
||||||
|
hostname_html = '-'
|
||||||
rows.append({
|
rows.append({
|
||||||
'hostname': parts[3] if parts[3] != '*' else '-',
|
'hostname': hostname_html,
|
||||||
'ip_address': parts[2],
|
'ip_address': parts[2],
|
||||||
'mac_address': parts[1],
|
'mac_address': parts[1],
|
||||||
'vlan_name': vlan_name,
|
'vlan_name': vlan_name,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue