Volver a la wiki

Port Assignment Guide

Port Assignment Guide

System for mapping discovered devices to physical switch ports in racks. Version: v1.0.39 (13-03-2026)


1. Overview

The Port Assignment System connects the logical world (discovered DeviceProfiles such as APs, cameras, and IoT devices) to the physical world (switch ports mounted in racks). Each assignment records which profile is plugged into which port on which switch.

Why it matters:


2. Architecture

Model: PortConnection

Located in network/models.py:

FieldTypeDescription
organizationFK → OrganizationTenant isolation
deviceFK → racks.DeviceThe switch (rack-mounted device with ports)
port_keyCharField(10)Port identifier from device.model_data.ports (e.g. "1", "sfp_1")
profileOneToOneField → DeviceProfileThe discovered device assigned to this port
notesCharField(255)Optional free-text note (e.g. “Lobby AP uplink”)
created_atDateTimeFieldAuto-set on creation

Constraints

ConstraintMechanismEffect
One port, one profileunique_together = [('device', 'port_key')]A physical port cannot have two profiles
One profile, one portOneToOneField on profileA profile cannot be assigned to two ports
Tenant isolationorganization FK + filtered queriesUsers only see their own connections

Data source for ports

Port metadata comes from device.model_data (JSON), specifically the ports dictionary. Each key is a port identifier and the value contains label, admin_status, oper_status, and speed. This data is populated during Auto-Provision SNMP discovery.


3. API Reference

All endpoints are under /api/network/ and require authentication. Tenant context is derived from the authenticated user’s organization.

3.1 List Connections

MethodGET
URL/api/network/port-connections
Query paramsdevice_id (optional), profile_id (optional)

Response 200: Array of PortConnectionOut

FieldTypeDescription
idintConnection ID
device_idintSwitch device ID
device_namestringSwitch name
rack_idintRack ID
rack_namestringRack name
port_keystringPort identifier
port_labelstringHuman-readable port label
profile_idintAssigned profile ID
profile_hostnamestringProfile hostname or IP
profile_ipstringProfile IP address
profile_device_typestringProfile device type (access_point, switch, router, other, etc.)
notesstringUser notes
created_atstringISO 8601 timestamp

Example:

GET /api/network/port-connections?device_id=42

3.2 Create Connection

MethodPOST
URL/api/network/port-connections

Request body (PortConnectionIn):

FieldTypeRequiredDescription
device_idintYesSwitch device ID
port_keystringYesPort key from device’s model_data
profile_idintYesDeviceProfile to assign
notesstringNoOptional note

Response 200: PortConnectionOut (the created connection)

Response 400: {"error": "..."} — see Validation Rules

Example:

POST /api/network/port-connections
{
    "device_id": 42,
    "port_key": "12",
    "profile_id": 107,
    "notes": "3rd floor AP uplink"
}

3.3 Delete Connection

MethodDELETE
URL/api/network/port-connections/{connection_id}

Response 200: {"success": true}

Response 404: {"error": "Connection not found"}

3.4 List Switches

MethodGET
URL/api/network/port-connections/switches
Query paramsrack_id (optional)

Returns all rack-mounted devices that have a ports dictionary in their model_data. These are the devices that can receive port assignments.

Response 200: Array of SwitchOut

FieldTypeDescription
device_idintDevice ID
device_namestringDevice name
rack_idintRack ID
rack_namestringRack name
port_countintTotal number of ports

3.5 Available Ports

MethodGET
URL/api/network/port-connections/available-ports/{device_id}

Returns unoccupied ports for a given switch device, sorted numerically.

Response 200: Array of AvailablePortOut

FieldTypeDescription
port_keystringPort identifier
labelstringHuman-readable label
admin_statusstringAdministrative status
oper_statusstringOperational status
speedstringPort speed

3.6 Suggest Assignment (LLDP/CDP)

MethodGET
URL/api/network/port-connections/suggest/{profile_id}

Auto-suggests a switch port based on the profile’s LLDP/CDP neighbor data.

Response 200: SuggestionOut

FieldTypeDescription
device_idint or nullSuggested switch device ID
device_namestring or nullSuggested switch name
rack_namestring or nullRack containing the switch
port_keystring or nullSuggested port key
confidenceint0-100 confidence score
reasonstringHuman-readable explanation

4. LLDP/CDP Auto-Match

The suggestion algorithm lives in network/services/port_suggestion.py. It attempts to match a profile to a physical switch port using LLDP/CDP neighbor data collected during discovery.

