From 05570ae4ade98eca869a07767f932af23d06e3a6 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Tue, 31 Dec 2019 20:47:13 +0000 Subject: [PATCH 01/16] Clean tagged VLANs --- netbox/dcim/forms.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 1774fc986..e4bd12c80 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -74,6 +74,15 @@ class InterfaceCommonForm: elif self.cleaned_data['mode'] == IFACE_MODE_TAGGED_ALL: self.cleaned_data['tagged_vlans'] = [] + # Validate tagged VLANs; must be a global VLAN or in the same site + else: + for tagged_vlan in tagged_vlans: + if tagged_vlan.site not in [self.cleaned_data['device'].site, None]: + raise forms.ValidationError({ + 'tagged_vlans': "The tagged VLAN ({}) must belong to the same site as the interface's parent " + "device/VM, or it must be global".format(tagged_vlan) + }) + class BulkRenameForm(forms.Form): """ From aa4f73ffbfa3c23a5d64595753f18a32fc672dfd Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 1 Jan 2020 12:09:51 +0000 Subject: [PATCH 02/16] Removed trailing space --- netbox/dcim/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index e4bd12c80..19fcc30dc 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -74,7 +74,7 @@ class InterfaceCommonForm: elif self.cleaned_data['mode'] == IFACE_MODE_TAGGED_ALL: self.cleaned_data['tagged_vlans'] = [] - # Validate tagged VLANs; must be a global VLAN or in the same site + # Validate tagged VLANs; must be a global VLAN or in the same site else: for tagged_vlan in tagged_vlans: if tagged_vlan.site not in [self.cleaned_data['device'].site, None]: From a110b0badbd8370e06ce8c0edfb1d82640a6bebe Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 1 Jan 2020 16:43:21 +0000 Subject: [PATCH 03/16] Removed no-longer-used choices (now handled via API-based select) --- netbox/dcim/forms.py | 90 -------------------------------------------- 1 file changed, 90 deletions(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 19fcc30dc..da4beb6bb 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2236,36 +2236,6 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): device__in=[self.instance.device, self.instance.device.get_vc_master()], type=IFACE_TYPE_LAG ) - # Limit VLan choices to those in: global vlans, global groups, the current site's group, the current site - vlan_choices = [] - global_vlans = VLAN.objects.filter(site=None, group=None) - vlan_choices.append( - ('Global', [(vlan.pk, vlan) for vlan in global_vlans]) - ) - for group in VLANGroup.objects.filter(site=None): - global_group_vlans = VLAN.objects.filter(group=group) - vlan_choices.append( - (group.name, [(vlan.pk, vlan) for vlan in global_group_vlans]) - ) - - site = getattr(self.instance.parent, 'site', None) - if site is not None: - - # Add non-grouped site VLANs - site_vlans = VLAN.objects.filter(site=site, group=None) - vlan_choices.append((site.name, [(vlan.pk, vlan) for vlan in site_vlans])) - - # Add grouped site VLANs - for group in VLANGroup.objects.filter(site=site): - site_group_vlans = VLAN.objects.filter(group=group) - vlan_choices.append(( - '{} / {}'.format(group.site.name, group.name), - [(vlan.pk, vlan) for vlan in site_group_vlans] - )) - - self.fields['untagged_vlan'].choices = [(None, '---------')] + vlan_choices - self.fields['tagged_vlans'].choices = vlan_choices - class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): name_pattern = ExpandableNameField( @@ -2346,36 +2316,6 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): else: self.fields['lag'].queryset = Interface.objects.none() - # Limit VLan choices to those in: global vlans, global groups, the current site's group, the current site - vlan_choices = [] - global_vlans = VLAN.objects.filter(site=None, group=None) - vlan_choices.append( - ('Global', [(vlan.pk, vlan) for vlan in global_vlans]) - ) - for group in VLANGroup.objects.filter(site=None): - global_group_vlans = VLAN.objects.filter(group=group) - vlan_choices.append( - (group.name, [(vlan.pk, vlan) for vlan in global_group_vlans]) - ) - - site = getattr(self.parent, 'site', None) - if site is not None: - - # Add non-grouped site VLANs - site_vlans = VLAN.objects.filter(site=site, group=None) - vlan_choices.append((site.name, [(vlan.pk, vlan) for vlan in site_vlans])) - - # Add grouped site VLANs - for group in VLANGroup.objects.filter(site=site): - site_group_vlans = VLAN.objects.filter(group=group) - vlan_choices.append(( - '{} / {}'.format(group.site.name, group.name), - [(vlan.pk, vlan) for vlan in site_group_vlans] - )) - - self.fields['untagged_vlan'].choices = [(None, '---------')] + vlan_choices - self.fields['tagged_vlans'].choices = vlan_choices - class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsForm, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -2458,36 +2398,6 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo else: self.fields['lag'].choices = [] - # Limit VLan choices to those in: global vlans, global groups, the current site's group, the current site - vlan_choices = [] - global_vlans = VLAN.objects.filter(site=None, group=None) - vlan_choices.append( - ('Global', [(vlan.pk, vlan) for vlan in global_vlans]) - ) - for group in VLANGroup.objects.filter(site=None): - global_group_vlans = VLAN.objects.filter(group=group) - vlan_choices.append( - (group.name, [(vlan.pk, vlan) for vlan in global_group_vlans]) - ) - if self.parent_obj is not None: - site = getattr(self.parent_obj, 'site', None) - if site is not None: - - # Add non-grouped site VLANs - site_vlans = VLAN.objects.filter(site=site, group=None) - vlan_choices.append((site.name, [(vlan.pk, vlan) for vlan in site_vlans])) - - # Add grouped site VLANs - for group in VLANGroup.objects.filter(site=site): - site_group_vlans = VLAN.objects.filter(group=group) - vlan_choices.append(( - '{} / {}'.format(group.site.name, group.name), - [(vlan.pk, vlan) for vlan in site_group_vlans] - )) - - self.fields['untagged_vlan'].choices = [(None, '---------')] + vlan_choices - self.fields['tagged_vlans'].choices = vlan_choices - class InterfaceBulkRenameForm(BulkRenameForm): pk = forms.ModelMultipleChoiceField( From d267aeb62112015db2f4b1cdf90afda348bfd700 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 1 Jan 2020 17:34:26 +0000 Subject: [PATCH 04/16] Filter VLANs to only those in the current site or global --- netbox/dcim/forms.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index da4beb6bb..7fc50f54b 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2185,6 +2185,9 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): widget=APISelect( api_url="/api/ipam/vlans/", display_field='display_name', + additional_query_params={ + 'site_id': 'null' + }, full=True ) ) @@ -2194,6 +2197,9 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): widget=APISelectMultiple( api_url="/api/ipam/vlans/", display_field='display_name', + additional_query_params={ + 'site_id': 'null' + }, full=True ) ) @@ -2236,6 +2242,10 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): device__in=[self.instance.device, self.instance.device.get_vc_master()], type=IFACE_TYPE_LAG ) + # Add the current site to the list of filtered VLANs + self.fields['untagged_vlan'].widget.attrs['1-data-additional-query-param-site_id'] = self.instance.device.site.pk + self.fields['tagged_vlans'].widget.attrs['1-data-additional-query-param-site_id'] = self.instance.device.site.pk + class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): name_pattern = ExpandableNameField( @@ -2287,6 +2297,9 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): widget=APISelect( api_url="/api/ipam/vlans/", display_field='display_name', + additional_query_params={ + 'site_id': 'null' + }, full=True ) ) @@ -2296,6 +2309,9 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): widget=APISelectMultiple( api_url="/api/ipam/vlans/", display_field='display_name', + additional_query_params={ + 'site_id': 'null' + }, full=True ) ) @@ -2316,6 +2332,10 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): else: self.fields['lag'].queryset = Interface.objects.none() + # Add the current site to the list of filtered VLANs + self.fields['untagged_vlan'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent.site.pk + self.fields['tagged_vlans'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent.site.pk + class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsForm, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -2367,6 +2387,9 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo widget=APISelect( api_url="/api/ipam/vlans/", display_field='display_name', + additional_query_params={ + 'site_id': 'null' + }, full=True ) ) @@ -2376,6 +2399,9 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo widget=APISelectMultiple( api_url="/api/ipam/vlans/", display_field='display_name', + additional_query_params={ + 'site_id': 'null' + }, full=True ) ) @@ -2398,6 +2424,10 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo else: self.fields['lag'].choices = [] + # Add the current site to the list of filtered VLANs + self.fields['untagged_vlan'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent_obj.site.pk + self.fields['tagged_vlans'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent_obj.site.pk + class InterfaceBulkRenameForm(BulkRenameForm): pk = forms.ModelMultipleChoiceField( From 1a57120b789435b1bc27139e0563bfe7a984794a Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 1 Jan 2020 17:43:39 +0000 Subject: [PATCH 05/16] 3589 changelog --- docs/release-notes/version-2.6.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 548492438..c6a509ab0 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -9,6 +9,7 @@ ## Bug Fixes * [#3106](https://github.com/netbox-community/netbox/issues/3106) - Restrict queryset of chained fields when form validation fails +* [#3589](https://github.com/netbox-community/netbox/issues/3589) - Limit the list of available VLANs to those valid and perform input validation on the tagged VLANs * [#3695](https://github.com/netbox-community/netbox/issues/3695) - Include A/Z termination sites for circuits in global search * [#3712](https://github.com/netbox-community/netbox/issues/3712) - Scrolling to target (hash) did not account for the header size * [#3780](https://github.com/netbox-community/netbox/issues/3780) - Fix AttributeError exception in API docs From 7ad9e8a2fbd5e655143a7a40d2d4b41765dd1f4d Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 1 Jan 2020 19:53:13 +0000 Subject: [PATCH 06/16] More informative error message --- netbox/dcim/forms.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 7fc50f54b..3c515152e 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -76,12 +76,14 @@ class InterfaceCommonForm: # Validate tagged VLANs; must be a global VLAN or in the same site else: - for tagged_vlan in tagged_vlans: - if tagged_vlan.site not in [self.cleaned_data['device'].site, None]: - raise forms.ValidationError({ - 'tagged_vlans': "The tagged VLAN ({}) must belong to the same site as the interface's parent " - "device/VM, or it must be global".format(tagged_vlan) - }) + valid_sites = [None, self.cleaned_data['device'].site] + invalid_vlans = [str(v) for v in tagged_vlans if v.site not in valid_sites] + + if invalid_vlans: + raise forms.ValidationError({ + 'tagged_vlans': "The tagged VLANs ({}) must belong to the same site as the interface's parent " + "device/VM, or they must be global".format(', '.join(invalid_vlans)) + }) class BulkRenameForm(forms.Form): From d3c6caf8a8db5cc643f0f5ed7fab2c78dff97c28 Mon Sep 17 00:00:00 2001 From: hSaria <34197532+hSaria@users.noreply.github.com> Date: Thu, 2 Jan 2020 17:52:22 +0000 Subject: [PATCH 07/16] Limit tagged validation to tagged interfaces Co-Authored-By: Jeremy Stretch --- netbox/dcim/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 3c515152e..902541353 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -75,7 +75,7 @@ class InterfaceCommonForm: self.cleaned_data['tagged_vlans'] = [] # Validate tagged VLANs; must be a global VLAN or in the same site - else: + elif self.cleaned_data['mode'] == IFACE_MODE_TAGGED: valid_sites = [None, self.cleaned_data['device'].site] invalid_vlans = [str(v) for v in tagged_vlans if v.site not in valid_sites] From 4b19073b8becd42d0d3a0622114b1ef9e46f9450 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Sat, 4 Jan 2020 13:30:31 +0000 Subject: [PATCH 08/16] Fixed #3187: Rack multi-selection field --- netbox/dcim/forms.py | 28 ++++++++++++++++++++++++++++ netbox/dcim/views.py | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index a5ce2811c..bbdbe251d 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -703,6 +703,34 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): ) +# +# Rack elevations +# + +class RackElevationFilterForm(RackFilterForm): + field_order = ['q', 'region', 'site', 'group_id', 'id', 'status', 'role', 'tenant_group', 'tenant'] + id = ChainedModelChoiceField( + queryset=Rack.objects.all(), + label='Rack', + chains=( + ('site', 'site'), + ('group_id', 'group_id'), + ), + required=False, + widget=APISelectMultiple( + api_url='/api/dcim/racks/', + display_field='display_name', + ) + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Filter the rack field based on the site and group + self.fields['site'].widget.add_filter_for('id', 'site') + self.fields['group_id'].widget.add_filter_for('id', 'group_id') + + # # Rack reservations # diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 959e1043e..2d98515cf 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -388,7 +388,7 @@ class RackElevationListView(PermissionRequiredMixin, View): 'page': page, 'total_count': total_count, 'face_id': face_id, - 'filter_form': forms.RackFilterForm(request.GET), + 'filter_form': forms.RackElevationFilterForm(request.GET), }) From dba40cd6bc124629319da89b06bf7c3a839be7f5 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Sat, 4 Jan 2020 13:32:07 +0000 Subject: [PATCH 09/16] Changelog (may conflict because adding headers) --- docs/release-notes/version-2.6.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 2bf55d857..ccbcfb754 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -1,3 +1,11 @@ +# v2.6.12 (FUTURE) + +## Enhancements + +* [#3187](https://github.com/netbox-community/netbox/issues/3187) - Add rack selection field to rack elevations + +--- + # v2.6.11 (2020-01-03) ## Bug Fixes From 792f38334a61ab2ee1004148f60dac0dab847939 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Sat, 4 Jan 2020 18:17:41 +0000 Subject: [PATCH 10/16] Fixes #2050: Image preview for attachments --- netbox/project-static/js/forms.js | 39 +++++++++++++++++++++ netbox/templates/inc/image_attachments.html | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/netbox/project-static/js/forms.js b/netbox/project-static/js/forms.js index 55f9afbd5..43c722ae5 100644 --- a/netbox/project-static/js/forms.js +++ b/netbox/project-static/js/forms.js @@ -398,4 +398,43 @@ $(document).ready(function() { // Account for the header height when hash-scrolling window.addEventListener('load', headerOffsetScroll); window.addEventListener('hashchange', headerOffsetScroll); + + // Offset between the preview window and the window edges + const IMAGE_PREVIEW_OFFSET_X = 20 + const IMAGE_PREVIEW_OFFSET_Y = 10 + + // Preview an image attachment when the link is hovered over + $('a.image-preview').on('mouseover', function(e) { + // Twice the offset to account for all sides of the picture + var maxWidth = window.innerWidth - (e.clientX + (IMAGE_PREVIEW_OFFSET_X * 2)); + var maxHeight = window.innerHeight - (e.clientY + (IMAGE_PREVIEW_OFFSET_Y * 2)); + var img = $('').attr('id', 'image-preview-window').css({ + display: 'none', + position: 'absolute', + maxWidth: maxWidth + 'px', + maxHeight: maxHeight + 'px', + left: e.pageX + IMAGE_PREVIEW_OFFSET_X + 'px', + top: e.pageY + IMAGE_PREVIEW_OFFSET_Y + 'px', + boxShadow: '0 0px 12px 3px rgba(0, 0, 0, 0.4)', + }); + + // Remove any existing preview windows and add the current one + $('#image-preview-window').remove(); + $('body').append(img); + + // Once loaded, show the preview if the image is indeed an image + img.on('load', function(e) { + if (e.target.complete && e.target.naturalWidth) { + $('#image-preview-window').fadeIn('fast'); + } + }); + + // Begin loading + img.attr('src', e.target.href); + }); + + // Fade the image out; it will be deleted when another one is previewed + $('a.image-preview').on('mouseout', function() { + $('#image-preview-window').fadeOut('fast') + }); }); diff --git a/netbox/templates/inc/image_attachments.html b/netbox/templates/inc/image_attachments.html index 1487b5349..2fee4dc78 100644 --- a/netbox/templates/inc/image_attachments.html +++ b/netbox/templates/inc/image_attachments.html @@ -10,7 +10,7 @@ - {{ attachment }} + {{ attachment }} {{ attachment.size|filesizeformat }} {{ attachment.created }} From 067af26892f4a3a92814150bead550a5964f5ae0 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Sat, 4 Jan 2020 18:19:05 +0000 Subject: [PATCH 11/16] Changelog (may conflict with other merges) --- docs/release-notes/version-2.6.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 2bf55d857..942f1c55b 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -1,3 +1,11 @@ +# v2.6.12 (FUTURE) + +## Enhancements + +* [#2050](https://github.com/netbox-community/netbox/issues/2050) - Preview image attachments when hovering the link + +--- + # v2.6.11 (2020-01-03) ## Bug Fixes From c45daca5f2376ce5b061b232f6c3a80b40aa6a0e Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Sun, 5 Jan 2020 09:10:46 +0000 Subject: [PATCH 12/16] Removed changes that will be covered in #3840 --- netbox/dcim/forms.py | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 932e9695a..52f49558f 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2210,9 +2210,6 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): widget=APISelect( api_url="/api/ipam/vlans/", display_field='display_name', - additional_query_params={ - 'site_id': 'null' - }, full=True ) ) @@ -2222,9 +2219,6 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): widget=APISelectMultiple( api_url="/api/ipam/vlans/", display_field='display_name', - additional_query_params={ - 'site_id': 'null' - }, full=True ) ) @@ -2267,10 +2261,6 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): device__in=[self.instance.device, self.instance.device.get_vc_master()], type=IFACE_TYPE_LAG ) - # Add the current site to the list of filtered VLANs - self.fields['untagged_vlan'].widget.attrs['1-data-additional-query-param-site_id'] = self.instance.device.site.pk - self.fields['tagged_vlans'].widget.attrs['1-data-additional-query-param-site_id'] = self.instance.device.site.pk - class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): name_pattern = ExpandableNameField( @@ -2322,9 +2312,6 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): widget=APISelect( api_url="/api/ipam/vlans/", display_field='display_name', - additional_query_params={ - 'site_id': 'null' - }, full=True ) ) @@ -2334,9 +2321,6 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): widget=APISelectMultiple( api_url="/api/ipam/vlans/", display_field='display_name', - additional_query_params={ - 'site_id': 'null' - }, full=True ) ) @@ -2357,10 +2341,6 @@ class InterfaceCreateForm(InterfaceCommonForm, ComponentForm, forms.Form): else: self.fields['lag'].queryset = Interface.objects.none() - # Add the current site to the list of filtered VLANs - self.fields['untagged_vlan'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent.site.pk - self.fields['tagged_vlans'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent.site.pk - class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsForm, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -2412,9 +2392,6 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo widget=APISelect( api_url="/api/ipam/vlans/", display_field='display_name', - additional_query_params={ - 'site_id': 'null' - }, full=True ) ) @@ -2424,9 +2401,6 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo widget=APISelectMultiple( api_url="/api/ipam/vlans/", display_field='display_name', - additional_query_params={ - 'site_id': 'null' - }, full=True ) ) @@ -2449,10 +2423,6 @@ class InterfaceBulkEditForm(InterfaceCommonForm, BootstrapMixin, AddRemoveTagsFo else: self.fields['lag'].choices = [] - # Add the current site to the list of filtered VLANs - self.fields['untagged_vlan'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent_obj.site.pk - self.fields['tagged_vlans'].widget.attrs['1-data-additional-query-param-site_id'] = self.parent_obj.site.pk - class InterfaceBulkRenameForm(BulkRenameForm): pk = forms.ModelMultipleChoiceField( From 7dddd4734ce5225aad0bcf1fecbf7d9c7aff1d70 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Sun, 5 Jan 2020 09:11:58 +0000 Subject: [PATCH 13/16] Updated changelog --- docs/release-notes/version-2.6.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 77c2f42b7..6b4cebae7 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -1,3 +1,11 @@ +# v2.6.12 (FUTURE) + +## Bug Fixes + +* [#3589](https://github.com/netbox-community/netbox/issues/3589) - Fix validation on tagged VLANs of an interface + +--- + # v2.6.11 (2020-01-03) ## Bug Fixes @@ -24,7 +32,6 @@ ## Bug Fixes * [#3106](https://github.com/netbox-community/netbox/issues/3106) - Restrict queryset of chained fields when form validation fails -* [#3589](https://github.com/netbox-community/netbox/issues/3589) - Limit the list of available VLANs to those valid and perform input validation on the tagged VLANs * [#3695](https://github.com/netbox-community/netbox/issues/3695) - Include A/Z termination sites for circuits in global search * [#3712](https://github.com/netbox-community/netbox/issues/3712) - Scrolling to target (hash) did not account for the header size * [#3780](https://github.com/netbox-community/netbox/issues/3780) - Fix AttributeError exception in API docs From e7ee4486a5ac99e996ae36e95751297157f02cc5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 7 Jan 2020 09:08:31 -0500 Subject: [PATCH 14/16] Fixes #3853: Fix device role link on config context view --- docs/release-notes/version-2.6.md | 1 + netbox/templates/extras/configcontext.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 4b4160d95..510e4253a 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -8,6 +8,7 @@ ## Bug Fixes * [#3589](https://github.com/netbox-community/netbox/issues/3589) - Fix validation on tagged VLANs of an interface +* [#3853](https://github.com/netbox-community/netbox/issues/3853) - Fix device role link on config context view --- diff --git a/netbox/templates/extras/configcontext.html b/netbox/templates/extras/configcontext.html index 3631122c3..f1ff4fa1f 100644 --- a/netbox/templates/extras/configcontext.html +++ b/netbox/templates/extras/configcontext.html @@ -112,7 +112,7 @@ {% if configcontext.roles.all %} {% else %} From 770f4c962cf4bfb5d44bf7cc6ac5f1e080e0cd7f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 7 Jan 2020 10:31:44 -0500 Subject: [PATCH 15/16] Fixes #3856: Allow filtering VM interfaces by multiple MAC addresses --- docs/release-notes/version-2.6.md | 1 + netbox/virtualization/filters.py | 13 +------------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 510e4253a..f3ff8798a 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -9,6 +9,7 @@ * [#3589](https://github.com/netbox-community/netbox/issues/3589) - Fix validation on tagged VLANs of an interface * [#3853](https://github.com/netbox-community/netbox/issues/3853) - Fix device role link on config context view +* [#3856](https://github.com/netbox-community/netbox/issues/3856) - Allow filtering VM interfaces by multiple MAC addresses --- diff --git a/netbox/virtualization/filters.py b/netbox/virtualization/filters.py index 6c75c78fc..8ce97f9e2 100644 --- a/netbox/virtualization/filters.py +++ b/netbox/virtualization/filters.py @@ -208,8 +208,7 @@ class InterfaceFilter(django_filters.FilterSet): to_field_name='name', label='Virtual machine', ) - mac_address = django_filters.CharFilter( - method='_mac_address', + mac_address = MultiValueMACAddressFilter( label='MAC address', ) @@ -217,16 +216,6 @@ class InterfaceFilter(django_filters.FilterSet): model = Interface fields = ['id', 'name', 'enabled', 'mtu'] - def _mac_address(self, queryset, name, value): - value = value.strip() - if not value: - return queryset - try: - mac = EUI(value.strip()) - return queryset.filter(mac_address=mac) - except AddrFormatError: - return queryset.none() - def search(self, queryset, name, value): if not value.strip(): return queryset From 8fef6edb27416f12f29c67cf0539721e4ef2a831 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 8 Jan 2020 11:12:44 -0500 Subject: [PATCH 16/16] Fixes #3862: Allow filtering device components by multiple device names --- docs/release-notes/version-2.6.md | 1 + netbox/dcim/filters.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index f3ff8798a..62d732a9b 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -10,6 +10,7 @@ * [#3589](https://github.com/netbox-community/netbox/issues/3589) - Fix validation on tagged VLANs of an interface * [#3853](https://github.com/netbox-community/netbox/issues/3853) - Fix device role link on config context view * [#3856](https://github.com/netbox-community/netbox/issues/3856) - Allow filtering VM interfaces by multiple MAC addresses +* [#3862](https://github.com/netbox-community/netbox/issues/3862) - Allow filtering device components by multiple device names --- diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 638313507..ffed7fa3d 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -646,7 +646,8 @@ class DeviceComponentFilterSet(django_filters.FilterSet): queryset=Device.objects.all(), label='Device (ID)', ) - device = django_filters.ModelChoiceFilter( + device = django_filters.ModelMultipleChoiceFilter( + field_name='device__name', queryset=Device.objects.all(), to_field_name='name', label='Device (name)',