From 89622f1ddf8c66a24ed4b05548516bcd52d97018 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 20 Nov 2018 13:00:57 -0500 Subject: [PATCH] Fixes #2602: Return HTTP 204 when no new IPs/prefixes are available for provisioning --- netbox/ipam/api/views.py | 47 +++++++++++++++++++++-------------- netbox/ipam/tests/test_api.py | 8 +++--- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 814339f61..e846f0489 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -96,25 +96,34 @@ class PrefixViewSet(CustomFieldModelViewSet): for i, requested_prefix in enumerate(requested_prefixes): # Validate requested prefix size - error_msg = None - if 'prefix_length' not in requested_prefix: - error_msg = "Item {}: prefix_length field missing".format(i) - elif not isinstance(requested_prefix['prefix_length'], int): - error_msg = "Item {}: Invalid prefix length ({})".format( - i, requested_prefix['prefix_length'] - ) - elif prefix.family == 4 and requested_prefix['prefix_length'] > 32: - error_msg = "Item {}: Invalid prefix length ({}) for IPv4".format( - i, requested_prefix['prefix_length'] - ) - elif prefix.family == 6 and requested_prefix['prefix_length'] > 128: - error_msg = "Item {}: Invalid prefix length ({}) for IPv6".format( - i, requested_prefix['prefix_length'] - ) - if error_msg: + prefix_length = requested_prefix.get('prefix_length') + if prefix_length is None: return Response( { - "detail": error_msg + "detail": "Item {}: prefix_length field missing".format(i) + }, + status=status.HTTP_400_BAD_REQUEST + ) + try: + prefix_length = int(prefix_length) + except ValueError: + return Response( + { + "detail": "Item {}: Invalid prefix length ({})".format(i, prefix_length), + }, + status=status.HTTP_400_BAD_REQUEST + ) + if prefix.family == 4 and prefix_length > 32: + return Response( + { + "detail": "Item {}: Invalid prefix length ({}) for IPv4".format(i, prefix_length), + }, + status=status.HTTP_400_BAD_REQUEST + ) + elif prefix.family == 6 and prefix_length > 128: + return Response( + { + "detail": "Item {}: Invalid prefix length ({}) for IPv6".format(i, prefix_length), }, status=status.HTTP_400_BAD_REQUEST ) @@ -131,7 +140,7 @@ class PrefixViewSet(CustomFieldModelViewSet): { "detail": "Insufficient space is available to accommodate the requested prefix size(s)" }, - status=status.HTTP_400_BAD_REQUEST + status=status.HTTP_204_NO_CONTENT ) # Remove the allocated prefix from the list of available prefixes @@ -187,7 +196,7 @@ class PrefixViewSet(CustomFieldModelViewSet): "detail": "An insufficient number of IP addresses are available within the prefix {} ({} " "requested, {} available)".format(prefix, len(requested_ips), len(available_ips)) }, - status=status.HTTP_400_BAD_REQUEST + status=status.HTTP_204_NO_CONTENT ) # Assign addresses from the list of available IPs and copy VRF assignment from the parent prefix diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py index e5e48aee2..13c635972 100644 --- a/netbox/ipam/tests/test_api.py +++ b/netbox/ipam/tests/test_api.py @@ -566,7 +566,7 @@ class PrefixTest(APITestCase): # Try to create one more prefix response = self.client.post(url, {'prefix_length': 30}, **self.header) - self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) + self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) self.assertIn('detail', response.data) def test_create_multiple_available_prefixes(self): @@ -583,7 +583,7 @@ class PrefixTest(APITestCase): {'prefix_length': 30, 'description': 'Test Prefix 5'}, ] response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) + self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) self.assertIn('detail', response.data) # Verify that no prefixes were created (the entire /28 is still available) @@ -628,7 +628,7 @@ class PrefixTest(APITestCase): # Try to create one more IP response = self.client.post(url, {}, **self.header) - self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) + self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) self.assertIn('detail', response.data) def test_create_multiple_available_ips(self): @@ -639,7 +639,7 @@ class PrefixTest(APITestCase): # Try to create nine IPs (only eight are available) data = [{'description': 'Test IP {}'.format(i)} for i in range(1, 10)] # 9 IPs response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) + self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) self.assertIn('detail', response.data) # Verify that no IPs were created (eight are still available)