diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index c8166cb44..c3ee5ae91 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -242,6 +242,16 @@ class Cable(PrimaryModel): ): raise ValidationError("A front port cannot be connected to it corresponding rear port") + # A CircuitTermination attached to a Cloud cannot have a Cable + if isinstance(self.termination_a, CircuitTermination) and self.termination_a.cloud is not None: + raise ValidationError({ + 'termination_a_id': "Circuit terminations attached to a cloud may not be cabled." + }) + if isinstance(self.termination_b, CircuitTermination) and self.termination_b.cloud is not None: + raise ValidationError({ + 'termination_b_id': "Circuit terminations attached to a cloud may not be cabled." + }) + # Check for an existing Cable connected to either termination object if self.termination_a.cable not in (None, self): raise ValidationError("{} already has a cable attached (#{})".format( diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index 815d86758..b4454aa8a 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -479,10 +479,13 @@ class CableTestCase(TestCase): device=self.patch_pannel, name='FP4', type='8p8c', rear_port=self.rear_port4, rear_port_position=1 ) self.provider = Provider.objects.create(name='Provider 1', slug='provider-1') + cloud = Cloud.objects.create(name='Cloud 1', provider=self.provider) self.circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') - self.circuit = Circuit.objects.create(provider=self.provider, type=self.circuittype, cid='1') - self.circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=site, term_side='A') - self.circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=site, term_side='Z') + self.circuit1 = Circuit.objects.create(provider=self.provider, type=self.circuittype, cid='1') + self.circuit2 = Circuit.objects.create(provider=self.provider, type=self.circuittype, cid='2') + self.circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit1, site=site, term_side='A') + self.circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit1, site=site, term_side='Z') + self.circuittermination3 = CircuitTermination.objects.create(circuit=self.circuit2, cloud=cloud, term_side='A') def test_cable_creation(self): """ @@ -552,6 +555,14 @@ class CableTestCase(TestCase): with self.assertRaises(ValidationError): cable.clean() + def test_cable_cannot_terminate_to_a_cloud_circuittermination(self): + """ + Neither side of a cable can be terminated to a CircuitTermination which is attached to a Cloud + """ + cable = Cable(termination_a=self.interface3, termination_b=self.circuittermination3) + with self.assertRaises(ValidationError): + cable.clean() + def test_rearport_connections(self): """ Test various combinations of RearPort connections.