The operator, reviewing SNMP on #5214: "this system looks incomplete like there's something missing from it". The one device shown was plugin.yaml's example (core-switch 192.168.1.1, community public), polled every minute; devices could only be defined by editing YAML in the image; a failed poll was logged at DEBUG and stored nowhere, so the page said "waiting for the next poll" forever; v3 ran as v2c; counters showed as lifetime totals. - Devices are rows (snmp_devices, migration snmp_001): address, port, v1/v2c community or a v3 user with auth/priv protocols and keys (secrets encrypted), presets plus custom readings, an optional host binding, and the newest poll's outcome. The YAML device list and its example are gone. - The SNMP page adds, edits and deletes them (admin, audited, with get_audit_entities so the audit log names and links a device). Readings come from presets (system uptime, interface traffic by number, UPS-MIB, Linux net-snmp) and custom "OID name [unit]" lines. - One GET per device with every OID, devices polled at once. The outcome is written to the row in words ("No reply from … within 5 s. Check the address and port, that SNMP is on, and the community"), with readings it lacks. v1's whole-request error drops that OID and asks again. SNMPv3 signs in with USM (MD5/SHA-1/SHA-2, DES/3DES/AES). - Test asks the unsaved form's device for its name, description, uptime and interfaces by number. It is an admin's explicit action; every page reads only stored rows (System 178's ruling). - Each reading has a unit; a counter is stored as a per-second rate (bytes as bit/s), a reset or wrap skipped. The page, widget and host panel say values in units and why a device is silent; the device page draws a chart per reading on a dated axis. Tests: readings and presets, the form and its secrets, v3 checks, rates, the poller against a stand-in pysnmp (one GET, v1 retry, timeout wording, USM), the pages, and an integration test of the poll writing outcomes and rates on Postgres. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
29 lines
1.5 KiB
HTML
29 lines
1.5 KiB
HTML
{# plugins/snmp/templates/snmp/host_panel.html — the SNMP panel on a host's
|
|
page: the devices bound to this host, or at its address, with their
|
|
readings in their units, or why they aren't answering. #}
|
|
{% from "_macros.html" import status_badge, stat_tile %}
|
|
<div class="card">
|
|
<div style="display:flex;align-items:baseline;justify-content:space-between;margin-bottom:0.6rem;gap:1rem;flex-wrap:wrap;">
|
|
<h3 class="section-title" style="margin-bottom:0;">SNMP</h3>
|
|
<a href="/plugins/snmp/" class="field-hint">All devices</a>
|
|
</div>
|
|
{% for d in devices %}
|
|
<div{% if not loop.last %} style="margin-bottom:1rem;"{% endif %}>
|
|
<div style="display:flex;align-items:center;gap:0.6rem;margin-bottom:0.5rem;flex-wrap:wrap;">
|
|
<a href="/plugins/snmp/devices/{{ d.id }}" style="font-weight:500;">{{ d.name }}</a>
|
|
<span class="field-hint mono">{{ d.address }}</span>
|
|
{% if d.reach == 'up' %}{{ status_badge('up', 'Answering') }}
|
|
{% elif d.reach == 'down' %}{{ status_badge('down', 'Not answering', title=d.says) }}
|
|
{% elif d.reach == 'stale' %}{{ status_badge('stale', 'Not polled', title=d.says) }}
|
|
{% else %}{{ status_badge('pending', 'Not polled yet') }}{% endif %}
|
|
</div>
|
|
{% if d.reach == 'down' %}<p class="field-hint" style="margin:0 0 0.5rem;">{{ d.says }}</p>{% endif %}
|
|
{% if d.reach != 'pending' and d.readings %}
|
|
<div class="stat-strip" style="margin-bottom:0;">
|
|
{% for r in d.readings %}{{ stat_tile(r.name, r.text) }}{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|