webapp: fix review findings (imaging types, NIC status, iPXE gates)
- imaging: coerce client payload and stored session fields to str/int, drop lists/dicts; tiles template guards pctype/current_stage; POST rejects non-object bodies and non-string serials. - nic_status: normalise every check-file entry; load nic.conf as-is with a [nic] fallback; split interface= lists; keep the check's binding while fresh, resolve wildcard sockets from the dnsmasq pin (never True for an excluded NIC); mark vanished NICs down; include role bridges; stale or future-dated files downgrade to warnings and drop evidence. - Overview renders the network pill in its own try and shows 'Network: unknown' when status fails. - ipxe_update: read every Authenticode signature (all WIN_CERTIFICATE entries plus nested SPC_NESTED_SIGNATURE) with openssl; shim swap and install need both Microsoft UEFI CA 2011 and 2023; install re-reads each file (snponly ipxe.efi only); staged.json schema version, older records shown stale and refused; uhci counts as native USB. - backups describe their files; risky rollbacks need a confirm flag. - mac_folders: guarded listdir, cached describe, configured TFTP root, warning for a shim without ipxe.efi. - evidence pack: years 2000..2100, 400 days inclusive. - a11y role=group on quick ranges; progress bar stays full during 'shim'. - tests/test_review_fixes.py: 29 unittest cases incl. both real shims.
This commit is contained in:
50
webapp/templates/_nic_status.html
Normal file
50
webapp/templates/_nic_status.html
Normal file
@@ -0,0 +1,50 @@
|
||||
{# Overview network pill and its problem notice. Rendered on its own by
|
||||
the dashboard view (part = 'pill' or 'notice') inside a try, so a broken
|
||||
status file can never take the Overview down. #}
|
||||
{% import '_ui.html' as ui %}
|
||||
{% if part == 'pill' %}
|
||||
{% set nic_dot = {'ok': 'var(--ok)', 'warn': 'var(--act)', 'bad': 'var(--fail)'}.get(nic.state, 'var(--off-edge)') %}
|
||||
{% set role_name = {'imaging': 'Imaging', 'ge': 'GE network', 'other': 'Other'} %}
|
||||
{% set verdict_chip = {'isolated': ('Isolated', 'ok'), 'ge': ('GE network', 'neutral'), 'foreign-dhcp': ('Other DHCP server', 'err'),
|
||||
'no-link': ('No link', 'off'), 'error': ('Check failed', 'warn')} %}
|
||||
<details class="more">
|
||||
<summary class="fbtn" style="background: var(--surface); min-height: 36px">
|
||||
<span class="dot" style="background: {{ nic_dot }}"></span>
|
||||
{{ {'ok': 'Network OK', 'warn': 'Network: check', 'bad': 'Network: DANGER'}.get(nic.state, 'Network: unknown') }}
|
||||
<span class="chev" aria-hidden="true">▾</span>
|
||||
</summary>
|
||||
<div class="menu" style="width: min(460px, calc(100vw - 32px)); padding: 12px 14px; gap: 10px; font-size: 13px">
|
||||
{% for i in nic.interfaces %}
|
||||
{% set bad_here = (i.role == 'imaging' and i.verdict in ('ge', 'foreign-dhcp')) or (i.role != 'imaging' and i.dnsmasq_bound) %}
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
|
||||
<span class="dot" style="background: {{ 'var(--fail)' if bad_here else ('var(--ok)' if i.link == 'up' else 'var(--act)') }}"></span>
|
||||
<strong>{{ role_name.get(i.role, i.role) }}</strong>
|
||||
<span class="mono muted">{{ i.iface }}</span>
|
||||
{% if i.verdict and i.verdict in verdict_chip %}{% set vc = verdict_chip[i.verdict] %}{{ ui.chip(vc[0], 'err' if bad_here else vc[1]) }}{% endif %}
|
||||
</div>
|
||||
<div class="muted" style="padding-left: 18px; white-space: normal">
|
||||
{{ 'Up' if i.link == 'up' else 'No link' }}{% if i.speed_mbps is number and i.speed_mbps > 0 %}, {% if i.speed_mbps >= 1000 %}{{ (i.speed_mbps // 1000) if i.speed_mbps % 1000 == 0 else (i.speed_mbps / 1000) | round(1) }} Gb/s{% else %}{{ i.speed_mbps }} Mb/s{% endif %}{% endif %}
|
||||
{% if i.addrs and i.addrs is not string %}<span class="mono">{{ i.addrs | join(', ') }}</span>{% endif %}
|
||||
{% if i.dnsmasq_bound is not none %}<br>DHCP/PXE {{ 'served here' if i.dnsmasq_bound else 'not served here' }}{% endif %}
|
||||
{% for e in (i.evidence if i.evidence is iterable and i.evidence is not string else []) %}<br>{{ e }}{% endfor %}{% for n in (i.notes if i.notes is iterable and i.notes is not string else []) %}<br><span class="sub">{{ n }}</span>{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="muted">{{ 'Interfaces unknown.' if nic.source == 'error' else 'No network interfaces found.' }}</div>
|
||||
{% endfor %}
|
||||
<div class="sub" style="white-space: normal; border-top: 1px solid var(--line); padding-top: 8px">
|
||||
{% if nic.source == 'check' and not nic.stale %}Checked {{ nic.checked_at | local_dt }} by pxe-nic-check.
|
||||
{% elif nic.source == 'check' %}The network check is stale (last {{ nic.checked_at | local_dt }}): showing link and addresses only.
|
||||
{% elif nic.source == 'error' %}The network status could not be read{% if nic.error %}: <span class="mono">{{ nic.error }}</span>{% endif %}. See the webapp log.
|
||||
{% else %}Link and addresses only; pxe-nic-check (the GE-network detector) is not installed yet.{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
{% elif part == 'notice' %}
|
||||
{% if nic and nic.problems %}
|
||||
<div class="notice{{ ' bad' if nic.state == 'bad' else '' }}" role="{{ 'alert' if nic.state == 'bad' else 'status' }}">
|
||||
<span>{% if nic.state == 'bad' %}<strong>Network danger.</strong> {% endif %}{% for level, text in nic.problems %}{{ text }}{% if not loop.last %} {% endif %}{% endfor %}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user