WinPE now reports each machine's WMI model, manufacturer, Dell system
SKU and BIOS version to /hardware/seen (winpe-status-push.ps1, best
effort, wmic only). The webapp records every model seen and checks it
against what the server has:
- each image's Deploy/Control/HardwareDriver.json, matched exactly as
PESetup's GetDriverByModel does (as reimplemented in
lint-driver-catalogue.py), plus whether the pack's zip is on disk;
- the WinPE BIOS manifest (substring match like check-bios.cmd).
/hardware lists every model with per-image driver status and BIOS
status. A model missing a Win11 pack or a BIOS entry becomes item 5 on
the Technician To-Do (and the banner count) until the pack/BIOS is added
or it is dismissed. Virtual machines are ignored.
Also deploys the repo winpe-status-push.ps1 over the live copy, which
predated the -CurrentStage/-StageIndex parameters startnet.cmd passes
for the BIOS-flash stage, so that status post was failing.
82 lines
3.8 KiB
HTML
82 lines
3.8 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Hardware Coverage - PXE Server Manager{% endblock %}
|
|
|
|
{% macro driver_badge(d) -%}
|
|
{% if d.status == 'ok' %}<span class="badge badge-success" title="{{ d.file }}">OK</span>
|
|
{% elif d.status == 'no-entry' %}<span class="badge badge-danger" title="No HardwareDriver.json entry matches this model">Missing</span>
|
|
{% elif d.status == 'zip-missing' %}<span class="badge badge-danger" title="Entry {{ d.file }} matches, but the zip is not on the server">Zip missing</span>
|
|
{% else %}<span class="text-muted">-</span>{% endif %}
|
|
{%- endmacro %}
|
|
|
|
{% macro bios_badge(b) -%}
|
|
{% if b.status == 'current' %}<span class="badge badge-success">{{ b.target }} (current)</span>
|
|
{% elif b.status == 'update' %}<span class="badge badge-info" title="{{ b.file }}">Flashes to {{ b.target }}</span>
|
|
{% elif b.status == 'file-missing' %}<span class="badge badge-danger" title="{{ b.file }} not in the BIOS folder">File missing</span>
|
|
{% else %}<span class="badge badge-danger">No BIOS entry</span>{% endif %}
|
|
{%- endmacro %}
|
|
|
|
{% block content %}
|
|
<div class="page-header">
|
|
<h1><i class="bi bi-cpu"></i> Hardware Coverage</h1>
|
|
<div class="header-actions">
|
|
<span class="badge badge-secondary badge-lg">{{ rows | length }} model{{ 's' if rows | length != 1 }} seen</span>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="text-muted">
|
|
Every model that has booted WinPE here, as reported by the machine itself (WMI model, Dell system SKU,
|
|
BIOS version), checked against each image's driver map and the WinPE BIOS manifest. A model missing a
|
|
Win11 driver pack or a BIOS entry also shows on the Technician To-Do until it is added or dismissed.
|
|
</p>
|
|
|
|
<div class="section-card">
|
|
{% if rows %}
|
|
<div class="table-container">
|
|
<table class="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Model (WMI)</th>
|
|
<th>System SKU</th>
|
|
<th>BIOS seen</th>
|
|
{% for image, os_label in images %}<th title="{{ image }}">{{ image | replace('gea-', '') }} <span class="text-muted">({{ os_label }})</span></th>{% endfor %}
|
|
<th>BIOS update</th>
|
|
<th>Last seen</th>
|
|
<th class="text-end"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for r in rows %}
|
|
<tr title="Serials: {{ r.serials | join(', ') }}{% if r.pctypes %} | Types: {{ r.pctypes | join(', ') }}{% endif %}">
|
|
<td>
|
|
<span class="mono">{{ r.model }}</span>
|
|
{% if r.manufacturer %}<div class="small text-muted">{{ r.manufacturer }}</div>{% endif %}
|
|
</td>
|
|
<td class="mono">{{ r.skus | join(', ') or '-' }}</td>
|
|
<td class="mono">{{ r.last_bios_version or '-' }}</td>
|
|
{% for image, os_label in images %}<td>{{ driver_badge(r.drivers[image]) }}</td>{% endfor %}
|
|
<td>{{ bios_badge(r.bios) }}</td>
|
|
<td class="mono text-nowrap">{{ r.last_seen | local_dt }}<div class="small text-muted">{{ r.count }} boot{{ 's' if r.count != 1 }}</div></td>
|
|
<td class="text-end text-nowrap">
|
|
{% if r.gap %}
|
|
<form method="post" action="{{ url_for('hardware_dismiss') }}" style="display:inline;">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" name="model" value="{{ r.model }}">
|
|
<input type="hidden" name="done" value="{{ '0' if r.dismissed else '1' }}">
|
|
<button type="submit" class="pxe-btn pxe-btn-ghost btn-row-action">{{ 'Reopen' if r.dismissed else 'Dismiss' }}</button>
|
|
</form>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center text-muted py-5">
|
|
<p class="mb-1">No machines have reported yet.</p>
|
|
<p class="small">Models appear here the next time a machine boots WinPE from this server.</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %}
|