Algorithm steps

  1. Read neighbors: Collect entries from profile.lldp_neighbors and profile.cdp_neighbors.
  2. Match hostname: For each neighbor, look for a DeviceProfile in the same organization where hostname matches the neighbor’s neighbor_hostname (case-insensitive) AND has a linked_device (meaning it is mapped to a rack device).
  3. Parse port key: Extract the numeric port identifier from the neighbor’s interface description using regex patterns that handle Cisco-style names (GigabitEthernet0/12, Gi1/0/24, Fa0/1), generic Port N, and plain numbers.
  4. Check availability: Verify the parsed port is not already occupied by another PortConnection.
  5. Return confidence score:
ScenarioConfidenceMeaning
Switch matched + port parsed + port available90High confidence, ready to assign
Switch matched + port not parseable50Switch found but manual port selection needed
Switch matched + port already occupied30Conflict detected, needs manual review
No matching switch found0No suggestion available

Supported interface name formats


5. Frontend Integration

PortAssignModal

Located in static/js/services/PortAssignModal.js. A reusable modal with cascading dropdowns.

Invocation:

PortAssignModal.show(profileId, profileName, onAssigned);
ParameterTypeDescription
profileIdnumberThe DeviceProfile ID to assign
profileNamestringDisplay name for the modal title
onAssignedfunctionCallback after successful assign/unassign
  1. Rack dropdown: Loads all racks via /api/racks/list.
  2. Switch dropdown: Enabled after rack selection. Loads switches in that rack via the switches endpoint.
  3. Port dropdown: Enabled after switch selection. Loads available (unoccupied) ports via the available-ports endpoint.
  4. Check LLDP button: Calls the suggest endpoint. If confidence >= 50, auto-selects rack, switch, and port in the dropdowns.
  5. Assign button: Enabled after port selection. POSTs the connection.
  6. Current assignment: If the profile already has a connection, a blue info bar is shown with an “Unassign” button.

Where it appears

LocationTriggerNotes
Wireless AP detail tab“Assign Port” button (btn-warning) in headerOpens modal + shows Port Connection info panel below Hardware section
Wireless sidebarClick on .port-badge next to an APOpens modal for that AP’s profile
Wireless Group Members table“Assign” button in member rows without assignmentOpens modal for the selected AP
Observatory manual target tab“Assign Port” button (btn-warning) in tab headerResolves DeviceProfile by IP, then opens modal
Rack Editor port tableHostname link in Description/Device columnsNavigates to Wireless or Observatory

6. Validation Rules

The POST /api/network/port-connections endpoint enforces these rules before creating a connection:

RuleError message
Device must belong to the user’s organization"Device not found"
Device must be in a non-deleted rack"Device not found"
port_key must exist in device.model_data.ports"Port \"X\" not found on device"
Profile must belong to the user’s organization"Profile not found"
Port must not already have a connection"Port X is already assigned"
Profile must not already be assigned elsewhere"This profile is already assigned to another port"

To reassign a profile to a different port, first delete the existing connection, then create a new one. The modal handles this via the “Unassign” button.


7. Visual Integration

Port badges

Assigned profiles display a .port-badge element showing the switch name and port label. Clicking the badge opens the PortAssignModal for reassignment.

Unassigned profiles show a muted badge (or no badge) indicating no port mapping exists.

Locations with port badges:

Rack Editor — Port Table

When viewing a switch in the Rack Editor properties panel, the port table includes:

CSS

FileClasses
static/css/pages/wireless.css.port-badge, .port-badge:hover
static/css/pages/observatory.css.port-badge, .obs-assign-port-btn, .obs-port-info
static/css/pages/editor.css.port-col-device, .port-connected-device, .port-connected-device:hover

Files Reference

FilePurpose
network/models.pyPortConnection model definition
network/api/port_connections.py6 API endpoints + schemas (incl. profile_device_type)
network/api/profiles.pyip filter param on profiles list endpoint
network/services/port_suggestion.pyLLDP/CDP auto-match algorithm
static/js/services/PortAssignModal.jsFrontend modal (Rack/Switch/Port cascade)
static/js/pages/wireless/WirelessDetail.js“Assign Port” button + Port Connection info panel in AP detail tab
static/js/pages/observatory.jsassignPort() + _loadObsPortInfo() for manual targets
static/js/pages/observatory/ObservatoryTabs.js“Assign Port” button in manual target tab header
static/js/editor/PropertiesPanelRenderer.jsDevice column + Description hostname links + loadPortConnections()
static/js/editor/PropertiesPanelEvents.jsClick guard for <a> links in port table rows
static/js/editor/ui_panels.jsCalls loadPortConnections() after port table render
static/css/pages/wireless.css.port-badge styles
static/css/pages/observatory.css.port-badge, .obs-assign-port-btn styles
static/css/pages/editor.css.port-col-device, .port-connected-device styles

Last updated: 13-03-2026

Véase también

Subir