Jeremy Stretch 6 лет назад
Родитель
Сommit
3fa4ceadb0

+ 1 - 1
netbox/dcim/api/serializers.py

@@ -469,7 +469,7 @@ class InterfaceSerializer(TaggitSerializer, ConnectedEndpointSerializer):
     device = NestedDeviceSerializer()
     device = NestedDeviceSerializer()
     type = ChoiceField(choices=InterfaceTypeChoices, required=False)
     type = ChoiceField(choices=InterfaceTypeChoices, required=False)
     lag = NestedInterfaceSerializer(required=False, allow_null=True)
     lag = NestedInterfaceSerializer(required=False, allow_null=True)
-    mode = ChoiceField(choices=IFACE_MODE_CHOICES, required=False, allow_null=True)
+    mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_null=True)
     untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
     untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
     tagged_vlans = SerializedPKRelatedField(
     tagged_vlans = SerializedPKRelatedField(
         queryset=VLAN.objects.all(),
         queryset=VLAN.objects.all(),

+ 24 - 9
netbox/dcim/choices.py

@@ -111,9 +111,7 @@ class DeviceFaceChoices(ChoiceSet):
 #
 #
 
 
 class ConsolePortTypeChoices(ChoiceSet):
 class ConsolePortTypeChoices(ChoiceSet):
-    """
-    ConsolePort/ConsoleServerPort.type slugs
-    """
+
     TYPE_DE9 = 'de-9'
     TYPE_DE9 = 'de-9'
     TYPE_DB25 = 'db-25'
     TYPE_DB25 = 'db-25'
     TYPE_RJ45 = 'rj-45'
     TYPE_RJ45 = 'rj-45'
@@ -152,6 +150,7 @@ class ConsolePortTypeChoices(ChoiceSet):
 #
 #
 
 
 class PowerPortTypeChoices(ChoiceSet):
 class PowerPortTypeChoices(ChoiceSet):
+
     # TODO: Add more power port types
     # TODO: Add more power port types
     # IEC 60320
     # IEC 60320
     TYPE_IEC_C6 = 'iec-60320-c6'
     TYPE_IEC_C6 = 'iec-60320-c6'
@@ -239,6 +238,7 @@ class PowerPortTypeChoices(ChoiceSet):
 #
 #
 
 
 class PowerOutletTypeChoices(ChoiceSet):
 class PowerOutletTypeChoices(ChoiceSet):
+
     # TODO: Add more power outlet types
     # TODO: Add more power outlet types
     # IEC 60320
     # IEC 60320
     TYPE_IEC_C5 = 'iec-60320-c5'
     TYPE_IEC_C5 = 'iec-60320-c5'
@@ -326,9 +326,7 @@ class PowerOutletTypeChoices(ChoiceSet):
 #
 #
 
 
 class InterfaceTypeChoices(ChoiceSet):
 class InterfaceTypeChoices(ChoiceSet):
-    """
-    Interface.type slugs
-    """
+
     # Virtual
     # Virtual
     TYPE_VIRTUAL = 'virtual'
     TYPE_VIRTUAL = 'virtual'
     TYPE_LAG = 'lag'
     TYPE_LAG = 'lag'
@@ -623,14 +621,31 @@ class InterfaceTypeChoices(ChoiceSet):
     }
     }
 
 
 
 
+class InterfaceModeChoices(ChoiceSet):
+
+    MODE_ACCESS = 'access'
+    MODE_TAGGED = 'tagged'
+    MODE_TAGGED_ALL = 'tagged-all'
+
+    CHOICES = (
+        (MODE_ACCESS, 'Access'),
+        (MODE_TAGGED, 'Tagged'),
+        (MODE_TAGGED_ALL, 'Tagged (All)'),
+    )
+
+    LEGACY_MAP = {
+        MODE_ACCESS: 100,
+        MODE_TAGGED: 200,
+        MODE_TAGGED_ALL: 300,
+    }
+
+
 #
 #
 # FrontPorts/RearPorts
 # FrontPorts/RearPorts
 #
 #
 
 
 class PortTypeChoices(ChoiceSet):
 class PortTypeChoices(ChoiceSet):
-    """
-    FrontPort/RearPort.type slugs
-    """
+
     TYPE_8P8C = '8p8c'
     TYPE_8P8C = '8p8c'
     TYPE_110_PUNCH = '110-punch'
     TYPE_110_PUNCH = '110-punch'
     TYPE_BNC = 'bnc'
     TYPE_BNC = 'bnc'

+ 0 - 8
netbox/dcim/constants.py

