Allow arbitrary connector/position counts for cable profiles #156

Open
opened 2026-04-05 16:22:24 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @jsenecal on 3/12/2026

NetBox version

v4.5.5

Feature type

Change to existing functionality

Proposed functionality

Make cable profiles accept arbitrary connector/position combinations instead of requiring a hardcoded class for each one. Currently, NetBox ships 26 profile classes (e.g. single-1c2p, trunk-4c4p). Adding a new combination requires modifying source code in three places: cable_profiles.py, choices.py, and the profile_class property in models/cables.py.

Slug-based parsing for symmetric profiles:

Single and trunk profiles follow a predictable pattern - both cable ends have identical connector/position layouts. Instead of requiring a dedicated class for each combination, the Cable.profile_class property would parse the slug format {type}-{C}c{P}p and dynamically generate the profile class:

  • single-1c32p -> a_connectors = {1: 32}, b_connectors = {1: 32}
  • trunk-4c16p -> a_connectors = {1: 16, 2: 16, 3: 16, 4: 16}, b_connectors = same

The generated classes use the existing BaseCableProfile mechanics. No changes to tracing, validation, or termination assignment logic.

Complex profiles stay hardcoded:

Breakout and shuffle profiles have non-linear position mappings that cannot be derived from the slug. These keep their existing dedicated classes and are looked up by exact slug before the parser runs.

Validation:

The profile field on Cable drops the choices=CableProfileChoices constraint at the model level. Validation moves to Cable.clean():

  1. Check if slug matches a known complex profile (breakout/shuffle) - valid
  2. Check if slug matches ^(single|trunk)-(\d+)c(\d+)p$ with connectors <= CABLE_CONNECTOR_MAX (256) and positions <= CABLE_POSITION_MAX (8192) - valid
  3. Otherwise - ValidationError

UI choices stay curated:

CableProfileChoices remains on form fields and filter widgets to control what the dropdown shows. Admins can extend it via FIELD_CHOICES in configuration.py as they already can with any ChoiceSet. The API and import paths accept any slug that passes validation.

Caching:

Generated profile classes are cached in a module-level dict keyed by slug so repeated access (e.g. during bulk path tracing) does not rebuild them.

CABLE_POSITION_MAX increase:

The current CABLE_POSITION_MAX of 1024 is too low for high-density fiber. Sumitomo Electric manufactures ribbon cables up to 6912 fibers. The constant should increase to 8192 to cover current real-world maximums with headroom.

Summary of file changes:

  • dcim/constants.py: CABLE_POSITION_MAX from 1024 to 8192
  • dcim/cable_profiles.py: add slug parser and profile class factory with caching
  • dcim/models/cables.py: remove choices= from profile field, update profile_class property to use factory, update clean() to validate slug format and bounds
  • dcim/choices.py: no change (stays as UI convenience)
  • Forms/filtersets: keep choices=CableProfileChoices on widgets
  • API serializer: relax to accept any valid slug
  • Migration: alter profile field, alter positions ArrayField max validator

Use case

The current fixed set of cable profiles covers common data center patching scenarios but falls short for outside plant (OSP) fiber infrastructure, where cable configurations vary widely and fiber counts far exceed what the built-in profiles support.

OSP loose tube cables group fibers into buffer tubes, typically 12 fibers per tube. A 144-fiber loose tube cable has 12 tubes of 12 fibers. Depending on how the cable is terminated, this could be modeled as single-1c144p (all fibers through one logical connector) or trunk-12c12p (one connector per buffer tube). A 288-fiber cable might be single-1c288p, trunk-24c12p, or trunk-12c24p. None of these exist in the built-in set.

OSP ribbon cables stack flat ribbons (12 or 24 fibers each) to achieve much higher densities. A 576-fiber ribbon cable might have 24 ribbons of 24 fibers. Sumitomo Electric's SpiderWeb Ribbon (SWR) technology pushes this to 3456 and 6912 fibers in a single cable. Modeling these as profiles requires position counts well beyond the current 16-position maximum.

Splice closures and fiber distribution hubs in OSP networks join these cables together. Accurate path tracing through splice points requires cable profiles that reflect the actual tube/ribbon structure of each cable segment. Without matching profiles, operators are forced to either leave cables unprofiled (losing trace accuracy) or split a single physical cable into multiple logical cables to fit available profiles (misrepresenting the infrastructure).

Every telco, utility, and hyperscaler has different cable specs from different manufacturers. There is no fixed set of profiles that covers all real-world OSP configurations. Making profiles parametric lets operators model their actual plant without forking NetBox or maintaining patches.

The change preserves full backward compatibility - all existing slugs and profiles continue to work identically.

Database changes

One migration:

  • Cable.profile: remove choices= parameter from the CharField definition (the field itself stays CharField(max_length=50, blank=True))
  • CableTermination.positions: update ArrayField validator from max 1024 to max 8192

No new models or fields.

External dependencies

None.

