Fix dropped-cable bug, tag VLAN 214 on FS.com switch uplinks
Found while wiring up VLAN 214 on switch uplink ports: export_topology.py deduped edges by DEVICE PAIR, so when a switch had two real cables to the same neighboring device (very common here -- most FS.com field switches run both SFP ports 9 and 10 into the same local patch panel before fanning out from its rear side) only one of the two cables survived into the graph. 43 real physical links across 30 device pairs were silently missing from the diagram. - export_topology.py: edges keyed per Cable (cable_id), never deduped by device pair. Edge count 80 -> 123. - generate_drawio.py: the tree-layout DFS had a matching bug -- a node's neighbor list wasn't deduped before recursing, so a parallel edge to an already-visited node got walked a second time, found no unvisited children, and got counted as a phantom extra leaf. One phantom leaf per redundant cable was inflating page height for no reason (bogus page height >16000px, clipped by draw.io's render cap, before this fix). NetBox changes (per user): all 42 FS.com IES3110-8TFP-R field switches' SFP ports (9 and 10, whichever are actually cabled -- chain-end switches only use port 9) are now interface.mode='tagged' with untagged_vlan=214 (Switch Management), the native VLAN on what the user confirmed are redundant trunk uplinks. 63 interfaces updated; the diagram now shows '9·V214' style tags on those connectors. Department-VLAN tagging (the other half of each trunk) is intentionally not done yet -- needs a real per-switch mapping, not a guess. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NM3nivbufxEWiKKmatEtEe
This commit is contained in:
@@ -80,7 +80,7 @@ cables = Cable.objects.filter(
|
||||
terminations__termination_type__model__in=["interface", "frontport", "rearport"],
|
||||
).distinct()
|
||||
|
||||
edges = {}
|
||||
edges = []
|
||||
for c in cables:
|
||||
terms = list(c.terminations.all())
|
||||
a_side = [t for t in terms if t.cable_end == "A"]
|
||||
@@ -92,11 +92,17 @@ for c in cables:
|
||||
if not da or not db:
|
||||
continue
|
||||
if da.id in touched_devices and db.id in touched_devices and da.id != db.id:
|
||||
key = tuple(sorted((da.id, db.id)))
|
||||
edges[key] = {
|
||||
# One entry PER CABLE (not deduped by device pair) -- a device
|
||||
# pair can be joined by more than one real cable (redundant
|
||||
# fiber pairs, or a switch with two local jumpers into the
|
||||
# same on-site patch panel that fan out to different places
|
||||
# from there), and collapsing those to one edge silently
|
||||
# drops real physical links.
|
||||
edges.append({
|
||||
"cable_id": c.id,
|
||||
"a": da.id, "a_port": ta.termination.name, "a_vlan": port_vlans(ta.termination),
|
||||
"b": db.id, "b_port": tb.termination.name, "b_vlan": port_vlans(tb.termination),
|
||||
}
|
||||
})
|
||||
|
||||
devs = Device.objects.filter(id__in=touched_devices).select_related(
|
||||
"site", "role", "device_type"
|
||||
@@ -115,7 +121,7 @@ out = {
|
||||
}
|
||||
for d in devs
|
||||
],
|
||||
"edges": list(edges.values()),
|
||||
"edges": edges,
|
||||
"vlans": [
|
||||
{"vid": v.vid, "name": v.name, "description": v.description,
|
||||
"prefixes": [str(p.prefix) for p in v.prefixes.all()],
|
||||
|
||||
Reference in New Issue
Block a user