#7503 initial bulk add device validation

This commit is contained in:
Arthur 2022-08-30 13:12:42 -07:00
parent 06b75d1b0e
commit 78c8fdbebf
3 changed files with 25 additions and 6 deletions

View File

@ -619,6 +619,24 @@ class PlatformSerializer(NetBoxModelSerializer):
] ]
class CustomDeviceListSerializer(serializers.ListSerializer):
def validate(self, attrs):
validated_data = super().validate(attrs)
devices = [Device(**item) for item in validated_data]
# break these up into racks for space validation
racks = {}
for device in devices:
if device.rack:
if device.rack not in racks:
racks[device.rack] = []
racks[device.rack].append(device)
for rack, devices in racks.items():
units = rack.check_for_space(devices)
return validated_data
class DeviceSerializer(NetBoxModelSerializer): class DeviceSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail')
device_type = NestedDeviceTypeSerializer() device_type = NestedDeviceTypeSerializer()
@ -655,6 +673,7 @@ class DeviceSerializer(NetBoxModelSerializer):
'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments', 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments',
'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated', 'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated',
] ]
list_serializer_class = CustomDeviceListSerializer
@swagger_serializer_method(serializer_or_field=NestedDeviceSerializer) @swagger_serializer_method(serializer_or_field=NestedDeviceSerializer)
def get_parent_device(self, obj): def get_parent_device(self, obj):

View File

@ -758,7 +758,7 @@ class Device(NetBoxModel, ConfigContextModel):
}) })
# Validate rack space # Validate rack space
rack.check_for_space([self, ]) self.rack.check_for_space([self, ])
except DeviceType.DoesNotExist: except DeviceType.DoesNotExist:
pass pass

View File

@ -332,7 +332,7 @@ class Rack(NetBoxModel):
:param exclude: List of devices IDs to exclude (useful when moving a device within a rack) :param exclude: List of devices IDs to exclude (useful when moving a device within a rack)
""" """
if exclude is not None: if exclude is not None:
devices = devices.exclude(pk__in=exclude) devices = [device for device in devices if device.pk not in exclude]
# Initialize the rack unit skeleton # Initialize the rack unit skeleton
units = list(self.units) units = list(self.units)
@ -369,7 +369,7 @@ class Rack(NetBoxModel):
:param exclude: List of devices IDs to exclude (useful when moving a device within a rack) :param exclude: List of devices IDs to exclude (useful when moving a device within a rack)
""" """
# Gather all devices which consume U space within the rack # Gather all devices which consume U space within the rack
devices = self.get_all_devices() devices = list(self.get_all_devices())
return self.check_available_units(devices, u_height, rack_face, exclude) return self.check_available_units(devices, u_height, rack_face, exclude)
def check_for_space(self, devices): def check_for_space(self, devices):
@ -377,13 +377,13 @@ class Rack(NetBoxModel):
for device in devices: for device in devices:
rack_face = device.face if not device.device_type.is_full_depth else None rack_face = device.face if not device.device_type.is_full_depth else None
exclude_list = [device.pk] if device.pk else [] exclude_list = [device.pk] if device.pk else []
available_units = rack.check_available_units( available_units = self.check_available_units(
rack_devices, u_height=device.device_type.u_height, rack_face=rack_face, exclude=exclude_list rack_devices, u_height=device.device_type.u_height, rack_face=rack_face, exclude=exclude_list
) )
if device.position and device.position not in available_units: if device.position and device.position not in available_units:
raise ValidationError({ raise ValidationError({
'position': f"U{self.position} is already occupied or does not have sufficient space to " 'position': f"U{device.position} is already occupied or does not have sufficient space to "
f"accommodate this device type: {self.device_type} ({self.device_type.u_height}U)" f"accommodate this device type: {device.device_type} ({device.device_type.u_height}U)"
}) })
rack_devices.append(device) rack_devices.append(device)