From 9c5891f1b6bb1fa38f1d0c735956e4d3c45aaa63 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 21 Nov 2022 14:08:33 -0500 Subject: [PATCH] Fixes #10929: Raise validation error when attempting to create a duplicate cable termination --- docs/release-notes/version-3.3.md | 1 + netbox/dcim/models/cables.py | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index b00577bf8..857529e83 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -15,6 +15,7 @@ * [#10241](https://github.com/netbox-community/netbox/issues/10241) - Support referencing custom field related objects by attribute in addition to PK * [#10579](https://github.com/netbox-community/netbox/issues/10579) - Mark cable traces terminating to a provider network as complete * [#10721](https://github.com/netbox-community/netbox/issues/10721) - Disable ordering by custom object field columns +* [#10929](https://github.com/netbox-community/netbox/issues/10929) - Raise validation error when attempting to create a duplicate cable termination * [#10938](https://github.com/netbox-community/netbox/issues/10938) - `render_field` template tag should respect `label` kwarg * [#10969](https://github.com/netbox-community/netbox/issues/10969) - Update cable paths ending at associated rear port when creating new front ports diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index 4dd8d98a1..d00cfd4e6 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -279,6 +279,17 @@ class CableTermination(models.Model): def clean(self): super().clean() + # Check for existing termination + existing_termination = CableTermination.objects.exclude(cable=self.cable).filter( + termination_type=self.termination_type, + termination_id=self.termination_id + ).first() + if existing_termination is not None: + raise ValidationError( + f"Duplicate termination found for {self.termination_type.app_label}.{self.termination_type.model} " + f"{self.termination_id}: cable {existing_termination.cable.pk}" + ) + # Validate interface type (if applicable) if self.termination_type.model == 'interface' and self.termination.type in NONCONNECTABLE_IFACE_TYPES: raise ValidationError(f"Cables cannot be terminated to {self.termination.get_type_display()} interfaces")