fix: retrace existing patchpanel cable paths

This commit is contained in:
2026-08-06 15:38:06 +02:00
parent e74d8fba31
commit 8c6c48531e
9 changed files with 119 additions and 22 deletions
+47 -16
View File
@@ -59,7 +59,23 @@ def pair_ports(front_ports, rear_ports):
return sorted(pairs, key=lambda pair: natural_port_key(pair[0]))
def synchronize_patchpanel(device_id):
def retrace_patchpanel_paths(ports):
"""Retrace cable paths touching any of the supplied pass-through ports."""
from dcim.models import CablePath
path_ids = set()
for port in ports:
path_ids.update(CablePath.objects.filter(_nodes__contains=port).values_list("pk", flat=True))
retraced = 0
for path_id in path_ids:
if cable_path := CablePath.objects.filter(pk=path_id).first():
cable_path.retrace()
retraced += 1
return retraced
def synchronize_patchpanel(device_id, *, force_retrace=False):
"""Enforce front position 1 -> rear position 1 for a Patchpanel device."""
if not device_id:
return 0
@@ -83,25 +99,40 @@ def synchronize_patchpanel(device_id):
"rear_port_position",
)
)
if current == expected:
return len(pairs)
if current != expected:
PortMapping.objects.filter(device_id=device_id).delete()
PortMapping.objects.bulk_create(
[
PortMapping(
device_id=device_id,
front_port_id=front.pk,
rear_port_id=rear.pk,
front_port_position=1,
rear_port_position=1,
)
for front, rear in pairs
]
)
force_retrace = True
PortMapping.objects.filter(device_id=device_id).delete()
PortMapping.objects.bulk_create(
[
PortMapping(
device_id=device_id,
front_port_id=front.pk,
rear_port_id=rear.pk,
front_port_position=1,
rear_port_position=1,
)
for front, rear in pairs
]
)
if force_retrace:
retrace_patchpanel_paths([*front_ports, *rear_ports])
return len(pairs)
def repair_existing_patchpanels():
"""Repair mappings and cable paths for all existing Patchpanel devices."""
from dcim.models import Device
device_ids = Device.objects.filter(role__name__iexact=PATCHPANEL_ROLE_NAME).values_list("pk", flat=True)
device_count = 0
mapping_count = 0
for device_id in device_ids:
mapping_count += synchronize_patchpanel(device_id, force_retrace=True)
device_count += 1
return device_count, mapping_count
def _component_saved(sender, instance, raw=False, **kwargs):
if not raw and not _component_instantiation_active.get():
synchronize_patchpanel(getattr(instance, "device_id", None))