From 758c5347fb3782b178e53f84eda9c08765af6c8e Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 11 Jan 2023 14:42:25 -0500 Subject: [PATCH] Fixes #10201: Fix AssertionError exception when removing some terminations from an existing cable --- docs/release-notes/version-3.4.md | 1 + netbox/dcim/signals.py | 3 ++ netbox/dcim/tests/test_cablepaths.py | 41 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/docs/release-notes/version-3.4.md b/docs/release-notes/version-3.4.md index e5b230018..83e7751aa 100644 --- a/docs/release-notes/version-3.4.md +++ b/docs/release-notes/version-3.4.md @@ -12,6 +12,7 @@ ### Bug Fixes +* [#10201](https://github.com/netbox-community/netbox/issues/10201) - Fix AssertionError exception when removing some terminations from an existing cable * [#11210](https://github.com/netbox-community/netbox/issues/11210) - Fix ValueError exception when attempting to bulk import cables attached to occupied terminations * [#11340](https://github.com/netbox-community/netbox/issues/11340) - Avoid flagging cable termination changes erroneously * [#11379](https://github.com/netbox-community/netbox/issues/11379) - Fix TypeError exception when bulk editing custom date fields diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index 522bb76c0..7ef08d2cc 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -124,6 +124,9 @@ def nullify_connected_endpoints(instance, **kwargs): model.objects.filter(pk=instance.termination_id).update(cable=None, cable_end='') for cablepath in CablePath.objects.filter(_nodes__contains=instance.cable): + # Remove the deleted CableTermination if it's one of the path's originating nodes + if instance.termination in cablepath.origins: + cablepath.origins.remove(instance.termination) cablepath.retrace() diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index 50a707bc6..3367a3efe 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -1804,3 +1804,44 @@ class CablePathTestCase(TestCase): is_active=True ) self.assertEqual(CablePath.objects.count(), 2) + + def test_303_remove_termination_from_existing_cable(self): + """ + [IF1] --C1-- [IF2] + [IF3] + """ + 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') + + # Create cables 1 + cable1 = Cable( + a_terminations=[interface1], + b_terminations=[interface2, interface3] + ) + cable1.save() + self.assertPathExists( + (interface1, cable1, [interface2, interface3]), + is_complete=True, + is_active=True + ) + self.assertPathExists( + ([interface2, interface3], cable1, interface1), + is_complete=True, + is_active=True + ) + + # Remove the termination to interface 3 + cable1 = Cable.objects.first() + cable1.b_terminations = [interface2] + cable1.save() + self.assertPathExists( + (interface1, cable1, interface2), + is_complete=True, + is_active=True + ) + self.assertPathExists( + (interface2, cable1, interface1), + is_complete=True, + is_active=True + )