From 1f4baa716ae033d72ff913e9dc77ed61944c62fa Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Thu, 7 Sep 2023 23:57:46 -0500 Subject: [PATCH] Changes to account for required SVG rendering changes and based on feedback --- netbox/dcim/models/cables.py | 16 +--- netbox/dcim/tests/test_cablepaths.py | 135 ++++++--------------------- 2 files changed, 31 insertions(+), 120 deletions(-) diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index c70b1d888..fb7a70783 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -545,21 +545,12 @@ class CablePath(models.Model): break assert all(type(link) in (Cable, WirelessLink) for link in links) - # Create set of links in path. Cannot use list(set()) as it does this in a non-deterministic manner - links_path = [] - for link in links: - if object_to_path_node(link) not in links_path: - links_path.append(object_to_path_node(link)) - # Step 3: Record the links - path.append(links_path) + path.append([object_to_path_node(link) for link in links]) # Step 4: Update the path status if a link is not connected - links_status = [ - link.status for link in links if hasattr(link, 'status') and - link.status != LinkStatusChoices.STATUS_CONNECTED - ] - if len(links_status) and len(links) != len(links_status): + links_status = [link.status for link in links if link.status != LinkStatusChoices.STATUS_CONNECTED] + if any([status != LinkStatusChoices.STATUS_CONNECTED for status in links_status]): is_active = False # Step 5: Determine the far-end terminations @@ -575,7 +566,6 @@ class CablePath(models.Model): cable_end = 'A' if lct.cable_end == 'B' else 'B' q_filter |= Q(cable=lct.cable, cable_end=cable_end) - assert q_filter is not Q() remote_cable_terminations = CableTermination.objects.filter(q_filter) remote_terminations = [ct.termination for ct in remote_cable_terminations] else: diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index 7d18bfaa1..bad515742 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -15,6 +15,7 @@ class CablePathTestCase(TestCase): 1XX: Test direct connections between different endpoint types 2XX: Test different cable topologies 3XX: Test responses to changes in existing objects + 4XX: Test to exclude specific cable topologies """ @classmethod def setUpTestData(cls): @@ -34,9 +35,9 @@ class CablePathTestCase(TestCase): circuit_type = CircuitType.objects.create(name='Circuit Type', slug='circuit-type') cls.circuit = Circuit.objects.create(provider=provider, type=circuit_type, cid='Circuit 1') - def assertPathExists(self, nodes, **kwargs): + def _get_cablepath(self, nodes, **kwargs): """ - Assert that a CablePath from origin to destination with a specific intermediate path exists. + Return a given cable path :param nodes: Iterable of steps, with each step being either a single node or a list of nodes :param is_active: Boolean indicating whether the end-to-end path is complete and active (optional) @@ -51,6 +52,18 @@ class CablePathTestCase(TestCase): path.append([object_to_path_node(step)]) cablepath = CablePath.objects.filter(path=path, **kwargs).first() + return cablepath + + def assertPathExists(self, nodes, **kwargs): + """ + Assert that a CablePath from origin to destination with a specific intermediate path exists. + + :param nodes: Iterable of steps, with each step being either a single node or a list of nodes + :param is_active: Boolean indicating whether the end-to-end path is complete and active (optional) + + :return: The matching CablePath (if any) + """ + cablepath = self._get_cablepath(nodes, **kwargs) self.assertIsNotNone(cablepath, msg='CablePath not found') return cablepath @@ -64,14 +77,7 @@ class CablePathTestCase(TestCase): :return: The matching CablePath (if any) """ - path = [] - for step in nodes: - if type(step) in (list, tuple): - path.append([object_to_path_node(node) for node in step]) - else: - path.append([object_to_path_node(step)]) - - cablepath = CablePath.objects.filter(path=path, **kwargs).first() + cablepath = self._get_cablepath(nodes, **kwargs) self.assertIsNone(cablepath, msg='CablePath not found') return cablepath @@ -327,7 +333,7 @@ class CablePathTestCase(TestCase): is_active=True ) path2 = self.assertPathExists( - ((interface3, interface4), cable1, (interface1, interface2)), + ((interface3, interface4), (cable1, cable1), (interface1, interface2)), is_complete=True, is_active=True ) @@ -1789,119 +1795,34 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 2) - def test_220_interface_to_interface_duplex_via_multiple_rearports_with_modules(self): + def test_220_interface_to_interface_duplex_via_multiple_front_and_rear_ports(self): """ - [IF1] --C1-- [[FP1] [RP1]] --C2-- [[RP2] [FP2]] --C3-- [IF2] - [[FP3] [RP3]] --C4-- [[RP4] [FP4]] + [IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2] + [IF2] --C5-- [FP3] [RP3] --C4-- [RP4] [FP4] """ module_type = ModuleType.objects.get(model='Test Module') module_bay1 = ModuleBay.objects.create(device=self.device, name='Module Bay 1', position='1') module_bay2 = ModuleBay.objects.create(device=self.device, name='Module Bay 2', position='2') module_bay3 = ModuleBay.objects.create(device=self.device, name='Module Bay 3', position='3') module_bay4 = ModuleBay.objects.create(device=self.device, name='Module Bay 4', position='4') - module1 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay1) - module2 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay2) - module3 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay3) - module4 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay4) - interface1 = Interface.objects.create(device=self.device, name='Interface 1') - interface2 = Interface.objects.create(device=self.device, name='Interface 2') - rearport1 = RearPort.objects.create(device=self.device, module=module1, name='Rear Port 1', positions=1) - rearport2 = RearPort.objects.create(device=self.device, module=module2, name='Rear Port 2', positions=1) - rearport3 = RearPort.objects.create(device=self.device, module=module3, name='Rear Port 3', positions=1) - rearport4 = RearPort.objects.create(device=self.device, module=module4, name='Rear Port 4', positions=1) - frontport1 = FrontPort.objects.create( - device=self.device, name='Front Port 1', module=module1, rear_port=rearport1, rear_port_position=1 - ) - frontport2 = FrontPort.objects.create( - device=self.device, name='Front Port 2', module=module2, rear_port=rearport2, rear_port_position=1 - ) - frontport3 = FrontPort.objects.create( - device=self.device, name='Front Port 3', module=module3, rear_port=rearport3, rear_port_position=1 - ) - frontport4 = FrontPort.objects.create( - device=self.device, name='Front Port 4', module=module4, rear_port=rearport4, rear_port_position=1 - ) - - cable2 = Cable( - a_terminations=[rearport1], - b_terminations=[rearport2] - ) - cable2.save() - cable4 = Cable( - a_terminations=[rearport3], - b_terminations=[rearport4] - ) - cable4.save() - self.assertEqual(CablePath.objects.count(), 0) - - # Create cable1 - cable1 = Cable( - a_terminations=[interface1], - b_terminations=[frontport1, frontport3] - ) - cable1.save() - self.assertPathExists( - (interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4), (rearport2, rearport4), (frontport2, frontport4)), - is_complete=False - ) - self.assertEqual(CablePath.objects.count(), 1) - - # Create cable 3 - cable3 = Cable( - a_terminations=[frontport2, frontport4], - b_terminations=[interface2] - ) - cable3.save() - self.assertPathExists( - ( - interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4), - (rearport2, rearport4), (frontport2, frontport4), cable3, interface2 - ), - is_complete=True, - is_active=True - ) - self.assertPathExists( - ( - interface2, cable3, (frontport2, frontport4), (rearport2, rearport4), (cable2, cable4), - (rearport1, rearport3), (frontport1, frontport3), cable1, interface1 - ), - is_complete=True, - is_active=True - ) - self.assertEqual(CablePath.objects.count(), 2) - - def test_221_interface_to_interface_duplex_via_multiple_rearports_with_modules(self): - """ - [IF1] --C1-- [[FP1] [RP1]] --C2-- [[RP2] [FP2]] --C3-- [IF2] - [IF2] --C5-- [[FP3] [RP3]] --C4-- [[RP4] [FP4]] - """ - module_type = ModuleType.objects.get(model='Test Module') - module_bay1 = ModuleBay.objects.create(device=self.device, name='Module Bay 1', position='1') - module_bay2 = ModuleBay.objects.create(device=self.device, name='Module Bay 2', position='2') - module_bay3 = ModuleBay.objects.create(device=self.device, name='Module Bay 3', position='3') - module_bay4 = ModuleBay.objects.create(device=self.device, name='Module Bay 4', position='4') - module1 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay1) - module2 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay2) - module3 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay3) - module4 = Module.objects.create(device=self.device, module_type=module_type, module_bay=module_bay4) interface1 = Interface.objects.create(device=self.device, name='Interface 1') interface2 = Interface.objects.create(device=self.device, name='Interface 2') interface3 = Interface.objects.create(device=self.device, name='Interface 3') - rearport1 = RearPort.objects.create(device=self.device, module=module1, name='Rear Port 1', positions=1) - rearport2 = RearPort.objects.create(device=self.device, module=module2, name='Rear Port 2', positions=1) - rearport3 = RearPort.objects.create(device=self.device, module=module3, name='Rear Port 3', positions=1) - rearport4 = RearPort.objects.create(device=self.device, module=module4, name='Rear Port 4', positions=1) + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1) + rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1) + rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3', positions=1) + rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4', positions=1) frontport1 = FrontPort.objects.create( - device=self.device, name='Front Port 1', module=module1, rear_port=rearport1, rear_port_position=1 + device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1 ) frontport2 = FrontPort.objects.create( - device=self.device, name='Front Port 2', module=module2, rear_port=rearport2, rear_port_position=1 + device=self.device, name='Front Port 2', rear_port=rearport2, rear_port_position=1 ) frontport3 = FrontPort.objects.create( - device=self.device, name='Front Port 3', module=module3, rear_port=rearport3, rear_port_position=1 + device=self.device, name='Front Port 3', rear_port=rearport3, rear_port_position=1 ) frontport4 = FrontPort.objects.create( - device=self.device, name='Front Port 4', module=module4, rear_port=rearport4, rear_port_position=1 + device=self.device, name='Front Port 4', rear_port=rearport4, rear_port_position=1 ) cable2 = Cable(