@@ -20,14 +20,6 @@ WIRELESS_IFACE_TYPES = [
 
 
 NONCONNECTABLE_IFACE_TYPES = VIRTUAL_IFACE_TYPES + WIRELESS_IFACE_TYPES
 NONCONNECTABLE_IFACE_TYPES = VIRTUAL_IFACE_TYPES + WIRELESS_IFACE_TYPES
 
 
-IFACE_MODE_ACCESS = 100
-IFACE_MODE_TAGGED = 200
-IFACE_MODE_TAGGED_ALL = 300
-IFACE_MODE_CHOICES = [
-    [IFACE_MODE_ACCESS, 'Access'],
-    [IFACE_MODE_TAGGED, 'Tagged'],
-    [IFACE_MODE_TAGGED_ALL, 'Tagged All'],
-]
 
 
 # Pass-through port types
 # Pass-through port types
 PORT_TYPE_8P8C = 1000
 PORT_TYPE_8P8C = 1000

+ 4 - 4
netbox/dcim/forms.py

@@ -66,13 +66,13 @@ class InterfaceCommonForm:
         tagged_vlans = self.cleaned_data['tagged_vlans']
         tagged_vlans = self.cleaned_data['tagged_vlans']
 
 
         # Untagged interfaces cannot be assigned tagged VLANs
         # Untagged interfaces cannot be assigned tagged VLANs
-        if self.cleaned_data['mode'] == IFACE_MODE_ACCESS and tagged_vlans:
+        if self.cleaned_data['mode'] == InterfaceModeChoices.MODE_ACCESS and tagged_vlans:
             raise forms.ValidationError({
             raise forms.ValidationError({
                 'mode': "An access interface cannot have tagged VLANs assigned."
                 'mode': "An access interface cannot have tagged VLANs assigned."
             })
             })
 
 
         # Remove all tagged VLAN assignments from "tagged all" interfaces
         # Remove all tagged VLAN assignments from "tagged all" interfaces
-        elif self.cleaned_data['mode'] == IFACE_MODE_TAGGED_ALL:
+        elif self.cleaned_data['mode'] == InterfaceModeChoices.MODE_TAGGED_ALL:
             self.cleaned_data['tagged_vlans'] = []
             self.cleaned_data['tagged_vlans'] = []
 
 
 
 
@@ -2450,7 +2450,7 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form):
         required=False
         required=False
     )
     )
     mode = forms.ChoiceField(
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         required=False,
         widget=StaticSelect2(),
         widget=StaticSelect2(),
     )
     )
@@ -2564,7 +2564,7 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo
         required=False
         required=False
     )
     )
     mode = forms.ChoiceField(
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         required=False,
         widget=StaticSelect2()
         widget=StaticSelect2()
     )
     )

+ 26 - 0
netbox/dcim/migrations/0082_3569_interface_fields.py

@@ -75,6 +75,13 @@ INTERFACE_TYPE_CHOICES = (
 )
 )
 
 
 
 
+INTERFACE_MODE_CHOICES = (
+    (100, 'access'),
+    (200, 'tagged'),
+    (300, 'tagged-all'),
+)
+
+
 def interfacetemplate_type_to_slug(apps, schema_editor):
 def interfacetemplate_type_to_slug(apps, schema_editor):
     InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate')
     InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate')
     for id, slug in INTERFACE_TYPE_CHOICES:
     for id, slug in INTERFACE_TYPE_CHOICES:
@@ -87,6 +94,12 @@ def interface_type_to_slug(apps, schema_editor):
         Interface.objects.filter(type=id).update(type=slug)
         Interface.objects.filter(type=id).update(type=slug)
 
 
 
 
+def interface_mode_to_slug(apps, schema_editor):
+    Interface = apps.get_model('dcim', 'Interface')
+    for id, slug in INTERFACE_MODE_CHOICES:
+        Interface.objects.filter(mode=id).update(mode=slug)
+
+
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
     atomic = False
     atomic = False
 
 
@@ -111,4 +124,17 @@ class Migration(migrations.Migration):
         migrations.RunPython(
         migrations.RunPython(
             code=interface_type_to_slug
             code=interface_type_to_slug
         ),
         ),
+        migrations.AlterField(
+            model_name='interface',
+            name='mode',
+            field=models.CharField(blank=True, default='', max_length=50),
+        ),
+        migrations.RunPython(
+            code=interface_mode_to_slug
+        ),
+        migrations.AlterField(
+            model_name='interface',
+            name='mode',
+            field=models.CharField(blank=True, max_length=50),
+        ),
     ]
     ]

+ 4 - 4
netbox/dcim/models.py

@@ -2261,10 +2261,10 @@ class Interface(CableTermination, ComponentModel):
         verbose_name='OOB Management',
         verbose_name='OOB Management',
         help_text='This interface is used only for out-of-band management'
         help_text='This interface is used only for out-of-band management'
     )
     )
