dcstephenson d275b7e821 Add NetBox-derived field switch topology (draw.io)
- export_topology.py: dumps switch + patch-panel cable graph from NetBox
  (Django shell, read-only)
- generate_drawio.py: renders topo_full.json as a draw.io diagram with
  natively-glued connectors (source/target by shape id, no hand-rolled
  glue formulas)
- topo_full.json + Field-Switch-Topology.drawio: current snapshot

Replaces the earlier hand-built .vsdx approach: plain-text format diffs
meaningfully in git, no Visio license needed to view/edit, and edges glue
natively instead of needing point-to-point formula hacks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NM3nivbufxEWiKKmatEtEe
2026-09-15 12:41:22 -05:00

Netbox

Generated documentation for the field-switch network, sourced from this utility's live NetBox instance. NetBox is the source of truth here, not this repo -- everything under topology/ is a build artifact, regenerated from NetBox and committed so history shows what the physical network changed, not just what someone drew.

topology/

file what it is
export_topology.py Run inside the NetBox Django shell. Walks every field/distribution switch's cable path (through patch panels and splice modules) and dumps the resulting device graph as JSON. Read-only.
topo_full.json Latest exported snapshot: devices (id, name, role, site, status) + edges (physical links, one per cable).
generate_drawio.py Pure-Python renderer: topo_full.json → Field-Switch-Topology.drawio. No NetBox access needed.
Field-Switch-Topology.drawio The diagram. Open at app.diagrams.net (or the desktop app, or the VS Code draw.io extension) -- free, no license needed.

Two distribution switches (fche-sw17a, dmo-lob-sw35a) anchor two fabrics; everything downstream is field switches daisy-chained through patch panels and fiber splice modules. A handful of switches sit outside both fabrics for a documented reason (spare/inventory, decommissioning, or planned/not-yet-installed) -- those are called out in their own box on the diagram rather than silently dropped.

Connectors in the .drawio file are glued by shape id (draw.io's native source/target reference on each edge) -- drag a switch or panel in the app and its links follow. That's different from this project's earlier Visio (.vsdx) attempt, where glue had to be hand-written as cell formulas because the format has no simpler mechanism; draw.io does this natively, which is a big part of why this repo uses it instead.

Regenerating

From the NetBox host (needs docker exec access to the NetBox container):

docker exec netbox-netbox-1 python3 /opt/netbox/netbox/manage.py shell \
    -c "$(cat topology/export_topology.py)" 2>/dev/null > topology/topo_full.json

python3 topology/generate_drawio.py topology/topo_full.json topology/Field-Switch-Topology.drawio

Commit both files together. The diff on topo_full.json is the real changelog -- it shows exactly which device or cable changed between two snapshots; the .drawio diff is mostly noise (coordinates) but is kept in sync so the rendered diagram never drifts from what NetBox actually says.

Gotchas learned the hard way

  • NetBox's cached cable path can go stale. If a switch's connected_endpoints comes back empty even though it's obviously cabled, try manage.py trace_paths --force before assuming the cable data itself is wrong -- it recomputes the path cache and doesn't touch any cable/termination records.
  • A patch panel's front↔rear pass-through has to be modeled explicitly (a PortMapping row). A splice module can have a perfectly good cable on both sides of a port and still fail to trace if that mapping is missing -- check FrontPort.objects.get(...).mappings.count() before assuming the far end really is disconnected.

Possible next step

export_topology.py talks to NetBox via the Django ORM (docker exec + manage.py shell), which only works run from the NetBox host itself. Swapping it for a NetBox REST API client (device/cable/interface endpoints + an API token) would let this regenerate from anywhere, including CI, without shell access to the container.

S
Description
No description provided
Readme 11 MiB
Languages
Python 88.6%
JavaScript 7.8%
HTML 3.6%