From c8f09f28b16979e84b32dca7b859cb9d5f4dd952 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 5 Jan 2021 21:10:58 -0500 Subject: [PATCH 01/80] 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 4c36332fc..ed1f9c732 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.3' +VERSION = '2.10.4-dev' # Hostname HOSTNAME = platform.node() From 47b7ec8d00905dd82a44945691b526750d1467ac Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 Jan 2021 11:19:11 -0500 Subject: [PATCH 02/80] Fixes #5584: Restore power utilization panel under device view --- docs/release-notes/version-2.10.md | 8 ++++++++ netbox/templates/dcim/device.html | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index a3ab5968c..9773ec1b7 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.4 (FUTURE) + +### Bug Fixes + +* [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view + +--- + ## v2.10.3 (2021-01-05) ### Bug Fixes diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 97f7c8953..55be343ac 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -204,7 +204,7 @@ {% plugin_left_page object %}
- {% if power_ports and poweroutlets %} + {% if object.powerports.exists and object.poweroutlets.exists %}
Power Utilization @@ -217,10 +217,10 @@ Available Utilization - {% for pp in power_ports %} - {% with utilization=pp.get_power_draw powerfeed=pp.connected_endpoint %} + {% for powerport in object.powerports.all %} + {% with utilization=powerport.get_power_draw powerfeed=powerport.connected_endpoint %} - {{ pp }} + {{ powerport }} {{ utilization.outlet_count }} {{ utilization.allocated }}VA {% if powerfeed.available_power %} From e9d888bf6330f1107f38aaa2458b7c04a34fc9fb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 Jan 2021 11:29:59 -0500 Subject: [PATCH 03/80] Closes #5570: Add "management only" filter widget for interfaces list --- docs/release-notes/version-2.10.md | 4 ++++ netbox/dcim/forms.py | 6 ++++++ netbox/dcim/tables/devices.py | 1 + 3 files changed, 11 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 9773ec1b7..f9dee5dec 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -2,6 +2,10 @@ ## v2.10.4 (FUTURE) +### Enhancements + +* [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list + ### Bug Fixes * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index f7eb510ec..18fdbdb40 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2687,6 +2687,12 @@ class InterfaceFilterForm(DeviceComponentFilterForm): choices=BOOLEAN_WITH_BLANK_CHOICES ) ) + mgmt_only = forms.NullBooleanField( + required=False, + widget=StaticSelect2( + choices=BOOLEAN_WITH_BLANK_CHOICES + ) + ) mac_address = forms.CharField( required=False, label='MAC address' diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index 663206505..2b067a69d 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -406,6 +406,7 @@ class BaseInterfaceTable(BaseTable): class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable): + mgmt_only = BooleanColumn() tags = TagColumn( url_name='dcim:interface_list' ) From c51d2a56ac09eb4b34882a3af0eaec9a9c0a6a31 Mon Sep 17 00:00:00 2001 From: Mikhail Yohman Date: Fri, 8 Jan 2021 19:30:27 -0700 Subject: [PATCH 04/80] Closes 5586: Adds name, master, and master_id filtering --- netbox/dcim/filters.py | 12 +++++++++++- netbox/dcim/tests/test_filters.py | 17 ++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 3046a0f33..05ae08923 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -1016,6 +1016,16 @@ class VirtualChassisFilterSet(BaseFilterSet): method='search', label='Search', ) + master_id = django_filters.ModelMultipleChoiceFilter( + queryset=Device.objects.all(), + label='Master (ID)', + ) + master = django_filters.ModelMultipleChoiceFilter( + field_name='master__name', + queryset=Device.objects.all(), + to_field_name='name', + label='Master (name)', + ) region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='master__site__region', @@ -1055,7 +1065,7 @@ class VirtualChassisFilterSet(BaseFilterSet): class Meta: model = VirtualChassis - fields = ['id', 'domain'] + fields = ['id', 'domain', 'name'] def search(self, queryset, name, value): if not value.strip(): diff --git a/netbox/dcim/tests/test_filters.py b/netbox/dcim/tests/test_filters.py index c701c47cf..a76788e65 100644 --- a/netbox/dcim/tests/test_filters.py +++ b/netbox/dcim/tests/test_filters.py @@ -2399,9 +2399,9 @@ class VirtualChassisTestCase(TestCase): Device.objects.bulk_create(devices) virtual_chassis = ( - VirtualChassis(master=devices[0], domain='Domain 1'), - VirtualChassis(master=devices[2], domain='Domain 2'), - VirtualChassis(master=devices[4], domain='Domain 3'), + VirtualChassis(name='VC 1', master=devices[0], domain='Domain 1'), + VirtualChassis(name='VC 2', master=devices[2], domain='Domain 2'), + VirtualChassis(name='VC 3', master=devices[4], domain='Domain 3'), ) VirtualChassis.objects.bulk_create(virtual_chassis) @@ -2417,6 +2417,17 @@ class VirtualChassisTestCase(TestCase): params = {'domain': ['Domain 1', 'Domain 2']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_master(self): + masters = Device.objects.all() + params = {'master_id': [masters[0].pk, masters[2].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'master': [masters[0].name, masters[2].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['VC 1', 'VC 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_region(self): regions = Region.objects.all()[:2] params = {'region_id': [regions[0].pk, regions[1].pk]} From 1e1e2d5f54a3c5ff60e15deb7a71a81fb4ddc8fb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 11 Jan 2021 11:28:03 -0500 Subject: [PATCH 05/80] Fixes #5597: Fix ordering devices by primary IP address --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/tables/devices.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 f9dee5dec..870a11890 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -9,6 +9,7 @@ ### Bug Fixes * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view +* [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address --- diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index 2b067a69d..edd9e7a43 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -129,6 +129,7 @@ class DeviceTable(BaseTable): ) primary_ip = tables.Column( linkify=True, + order_by=('primary_ip6', 'primary_ip4'), verbose_name='IP Address' ) primary_ip4 = tables.Column( From e13d96a6f24ad45fdfd354a47f22947b005b7acc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sun, 17 Jan 2021 14:08:59 -0500 Subject: [PATCH 06/80] Don't pin Ubuntu installations to Python 3.6 --- docs/installation/3-netbox.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation/3-netbox.md b/docs/installation/3-netbox.md index 9745df1f3..f2461b40d 100644 --- a/docs/installation/3-netbox.md +++ b/docs/installation/3-netbox.md @@ -7,12 +7,12 @@ This section of the documentation discusses installing and configuring the NetBo Begin by installing all system packages required by NetBox and its dependencies. !!! note - NetBox v2.8.0 and later require Python 3.6, 3.7, or 3.8. This documentation assumes Python 3.6. + NetBox v2.8.0 and later require Python 3.6, 3.7, or 3.8. ### Ubuntu ```no-highlight -sudo apt install -y python3.6 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev +sudo apt install -y python3 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev ``` ### CentOS From d838a76461771f71144c8b9ae75eef55aa71e8ca Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Mon, 18 Jan 2021 14:06:28 +0100 Subject: [PATCH 07/80] Add choices for GG45 and TERA connectors and Cat7a/Cat8 cables Fixes #5612 --- netbox/dcim/choices.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index d8f8e3e27..d4cc0ecf4 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -873,6 +873,10 @@ class PortTypeChoices(ChoiceSet): TYPE_8P6C = '8p6c' TYPE_8P4C = '8p4c' TYPE_8P2C = '8p2c' + TYPE_GG45 = 'gg45' + TYPE_TERA4P = 'tera-4p' + TYPE_TERA2P = 'tera-2p' + TYPE_TERA1P = 'tera-1p' TYPE_110_PUNCH = '110-punch' TYPE_BNC = 'bnc' TYPE_MRJ21 = 'mrj21' @@ -898,6 +902,10 @@ class PortTypeChoices(ChoiceSet): (TYPE_8P6C, '8P6C'), (TYPE_8P4C, '8P4C'), (TYPE_8P2C, '8P2C'), + (TYPE_GG45, 'GG45'), + (TYPE_TERA4P, 'TERA 4P'), + (TYPE_TERA2P, 'TERA 2P'), + (TYPE_TERA1P, 'TERA 1P'), (TYPE_110_PUNCH, '110 Punch'), (TYPE_BNC, 'BNC'), (TYPE_MRJ21, 'MRJ21'), @@ -936,6 +944,8 @@ class CableTypeChoices(ChoiceSet): TYPE_CAT6 = 'cat6' TYPE_CAT6A = 'cat6a' TYPE_CAT7 = 'cat7' + TYPE_CAT7A = 'cat7a' + TYPE_CAT8 = 'cat8' TYPE_DAC_ACTIVE = 'dac-active' TYPE_DAC_PASSIVE = 'dac-passive' TYPE_MRJ21_TRUNK = 'mrj21-trunk' @@ -960,6 +970,8 @@ class CableTypeChoices(ChoiceSet): (TYPE_CAT6, 'CAT6'), (TYPE_CAT6A, 'CAT6a'), (TYPE_CAT7, 'CAT7'), + (TYPE_CAT7A, 'CAT7a'), + (TYPE_CAT8, 'CAT8'), (TYPE_DAC_ACTIVE, 'Direct Attach Copper (Active)'), (TYPE_DAC_PASSIVE, 'Direct Attach Copper (Passive)'), (TYPE_MRJ21_TRUNK, 'MRJ21 Trunk'), From 69bf451b209087b7a4025571c816551eee47538a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 19 Jan 2021 09:41:49 -0500 Subject: [PATCH 08/80] Changelog for #5586 and #5612 --- docs/release-notes/version-2.10.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 870a11890..63eec8083 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -5,6 +5,8 @@ ### Enhancements * [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list +* [#5586](https://github.com/netbox-community/netbox/issues/5586) - Allow filtering virtual chassis by name and master +* [#5612](https://github.com/netbox-community/netbox/issues/5612) - Add GG45 and TERA port types, and CAT7a and CAT8 cable types ### Bug Fixes From a0e82e181701159012882c6ba1378a6b2f3453e1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 19 Jan 2021 10:49:56 -0500 Subject: [PATCH 09/80] Fixes #5574: Restrict the creation of device bay templates on non-parent device types --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/models/device_component_templates.py | 6 ++++++ netbox/dcim/tests/test_api.py | 5 ++++- netbox/dcim/tests/test_views.py | 5 +++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 63eec8083..a653173f9 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -10,6 +10,7 @@ ### Bug Fixes +* [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index 58233f3bf..e52fe2602 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -363,3 +363,9 @@ class DeviceBayTemplate(ComponentTemplateModel): name=self.name, label=self.label ) + + def clean(self): + if self.device_type and self.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT: + raise ValidationError( + f"Subdevice role of device type ({self.device_type}) must be set to \"parent\" to allow device bays." + ) diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index 77c3b4786..ad1ca930c 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -740,7 +740,10 @@ class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase): def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' + manufacturer=manufacturer, + model='Device Type 1', + slug='device-type-1', + subdevice_role=SubdeviceRoleChoices.ROLE_PARENT ) device_bay_templates = ( diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 91ec8776c..86518af84 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -396,6 +396,7 @@ manufacturer: Generic model: TEST-1000 slug: test-1000 u_height: 2 +subdevice_role: parent comments: test comment console-ports: - name: Console Port 1 @@ -831,8 +832,8 @@ class DeviceBayTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') devicetypes = ( - DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), - DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), + DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1', subdevice_role=SubdeviceRoleChoices.ROLE_PARENT), + DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2', subdevice_role=SubdeviceRoleChoices.ROLE_PARENT), ) DeviceType.objects.bulk_create(devicetypes) From 3c9be8cd0806c29445310e01957ab09afbe24818 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 19 Jan 2021 11:24:34 -0500 Subject: [PATCH 10/80] Fixes #5639: Fix filtering connection lists by device name --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/filters.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index a653173f9..f3cf87764 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -13,6 +13,7 @@ * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address +* [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name --- diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 05ae08923..03deca2a4 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -1152,7 +1152,7 @@ class ConnectionFilterSet: def filter_device(self, queryset, name, value): if not value: return queryset - return queryset.filter(device_id__in=value) + return queryset.filter(**{f'{name}__in': value}) class ConsoleConnectionFilterSet(ConnectionFilterSet, BaseFilterSet): From f469920759f8711c8443de9ee0892e042a895fd3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 15:18:13 -0500 Subject: [PATCH 11/80] Fixes #5640: Fix permissions assessment when adding VM interfaces in bulk --- docs/release-notes/version-2.10.md | 1 + netbox/templates/virtualization/virtualmachine_list.html | 2 +- netbox/virtualization/views.py | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index f3cf87764..0ef5f2a0f 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -14,6 +14,7 @@ * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name +* [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk --- diff --git a/netbox/templates/virtualization/virtualmachine_list.html b/netbox/templates/virtualization/virtualmachine_list.html index 9d8c1720f..245e55092 100644 --- a/netbox/templates/virtualization/virtualmachine_list.html +++ b/netbox/templates/virtualization/virtualmachine_list.html @@ -7,7 +7,7 @@ Add Components
{% endif %} diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index 9ef4a0863..dcf9ebcda 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -396,3 +396,6 @@ class VirtualMachineBulkAddInterfaceView(generic.BulkComponentCreateView): model_form = forms.VMInterfaceForm filterset = filters.VirtualMachineFilterSet table = tables.VirtualMachineTable + + def get_required_permission(self): + return f'virtualization.add_vminterface' From 0994719b9124cfc10626598eebb7cee459903d2a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 15:36:04 -0500 Subject: [PATCH 12/80] Add NetBox installation video to docs --- docs/installation/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/installation/index.md b/docs/installation/index.md index 730176e0c..71e669295 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -11,6 +11,10 @@ The following sections detail how to set up a new instance of NetBox: 5. [HTTP server](5-http-server.md) 6. [LDAP authentication](6-ldap.md) (optional) +The video below demonstrates the installation of NetBox v2.10.3 on Ubuntu 20.04 for your reference. + + + ## Requirements | Dependency | Minimum Version | From e739d6aa057750d17af01d4f9b772027d47183c5 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Wed, 20 Jan 2021 23:52:54 +0000 Subject: [PATCH 13/80] Fix white cables --- netbox/templates/dcim/trace/cable.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/templates/dcim/trace/cable.html b/netbox/templates/dcim/trace/cable.html index 4235768a6..7a7fbcf55 100644 --- a/netbox/templates/dcim/trace/cable.html +++ b/netbox/templates/dcim/trace/cable.html @@ -1,6 +1,6 @@ {% load helpers %} -
+
{% if cable.label %}{{ cable.label }}{% else %}Cable #{{ cable.pk }}{% endif %} From fefc6233436a3df4d2b106aac4f7d059aae6f951 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 20:48:24 -0500 Subject: [PATCH 14/80] Changelog for #5603 --- 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 0ef5f2a0f..16d48dba7 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -13,6 +13,7 @@ * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address +* [#5603](https://github.com/netbox-community/netbox/issues/5603) - Fix display of white cables in trace view * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name * [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk From 5e962719ca84a250f24d61a5d999e9e6c8e91ad0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 21:29:23 -0500 Subject: [PATCH 15/80] Closes #5542: Show cable trace lengths in both meters and feet --- docs/release-notes/version-2.10.md | 1 + netbox/templates/dcim/cable_trace.html | 3 ++- netbox/utilities/templatetags/helpers.py | 8 ++++++++ 3 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 16d48dba7..27d9fef49 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -4,6 +4,7 @@ ### Enhancements +* [#5542](https://github.com/netbox-community/netbox/issues/5542) - Show cable trace lengths in both meters and feet * [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list * [#5586](https://github.com/netbox-community/netbox/issues/5586) - Allow filtering virtual chassis by name and master * [#5612](https://github.com/netbox-community/netbox/issues/5612) - Add GG45 and TERA port types, and CAT7a and CAT8 cable types diff --git a/netbox/templates/dcim/cable_trace.html b/netbox/templates/dcim/cable_trace.html index a36922612..a39ada1ce 100644 --- a/netbox/templates/dcim/cable_trace.html +++ b/netbox/templates/dcim/cable_trace.html @@ -69,7 +69,8 @@
Total segments: {{ traced_path|length }}
Total length: {% if total_length %} - {{ total_length|floatformat:"-2" }} Meters + {{ total_length|floatformat:"-2" }} Meters / + {{ total_length|meters_to_feet|floatformat:"-2" }} Feet {% else %} N/A {% endif %} diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index 29c920d4f..01dce8479 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -220,6 +220,14 @@ def as_range(n): return range(n) +@register.filter() +def meters_to_feet(n): + """ + Convert a length from meters to feet. + """ + return float(n) * 3.28084 + + # # Tags # From 3de04094fb4f5f53ed5319d831e099e135a2446b Mon Sep 17 00:00:00 2001 From: Riley Littlefield Date: Sat, 23 Jan 2021 13:41:48 -0500 Subject: [PATCH 16/80] Fixes typo --- docs/configuration/required-settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/required-settings.md b/docs/configuration/required-settings.md index 2edf6c7c7..f03745930 100644 --- a/docs/configuration/required-settings.md +++ b/docs/configuration/required-settings.md @@ -5,7 +5,7 @@ This is a list of valid fully-qualified domain names (FQDNs) and/or IP addresses that can be used to reach the NetBox service. Usually this is the same as the hostname for the NetBox server, but can also be different; for example, when using a reverse proxy serving the NetBox website under a different FQDN than the hostname of the NetBox server. To help guard against [HTTP Host header attackes](https://docs.djangoproject.com/en/3.0/topics/security/#host-headers-virtual-hosting), NetBox will not permit access to the server via any other hostnames (or IPs). !!! note - This parameter must always be defined as a list or tuple, even if only value is provided. + This parameter must always be defined as a list or tuple, even if only a single value is provided. The value of this option is also used to set `CSRF_TRUSTED_ORIGINS`, which restricts POST requests to the same set of hosts (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-CSRF_TRUSTED_ORIGINS)). Keep in mind that NetBox, by default, sets `USE_X_FORWARDED_HOST` to true, which means that if you're using a reverse proxy, it's the FQDN used to reach that reverse proxy which needs to be in this list (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#allowed-hosts)). From 9eb64dc6a47ba6400b92e02125bd0251b7bf74e1 Mon Sep 17 00:00:00 2001 From: Riley Littlefield Date: Sat, 23 Jan 2021 13:54:44 -0500 Subject: [PATCH 17/80] Fixes another typo --- docs/configuration/required-settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/required-settings.md b/docs/configuration/required-settings.md index f03745930..dba8cdc8c 100644 --- a/docs/configuration/required-settings.md +++ b/docs/configuration/required-settings.md @@ -101,7 +101,7 @@ REDIS = { If you are using [Redis Sentinel](https://redis.io/topics/sentinel) for high-availability purposes, there is minimal configuration necessary to convert NetBox to recognize it. It requires the removal of the `HOST` and `PORT` keys from -above and the addition of two new keys. +above and the addition of three new keys. * `SENTINELS`: List of tuples or tuple of tuples with each inner tuple containing the name or IP address of the Redis server and port for each sentinel instance to connect to From 60baa5e59e1d5f3f71f1cb8c051c700dc27ba5c6 Mon Sep 17 00:00:00 2001 From: Riley Littlefield Date: Sat, 23 Jan 2021 14:06:48 -0500 Subject: [PATCH 18/80] Fixes small typo in optional settings --- docs/configuration/optional-settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index 91c0e7597..4af83493e 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -56,7 +56,7 @@ BASE_PATH = 'netbox/' Default: 900 -The number of seconds to cache entries will be retained before expiring. +The number of seconds that cache entries will be retained before expiring. --- From b6e532f01d852738f40eb8bedc89f5c056b2f62c Mon Sep 17 00:00:00 2001 From: Thomas Fargeix Date: Sun, 24 Jan 2021 21:20:55 +0100 Subject: [PATCH 19/80] Fix how SECRET_KEY is generated Use secrets.choice instead of random.sample to generate the secret key. --- netbox/generate_secret_key.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/netbox/generate_secret_key.py b/netbox/generate_secret_key.py index 3c88aa710..c3de29cee 100755 --- a/netbox/generate_secret_key.py +++ b/netbox/generate_secret_key.py @@ -1,7 +1,6 @@ #!/usr/bin/env python # This script will generate a random 50-character string suitable for use as a SECRET_KEY. -import random +import secrets charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(-_=+)' -secure_random = random.SystemRandom() -print(''.join(secure_random.sample(charset, 50))) +print(''.join(secrets.choice(charset) for _ in range(50))) From 87c600aa7cc3da60019a34b2c75162baefa4e40f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 25 Jan 2021 14:19:32 -0500 Subject: [PATCH 20/80] Fixes #5665: Validate rack group is assigned to same site when creating a rack --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/models/racks.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 27d9fef49..98595ff4a 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -17,6 +17,7 @@ * [#5603](https://github.com/netbox-community/netbox/issues/5603) - Fix display of white cables in trace view * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name * [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk +* [#5665](https://github.com/netbox-community/netbox/issues/5665) - Validate rack group is assigned to same site when creating a rack --- diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index ccc775954..dfaf7da61 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -299,6 +299,10 @@ class Rack(ChangeLoggedModel, CustomFieldModel): def clean(self): super().clean() + # Validate group/site assignment + if self.site and self.group and self.group.site != self.site: + raise ValidationError(f"Assigned rack group must belong to parent site ({self.site}).") + # Validate outer dimensions and unit if (self.outer_width is not None or self.outer_depth is not None) and not self.outer_unit: raise ValidationError("Must specify a unit when setting an outer width/depth") From 137aa9da2c2e71b352c287341bfcdd80d56d706c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 25 Jan 2021 14:29:03 -0500 Subject: [PATCH 21/80] Fixes #5648: Include VC member interfaces on interfaces tab count when viewing VC master --- docs/release-notes/version-2.10.md | 1 + netbox/templates/dcim/device/base.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 98595ff4a..05b48a896 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -17,6 +17,7 @@ * [#5603](https://github.com/netbox-community/netbox/issues/5603) - Fix display of white cables in trace view * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name * [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk +* [#5648](https://github.com/netbox-community/netbox/issues/5648) - Include VC member interfaces on interfaces tab count when viewing VC master * [#5665](https://github.com/netbox-community/netbox/issues/5665) - Validate rack group is assigned to same site when creating a rack --- diff --git a/netbox/templates/dcim/device/base.html b/netbox/templates/dcim/device/base.html index 631abde89..8f488b284 100644 --- a/netbox/templates/dcim/device/base.html +++ b/netbox/templates/dcim/device/base.html @@ -90,7 +90,7 @@ - {% with interface_count=object.interfaces.count %} + {% with interface_count=object.vc_interfaces.count %} {% if interface_count %}
- {% with rack=object.rack %} -
-
-
-