-    mode = models.PositiveSmallIntegerField(
-        choices=IFACE_MODE_CHOICES,
+    mode = models.CharField(
+        max_length=50,
+        choices=InterfaceModeChoices,
         blank=True,
         blank=True,
-        null=True
     )
     )
     untagged_vlan = models.ForeignKey(
     untagged_vlan = models.ForeignKey(
         to='ipam.VLAN',
         to='ipam.VLAN',
@@ -2373,7 +2373,7 @@ class Interface(CableTermination, ComponentModel):
             self.untagged_vlan = None
             self.untagged_vlan = None
 
 
         # Only "tagged" interfaces may have tagged VLANs assigned. ("tagged all" implies all VLANs are assigned.)
         # Only "tagged" interfaces may have tagged VLANs assigned. ("tagged all" implies all VLANs are assigned.)
-        if self.pk and self.mode is not IFACE_MODE_TAGGED:
+        if self.pk and self.mode is not InterfaceModeChoices.MODE_TAGGED:
             self.tagged_vlans.clear()
             self.tagged_vlans.clear()
 
 
         return super().save(*args, **kwargs)
         return super().save(*args, **kwargs)

+ 5 - 5
netbox/dcim/tests/test_api.py

@@ -3,7 +3,7 @@ from netaddr import IPNetwork
 from rest_framework import status
 from rest_framework import status
 
 
 from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
 from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
-from dcim.choices import SubdeviceRoleChoices
+from dcim.choices import InterfaceModeChoices, SubdeviceRoleChoices
 from dcim.constants import *
 from dcim.constants import *
 from dcim.models import (
 from dcim.models import (
     Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
     Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
@@ -2474,7 +2474,7 @@ class InterfaceTest(APITestCase):
         data = {
         data = {
             'device': self.device.pk,
             'device': self.device.pk,
             'name': 'Test Interface 4',
             'name': 'Test Interface 4',
-            'mode': IFACE_MODE_TAGGED,
+            'mode': InterfaceModeChoices.MODE_TAGGED,
             'untagged_vlan': self.vlan3.id,
             'untagged_vlan': self.vlan3.id,
             'tagged_vlans': [self.vlan1.id, self.vlan2.id],
             'tagged_vlans': [self.vlan1.id, self.vlan2.id],
         }
         }
@@ -2521,21 +2521,21 @@ class InterfaceTest(APITestCase):
             {
             {
                 'device': self.device.pk,
                 'device': self.device.pk,
                 'name': 'Test Interface 4',
                 'name': 'Test Interface 4',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
                 'tagged_vlans': [self.vlan1.id],
             },
             },
             {
             {
                 'device': self.device.pk,
                 'device': self.device.pk,
                 'name': 'Test Interface 5',
                 'name': 'Test Interface 5',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
                 'tagged_vlans': [self.vlan1.id],
             },
             },
             {
             {
                 'device': self.device.pk,
                 'device': self.device.pk,
                 'name': 'Test Interface 6',
                 'name': 'Test Interface 6',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
                 'tagged_vlans': [self.vlan1.id],
             },
             },

+ 2 - 3
netbox/virtualization/api/serializers.py

@@ -3,8 +3,7 @@ from rest_framework import serializers
 from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
 from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
 
 
 from dcim.api.nested_serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer
 from dcim.api.nested_serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer
-from dcim.choices import InterfaceTypeChoices
-from dcim.constants import IFACE_MODE_CHOICES
+from dcim.choices import InterfaceModeChoices, InterfaceTypeChoices
 from dcim.models import Interface
 from dcim.models import Interface
 from extras.api.customfields import CustomFieldModelSerializer
 from extras.api.customfields import CustomFieldModelSerializer
 from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
 from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
@@ -100,7 +99,7 @@ class VirtualMachineWithConfigContextSerializer(VirtualMachineSerializer):
 class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
 class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
     virtual_machine = NestedVirtualMachineSerializer()
     virtual_machine = NestedVirtualMachineSerializer()
     type = ChoiceField(choices=InterfaceTypeChoices, default=InterfaceTypeChoices.TYPE_VIRTUAL, required=False)
     type = ChoiceField(choices=InterfaceTypeChoices, default=InterfaceTypeChoices.TYPE_VIRTUAL, required=False)
-    mode = ChoiceField(choices=IFACE_MODE_CHOICES, required=False, allow_null=True)
+    mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_null=True)
     untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
     untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
     tagged_vlans = SerializedPKRelatedField(
     tagged_vlans = SerializedPKRelatedField(
         queryset=VLAN.objects.all(),
         queryset=VLAN.objects.all(),

+ 5 - 6
netbox/virtualization/forms.py

@@ -2,8 +2,7 @@ from django import forms
 from django.core.exceptions import ValidationError
 from django.core.exceptions import ValidationError
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
-from dcim.choices import InterfaceTypeChoices
-from dcim.constants import IFACE_MODE_ACCESS, IFACE_MODE_TAGGED_ALL, IFACE_MODE_CHOICES
+from dcim.choices import InterfaceModeChoices, InterfaceTypeChoices
 from dcim.forms import INTERFACE_MODE_HELP_TEXT
 from dcim.forms import INTERFACE_MODE_HELP_TEXT
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
 from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
 from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
@@ -718,13 +717,13 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm):
         tagged_vlans = self.cleaned_data['tagged_vlans']
         tagged_vlans = self.cleaned_data['tagged_vlans']
 
 
         # Untagged interfaces cannot be assigned tagged VLANs
         # Untagged interfaces cannot be assigned tagged VLANs
-        if self.cleaned_data['mode'] == IFACE_MODE_ACCESS and tagged_vlans:
+        if self.cleaned_data['mode'] == InterfaceModeChoices.MODE_ACCESS and tagged_vlans:
             raise forms.ValidationError({
             raise forms.ValidationError({
                 'mode': "An access interface cannot have tagged VLANs assigned."
                 'mode': "An access interface cannot have tagged VLANs assigned."
             })
             })
 
 
         # Remove all tagged VLAN assignments from "tagged all" interfaces
         # Remove all tagged VLAN assignments from "tagged all" interfaces
-        elif self.cleaned_data['mode'] == IFACE_MODE_TAGGED_ALL:
+        elif self.cleaned_data['mode'] == InterfaceModeChoices.MODE_TAGGED_ALL:
             self.cleaned_data['tagged_vlans'] = []
             self.cleaned_data['tagged_vlans'] = []
 
 
 
 
@@ -755,7 +754,7 @@ class InterfaceCreateForm(ComponentForm):
         required=False
         required=False
     )
     )
     mode = forms.ChoiceField(
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         required=False,
         widget=StaticSelect2(),
         widget=StaticSelect2(),
     )
     )
@@ -840,7 +839,7 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
         required=False
         required=False
     )
     )
     mode = forms.ChoiceField(
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         required=False,
         widget=StaticSelect2()
         widget=StaticSelect2()
     )
     )

