From a3f172fc77c08a5af2f5f683a281d73b8403fb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Est=C3=A9vez?= Date: Fri, 25 Feb 2022 11:30:13 -0500 Subject: [PATCH 01/38] Conflicting documentation on remote default group In the current documentation we have two seemingly conflicting sentences: * REMOTE_AUTH_DEFAULT_GROUPS: (Requires REMOTE_AUTH_ENABLED.) * REMOTE_AUTH_ENABLED: (REMOTE_AUTH_DEFAULT_GROUPS will not function if REMOTE_AUTH_ENABLED is enabled) --- docs/configuration/remote-authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/remote-authentication.md b/docs/configuration/remote-authentication.md index 73d29415b..2c3a7002f 100644 --- a/docs/configuration/remote-authentication.md +++ b/docs/configuration/remote-authentication.md @@ -43,7 +43,7 @@ A mapping of permissions to assign a new user account when created using remote Default: `False` -NetBox can be configured to support remote user authentication by inferring user authentication from an HTTP header set by the HTTP reverse proxy (e.g. nginx or Apache). Set this to `True` to enable this functionality. (Local authentication will still take effect as a fallback.) (`REMOTE_AUTH_DEFAULT_GROUPS` will not function if `REMOTE_AUTH_ENABLED` is enabled) +NetBox can be configured to support remote user authentication by inferring user authentication from an HTTP header set by the HTTP reverse proxy (e.g. nginx or Apache). Set this to `True` to enable this functionality. (Local authentication will still take effect as a fallback.) (`REMOTE_AUTH_DEFAULT_GROUPS` will not function if `REMOTE_AUTH_ENABLED` is disabled) --- From 36d6ae33d15e93cc552827cdea363a9c00c7f823 Mon Sep 17 00:00:00 2001 From: kkthxbye-code Date: Mon, 4 Apr 2022 18:00:38 +0200 Subject: [PATCH 02/38] Allow setting individual timeouts on scripts and reports --- docs/customization/custom-scripts.md | 4 ++++ netbox/extras/api/views.py | 6 ++++-- netbox/extras/management/commands/runreport.py | 3 ++- netbox/extras/models/models.py | 6 ++++-- netbox/extras/reports.py | 1 + netbox/extras/scripts.py | 6 +++++- netbox/extras/views.py | 7 +++++-- 7 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/customization/custom-scripts.md b/docs/customization/custom-scripts.md index 02af19726..982a4f8e3 100644 --- a/docs/customization/custom-scripts.md +++ b/docs/customization/custom-scripts.md @@ -89,6 +89,10 @@ The checkbox to commit database changes when executing a script is checked by de commit_default = False ``` +### `job_timeout` + +Set the allowed runtime of a script. If not set the `RQ_DEFAULT_TIMEOUT` will be used. + ## Accessing Request Data Details of the current HTTP request (the one being made to execute the script) are available as the instance attribute `self.request`. This can be used to infer, for example, the user executing the script and the client IP address: diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 4f42b4c93..579e39d86 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -236,7 +236,8 @@ class ReportViewSet(ViewSet): run_report, report.full_name, report_content_type, - request.user + request.user, + job_timeout=report.job_timeout ) report.result = job_result @@ -320,7 +321,8 @@ class ScriptViewSet(ViewSet): request.user, data=data, request=copy_safe_request(request), - commit=commit + commit=commit, + job_timeout=script.job_timeout, ) script.result = job_result serializer = serializers.ScriptDetailSerializer(script, context={'request': request}) diff --git a/netbox/extras/management/commands/runreport.py b/netbox/extras/management/commands/runreport.py index de7c5c91b..ee166ae6a 100644 --- a/netbox/extras/management/commands/runreport.py +++ b/netbox/extras/management/commands/runreport.py @@ -35,7 +35,8 @@ class Command(BaseCommand): run_report, report.full_name, report_content_type, - None + None, + job_timeout=report.job_timeout ) # Wait on the job to finish diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index ef0ab8b1f..48a076f75 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -13,6 +13,7 @@ from django.urls import reverse from django.utils import timezone from django.utils.formats import date_format from rest_framework.utils.encoders import JSONEncoder +import django_rq from extras.choices import * from extras.constants import * @@ -549,8 +550,9 @@ class JobResult(models.Model): user=user, job_id=uuid.uuid4() ) - - func.delay(*args, job_id=str(job_result.job_id), job_result=job_result, **kwargs) + + queue = django_rq.get_queue("default") + queue.enqueue(func, job_id=str(job_result.job_id), job_result=job_result, **kwargs) return job_result diff --git a/netbox/extras/reports.py b/netbox/extras/reports.py index 2eb6584c9..0bdc4847e 100644 --- a/netbox/extras/reports.py +++ b/netbox/extras/reports.py @@ -119,6 +119,7 @@ class Report(object): } """ description = None + job_timeout = None def __init__(self): diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index f80dfaefa..4b9d17d67 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -298,6 +298,10 @@ class BaseScript: def module(cls): return cls.__module__ + @classproperty + def job_timeout(self): + return getattr(self.Meta, 'job_timeout', None) + @classmethod def _get_vars(cls): vars = {} @@ -414,7 +418,7 @@ def is_variable(obj): return isinstance(obj, ScriptVariable) -@job('default') +#@job('default') def run_script(data, request, commit=True, *args, **kwargs): """ A wrapper for calling Script.run(). This performs error handling and provides a hook for committing changes. It diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 0a190dd49..785c5eb5a 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -588,7 +588,8 @@ class ReportView(ContentTypePermissionRequiredMixin, View): run_report, report.full_name, report_content_type, - request.user + request.user, + job_timeout=report.job_timeout ) return redirect('extras:report_result', job_result_pk=job_result.pk) @@ -708,6 +709,7 @@ class ScriptView(ContentTypePermissionRequiredMixin, GetScriptMixin, View): commit = form.cleaned_data.pop('_commit') script_content_type = ContentType.objects.get(app_label='extras', model='script') + job_result = JobResult.enqueue_job( run_script, script.full_name, @@ -715,7 +717,8 @@ class ScriptView(ContentTypePermissionRequiredMixin, GetScriptMixin, View): request.user, data=form.cleaned_data, request=copy_safe_request(request), - commit=commit + commit=commit, + job_timeout=script.job_timeout, ) return redirect('extras:script_result', job_result_pk=job_result.pk) From 69b4d0d44b5f119dad14003e00dc78872cd836cb Mon Sep 17 00:00:00 2001 From: kkthxbye-code Date: Mon, 4 Apr 2022 18:13:13 +0200 Subject: [PATCH 03/38] #9028 - Fix pep8 syntax --- netbox/extras/models/models.py | 2 +- netbox/extras/scripts.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 48a076f75..e614a1258 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -550,7 +550,7 @@ class JobResult(models.Model): user=user, job_id=uuid.uuid4() ) - + queue = django_rq.get_queue("default") queue.enqueue(func, job_id=str(job_result.job_id), job_result=job_result, **kwargs) diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index 4b9d17d67..5351bca8a 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -418,7 +418,6 @@ def is_variable(obj): return isinstance(obj, ScriptVariable) -#@job('default') def run_script(data, request, commit=True, *args, **kwargs): """ A wrapper for calling Script.run(). This performs error handling and provides a hook for committing changes. It From ea197eff5f4fe925bb354d1375912decd81752bd Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 5 Apr 2022 17:12:13 -0400 Subject: [PATCH 04/38] PRVB --- docs/release-notes/version-3.2.md | 4 ++++ netbox/netbox/settings.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 9f354dbd6..ddf2ebded 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -1,5 +1,9 @@ # NetBox v3.2 +## v3.2.1 (FUTURE) + +--- + ## v3.2.0 (2022-04-05) !!! warning "Python 3.8 or Later Required" diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 1e972df8c..04c0e9c3d 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -26,7 +26,7 @@ django.utils.encoding.force_text = force_str # Environment setup # -VERSION = '3.2.0' +VERSION = '3.2.1-dev' # Hostname HOSTNAME = platform.node() From 523390cd8e989b49f59a757695e585a923ae199f Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Wed, 6 Apr 2022 13:35:22 -0500 Subject: [PATCH 05/38] #9061 - Change inheritance order for DeviceComponentFilterSets --- docs/release-notes/version-3.2.md | 5 +++++ netbox/dcim/filtersets.py | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index ddf2ebded..cdb319e98 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -2,6 +2,11 @@ ## v3.2.1 (FUTURE) +### Bug Fixes (From Beta2) + +* [#9061](https://github.com/netbox-community/netbox/issues/9061) - Change inheritance order for DeviceComponentFilterSets + + --- ## v3.2.0 (2022-04-05) diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index a380fbcce..0f4e7cf7e 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -1095,8 +1095,8 @@ class PathEndpointFilterSet(django_filters.FilterSet): class ConsolePortFilterSet( - NetBoxModelFilterSet, ModularDeviceComponentFilterSet, + NetBoxModelFilterSet, CableTerminationFilterSet, PathEndpointFilterSet ): @@ -1111,8 +1111,8 @@ class ConsolePortFilterSet( class ConsoleServerPortFilterSet( - NetBoxModelFilterSet, ModularDeviceComponentFilterSet, + NetBoxModelFilterSet, CableTerminationFilterSet, PathEndpointFilterSet ): @@ -1127,8 +1127,8 @@ class ConsoleServerPortFilterSet( class PowerPortFilterSet( - NetBoxModelFilterSet, ModularDeviceComponentFilterSet, + NetBoxModelFilterSet, CableTerminationFilterSet, PathEndpointFilterSet ): @@ -1143,8 +1143,8 @@ class PowerPortFilterSet( class PowerOutletFilterSet( - NetBoxModelFilterSet, ModularDeviceComponentFilterSet, + NetBoxModelFilterSet, CableTerminationFilterSet, PathEndpointFilterSet ): @@ -1163,8 +1163,8 @@ class PowerOutletFilterSet( class InterfaceFilterSet( - NetBoxModelFilterSet, ModularDeviceComponentFilterSet, + NetBoxModelFilterSet, CableTerminationFilterSet, PathEndpointFilterSet ): @@ -1291,8 +1291,8 @@ class InterfaceFilterSet( class FrontPortFilterSet( - NetBoxModelFilterSet, ModularDeviceComponentFilterSet, + NetBoxModelFilterSet, CableTerminationFilterSet ): type = django_filters.MultipleChoiceFilter( @@ -1306,8 +1306,8 @@ class FrontPortFilterSet( class RearPortFilterSet( - NetBoxModelFilterSet, ModularDeviceComponentFilterSet, + NetBoxModelFilterSet, CableTerminationFilterSet ): type = django_filters.MultipleChoiceFilter( @@ -1320,21 +1320,21 @@ class RearPortFilterSet( fields = ['id', 'name', 'label', 'type', 'color', 'positions', 'description'] -class ModuleBayFilterSet(NetBoxModelFilterSet, DeviceComponentFilterSet): +class ModuleBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet): class Meta: model = ModuleBay fields = ['id', 'name', 'label', 'description'] -class DeviceBayFilterSet(NetBoxModelFilterSet, DeviceComponentFilterSet): +class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet): class Meta: model = DeviceBay fields = ['id', 'name', 'label', 'description'] -class InventoryItemFilterSet(NetBoxModelFilterSet, DeviceComponentFilterSet): +class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet): parent_id = django_filters.ModelMultipleChoiceFilter( queryset=InventoryItem.objects.all(), label='Parent inventory item (ID)', From 85e65edb7d98c07f857dcb20f87359a8c81a82a2 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Wed, 6 Apr 2022 13:46:31 -0500 Subject: [PATCH 06/38] Fixes #9057 - Fix missing instance counts for module types --- docs/release-notes/version-3.2.md | 1 + netbox/dcim/views.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index cdb319e98..6fe4ed851 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -4,6 +4,7 @@ ### Bug Fixes (From Beta2) +* [#9057](https://github.com/netbox-community/netbox/issues/9057) - Fix missing instance counts for module types * [#9061](https://github.com/netbox-community/netbox/issues/9061) - Change inheritance order for DeviceComponentFilterSets diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 4157fd2e9..e60e6abc8 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -960,7 +960,7 @@ class DeviceTypeBulkDeleteView(generic.BulkDeleteView): class ModuleTypeListView(generic.ObjectListView): queryset = ModuleType.objects.prefetch_related('manufacturer').annotate( - # instance_count=count_related(Module, 'module_type') + instance_count=count_related(Module, 'module_type') ) filterset = filtersets.ModuleTypeFilterSet filterset_form = forms.ModuleTypeFilterForm @@ -1066,7 +1066,7 @@ class ModuleTypeImportView(generic.ObjectImportView): class ModuleTypeBulkEditView(generic.BulkEditView): queryset = ModuleType.objects.prefetch_related('manufacturer').annotate( - # instance_count=count_related(Module, 'module_type') + instance_count=count_related(Module, 'module_type') ) filterset = filtersets.ModuleTypeFilterSet table = tables.ModuleTypeTable @@ -1075,7 +1075,7 @@ class ModuleTypeBulkEditView(generic.BulkEditView): class ModuleTypeBulkDeleteView(generic.BulkDeleteView): queryset = ModuleType.objects.prefetch_related('manufacturer').annotate( - # instance_count=count_related(Module, 'module_type') + instance_count=count_related(Module, 'module_type') ) filterset = filtersets.ModuleTypeFilterSet table = tables.ModuleTypeTable From 6760533a101a9ecf048d19f0cab96264e8324c05 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 6 Apr 2022 20:01:09 -0400 Subject: [PATCH 07/38] Fixes #8931: Copy assigned tenant when cloning a location --- docs/release-notes/version-3.2.md | 4 ++-- netbox/dcim/models/sites.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 6fe4ed851..4740d0e0c 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -2,12 +2,12 @@ ## v3.2.1 (FUTURE) -### Bug Fixes (From Beta2) +### Bug Fixes +* [#8931](https://github.com/netbox-community/netbox/issues/8931) - Copy assigned tenant when cloning a location * [#9057](https://github.com/netbox-community/netbox/issues/9057) - Fix missing instance counts for module types * [#9061](https://github.com/netbox-community/netbox/issues/9061) - Change inheritance order for DeviceComponentFilterSets - --- ## v3.2.0 (2022-04-05) diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index 53e3bcceb..d02bd0932 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -367,7 +367,7 @@ class Location(NestedGroupModel): to='extras.ImageAttachment' ) - clone_fields = ['site', 'parent', 'description'] + clone_fields = ['site', 'parent', 'tenant', 'description'] class Meta: ordering = ['site', 'name'] From d93e944c07a1f045514f973cb9d8a84dccc1e70e Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 6 Apr 2022 20:12:14 -0400 Subject: [PATCH 08/38] Closes #8973: Display VLAN group count under site view --- docs/release-notes/version-3.2.md | 4 ++++ netbox/dcim/views.py | 6 +++++- netbox/templates/dcim/site.html | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 4740d0e0c..90f339111 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -2,6 +2,10 @@ ## v3.2.1 (FUTURE) +### Enhancements + +* [#8973](https://github.com/netbox-community/netbox/issues/8973) - Display VLAN group count under site view + ### Bug Fixes * [#8931](https://github.com/netbox-community/netbox/issues/8931) - Copy assigned tenant when cloning a location diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index e60e6abc8..c0b46f16e 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -14,7 +14,7 @@ from django.views.generic import View from circuits.models import Circuit from extras.views import ObjectConfigContextView -from ipam.models import ASN, IPAddress, Prefix, Service, VLAN +from ipam.models import ASN, IPAddress, Prefix, Service, VLAN, VLANGroup from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable from netbox.views import generic from utilities.forms import ConfirmationForm @@ -320,6 +320,10 @@ class SiteView(generic.ObjectView): 'rack_count': Rack.objects.restrict(request.user, 'view').filter(site=instance).count(), 'device_count': Device.objects.restrict(request.user, 'view').filter(site=instance).count(), 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'vlangroup_count': VLANGroup.objects.restrict(request.user, 'view').filter( + scope_type=ContentType.objects.get_for_model(Site), + scope_id=instance.pk + ).count(), 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=instance).count(), 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).count(), 'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance).count(), diff --git a/netbox/templates/dcim/site.html b/netbox/templates/dcim/site.html index fe0a558eb..c15cab468 100644 --- a/netbox/templates/dcim/site.html +++ b/netbox/templates/dcim/site.html @@ -188,6 +188,16 @@ {% endif %} + + VLAN Groups + + {% if stats.vlangroup_count %} + {{ stats.vlangroup_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} + + VLANs From f4e78b0ea6e0db8d6c07cdb0e6adfcaddcd542f4 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 6 Apr 2022 20:29:28 -0400 Subject: [PATCH 09/38] Fixes #9065: Min/max VID should not be required when filtering VLAN groups --- docs/release-notes/version-3.2.md | 1 + netbox/ipam/forms/filtersets.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 90f339111..1d2516cdf 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -11,6 +11,7 @@ * [#8931](https://github.com/netbox-community/netbox/issues/8931) - Copy assigned tenant when cloning a location * [#9057](https://github.com/netbox-community/netbox/issues/9057) - Fix missing instance counts for module types * [#9061](https://github.com/netbox-community/netbox/issues/9061) - Change inheritance order for DeviceComponentFilterSets +* [#9065](https://github.com/netbox-community/netbox/issues/9065) - Min/max VID should not be required when filtering VLAN groups --- diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py index 57f39f8c2..bbd6bb97b 100644 --- a/netbox/ipam/forms/filtersets.py +++ b/netbox/ipam/forms/filtersets.py @@ -377,12 +377,16 @@ class VLANGroupFilterForm(NetBoxModelFilterSetForm): label=_('Rack') ) min_vid = forms.IntegerField( + required=False, min_value=VLAN_VID_MIN, max_value=VLAN_VID_MAX, + label='Minimum VID' ) max_vid = forms.IntegerField( + required=False, min_value=VLAN_VID_MIN, max_value=VLAN_VID_MAX, + label='Maximum VID' ) tag = TagFilterField(model) From b9f6a5625f221ede86b022dd30abebe373209676 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 6 Apr 2022 20:30:29 -0400 Subject: [PATCH 10/38] Update supported Python versions --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index ae3fe68f3..65097e9be 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -22,9 +22,9 @@ body: label: Python version description: What version of Python are you currently running? options: - - "3.7" - "3.8" - "3.9" + - "3.10" validations: required: true - type: textarea From c3d9910e082f5878a9312c0ee18cadd5b7f8a671 Mon Sep 17 00:00:00 2001 From: Jason Yates Date: Thu, 7 Apr 2022 08:21:13 +0100 Subject: [PATCH 11/38] Limit amount of nonracked devices displayed Fixes #8920 Limits the amount of non-racked devices on Site and Location view to 10 and provides a link to the device list this is pre-filtered to the relevant site or location. --- netbox/dcim/views.py | 18 ++++- .../templates/dcim/inc/nonracked_devices.html | 68 +++++++++++-------- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index c0b46f16e..9b24ea9d1 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -346,7 +346,13 @@ class SiteView(generic.ObjectView): site=instance, position__isnull=True, parent_bay__isnull=True - ).prefetch_related('device_type__manufacturer') + ).prefetch_related('device_type__manufacturer').order_by('-pk')[:10] + + total_nonracked_devices_count = Device.objects.filter( + site=instance, + position__isnull=True, + parent_bay__isnull=True + ).count() asns = ASN.objects.restrict(request.user, 'view').filter(sites=instance) asn_count = asns.count() @@ -358,6 +364,7 @@ class SiteView(generic.ObjectView): 'locations': locations, 'asns': asns, 'nonracked_devices': nonracked_devices, + 'total_nonracked_devices_count': total_nonracked_devices_count, } @@ -439,13 +446,20 @@ class LocationView(generic.ObjectView): location=instance, position__isnull=True, parent_bay__isnull=True - ).prefetch_related('device_type__manufacturer') + ).prefetch_related('device_type__manufacturer').order_by('-pk')[:10] + + total_nonracked_devices_count = Device.objects.filter( + location=instance, + position__isnull=True, + parent_bay__isnull=True + ).count() return { 'rack_count': rack_count, 'device_count': device_count, 'child_locations_table': child_locations_table, 'nonracked_devices': nonracked_devices, + 'total_nonracked_devices_count': total_nonracked_devices_count, } diff --git a/netbox/templates/dcim/inc/nonracked_devices.html b/netbox/templates/dcim/inc/nonracked_devices.html index 7f4da2f24..68112e2a7 100644 --- a/netbox/templates/dcim/inc/nonracked_devices.html +++ b/netbox/templates/dcim/inc/nonracked_devices.html @@ -1,40 +1,54 @@ {% load helpers %}
-
- Non-Racked Devices -
-
-{% if nonracked_devices %} - - - - - - - - {% for device in nonracked_devices %} - - - - - {% if device.parent_bay %} - - - {% else %} - +
+ Non-Racked Devices +
+
+ {% if nonracked_devices %} +
NameRoleTypeParent Device
- {{ device }} - {{ device.device_role }}{{ device.device_type }}{{ device.parent_bay.device|linkify }}{{ device.parent_bay }}
+ + + + + + + {% for device in nonracked_devices %} + + + + + {% if device.parent_bay %} + + + {% else %} + + {% endif %} + + {% endfor %} +
NameRoleTypeParent Device
+ {{ device }} + {{ device.device_role }}{{ device.device_type }}{{ device.parent_bay.device|linkify }}{{ device.parent_bay }}
+ + {% if nonracked_devices.count == 10 %} + {% if object|meta:'verbose_name' == 'site' %} +
+ Displaying 10 of {{ total_nonracked_devices_count }} devices (View full list) +
+ {% elif object|meta:'verbose_name' == 'location' %} +
+ Displaying 10 of {{ total_nonracked_devices_count }} devices (View full list) +
{% endif %} - - {% endfor %} - + {% endif %} + {% else %}
None
{% endif %}
+ {% if perms.dcim.add_device %} {% if object|meta:'verbose_name' == 'rack' %} - {# TODO: Improve the design & layout #} {% if auth_backends %} -
Or use an SSO provider:
- {% for name, backend in auth_backends.items %} -

{{ name }}

+
Or use a single sign-on (SSO) provider:
+ {% for name, display in auth_backends.items %} +
+ {% if display.1 %}{% endif %} + {{ display.0 }} +
{% endfor %} {% endif %} diff --git a/netbox/users/views.py b/netbox/users/views.py index 04c0c5155..6a923e77e 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -16,6 +16,7 @@ from social_core.backends.utils import load_backends from extras.models import ObjectChange from extras.tables import ObjectChangeTable +from netbox.authentication import get_auth_backend_display from netbox.config import get_config from utilities.forms import ConfirmationForm from .forms import LoginForm, PasswordChangeForm, TokenForm, UserConfigForm @@ -43,9 +44,13 @@ class LoginView(View): logger = logging.getLogger('netbox.auth.login') return self.redirect_to_next(request, logger) + auth_backends = { + name: get_auth_backend_display(name) for name in load_backends(settings.AUTHENTICATION_BACKENDS).keys() + } + return render(request, self.template_name, { 'form': form, - 'auth_backends': load_backends(settings.AUTHENTICATION_BACKENDS), + 'auth_backends': auth_backends, }) def post(self, request): From fa5cf665ce7e36a5a8abd6c43b558365f3c4fe41 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 14 Apr 2022 11:13:04 -0400 Subject: [PATCH 37/38] Fixes #9128: Resolve component labels per module bay position when installing modules --- docs/release-notes/version-3.2.md | 1 + .../dcim/models/device_component_templates.py | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 33cfd140d..e73c3048e 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -26,6 +26,7 @@ * [#9100](https://github.com/netbox-community/netbox/issues/9100) - Include position field in module type YAML export * [#9116](https://github.com/netbox-community/netbox/issues/9116) - `assigned_to_interface` filter for IP addresses should not match FHRP group assignments * [#9118](https://github.com/netbox-community/netbox/issues/9118) - Fix validation error when importing VM child interfaces +* [#9128](https://github.com/netbox-community/netbox/issues/9128) - Resolve component labels per module bay position when installing modules --- diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index b363d6ea4..647abe148 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -124,6 +124,11 @@ class ModularComponentTemplateModel(ComponentTemplateModel): return self.name.replace('{module}', module.module_bay.position) return self.name + def resolve_label(self, module): + if module: + return self.label.replace('{module}', module.module_bay.position) + return self.label + class ConsolePortTemplate(ModularComponentTemplateModel): """ @@ -147,7 +152,7 @@ class ConsolePortTemplate(ModularComponentTemplateModel): def instantiate(self, **kwargs): return self.component_model( name=self.resolve_name(kwargs.get('module')), - label=self.label, + label=self.resolve_label(kwargs.get('module')), type=self.type, **kwargs ) @@ -175,7 +180,7 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel): def instantiate(self, **kwargs): return self.component_model( name=self.resolve_name(kwargs.get('module')), - label=self.label, + label=self.resolve_label(kwargs.get('module')), type=self.type, **kwargs ) @@ -215,7 +220,7 @@ class PowerPortTemplate(ModularComponentTemplateModel): def instantiate(self, **kwargs): return self.component_model( name=self.resolve_name(kwargs.get('module')), - label=self.label, + label=self.resolve_label(kwargs.get('module')), type=self.type, maximum_draw=self.maximum_draw, allocated_draw=self.allocated_draw, @@ -286,7 +291,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel): power_port = None return self.component_model( name=self.resolve_name(kwargs.get('module')), - label=self.label, + label=self.resolve_label(kwargs.get('module')), type=self.type, power_port=power_port, feed_leg=self.feed_leg, @@ -326,7 +331,7 @@ class InterfaceTemplate(ModularComponentTemplateModel): def instantiate(self, **kwargs): return self.component_model( name=self.resolve_name(kwargs.get('module')), - label=self.label, + label=self.resolve_label(kwargs.get('module')), type=self.type, mgmt_only=self.mgmt_only, **kwargs @@ -397,7 +402,7 @@ class FrontPortTemplate(ModularComponentTemplateModel): rear_port = None return self.component_model( name=self.resolve_name(kwargs.get('module')), - label=self.label, + label=self.resolve_label(kwargs.get('module')), type=self.type, color=self.color, rear_port=rear_port, @@ -437,7 +442,7 @@ class RearPortTemplate(ModularComponentTemplateModel): def instantiate(self, **kwargs): return self.component_model( name=self.resolve_name(kwargs.get('module')), - label=self.label, + label=self.resolve_label(kwargs.get('module')), type=self.type, color=self.color, positions=self.positions, From fdc018d8096355f87615318c6ab2b611777eebed Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 14 Apr 2022 13:58:18 -0400 Subject: [PATCH 38/38] Release v3.2.1 --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- .github/ISSUE_TEMPLATE/feature_request.yaml | 2 +- docs/release-notes/version-3.2.md | 2 +- netbox/netbox/settings.py | 2 +- requirements.txt | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 65097e9be..b5de9bfee 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.2.0 + placeholder: v3.2.1 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 1ce4c0a11..138e0f9b4 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.2.0 + placeholder: v3.2.1 validations: required: true - type: dropdown diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index e73c3048e..cd19a6d65 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -1,6 +1,6 @@ # NetBox v3.2 -## v3.2.1 (FUTURE) +## v3.2.1 (2022-04-14) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 04c0e9c3d..4e3017d8d 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -26,7 +26,7 @@ django.utils.encoding.force_text = force_str # Environment setup # -VERSION = '3.2.1-dev' +VERSION = '3.2.1' # Hostname HOSTNAME = platform.node() diff --git a/requirements.txt b/requirements.txt index ce0e52087..35867410b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==4.0.3 +Django==4.0.4 django-cors-headers==3.11.0 django-debug-toolbar==3.2.4 django-filter==21.1 @@ -18,7 +18,7 @@ gunicorn==20.1.0 Jinja2==3.0.3 Markdown==3.3.6 markdown-include==0.6.0 -mkdocs-material==8.2.8 +mkdocs-material==8.2.9 mkdocstrings==0.17.0 netaddr==0.8.0 Pillow==9.1.0 @@ -27,7 +27,7 @@ PyYAML==6.0 social-auth-app-django==5.0.0 social-auth-core==4.2.0 svgwrite==1.4.2 -tablib==3.2.0 +tablib==3.2.1 tzdata==2022.1 # Workaround for #7401