mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #2777: Fix cable validation to handle duplicate connections on import
This commit is contained in:
@ -15,6 +15,7 @@ v2.5.3 (FUTURE)
|
|||||||
* [#2742](https://github.com/digitalocean/netbox/issues/2742) - Preserve cluster assignment when editing a device
|
* [#2742](https://github.com/digitalocean/netbox/issues/2742) - Preserve cluster assignment when editing a device
|
||||||
* [#2757](https://github.com/digitalocean/netbox/issues/2757) - Always treat first/last IPs within a /31 or /127 as usable
|
* [#2757](https://github.com/digitalocean/netbox/issues/2757) - Always treat first/last IPs within a /31 or /127 as usable
|
||||||
* [#2762](https://github.com/digitalocean/netbox/issues/2762) - Add missing DCIM field values to API `_choices` endpoint
|
* [#2762](https://github.com/digitalocean/netbox/issues/2762) - Add missing DCIM field values to API `_choices` endpoint
|
||||||
|
* [#2777](https://github.com/digitalocean/netbox/issues/2777) - Fix cable validation to handle duplicate connections on import
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -2558,52 +2558,55 @@ class Cable(ChangeLoggedModel):
|
|||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
||||||
# Check that termination types are compatible
|
if self.termination_a and self.termination_b:
|
||||||
type_a = self.termination_a_type.model
|
|
||||||
type_b = self.termination_b_type.model
|
|
||||||
if type_b not in COMPATIBLE_TERMINATION_TYPES.get(type_a):
|
|
||||||
raise ValidationError("Incompatible termination types: {} and {}".format(
|
|
||||||
self.termination_a_type, self.termination_b_type
|
|
||||||
))
|
|
||||||
|
|
||||||
# A termination point cannot be connected to itself
|
type_a = self.termination_a_type.model
|
||||||
if self.termination_a == self.termination_b:
|
type_b = self.termination_b_type.model
|
||||||
raise ValidationError("Cannot connect {} to itself".format(self.termination_a_type))
|
|
||||||
|
|
||||||
# A front port cannot be connected to its corresponding rear port
|
# Check that termination types are compatible
|
||||||
if (
|
if type_b not in COMPATIBLE_TERMINATION_TYPES.get(type_a):
|
||||||
type_a in ['frontport', 'rearport'] and
|
raise ValidationError("Incompatible termination types: {} and {}".format(
|
||||||
type_b in ['frontport', 'rearport'] and
|
self.termination_a_type, self.termination_b_type
|
||||||
(
|
))
|
||||||
getattr(self.termination_a, 'rear_port', None) == self.termination_b or
|
|
||||||
getattr(self.termination_b, 'rear_port', None) == self.termination_a
|
|
||||||
)
|
|
||||||
):
|
|
||||||
raise ValidationError("A front port cannot be connected to it corresponding rear port")
|
|
||||||
|
|
||||||
# Check for an existing Cable connected to either termination object
|
# A termination point cannot be connected to itself
|
||||||
if self.termination_a.cable not in (None, self):
|
if self.termination_a == self.termination_b:
|
||||||
raise ValidationError("{} already has a cable attached (#{})".format(
|
raise ValidationError("Cannot connect {} to itself".format(self.termination_a_type))
|
||||||
self.termination_a, self.termination_a.cable_id
|
|
||||||
))
|
|
||||||
if self.termination_b.cable not in (None, self):
|
|
||||||
raise ValidationError("{} already has a cable attached (#{})".format(
|
|
||||||
self.termination_b, self.termination_b.cable_id
|
|
||||||
))
|
|
||||||
|
|
||||||
# Virtual interfaces cannot be connected
|
# A front port cannot be connected to its corresponding rear port
|
||||||
endpoint_a, endpoint_b, _ = self.get_path_endpoints()
|
if (
|
||||||
if (
|
type_a in ['frontport', 'rearport'] and
|
||||||
(
|
type_b in ['frontport', 'rearport'] and
|
||||||
isinstance(endpoint_a, Interface) and
|
(
|
||||||
endpoint_a.form_factor == IFACE_FF_VIRTUAL
|
getattr(self.termination_a, 'rear_port', None) == self.termination_b or
|
||||||
) or
|
getattr(self.termination_b, 'rear_port', None) == self.termination_a
|
||||||
(
|
)
|
||||||
isinstance(endpoint_b, Interface) and
|
):
|
||||||
endpoint_b.form_factor == IFACE_FF_VIRTUAL
|
raise ValidationError("A front port cannot be connected to it corresponding rear port")
|
||||||
)
|
|
||||||
):
|
# Check for an existing Cable connected to either termination object
|
||||||
raise ValidationError("Cannot connect to a virtual interface")
|
if self.termination_a.cable not in (None, self):
|
||||||
|
raise ValidationError("{} already has a cable attached (#{})".format(
|
||||||
|
self.termination_a, self.termination_a.cable_id
|
||||||
|
))
|
||||||
|
if self.termination_b.cable not in (None, self):
|
||||||
|
raise ValidationError("{} already has a cable attached (#{})".format(
|
||||||
|
self.termination_b, self.termination_b.cable_id
|
||||||
|
))
|
||||||
|
|
||||||
|
# Virtual interfaces cannot be connected
|
||||||
|
endpoint_a, endpoint_b, _ = self.get_path_endpoints()
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
isinstance(endpoint_a, Interface) and
|
||||||
|
endpoint_a.form_factor == IFACE_FF_VIRTUAL
|
||||||
|
) or
|
||||||
|
(
|
||||||
|
isinstance(endpoint_b, Interface) and
|
||||||
|
endpoint_b.form_factor == IFACE_FF_VIRTUAL
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise ValidationError("Cannot connect to a virtual interface")
|
||||||
|
|
||||||
# Validate length and length_unit
|
# Validate length and length_unit
|
||||||
if self.length is not None and self.length_unit is None:
|
if self.length is not None and self.length_unit is None:
|
||||||
|
Reference in New Issue
Block a user