Front

-
- {% include 'dcim/inc/rack_elevation.html' with face='front' %} -
-
-
-

Rear

-
- {% include 'dcim/inc/rack_elevation.html' with face='rear' %} +
+
+
+

Front

+ {% include 'dcim/inc/rack_elevation.html' with object=object.rack face='front' %}
- {% endwith %} +
+
+

Rear

+
+ {% include 'dcim/inc/rack_elevation.html' with object=object.rack face='rear' %} +
+
{% plugin_right_page object %}
From 90e8f26cd4e34d9ea3364fa15a961f47298d0e05 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 10:17:58 -0500 Subject: [PATCH 23/80] Closes #5678: Show available type choices for all device component import forms --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/forms.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 1d954d383..02897b614 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -8,6 +8,7 @@ * [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list * [#5586](https://github.com/netbox-community/netbox/issues/5586) - Allow filtering virtual chassis by name and master * [#5612](https://github.com/netbox-community/netbox/issues/5612) - Add GG45 and TERA port types, and CAT7a and CAT8 cable types +* [#5678](https://github.com/netbox-community/netbox/issues/5678) - Show available type choices for all device component import forms ### Bug Fixes diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 18fdbdb40..fd533b6ac 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2352,6 +2352,10 @@ class ConsolePortCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=ConsolePortTypeChoices, + help_text='Port type' + ) class Meta: model = ConsolePort @@ -2425,6 +2429,10 @@ class ConsoleServerPortCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=ConsolePortTypeChoices, + help_text='Port type' + ) class Meta: model = ConsoleServerPort @@ -2510,6 +2518,10 @@ class PowerPortCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=PowerPortTypeChoices, + help_text='Port type' + ) class Meta: model = PowerPort @@ -2630,6 +2642,10 @@ class PowerOutletCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=PowerOutletTypeChoices, + help_text='Outlet type' + ) power_port = CSVModelChoiceField( queryset=PowerPort.objects.all(), required=False, From d5a0e12283d4dadf8b36f4826faeeafe4cccb2a5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 10:35:03 -0500 Subject: [PATCH 24/80] Certain component types are optional --- netbox/dcim/forms.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index fd533b6ac..40c16d59f 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2354,6 +2354,7 @@ class ConsolePortCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=ConsolePortTypeChoices, + required=False, help_text='Port type' ) @@ -2431,6 +2432,7 @@ class ConsoleServerPortCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=ConsolePortTypeChoices, + required=False, help_text='Port type' ) @@ -2520,6 +2522,7 @@ class PowerPortCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=PowerPortTypeChoices, + required=False, help_text='Port type' ) @@ -2644,6 +2647,7 @@ class PowerOutletCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=PowerOutletTypeChoices, + required=False, help_text='Outlet type' ) power_port = CSVModelChoiceField( From edc015d9bf1312f0925d17ccdd7590c44045859e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 11:20:06 -0500 Subject: [PATCH 25/80] Emphasize use of GitHub discussions in README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 68927463d..a12daa783 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,7 @@ complete list of requirements, see `requirements.txt`. The code is available [on The complete documentation for NetBox can be found at [Read the Docs](https://netbox.readthedocs.io/en/stable/). -Questions? Comments? Please start a [discussion on GitHub](https://github.com/netbox-community/netbox/discussions), -or join us in the **#netbox** Slack channel on [NetworkToCode](https://networktocode.slack.com/)! +Questions? Comments? Start by perusing our [GitHub discussions](https://github.com/netbox-community/netbox/discussions) for the topic you have in mind. ### Build Status From a23ff4e5191836005ee59f8484641c6043b0ef8f Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 26 Jan 2021 10:34:07 -0600 Subject: [PATCH 26/80] Fixes: #5232 - Corrects swagger definition --- 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 02897b614..9be3f22d1 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -12,6 +12,7 @@ ### Bug Fixes +* [#5232](https://github.com/netbox-community/netbox/issues/5232) - Correct swagger definition for ip_prefixes_available-ips_create API * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address From aabc1a82655ad680e99c76ef1b86280e8cb97170 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 26 Jan 2021 10:34:07 -0600 Subject: [PATCH 27/80] Fixes: #5232 - Corrects swagger definition --- docs/release-notes/version-2.10.md | 1 + netbox/ipam/api/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 02897b614..9be3f22d1 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -12,6 +12,7 @@ ### Bug Fixes +* [#5232](https://github.com/netbox-community/netbox/issues/5232) - Correct swagger definition for ip_prefixes_available-ips_create API * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index d9eae69aa..c322c249d 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -178,7 +178,7 @@ class PrefixViewSet(CustomFieldModelViewSet): @swagger_auto_schema(method='get', responses={200: serializers.AvailableIPSerializer(many=True)}) @swagger_auto_schema(method='post', responses={201: serializers.AvailableIPSerializer(many=True)}, - request_body=serializers.AvailableIPSerializer(many=False)) + request_body=serializers.AvailableIPSerializer(many=True)) @action(detail=True, url_path='available-ips', methods=['get', 'post'], queryset=IPAddress.objects.all()) @advisory_lock(ADVISORY_LOCK_KEYS['available-ips']) def available_ips(self, request, pk=None): From 0680b01a96e3ed2cec2b377e5831603eb4ffc534 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 26 Jan 2021 11:47:33 -0600 Subject: [PATCH 28/80] update python package name At least on ubuntu 20.04, the python3 package is now 3.8, but the package 'python3' points to the current best version of python available without needing to specialize a minor version and should require fewer changes to the document. --- docs/installation/3-netbox.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/3-netbox.md b/docs/installation/3-netbox.md index 9745df1f3..7698be4ad 100644 --- a/docs/installation/3-netbox.md +++ b/docs/installation/3-netbox.md @@ -12,7 +12,7 @@ Begin by installing all system packages required by NetBox and its dependencies. ### Ubuntu ```no-highlight -sudo apt install -y python3.6 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev +sudo apt install -y python3 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev ``` ### CentOS From 03e48161a152ed0c6029b1834a7dc44c55f98fcc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 13:06:29 -0500 Subject: [PATCH 29/80] Release v2.10.4 --- 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 9be3f22d1..b6bc33229 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.4 (FUTURE) +## v2.10.4 (2021-01-26) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index ed1f9c732..3dd780b26 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-dev' +VERSION = '2.10.4' # Hostname HOSTNAME = platform.node() From fc8f02c180dc8dd9ec6d6b3226432382f22e6f69 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 26 Jan 2021 14:03:46 -0600 Subject: [PATCH 30/80] Corrects error with ListSerializer as request_body --- netbox/utilities/custom_inspectors.py | 51 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/netbox/utilities/custom_inspectors.py b/netbox/utilities/custom_inspectors.py index 95c647fb8..b110a9123 100644 --- a/netbox/utilities/custom_inspectors.py +++ b/netbox/utilities/custom_inspectors.py @@ -28,29 +28,38 @@ class NetBoxSwaggerAutoSchema(SwaggerAutoSchema): serializer = super().get_request_serializer() if serializer is not None and self.method in self.implicit_body_methods: - properties = {} - for child_name, child in serializer.fields.items(): - if isinstance(child, (ChoiceField, WritableNestedSerializer)): - properties[child_name] = None - elif isinstance(child, ManyRelatedField) and isinstance(child.child_relation, SerializedPKRelatedField): - properties[child_name] = None - - if properties: - if type(serializer) not in self.writable_serializers: - writable_name = 'Writable' + type(serializer).__name__ - meta_class = getattr(type(serializer), 'Meta', None) - if meta_class: - ref_name = 'Writable' + get_serializer_ref_name(serializer) - writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name}) - properties['Meta'] = writable_meta - - self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties) - - writable_class = self.writable_serializers[type(serializer)] - serializer = writable_class() - + writable_class = self.get_writable_class(serializer) + if writable_class is not None: + if hasattr(serializer, 'child'): + child_serializer = self.get_writable_class(serializer.child) + serializer = writable_class(child=child_serializer) + else: + serializer = writable_class() return serializer + def get_writable_class(self, serializer): + properties = {} + fields = {} if hasattr(serializer, 'child') else serializer.fields + for child_name, child in fields.items(): + if isinstance(child, (ChoiceField, WritableNestedSerializer)): + properties[child_name] = None + elif isinstance(child, ManyRelatedField) and isinstance(child.child_relation, SerializedPKRelatedField): + properties[child_name] = None + + if properties: + if type(serializer) not in self.writable_serializers: + writable_name = 'Writable' + type(serializer).__name__ + meta_class = getattr(type(serializer), 'Meta', None) + if meta_class: + ref_name = 'Writable' + get_serializer_ref_name(serializer) + writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name}) + properties['Meta'] = writable_meta + + self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties) + + writable_class = self.writable_serializers[type(serializer)] + return writable_class + class SerializedPKRelatedFieldInspector(FieldInspector): def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): From 196407307219fd29e3540965f0500bf4331f5876 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 16:02:14 -0500 Subject: [PATCH 31/80] 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 32/80] 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 33/80] 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 34/80] 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 35/80] 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 36/80] 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 37/80] 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 38/80] 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 39/80] 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 40/80] 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 41/80] 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 42/80] 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 43/80] 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 44/80] 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 45/80] 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 46/80] 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 47/80] 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 48/80] 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 49/80] 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 50/80] 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() From b1cd634ab4ee0a399075b21031e9f0b559991807 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 24 Feb 2021 15:38:36 -0500 Subject: [PATCH 51/80] 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 af5f5521b..604b755d8 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' +VERSION = '2.10.6-dev' # Hostname HOSTNAME = platform.node() From d2c8aae59c68307424dd914a9076b39c0d580857 Mon Sep 17 00:00:00 2001 From: Luke Anderson Date: Mon, 15 Feb 2021 21:01:55 +1030 Subject: [PATCH 52/80] Fix #5819 and #5872 - Fix Primary IP Sorting Issues for Devices and VMs --- netbox/dcim/tables/devices.py | 18 +++++++++++++----- netbox/virtualization/tables.py | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index edd9e7a43..52f4449af 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -1,5 +1,6 @@ import django_tables2 as tables from django_tables2.utils import Accessor +from django.conf import settings from dcim.models import ( ConsolePort, ConsoleServerPort, Device, DeviceBay, DeviceRole, FrontPort, Interface, InventoryItem, Platform, @@ -127,11 +128,18 @@ class DeviceTable(BaseTable): verbose_name='Type', text=lambda record: record.device_type.display_name ) - primary_ip = tables.Column( - linkify=True, - order_by=('primary_ip6', 'primary_ip4'), - verbose_name='IP Address' - ) + if settings.PREFER_IPV4: + primary_ip = tables.Column( + linkify=True, + order_by=('primary_ip4', 'primary_ip6'), + verbose_name='IP Address' + ) + else: + primary_ip = tables.Column( + linkify=True, + order_by=('primary_ip6', 'primary_ip4'), + verbose_name='IP Address' + ) primary_ip4 = tables.Column( linkify=True, verbose_name='IPv4 Address' diff --git a/netbox/virtualization/tables.py b/netbox/virtualization/tables.py index 34a070623..e183765f1 100644 --- a/netbox/virtualization/tables.py +++ b/netbox/virtualization/tables.py @@ -1,5 +1,5 @@ import django_tables2 as tables - +from django.conf import settings from dcim.tables.devices import BaseInterfaceTable from tenancy.tables import COL_TENANT from utilities.tables import ( @@ -125,10 +125,18 @@ class VirtualMachineDetailTable(VirtualMachineTable): linkify=True, verbose_name='IPv6 Address' ) - primary_ip = tables.Column( - linkify=True, - verbose_name='IP Address' - ) + if settings.PREFER_IPV4: + primary_ip = tables.Column( + linkify=True, + order_by=('primary_ip4', 'primary_ip6'), + verbose_name='IP Address' + ) + else: + primary_ip = tables.Column( + linkify=True, + order_by=('primary_ip6', 'primary_ip4'), + verbose_name='IP Address' + ) tags = TagColumn( url_name='virtualization:virtualmachine_list' ) From cfddf570b90d692201284ed16e60b5cfdf97cbf8 Mon Sep 17 00:00:00 2001 From: Julian Jacobi Date: Mon, 1 Mar 2021 09:27:21 +0100 Subject: [PATCH 53/80] add custom links to device components --- netbox/dcim/models/device_components.py | 18 +++++++++--------- netbox/templates/dcim/device_component.html | 4 ++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 452aacb56..40063234f 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -198,7 +198,7 @@ class PathEndpoint(models.Model): # Console ports # -@extras_features('export_templates', 'webhooks') +@extras_features('export_templates', 'webhooks', 'custom_links') class ConsolePort(CableTermination, PathEndpoint, ComponentModel): """ A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts. @@ -234,7 +234,7 @@ class ConsolePort(CableTermination, PathEndpoint, ComponentModel): # Console server ports # -@extras_features('webhooks') +@extras_features('webhooks', 'custom_links') class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel): """ A physical port within a Device (typically a designated console server) which provides access to ConsolePorts. @@ -270,7 +270,7 @@ class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel): # Power ports # -@extras_features('export_templates', 'webhooks') +@extras_features('export_templates', 'webhooks', 'custom_links') class PowerPort(CableTermination, PathEndpoint, ComponentModel): """ A physical power supply (intake) port within a Device. PowerPorts connect to PowerOutlets. @@ -379,7 +379,7 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel): # Power outlets # -@extras_features('webhooks') +@extras_features('webhooks', 'custom_links') class PowerOutlet(CableTermination, PathEndpoint, ComponentModel): """ A physical power outlet (output) within a Device which provides power to a PowerPort. @@ -479,7 +479,7 @@ class BaseInterface(models.Model): return super().save(*args, **kwargs) -@extras_features('export_templates', 'webhooks') +@extras_features('export_templates', 'webhooks', 'custom_links') class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface): """ A network interface within a Device. A physical Interface can connect to exactly one other Interface. @@ -624,7 +624,7 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface): # Pass-through ports # -@extras_features('webhooks') +@extras_features('webhooks', 'custom_links') class FrontPort(CableTermination, ComponentModel): """ A pass-through port on the front of a Device. @@ -687,7 +687,7 @@ class FrontPort(CableTermination, ComponentModel): }) -@extras_features('webhooks') +@extras_features('webhooks', 'custom_links') class RearPort(CableTermination, ComponentModel): """ A pass-through port on the rear of a Device. @@ -740,7 +740,7 @@ class RearPort(CableTermination, ComponentModel): # Device bays # -@extras_features('webhooks') +@extras_features('webhooks', 'custom_links') class DeviceBay(ComponentModel): """ An empty space within a Device which can house a child device @@ -800,7 +800,7 @@ class DeviceBay(ComponentModel): # Inventory items # -@extras_features('export_templates', 'webhooks') +@extras_features('export_templates', 'webhooks', 'custom_links') class InventoryItem(MPTTModel, ComponentModel): """ An InventoryItem represents a serialized piece of hardware within a Device, such as a line card or power supply. diff --git a/netbox/templates/dcim/device_component.html b/netbox/templates/dcim/device_component.html index c0ce453b3..234d10fdd 100644 --- a/netbox/templates/dcim/device_component.html +++ b/netbox/templates/dcim/device_component.html @@ -1,6 +1,7 @@ {% extends 'base.html' %} {% load helpers %} {% load perms %} +{% load custom_links %} {% load plugins %} {% block header %} @@ -30,6 +31,9 @@ {% endif %}

