Telemetry: gnmic + Prometheus + Grafana weathermap dashboard, iperf3 traffic generator #59

Merged
Damien merged 30 commits from feat/telemetry into main 2026-07-20 16:59:10 +00:00

30 Commits

Author SHA1 Message Date
5e5d6b45df Fix scripts/README.md doc drift after iperf3/weathermap direction fixes
Traffic direction docs still described the pre-fix client->server
iperf3 flow and the pre-fix tx/rx weathermap query pair.

Refs #57, Refs #58
2026-07-20 16:57:28 +00:00
4719a77f21 Reverse iperf3 traffic direction to DC->campus (server pushes to client)
Without -R, iperf3's client sends and the server only receives, so
traffic ran campus-host -> dc-server -- backwards for what these roles
represent: dc-serverN is the DC-hosted service, campus-hostN is the
consumer, and a real service delivers data to the consumer rather than
just absorbing uploads from it.

Refs #58
2026-07-20 16:37:16 +00:00
08124c8a1c Fix weathermap links to show both traffic directions
Z side queried z_host's rx, which measures the same A->Z flow as A
side's tx (same traffic, counted at each end) -- the Z->A direction
was never queried by either side. Use z_host's own tx instead, so
each side surfaces its own (opposite) direction.

Confirmed against the iperf3 traffic generator: DC access-leaf links
read ~500Kbps (ACK-only) before the fix despite ~18-20Mbps of real
downstream traffic to dc-server2/4, because that flow ran leaf->access
(Z->A), the unqueried direction. Campus links looked correct only by
coincidence -- campus hosts are the iperf3 clients, so their upload
traffic happens to run access->leaf (A->Z), the direction that was
queried.

