PUT on Existing Devices Returns Errors #1170

Closed
opened 2025-12-29 16:29:41 +01:00 by adam · 1 comment
Owner

Originally created by @zachmoody on GitHub (Aug 11, 2017).

Issue type: Bug

Python version: 2.7.6
NetBox version: develop

Updating device with PUT failed RU validation. Seems it was introduced in 1f9806a480. I think the error is the result of a ValidationError raised after checking for available RU. Here's the error:

{"non_field_errors":["U<RU> is already occupied or does not have sufficient space to accommodate a(n) <MODEL>."]}

This should test for the behavior.

--- a/netbox/dcim/tests/test_api.py
+++ b/netbox/dcim/tests/test_api.py
@@ -1267,8 +1267,10 @@ class DeviceTest(HttpStatusMixin, APITestCase):
         self.devicerole2 = DeviceRole.objects.create(
             name='Test Device Role 2', slug='test-device-role-2', color='00ff00'
         )
+        self.site1_r1 = Rack.objects.create(name='Test Rack S1R1', site=self.site1)
         self.device1 = Device.objects.create(
-            device_type=self.devicetype1, device_role=self.devicerole1, name='Test Device 1', site=self.site1
+            device_type=self.devicetype1, device_role=self.devicerole1, name='Test Device 1', site=self.site1,
+            rack=self.site1_r1, position=42, face=1
         )
         self.device2 = Device.objects.create(
             device_type=self.devicetype1, device_role=self.devicerole1, name='Test Device 2', site=self.site1
@@ -1331,6 +1333,24 @@ class DeviceTest(HttpStatusMixin, APITestCase):
         self.assertEqual(device1.name, data['name'])
         self.assertEqual(device1.site_id, data['site'])

+    def test_update_device_field(self):
+        '''Update a single field on a device'''
+        data = {
+            'name': 'Test Device X',
+            'device_type': self.devicetype1.pk,
+            'device_role': self.devicerole1.pk,
+            'site': self.site1.pk,
+            'position': 42,
+            'rack': self.site1_r1.pk,
+            'face': 1,
+        }
+        url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk})
+        response = self.client.put(url, data, **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertEqual(Device.objects.count(), 3)
+        device1 = Device.objects.get(pk=response.data['id'])
+        self.assertEqual(device1.name, 'Test Device X')
+
     def test_delete_device(self):

         url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk})
Originally created by @zachmoody on GitHub (Aug 11, 2017). <!-- Please note: GitHub issues are to be used only for feature requests and bug reports. For installation assistance or general discussion, please join us on the mailing list: https://groups.google.com/forum/#!forum/netbox-discuss Please indicate "bug report" or "feature request" below. Be sure to search the existing set of issues (both open and closed) to see if a similar issue has already been raised. --> ### Issue type: Bug <!-- If filing a bug, please indicate the version of Python and NetBox you are running. (This is not necessary for feature requests.) --> **Python version:** 2.7.6 **NetBox version:** develop <!-- If filing a bug, please record the exact steps taken to reproduce the bug and any errors messages that are generated. If filing a feature request, please precisely describe the data model or workflow you would like to see implemented, and provide a use case. --> Updating device with `PUT` failed RU validation. Seems it was introduced in 1f9806a480589764c6dca3e78e39b8d26648e3e5. I think the error is the result of a ValidationError raised after checking for available RU. Here's the error: ``` {"non_field_errors":["U<RU> is already occupied or does not have sufficient space to accommodate a(n) <MODEL>."]} ``` This should test for the behavior. ```diff --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -1267,8 +1267,10 @@ class DeviceTest(HttpStatusMixin, APITestCase): self.devicerole2 = DeviceRole.objects.create( name='Test Device Role 2', slug='test-device-role-2', color='00ff00' ) + self.site1_r1 = Rack.objects.create(name='Test Rack S1R1', site=self.site1) self.device1 = Device.objects.create( - device_type=self.devicetype1, device_role=self.devicerole1, name='Test Device 1', site=self.site1 + device_type=self.devicetype1, device_role=self.devicerole1, name='Test Device 1', site=self.site1, + rack=self.site1_r1, position=42, face=1 ) self.device2 = Device.objects.create( device_type=self.devicetype1, device_role=self.devicerole1, name='Test Device 2', site=self.site1 @@ -1331,6 +1333,24 @@ class DeviceTest(HttpStatusMixin, APITestCase): self.assertEqual(device1.name, data['name']) self.assertEqual(device1.site_id, data['site']) + def test_update_device_field(self): + '''Update a single field on a device''' + data = { + 'name': 'Test Device X', + 'device_type': self.devicetype1.pk, + 'device_role': self.devicerole1.pk, + 'site': self.site1.pk, + 'position': 42, + 'rack': self.site1_r1.pk, + 'face': 1, + } + url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk}) + response = self.client.put(url, data, **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + self.assertEqual(Device.objects.count(), 3) + device1 = Device.objects.get(pk=response.data['id']) + self.assertEqual(device1.name, 'Test Device X') + def test_delete_device(self): url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk}) ```
adam added the type: bug label 2025-12-29 16:29:41 +01:00
adam closed this issue 2025-12-29 16:29:41 +01:00
Author
Owner

@zachmoody commented on GitHub (Aug 15, 2017):

Dug a bit more into this. Seems that self.pk is None which is causing the logic in clean() to treat it like a new device. 🤔

@zachmoody commented on GitHub (Aug 15, 2017): Dug a bit more into this. Seems that `self.pk` is None which is causing the logic in clean() to treat it like a new device. 🤔
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#1170