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:
- Physical-logical mapping: Know exactly where every device is physically connected.
- Troubleshooting: When a device goes offline, immediately identify the switch and port to check.
- Documentation: Maintain an accurate, up-to-date port map without spreadsheets.
- LLDP/CDP auto-match: Leverage neighbor discovery data to suggest assignments automatically.
2. Architecture
Model: PortConnection
Located in network/models.py:
| Field | Type | Description |
|---|---|---|
organization | FK → Organization | Tenant isolation |
device | FK → racks.Device | The switch (rack-mounted device with ports) |
port_key | CharField(10) | Port identifier from device.model_data.ports (e.g. "1", "sfp_1") |
profile | OneToOneField → DeviceProfile | The discovered device assigned to this port |
notes | CharField(255) | Optional free-text note (e.g. “Lobby AP uplink”) |
created_at | DateTimeField | Auto-set on creation |
Constraints
| Constraint | Mechanism | Effect |
|---|---|---|
| One port, one profile | unique_together = [('device', 'port_key')] | A physical port cannot have two profiles |
| One profile, one port | OneToOneField on profile | A profile cannot be assigned to two ports |
| Tenant isolation | organization FK + filtered queries | Users 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
| Method | GET |
| URL | /api/network/port-connections |
| Query params | device_id (optional), profile_id (optional) |
Response 200: Array of PortConnectionOut
| Field | Type | Description |
|---|---|---|
id | int | Connection ID |
device_id | int | Switch device ID |
device_name | string | Switch name |
rack_id | int | Rack ID |
rack_name | string | Rack name |
port_key | string | Port identifier |
port_label | string | Human-readable port label |
profile_id | int | Assigned profile ID |
profile_hostname | string | Profile hostname or IP |
profile_ip | string | Profile IP address |
profile_device_type | string | Profile device type (access_point, switch, router, other, etc.) |
notes | string | User notes |
created_at | string | ISO 8601 timestamp |
Example:
GET /api/network/port-connections?device_id=42
3.2 Create Connection
| Method | POST |
| URL | /api/network/port-connections |
Request body (PortConnectionIn):
| Field | Type | Required | Description |
|---|---|---|---|
device_id | int | Yes | Switch device ID |
port_key | string | Yes | Port key from device’s model_data |
profile_id | int | Yes | DeviceProfile to assign |
notes | string | No | Optional 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
| Method | DELETE |
| URL | /api/network/port-connections/{connection_id} |
Response 200: {"success": true}
Response 404: {"error": "Connection not found"}
3.4 List Switches
| Method | GET |
| URL | /api/network/port-connections/switches |
| Query params | rack_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
| Field | Type | Description |
|---|---|---|
device_id | int | Device ID |
device_name | string | Device name |
rack_id | int | Rack ID |
rack_name | string | Rack name |
port_count | int | Total number of ports |
3.5 Available Ports
| Method | GET |
| URL | /api/network/port-connections/available-ports/{device_id} |
Returns unoccupied ports for a given switch device, sorted numerically.
Response 200: Array of AvailablePortOut
| Field | Type | Description |
|---|---|---|
port_key | string | Port identifier |
label | string | Human-readable label |
admin_status | string | Administrative status |
oper_status | string | Operational status |
speed | string | Port speed |
3.6 Suggest Assignment (LLDP/CDP)
| Method | GET |
| 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
| Field | Type | Description |
|---|---|---|
device_id | int or null | Suggested switch device ID |
device_name | string or null | Suggested switch name |
rack_name | string or null | Rack containing the switch |
port_key | string or null | Suggested port key |
confidence | int | 0-100 confidence score |
reason | string | Human-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
- Read neighbors: Collect entries from
profile.lldp_neighborsandprofile.cdp_neighbors. - Match hostname: For each neighbor, look for a
DeviceProfilein the same organization wherehostnamematches the neighbor’sneighbor_hostname(case-insensitive) AND has alinked_device(meaning it is mapped to a rack device). - 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), genericPort N, and plain numbers. - Check availability: Verify the parsed port is not already occupied by another
PortConnection. - Return confidence score:
| Scenario | Confidence | Meaning |
|---|---|---|
| Switch matched + port parsed + port available | 90 | High confidence, ready to assign |
| Switch matched + port not parseable | 50 | Switch found but manual port selection needed |
| Switch matched + port already occupied | 30 | Conflict detected, needs manual review |
| No matching switch found | 0 | No suggestion available |
Supported interface name formats
GigabitEthernet0/1/12,Gi1/0/24,Fa0/1TenGigabitEthernet1/1,Te1/0/1Eth1/12,Port 24- Plain numeric (
12)
5. Frontend Integration
PortAssignModal
Located in static/js/services/PortAssignModal.js. A reusable modal with cascading dropdowns.
Invocation:
PortAssignModal.show(profileId, profileName, onAssigned);
| Parameter | Type | Description |
|---|---|---|
profileId | number | The DeviceProfile ID to assign |
profileName | string | Display name for the modal title |
onAssigned | function | Callback after successful assign/unassign |
Modal workflow
- Rack dropdown: Loads all racks via
/api/racks/list. - Switch dropdown: Enabled after rack selection. Loads switches in that rack via the switches endpoint.
- Port dropdown: Enabled after switch selection. Loads available (unoccupied) ports via the available-ports endpoint.
- Check LLDP button: Calls the suggest endpoint. If confidence >= 50, auto-selects rack, switch, and port in the dropdowns.
- Assign button: Enabled after port selection. POSTs the connection.
- Current assignment: If the profile already has a connection, a blue info bar is shown with an “Unassign” button.
Where it appears
| Location | Trigger | Notes |
|---|---|---|
| Wireless AP detail tab | “Assign Port” button (btn-warning) in header | Opens modal + shows Port Connection info panel below Hardware section |
| Wireless sidebar | Click on .port-badge next to an AP | Opens modal for that AP’s profile |
| Wireless Group Members table | “Assign” button in member rows without assignment | Opens modal for the selected AP |
| Observatory manual target tab | “Assign Port” button (btn-warning) in tab header | Resolves DeviceProfile by IP, then opens modal |
| Rack Editor port table | Hostname link in Description/Device columns | Navigates to Wireless or Observatory |
6. Validation Rules
The POST /api/network/port-connections endpoint enforces these rules before creating a connection:
| Rule | Error 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:
- Wireless sidebar: Next to each AP entry, showing the physical connection.
- Wireless AP detail tab: Port Connection info panel next to Hardware section — shows switch/rack/port or “Not assigned” with inline Unassign button.
- Observatory sidebar: On rack devices that have a port assignment.
- Observatory manual target tab: Port badge appears after assignment, replacing the “Assign Port” button.
- Group Members table: In the Wireless Groups detail view, each member row shows its port assignment or an “Assign” button.
Rack Editor — Port Table
When viewing a switch in the Rack Editor properties panel, the port table includes:
- Device column: Shows the hostname (orange text) of the assigned DeviceProfile as a clickable link.
- Description column: Appends the assigned hostname after existing port description text (separated by
·). - Navigation links: Clicking the hostname navigates to:
/monitoring/wireless/— ifprofile_device_typeisaccess_point/monitoring/(Observatory) — for all other device types
- Async loading: Port connections are fetched via
loadPortConnections(deviceId)after the port table renders, so the page remains responsive.
CSS
| File | Classes |
|---|---|
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
| File | Purpose |
|---|---|
network/models.py | PortConnection model definition |
network/api/port_connections.py | 6 API endpoints + schemas (incl. profile_device_type) |
network/api/profiles.py | ip filter param on profiles list endpoint |
network/services/port_suggestion.py | LLDP/CDP auto-match algorithm |
static/js/services/PortAssignModal.js | Frontend 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.js | assignPort() + _loadObsPortInfo() for manual targets |
static/js/pages/observatory/ObservatoryTabs.js | “Assign Port” button in manual target tab header |
static/js/editor/PropertiesPanelRenderer.js | Device column + Description hostname links + loadPortConnections() |
static/js/editor/PropertiesPanelEvents.js | Click guard for <a> links in port table rows |
static/js/editor/ui_panels.js | Calls 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
- [[concept—network—auto-provision]] — concepto de auto-descubrimiento de red
- [[crearack-tech—backend—auto-provision-guide]] — guía técnica de Auto-Provision
- [[crearack-tech—agents—dev-auto-provision]] — perfil de subagente dev-auto-provision
- [[crearack-tech—guides—interconnection-guide]] — guía de interconexionado
- [[crearack—network—discovery]] — discovery de dispositivos
- [[crearack—redes-infra—switches-routers]] — switches y routers en CreaRack
- [[entity—network—model—deviceprofile]] — perfil de dispositivo descubierto