+ 5 - 6
netbox/virtualization/tests/test_api.py

@@ -2,8 +2,7 @@ from django.urls import reverse
 from netaddr import IPNetwork
 from netaddr import IPNetwork
 from rest_framework import status
 from rest_framework import status
 
 
-from dcim.choices import InterfaceTypeChoices
-from dcim.constants import IFACE_MODE_TAGGED
+from dcim.choices import InterfaceModeChoices, InterfaceTypeChoices
 from dcim.models import Interface
 from dcim.models import Interface
 from ipam.models import IPAddress, VLAN
 from ipam.models import IPAddress, VLAN
 from utilities.testing import APITestCase
 from utilities.testing import APITestCase
@@ -552,7 +551,7 @@ class InterfaceTest(APITestCase):
         data = {
         data = {
             'virtual_machine': self.virtualmachine.pk,
             'virtual_machine': self.virtualmachine.pk,
             'name': 'Test Interface 4',
             'name': 'Test Interface 4',
-            'mode': IFACE_MODE_TAGGED,
+            'mode': InterfaceModeChoices.MODE_TAGGED,
             'untagged_vlan': self.vlan3.id,
             'untagged_vlan': self.vlan3.id,
             'tagged_vlans': [self.vlan1.id, self.vlan2.id],
             'tagged_vlans': [self.vlan1.id, self.vlan2.id],
         }
         }
@@ -599,21 +598,21 @@ class InterfaceTest(APITestCase):
             {
             {
                 'virtual_machine': self.virtualmachine.pk,
                 'virtual_machine': self.virtualmachine.pk,
                 'name': 'Test Interface 4',
                 'name': 'Test Interface 4',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
                 'tagged_vlans': [self.vlan1.id],
             },
             },
             {
             {
                 'virtual_machine': self.virtualmachine.pk,
                 'virtual_machine': self.virtualmachine.pk,
                 'name': 'Test Interface 5',
                 'name': 'Test Interface 5',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
                 'tagged_vlans': [self.vlan1.id],
             },
             },
             {
             {
                 'virtual_machine': self.virtualmachine.pk,
                 'virtual_machine': self.virtualmachine.pk,
                 'name': 'Test Interface 6',
                 'name': 'Test Interface 6',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
                 'tagged_vlans': [self.vlan1.id],
             },
             },