diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 5204e6a0e..e6fb9df57 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -294,14 +294,14 @@ class ConsolePortTemplateSerializer(serializers.ModelSerializer): class Meta: model = ConsolePortTemplate - fields = ['id', 'device_type', 'name'] + fields = ['id', 'device_type', 'name', 'form_factor'] class WritableConsolePortTemplateSerializer(ValidatedModelSerializer): class Meta: model = ConsolePortTemplate - fields = ['id', 'device_type', 'name'] + fields = ['id', 'device_type', 'name', 'form_factor'] # @@ -313,14 +313,14 @@ class ConsoleServerPortTemplateSerializer(serializers.ModelSerializer): class Meta: model = ConsoleServerPortTemplate - fields = ['id', 'device_type', 'name'] + fields = ['id', 'device_type', 'name', 'form_factor'] class WritableConsoleServerPortTemplateSerializer(ValidatedModelSerializer): class Meta: model = ConsoleServerPortTemplate - fields = ['id', 'device_type', 'name'] + fields = ['id', 'device_type', 'name', 'form_factor'] # @@ -527,7 +527,7 @@ class ConsoleServerPortSerializer(serializers.ModelSerializer): class Meta: model = ConsoleServerPort - fields = ['id', 'device', 'name', 'connected_console'] + fields = ['id', 'device', 'name', 'connected_console', 'form_factor'] read_only_fields = ['connected_console'] @@ -535,7 +535,7 @@ class WritableConsoleServerPortSerializer(ValidatedModelSerializer): class Meta: model = ConsoleServerPort - fields = ['id', 'device', 'name'] + fields = ['id', 'device', 'name', 'form_factor'] # @@ -548,14 +548,14 @@ class ConsolePortSerializer(serializers.ModelSerializer): class Meta: model = ConsolePort - fields = ['id', 'device', 'name', 'cs_port', 'connection_status'] + fields = ['id', 'device', 'name', 'cs_port', 'connection_status', 'form_factor'] class WritableConsolePortSerializer(ValidatedModelSerializer): class Meta: model = ConsolePort - fields = ['id', 'device', 'name', 'cs_port', 'connection_status'] + fields = ['id', 'device', 'name', 'cs_port', 'connection_status', 'form_factor'] # diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index b355e6c85..3a6be41f9 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -87,6 +87,9 @@ IFACE_FF_T1 = 4000 IFACE_FF_E1 = 4010 IFACE_FF_T3 = 4040 IFACE_FF_E3 = 4050 +IFACE_FF_RJ45_S = 4060 +IFACE_FF_DE9_S = 4070 +IFACE_FF_DB25_S = 4080 # Stacking IFACE_FF_STACKWISE = 5000 IFACE_FF_STACKWISE_PLUS = 5050 @@ -96,6 +99,15 @@ IFACE_FF_JUNIPER_VCP = 5200 # Other IFACE_FF_OTHER = 32767 +# Console +IFACE_FF_CON_RJ45 = 6000 +IFACE_FF_CON_DE9 = 6010 +IFACE_FF_CON_DB25 = 6020 +IFACE_FF_CON_USB = 6030 +IFACE_FF_CON_MCUSB = 6040 +IFACE_FF_CON_MNUSB = 6050 +IFACE_FF_CON_KVM = 6060 + IFACE_FF_CHOICES = [ [ 'Virtual interfaces', @@ -158,6 +170,9 @@ IFACE_FF_CHOICES = [ [IFACE_FF_E1, 'E1 (2.048 Mbps)'], [IFACE_FF_T3, 'T3 (45 Mbps)'], [IFACE_FF_E3, 'E3 (34 Mbps)'], + [IFACE_FF_RJ45_S, 'RJ45'], + [IFACE_FF_DE9_S, 'DE9'], + [IFACE_FF_DB25_S, 'DB25'], ] ], [ @@ -178,6 +193,31 @@ IFACE_FF_CHOICES = [ ], ] +CONSOLE_FF_CHOICES = [ + [ + 'Console', + [ + [IFACE_FF_CON_RJ45, 'RJ45 Serial'], + [IFACE_FF_CON_DE9, 'DE9 Serial'], + [IFACE_FF_CON_DB25, 'DB25 Serial'], + [IFACE_FF_CON_USB, 'USB to Serial'], + [IFACE_FF_CON_MCUSB, 'Micro USB to Serial'], + [IFACE_FF_CON_MNUSB, 'Mini USB to Serial'], + [IFACE_FF_CON_KVM, 'KVM'], + ] + ], +] + +CONSOLE_IFACE_TYPES = [ + IFACE_FF_CON_RJ45, + IFACE_FF_CON_DE9, + IFACE_FF_CON_DB25, + IFACE_FF_CON_USB, + IFACE_FF_CON_MCUSB, + IFACE_FF_CON_MNUSB, + IFACE_FF_CON_KVM, +] + VIRTUAL_IFACE_TYPES = [ IFACE_FF_VIRTUAL, IFACE_FF_LAG, diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 98c075cd3..7db5274f9 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -22,7 +22,7 @@ from virtualization.models import Cluster from .constants import ( CONNECTION_STATUS_CHOICES, CONNECTION_STATUS_CONNECTED, IFACE_FF_CHOICES, IFACE_FF_LAG, IFACE_ORDERING_CHOICES, RACK_FACE_CHOICES, RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES, RACK_WIDTH_19IN, RACK_WIDTH_23IN, STATUS_CHOICES, - SUBDEVICE_ROLE_CHILD, SUBDEVICE_ROLE_PARENT, SUBDEVICE_ROLE_CHOICES, + SUBDEVICE_ROLE_CHILD, SUBDEVICE_ROLE_PARENT, SUBDEVICE_ROLE_CHOICES, CONSOLE_FF_CHOICES ) from .formfields import MACAddressFormField from .models import ( @@ -550,7 +550,7 @@ class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm): class Meta: model = ConsolePortTemplate - fields = ['device_type', 'name'] + fields = ['device_type', 'name', 'form_factor'] widgets = { 'device_type': forms.HiddenInput(), } @@ -558,13 +558,14 @@ class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm): class ConsolePortTemplateCreateForm(ComponentForm): name_pattern = ExpandableNameField(label='Name') + form_factor = forms.ChoiceField(choices=CONSOLE_FF_CHOICES) class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm): class Meta: model = ConsoleServerPortTemplate - fields = ['device_type', 'name'] + fields = ['device_type', 'name', 'form_factor'] widgets = { 'device_type': forms.HiddenInput(), } @@ -572,6 +573,7 @@ class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm): class ConsoleServerPortTemplateCreateForm(ComponentForm): name_pattern = ExpandableNameField(label='Name') + form_factor = forms.ChoiceField(choices=CONSOLE_FF_CHOICES) class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm): @@ -1088,7 +1090,7 @@ class ConsolePortForm(BootstrapMixin, forms.ModelForm): class Meta: model = ConsolePort - fields = ['device', 'name'] + fields = ['device', 'name', 'form_factor'] widgets = { 'device': forms.HiddenInput(), } @@ -1096,6 +1098,7 @@ class ConsolePortForm(BootstrapMixin, forms.ModelForm): class ConsolePortCreateForm(ComponentForm): name_pattern = ExpandableNameField(label='Name') + form_factor = forms.ChoiceField(choices=CONSOLE_FF_CHOICES) class ConsoleConnectionCSVForm(forms.ModelForm): @@ -1257,7 +1260,7 @@ class ConsoleServerPortForm(BootstrapMixin, forms.ModelForm): class Meta: model = ConsoleServerPort - fields = ['device', 'name'] + fields = ['device', 'name', 'form_factor'] widgets = { 'device': forms.HiddenInput(), } @@ -1265,6 +1268,7 @@ class ConsoleServerPortForm(BootstrapMixin, forms.ModelForm): class ConsoleServerPortCreateForm(ComponentForm): name_pattern = ExpandableNameField(label='Name') + form_factor = forms.ChoiceField(choices=CONSOLE_FF_CHOICES) class ConsoleServerPortConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.Form): diff --git a/netbox/dcim/migrations/0050_serial_and_console_form_factors.py b/netbox/dcim/migrations/0050_serial_and_console_form_factors.py new file mode 100644 index 000000000..fc14e45e6 --- /dev/null +++ b/netbox/dcim/migrations/0050_serial_and_console_form_factors.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-09 18:43 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0049_rackreservation_change_user'), + ] + + operations = [ + migrations.AddField( + model_name='consoleserverport', + name='form_factor', + field=models.PositiveSmallIntegerField(null=True, choices=[['Console', + [[6000, 'RJ45 Serial'], + [6010, 'DE9 Serial'], + [6020, 'DB25 Serial'], + [6030, 'USB to Serial'], + [6040, 'Micro USB to Serial'], + [6050, 'Mini USB to Serial'], + [6060, 'KVM']]]]) + ), + migrations.AddField( + model_name='consoleserverporttemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(null=True, choices=[['Console', + [[6000, 'RJ45 Serial'], + [6010, 'DE9 Serial'], + [6020, 'DB25 Serial'], + [6030, 'USB to Serial'], + [6040, 'Micro USB to Serial'], + [6050, 'Mini USB to Serial'], + [6060, 'KVM']]]]) + ), + migrations.AddField( + model_name='consoleport', + name='form_factor', + field=models.PositiveSmallIntegerField(null=True, choices=[['Console', + [[6000, 'RJ45 Serial'], + [6010, 'DE9 Serial'], + [6020, 'DB25 Serial'], + [6030, 'USB to Serial'], + [6040, 'Micro USB to Serial'], + [6050, 'Mini USB to Serial'], + [6060, 'KVM']]]]) + ), + migrations.AddField( + model_name='consoleporttemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(null=True, choices=[['Console', + [[6000, 'RJ45 Serial'], + [6010, 'DE9 Serial'], + [6020, 'DB25 Serial'], + [6030, 'USB to Serial'], + [6040, 'Micro USB to Serial'], + [6050, 'Mini USB to Serial'], + [6060, 'KVM']]]]) + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1510, 'CFP2 (100GE)'], [1520, 'CFP4 (100GE)'], [1550, 'Cisco CPAK (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)'], [4060, 'RJ45'], [4070, 'DE9'], [4080, 'DB25']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1510, 'CFP2 (100GE)'], [1520, 'CFP4 (100GE)'], [1550, 'Cisco CPAK (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)'], [4060, 'RJ45'], [4070, 'DE9'], [4080, 'DB25']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + ] diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 2b1f403e7..786202888 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -641,6 +641,7 @@ class ConsolePortTemplate(models.Model): """ device_type = models.ForeignKey('DeviceType', related_name='console_port_templates', on_delete=models.CASCADE) name = models.CharField(max_length=50) + form_factor = models.PositiveSmallIntegerField(choices=CONSOLE_FF_CHOICES, default=IFACE_FF_CON_RJ45) class Meta: ordering = ['device_type', 'name'] @@ -657,6 +658,7 @@ class ConsoleServerPortTemplate(models.Model): """ device_type = models.ForeignKey('DeviceType', related_name='cs_port_templates', on_delete=models.CASCADE) name = models.CharField(max_length=50) + form_factor = models.PositiveSmallIntegerField(choices=CONSOLE_FF_CHOICES, default=IFACE_FF_CON_RJ45) class Meta: ordering = ['device_type', 'name'] @@ -961,11 +963,11 @@ class Device(CreatedUpdatedModel, CustomFieldModel): # If this is a new Device, instantiate all of the related components per the DeviceType definition if is_new: ConsolePort.objects.bulk_create( - [ConsolePort(device=self, name=template.name) for template in + [ConsolePort(device=self, name=template.name, form_factor=template.form_factor) for template in self.device_type.console_port_templates.all()] ) ConsoleServerPort.objects.bulk_create( - [ConsoleServerPort(device=self, name=template.name) for template in + [ConsoleServerPort(device=self, name=template.name, form_factor=template.form_factor) for template in self.device_type.cs_port_templates.all()] ) PowerPort.objects.bulk_create( @@ -1063,11 +1065,12 @@ class ConsolePort(models.Model): """ device = models.ForeignKey('Device', related_name='console_ports', on_delete=models.CASCADE) name = models.CharField(max_length=50) + form_factor = models.PositiveSmallIntegerField(choices=CONSOLE_FF_CHOICES, default=IFACE_FF_CON_RJ45) cs_port = models.OneToOneField('ConsoleServerPort', related_name='connected_console', on_delete=models.SET_NULL, verbose_name='Console server port', blank=True, null=True) connection_status = models.NullBooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED) - csv_headers = ['console_server', 'cs_port', 'device', 'console_port', 'connection_status'] + csv_headers = ['console_server', 'cs_port', 'device', 'console_port', 'form_factor', 'connection_status'] class Meta: ordering = ['device', 'name'] @@ -1108,6 +1111,7 @@ class ConsoleServerPort(models.Model): """ device = models.ForeignKey('Device', related_name='cs_ports', on_delete=models.CASCADE) name = models.CharField(max_length=50) + form_factor = models.PositiveSmallIntegerField(choices=CONSOLE_FF_CHOICES, default=IFACE_FF_CON_RJ45) objects = ConsoleServerPortManager() diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index 0349396fa..cd8b535e6 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -305,7 +305,7 @@ class ConsolePortTemplateTable(BaseTable): class Meta(BaseTable.Meta): model = ConsolePortTemplate - fields = ('pk', 'name') + fields = ('pk', 'name', 'form_factor') empty_text = "None" @@ -314,7 +314,7 @@ class ConsoleServerPortTemplateTable(BaseTable): class Meta(BaseTable.Meta): model = ConsoleServerPortTemplate - fields = ('pk', 'name') + fields = ('pk', 'name', 'form_factor') empty_text = "None" diff --git a/netbox/templates/dcim/inc/consoleport.html b/netbox/templates/dcim/inc/consoleport.html index 62375c7f2..c2095906d 100644 --- a/netbox/templates/dcim/inc/consoleport.html +++ b/netbox/templates/dcim/inc/consoleport.html @@ -2,6 +2,9 @@ {{ cp }} + + {{ cp.get_form_factor_display }} + {% if cp.cs_port %} {{ cp.cs_port.device }} diff --git a/netbox/templates/dcim/inc/powerport.html b/netbox/templates/dcim/inc/powerport.html index 555d6d3ee..9d1db6b2f 100644 --- a/netbox/templates/dcim/inc/powerport.html +++ b/netbox/templates/dcim/inc/powerport.html @@ -3,6 +3,7 @@ {{ pp }} {% if pp.power_outlet %} + {{ pp.power_outlet.device }} @@ -10,6 +11,7 @@ {{ pp.power_outlet }} {% else %} + Not connected