diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 2ba3845f6..b86ef9d6a 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -755,3 +755,82 @@ class PortTypeChoices(ChoiceSet): TYPE_LSH: 2600, TYPE_LSH_APC: 2610, } + + +# +# Cables +# + +class CableTypeChoices(ChoiceSet): + + TYPE_CAT3 = 'cat3' + TYPE_CAT5 = 'cat5' + TYPE_CAT5E = 'cat5e' + TYPE_CAT6 = 'cat6' + TYPE_CAT6A = 'cat6a' + TYPE_CAT7 = 'cat7' + TYPE_DAC_ACTIVE = 'dac-active' + TYPE_DAC_PASSIVE = 'dac-passive' + TYPE_COAXIAL = 'coaxial' + TYPE_MMF = 'mmf' + TYPE_MMF_OM1 = 'mmf-om1' + TYPE_MMF_OM2 = 'mmf-om2' + TYPE_MMF_OM3 = 'mmf-om3' + TYPE_MMF_OM4 = 'mmf-om4' + TYPE_SMF = 'smf' + TYPE_SMF_OS1 = 'smf-os1' + TYPE_SMF_OS2 = 'smf-os2' + TYPE_AOC = 'aoc' + TYPE_POWER = 'power' + + CHOICES = ( + ( + 'Copper', ( + (TYPE_CAT3, 'CAT3'), + (TYPE_CAT5, 'CAT5'), + (TYPE_CAT5E, 'CAT5e'), + (TYPE_CAT6, 'CAT6'), + (TYPE_CAT6A, 'CAT6a'), + (TYPE_CAT7, 'CAT7'), + (TYPE_DAC_ACTIVE, 'Direct Attach Copper (Active)'), + (TYPE_DAC_PASSIVE, 'Direct Attach Copper (Passive)'), + (TYPE_COAXIAL, 'Coaxial'), + ), + ), + ( + 'Fiber', ( + (TYPE_MMF, 'Multimode Fiber'), + (TYPE_MMF_OM1, 'Multimode Fiber (OM1)'), + (TYPE_MMF_OM2, 'Multimode Fiber (OM2)'), + (TYPE_MMF_OM3, 'Multimode Fiber (OM3)'), + (TYPE_MMF_OM4, 'Multimode Fiber (OM4)'), + (TYPE_SMF, 'Singlemode Fiber'), + (TYPE_SMF_OS1, 'Singlemode Fiber (OS1)'), + (TYPE_SMF_OS2, 'Singlemode Fiber (OS2)'), + (TYPE_AOC, 'Active Optical Cabling (AOC)'), + ), + ), + (TYPE_POWER, 'Power'), + ) + + LEGACY_MAP = { + TYPE_CAT3: 1300, + TYPE_CAT5: 1500, + TYPE_CAT5E: 1510, + TYPE_CAT6: 1600, + TYPE_CAT6A: 1610, + TYPE_CAT7: 1700, + TYPE_DAC_ACTIVE: 1800, + TYPE_DAC_PASSIVE: 1810, + TYPE_COAXIAL: 1900, + TYPE_MMF: 3000, + TYPE_MMF_OM1: 3010, + TYPE_MMF_OM2: 3020, + TYPE_MMF_OM3: 3030, + TYPE_MMF_OM4: 3040, + TYPE_SMF: 3500, + TYPE_SMF_OS1: 3510, + TYPE_SMF_OS2: 3520, + TYPE_AOC: 3800, + TYPE_POWER: 5000, + } diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 5892df352..7aff330e5 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -45,56 +45,6 @@ CABLE_TERMINATION_TYPES = [ 'circuittermination', ] -# Cable types -CABLE_TYPE_CAT3 = 1300 -CABLE_TYPE_CAT5 = 1500 -CABLE_TYPE_CAT5E = 1510 -CABLE_TYPE_CAT6 = 1600 -CABLE_TYPE_CAT6A = 1610 -CABLE_TYPE_CAT7 = 1700 -CABLE_TYPE_DAC_ACTIVE = 1800 -CABLE_TYPE_DAC_PASSIVE = 1810 -CABLE_TYPE_COAXIAL = 1900 -CABLE_TYPE_MMF = 3000 -CABLE_TYPE_MMF_OM1 = 3010 -CABLE_TYPE_MMF_OM2 = 3020 -CABLE_TYPE_MMF_OM3 = 3030 -CABLE_TYPE_MMF_OM4 = 3040 -CABLE_TYPE_SMF = 3500 -CABLE_TYPE_SMF_OS1 = 3510 -CABLE_TYPE_SMF_OS2 = 3520 -CABLE_TYPE_AOC = 3800 -CABLE_TYPE_POWER = 5000 -CABLE_TYPE_CHOICES = ( - ( - 'Copper', ( - (CABLE_TYPE_CAT3, 'CAT3'), - (CABLE_TYPE_CAT5, 'CAT5'), - (CABLE_TYPE_CAT5E, 'CAT5e'), - (CABLE_TYPE_CAT6, 'CAT6'), - (CABLE_TYPE_CAT6A, 'CAT6a'), - (CABLE_TYPE_CAT7, 'CAT7'), - (CABLE_TYPE_DAC_ACTIVE, 'Direct Attach Copper (Active)'), - (CABLE_TYPE_DAC_PASSIVE, 'Direct Attach Copper (Passive)'), - (CABLE_TYPE_COAXIAL, 'Coaxial'), - ), - ), - ( - 'Fiber', ( - (CABLE_TYPE_MMF, 'Multimode Fiber'), - (CABLE_TYPE_MMF_OM1, 'Multimode Fiber (OM1)'), - (CABLE_TYPE_MMF_OM2, 'Multimode Fiber (OM2)'), - (CABLE_TYPE_MMF_OM3, 'Multimode Fiber (OM3)'), - (CABLE_TYPE_MMF_OM4, 'Multimode Fiber (OM4)'), - (CABLE_TYPE_SMF, 'Singlemode Fiber'), - (CABLE_TYPE_SMF_OS1, 'Singlemode Fiber (OS1)'), - (CABLE_TYPE_SMF_OS2, 'Singlemode Fiber (OS2)'), - (CABLE_TYPE_AOC, 'Active Optical Cabling (AOC)'), - ), - ), - (CABLE_TYPE_POWER, 'Power'), -) - CABLE_TERMINATION_TYPE_CHOICES = { # (API endpoint, human-friendly name) 'consoleport': ('console-ports', 'Console port'), diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index e3c6f64ac..4e8e21f6d 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -939,7 +939,7 @@ class CableFilter(django_filters.FilterSet): label='Search', ) type = django_filters.MultipleChoiceFilter( - choices=CABLE_TYPE_CHOICES + choices=CableTypeChoices ) status = django_filters.MultipleChoiceFilter( choices=CONNECTION_STATUS_CHOICES diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 51e454a16..8cfeb2736 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -3144,7 +3144,7 @@ class CableCSVForm(forms.ModelForm): help_text='Connection status' ) type = CSVChoiceField( - choices=CABLE_TYPE_CHOICES, + choices=CableTypeChoices, required=False, help_text='Cable type' ) @@ -3229,7 +3229,7 @@ class CableBulkEditForm(BootstrapMixin, BulkEditForm): widget=forms.MultipleHiddenInput ) type = forms.ChoiceField( - choices=add_blank_choice(CABLE_TYPE_CHOICES), + choices=add_blank_choice(CableTypeChoices), required=False, initial='', widget=StaticSelect2() @@ -3303,7 +3303,7 @@ class CableFilterForm(BootstrapMixin, forms.Form): ) ) type = forms.MultipleChoiceField( - choices=add_blank_choice(CABLE_TYPE_CHOICES), + choices=add_blank_choice(CableTypeChoices), required=False, widget=StaticSelect2() ) diff --git a/netbox/dcim/migrations/0083_3569_cable_fields.py b/netbox/dcim/migrations/0083_3569_cable_fields.py new file mode 100644 index 000000000..432935ecf --- /dev/null +++ b/netbox/dcim/migrations/0083_3569_cable_fields.py @@ -0,0 +1,54 @@ +from django.db import migrations, models + + +CABLE_TYPE_CHOICES = ( + (1300, 'cat3'), + (1500, 'cat5'), + (1510, 'cat5e'), + (1600, 'cat6'), + (1610, 'cat6a'), + (1700, 'cat7'), + (1800, 'dac-active'), + (1810, 'dac-passive'), + (1900, 'coaxial'), + (3000, 'mmf'), + (3010, 'mmf-om1'), + (3020, 'mmf-om2'), + (3030, 'mmf-om3'), + (3040, 'mmf-om4'), + (3500, 'smf'), + (3510, 'smf-os1'), + (3520, 'smf-os2'), + (3800, 'aoc'), + (5000, 'power'), +) + + +def cable_type_to_slug(apps, schema_editor): + Cable = apps.get_model('dcim', 'Cable') + for id, slug in CABLE_TYPE_CHOICES: + Cable.objects.filter(type=id).update(type=slug) + + +class Migration(migrations.Migration): + atomic = False + + dependencies = [ + ('dcim', '0082_3569_port_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='cable', + name='type', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=cable_type_to_slug + ), + migrations.AlterField( + model_name='cable', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + ] diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 926377f9f..3e1de04d7 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -2809,10 +2809,10 @@ class Cable(ChangeLoggedModel): ct_field='termination_b_type', fk_field='termination_b_id' ) - type = models.PositiveSmallIntegerField( - choices=CABLE_TYPE_CHOICES, - blank=True, - null=True + type = models.CharField( + max_length=50, + choices=CableTypeChoices, + blank=True ) status = models.BooleanField( choices=CONNECTION_STATUS_CHOICES, diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 6bda7c6c5..9315b201d 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -527,15 +527,15 @@ class CableTestCase(TestCase): iface6 = Interface(device=device2, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED) iface6.save() - Cable(termination_a=iface1, termination_b=iface4, type=CABLE_TYPE_CAT6).save() - Cable(termination_a=iface2, termination_b=iface5, type=CABLE_TYPE_CAT6).save() - Cable(termination_a=iface3, termination_b=iface6, type=CABLE_TYPE_CAT6).save() + Cable(termination_a=iface1, termination_b=iface4, type=CableTypeChoices.TYPE_CAT6).save() + Cable(termination_a=iface2, termination_b=iface5, type=CableTypeChoices.TYPE_CAT6).save() + Cable(termination_a=iface3, termination_b=iface6, type=CableTypeChoices.TYPE_CAT6).save() def test_cable_list(self): url = reverse('dcim:cable_list') params = { - "type": CABLE_TYPE_CAT6, + "type": CableTypeChoices.TYPE_CAT6, } response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))