From 196407307219fd29e3540965f0500bf4331f5876 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 16:02:14 -0500 Subject: [PATCH 01/20] PRVB --- netbox/netbox/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 3dd780b26..af5b01adc 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -16,7 +16,7 @@ from django.core.validators import URLValidator # Environment setup # -VERSION = '2.10.4' +VERSION = '2.10.5-dev' # Hostname HOSTNAME = platform.node() From f28474d86ee2f29cbf6e761b25cf1d464dc329c0 Mon Sep 17 00:00:00 2001 From: Brian Candler Date: Tue, 2 Feb 2021 08:16:35 +0000 Subject: [PATCH 02/20] Fix sample report in documentation Raised in #5729 --- docs/additional-features/reports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/additional-features/reports.md b/docs/additional-features/reports.md index 9d60f797e..1266c22ec 100644 --- a/docs/additional-features/reports.md +++ b/docs/additional-features/reports.md @@ -66,7 +66,7 @@ class DeviceConnectionsReport(Report): for power_port in PowerPort.objects.filter(device=device): if power_port.connected_endpoint is not None: connected_ports += 1 - if not power_port.connection_status: + if not power_port.path.is_active: self.log_warning( device, "Power connection for {} marked as planned".format(power_port.name) From b4ba5cbb7a3e365f8c1d145b0b2ce05850323ca1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 2 Feb 2021 11:49:38 -0500 Subject: [PATCH 03/20] Fixes #5716: Fix filtering rack reservations by custom field --- docs/release-notes/version-2.10.md | 8 ++++++++ netbox/dcim/filters.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index b6bc33229..49f80d897 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -1,5 +1,13 @@ # NetBox v2.10 +## v2.10.5 (FUTURE) + +### Bug Fixes + +* [#5716](https://github.com/netbox-community/netbox/issues/5716) - Fix filtering rack reservations by custom field + +--- + ## v2.10.4 (2021-01-26) ### Enhancements diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 03deca2a4..41363c261 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -264,7 +264,7 @@ class RackFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, ) -class RackReservationFilterSet(BaseFilterSet, TenancyFilterSet): +class RackReservationFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet): q = django_filters.CharFilter( method='search', label='Search', From be1b6b6aa3c0ad0880f72a69da70a8c31e9bc295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Blot?= Date: Thu, 4 Feb 2021 16:50:07 +0100 Subject: [PATCH 04/20] fix: add missing password when using redis in sentinel mode --- netbox/netbox/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index af5b01adc..1e77619b8 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -391,6 +391,7 @@ if CACHING_REDIS_USING_SENTINEL: 'locations': CACHING_REDIS_SENTINELS, 'service_name': CACHING_REDIS_SENTINEL_SERVICE, 'db': CACHING_REDIS_DATABASE, + 'password': CACHING_REDIS_PASSWORD, } else: if CACHING_REDIS_SSL: From e3e928f1c4dbd45a66b35328dfb2252d3b512417 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 4 Feb 2021 13:01:55 -0500 Subject: [PATCH 05/20] Fixes #5718: Fix bulk editing of services when no port(s) are defined --- docs/release-notes/version-2.10.md | 1 + netbox/netbox/views/generic.py | 2 +- netbox/utilities/forms/widgets.py | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 49f80d897..fccd86abd 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -5,6 +5,7 @@ ### Bug Fixes * [#5716](https://github.com/netbox-community/netbox/issues/5716) - Fix filtering rack reservations by custom field +* [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined --- diff --git a/netbox/netbox/views/generic.py b/netbox/netbox/views/generic.py index bd21d469c..216b50759 100644 --- a/netbox/netbox/views/generic.py +++ b/netbox/netbox/views/generic.py @@ -792,7 +792,7 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): if form.cleaned_data[name]: getattr(obj, name).set(form.cleaned_data[name]) # Normal fields - elif form.cleaned_data[name] not in (None, ''): + elif form.cleaned_data[name] not in (None, '', []): setattr(obj, name, form.cleaned_data[name]) # Update custom fields diff --git a/netbox/utilities/forms/widgets.py b/netbox/utilities/forms/widgets.py index cd6fb0fbb..1c456c74c 100644 --- a/netbox/utilities/forms/widgets.py +++ b/netbox/utilities/forms/widgets.py @@ -114,7 +114,10 @@ class ContentTypeSelect(StaticSelect2): class NumericArrayField(SimpleArrayField): def to_python(self, value): - value = ','.join([str(n) for n in parse_numeric_range(value)]) + if not value: + return [] + if isinstance(value, str): + value = ','.join([str(n) for n in parse_numeric_range(value)]) return super().to_python(value) From 1430c0a6e6444b06581dae6e6deb4a0434dd95ee Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 4 Feb 2021 13:19:42 -0500 Subject: [PATCH 06/20] Fixes #5738: Fix redirect to device components view after disconnecting a cable --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/tables/template_code.py | 35 +++++++++++++++++++ .../dcim/inc/cable_toggle_buttons.html | 5 --- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index fccd86abd..94b80ef1c 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -6,6 +6,7 @@ * [#5716](https://github.com/netbox-community/netbox/issues/5716) - Fix filtering rack reservations by custom field * [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined +* [#5738](https://github.com/netbox-community/netbox/issues/5738) - Fix redirect to device components view after disconnecting a cable --- diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py index ee1dc091b..7a52b85b0 100644 --- a/netbox/dcim/tables/template_code.py +++ b/netbox/dcim/tables/template_code.py @@ -95,6 +95,11 @@ CONSOLEPORT_BUTTONS = """ {% if record.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} + {% if perms.dcim.delete_cable %} + + + + {% endif %} {% elif perms.dcim.add_cable %} @@ -115,6 +120,11 @@ CONSOLESERVERPORT_BUTTONS = """ {% if record.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} + {% if perms.dcim.delete_cable %} + + + + {% endif %} {% elif perms.dcim.add_cable %} @@ -135,6 +145,11 @@ POWERPORT_BUTTONS = """ {% if record.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} + {% if perms.dcim.delete_cable %} + + + + {% endif %} {% elif perms.dcim.add_cable %} @@ -154,6 +169,11 @@ POWEROUTLET_BUTTONS = """ {% if record.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} + {% if perms.dcim.delete_cable %} + + + + {% endif %} {% elif perms.dcim.add_cable %} @@ -172,6 +192,11 @@ INTERFACE_BUTTONS = """ {% if record.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} + {% if perms.dcim.delete_cable %} + + + + {% endif %} {% elif record.is_connectable and perms.dcim.add_cable %} @@ -193,6 +218,11 @@ FRONTPORT_BUTTONS = """ {% if record.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} + {% if perms.dcim.delete_cable %} + + + + {% endif %} {% elif perms.dcim.add_cable %} @@ -216,6 +246,11 @@ REARPORT_BUTTONS = """ {% if record.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} + {% if perms.dcim.delete_cable %} + + + + {% endif %} {% elif perms.dcim.add_cable %} diff --git a/netbox/templates/dcim/inc/cable_toggle_buttons.html b/netbox/templates/dcim/inc/cable_toggle_buttons.html index 98e4efd94..e3eb318ac 100644 --- a/netbox/templates/dcim/inc/cable_toggle_buttons.html +++ b/netbox/templates/dcim/inc/cable_toggle_buttons.html @@ -9,8 +9,3 @@ {% endif %} {% endif %} -{% if perms.dcim.delete_cable %} - - - -{% endif %} From 5fbe766a0a3e887298ce4c993b282525c0df3a93 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Thu, 4 Feb 2021 21:36:06 +0100 Subject: [PATCH 07/20] NetBox should always be referred to as NetBox Fix all instances of "Netbox" except the one that is used as an example how not to write it. Ref: docs/development/style-guide.md --- docs/additional-features/prometheus-metrics.md | 2 +- docs/installation/6-ldap.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/additional-features/prometheus-metrics.md b/docs/additional-features/prometheus-metrics.md index 048eb68b3..56365e336 100644 --- a/docs/additional-features/prometheus-metrics.md +++ b/docs/additional-features/prometheus-metrics.md @@ -26,4 +26,4 @@ For the exhaustive list of exposed metrics, visit the `/metrics` endpoint on you When deploying NetBox in a multiprocess manner (e.g. running multiple Gunicorn workers) the Prometheus client library requires the use of a shared directory to collect metrics from all worker processes. To configure this, first create or designate a local directory to which the worker processes have read and write access, and then configure your WSGI service (e.g. Gunicorn) to define this path as the `prometheus_multiproc_dir` environment variable. !!! warning - If having accurate long-term metrics in a multiprocess environment is crucial to your deployment, it's recommended you use the `uwsgi` library instead of `gunicorn`. The issue lies in the way `gunicorn` tracks worker processes (vs `uwsgi`) which helps manage the metrics files created by the above configurations. If you're using Netbox with gunicorn in a containerized enviroment following the one-process-per-container methodology, then you will likely not need to change to `uwsgi`. More details can be found in [issue #3779](https://github.com/netbox-community/netbox/issues/3779#issuecomment-590547562). \ No newline at end of file + If having accurate long-term metrics in a multiprocess environment is crucial to your deployment, it's recommended you use the `uwsgi` library instead of `gunicorn`. The issue lies in the way `gunicorn` tracks worker processes (vs `uwsgi`) which helps manage the metrics files created by the above configurations. If you're using NetBox with gunicorn in a containerized enviroment following the one-process-per-container methodology, then you will likely not need to change to `uwsgi`. More details can be found in [issue #3779](https://github.com/netbox-community/netbox/issues/3779#issuecomment-590547562). diff --git a/docs/installation/6-ldap.md b/docs/installation/6-ldap.md index 25f9c8f2b..1c5424595 100644 --- a/docs/installation/6-ldap.md +++ b/docs/installation/6-ldap.md @@ -140,7 +140,7 @@ AUTH_LDAP_CACHE_TIMEOUT = 3600 ## Troubleshooting LDAP -`systemctl restart netbox` restarts the Netbox service, and initiates any changes made to `ldap_config.py`. If there are syntax errors present, the NetBox process will not spawn an instance, and errors should be logged to `/var/log/messages`. +`systemctl restart netbox` restarts the NetBox service, and initiates any changes made to `ldap_config.py`. If there are syntax errors present, the NetBox process will not spawn an instance, and errors should be logged to `/var/log/messages`. For troubleshooting LDAP user/group queries, add or merge the following [logging](/configuration/optional-settings.md#logging) configuration to `configuration.py`: From 713f02ca3fe7d05a005ef8f0975c62f6bb812052 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 7 Feb 2021 10:31:56 +0000 Subject: [PATCH 08/20] Fixes #5735: enforcement of duplicate IP address detection with roles --- netbox/ipam/models.py | 11 +++++------ netbox/ipam/tests/test_models.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 0ae9db7b2..e8b3dff0a 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -734,13 +734,12 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): }) # Enforce unique IP space (if applicable) - if self.role not in IPADDRESS_ROLES_NONUNIQUE and (( - self.vrf is None and settings.ENFORCE_GLOBAL_UNIQUE - ) or ( - self.vrf and self.vrf.enforce_unique - )): + if (self.vrf is None and settings.ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique): duplicate_ips = self.get_duplicates() - if duplicate_ips: + if duplicate_ips and ( + self.role not in IPADDRESS_ROLES_NONUNIQUE or + any(dip.role not in IPADDRESS_ROLES_NONUNIQUE for dip in duplicate_ips) + ): raise ValidationError({ 'address': "Duplicate IP address found in {}: {}".format( "VRF {}".format(self.vrf) if self.vrf else "global table", diff --git a/netbox/ipam/tests/test_models.py b/netbox/ipam/tests/test_models.py index 6091aa70e..a47862165 100644 --- a/netbox/ipam/tests/test_models.py +++ b/netbox/ipam/tests/test_models.py @@ -259,6 +259,18 @@ class TestIPAddress(TestCase): duplicate_ip = IPAddress(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24')) self.assertRaises(ValidationError, duplicate_ip.clean) + @override_settings(ENFORCE_GLOBAL_UNIQUE=True) + def test_duplicate_nonunique_nonrole_role(self): + IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24')) + duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) + self.assertRaises(ValidationError, duplicate_ip.clean) + + @override_settings(ENFORCE_GLOBAL_UNIQUE=True) + def test_duplicate_nonunique_role_nonrole(self): + IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) + duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')) + self.assertRaises(ValidationError, duplicate_ip.clean) + @override_settings(ENFORCE_GLOBAL_UNIQUE=True) def test_duplicate_nonunique_role(self): IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) From 3b53cf5e8458c770e92d1a0477843b9c0d8b5ec6 Mon Sep 17 00:00:00 2001 From: Brian Candler Date: Sun, 7 Feb 2021 19:46:30 +0000 Subject: [PATCH 09/20] Update docs to to create database explicitly with UTF8 encoding. Fixes #5760 --- docs/installation/1-postgresql.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/1-postgresql.md b/docs/installation/1-postgresql.md index bcc670e2b..4ac1104d7 100644 --- a/docs/installation/1-postgresql.md +++ b/docs/installation/1-postgresql.md @@ -51,7 +51,7 @@ $ sudo -u postgres psql psql (12.5 (Ubuntu 12.5-0ubuntu0.20.04.1)) Type "help" for help. -postgres=# CREATE DATABASE netbox; +postgres=# CREATE DATABASE netbox ENCODING 'UTF8' LC_COLLATE='C.UTF-8' LC_CTYPE='C.UTF-8'; CREATE DATABASE postgres=# CREATE USER netbox WITH PASSWORD 'J5brHrAXFLQSif0K'; CREATE ROLE From 6c676d21c3d3eed26b330e71eb9ed3bf81c1f9f6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 8 Feb 2021 15:09:20 -0500 Subject: [PATCH 10/20] Changelog for #5735 --- docs/release-notes/version-2.10.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 94b80ef1c..caf37b1ce 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -6,6 +6,7 @@ * [#5716](https://github.com/netbox-community/netbox/issues/5716) - Fix filtering rack reservations by custom field * [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined +* [#5735](https://github.com/netbox-community/netbox/issues/5735) - Ensure consistent treatment of duplicate IP addresses * [#5738](https://github.com/netbox-community/netbox/issues/5738) - Fix redirect to device components view after disconnecting a cable --- From 3d90e3aee9e14875c6caa25f22a62baafa7e065c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 8 Feb 2021 16:44:04 -0500 Subject: [PATCH 11/20] Fixes #5626: Fix REST API representation for circuit terminations connected to non-interface endpoints --- docs/release-notes/version-2.10.md | 1 + netbox/circuits/api/serializers.py | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index caf37b1ce..320217a74 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -4,6 +4,7 @@ ### Bug Fixes +* [#5626](https://github.com/netbox-community/netbox/issues/5626) - Fix REST API representation for circuit terminations connected to non-interface endpoints * [#5716](https://github.com/netbox-community/netbox/issues/5716) - Fix filtering rack reservations by custom field * [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined * [#5735](https://github.com/netbox-community/netbox/issues/5735) - Ensure consistent treatment of duplicate IP addresses diff --git a/netbox/circuits/api/serializers.py b/netbox/circuits/api/serializers.py index 88890bf95..12ec9ba7f 100644 --- a/netbox/circuits/api/serializers.py +++ b/netbox/circuits/api/serializers.py @@ -40,14 +40,16 @@ class CircuitTypeSerializer(ValidatedModelSerializer): fields = ['id', 'url', 'name', 'slug', 'description', 'circuit_count'] -class CircuitCircuitTerminationSerializer(WritableNestedSerializer): +class CircuitCircuitTerminationSerializer(WritableNestedSerializer, ConnectedEndpointSerializer): url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittermination-detail') site = NestedSiteSerializer() - connected_endpoint = NestedInterfaceSerializer() class Meta: model = CircuitTermination - fields = ['id', 'url', 'site', 'connected_endpoint', 'port_speed', 'upstream_speed', 'xconnect_id'] + fields = [ + 'id', 'url', 'site', 'port_speed', 'upstream_speed', 'xconnect_id', 'connected_endpoint', + 'connected_endpoint_type', 'connected_endpoint_reachable', + ] class CircuitSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): From 8640f500d1439f3d2deddb4edbe3069ee9594b62 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 9 Feb 2021 13:32:29 -0500 Subject: [PATCH 12/20] Closes #5776: Upgrade pip when running upgrade.sh --- upgrade.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/upgrade.sh b/upgrade.sh index 2e35a02f9..648f825a0 100755 --- a/upgrade.sh +++ b/upgrade.sh @@ -29,19 +29,25 @@ eval $COMMAND || { # Activate the virtual environment source "${VIRTUALENV}/bin/activate" +# Upgrade pip +COMMAND="pip install --upgrade pip" +echo "Updating pip ($COMMAND)..." +eval $COMMAND || exit 1 +pip -V + # Install necessary system packages -COMMAND="pip3 install wheel" +COMMAND="pip install wheel" echo "Installing Python system packages ($COMMAND)..." eval $COMMAND || exit 1 # Install required Python packages -COMMAND="pip3 install -r requirements.txt" +COMMAND="pip install -r requirements.txt" echo "Installing core dependencies ($COMMAND)..." eval $COMMAND || exit 1 # Install optional packages (if any) if [ -s "local_requirements.txt" ]; then - COMMAND="pip3 install -r local_requirements.txt" + COMMAND="pip install -r local_requirements.txt" echo "Installing local dependencies ($COMMAND)..." eval $COMMAND || exit 1 elif [ -f "local_requirements.txt" ]; then From efbda6d5afa9929148a346bbaf5b31011bb08a63 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 9 Feb 2021 15:15:49 -0500 Subject: [PATCH 13/20] Apply stale rules to PRs --- .github/stale.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/stale.yml b/.github/stale.yml index fdfb1d590..92da07e6a 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,8 +1,5 @@ # Configuration for Stale (https://github.com/apps/stale) -# Pull requests are exempt from being marked as stale -only: issues - # Number of days of inactivity before an issue becomes stale daysUntilStale: 45 From fa3199d41cd884a7137d612915054b3da5e63935 Mon Sep 17 00:00:00 2001 From: pgnuta Date: Thu, 11 Feb 2021 11:49:57 +1300 Subject: [PATCH 14/20] Update serializers.py Group should be nullable via API to match frontend functionality and Swagger documentation. --- netbox/tenancy/api/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/tenancy/api/serializers.py b/netbox/tenancy/api/serializers.py index 05e83853e..4c2f9faee 100644 --- a/netbox/tenancy/api/serializers.py +++ b/netbox/tenancy/api/serializers.py @@ -24,7 +24,7 @@ class TenantGroupSerializer(ValidatedModelSerializer): class TenantSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:tenant-detail') - group = NestedTenantGroupSerializer(required=False) + group = NestedTenantGroupSerializer(required=False, allow_null=True) circuit_count = serializers.IntegerField(read_only=True) device_count = serializers.IntegerField(read_only=True) ipaddress_count = serializers.IntegerField(read_only=True) From 3d3748d6f54cd2bd168554b141b5f3541a0b88ac Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Fri, 12 Feb 2021 10:53:40 -0600 Subject: [PATCH 15/20] Fixes: #5315 - Make "null_option" on DynamicModelChoiceField also null the value on the model. (#5704) Fixes: #5315 - Fix site unassignment from VLAN when using "None" option --- docs/release-notes/version-2.10.md | 1 + netbox/utilities/forms/fields.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 320217a74..bc3d0e1a5 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -4,6 +4,7 @@ ### Bug Fixes +* [#5315](https://github.com/netbox-community/netbox/issues/5315) - Fix site unassignment from VLAN when using "None" option * [#5626](https://github.com/netbox-community/netbox/issues/5626) - Fix REST API representation for circuit terminations connected to non-interface endpoints * [#5716](https://github.com/netbox-community/netbox/issues/5716) - Fix filtering rack reservations by custom field * [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined diff --git a/netbox/utilities/forms/fields.py b/netbox/utilities/forms/fields.py index a5b76fd8d..5f1e06c3b 100644 --- a/netbox/utilities/forms/fields.py +++ b/netbox/utilities/forms/fields.py @@ -5,6 +5,7 @@ from io import StringIO import django_filters from django import forms +from django.conf import settings from django.forms.fields import JSONField as _JSONField, InvalidJSONInput from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.db.models import Count @@ -355,7 +356,15 @@ class DynamicModelChoiceField(DynamicModelChoiceMixin, forms.ModelChoiceField): Override get_bound_field() to avoid pre-populating field choices with a SQL query. The field will be rendered only with choices set via bound data. Choices are populated on-demand via the APISelect widget. """ - pass + + def clean(self, value): + """ + When null option is enabled and "None" is sent as part of a form to be submitted, it is sent as the + string 'null'. This will check for that condition and gracefully handle the conversion to a NoneType. + """ + if self.null_option is not None and value == settings.FILTERS_NULL_CHOICE_VALUE: + return None + return super().clean(value) class DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultipleChoiceField): From 4c7c2edf9a2e905bf8b513df3bc030e750e29c70 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Mon, 22 Feb 2021 23:23:33 +0000 Subject: [PATCH 16/20] Fixes: #5847 - Provide custom CSS for pagination chevrons --- netbox/project-static/css/base.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netbox/project-static/css/base.css b/netbox/project-static/css/base.css index 94bd74a46..efdca81be 100644 --- a/netbox/project-static/css/base.css +++ b/netbox/project-static/css/base.css @@ -177,6 +177,10 @@ nav ul.pagination { margin-top: 0; margin-bottom: 8px !important; } +.pagination > li > a > .mdi::before { + top: 0; + font-size: 14px; +} /* Devices */ table.component-list td.subtable { From b392502b9b3ac33669a8fb22213dbad9b4585959 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 24 Feb 2021 14:21:42 -0500 Subject: [PATCH 17/20] Fixes #5841: Disallow the creation of available prefixes/IP addresses in violation of assigned permission constraints --- docs/release-notes/version-2.10.md | 1 + netbox/ipam/api/views.py | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index bc3d0e1a5..f42522194 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -10,6 +10,7 @@ * [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined * [#5735](https://github.com/netbox-community/netbox/issues/5735) - Ensure consistent treatment of duplicate IP addresses * [#5738](https://github.com/netbox-community/netbox/issues/5738) - Fix redirect to device components view after disconnecting a cable +* [#5841](https://github.com/netbox-community/netbox/issues/5841) - Disallow the creation of available prefixes/IP addresses in violation of assigned permission constraints --- diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index c322c249d..16db8f04f 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -1,4 +1,6 @@ from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied +from django.db import transaction from django.shortcuts import get_object_or_404 from django_pglocks import advisory_lock from drf_yasg.utils import swagger_auto_schema @@ -162,7 +164,12 @@ class PrefixViewSet(CustomFieldModelViewSet): # Create the new Prefix(es) if serializer.is_valid(): - serializer.save() + try: + with transaction.atomic(): + created = serializer.save() + self._validate_objects(created) + except ObjectDoesNotExist: + raise PermissionDenied() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -225,7 +232,12 @@ class PrefixViewSet(CustomFieldModelViewSet): # Create the new IP address(es) if serializer.is_valid(): - serializer.save() + try: + with transaction.atomic(): + created = serializer.save() + self._validate_objects(created) + except ObjectDoesNotExist: + raise PermissionDenied() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) From 04a6e2de9df26e900afeb48b34f677af3e6f9f23 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 24 Feb 2021 14:39:09 -0500 Subject: [PATCH 18/20] Changelog and test for #5786 --- docs/release-notes/version-2.10.md | 1 + netbox/tenancy/tests/test_api.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index f42522194..1817edb56 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -10,6 +10,7 @@ * [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined * [#5735](https://github.com/netbox-community/netbox/issues/5735) - Ensure consistent treatment of duplicate IP addresses * [#5738](https://github.com/netbox-community/netbox/issues/5738) - Fix redirect to device components view after disconnecting a cable +* [#5786](https://github.com/netbox-community/netbox/issues/5786) - Allow setting null tenant group on tenant via REST API * [#5841](https://github.com/netbox-community/netbox/issues/5841) - Disallow the creation of available prefixes/IP addresses in violation of assigned permission constraints --- diff --git a/netbox/tenancy/tests/test_api.py b/netbox/tenancy/tests/test_api.py index 7af3c8d79..c512ff688 100644 --- a/netbox/tenancy/tests/test_api.py +++ b/netbox/tenancy/tests/test_api.py @@ -56,6 +56,7 @@ class TenantTest(APIViewTestCases.APIViewTestCase): model = Tenant brief_fields = ['id', 'name', 'slug', 'url'] bulk_update_data = { + 'group': None, 'description': 'New description', } From a40f52ee6245df3bae406d39befd9bf82ee83a4b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 24 Feb 2021 15:02:13 -0500 Subject: [PATCH 19/20] Changelog for #5753 --- docs/release-notes/version-2.10.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 1817edb56..9d086789e 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -10,6 +10,7 @@ * [#5718](https://github.com/netbox-community/netbox/issues/5718) - Fix bulk editing of services when no port(s) are defined * [#5735](https://github.com/netbox-community/netbox/issues/5735) - Ensure consistent treatment of duplicate IP addresses * [#5738](https://github.com/netbox-community/netbox/issues/5738) - Fix redirect to device components view after disconnecting a cable +* [#5753](https://github.com/netbox-community/netbox/issues/5753) - Fix Redis Sentinel password application for caching * [#5786](https://github.com/netbox-community/netbox/issues/5786) - Allow setting null tenant group on tenant via REST API * [#5841](https://github.com/netbox-community/netbox/issues/5841) - Disallow the creation of available prefixes/IP addresses in violation of assigned permission constraints From db781437fc72b19c64cd0b55196d574bf08f3b14 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 24 Feb 2021 15:15:33 -0500 Subject: [PATCH 20/20] Release v2.10.5 --- docs/release-notes/version-2.10.md | 2 +- netbox/netbox/settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 9d086789e..2f7079f03 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -1,6 +1,6 @@ # NetBox v2.10 -## v2.10.5 (FUTURE) +## v2.10.5 (2021-02-24) ### Bug Fixes diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 1e77619b8..af5f5521b 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -16,7 +16,7 @@ from django.core.validators import URLValidator # Environment setup # -VERSION = '2.10.5-dev' +VERSION = '2.10.5' # Hostname HOSTNAME = platform.node()