{% block title %}{{ object.device }} / {{ object }}{% endblock %}

+
+ {% custom_links object %} +
From 61e5eff6660a3e1734b459a19adc3d83195bb4ce Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 8 Mar 2021 16:27:12 -0500 Subject: [PATCH 73/80] Fixes #5935: Fix filtering prefixes list by multiple prefix values --- docs/release-notes/version-2.10.md | 1 + netbox/ipam/filters.py | 16 ++++++++-------- netbox/ipam/tests/test_filters.py | 5 +++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 2996bdf96..529f52a1a 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -13,6 +13,7 @@ * [#5703](https://github.com/netbox-community/netbox/issues/5703) - Fix VRF and Tenant field population when adding IP addresses from prefix * [#5819](https://github.com/netbox-community/netbox/issues/5819) - Enable ordering of virtual machines by primary IP address * [#5872](https://github.com/netbox-community/netbox/issues/5872) - Ordering of devices by primary IP should respect PREFER_IPV4 configuration parameter +* [#5935](https://github.com/netbox-community/netbox/issues/5935) - Fix filtering prefixes list by multiple prefix values ## v2.10.5 (2021-02-24) diff --git a/netbox/ipam/filters.py b/netbox/ipam/filters.py index 176d77a88..974dfb08e 100644 --- a/netbox/ipam/filters.py +++ b/netbox/ipam/filters.py @@ -192,7 +192,7 @@ class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet field_name='prefix', lookup_expr='family' ) - prefix = django_filters.CharFilter( + prefix = MultiValueCharFilter( method='filter_prefix', label='Prefix', ) @@ -304,13 +304,13 @@ class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet return queryset.filter(qs_filter) def filter_prefix(self, queryset, name, value): - if not value.strip(): - return queryset - try: - query = str(netaddr.IPNetwork(value).cidr) - return queryset.filter(prefix=query) - except (AddrFormatError, ValueError): - return queryset.none() + query_values = [] + for v in value: + try: + query_values.append(netaddr.IPNetwork(v)) + except (AddrFormatError, ValueError): + pass + return queryset.filter(prefix__in=query_values) def search_within(self, queryset, name, value): value = value.strip() diff --git a/netbox/ipam/tests/test_filters.py b/netbox/ipam/tests/test_filters.py index 2fead3d93..3be539df3 100644 --- a/netbox/ipam/tests/test_filters.py +++ b/netbox/ipam/tests/test_filters.py @@ -422,6 +422,11 @@ class PrefixTestCase(TestCase): params = {'family': '6'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5) + def test_prefix(self): + prefixes = Prefix.objects.all()[:2] + params = {'prefix': [prefixes[0].prefix, prefixes[1].prefix]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_is_pool(self): params = {'is_pool': 'true'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) From 5b5110acbf1002e8bbe80c80e4413313387528ea Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 8 Mar 2021 16:46:11 -0500 Subject: [PATCH 74/80] Closes #5923: Include depdency upgrades as part of standard release process --- docs/development/release-checklist.md | 40 +++++++++++++++------------ 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/docs/development/release-checklist.md b/docs/development/release-checklist.md index f3338ffd3..d8cb671f6 100644 --- a/docs/development/release-checklist.md +++ b/docs/development/release-checklist.md @@ -2,24 +2,9 @@ ## Minor Version Bumps -### Update Requirements +### Address Pinned Dependencies -Required Python packages are maintained in two files. `base_requirements.txt` contains a list of all the packages required by NetBox. Some of them may be pinned to a specific version of the package due to a known issue. For example: - -``` -# https://github.com/encode/django-rest-framework/issues/6053 -djangorestframework==3.8.1 -``` - -The other file is `requirements.txt`, which lists each of the required packages pinned to its current stable version. When NetBox is installed, the Python environment is configured to match this file. This helps ensure that a new release of a dependency doesn't break NetBox. - -Every minor version release should refresh `requirements.txt` so that it lists the most recent stable release of each package. To do this: - -1. Create a new virtual environment. -2. Install the latest version of all required packages `pip install -U -r base_requirements.txt`). -3. Run all tests and check that the UI and API function as expected. -4. Review each requirement's release notes for any breaking or otherwise noteworthy changes. -5. Update the package versions in `requirements.txt` as appropriate. +Check `base_requirements.txt` for any dependencies pinned to a specific version, and upgrade them to their most stable release (where possible). ### Update Static Libraries @@ -58,6 +43,27 @@ Submit a pull request to merge the `feature` branch into the `develop` branch in ## All Releases +### Update Requirements + +Required Python packages are maintained in two files. `base_requirements.txt` contains a list of all the packages required by NetBox. Some of them may be pinned to a specific version of the package due to a known issue. For example: + +``` +# https://github.com/encode/django-rest-framework/issues/6053 +djangorestframework==3.8.1 +``` + +The other file is `requirements.txt`, which lists each of the required packages pinned to its current stable version. When NetBox is installed, the Python environment is configured to match this file. This helps ensure that a new release of a dependency doesn't break NetBox. + +Every release should refresh `requirements.txt` so that it lists the most recent stable release of each package. To do this: + +1. Create a new virtual environment. +2. Install the latest version of all required packages `pip install -U -r base_requirements.txt`). +3. Run all tests and check that the UI and API function as expected. +4. Review each requirement's release notes for any breaking or otherwise noteworthy changes. +5. Update the package versions in `requirements.txt` as appropriate. + +In cases where upgrading a dependency to its most recent release is breaking, it should be pinned to its current minor version in `base_requirements.txt` (with an explanatory comment) and revisited for the next major NetBox release. + ### Verify CI Build Status Ensure that continuous integration testing on the `develop` branch is completing successfully. From e7157973e717653b67ee4c6709cf8d8be5ac149b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 8 Mar 2021 16:51:11 -0500 Subject: [PATCH 75/80] Fixes #5922: Fix options for filtering object permissions in admin UI --- docs/release-notes/version-2.10.md | 1 + netbox/users/admin.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 529f52a1a..f00e38476 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -13,6 +13,7 @@ * [#5703](https://github.com/netbox-community/netbox/issues/5703) - Fix VRF and Tenant field population when adding IP addresses from prefix * [#5819](https://github.com/netbox-community/netbox/issues/5819) - Enable ordering of virtual machines by primary IP address * [#5872](https://github.com/netbox-community/netbox/issues/5872) - Ordering of devices by primary IP should respect PREFER_IPV4 configuration parameter +* [#5922](https://github.com/netbox-community/netbox/issues/5922) - Fix options for filtering object permissions in admin UI * [#5935](https://github.com/netbox-community/netbox/issues/5935) - Fix filtering prefixes list by multiple prefix values ## v2.10.5 (2021-02-24) diff --git a/netbox/users/admin.py b/netbox/users/admin.py index f2fe4a0b4..e1625e1ed 100644 --- a/netbox/users/admin.py +++ b/netbox/users/admin.py @@ -223,7 +223,7 @@ class ObjectTypeListFilter(admin.SimpleListFilter): parameter_name = 'object_type' def lookups(self, request, model_admin): - object_types = ObjectPermission.objects.values_list('id', flat=True).distinct() + object_types = ObjectPermission.objects.values_list('object_types__pk', flat=True).distinct() content_types = ContentType.objects.filter(pk__in=object_types).order_by('app_label', 'model') return [ (ct.pk, ct) for ct in content_types From 835e11d10f51938a6cd4f7133e397cceda2e70d2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 8 Mar 2021 16:54:28 -0500 Subject: [PATCH 76/80] Fixes #5920: Revert #5760 (do not force database encoding) --- 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 4ac1104d7..bcc670e2b 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 ENCODING 'UTF8' LC_COLLATE='C.UTF-8' LC_CTYPE='C.UTF-8'; +postgres=# CREATE DATABASE netbox; CREATE DATABASE postgres=# CREATE USER netbox WITH PASSWORD 'J5brHrAXFLQSif0K'; CREATE ROLE From 358d7ac5623b90e359c33873bfcdae8c896eb76d Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 8 Mar 2021 17:16:07 -0500 Subject: [PATCH 77/80] Closes #5942: Add button to add a new IP address on interface view --- docs/release-notes/version-2.10.md | 2 ++ netbox/templates/dcim/interface.html | 19 ++++++++++++++++++- .../templates/virtualization/vminterface.html | 19 ++++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index f00e38476..942da03da 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -7,6 +7,8 @@ * [#5592](https://github.com/netbox-community/netbox/issues/5592) - Add IP addresses count to VRF view * [#5630](https://github.com/netbox-community/netbox/issues/5630) - Add QSFP+ (64GFC) FibreChannel Interface option * [#5884](https://github.com/netbox-community/netbox/issues/5884) - Enable custom links for device components +* [#5914](https://github.com/netbox-community/netbox/issues/5914) - Add edit/delete buttons for IP addresses on interface view +* [#5942](https://github.com/netbox-community/netbox/issues/5942) - Add button to add a new IP address on interface view ### Bug Fixes diff --git a/netbox/templates/dcim/interface.html b/netbox/templates/dcim/interface.html index 3ae0733a1..2c0f6e01f 100644 --- a/netbox/templates/dcim/interface.html +++ b/netbox/templates/dcim/interface.html @@ -1,6 +1,7 @@ {% extends 'dcim/device_component.html' %} {% load helpers %} {% load plugins %} +{% load render_table from django_tables2 %} {% block content %}
@@ -226,7 +227,23 @@
- {% include 'panel_table.html' with table=ipaddress_table heading="IP Addresses" %} +
+
+ IP Addresses +
+ {% if ipaddress_table.rows %} + {% render_table ipaddress_table 'inc/table.html' %} + {% else %} +
None
+ {% endif %} + {% if perms.ipam.add_ipaddress %} + + {% endif %} +
diff --git a/netbox/templates/virtualization/vminterface.html b/netbox/templates/virtualization/vminterface.html index 7263fd9ae..fb1190d72 100644 --- a/netbox/templates/virtualization/vminterface.html +++ b/netbox/templates/virtualization/vminterface.html @@ -1,6 +1,7 @@ {% extends 'base.html' %} {% load helpers %} {% load plugins %} +{% load render_table from django_tables2 %} {% block header %}
@@ -93,7 +94,23 @@
- {% include 'panel_table.html' with table=ipaddress_table heading="IP Addresses" %} +
+
+ IP Addresses +
+ {% if ipaddress_table.rows %} + {% render_table ipaddress_table 'inc/table.html' %} + {% else %} +
None
+ {% endif %} + {% if perms.ipam.add_ipaddress %} + + {% endif %} +
From 1cc82f2ab76ea6dc270d1c2dc8bdc7f5d5e5311b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 9 Mar 2021 15:20:06 -0500 Subject: [PATCH 78/80] Create FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..5b4e4e5a4 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [jeremystretch] From c3ad2d0a807797caac40a932e2476ab7bd410036 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 9 Mar 2021 16:39:55 -0500 Subject: [PATCH 79/80] Fixes #5948: Invalidate cached queries when running renaturalize --- docs/release-notes/version-2.10.md | 1 + .../management/commands/renaturalize.py | 24 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 942da03da..0925c2c8b 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -17,6 +17,7 @@ * [#5872](https://github.com/netbox-community/netbox/issues/5872) - Ordering of devices by primary IP should respect PREFER_IPV4 configuration parameter * [#5922](https://github.com/netbox-community/netbox/issues/5922) - Fix options for filtering object permissions in admin UI * [#5935](https://github.com/netbox-community/netbox/issues/5935) - Fix filtering prefixes list by multiple prefix values +* [#5948](https://github.com/netbox-community/netbox/issues/5948) - Invalidate cached queries when running `renaturalize` ## v2.10.5 (2021-02-24) diff --git a/netbox/extras/management/commands/renaturalize.py b/netbox/extras/management/commands/renaturalize.py index cfd037910..8ad51966a 100644 --- a/netbox/extras/management/commands/renaturalize.py +++ b/netbox/extras/management/commands/renaturalize.py @@ -1,3 +1,4 @@ +from cacheops import invalidate_model from django.apps import apps from django.core.management.base import BaseCommand, CommandError @@ -27,7 +28,7 @@ class Command(BaseCommand): app_label, model_name = name.split('.') except ValueError: raise CommandError( - "Invalid format: {}. Models must be specified in the form app_label.ModelName.".format(name) + f"Invalid format: {name}. Models must be specified in the form app_label.ModelName." ) try: app_config = apps.get_app_config(app_label) @@ -36,13 +37,13 @@ class Command(BaseCommand): try: model = app_config.get_model(model_name) except LookupError: - raise CommandError("Unknown model: {}.{}".format(app_label, model_name)) + raise CommandError(f"Unknown model: {app_label}.{model_name}") fields = [ field for field in model._meta.concrete_fields if type(field) is NaturalOrderingField ] if not fields: raise CommandError( - "Invalid model: {}.{} does not employ natural ordering".format(app_label, model_name) + f"Invalid model: {app_label}.{model_name} does not employ natural ordering" ) models.append( (model, fields) @@ -67,7 +68,7 @@ class Command(BaseCommand): models = self._get_models(args) if options['verbosity']: - self.stdout.write("Renaturalizing {} models.".format(len(models))) + self.stdout.write(f"Renaturalizing {len(models)} models.") for model, fields in models: for field in fields: @@ -78,7 +79,7 @@ class Command(BaseCommand): # Print the model and field name if options['verbosity']: self.stdout.write( - "{}.{} ({})... ".format(model._meta.label, field.target_field, field.name), + f"{model._meta.label}.{field.target_field} ({field.name})... ", ending='\n' if options['verbosity'] >= 2 else '' ) self.stdout.flush() @@ -89,23 +90,26 @@ class Command(BaseCommand): naturalized_value = naturalize(value, max_length=field.max_length) if options['verbosity'] >= 2: - self.stdout.write(" {} -> {}".format(value, naturalized_value), ending='') + self.stdout.write(f" {value} -> {naturalized_value}", ending='') self.stdout.flush() # Update each unique field value in bulk changed = model.objects.filter(name=value).update(**{field.name: naturalized_value}) if options['verbosity'] >= 2: - self.stdout.write(" ({})".format(changed)) + self.stdout.write(f" ({changed})") count += changed # Print the total count of alterations for the field if options['verbosity'] >= 2: - self.stdout.write(self.style.SUCCESS("{} {} updated ({} unique values)".format( - count, model._meta.verbose_name_plural, queryset.count() - ))) + self.stdout.write(self.style.SUCCESS( + f"{count} {model._meta.verbose_name_plural} updated ({queryset.count()} unique values)" + )) elif options['verbosity']: self.stdout.write(self.style.SUCCESS(str(count))) + # Invalidate cached queries + invalidate_model(model) + if options['verbosity']: self.stdout.write(self.style.SUCCESS("Done.")) From 5b07c77708b2089885d8246f4fa14bf22a3354e1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 9 Mar 2021 16:57:03 -0500 Subject: [PATCH 80/80] Release v2.10.6 --- docs/release-notes/version-2.10.md | 4 ++-- netbox/netbox/settings.py | 2 +- requirements.txt | 24 ++++++++++++------------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 0925c2c8b..2b3792204 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.6 (FUTURE) +## v2.10.6 (2021-03-09) ### Enhancements @@ -14,7 +14,7 @@ * [#5703](https://github.com/netbox-community/netbox/issues/5703) - Fix VRF and Tenant field population when adding IP addresses from prefix * [#5819](https://github.com/netbox-community/netbox/issues/5819) - Enable ordering of virtual machines by primary IP address -* [#5872](https://github.com/netbox-community/netbox/issues/5872) - Ordering of devices by primary IP should respect PREFER_IPV4 configuration parameter +* [#5872](https://github.com/netbox-community/netbox/issues/5872) - Ordering of devices by primary IP should respect `PREFER_IPV4` configuration parameter * [#5922](https://github.com/netbox-community/netbox/issues/5922) - Fix options for filtering object permissions in admin UI * [#5935](https://github.com/netbox-community/netbox/issues/5935) - Fix filtering prefixes list by multiple prefix values * [#5948](https://github.com/netbox-community/netbox/issues/5948) - Invalidate cached queries when running `renaturalize` diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 604b755d8..4f4c09603 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.6-dev' +VERSION = '2.10.6' # Hostname HOSTNAME = platform.node() diff --git a/requirements.txt b/requirements.txt index 18ce530fd..ae16926b7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,23 +1,23 @@ -Django==3.1.3 +Django==3.1.7 django-cacheops==5.1 -django-cors-headers==3.5.0 -django-debug-toolbar==3.1.1 +django-cors-headers==3.7.0 +django-debug-toolbar==3.2 django-filter==2.4.0 -django-mptt==0.11.0 +django-mptt==0.12.0 django-pglocks==1.0.4 django-prometheus==2.1.0 django-rq==2.4.0 -django-tables2==2.3.3 +django-tables2==2.3.4 django-taggit==1.3.0 -django-timezone-field==4.0 +django-timezone-field==4.1.1 djangorestframework==3.12.2 drf-yasg[validation]==1.20.0 gunicorn==20.0.4 -Jinja2==2.11.2 -Markdown==3.3.3 +Jinja2==2.11.3 +Markdown==3.3.4 netaddr==0.8.0 -Pillow==8.0.1 +Pillow==8.1.2 psycopg2-binary==2.8.6 -pycryptodome==3.9.9 -PyYAML==5.3.1 -svgwrite==1.4 +pycryptodome==3.10.1 +PyYAML==5.4.1 +svgwrite==1.4.1