Refs #57
2026-07-20 16:31:33 +00:00
8349791630 Merge pull request 'Add iperf3 traffic generator for DC<->Campus gold VRF path' (#56) from feat/iperf-traffic-generator into feat/telemetry
Reviewed-on: #56
2026-07-20 16:15:19 +00:00
3c3b28c987 Merge branch 'feat/telemetry' into feat/iperf-traffic-generator 2026-07-20 16:15:09 +00:00
5b12894289 Add iperf3 traffic generator for DC<->Campus gold VRF path
Host containers sit idle otherwise, leaving IPFabric ARP/MAC tables and
Grafana throughput graphs empty until someone manually generates traffic.

Refs #55
2026-07-20 16:09:39 +00:00
Damien
0f3aa27566 Add Grafana weathermap dashboard asset 2026-07-10 15:35:12 +02:00
1cbea38522 Fix read-back arrow to terminate on dashboard-base.json's edge, not its middle 2026-07-10 13:22:56 +00:00
64a8287518 Update scripts README table formatting 2026-07-10 13:19:43 +00:00
045179e098 Reword scripts/README.md for readability, add pipeline diagram
Same content, restructured for scanning: tables instead of long
paragraphs (credentials, troubleshooting, env vars), shorter sentences,
deep rationale trimmed to a phrase + issue reference instead of inline
essays. Cut from 258 to 135 lines.

Added assets/weathermap-pipeline.svg showing the IPFabric/Prometheus ->
generator -> merge (with the manual base) -> Grafana flow, referenced at
the top of the README.
2026-07-10 13:18:05 +00:00
998014d144 Update Grafana weathermap dashboard node positions 2026-07-10 13:08:43 +00:00
8fb83b9446 Add end-to-end how-to guide + regenerate dashboard from a clean reset
Full reset validation: deleted weathermap-dashboard.json and the live
Grafana dashboard (dashboard-base.json untouched, it's the manual part).
Regenerated from scratch and reprovisioned -- confirms the first-ever-run
path (0 live positions found, full layered layout applied, all 4 panels'
queries resolve).

Documented the whole flow in scripts/README.md as a start-to-finish
how-to: credential acquisition (UI steps for the fiddly API paths --
Grafana service account token, datasource UID, plugin id), dry run,
provision, verification (UI walkthrough + API/Explore alternative),
re-running after topology changes, and a troubleshooting table. Added
GRAFANA_DATASOURCE_UID and the optional env vars to envrc.sample.
2026-07-10 12:58:15 +00:00
9b53ab0683 Fix inconsistent node rectangle height via compactVerticalLinks
Confirmed root cause against the installed plugin's real module.js (not
the #48 schema doc, which doesn't cover this): node height is driven by
max(anchors[Left].numLinks, anchors[Right].numLinks) whenever
compactVerticalLinks is false, which is why campus-leaf1 (3 links) and
campus-leaf2 (4 links) rendered at different heights despite the same
role. Width is unaffected by link count -- it's always recomputed from
the label text at render time, no override field exists.

Set compactVerticalLinks: true on every generated node, which makes
height a constant (fontSize + 2*padding.vertical) regardless of link
count, for every node (padding/fontSize are already uniform fabric-wide).

Refs #54
2026-07-10 12:50:12 +00:00
fcd7ea2567 Layered default layout by hostname role + preserve live node positions
Default node position for spine/core/border-leaf/leaf/access is now a
Y-tier by role (parsed from hostname, same trust level as the site
parsing from #49) with X grouped by site within each tier, replacing
the flat site-grid heuristic.

Position specifically is now read from the live Grafana dashboard before
computing anything, so a node manually drag-and-dropped in the UI keeps
its position across regeneration -- only nodes with no live position yet
(new devices, or first-ever run) get the layered default. Devices removed
from the topology are simply absent from this run's output, so no
orphaned position/link reference is possible.

Refs #53
2026-07-10 10:40:42 +00:00
e73b789f92 Add sample environment file with Grafana and IPFabric credentials 2026-07-10 10:20:29 +00:00
632d146368 Split weathermap generation from dashboard composition
generate_weathermap.py now emits only the weathermap panel (targets +
options.weathermap) and merges it into a manually-authored dashboard base
(configs/grafana/dashboard-base.json) at a reserved slot panel, keeping
the base's gridPos so layout stays manual. The BGP sessions table,
ports/interfaces table, throughput graphs, and template variables move
out of the script entirely into that base file.

Verified zero regression: merged output is identical to the prior
generator-only output except for JSON key ordering, and all panel
queries re-validated via /api/ds/query.

Refs #52
2026-07-10 10:12:07 +00:00
dba06c1607 Exclude Management0 from per-site throughput panel
gNMI telemetry traffic on the OOB management port swamped fabric traffic
in the site-aggregate sums, producing a misleading ~10x in/out asymmetry
that read as a real traffic anomaly.

Closes #51
2026-07-10 09:56:07 +00:00
b726848da0 Guard VNI tooltip join against transient duplicate series
Wrap the group_left RHS in max by (device, vlan) so a Prometheus restart
or relabel change (old/new label-set series briefly coexisting in the
staleness window) can't trip PromQL's many-to-many matching error.

Closes #50
2026-07-10 09:51:48 +00:00
b03464d0df Extend weathermap dashboard with BGP/ports tables, per-site throughput, fix node status query
Fix node.statusQuery colliding legends: multi-neighbor devices previously
sourced from raw per-neighbor BGP session-state series that collide under
one legend, so an arbitrary neighbor won. Replace with a combined
device-up * worst-BGP-session query per device, with an explicit fallback
so zero-BGP devices (access switches) read as neutral/OK.

Add site label via Prometheus relabel (derived from device naming
convention) instead of per-query label_replace(). Add site/device template
variables, BGP sessions table, ports/interfaces table (Grafana merge
transform, not PromQL join), and per-site throughput graphs.

Refs #49
2026-07-10 09:45:40 +00:00
3c680a2b17 Move weathermap generator docs to scripts/README.md
Root README now just links to it. Also updates the default
GRAFANA_WEATHERMAP_PLUGIN_ID to the fork actually installed
(tamirsuliman-weathermap-panel), confirmed while validating #48.

Refs #48
2026-07-09 17:18:40 +00:00
36c93d9ecd Fix missing/wrong anchor fields crashing the weathermap panel
tamirsuliman-weathermap-panel (the plugin actually installed, not the
allamiro fork the schema research was done against) requires node.anchors
-- a numLinks/numFilledLinks tally per anchor position -- and expects
link.sides.*.anchor as the plugin's numeric TS enum value (Center=0,
Top=1, Bottom=2, Left=3, Right=4), not an anchor name string. Omitting
anchors entirely (per the "safe to omit, auto-defaulted" schema-research
note, which turns out to be fork-specific) crashed the panel on load with
"TypeError: undefined is not an object (evaluating 'i.anchors[0]')".

Enum values reverse-engineered from the installed plugin's module.js.

Refs #48
2026-07-09 17:13:27 +00:00
0aff25f509 Fix PromQL regex escaping for hyphenated hostnames
re.escape() escapes '-' as '\-', which Python's regex engine accepts
but PromQL's RE2 engine rejects outright (every hostname in this lab
is hyphenated, e.g. dc-leaf1). All 4 panel targets were failing with
"unknown escape sequence U+002D" until now. Also swaps the dashboard
to the newly-created NetLab datasource, which actually has gnmic data
(the previously-wired external Prometheus datasource had none).

Refs #48
2026-07-09 17:08:51 +00:00
f711210379 Generate weathermap-ng panel config from IPFabric topology
Adds scripts/generate_weathermap.py: fetches device inventory and
connectivity-matrix from IPFabric, cross-checks IPFabric's abbreviated
interface names against the live gnmic exporter, and emits a Grafana
dashboard-as-code JSON (configs/grafana/weathermap-dashboard.json) with
the weathermap-ng panel wired to explicit legendFormat-resolved queries
for BGP status, interface tx/rx, and VXLAN MAC-per-VNI.

Refs #48
2026-07-09 16:48:40 +00:00
1f8a3ef6d6 Deploy containerized Prometheus for gnmic telemetry
Add prometheus node to the Containerlab topology, scraping the gnmic
exporter (172.16.0.70:9273) at 5s interval with relabeling to clean
device/interface/neighbor_address/vlan/mac_address/afi_safi labels.
Validated against BGP and system metrics confirmed in #44. Existing
external Prometheus instance stays untouched in parallel.

Refs #45
2026-07-09 14:42:53 +00:00
b6a49bfeac Add CLAUDE.md with project conventions and guidelines 2026-07-09 13:33:58 +00:00
71cc8de7d5 Integrate gnmic for gNMI telemetry collection
Add gnmic container node subscribing to interface, BGP, system, and
VXLAN gNMI paths across all Arista cEOS nodes, exposed via a
Prometheus exporter. gNMI runs in plaintext (no SSL profile on
management api gnmi), so insecure:true is used instead of TLS.

Refs #43, Refs #44
2026-07-09 13:33:21 +00:00
Damien
d12e057bc8 Remove outdated core reworked diagram 2026-07-09 11:01:36 +02:00
Damien
d3b59a02e9 Remove old Core.svg diagram 2026-07-01 17:22:39 +02:00
Damien
553c713d17 Remove HomeLab v1 diagram 2026-06-21 16:14:56 +02:00
Damien
3104d7ea63 Add HomeLab v1 infrastructure diagram 2026-06-12 11:36:12 +02:00