From bb6fb81fc0e5dfd5512f5928b4038a8ae4b7e19b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Feb 2019 14:34:05 -0500 Subject: [PATCH] Closes #2643: Add description field to console/power components and device bays --- CHANGELOG.md | 1 + netbox/dcim/api/serializers.py | 18 +++--- netbox/dcim/filters.py | 22 +++---- netbox/dcim/forms.py | 58 +++++++++++++++++-- .../0071_device_components_add_description.py | 38 ++++++++++++ netbox/dcim/models.py | 35 +++++------ netbox/templates/dcim/device.html | 3 + netbox/templates/dcim/inc/consoleport.html | 5 ++ .../templates/dcim/inc/consoleserverport.html | 9 ++- netbox/templates/dcim/inc/devicebay.html | 32 +++++++--- netbox/templates/dcim/inc/poweroutlet.html | 9 ++- netbox/templates/dcim/inc/powerport.html | 5 ++ 12 files changed, 181 insertions(+), 54 deletions(-) create mode 100644 netbox/dcim/migrations/0071_device_components_add_description.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 30fcca53211..13bb12931f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ the Config Context from being included in any results. ## Enhancements * [#2324](https://github.com/digitalocean/netbox/issues/2324) - Add color option for tags +* [#2643](https://github.com/digitalocean/netbox/issues/2643) - Add `description` field to console/power components and device bays * [#2791](https://github.com/digitalocean/netbox/issues/2791) - Add a comment field for tags --- diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index c17400a359b..82bd9b6be51 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -346,8 +346,8 @@ class ConsoleServerPortSerializer(TaggitSerializer, ConnectedEndpointSerializer) class Meta: model = ConsoleServerPort fields = [ - 'id', 'device', 'name', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', - 'tags', + 'id', 'device', 'name', 'description', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', + 'cable', 'tags', ] @@ -359,8 +359,8 @@ class ConsolePortSerializer(TaggitSerializer, ConnectedEndpointSerializer): class Meta: model = ConsolePort fields = [ - 'id', 'device', 'name', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', - 'tags', + 'id', 'device', 'name', 'description', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', + 'cable', 'tags', ] @@ -372,8 +372,8 @@ class PowerOutletSerializer(TaggitSerializer, ConnectedEndpointSerializer): class Meta: model = PowerOutlet fields = [ - 'id', 'device', 'name', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', - 'tags', + 'id', 'device', 'name', 'description', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', + 'cable', 'tags', ] @@ -385,8 +385,8 @@ class PowerPortSerializer(TaggitSerializer, ConnectedEndpointSerializer): class Meta: model = PowerPort fields = [ - 'id', 'device', 'name', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', - 'tags', + 'id', 'device', 'name', 'description', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', + 'cable', 'tags', ] @@ -475,7 +475,7 @@ class DeviceBaySerializer(TaggitSerializer, ValidatedModelSerializer): class Meta: model = DeviceBay - fields = ['id', 'device', 'name', 'installed_device', 'tags'] + fields = ['id', 'device', 'name', 'description', 'installed_device', 'tags'] # diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 4974c3b4d62..4b22b20027f 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -689,7 +689,8 @@ def search(self, queryset, name, value): if not value.strip(): return queryset return queryset.filter( - Q(name__icontains=value) + Q(name__icontains=value) | + Q(description__icontains=value) ) @@ -702,7 +703,7 @@ class ConsolePortFilter(DeviceComponentFilterSet): class Meta: model = ConsolePort - fields = ['name', 'connection_status'] + fields = ['name', 'description', 'connection_status'] class ConsoleServerPortFilter(DeviceComponentFilterSet): @@ -714,7 +715,7 @@ class ConsoleServerPortFilter(DeviceComponentFilterSet): class Meta: model = ConsoleServerPort - fields = ['name', 'connection_status'] + fields = ['name', 'description', 'connection_status'] class PowerPortFilter(DeviceComponentFilterSet): @@ -726,7 +727,7 @@ class PowerPortFilter(DeviceComponentFilterSet): class Meta: model = PowerPort - fields = ['name', 'connection_status'] + fields = ['name', 'description', 'connection_status'] class PowerOutletFilter(DeviceComponentFilterSet): @@ -738,7 +739,7 @@ class PowerOutletFilter(DeviceComponentFilterSet): class Meta: model = PowerOutlet - fields = ['name', 'connection_status'] + fields = ['name', 'description', 'connection_status'] class InterfaceFilter(django_filters.FilterSet): @@ -793,13 +794,14 @@ class InterfaceFilter(django_filters.FilterSet): class Meta: model = Interface - fields = ['name', 'connection_status', 'form_factor', 'enabled', 'mtu', 'mgmt_only'] + fields = ['name', 'connection_status', 'form_factor', 'enabled', 'mtu', 'mgmt_only', 'description'] def search(self, queryset, name, value): if not value.strip(): return queryset return queryset.filter( - Q(name__icontains=value) + Q(name__icontains=value) | + Q(description__icontains=value) ).distinct() def filter_device(self, queryset, name, value): @@ -857,7 +859,7 @@ class FrontPortFilter(DeviceComponentFilterSet): class Meta: model = FrontPort - fields = ['name', 'type'] + fields = ['name', 'type', 'description'] class RearPortFilter(DeviceComponentFilterSet): @@ -869,14 +871,14 @@ class RearPortFilter(DeviceComponentFilterSet): class Meta: model = RearPort - fields = ['name', 'type'] + fields = ['name', 'type', 'description'] class DeviceBayFilter(DeviceComponentFilterSet): class Meta: model = DeviceBay - fields = ['name'] + fields = ['name', 'description'] class InventoryItemFilter(DeviceComponentFilterSet): diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index bf774dfcbd7..18627c2f554 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -1854,7 +1854,7 @@ class ConsolePortForm(BootstrapMixin, forms.ModelForm): class Meta: model = ConsolePort fields = [ - 'device', 'name', 'tags', + 'device', 'name', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), @@ -1865,6 +1865,10 @@ class ConsolePortCreateForm(ComponentForm): name_pattern = ExpandableNameField( label='Name' ) + description = forms.CharField( + max_length=100, + required=False + ) tags = TagField( required=False ) @@ -1882,7 +1886,7 @@ class ConsoleServerPortForm(BootstrapMixin, forms.ModelForm): class Meta: model = ConsoleServerPort fields = [ - 'device', 'name', 'tags', + 'device', 'name', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), @@ -1893,11 +1897,31 @@ class ConsoleServerPortCreateForm(ComponentForm): name_pattern = ExpandableNameField( label='Name' ) + description = forms.CharField( + max_length=100, + required=False + ) tags = TagField( required=False ) +class ConsoleServerPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): + pk = forms.ModelMultipleChoiceField( + queryset=ConsoleServerPort.objects.all(), + widget=forms.MultipleHiddenInput() + ) + description = forms.CharField( + max_length=100, + required=False + ) + + class Meta: + nullable_fields = [ + 'description', + ] + + class ConsoleServerPortBulkRenameForm(BulkRenameForm): pk = forms.ModelMultipleChoiceField( queryset=ConsoleServerPort.objects.all(), @@ -1924,7 +1948,7 @@ class PowerPortForm(BootstrapMixin, forms.ModelForm): class Meta: model = PowerPort fields = [ - 'device', 'name', 'tags', + 'device', 'name', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), @@ -1935,6 +1959,10 @@ class PowerPortCreateForm(ComponentForm): name_pattern = ExpandableNameField( label='Name' ) + description = forms.CharField( + max_length=100, + required=False + ) tags = TagField( required=False ) @@ -1952,7 +1980,7 @@ class PowerOutletForm(BootstrapMixin, forms.ModelForm): class Meta: model = PowerOutlet fields = [ - 'device', 'name', 'tags', + 'device', 'name', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), @@ -1963,11 +1991,31 @@ class PowerOutletCreateForm(ComponentForm): name_pattern = ExpandableNameField( label='Name' ) + description = forms.CharField( + max_length=100, + required=False + ) tags = TagField( required=False ) +class PowerOutletBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): + pk = forms.ModelMultipleChoiceField( + queryset=PowerOutlet.objects.all(), + widget=forms.MultipleHiddenInput() + ) + description = forms.CharField( + max_length=100, + required=False + ) + + class Meta: + nullable_fields = [ + 'description', + ] + + class PowerOutletBulkRenameForm(BulkRenameForm): pk = forms.ModelMultipleChoiceField( queryset=PowerOutlet.objects.all(), @@ -2776,7 +2824,7 @@ class DeviceBayForm(BootstrapMixin, forms.ModelForm): class Meta: model = DeviceBay fields = [ - 'device', 'name', 'tags', + 'device', 'name', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), diff --git a/netbox/dcim/migrations/0071_device_components_add_description.py b/netbox/dcim/migrations/0071_device_components_add_description.py new file mode 100644 index 00000000000..d38f8a88b86 --- /dev/null +++ b/netbox/dcim/migrations/0071_device_components_add_description.py @@ -0,0 +1,38 @@ +# Generated by Django 2.1.7 on 2019-02-20 18:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0070_custom_tag_models'), + ] + + operations = [ + migrations.AddField( + model_name='consoleport', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='consoleserverport', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='devicebay', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='poweroutlet', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='powerport', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + ] diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 3715e30331e..b7675b34e05 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -46,6 +46,10 @@ def log_change(self, user, request_id, action): class ComponentModel(models.Model): + description = models.CharField( + max_length=100, + blank=True + ) class Meta: abstract = True @@ -1745,7 +1749,7 @@ class ConsolePort(CableTermination, ComponentModel): objects = DeviceComponentManager() tags = TaggableManager(through=TaggedItem) - csv_headers = ['device', 'name'] + csv_headers = ['device', 'name', 'description'] class Meta: ordering = ['device', 'name'] @@ -1761,6 +1765,7 @@ def to_csv(self): return ( self.device.identifier, self.name, + self.description, ) @@ -1788,7 +1793,7 @@ class ConsoleServerPort(CableTermination, ComponentModel): objects = DeviceComponentManager() tags = TaggableManager(through=TaggedItem) - csv_headers = ['device', 'name'] + csv_headers = ['device', 'name', 'description'] class Meta: unique_together = ['device', 'name'] @@ -1803,6 +1808,7 @@ def to_csv(self): return ( self.device.identifier, self.name, + self.description, ) @@ -1841,7 +1847,7 @@ class PowerPort(CableTermination, ComponentModel): class Meta: ordering = ['device', 'name'] - unique_together = ['device', 'name'] + unique_together = ['device', 'name', 'description'] def __str__(self): return self.name @@ -1853,6 +1859,7 @@ def to_csv(self): return ( self.device.identifier, self.name, + self.description, ) @@ -1883,7 +1890,7 @@ class PowerOutlet(CableTermination, ComponentModel): csv_headers = ['device', 'name'] class Meta: - unique_together = ['device', 'name'] + unique_together = ['device', 'name', 'description'] def __str__(self): return self.name @@ -1895,6 +1902,7 @@ def to_csv(self): return ( self.device.identifier, self.name, + self.description, ) @@ -1973,10 +1981,6 @@ class Interface(CableTermination, ComponentModel): verbose_name='OOB Management', help_text='This interface is used only for out-of-band management' ) - description = models.CharField( - max_length=100, - blank=True - ) mode = models.PositiveSmallIntegerField( choices=IFACE_MODE_CHOICES, blank=True, @@ -2193,10 +2197,6 @@ class FrontPort(CableTermination, ComponentModel): default=1, validators=[MinValueValidator(1), MaxValueValidator(64)] ) - description = models.CharField( - max_length=100, - blank=True - ) objects = DeviceComponentManager() tags = TaggableManager(through=TaggedItem) @@ -2259,10 +2259,6 @@ class RearPort(CableTermination, ComponentModel): default=1, validators=[MinValueValidator(1), MaxValueValidator(64)] ) - description = models.CharField( - max_length=100, - blank=True - ) objects = DeviceComponentManager() tags = TaggableManager(through=TaggedItem) @@ -2314,7 +2310,7 @@ class DeviceBay(ComponentModel): objects = DeviceComponentManager() tags = TaggableManager(through=TaggedItem) - csv_headers = ['device', 'name', 'installed_device'] + csv_headers = ['device', 'name', 'installed_device', 'description'] class Meta: ordering = ['device', 'name'] @@ -2331,6 +2327,7 @@ def to_csv(self): self.device.identifier, self.name, self.installed_device.identifier if self.installed_device else None, + self.description, ) def clean(self): @@ -2400,10 +2397,6 @@ class InventoryItem(ComponentModel): default=False, verbose_name='Discovered' ) - description = models.CharField( - max_length=100, - blank=True - ) tags = TaggableManager(through=TaggedItem) diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 716752c57b7..895f5eb591c 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -445,6 +445,7 @@

