diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 855b58387..1e47e16ae 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.3.8 + placeholder: v3.3.9 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 6688de9fe..94c879aed 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.3.8 + placeholder: v3.3.9 validations: required: true - type: dropdown diff --git a/docs/customization/reports.md b/docs/customization/reports.md index 470868ea0..b83c4a177 100644 --- a/docs/customization/reports.md +++ b/docs/customization/reports.md @@ -45,7 +45,7 @@ class DeviceConnectionsReport(Report): # Check that every console port for every active device has a connection defined. active = DeviceStatusChoices.STATUS_ACTIVE for console_port in ConsolePort.objects.prefetch_related('device').filter(device__status=active): - if console_port.connected_endpoint is None: + if not console_port.connected_endpoints: self.log_failure( console_port.device, "No console connection defined for {}".format(console_port.name) @@ -64,7 +64,7 @@ class DeviceConnectionsReport(Report): for device in Device.objects.filter(status=DeviceStatusChoices.STATUS_ACTIVE): connected_ports = 0 for power_port in PowerPort.objects.filter(device=device): - if power_port.connected_endpoint is not None: + if power_port.connected_endpoints: connected_ports += 1 if not power_port.path.is_active: self.log_warning( diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index ffb3b9ffe..2d62fb5bd 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -1,6 +1,10 @@ # NetBox v3.3 -## v3.3.9 (FUTURE) +## v3.3.10 (FUTURE) + +--- + +## v3.3.9 (2022-11-30) ### Enhancements @@ -21,6 +25,9 @@ * [#10969](https://github.com/netbox-community/netbox/issues/10969) - Update cable paths ending at associated rear port when creating new front ports * [#10996](https://github.com/netbox-community/netbox/issues/10996) - Hide checkboxes on child object lists when no bulk operations are available * [#10997](https://github.com/netbox-community/netbox/issues/10997) - Fix exception when editing NAT IP for VM with no cluster +* [#11014](https://github.com/netbox-community/netbox/issues/11014) - Use natural ordering when sorting rack elevations by name +* [#11028](https://github.com/netbox-community/netbox/issues/11028) - Enable bulk clearing of color attribute of pass-through ports +* [#11047](https://github.com/netbox-community/netbox/issues/11047) - Cloning a rack reservation should replicate rack & user --- diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index c21988b45..d0eae8ac9 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -1321,7 +1321,7 @@ class FrontPortBulkEditForm( fieldsets = ( (None, ('module', 'type', 'label', 'color', 'description', 'mark_connected')), ) - nullable_fields = ('module', 'label', 'description') + nullable_fields = ('module', 'label', 'description', 'color') class RearPortBulkEditForm( @@ -1332,7 +1332,7 @@ class RearPortBulkEditForm( fieldsets = ( (None, ('module', 'type', 'label', 'color', 'description', 'mark_connected')), ) - nullable_fields = ('module', 'label', 'description') + nullable_fields = ('module', 'label', 'description', 'color') class ModuleBayBulkEditForm( diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 7b3534a4e..96b53228c 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -197,7 +197,7 @@ class PathEndpoint(models.Model): dcim.signals in response to changes in the cable path, and complements the `origin` GenericForeignKey field on the CablePath model. `_path` should not be accessed directly; rather, use the `path` property. - `connected_endpoint()` is a convenience method for returning the destination of the associated CablePath, if any. + `connected_endpoints()` is a convenience method for returning the destination of the associated CablePath, if any. """ _path = models.ForeignKey( to='dcim.CablePath', diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 8cdc9c691..ab56ddd09 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -486,6 +486,7 @@ class RackReservation(PrimaryModel): max_length=200 ) + clone_fields = ('rack', 'user', 'tenant') prerequisite_models = ( 'dcim.Rack', ) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index a1c11bb3d..9edf5b152 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -653,17 +653,18 @@ class RackElevationListView(generic.ObjectListView): racks = filtersets.RackFilterSet(request.GET, self.queryset).qs total_count = racks.count() + # Ordering ORDERING_CHOICES = { 'name': 'Name (A-Z)', '-name': 'Name (Z-A)', 'facility_id': 'Facility ID (A-Z)', '-facility_id': 'Facility ID (Z-A)', } - sort = request.GET.get('sort', "name") + sort = request.GET.get('sort', 'name') if sort not in ORDERING_CHOICES: sort = 'name' - - racks = racks.order_by(sort) + sort_field = sort.replace("name", "_name") # Use natural ordering + racks = racks.order_by(sort_field) # Pagination per_page = get_paginate_count(request) diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 083417cd3..aa31db97c 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -265,7 +265,7 @@ Utilization {% for powerport in object.powerports.all %} - {% with utilization=powerport.get_power_draw powerfeed=powerport.connected_endpoint %} + {% with utilization=powerport.get_power_draw powerfeed=powerport.connected_endpoints.0 %} {{ powerport }} {{ utilization.outlet_count }} diff --git a/netbox/templates/dcim/interface.html b/netbox/templates/dcim/interface.html index 73d590d3d..b593b7c00 100644 --- a/netbox/templates/dcim/interface.html +++ b/netbox/templates/dcim/interface.html @@ -211,7 +211,7 @@
Wireless
- {% with peer=object.connected_endpoint %} + {% with peer=object.connected_endpoints.0 %} diff --git a/netbox/templates/dcim/rack.html b/netbox/templates/dcim/rack.html index 3c31dc49d..15fca7846 100644 --- a/netbox/templates/dcim/rack.html +++ b/netbox/templates/dcim/rack.html @@ -202,7 +202,7 @@ - {% with power_port=powerfeed.connected_endpoint %} + {% with power_port=powerfeed.connected_endpoints.0 %} {% if power_port %} {% else %} diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index 7c5b193fd..228370954 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -217,6 +217,7 @@ def status_from_tag(tag: str = "info") -> str: 'warning': 'warning', 'success': 'success', 'error': 'danger', + 'danger': 'danger', 'debug': 'info', 'info': 'info', } diff --git a/requirements.txt b/requirements.txt index da69f5a88..c875708a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ django-redis==5.2.0 django-rich==1.4.0 django-rq==2.6.0 django-tables2==2.4.1 -django-taggit==3.0.0 +django-taggit==3.1.0 django-timezone-field==5.0 djangorestframework==3.14.0 drf-yasg[validation]==1.21.4 @@ -19,18 +19,18 @@ graphene-django==3.0.0 gunicorn==20.1.0 Jinja2==3.1.2 Markdown==3.3.7 -mkdocs-material==8.5.10 +mkdocs-material==8.5.11 mkdocstrings[python-legacy]==0.19.0 netaddr==0.8.0 Pillow==9.3.0 psycopg2-binary==2.9.5 PyYAML==6.0 -sentry-sdk==1.11.0 +sentry-sdk==1.11.1 social-auth-app-django==5.0.0 social-auth-core[openidconnect]==4.3.0 svgwrite==1.4.3 tablib==3.2.1 -tzdata==2022.6 +tzdata==2022.7 # Workaround for #7401 jsonschema==3.2.0
{{ powerfeed|linkify }} {% badge powerfeed.get_status_display bg_color=powerfeed.get_status_color %} {% badge powerfeed.get_type_display bg_color=powerfeed.get_type_color %}{% utilization_graph power_port.get_power_draw.allocated|percentage:powerfeed.available_power %}