*Originally created by @jsenecal on 3/12/2026* ### NetBox version v4.5.5 ### Feature type Change to existing functionality ### Proposed functionality Make cable profiles accept arbitrary connector/position combinations instead of requiring a hardcoded class for each one. Currently, NetBox ships 26 profile classes (e.g. `single-1c2p`, `trunk-4c4p`). Adding a new combination requires modifying source code in three places: `cable_profiles.py`, `choices.py`, and the `profile_class` property in `models/cables.py`. **Slug-based parsing for symmetric profiles:** Single and trunk profiles follow a predictable pattern - both cable ends have identical connector/position layouts. Instead of requiring a dedicated class for each combination, the `Cable.profile_class` property would parse the slug format `{type}-{C}c{P}p` and dynamically generate the profile class: - `single-1c32p` -> `a_connectors = {1: 32}`, `b_connectors = {1: 32}` - `trunk-4c16p` -> `a_connectors = {1: 16, 2: 16, 3: 16, 4: 16}`, `b_connectors` = same The generated classes use the existing `BaseCableProfile` mechanics. No changes to tracing, validation, or termination assignment logic. **Complex profiles stay hardcoded:** Breakout and shuffle profiles have non-linear position mappings that cannot be derived from the slug. These keep their existing dedicated classes and are looked up by exact slug before the parser runs. **Validation:** The `profile` field on `Cable` drops the `choices=CableProfileChoices` constraint at the model level. Validation moves to `Cable.clean()`: 1. Check if slug matches a known complex profile (breakout/shuffle) - valid 2. Check if slug matches `^(single|trunk)-(\d+)c(\d+)p$` with connectors <= `CABLE_CONNECTOR_MAX` (256) and positions <= `CABLE_POSITION_MAX` (8192) - valid 3. Otherwise - `ValidationError` **UI choices stay curated:** `CableProfileChoices` remains on form fields and filter widgets to control what the dropdown shows. Admins can extend it via `FIELD_CHOICES` in `configuration.py` as they already can with any `ChoiceSet`. The API and import paths accept any slug that passes validation. **Caching:** Generated profile classes are cached in a module-level dict keyed by slug so repeated access (e.g. during bulk path tracing) does not rebuild them. **CABLE_POSITION_MAX increase:** The current `CABLE_POSITION_MAX` of 1024 is too low for high-density fiber. Sumitomo Electric manufactures ribbon cables up to 6912 fibers. The constant should increase to 8192 to cover current real-world maximums with headroom. **Summary of file changes:** - `dcim/constants.py`: `CABLE_POSITION_MAX` from 1024 to 8192 - `dcim/cable_profiles.py`: add slug parser and profile class factory with caching - `dcim/models/cables.py`: remove `choices=` from `profile` field, update `profile_class` property to use factory, update `clean()` to validate slug format and bounds - `dcim/choices.py`: no change (stays as UI convenience) - Forms/filtersets: keep `choices=CableProfileChoices` on widgets - API serializer: relax to accept any valid slug - Migration: alter `profile` field, alter `positions` ArrayField max validator ### Use case The current fixed set of cable profiles covers common data center patching scenarios but falls short for outside plant (OSP) fiber infrastructure, where cable configurations vary widely and fiber counts far exceed what the built-in profiles support. **OSP loose tube cables** group fibers into buffer tubes, typically 12 fibers per tube. A 144-fiber loose tube cable has 12 tubes of 12 fibers. Depending on how the cable is terminated, this could be modeled as `single-1c144p` (all fibers through one logical connector) or `trunk-12c12p` (one connector per buffer tube). A 288-fiber cable might be `single-1c288p`, `trunk-24c12p`, or `trunk-12c24p`. None of these exist in the built-in set. **OSP ribbon cables** stack flat ribbons (12 or 24 fibers each) to achieve much higher densities. A 576-fiber ribbon cable might have 24 ribbons of 24 fibers. Sumitomo Electric's SpiderWeb Ribbon (SWR) technology pushes this to 3456 and 6912 fibers in a single cable. Modeling these as profiles requires position counts well beyond the current 16-position maximum. **Splice closures and fiber distribution hubs** in OSP networks join these cables together. Accurate path tracing through splice points requires cable profiles that reflect the actual tube/ribbon structure of each cable segment. Without matching profiles, operators are forced to either leave cables unprofiled (losing trace accuracy) or split a single physical cable into multiple logical cables to fit available profiles (misrepresenting the infrastructure). Every telco, utility, and hyperscaler has different cable specs from different manufacturers. There is no fixed set of profiles that covers all real-world OSP configurations. Making profiles parametric lets operators model their actual plant without forking NetBox or maintaining patches. The change preserves full backward compatibility - all existing slugs and profiles continue to work identically. ### Database changes One migration: - `Cable.profile`: remove `choices=` parameter from the `CharField` definition (the field itself stays `CharField(max_length=50, blank=True)`) - `CableTermination.positions`: update `ArrayField` validator from max 1024 to max 8192 No new models or fields. ### External dependencies None.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#156