mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixed up validation of Interface VLAN assignments
This commit is contained in:
@ -699,35 +699,20 @@ class WritableInterfaceSerializer(ValidatedModelSerializer):
|
|||||||
'id', 'device', 'name', 'form_factor', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only', 'description',
|
'id', 'device', 'name', 'form_factor', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only', 'description',
|
||||||
'mode', 'untagged_vlan', 'tagged_vlans',
|
'mode', 'untagged_vlan', 'tagged_vlans',
|
||||||
]
|
]
|
||||||
ignore_validation_fields = [
|
|
||||||
'tagged_vlans'
|
|
||||||
]
|
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
|
|
||||||
# Get the device for later use
|
# Validate that all untagged VLANs either belong to the same site as the Interface's parent Deivce or
|
||||||
if self.instance:
|
# VirtualMachine, or are global.
|
||||||
device = self.instance.device
|
parent = self.instance.parent if self.instance else data.get('device') or data.get('virtual_machine')
|
||||||
else:
|
for vlan in data.get('tagged_vlans', []):
|
||||||
device = data.get('device')
|
if vlan.site not in [parent, None]:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"Tagged VLAN {} must belong to the same site as the interface's parent device/VM, or it must be "
|
||||||
|
"global".format(vlan)
|
||||||
|
)
|
||||||
|
|
||||||
# Validate VLANs belong to the device's site or global
|
return super(WritableInterfaceSerializer, self).validate(data)
|
||||||
# We have to do this here decause of the ManyToMany relationship
|
|
||||||
native_vlan = data.get('native_vlan')
|
|
||||||
if native_vlan:
|
|
||||||
if native_vlan.site != device.site and native_vlan.site is not None:
|
|
||||||
raise serializers.ValidationError("Native VLAN is invalid for the interface's device.")
|
|
||||||
|
|
||||||
tagged_vlan_members = data.get('tagged_vlan_members')
|
|
||||||
if tagged_vlan_members:
|
|
||||||
for vlan in tagged_vlan_members:
|
|
||||||
if vlan.site != device.site and vlan.site is not None:
|
|
||||||
raise serializers.ValidationError("Tagged VLAN {} is invalid for the interface's device.".format(vlan))
|
|
||||||
|
|
||||||
# Enforce model validation
|
|
||||||
super(WritableInterfaceSerializer, self).validate(data)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1318,6 +1318,13 @@ class Interface(models.Model):
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Validate untagged VLAN
|
||||||
|
if self.untagged_vlan and self.untagged_vlan.site not in [self.parent.site, None]:
|
||||||
|
raise ValidationError({
|
||||||
|
'untagged_vlan': "The untagged VLAN ({}) must belong to the same site as the interface's parent "
|
||||||
|
"device/VM, or it must be global".format(self.untagged_vlan)
|
||||||
|
})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent(self):
|
def parent(self):
|
||||||
return self.device or self.virtual_machine
|
return self.device or self.virtual_machine
|
||||||
|
@ -48,11 +48,6 @@ class ValidatedModelSerializer(ModelSerializer):
|
|||||||
attrs = data.copy()
|
attrs = data.copy()
|
||||||
attrs.pop('custom_fields', None)
|
attrs.pop('custom_fields', None)
|
||||||
|
|
||||||
# remove any fields marked for no validation
|
|
||||||
ignore_validation_fields = getattr(self.Meta, 'ignore_validation_fields', [])
|
|
||||||
for field in ignore_validation_fields:
|
|
||||||
attrs.pop(field)
|
|
||||||
|
|
||||||
# Run clean() on an instance of the model
|
# Run clean() on an instance of the model
|
||||||
if self.instance is None:
|
if self.instance is None:
|
||||||
instance = self.Meta.model(**attrs)
|
instance = self.Meta.model(**attrs)
|
||||||
|
Reference in New Issue
Block a user