diff --git a/netbox/dcim/api/serializers_/device_components.py b/netbox/dcim/api/serializers_/device_components.py index f26e81aa1..16b68671b 100644 --- a/netbox/dcim/api/serializers_/device_components.py +++ b/netbox/dcim/api/serializers_/device_components.py @@ -244,7 +244,7 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect tagged_vlans = [] if self.instance.pk and 'mode' in data.keys(): - mode = data.get('mode') if 'mode' in self.data.keys() else self.instance.get('mode') + mode = data.get('mode') if 'mode' in data.keys() else self.instance.get('mode') elif 'mode' in data.keys(): mode = data.get('mode') @@ -254,9 +254,15 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect elif 'tagged_vlans' in data.keys(): tagged_vlans = data.get('tagged_vlans') + if self.instance.pk and 'untagged_vlan' in data.keys(): + untagged_vlan = data.get('untagged_vlan') if 'untagged_vlan' in data.keys() else \ + self.instance.untagged_vlan + elif 'untagged_vlan' in data.keys(): + untagged_vlan = data.get('untagged_vlan') + if mode != InterfaceModeChoices.MODE_TAGGED and tagged_vlans: raise serializers.ValidationError({ - 'tagged_vlans': "Interface mode does not support including tagged vlans" + 'tagged_vlans': _("Interface mode does not support including tagged vlans") }) # Validate many-to-many VLAN assignments diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index a03175725..b26247a94 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -1366,6 +1366,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm): def clean(self): mode = None tagged_vlans = [] + untagged_vlan = None if self.instance.pk and 'mode' in self.cleaned_data.keys(): mode = self.cleaned_data.get('mode') if 'mode' in self.cleaned_data.keys() else self.instance.get('mode') @@ -1378,9 +1379,15 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm): elif 'tagged_vlans' in self.cleaned_data.keys(): tagged_vlans = self.cleaned_data.get('tagged_vlans') + if self.instance.pk and 'untagged_vlan' in self.cleaned_data.keys(): + untagged_vlan = self.cleaned_data.get('untagged_vlan') if 'untagged_vlan' in self.cleaned_data.keys() else\ + self.instance.untagged_vlan + elif 'untagged_vlan' in self.cleaned_data.keys(): + untagged_vlan = self.cleaned_data.get('untagged_vlan') + if mode != InterfaceModeChoices.MODE_TAGGED and tagged_vlans: raise forms.ValidationError({ - 'tagged_vlans': "Interface mode does not support including tagged vlans" + 'tagged_vlans': _("Interface mode does not support including tagged vlans") }) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 101a1a459..f38343f5d 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -894,7 +894,7 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd raise ValidationError({'rf_channel_width': _("Cannot specify custom width with channel selected.")}) # VLAN validation - if self.mode is None and self.untagged_vlan: + if not self.mode and self.untagged_vlan: raise ValidationError({'untagged_vlan': _("Interface mode does not support including an untagged vlan.")}) # Validate untagged VLAN