{{ device }}

{% endif %} Name Status + Description Installed Device @@ -570,6 +571,7 @@

{{ device }}

{% endif %} Name + Description Cable Connection @@ -625,6 +627,7 @@

{{ device }}

{% endif %} Name + Description Cable Connection diff --git a/netbox/templates/dcim/inc/consoleport.html b/netbox/templates/dcim/inc/consoleport.html index e78ab7ea7de..74b13fdbcf4 100644 --- a/netbox/templates/dcim/inc/consoleport.html +++ b/netbox/templates/dcim/inc/consoleport.html @@ -5,6 +5,11 @@ {{ cp }} + {# Description #} + + {{ cp.description }} + + {# Cable #} {% if cp.cable %} diff --git a/netbox/templates/dcim/inc/consoleserverport.html b/netbox/templates/dcim/inc/consoleserverport.html index 212846b0074..93f89a1e0aa 100644 --- a/netbox/templates/dcim/inc/consoleserverport.html +++ b/netbox/templates/dcim/inc/consoleserverport.html @@ -1,3 +1,5 @@ +{% load helpers %} + {# Checkbox #} @@ -12,12 +14,17 @@ {{ csp }} + {# Description #} + + {{ csp.description|placeholder }} + + {# Cable #} {% if csp.cable %} {{ csp.cable }} {% else %} - — + {% endif %} diff --git a/netbox/templates/dcim/inc/devicebay.html b/netbox/templates/dcim/inc/devicebay.html index dc2977855ec..9ae8958ec38 100644 --- a/netbox/templates/dcim/inc/devicebay.html +++ b/netbox/templates/dcim/inc/devicebay.html @@ -1,16 +1,35 @@ +{% load helpers %} + {% if perms.dcim.change_devicebay or perms.dcim.delete_devicebay %} {% endif %} + + {# Name #} {{ devicebay.name }} + + {# Status #} + + {% if devicebay.installed_device %} + + {{ devicebay.installed_device.get_status_display }} + + {% else %} + Vacant + {% endif %} + + + {# Description #} + + {{ devicebay.description|placeholder }} + + + {# Installed device #} {% if devicebay.installed_device %} - - {{ devicebay.installed_device.get_status_display }} - {{ devicebay.installed_device }} @@ -18,11 +37,10 @@ {{ devicebay.installed_device.device_type.display_name }} {% else %} - - - Vacant - + {% endif %} + + {# Actions #} {% if perms.dcim.change_devicebay %} {% if devicebay.installed_device %} diff --git a/netbox/templates/dcim/inc/poweroutlet.html b/netbox/templates/dcim/inc/poweroutlet.html index 54ce414adca..7b359d36d71 100644 --- a/netbox/templates/dcim/inc/poweroutlet.html +++ b/netbox/templates/dcim/inc/poweroutlet.html @@ -1,3 +1,5 @@ +{% load helpers %} + {# Checkbox #} @@ -12,12 +14,17 @@ {{ po }} + {# Description #} + + {{ po.description|placeholder }} + + {# Cable #} {% if po.cable %} {{ po.cable }} {% else %} - — + {% endif %} diff --git a/netbox/templates/dcim/inc/powerport.html b/netbox/templates/dcim/inc/powerport.html index 4bfbdadcfe4..55838399e4a 100644 --- a/netbox/templates/dcim/inc/powerport.html +++ b/netbox/templates/dcim/inc/powerport.html @@ -5,6 +5,11 @@ {{ pp }} + {# Description #} + + {{ pp.description }} + + {# Cable #} {% if pp.cable %}