From b5e4fdc3d8fcb5d0e796dad1a4f3c1ce2797f7e2 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 15 Feb 2022 09:32:52 -0500 Subject: [PATCH 01/36] PRVB --- docs/release-notes/version-3.1.md | 4 ++++ netbox/netbox/settings.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 1e7e5ac2f..8cddf65ec 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -1,5 +1,9 @@ # NetBox v3.1 +## v3.1.9 (FUTURE) + +--- + ## v3.1.8 (2022-02-15) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index d5a7bfaec..f5501f54f 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -19,7 +19,7 @@ from netbox.config import PARAMS # Environment setup # -VERSION = '3.1.8' +VERSION = '3.1.9-dev' # Hostname HOSTNAME = platform.node() From 6bbf168cecb338c378ef3560dee8d2840b322865 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 15 Feb 2022 09:27:55 -0600 Subject: [PATCH 02/36] Fixes #8546 - Fix import to restrict bridge, parent, lag to device interfaces --- docs/release-notes/version-3.1.md | 4 ++++ netbox/dcim/forms/bulk_import.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 8cddf65ec..8d0762b99 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -2,6 +2,10 @@ ## v3.1.9 (FUTURE) +### Bug Fixes + +* [#8546](https://github.com/netbox-community/netbox/issues/8546) - Fix import to restrict bridge, parent, lag to device interfaces + --- ## v3.1.8 (2022-02-15) diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index df8c4ec01..59b59bb00 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -605,6 +605,19 @@ class InterfaceCSVForm(CustomFieldModelCSVForm): 'rf_channel_width', 'tx_power', ) + def __init__(self, data=None, *args, **kwargs): + super().__init__(data, *args, **kwargs) + + if data: + # Limit interface choices for parent, bridge and lag to device only + params = {} + if data.get('device'): + params[f"device__{self.fields['device'].to_field_name}"] = data.get('device') + if params: + self.fields['parent'].queryset = self.fields['parent'].queryset.filter(**params) + self.fields['bridge'].queryset = self.fields['bridge'].queryset.filter(**params) + self.fields['lag'].queryset = self.fields['lag'].queryset.filter(**params) + def clean_enabled(self): # Make sure enabled is True when it's not included in the uploaded data if 'enabled' not in self.data: From b343035060dc392a602ea9cc8294853f874312f9 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 16 Feb 2022 16:21:32 -0500 Subject: [PATCH 03/36] Fixes #8674: Fix rendering of tabbed content in documentation --- docs/release-notes/version-3.1.md | 3 ++- mkdocs.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 8d0762b99..637e5bc02 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -4,7 +4,8 @@ ### Bug Fixes -* [#8546](https://github.com/netbox-community/netbox/issues/8546) - Fix import to restrict bridge, parent, lag to device interfaces +* [#8546](https://github.com/netbox-community/netbox/issues/8546) - Fix bulk import to restrict bridge, parent, and LAG to device interfaces +* [#8674](https://github.com/netbox-community/netbox/issues/8674) - Fix rendering of tabbed content in documentation --- diff --git a/mkdocs.yml b/mkdocs.yml index 3fb838ffd..4be5b16e7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -34,7 +34,8 @@ markdown_extensions: emoji_index: !!python/name:materialx.emoji.twemoji emoji_generator: !!python/name:materialx.emoji.to_svg - pymdownx.superfences - - pymdownx.tabbed + - pymdownx.tabbed: + alternate_style: true nav: - Introduction: 'index.md' - Installation: From 90ee689d5ae61e829042e35824b4ff4201476e44 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 17 Feb 2022 10:31:28 -0500 Subject: [PATCH 04/36] Closes #8678: Validate minimum required Python version --- upgrade.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/upgrade.sh b/upgrade.sh index 67b8aaa89..301225958 100755 --- a/upgrade.sh +++ b/upgrade.sh @@ -10,6 +10,23 @@ cd "$(dirname "$0")" VIRTUALENV="$(pwd -P)/venv" PYTHON="${PYTHON:-python3}" +# Validate the minimum required Python version +COMMAND="${PYTHON} -c 'import sys; exit(1 if sys.version_info < (3, 7) else 0)'" +PYTHON_VERSION=$(eval "${PYTHON} -V") +eval $COMMAND || { + echo "--------------------------------------------------------------------" + echo "ERROR: Unsupported Python version: ${PYTHON_VERSION}. NetBox requires" + echo "Python 3.7 or later. To specify an alternate Python executable, set" + echo "the PYTHON environment variable. For example:" + echo "" + echo " sudo PYTHON=/usr/bin/python3.7 ./upgrade.sh" + echo "" + echo "To show your current Python version: ${PYTHON} -V" + echo "--------------------------------------------------------------------" + exit 1 +} +echo "Using ${PYTHON_VERSION}" + # Remove the existing virtual environment (if any) if [ -d "$VIRTUALENV" ]; then COMMAND="rm -rf ${VIRTUALENV}" From 2503a3e3cacc3c7917497e5f0aa1c386e577c48a Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 22 Feb 2022 09:02:31 -0500 Subject: [PATCH 05/36] Fixes #8717: Fix redirection after bulk edit/delete of prefixes from aggregate view --- docs/release-notes/version-3.1.md | 1 + netbox/templates/ipam/aggregate/prefixes.html | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 637e5bc02..f403c9bd4 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -6,6 +6,7 @@ * [#8546](https://github.com/netbox-community/netbox/issues/8546) - Fix bulk import to restrict bridge, parent, and LAG to device interfaces * [#8674](https://github.com/netbox-community/netbox/issues/8674) - Fix rendering of tabbed content in documentation +* [#8717](https://github.com/netbox-community/netbox/issues/8717) - Fix redirection after bulk edit/delete of prefixes from aggregate view --- diff --git a/netbox/templates/ipam/aggregate/prefixes.html b/netbox/templates/ipam/aggregate/prefixes.html index 14d4b38bb..bb574ebf0 100644 --- a/netbox/templates/ipam/aggregate/prefixes.html +++ b/netbox/templates/ipam/aggregate/prefixes.html @@ -25,12 +25,12 @@
{% if perms.ipam.change_prefix %} - {% endif %} {% if perms.ipam.delete_prefix %} - {% endif %} From 4913d7ee399505f0aeae2f1b7e91efd0e544bc1a Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 22 Feb 2022 09:05:31 -0500 Subject: [PATCH 06/36] Fixes #8713: Restore missing "add" button on services list view --- docs/release-notes/version-3.1.md | 1 + netbox/ipam/views.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index f403c9bd4..f6b1292b8 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -6,6 +6,7 @@ * [#8546](https://github.com/netbox-community/netbox/issues/8546) - Fix bulk import to restrict bridge, parent, and LAG to device interfaces * [#8674](https://github.com/netbox-community/netbox/issues/8674) - Fix rendering of tabbed content in documentation +* [#8713](https://github.com/netbox-community/netbox/issues/8713) - Restore missing "add" button on services list view * [#8717](https://github.com/netbox-community/netbox/issues/8717) - Fix redirection after bulk edit/delete of prefixes from aggregate view --- diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index c9ac44f46..aab9a6249 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -1038,7 +1038,6 @@ class ServiceListView(generic.ObjectListView): filterset = filtersets.ServiceFilterSet filterset_form = forms.ServiceFilterForm table = tables.ServiceTable - action_buttons = ('import', 'export') class ServiceView(generic.ObjectView): From b1de85a44f8387b381d1eb7770d9ca2c5f63c503 Mon Sep 17 00:00:00 2001 From: Stephan Blanke Date: Tue, 22 Feb 2022 23:27:11 +0100 Subject: [PATCH 07/36] Fixes #8710: Show/hide form elements based on scope selection --- netbox/project-static/dist/netbox.js | Bin 375539 -> 375602 bytes netbox/project-static/dist/netbox.js.map | Bin 344880 -> 344930 bytes .../project-static/src/forms/scopeSelector.ts | 35 +++++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index f388b96cf44e3602a9bb75a8663b3dd01cfa7814..45abd19e6209158d93fbe083fce3e1de985a9f5e 100644 GIT binary patch delta 27685 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 Y5Gd+g<}$q|gr%R!(sMg+D2wtt05g?2qyPW_ delta 145 zcmaFVCc2?bw4sHug{g&k3(K4U`M?Ti9d}1ZUmZ_JM` z7ELDk;3%C)pcq(bDoA}LNZQ=B!d1uL(ZY4QYB0-AX4gE|=^ukxl-MG5ydB-krb~vf jv
-{% endblock layout %} +{% endblock layout %} \ No newline at end of file From cb0386779c8526d379aa43a691894c3fe3d3c20b Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 1 Mar 2022 09:17:24 -0500 Subject: [PATCH 23/36] Announce 2022 community survey --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8429cd4b3..42bf8b619 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ NetBox logo
+:loudspeaker: The **[2022 NetBox community survey](https://forms.gle/KR8YbR8GiJ9EYXM28)** is now open! We collect this feedback and demographic data from NetBox users around the world to help shape the project's long-term development goals. Please take a few minutes to share your responses! + ![Master branch build status](https://github.com/netbox-community/netbox/workflows/CI/badge.svg?branch=master) NetBox is an infrastructure resource modeling (IRM) tool designed to empower From 1ab51ca04e9df40b33e747148e2c461f5ff7f262 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 1 Mar 2022 09:29:58 -0500 Subject: [PATCH 24/36] Announce 2022 community survey --- docs/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/index.md b/docs/index.md index 943f1d7ab..5742c0ab6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,7 @@ ![NetBox](netbox_logo.svg "NetBox logo"){style="height: 100px; margin-bottom: 3em"} +:loudspeaker: The **[2022 NetBox community survey](https://forms.gle/KR8YbR8GiJ9EYXM28)** is now open! We collect this feedback and demographic data from NetBox users around the world to help shape the project's long-term development goals. Please take a few minutes to share your responses! + # What is NetBox? NetBox is an infrastructure resource modeling (IRM) application designed to empower network automation. Initially conceived by the network engineering team at [DigitalOcean](https://www.digitalocean.com/), NetBox was developed specifically to address the needs of network and infrastructure engineers. NetBox is made available as open source under the Apache 2 license. It encompasses the following aspects of network management: From df430394b018fcb2f4b7bbc42be3c22f7e05bc26 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 1 Mar 2022 11:07:19 -0500 Subject: [PATCH 25/36] Closes #8766: Add SCTP to service protocols list --- docs/release-notes/version-3.1.md | 1 + netbox/ipam/choices.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 08a9ab337..ebe9bee46 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -6,6 +6,7 @@ * [#8594](https://github.com/netbox-community/netbox/issues/8594) - Enable filtering by exact description match for all applicable models * [#8629](https://github.com/netbox-community/netbox/issues/8629) - Add description to tag table search function +* [#8766](https://github.com/netbox-community/netbox/issues/8766) - Add SCTP to service protocols list ### Bug Fixes diff --git a/netbox/ipam/choices.py b/netbox/ipam/choices.py index 526ef07d9..647a82810 100644 --- a/netbox/ipam/choices.py +++ b/netbox/ipam/choices.py @@ -189,8 +189,10 @@ class ServiceProtocolChoices(ChoiceSet): PROTOCOL_TCP = 'tcp' PROTOCOL_UDP = 'udp' + PROTOCOL_SCTP = 'sctp' CHOICES = ( (PROTOCOL_TCP, 'TCP'), (PROTOCOL_UDP, 'UDP'), + (PROTOCOL_SCTP, 'SCTP'), ) From 7f752d91029db3c51d814e1392f709d6a565f0cc Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 1 Mar 2022 11:32:17 -0500 Subject: [PATCH 26/36] Closes #8762: Link to rack elevations list from site view --- docs/release-notes/version-3.1.md | 1 + netbox/templates/dcim/site.html | 126 +++++++++++++++++++++--------- 2 files changed, 92 insertions(+), 35 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index ebe9bee46..d34271f4c 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -6,6 +6,7 @@ * [#8594](https://github.com/netbox-community/netbox/issues/8594) - Enable filtering by exact description match for all applicable models * [#8629](https://github.com/netbox-community/netbox/issues/8629) - Add description to tag table search function +* [#8762](https://github.com/netbox-community/netbox/issues/8762) - Link to rack elevations list from site view * [#8766](https://github.com/netbox-community/netbox/issues/8766) - Add SCTP to service protocols list ### Bug Fixes diff --git a/netbox/templates/dcim/site.html b/netbox/templates/dcim/site.html index 2ad970301..f71105d1b 100644 --- a/netbox/templates/dcim/site.html +++ b/netbox/templates/dcim/site.html @@ -183,42 +183,98 @@
-
Stats
+
Related Objects
-
-
-

{{ stats.location_count }}

-

Locations

-
- -
-

{{ stats.device_count }}

-

Devices

-
-
-

{{ stats.prefix_count }}

-

Prefixes

-
- -
-

{{ stats.circuit_count }}

-

Circuits

-
-
-

{{ stats.vm_count }}

-

Virtual Machines

-
- -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Locations + {% if stats.location_count %} + {{ stats.location_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
Racks + {% if stats.rack_count %} + + {% else %} + {{ ''|placeholder }} + {% endif %} +
Devices + {% if stats.device_count %} + {{ stats.device_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
Virtual Machines + {% if stats.vm_count %} + {{ stats.vm_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
Prefixes + {% if stats.prefix_count %} + {{ stats.prefix_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
VLANs + {% if stats.vlan_count %} + {{ stats.vlan_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
ASNs + {% if stats.asn_count %} + {{ stats.asn_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
Circuits + {% if stats.circuit_count %} + {{ stats.circuit_count }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
{% include 'inc/panels/contacts.html' %} From 2b6e0405a5fdb3f8ff3504c16a4660b849b693c3 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 1 Mar 2022 11:43:00 -0500 Subject: [PATCH 27/36] Closes #8736: Add PC and UPC fiber end faces for LC/SC/LSH port types --- docs/release-notes/version-3.1.md | 1 + netbox/dcim/choices.py | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index d34271f4c..2b3cc4e7f 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -6,6 +6,7 @@ * [#8594](https://github.com/netbox-community/netbox/issues/8594) - Enable filtering by exact description match for all applicable models * [#8629](https://github.com/netbox-community/netbox/issues/8629) - Add description to tag table search function +* [#8736](https://github.com/netbox-community/netbox/issues/8736) - Add PC and UPC fiber end faces for LC/SC/LSH port types * [#8762](https://github.com/netbox-community/netbox/issues/8762) - Link to rack elevations list from site view * [#8766](https://github.com/netbox-community/netbox/issues/8766) - Add SCTP to service protocols list diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 1d3b59497..8900b2d89 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -1013,13 +1013,19 @@ class PortTypeChoices(ChoiceSet): TYPE_MRJ21 = 'mrj21' TYPE_ST = 'st' TYPE_SC = 'sc' + TYPE_SC_PC = 'sc-pc' + TYPE_SC_UPC = 'sc-upc' TYPE_SC_APC = 'sc-apc' TYPE_FC = 'fc' TYPE_LC = 'lc' + TYPE_LC_PC = 'lc-pc' + TYPE_LC_UPC = 'lc-upc' TYPE_LC_APC = 'lc-apc' TYPE_MTRJ = 'mtrj' TYPE_MPO = 'mpo' TYPE_LSH = 'lsh' + TYPE_LSH_PC = 'lsh-pc' + TYPE_LSH_UPC = 'lsh-upc' TYPE_LSH_APC = 'lsh-apc' TYPE_SPLICE = 'splice' TYPE_CS = 'cs' @@ -1059,12 +1065,18 @@ class PortTypeChoices(ChoiceSet): ( (TYPE_FC, 'FC'), (TYPE_LC, 'LC'), + (TYPE_LC_PC, 'LC/PC'), + (TYPE_LC_UPC, 'LC/UPC'), (TYPE_LC_APC, 'LC/APC'), (TYPE_LSH, 'LSH'), + (TYPE_LSH_PC, 'LSH/PC'), + (TYPE_LSH_UPC, 'LSH/UPC'), (TYPE_LSH_APC, 'LSH/APC'), (TYPE_MPO, 'MPO'), (TYPE_MTRJ, 'MTRJ'), (TYPE_SC, 'SC'), + (TYPE_SC_PC, 'SC/PC'), + (TYPE_SC_UPC, 'SC/UPC'), (TYPE_SC_APC, 'SC/APC'), (TYPE_ST, 'ST'), (TYPE_CS, 'CS'), From e3258bcf5a3fbcdea7b0c0ab08fa8bca71b50b6c Mon Sep 17 00:00:00 2001 From: Jason Yates Date: Wed, 2 Mar 2022 08:45:22 +0000 Subject: [PATCH 28/36] Updating mkdocs to automatically adjust theme Automatically adjusts documentation theme between default/slate based on users preference for dark mode. --- mkdocs.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 4be5b16e7..6245f3bb2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,11 +8,13 @@ theme: icon: repo: fontawesome/brands/github palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default toggle: icon: material/lightbulb-outline name: Switch to Dark Mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate toggle: icon: material/lightbulb name: Switch to Light Mode From 90257e9dee40e0317bcbd8cab81d99e6ab57c140 Mon Sep 17 00:00:00 2001 From: seros1521 <55374617+seros1521@users.noreply.github.com> Date: Fri, 4 Mar 2022 13:15:24 +0700 Subject: [PATCH 29/36] Fixes #8715: eliminates duplicates when used in many-to-many field constraints When using permissions that use tags, a user may receive multiple permissions of the same type if multiple tags are assigned to the device. This causes the RestrictedQuerySet class to generate a query similar to this: >>> dcim.models.Device.objects.filter(Q(tags__name='tag1')|Q(tags__name='tag2')) , ]> This query returns the same object twice if both tags are assigned to it. This is due to the use of the django-taggit library. The library's documentation describes this behavior as expected and suggests using an explicit distinct() call in queries to avoid duplicates. However, the use of DISTINCT in queries has a global side effect - deduplication of responses, which may or may not be acceptable behavior (depending on further use). Since it is not known how RestrictedQuerySet will be used in the rest of the code, it was decided to dedupe using a subquery. --- netbox/utilities/querysets.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/netbox/utilities/querysets.py b/netbox/utilities/querysets.py index 738b72dc3..97d2e8779 100644 --- a/netbox/utilities/querysets.py +++ b/netbox/utilities/querysets.py @@ -39,6 +39,12 @@ class RestrictedQuerySet(QuerySet): # Any permission with null constraints grants access to _all_ instances attrs = Q() break + else: + # for else, when no break + # avoid duplicates when JOIN on many-to-many fields without using DISTINCT. + # DISTINCT acts globally on the entire request, which may not be desirable. + allowed_objects = self.model.objects.filter(attrs) + attrs = Q(pk__in=allowed_objects) qs = self.filter(attrs) return qs From 5c48d116eb3568465f2d75cc157172519a923d20 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Fri, 4 Mar 2022 13:20:17 -0500 Subject: [PATCH 30/36] Closes #8664: Show assigned ASNs/sites under list views --- docs/release-notes/version-3.1.md | 1 + netbox/dcim/tables/sites.py | 8 ++++++-- netbox/ipam/tables/ip.py | 6 +++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 2b3cc4e7f..deb23d724 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -6,6 +6,7 @@ * [#8594](https://github.com/netbox-community/netbox/issues/8594) - Enable filtering by exact description match for all applicable models * [#8629](https://github.com/netbox-community/netbox/issues/8629) - Add description to tag table search function +* [#8664](https://github.com/netbox-community/netbox/issues/8664) - Show assigned ASNs/sites under list views * [#8736](https://github.com/netbox-community/netbox/issues/8736) - Add PC and UPC fiber end faces for LC/SC/LSH port types * [#8762](https://github.com/netbox-community/netbox/issues/8762) - Link to rack elevations list from site view * [#8766](https://github.com/netbox-community/netbox/issues/8766) - Add SCTP to service protocols list diff --git a/netbox/dcim/tables/sites.py b/netbox/dcim/tables/sites.py index e658f1caa..bf4812cfa 100644 --- a/netbox/dcim/tables/sites.py +++ b/netbox/dcim/tables/sites.py @@ -85,6 +85,10 @@ class SiteTable(BaseTable): accessor=tables.A('asns__count'), viewname='ipam:asn_list', url_params={'site_id': 'pk'}, + verbose_name='ASN Count' + ) + asns = tables.ManyToManyColumn( + linkify_item=True, verbose_name='ASNs' ) tenant = TenantColumn() @@ -96,8 +100,8 @@ class SiteTable(BaseTable): class Meta(BaseTable.Meta): model = Site fields = ( - 'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'asn_count', 'time_zone', - 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', + 'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'asns', 'asn_count', + 'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone', 'contact_email', 'comments', 'tags', 'created', 'last_updated', ) default_columns = ('pk', 'name', 'status', 'facility', 'region', 'group', 'tenant', 'description') diff --git a/netbox/ipam/tables/ip.py b/netbox/ipam/tables/ip.py index 2cd2ab6ac..f1d490463 100644 --- a/netbox/ipam/tables/ip.py +++ b/netbox/ipam/tables/ip.py @@ -117,6 +117,10 @@ class ASNTable(BaseTable): site_count = LinkedCountColumn( viewname='dcim:site_list', url_params={'asn_id': 'pk'}, + verbose_name='Site Count' + ) + sites = tables.ManyToManyColumn( + linkify_item=True, verbose_name='Sites' ) tenant = TenantColumn() @@ -129,7 +133,7 @@ class ASNTable(BaseTable): class Meta(BaseTable.Meta): model = ASN fields = ( - 'pk', 'asn', 'asn_asdot', 'rir', 'site_count', 'tenant', 'description', 'actions', 'created', + 'pk', 'asn', 'asn_asdot', 'rir', 'site_count', 'tenant', 'description', 'sites', 'actions', 'created', 'last_updated', 'tags', ) default_columns = ('pk', 'asn', 'rir', 'site_count', 'sites', 'description', 'tenant', 'actions') From 6423b386d2556605f4939baaf8f3e9bf0749ff4f Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Fri, 4 Mar 2022 13:30:32 -0500 Subject: [PATCH 31/36] Closes #8758: Allow empty string substitution when renaming objects in bulk --- docs/release-notes/version-3.1.md | 1 + netbox/utilities/forms/forms.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index deb23d724..f444b74bf 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -8,6 +8,7 @@ * [#8629](https://github.com/netbox-community/netbox/issues/8629) - Add description to tag table search function * [#8664](https://github.com/netbox-community/netbox/issues/8664) - Show assigned ASNs/sites under list views * [#8736](https://github.com/netbox-community/netbox/issues/8736) - Add PC and UPC fiber end faces for LC/SC/LSH port types +* [#8758](https://github.com/netbox-community/netbox/issues/8758) - Allow empty string substitution when renaming objects in bulk * [#8762](https://github.com/netbox-community/netbox/issues/8762) - Link to rack elevations list from site view * [#8766](https://github.com/netbox-community/netbox/issues/8766) - Add SCTP to service protocols list diff --git a/netbox/utilities/forms/forms.py b/netbox/utilities/forms/forms.py index 88f837b2b..b69472e6f 100644 --- a/netbox/utilities/forms/forms.py +++ b/netbox/utilities/forms/forms.py @@ -98,7 +98,9 @@ class BulkRenameForm(BootstrapMixin, forms.Form): An extendable form to be used for renaming objects in bulk. """ find = forms.CharField() - replace = forms.CharField() + replace = forms.CharField( + required=False + ) use_regex = forms.BooleanField( required=False, initial=True, From 81610ba86eeeeeac6c3ac5b9719f70831cf3ffa2 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Fri, 4 Mar 2022 13:45:59 -0500 Subject: [PATCH 32/36] Fixes #8724: Fix exception during device import with invalid device type --- docs/release-notes/version-3.1.md | 1 + netbox/dcim/models/devices.py | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index f444b74bf..b530c269a 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -20,6 +20,7 @@ * [#8710](https://github.com/netbox-community/netbox/issues/8710) - Fix dynamic scope selection form fields when creating a VLAN group * [#8713](https://github.com/netbox-community/netbox/issues/8713) - Restore missing "add" button on services list view * [#8717](https://github.com/netbox-community/netbox/issues/8717) - Fix redirection after bulk edit/delete of prefixes from aggregate view +* [#8724](https://github.com/netbox-community/netbox/issues/8724) - Fix exception during device import with invalid device type --- diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index a2ae20319..6b8ff043d 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -670,10 +670,11 @@ class Device(PrimaryModel, ConfigContextModel): }) # Prevent 0U devices from being assigned to a specific position - if self.position and self.device_type.u_height == 0: - raise ValidationError({ - 'position': f"A U0 device type ({self.device_type}) cannot be assigned to a rack position." - }) + if hasattr(self, 'device_type'): + if self.position and self.device_type.u_height == 0: + raise ValidationError({ + 'position': f"A U0 device type ({self.device_type}) cannot be assigned to a rack position." + }) if self.rack: From 2451b0a5b14734df5553df9944ffe6670de06725 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 7 Mar 2022 08:50:58 -0500 Subject: [PATCH 33/36] Clean up search results layout --- netbox/templates/search.html | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/netbox/templates/search.html b/netbox/templates/search.html index 187b76c59..a47b48b09 100644 --- a/netbox/templates/search.html +++ b/netbox/templates/search.html @@ -5,7 +5,18 @@ {% block title %}Search{% endblock %} -{% block content %} +{% block tabs %} + +{% endblock tabs %} + +{% block content-wrapper %} +
{% if request.GET.q %} {% if results %}
@@ -73,4 +84,5 @@
{% endif %} -{% endblock content %} +
+{% endblock content-wrapper %} From 3c78c100b5b69aa1424754697438a6029d860a56 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 7 Mar 2022 09:00:00 -0500 Subject: [PATCH 34/36] Fixes #8808: Fix members count under FHRP group list --- docs/release-notes/version-3.1.md | 1 + netbox/ipam/tables/fhrp.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index b530c269a..0d1e44ab9 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -21,6 +21,7 @@ * [#8713](https://github.com/netbox-community/netbox/issues/8713) - Restore missing "add" button on services list view * [#8717](https://github.com/netbox-community/netbox/issues/8717) - Fix redirection after bulk edit/delete of prefixes from aggregate view * [#8724](https://github.com/netbox-community/netbox/issues/8724) - Fix exception during device import with invalid device type +* [#8808](https://github.com/netbox-community/netbox/issues/8808) - Fix members count under FHRP group list --- diff --git a/netbox/ipam/tables/fhrp.py b/netbox/ipam/tables/fhrp.py index d615b6374..19f1c8c71 100644 --- a/netbox/ipam/tables/fhrp.py +++ b/netbox/ipam/tables/fhrp.py @@ -27,8 +27,8 @@ class FHRPGroupTable(BaseTable): orderable=False, verbose_name='IP Addresses' ) - interface_count = tables.Column( - verbose_name='Interfaces' + member_count = tables.Column( + verbose_name='Members' ) tags = TagColumn( url_name='ipam:fhrpgroup_list' @@ -37,10 +37,10 @@ class FHRPGroupTable(BaseTable): class Meta(BaseTable.Meta): model = FHRPGroup fields = ( - 'pk', 'group_id', 'protocol', 'auth_type', 'auth_key', 'description', 'ip_addresses', 'interface_count', + 'pk', 'group_id', 'protocol', 'auth_type', 'auth_key', 'description', 'ip_addresses', 'member_count', 'tags', 'created', 'last_updated', ) - default_columns = ('pk', 'group_id', 'protocol', 'auth_type', 'description', 'ip_addresses', 'interface_count') + default_columns = ('pk', 'group_id', 'protocol', 'auth_type', 'description', 'ip_addresses', 'member_count') class FHRPGroupAssignmentTable(BaseTable): From 2cfbfe473e7548dc5cb37b5005b36c67f055333e Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 7 Mar 2022 09:02:47 -0500 Subject: [PATCH 35/36] Fixes #8807: Correct REST API URL for FHRP group assignments --- docs/release-notes/version-3.1.md | 1 + netbox/ipam/api/serializers.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index 0d1e44ab9..a78fe8fb7 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -21,6 +21,7 @@ * [#8713](https://github.com/netbox-community/netbox/issues/8713) - Restore missing "add" button on services list view * [#8717](https://github.com/netbox-community/netbox/issues/8717) - Fix redirection after bulk edit/delete of prefixes from aggregate view * [#8724](https://github.com/netbox-community/netbox/issues/8724) - Fix exception during device import with invalid device type +* [#8807](https://github.com/netbox-community/netbox/issues/8807) - Correct REST API URL for FHRP group assignments * [#8808](https://github.com/netbox-community/netbox/issues/8808) - Fix members count under FHRP group list --- diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index aa1d2834a..a2c47aaec 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -126,7 +126,7 @@ class FHRPGroupSerializer(PrimaryModelSerializer): class FHRPGroupAssignmentSerializer(PrimaryModelSerializer): - url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:contactassignment-detail') + url = serializers.HyperlinkedIdentityField(view_name='ipam-api:fhrpgroupassignment-detail') group = NestedFHRPGroupSerializer() interface_type = ContentTypeField( queryset=ContentType.objects.all() From a5603c9953bb7540d339a2dab670e73e6a894550 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 7 Mar 2022 09:47:31 -0500 Subject: [PATCH 36/36] Release v3.1.9 --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- .github/ISSUE_TEMPLATE/feature_request.yaml | 2 +- docs/release-notes/version-3.1.md | 3 ++- netbox/netbox/settings.py | 2 +- requirements.txt | 4 ++-- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index ad72e0735..3af825d30 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.1.8 + placeholder: v3.1.9 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 68256471c..f5bf198b8 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.1.8 + placeholder: v3.1.9 validations: required: true - type: dropdown diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index a78fe8fb7..5decff1b3 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -1,6 +1,6 @@ # NetBox v3.1 -## v3.1.9 (FUTURE) +## v3.1.9 (2022-03-07) ### Enhancements @@ -19,6 +19,7 @@ * [#8674](https://github.com/netbox-community/netbox/issues/8674) - Fix rendering of tabbed content in documentation * [#8710](https://github.com/netbox-community/netbox/issues/8710) - Fix dynamic scope selection form fields when creating a VLAN group * [#8713](https://github.com/netbox-community/netbox/issues/8713) - Restore missing "add" button on services list view +* [#8715](https://github.com/netbox-community/netbox/issues/8715) - Avoid returning multiple objects when restricting querysets using multiple tags in permissions * [#8717](https://github.com/netbox-community/netbox/issues/8717) - Fix redirection after bulk edit/delete of prefixes from aggregate view * [#8724](https://github.com/netbox-community/netbox/issues/8724) - Fix exception during device import with invalid device type * [#8807](https://github.com/netbox-community/netbox/issues/8807) - Correct REST API URL for FHRP group assignments diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index f5501f54f..02d52664f 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -19,7 +19,7 @@ from netbox.config import PARAMS # Environment setup # -VERSION = '3.1.9-dev' +VERSION = '3.1.9' # Hostname HOSTNAME = platform.node() diff --git a/requirements.txt b/requirements.txt index 5489b99cd..b975877bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ django-redis==5.2.0 django-rq==2.5.1 django-tables2==2.4.1 django-taggit==2.1.0 -django-timezone-field==4.2.3 +django-timezone-field==5.0 djangorestframework==3.12.4 drf-yasg[validation]==1.20.0 graphene_django==2.15.0 @@ -18,7 +18,7 @@ gunicorn==20.1.0 Jinja2==3.0.3 Markdown==3.3.6 markdown-include==0.6.0 -mkdocs-material==8.1.11 +mkdocs-material==8.2.5 netaddr==0.8.0 Pillow==9.0.1 psycopg2-binary==2.9.3