diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index 1a8372242..e2be2944f 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -546,7 +546,6 @@ class CablePath(models.Model): is_split = False while terminations: - prev_path = path.copy() # Terminations must all be of the same type assert all(isinstance(t, type(terminations[0])) for t in terminations[1:]) @@ -588,9 +587,19 @@ class CablePath(models.Model): # Step 4: Record the links, keeping cables in order to allow for SVG rendering cables = [] + loop_detected = False + for link in links: - if object_to_path_node(link) not in cables: - cables.append(object_to_path_node(link)) + cable = object_to_path_node(link) + if cable not in cables: + # Detect infinite loop in cabling topology + for node in path: + if cable in node: + loop_detected = True + cables.append(cable) + if loop_detected: + logger.warning('Infinite loop detected while updating cable path trace') + break path.append(cables) # Step 5: Update the path status if a link is not connected @@ -726,14 +735,6 @@ class CablePath(models.Model): is_split = True break - # Detect infinite loop in cabling topology - num_elements_added = len(path) - len(prev_path) - prev_elements_added = prev_path[-num_elements_added:] - elements_added = path[-num_elements_added:] - if elements_added == prev_elements_added: - logger.warning('Infinite loop detected while updating cable path trace') - break - return cls( path=path, is_complete=is_complete, diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index 072712733..d04bfb80d 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -2373,12 +2373,12 @@ class CablePathTestCase(TestCase): ct_rearport = ContentType.objects.get(app_label='dcim', model='rearport') cable_1 = Cable.objects.create() - termination_1a = CableTermination.objects.create(cable=cable_1, cable_end='A', termination_type=ct_interface, termination_id=interface.id) - termination_1b = CableTermination.objects.create(cable=cable_1, cable_end='B', termination_type=ct_frontport, termination_id=front_port_1.id) + CableTermination.objects.create(cable=cable_1, cable_end='A', termination_type=ct_interface, termination_id=interface.id) + CableTermination.objects.create(cable=cable_1, cable_end='B', termination_type=ct_frontport, termination_id=front_port_1.id) cable_2 = Cable.objects.create() - termination_2a = CableTermination.objects.create(cable=cable_2, cable_end='A', termination_type=ct_frontport, termination_id=front_port_2.id) - termination_2b = CableTermination.objects.create(cable=cable_2, cable_end='B', termination_type=ct_rearport, termination_id=rear_splice.id) + CableTermination.objects.create(cable=cable_2, cable_end='A', termination_type=ct_frontport, termination_id=front_port_2.id) + CableTermination.objects.create(cable=cable_2, cable_end='B', termination_type=ct_rearport, termination_id=rear_splice.id) cable_1._terminations_modified = True cable_1.save()