Parcourir la source

Interface.mode to slug (#3569)

Jeremy Stretch il y a 6 ans
Parent
commit
3fa4ceadb0

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

@@ -469,7 +469,7 @@ class InterfaceSerializer(TaggitSerializer, ConnectedEndpointSerializer):
     device = NestedDeviceSerializer()
     type = ChoiceField(choices=InterfaceTypeChoices, required=False)
     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)
     tagged_vlans = SerializedPKRelatedField(
         queryset=VLAN.objects.all(),

+ 24 - 9
netbox/dcim/choices.py

@@ -111,9 +111,7 @@ class DeviceFaceChoices(ChoiceSet):
 #
 
 class ConsolePortTypeChoices(ChoiceSet):
-    """
-    ConsolePort/ConsoleServerPort.type slugs
-    """
+
     TYPE_DE9 = 'de-9'
     TYPE_DB25 = 'db-25'
     TYPE_RJ45 = 'rj-45'
@@ -152,6 +150,7 @@ class ConsolePortTypeChoices(ChoiceSet):
 #
 
 class PowerPortTypeChoices(ChoiceSet):
+
     # TODO: Add more power port types
     # IEC 60320
     TYPE_IEC_C6 = 'iec-60320-c6'
@@ -239,6 +238,7 @@ class PowerPortTypeChoices(ChoiceSet):
 #
 
 class PowerOutletTypeChoices(ChoiceSet):
+
     # TODO: Add more power outlet types
     # IEC 60320
     TYPE_IEC_C5 = 'iec-60320-c5'
@@ -326,9 +326,7 @@ class PowerOutletTypeChoices(ChoiceSet):
 #
 
 class InterfaceTypeChoices(ChoiceSet):
-    """
-    Interface.type slugs
-    """
+
     # Virtual
     TYPE_VIRTUAL = 'virtual'
     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
 #
 
 class PortTypeChoices(ChoiceSet):
-    """
-    FrontPort/RearPort.type slugs
-    """
+
     TYPE_8P8C = '8p8c'
     TYPE_110_PUNCH = '110-punch'
     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
 
-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
 PORT_TYPE_8P8C = 1000

+ 4 - 4
netbox/dcim/forms.py

@@ -66,13 +66,13 @@ class InterfaceCommonForm:
         tagged_vlans = self.cleaned_data['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({
                 'mode': "An access interface cannot have tagged VLANs assigned."
             })
 
         # 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'] = []
 
 
@@ -2450,7 +2450,7 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form):
         required=False
     )
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         widget=StaticSelect2(),
     )
@@ -2564,7 +2564,7 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo
         required=False
     )
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         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):
     InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate')
     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)
 
 
+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):
     atomic = False
 
@@ -111,4 +124,17 @@ class Migration(migrations.Migration):
         migrations.RunPython(
             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',
         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,
-        null=True
     )
     untagged_vlan = models.ForeignKey(
         to='ipam.VLAN',
@@ -2373,7 +2373,7 @@ class Interface(CableTermination, ComponentModel):
             self.untagged_vlan = None
 
         # 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()
 
         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 circuits.models import Circuit, CircuitTermination, CircuitType, Provider
-from dcim.choices import SubdeviceRoleChoices
+from dcim.choices import InterfaceModeChoices, SubdeviceRoleChoices
 from dcim.constants import *
 from dcim.models import (
     Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
@@ -2474,7 +2474,7 @@ class InterfaceTest(APITestCase):
         data = {
             'device': self.device.pk,
             'name': 'Test Interface 4',
-            'mode': IFACE_MODE_TAGGED,
+            'mode': InterfaceModeChoices.MODE_TAGGED,
             'untagged_vlan': self.vlan3.id,
             'tagged_vlans': [self.vlan1.id, self.vlan2.id],
         }
@@ -2521,21 +2521,21 @@ class InterfaceTest(APITestCase):
             {
                 'device': self.device.pk,
                 'name': 'Test Interface 4',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
             },
             {
                 'device': self.device.pk,
                 'name': 'Test Interface 5',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.id,
                 'tagged_vlans': [self.vlan1.id],
             },
             {
                 'device': self.device.pk,
                 'name': 'Test Interface 6',
-                'mode': IFACE_MODE_TAGGED,
+                'mode': InterfaceModeChoices.MODE_TAGGED,
                 'untagged_vlan': self.vlan2.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 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 extras.api.customfields import CustomFieldModelSerializer
 from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
@@ -100,7 +99,7 @@ class VirtualMachineWithConfigContextSerializer(VirtualMachineSerializer):
 class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
     virtual_machine = NestedVirtualMachineSerializer()
     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)
     tagged_vlans = SerializedPKRelatedField(
         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 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.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
 from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
@@ -718,13 +717,13 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm):
         tagged_vlans = self.cleaned_data['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({
                 'mode': "An access interface cannot have tagged VLANs assigned."
             })
 
         # 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'] = []
 
 
@@ -755,7 +754,7 @@ class InterfaceCreateForm(ComponentForm):
         required=False
     )
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         widget=StaticSelect2(),
     )
@@ -840,7 +839,7 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
         required=False
     )
     mode = forms.ChoiceField(
-        choices=add_blank_choice(IFACE_MODE_CHOICES),
+        choices=add_blank_choice(InterfaceModeChoices),
         required=False,
         widget=StaticSelect2()
     )

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

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