NetBox plugin for automatic fiber cabling over structured cabling (end-to-end free-fiber selection).
Project description
netbox-plugin-autocabling
NetBox plugin for automatic fiber cabling over structured cabling. Give it two endpoints — two racks or two device ports — and it finds the free fiber channel end to end across the existing backbone (patch panels, trunks, modules) and creates the patch cables that connect them. Deterministic, idempotent, and module-agnostic.
It also audits the backbone: per-panel capacities, saturation, and a data-quality dashboard that surfaces the inconsistencies the routing engine would otherwise hit.
Compatibility
| NetBox | Python | netbox-plugin-autocabling |
|---|---|---|
| 4.5 – 4.6 | ≥ 3.12 | 0.1.x |
See COMPATIBILITY.md.
Installation
pip install netbox-plugin-autocabling
# configuration.py — note the underscore: the pip package is netbox-plugin-autocabling,
# but the importable plugin (used here) is netbox_autocabling
PLUGINS = ["netbox_autocabling"]
python manage.py migrate netbox_autocabling
How it works
The plugin builds a channel graph of a site from the structured cabling: rear ports,
their modules (media: SMF/MMF), the rear↔rear trunks between racks, and the
front-port mappings used to patch through. Only panels carrying the backbone tag
(trunk_tag, default autocable-backbone) are routable, so you decide which cabling the
engine is allowed to use.
Routing happens at the rack + media level (module-agnostic): the engine selects a free fiber end to end, then emits the concrete patch cables (front-port to front-port at each hop, equipment port at the ends). The graph is cached per site and invalidated automatically on any cable, termination or backbone-tag change.
Features
Port-to-port auto-cabling
Cable two device ports (Interface / FrontPort / RearPort) over the backbone.
- New cabling (sidebar Auto-cabling → Cabling → New cabling): pick source & destination device/port + media → preview (annotated path diagram, the exact cables to create, human-readable status, bridge/overflow alerts) → execute.
- ⚡ Auto-cable from this port button on any uncabled Interface / FrontPort page.
- Every execution records a cabling job (history) with the created cable ids.
Rack-to-rack auto-cabling
Cable two racks end to end from the CLI (read-only by default, --create to write,
--dry-run to show the plan without writing):
python manage.py autocable <rackA> <rackB> SMF --site Site-1 --create
Routing rules
- Same rack → direct intra-rack cable.
- Satellite rack (no panel of its own) → enters the backbone via a panel in the same room (intra-room adjacency; toggleable).
- Multi-hop reroute → a saturated direct trunk is automatically routed around over
free trunks on a longer path; the result is
exhaustedonly when no free path exists. - Saturation overflow → when a rack's own trunks are saturated, routing can fall back
— as a last resort — to a co-located rack via a same-room cable to pull
(confirmation required; toggleable via
saturation_overflow). - Same-room bridge → if two disjoint backbone segments meet in a room, a direct
panel-to-panel cable can join them in the middle of the path. A bridge is a physical
cable to pull, so it is only preferred over an all-trunk path when it avoids a detour of
at least
bridge_detour_thresholdhops per bridge (it is still used unconditionally when it is the only way). Which racks may be bridged can be restricted (see Allowed bridges). - Same room, no structured path → a direct device-to-device cable is proposed
(confirmation; toggleable via
allow_direct). - Otherwise
no_pathis explained: rack off backbone, two unconnected islands, or a path available only in the other media.
CSV batch
Cable many pairs at once (Auto-cabling → Cabling → CSV batch) with collision-free allocation (each row reserves its fibers so later rows don't reuse them):
src_device,dest_device,src_port,dest_port,media
Analyze → per-row path, duplicate / bridge / overflow flags → execute.
Allowed bridges (per-location whitelist)
By default every pair of co-located racks may be bridged. A location with ≥ 1 allowed bridge becomes restricted: only its listed rack pairs may be bridged — useful to forbid pulling a fiber between the two most distant racks of a large room. A location with none stays open (e.g. floor rooms).
Managed under Auto-cabling → Configuration → Allowed bridges (guided site → room → racks form), with a native CSV/JSON/YAML import:
site,location,rack_a,rack_b
site/location are optional but recommended — they scope the rack lookup so same-named
racks in different rooms are disambiguated.
Capacities audit
Auto-cabling → Cabling → Capacities: per-panel free / total fibers with a fill bar, filterable by location (whole subtree) / rack / media, plus CSV export. Patch-panel and rack pages also show backbone cards — next-hop trunks with a traffic-light saturation bar and linked neighbor racks.
Health / data-quality dashboard
Auto-cabling → Cabling → Health: per-site structural overview (racks on backbone, trunks, bridges, media split, disconnected islands, off-backbone racks) plus the data anomalies the routing engine silently discards, each row linked to its NetBox object:
- mixed-media trunks — a trunk with SMF on one end and MMF on the other;
- self-referencing trunks — a panel cabled to itself;
- dangling trunks — a rear↔rear cable with a single visible endpoint;
- unmapped module rear ports — a rear port with no front mapping (unusable fiber).
It also lists, as informational (not anomalies), legitimate intra-rack cross-connects (rear↔rear cables between two panels of the same rack) — valid cabling that simply doesn't participate in inter-rack routing.
The same scan is available headless:
python manage.py cabling_anomalies --site Site-1
Work order & rollback
From a job (or a batch / a selection): export an Excel work order for the field technician, and roll back a job (deletes exactly the cables it created).
Search
Cabling jobs are indexed in NetBox global search, and a background anomaly-scan job can be scheduled.
Settings
Static defaults in the configuration file:
PLUGINS_CONFIG = {
"netbox_autocabling": {
"trunk_tag": "autocable-backbone", # routable backbone panels
"cable_types": {"SMF": "smf-os2", "MMF": "mmf-om4"}, # cable type created per media
}
}
A Settings page (Auto-cabling → Configuration → Settings) overrides these at runtime,
without a restart. Resolution order: Settings page → PLUGINS_CONFIG → built-in
default.
| Setting | Effect |
|---|---|
intra_room_adjacency |
satellite racks enter the backbone via a same-room panel |
saturation_overflow |
allow borrowing a co-located rack when own trunks are full |
allow_direct |
propose a direct cable when there is no structured path in the room |
bridge_detour_threshold |
hops/bridge a bridge must save to win over an all-trunk path (default 3; 1 = bridge wins as soon as it is shorter) |
trunk_tag |
slug of the backbone tag |
cable_types |
cable type created per media, e.g. {"SMF": "smf-os2", "MMF": "mmf-om5"} |
default_media |
media preselected in the cabling form |
REST API
# plan (read-only)
curl -X POST .../api/plugins/autocabling/cabling-jobs/plan/ \
-d '{"port_a": 1234, "port_b": 5678, "media": "SMF"}'
# create (requires dcim.add_cable)
curl -X POST .../api/plugins/autocabling/cabling-jobs/cable/ \
-d '{"port_a": 1234, "port_b": 5678, "media": "SMF"}'
Endpoints are also exposed for cabling-jobs, allowed-bridges and settings.
Python API
from netbox_autocabling.services import plan_port_to_port, create_port_cabling
from netbox_autocabling.graph_cache import get_graph
plan = plan_port_to_port(if_a, if_b, "SMF", graph=get_graph(if_a.device.site))
if plan.ok:
create_port_cabling(plan) # idempotent, type-agnostic
Seeding a test site
All idempotent and --dry-run compatible — instantiate switches on a site that has none,
then tag the backbone:
python manage.py autocable_seed_device_types # generic Cisco device types
python manage.py autocable_seed_switches --site site-1 # one switch per rack
python manage.py autocable_tag_backbone --site site-1 # tag the backbone panels
Development
Tooling is standardized on uv:
uvx ruff check .
uv build
python manage.py test netbox_autocabling
CI (.github/workflows/ci.yml) runs the suite against NetBox 4.5 and 4.6 plus a
netbox-plugin-audit pass.
License
Apache-2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file netbox_plugin_autocabling-0.1.0.tar.gz.
File metadata
- Download URL: netbox_plugin_autocabling-0.1.0.tar.gz
- Upload date:
- Size: 100.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15bccb4d7b546c9481710dcbccaaac79d684858d24c38404210c9e14aa536e20
|
|
| MD5 |
4c5a809484e6dd06341f21ca71fec78b
|
|
| BLAKE2b-256 |
ba2bbb3fa74ad36fcac384103cc007cbb5618102e28b95bd651cd334d6b79dd2
|
Provenance
The following attestation bundles were made for netbox_plugin_autocabling-0.1.0.tar.gz:
Publisher:
release.yml on bpapaylle/netbox-plugin-autocabling
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
netbox_plugin_autocabling-0.1.0.tar.gz -
Subject digest:
15bccb4d7b546c9481710dcbccaaac79d684858d24c38404210c9e14aa536e20 - Sigstore transparency entry: 1859670297
- Sigstore integration time:
-
Permalink:
bpapaylle/netbox-plugin-autocabling@85b84c853ccfe8f977be14469a2ece093e265175 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bpapaylle
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@85b84c853ccfe8f977be14469a2ece093e265175 -
Trigger Event:
push
-
Statement type:
File details
Details for the file netbox_plugin_autocabling-0.1.0-py3-none-any.whl.
File metadata
- Download URL: netbox_plugin_autocabling-0.1.0-py3-none-any.whl
- Upload date:
- Size: 118.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4eb270cf651374b2dec0e9c302d057cbca650f0fd5eea769cac3136f8e6b7724
|
|
| MD5 |
8e177acf13221a11004b8a05b15ed3e7
|
|
| BLAKE2b-256 |
10d8e1839ab490dda0bc51031035912c75d348f1c183c8b73ec435a8b0a46f18
|
Provenance
The following attestation bundles were made for netbox_plugin_autocabling-0.1.0-py3-none-any.whl:
Publisher:
release.yml on bpapaylle/netbox-plugin-autocabling
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
netbox_plugin_autocabling-0.1.0-py3-none-any.whl -
Subject digest:
4eb270cf651374b2dec0e9c302d057cbca650f0fd5eea769cac3136f8e6b7724 - Sigstore transparency entry: 1859670408
- Sigstore integration time:
-
Permalink:
bpapaylle/netbox-plugin-autocabling@85b84c853ccfe8f977be14469a2ece093e265175 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bpapaylle
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@85b84c853ccfe8f977be14469a2ece093e265175 -
Trigger Event:
push
-
Statement type: