From add8640514564c79141db31527d677b6673891c1 Mon Sep 17 00:00:00 2001 From: Alexander Haase Date: Wed, 18 Sep 2024 20:16:13 +0200 Subject: [PATCH] Fix device location check Instead of an exact match between device and rack location, it is now sufficient if the device location or one of its children contains the selected rack. --- netbox/dcim/models/devices.py | 2 +- netbox/dcim/tests/test_models.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index c281e5de2..771401044 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -840,7 +840,7 @@ class Device( "Location {location} does not belong to site {site}." ).format(location=self.location, site=self.site) }) - if self.rack and self.location and self.rack.location != self.location: + if self.rack and self.location and not self.location.get_descendants(True).contains(self.rack.location): raise ValidationError({ 'rack': _( "Rack {rack} does not belong to location {location}." diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index c4f7b0691..58e01ebc7 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -613,6 +613,25 @@ class DeviceTestCase(TestCase): with self.assertRaises(ValidationError): Device(name='device2', site=sites[0], location=locations[1], device_type=device_type, role=device_role).full_clean() + def test_device_mismatched_rack_location(self): + site = Site.objects.first() + + locations = ( + Location(name='Location 1', slug='location-1', site=site), + Location(name='Location 2', slug='location-2', site=site), + ) + for location in locations: + location.save() + + rack = Rack.objects.create(name='Rack 1', site=site, location=locations[0]) + + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + + # Device should use location from rack + with self.assertRaises(ValidationError): + Device(name='device1', site=site, location=locations[1], rack=rack, device_type=device_type, role=device_role).full_clean() + def test_device_rack_clone_fields(self): site = Site.objects.first() location = Location(name='Location 1', slug='location-1', site=site)