fix: pair LC patchpanel ports by number
This commit is contained in:
@@ -30,6 +30,11 @@ Ab Version `0.10.3` kann dort optional eine VLAN-Gruppe ausgewählt werden. Sie
|
|||||||
dient als dynamischer Filter für die VLAN-Mehrfachauswahl und wird nicht als
|
dient als dynamischer Filter für die VLAN-Mehrfachauswahl und wird nicht als
|
||||||
zusätzliche Eigenschaft der Verbindung gespeichert.
|
zusätzliche Eigenschaft der Verbindung gespeichert.
|
||||||
|
|
||||||
|
Ab Version `0.10.4` verwendet die Patchpanel-Automatik die numerische
|
||||||
|
Portkennung unabhängig von zusätzlichen Bezeichnungen wie `LC`, `Front` oder
|
||||||
|
`Rear`. Damit werden auch kleinere LC/LC-Patchpanels, etwa mit sechs Ports,
|
||||||
|
fortlaufend eins-zu-eins zugeordnet.
|
||||||
|
|
||||||
## Kompatibilität
|
## Kompatibilität
|
||||||
|
|
||||||
- NetBox `>=4.6.5,<4.7`
|
- NetBox `>=4.6.5,<4.7`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from netbox.plugins import PluginConfig, get_plugin_config
|
from netbox.plugins import PluginConfig, get_plugin_config
|
||||||
|
|
||||||
__version__ = "0.10.3"
|
__version__ = "0.10.4"
|
||||||
|
|
||||||
|
|
||||||
class NetBoxUtilitiesConfig(PluginConfig):
|
class NetBoxUtilitiesConfig(PluginConfig):
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ def port_identifier(port):
|
|||||||
name = str(getattr(port, "name", "")).casefold()
|
name = str(getattr(port, "name", "")).casefold()
|
||||||
name = re.sub(r"\b(?:front|rear)(?:[\s_-]*port)?(?=\b|\d)", " ", name)
|
name = re.sub(r"\b(?:front|rear)(?:[\s_-]*port)?(?=\b|\d)", " ", name)
|
||||||
name = re.sub(r"^(?:fp|rp|f|r)(?=\s*[-_.:/]?\s*\d)", "", name)
|
name = re.sub(r"^(?:fp|rp|f|r)(?=\s*[-_.:/]?\s*\d)", "", name)
|
||||||
|
numbers = tuple(int(token) for token in re.findall(r"\d+", name))
|
||||||
|
if numbers:
|
||||||
|
return numbers
|
||||||
tokens = re.findall(r"\d+|[^\W\d_]+", name)
|
tokens = re.findall(r"\d+|[^\W\d_]+", name)
|
||||||
identifier = tuple(int(token) if token.isdigit() else token for token in tokens)
|
identifier = tuple(int(token) if token.isdigit() else token for token in tokens)
|
||||||
return identifier or None
|
return identifier or None
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
from django.test import SimpleTestCase
|
||||||
|
|
||||||
|
from netbox_utilities.patchpanel import pair_ports, port_identifier
|
||||||
|
|
||||||
|
|
||||||
|
def port(pk, name):
|
||||||
|
return SimpleNamespace(pk=pk, name=name)
|
||||||
|
|
||||||
|
|
||||||
|
class LCPatchpanelPairingTest(SimpleTestCase):
|
||||||
|
def test_uses_numeric_identifier_despite_connector_labels(self):
|
||||||
|
self.assertEqual(port_identifier(port(1, "LC Front 01")), (1,))
|
||||||
|
self.assertEqual(port_identifier(port(2, "Rear 1")), (1,))
|
||||||
|
|
||||||
|
def test_pairs_all_six_lc_ports_by_number(self):
|
||||||
|
front_ports = [port(number, f"LC Front {number}") for number in range(1, 7)]
|
||||||
|
rear_ports = [port(100 + number, f"Rear {number}") for number in range(1, 7)]
|
||||||
|
|
||||||
|
pairs = pair_ports(front_ports, rear_ports)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[(front.pk, rear.pk) for front, rear in pairs],
|
||||||
|
[(number, 100 + number) for number in range(1, 7)],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_keeps_compound_numeric_identifiers_distinct(self):
|
||||||
|
front_ports = [port(12, "Cassette 1 LC 2"), port(13, "Cassette 1 LC 3")]
|
||||||
|
rear_ports = [port(112, "Rear 1/2"), port(113, "Rear 1/3")]
|
||||||
|
|
||||||
|
pairs = pair_ports(front_ports, rear_ports)
|
||||||
|
|
||||||
|
self.assertEqual([(front.pk, rear.pk) for front, rear in pairs], [(12, 112), (13, 113)])
|
||||||
@@ -449,7 +449,7 @@ class ReorderRackFrontendTest(SimpleTestCase):
|
|||||||
self.assertEqual(template_name, "netbox_utilities/reorder_rack.html")
|
self.assertEqual(template_name, "netbox_utilities/reorder_rack.html")
|
||||||
self.assertEqual(context["reorder_devices"][0]["label"], "LEO-Fritzbox")
|
self.assertEqual(context["reorder_devices"][0]["label"], "LEO-Fritzbox")
|
||||||
self.assertEqual(context["reorder_devices"][0]["grid_width"], 6)
|
self.assertEqual(context["reorder_devices"][0]["grid_width"], 6)
|
||||||
self.assertEqual(context["asset_version"], "0.10.3")
|
self.assertEqual(context["asset_version"], "0.10.4")
|
||||||
self.assertIs(context["reorder_rack_width_data"], get_width_data.return_value)
|
self.assertIs(context["reorder_rack_width_data"], get_width_data.return_value)
|
||||||
get_width_data.assert_called_once()
|
get_width_data.assert_called_once()
|
||||||
self.assertIs(get_width_data.call_args.kwargs["rack"], rack)
|
self.assertIs(get_width_data.call_args.kwargs["rack"], rack)
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ class TopologyViewsRackWidthTest(SimpleTestCase):
|
|||||||
self.assertIn('id="netbox-utilities-topology-rack-width-styles"', html)
|
self.assertIn('id="netbox-utilities-topology-rack-width-styles"', html)
|
||||||
self.assertIn('.rack-device[href="/dcim/devices/334/"]', html)
|
self.assertIn('.rack-device[href="/dcim/devices/334/"]', html)
|
||||||
self.assertIn("left: calc(50% + 3px) !important", html)
|
self.assertIn("left: calc(50% + 3px) !important", html)
|
||||||
self.assertIn("netbox_utilities/topology-rack-width.js?v=0.10.3", html)
|
self.assertIn("netbox_utilities/topology-rack-width.js?v=0.10.4", html)
|
||||||
self.assertIn("left:calc(0% + 3px)!important", html)
|
self.assertIn("left:calc(0% + 3px)!important", html)
|
||||||
self.assertIn("left:calc(50% + 3px)!important", html)
|
self.assertIn("left:calc(50% + 3px)!important", html)
|
||||||
self.assertIn("width:calc(50% - 6px)!important", html)
|
self.assertIn("width:calc(50% - 6px)!important", html)
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "netbox-utilities"
|
name = "netbox-utilities"
|
||||||
version = "0.10.3"
|
version = "0.10.4"
|
||||||
description = "Navigation, tenant utilities, connection VLANs, partial-width racks, and bulk operations for NetBox 4.6"
|
description = "Navigation, tenant utilities, connection VLANs, partial-width racks, and bulk operations for NetBox 4.6"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
Reference in New Issue
Block a user