From 3522eafd2ca7924e4883feeb63006972502f0fc5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sat, 22 Aug 2020 21:06:06 -0400 Subject: [PATCH 01/65] Post-release version bump --- 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 74cfcbd83..6a836ff74 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.9.1' +VERSION = '2.9.2-dev' # Hostname HOSTNAME = platform.node() From fcc15d2e33535db8d8a28b3698aa106baf3413e2 Mon Sep 17 00:00:00 2001 From: Joakim Bakke Hellum Date: Sun, 23 Aug 2020 20:49:50 +0200 Subject: [PATCH 02/65] Use correct serializer for available-prefixes POST response POST `/ipam/prefixes/{id}/available-prefixes/` returns single `Prefix` object, not list of `AvailablePrefix` objects. --- netbox/ipam/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 0d273e4d8..280bb4322 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -88,7 +88,7 @@ class PrefixViewSet(CustomFieldModelViewSet): return super().get_serializer_class() @swagger_auto_schema(method='get', responses={200: serializers.AvailablePrefixSerializer(many=True)}) - @swagger_auto_schema(method='post', responses={201: serializers.AvailablePrefixSerializer(many=True)}) + @swagger_auto_schema(method='post', responses={201: serializers.PrefixSerializer(many=False)}) @action(detail=True, url_path='available-prefixes', methods=['get', 'post']) @advisory_lock(ADVISORY_LOCK_KEYS['available-prefixes']) def available_prefixes(self, request, pk=None): From 6e28490b848b4903f050d306b1a914701e43d6d4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 09:41:04 -0400 Subject: [PATCH 03/65] Fixes #5038: Fix validation of primary IPs assigned to virtual machines --- docs/release-notes/version-2.9.md | 8 ++++++++ netbox/dcim/forms.py | 2 +- netbox/virtualization/forms.py | 27 ++++++++++++++------------- netbox/virtualization/models.py | 6 +++--- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 549067b13..d521cb13c 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -1,5 +1,13 @@ # NetBox v2.9 +## v2.9.2 (FUTURE) + +### Bug Fixes + +* [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines + +--- + ## v2.9.1 (2020-08-22) ### Enhancements diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 2b8bf4e9e..2e4aaed2e 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -1811,7 +1811,7 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): nat_inside__assigned_object_id__in=interface_ids ).prefetch_related('assigned_object') if nat_ips: - ip_list = [(ip.id, f'{ip.address} ({ip.assigned_object})') for ip in nat_ips] + ip_list = [(ip.id, f'{ip.address} (NAT)') for ip in nat_ips] ip_choices.append(('NAT IPs', ip_list)) self.fields['primary_ip{}'.format(family)].choices = ip_choices diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index a64a0a7d8..8ba288d1c 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from dcim.choices import InterfaceModeChoices @@ -325,28 +326,28 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): # Compile list of choices for primary IPv4 and IPv6 addresses for family in [4, 6]: ip_choices = [(None, '---------')] + + # Gather PKs of all interfaces belonging to this VM + interface_ids = self.instance.interfaces.values_list('pk', flat=True) + # Collect interface IPs - interface_ips = IPAddress.objects.prefetch_related('interface').filter( + interface_ips = IPAddress.objects.filter( address__family=family, - vminterface__in=self.instance.interfaces.values_list('id', flat=True) + assigned_object_type=ContentType.objects.get_for_model(VMInterface), + assigned_object_id__in=interface_ids ) if interface_ips: - ip_choices.append( - ('Interface IPs', [ - (ip.id, '{} ({})'.format(ip.address, ip.interface)) for ip in interface_ips - ]) - ) + ip_list = [(ip.id, f'{ip.address} ({ip.assigned_object})') for ip in interface_ips] + ip_choices.append(('Interface IPs', ip_list)) # Collect NAT IPs nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter( address__family=family, - nat_inside__vminterface__in=self.instance.interfaces.values_list('id', flat=True) + nat_inside__assigned_object_type=ContentType.objects.get_for_model(VMInterface), + nat_inside__assigned_object_id__in=interface_ids ) if nat_ips: - ip_choices.append( - ('NAT IPs', [ - (ip.id, '{} ({})'.format(ip.address, ip.nat_inside.address)) for ip in nat_ips - ]) - ) + ip_list = [(ip.id, f'{ip.address} (NAT)') for ip in nat_ips] + ip_choices.append(('NAT IPs', ip_list)) self.fields['primary_ip{}'.format(family)].choices = ip_choices else: diff --git a/netbox/virtualization/models.py b/netbox/virtualization/models.py index f787aef0e..7d0b99872 100644 --- a/netbox/virtualization/models.py +++ b/netbox/virtualization/models.py @@ -335,13 +335,13 @@ class VirtualMachine(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): for field in ['primary_ip4', 'primary_ip6']: ip = getattr(self, field) if ip is not None: - if ip.interface in interfaces: + if ip.assigned_object in interfaces: pass - elif self.primary_ip4.nat_inside is not None and self.primary_ip4.nat_inside.interface in interfaces: + elif ip.nat_inside is not None and ip.nat_inside.assigned_object in interfaces: pass else: raise ValidationError({ - field: "The specified IP address ({}) is not assigned to this VM.".format(ip), + field: f"The specified IP address ({ip}) is not assigned to this VM.", }) def to_csv(self): From e7cf87be97a6ce9e34e58fbe75a5609a0002b00f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:39:41 -0400 Subject: [PATCH 04/65] Fixes #5035: Fix exception when modifying an IP address assigned to a VM --- docs/release-notes/version-2.9.md | 1 + netbox/ipam/models.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index d521cb13c..7f085505a 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -4,6 +4,7 @@ ### Bug Fixes +* [#5035](https://github.com/netbox-community/netbox/issues/5035) - Fix exception when modifying an IP address assigned to a VM * [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines --- diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 58dd96089..cf9ecbf89 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -745,7 +745,7 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): 'vminterface': f"IP address is primary for virtual machine {vm} but not assigned to an " f"interface" }) - elif self.interface.virtual_machine != vm: + elif self.assigned_object.virtual_machine != vm: raise ValidationError({ 'vminterface': f"IP address is primary for virtual machine {vm} but assigned to " f"{self.assigned_object.virtual_machine} ({self.assigned_object})" From 9147823305f00c4932a1e9ca13f24c46c7f576bc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:47:26 -0400 Subject: [PATCH 05/65] Fixes #5042: Fix display of SLAAC label for IP addresses status --- docs/release-notes/version-2.9.md | 1 + netbox/ipam/models.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 7f085505a..2683e85cf 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -6,6 +6,7 @@ * [#5035](https://github.com/netbox-community/netbox/issues/5035) - Fix exception when modifying an IP address assigned to a VM * [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines +* [#5042](https://github.com/netbox-community/netbox/issues/5042) - Fix display of SLAAC label for IP addresses status --- diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index cf9ecbf89..2aeee30fc 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -669,6 +669,7 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): 'reserved': 'info', 'deprecated': 'danger', 'dhcp': 'success', + 'slaac': 'success', } ROLE_CLASS_MAP = { From 78d6561e3928e2d221044cf3fb1096e16437f398 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:51:47 -0400 Subject: [PATCH 06/65] Fixes #5040: Limit SLAAC status to IPv6 addresses --- docs/release-notes/version-2.9.md | 1 + netbox/ipam/models.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 2683e85cf..54bd5a84d 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -6,6 +6,7 @@ * [#5035](https://github.com/netbox-community/netbox/issues/5035) - Fix exception when modifying an IP address assigned to a VM * [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines +* [#5040](https://github.com/netbox-community/netbox/issues/5040) - Limit SLAAC status to IPv6 addresses * [#5042](https://github.com/netbox-community/netbox/issues/5042) - Fix display of SLAAC label for IP addresses status --- diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 2aeee30fc..832e09330 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -752,6 +752,12 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): f"{self.assigned_object.virtual_machine} ({self.assigned_object})" }) + # Validate IP status selection + if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6: + raise ValidationError({ + 'status': "Only IPv6 addresses can be assigned SLAAC status" + }) + def save(self, *args, **kwargs): # Force dns_name to lowercase From 32a0e519add5c8a3542fdd6346d222623ad81a66 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:56:23 -0400 Subject: [PATCH 07/65] Fixes #5041: Fix form tabs when assigning an IP to a VM interface --- docs/release-notes/version-2.9.md | 1 + netbox/templates/ipam/inc/ipadress_edit_header.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 54bd5a84d..6ed07d536 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -7,6 +7,7 @@ * [#5035](https://github.com/netbox-community/netbox/issues/5035) - Fix exception when modifying an IP address assigned to a VM * [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines * [#5040](https://github.com/netbox-community/netbox/issues/5040) - Limit SLAAC status to IPv6 addresses +* [#5041](https://github.com/netbox-community/netbox/issues/5041) - Fix form tabs when assigning an IP to a VM interface * [#5042](https://github.com/netbox-community/netbox/issues/5042) - Fix display of SLAAC label for IP addresses status --- diff --git a/netbox/templates/ipam/inc/ipadress_edit_header.html b/netbox/templates/ipam/inc/ipadress_edit_header.html index b8ec3878a..ed9692eea 100644 --- a/netbox/templates/ipam/inc/ipadress_edit_header.html +++ b/netbox/templates/ipam/inc/ipadress_edit_header.html @@ -4,7 +4,7 @@ - {% if 'interface' in request.GET %} + {% if 'interface' in request.GET or 'vminterface' in request.GET %} From df97eb2f72c602d4eef7fb3d51ba7d2cf4532b97 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 11:33:45 -0400 Subject: [PATCH 08/65] Fixes #5045: Allow assignment of interfaces to non-master VC peer LAG during import --- docs/release-notes/version-2.9.md | 1 + netbox/dcim/forms.py | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 6ed07d536..6c1b17c42 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -9,6 +9,7 @@ * [#5040](https://github.com/netbox-community/netbox/issues/5040) - Limit SLAAC status to IPv6 addresses * [#5041](https://github.com/netbox-community/netbox/issues/5041) - Fix form tabs when assigning an IP to a VM interface * [#5042](https://github.com/netbox-community/netbox/issues/5042) - Fix display of SLAAC label for IP addresses status +* [#5045](https://github.com/netbox-community/netbox/issues/5045) - Allow assignment of interfaces to non-master VC peer LAG during import --- diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 2e4aaed2e..b6ba55d6d 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2879,17 +2879,22 @@ class InterfaceCSVForm(CSVModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Limit LAG choices to interfaces belonging to this device (or VC master) + # Limit LAG choices to interfaces belonging to this device (or virtual chassis) device = None if self.is_bound and 'device' in self.data: try: device = self.fields['device'].to_python(self.data['device']) except forms.ValidationError: pass - - if device: + if device and device.virtual_chassis: self.fields['lag'].queryset = Interface.objects.filter( - device__in=[device, device.get_vc_master()], type=InterfaceTypeChoices.TYPE_LAG + Q(device=device) | Q(device__virtual_chassis=device.virtual_chassis), + type=InterfaceTypeChoices.TYPE_LAG + ) + elif device: + self.fields['lag'].queryset = Interface.objects.filter( + device=device, + type=InterfaceTypeChoices.TYPE_LAG ) else: self.fields['lag'].queryset = Interface.objects.none() From 5da7590eea2c4e7eaa7c57bc4c18b78c8cefb626 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 12:04:48 -0400 Subject: [PATCH 09/65] Fixes #4988: Fix ordering of rack reservations with identical creation times --- docs/release-notes/version-2.9.md | 1 + .../migrations/0115_rackreservation_order.py | 17 +++++++++++++++++ netbox/dcim/models/racks.py | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 netbox/dcim/migrations/0115_rackreservation_order.py diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 6c1b17c42..7d9b2c1e3 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -4,6 +4,7 @@ ### Bug Fixes +* [#4988](https://github.com/netbox-community/netbox/issues/4988) - Fix ordering of rack reservations with identical creation times * [#5035](https://github.com/netbox-community/netbox/issues/5035) - Fix exception when modifying an IP address assigned to a VM * [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines * [#5040](https://github.com/netbox-community/netbox/issues/5040) - Limit SLAAC status to IPv6 addresses diff --git a/netbox/dcim/migrations/0115_rackreservation_order.py b/netbox/dcim/migrations/0115_rackreservation_order.py new file mode 100644 index 000000000..594f6b9a4 --- /dev/null +++ b/netbox/dcim/migrations/0115_rackreservation_order.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1 on 2020-08-24 16:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0114_update_jsonfield'), + ] + + operations = [ + migrations.AlterModelOptions( + name='rackreservation', + options={'ordering': ['created', 'pk']}, + ), + ] diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 3169272b4..6c5ab08b9 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -600,7 +600,7 @@ class RackReservation(ChangeLoggedModel): csv_headers = ['site', 'rack_group', 'rack', 'units', 'tenant', 'user', 'description'] class Meta: - ordering = ['created'] + ordering = ['created', 'pk'] def __str__(self): return "Reservation for rack {}".format(self.rack) From a0790e911975c0a7ead4a97439fe3d17822740d8 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 15:17:36 -0400 Subject: [PATCH 10/65] Changelog for #5002 --- docs/release-notes/version-2.9.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 7d9b2c1e3..d407026e0 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -5,6 +5,7 @@ ### Bug Fixes * [#4988](https://github.com/netbox-community/netbox/issues/4988) - Fix ordering of rack reservations with identical creation times +* [#5002](https://github.com/netbox-community/netbox/issues/5002) - Correct OpenAPI definition for `available-prefixes` endpoint * [#5035](https://github.com/netbox-community/netbox/issues/5035) - Fix exception when modifying an IP address assigned to a VM * [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines * [#5040](https://github.com/netbox-community/netbox/issues/5040) - Limit SLAAC status to IPv6 addresses From f23900fc8c60d1e0e4f651ad27c0b29ea4fb1799 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 09:22:53 -0400 Subject: [PATCH 11/65] Fixes #5059: Fix inclusion of checkboxes for interfaces in virtual machine view --- docs/release-notes/version-2.9.md | 1 + netbox/templates/virtualization/inc/vminterface.html | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index d407026e0..36e54c6fd 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -12,6 +12,7 @@ * [#5041](https://github.com/netbox-community/netbox/issues/5041) - Fix form tabs when assigning an IP to a VM interface * [#5042](https://github.com/netbox-community/netbox/issues/5042) - Fix display of SLAAC label for IP addresses status * [#5045](https://github.com/netbox-community/netbox/issues/5045) - Allow assignment of interfaces to non-master VC peer LAG during import +* [#5059](https://github.com/netbox-community/netbox/issues/5059) - Fix inclusion of checkboxes for interfaces in virtual machine view --- diff --git a/netbox/templates/virtualization/inc/vminterface.html b/netbox/templates/virtualization/inc/vminterface.html index 5410fba7a..9ee1fa396 100644 --- a/netbox/templates/virtualization/inc/vminterface.html +++ b/netbox/templates/virtualization/inc/vminterface.html @@ -2,7 +2,7 @@ {# Checkbox #} - {% if perms.virtualization.change_interface or perms.virtualization.delete_interface %} + {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} @@ -48,12 +48,12 @@ {% endif %} - {% if perms.virtualization.change_interface %} + {% if perms.virtualization.change_vminterface %} {% endif %} - {% if perms.virtualization.delete_interface %} + {% if perms.virtualization.delete_vminterface %} @@ -65,7 +65,7 @@ {% if ipaddresses %} {# Placeholder #} - {% if perms.virtualization.change_interface or perms.virtualization.delete_interface %} + {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} {% endif %} From 5fe4e6cc96bd5486c410ecad5cf4896d82a72ab6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 09:26:56 -0400 Subject: [PATCH 12/65] Fixes #5058: Correct URL for front rack elevation images when using external storage --- docs/release-notes/version-2.9.md | 1 + netbox/dcim/elevations.py | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 36e54c6fd..47efc5e7c 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -12,6 +12,7 @@ * [#5041](https://github.com/netbox-community/netbox/issues/5041) - Fix form tabs when assigning an IP to a VM interface * [#5042](https://github.com/netbox-community/netbox/issues/5042) - Fix display of SLAAC label for IP addresses status * [#5045](https://github.com/netbox-community/netbox/issues/5045) - Allow assignment of interfaces to non-master VC peer LAG during import +* [#5058](https://github.com/netbox-community/netbox/issues/5058) - Correct URL for front rack elevation images when using external storage * [#5059](https://github.com/netbox-community/netbox/issues/5059) - Fix inclusion of checkboxes for interfaces in virtual machine view --- diff --git a/netbox/dcim/elevations.py b/netbox/dcim/elevations.py index cef95a7b6..5a22188b8 100644 --- a/netbox/dcim/elevations.py +++ b/netbox/dcim/elevations.py @@ -94,8 +94,12 @@ class RackElevationSVG: # Embed front device type image if one exists if self.include_images and device.device_type.front_image: - url = '{}{}'.format(self.base_url, device.device_type.front_image.url) - image = drawing.image(href=url, insert=start, size=end, class_='device-image') + image = drawing.image( + href=device.device_type.front_image.url, + insert=start, + size=end, + class_='device-image' + ) image.fit(scale='slice') link.add(image) @@ -107,8 +111,12 @@ class RackElevationSVG: # Embed rear device type image if one exists if self.include_images and device.device_type.rear_image: - url = device.device_type.rear_image.url - image = drawing.image(href=url, insert=start, size=end, class_='device-image') + image = drawing.image( + href=device.device_type.rear_image.url, + insert=start, + size=end, + class_='device-image' + ) image.fit(scale='slice') drawing.add(image) From fa73bf8e872a3fb5a4d4508bd82e2a9945484b2d Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 09:43:20 -0400 Subject: [PATCH 13/65] Closes #5505: Add tags column to device/VM component list tables --- docs/release-notes/version-2.9.md | 4 +++ netbox/dcim/tables.py | 50 +++++++++++++++++++++++++------ netbox/virtualization/tables.py | 5 +++- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 47efc5e7c..fb84d84e1 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -2,6 +2,10 @@ ## v2.9.2 (FUTURE) +### Enhancements + +* [#5055](https://github.com/netbox-community/netbox/issues/5055) - Add tags column to device/VM component list tables + ### Bug Fixes * [#4988](https://github.com/netbox-community/netbox/issues/4988) - Fix ordering of rack reservations with identical creation times diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index e48eaedba..78fa1dea6 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -706,34 +706,48 @@ class DeviceComponentTable(BaseTable): class ConsolePortTable(DeviceComponentTable): + tags = TagColumn( + url_name='dcim:consoleport_list' + ) class Meta(DeviceComponentTable.Meta): model = ConsolePort - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable') + fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') class ConsoleServerPortTable(DeviceComponentTable): + tags = TagColumn( + url_name='dcim:consoleserverport_list' + ) class Meta(DeviceComponentTable.Meta): model = ConsoleServerPort - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable') + fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') class PowerPortTable(DeviceComponentTable): + tags = TagColumn( + url_name='dcim:powerport_list' + ) class Meta(DeviceComponentTable.Meta): model = PowerPort - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable') + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', 'tags', + ) default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description') class PowerOutletTable(DeviceComponentTable): + tags = TagColumn( + url_name='dcim:poweroutlet_list' + ) class Meta(DeviceComponentTable.Meta): model = PowerOutlet - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable') + fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'tags') default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description') @@ -753,12 +767,15 @@ class BaseInterfaceTable(BaseTable): class InterfaceTable(DeviceComponentTable, BaseInterfaceTable): + tags = TagColumn( + url_name='dcim:interface_list' + ) class Meta(DeviceComponentTable.Meta): model = Interface fields = ( 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', - 'description', 'cable', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', + 'description', 'cable', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', ) default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description') @@ -767,18 +784,26 @@ class FrontPortTable(DeviceComponentTable): rear_port_position = tables.Column( verbose_name='Position' ) + tags = TagColumn( + url_name='dcim:frontport_list' + ) class Meta(DeviceComponentTable.Meta): model = FrontPort - fields = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable') + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'tags', + ) default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description') class RearPortTable(DeviceComponentTable): + tags = TagColumn( + url_name='dcim:rearport_list' + ) class Meta(DeviceComponentTable.Meta): model = RearPort - fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable') + fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'tags') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') @@ -786,10 +811,13 @@ class DeviceBayTable(DeviceComponentTable): installed_device = tables.Column( linkify=True ) + tags = TagColumn( + url_name='dcim:devicebay_list' + ) class Meta(DeviceComponentTable.Meta): model = DeviceBay - fields = ('pk', 'device', 'name', 'label', 'installed_device', 'description') + fields = ('pk', 'device', 'name', 'label', 'installed_device', 'description', 'tags') default_columns = ('pk', 'device', 'name', 'label', 'installed_device', 'description') @@ -798,12 +826,16 @@ class InventoryItemTable(DeviceComponentTable): linkify=True ) discovered = BooleanColumn() + tags = TagColumn( + url_name='dcim:inventoryitem_list' + ) + cable = None # Override DeviceComponentTable class Meta(DeviceComponentTable.Meta): model = InventoryItem fields = ( 'pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', - 'discovered', + 'discovered', 'tags', ) default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag') diff --git a/netbox/virtualization/tables.py b/netbox/virtualization/tables.py index 039934d70..5f5b9326d 100644 --- a/netbox/virtualization/tables.py +++ b/netbox/virtualization/tables.py @@ -154,11 +154,14 @@ class VMInterfaceTable(BaseInterfaceTable): name = tables.Column( linkify=True ) + tags = TagColumn( + url_name='virtualization:vminterface_list' + ) class Meta(BaseTable.Meta): model = VMInterface fields = ( - 'pk', 'virtual_machine', 'name', 'enabled', 'mac_address', 'mtu', 'description', 'ip_addresses', + 'pk', 'virtual_machine', 'name', 'enabled', 'mac_address', 'mtu', 'description', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', ) default_columns = ('pk', 'virtual_machine', 'name', 'enabled', 'description') From 5cdccb47f4d408ca99887148642dfdc437875b16 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 11:27:17 -0400 Subject: [PATCH 14/65] Fixes #5060: Fix validation when bulk-importing child devices --- docs/release-notes/version-2.9.md | 1 + netbox/dcim/models/devices.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index fb84d84e1..3bcdbbccb 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -18,6 +18,7 @@ * [#5045](https://github.com/netbox-community/netbox/issues/5045) - Allow assignment of interfaces to non-master VC peer LAG during import * [#5058](https://github.com/netbox-community/netbox/issues/5058) - Correct URL for front rack elevation images when using external storage * [#5059](https://github.com/netbox-community/netbox/issues/5059) - Fix inclusion of checkboxes for interfaces in virtual machine view +* [#5060](https://github.com/netbox-community/netbox/issues/5060) - Fix validation when bulk-importing child devices --- diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 4189e0446..e96becadf 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -633,7 +633,7 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): # Check for a duplicate name on a device assigned to the same Site and no Tenant. This is necessary # because Django does not consider two NULL fields to be equal, and thus will not trigger a violation # of the uniqueness constraint without manual intervention. - if self.name and self.tenant is None: + if self.name and hasattr(self, 'site') and self.tenant is None: if Device.objects.exclude(pk=self.pk).filter( name=self.name, site=self.site, From 523c32b8afabf4ba7245f6ce0e76a7489f20bb7c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 13:26:41 -0400 Subject: [PATCH 15/65] Fixes #5061: Allow adding/removing tags when bulk editing virtual machine interfaces --- docs/release-notes/version-2.9.md | 1 + netbox/virtualization/forms.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 3bcdbbccb..57aae0c7a 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -19,6 +19,7 @@ * [#5058](https://github.com/netbox-community/netbox/issues/5058) - Correct URL for front rack elevation images when using external storage * [#5059](https://github.com/netbox-community/netbox/issues/5059) - Fix inclusion of checkboxes for interfaces in virtual machine view * [#5060](https://github.com/netbox-community/netbox/issues/5060) - Fix validation when bulk-importing child devices +* [#5061](https://github.com/netbox-community/netbox/issues/5061) - Allow adding/removing tags when bulk editing virtual machine interfaces --- diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index 8ba288d1c..5d002decc 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -684,7 +684,7 @@ class VMInterfaceCSVForm(CSVModelForm): return self.cleaned_data['enabled'] -class VMInterfaceBulkEditForm(BootstrapMixin, BulkEditForm): +class VMInterfaceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=VMInterface.objects.all(), widget=forms.MultipleHiddenInput() From e8e4ff4111a23bb34cc10187d4f1a1963c406787 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 13:46:31 -0400 Subject: [PATCH 16/65] Closes #5056: Add interface and parent columns to IP address list --- docs/release-notes/version-2.9.md | 1 + netbox/ipam/api/views.py | 2 +- netbox/ipam/tables.py | 16 ++++++++++++---- netbox/ipam/views.py | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 57aae0c7a..30aeb2070 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -5,6 +5,7 @@ ### Enhancements * [#5055](https://github.com/netbox-community/netbox/issues/5055) - Add tags column to device/VM component list tables +* [#5056](https://github.com/netbox-community/netbox/issues/5056) - Add interface and parent columns to IP address list ### Bug Fixes diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 280bb4322..dd0731bb8 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -247,7 +247,7 @@ class PrefixViewSet(CustomFieldModelViewSet): class IPAddressViewSet(CustomFieldModelViewSet): queryset = IPAddress.objects.prefetch_related( - 'vrf__tenant', 'tenant', 'nat_inside', 'nat_outside', 'tags', + 'vrf__tenant', 'tenant', 'nat_inside', 'nat_outside', 'tags', 'assigned_object' ) serializer_class = serializers.IPAddressSerializer filterset_class = filters.IPAddressFilterSet diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 5a4e2c133..7b4aa44ba 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -387,15 +387,23 @@ class IPAddressTable(BaseTable): tenant = tables.TemplateColumn( template_code=TENANT_LINK ) - assigned = tables.BooleanColumn( - accessor='assigned_object_id', - verbose_name='Assigned' + assigned_object = tables.Column( + linkify=True, + orderable=False, + verbose_name='Interface' + ) + assigned_object_parent = tables.Column( + accessor='assigned_object__parent', + linkify=True, + orderable=False, + verbose_name='Interface Parent' ) class Meta(BaseTable.Meta): model = IPAddress fields = ( - 'pk', 'address', 'vrf', 'status', 'role', 'tenant', 'assigned', 'dns_name', 'description', + 'pk', 'address', 'vrf', 'status', 'role', 'tenant', 'assigned_object', 'assigned_object_parent', 'dns_name', + 'description', ) row_attrs = { 'class': lambda record: 'success' if not isinstance(record, IPAddress) else '', diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 8ea33764c..68f7da8ad 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -493,7 +493,7 @@ class PrefixBulkDeleteView(BulkDeleteView): class IPAddressListView(ObjectListView): queryset = IPAddress.objects.prefetch_related( - 'vrf__tenant', 'tenant', 'nat_inside' + 'vrf__tenant', 'tenant', 'nat_inside', 'assigned_object' ) filterset = filters.IPAddressFilterSet filterset_form = forms.IPAddressFilterForm From f3e4911c6885c9dec281f8f4fe661d354184607a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 14:03:51 -0400 Subject: [PATCH 17/65] Release v2.9.2 --- docs/release-notes/version-2.9.md | 2 +- netbox/netbox/settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 30aeb2070..e853a06e4 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -1,6 +1,6 @@ # NetBox v2.9 -## v2.9.2 (FUTURE) +## v2.9.2 (2020-08-27) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 6a836ff74..61dc9cd72 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.9.2-dev' +VERSION = '2.9.2' # Hostname HOSTNAME = platform.node() From 2435c177f53186b1f9d4683377b3e73315a7e0d3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 14:15:09 -0400 Subject: [PATCH 18/65] Post-release version bump --- 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 61dc9cd72..bfffe7135 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.9.2' +VERSION = '2.9.3-dev' # Hostname HOSTNAME = platform.node() From bfcbd9da6c17df65b63a355c276cea0b53d5d305 Mon Sep 17 00:00:00 2001 From: Simeon Keske Date: Sun, 30 Aug 2020 01:44:27 +0200 Subject: [PATCH 19/65] Redirect users away from /login, if they are already logged in --- netbox/users/views.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/netbox/users/views.py b/netbox/users/views.py index 755232444..011281b45 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -36,6 +36,15 @@ class LoginView(View): return super().dispatch(*args, **kwargs) def get(self, request): + if request.user.is_authenticated: + # Already logged-in, determine where to redirect + redirect_to = request.GET.get('next', reverse('home')) + if redirect_to and not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()): + logger.warning(f"Ignoring unsafe 'next' URL passed to login form: {redirect_to}") + redirect_to = reverse('home') + + return HttpResponseRedirect(redirect_to) + form = LoginForm(request) return render(request, self.template_name, { From 5bff50cade41dd55756e0ff4ff3f0df5fca50041 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 31 Aug 2020 15:26:00 -0400 Subject: [PATCH 20/65] Fixes #5063: Fix "add device" link in rack elevations for opposite side of half-depth devices --- docs/release-notes/version-2.9.md | 8 ++++++++ netbox/dcim/elevations.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index e853a06e4..9593ea414 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -1,5 +1,13 @@ # NetBox v2.9 +## v2.9.3 (FUTURE) + +### Bug Fixes + +* [#5063](https://github.com/netbox-community/netbox/issues/5063) - Fix "add device" link in rack elevations for opposite side of half-depth devices + +--- + ## v2.9.2 (2020-08-27) ### Enhancements diff --git a/netbox/dcim/elevations.py b/netbox/dcim/elevations.py index 5a22188b8..93c44f087 100644 --- a/netbox/dcim/elevations.py +++ b/netbox/dcim/elevations.py @@ -149,7 +149,7 @@ class RackElevationSVG: unit_cursor = 0 for u in elevation: o = other[unit_cursor] - if not u['device'] and o['device']: + if not u['device'] and o['device'] and o['device'].device_type.is_full_depth: u['device'] = o['device'] u['height'] = 1 unit_cursor += u.get('height', 1) From 473d76c9d1cf24deab6991b1eb994fa11f53a65e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 31 Aug 2020 15:34:40 -0400 Subject: [PATCH 21/65] Fixes #5074: Fix inclusion of VC member interfaces when viewing VC master --- docs/release-notes/version-2.9.md | 1 + netbox/dcim/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 9593ea414..bfc5642af 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -5,6 +5,7 @@ ### Bug Fixes * [#5063](https://github.com/netbox-community/netbox/issues/5063) - Fix "add device" link in rack elevations for opposite side of half-depth devices +* [#5074](https://github.com/netbox-community/netbox/issues/5074) - Fix inclusion of VC member interfaces when viewing VC master --- diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index c016f6e54..5b0a396bf 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1033,7 +1033,7 @@ class DeviceView(ObjectView): ) # Interfaces - interfaces = device.vc_interfaces.restrict(request.user, 'view').filter(device=device).prefetch_related( + interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related( Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), 'lag', '_connected_interface__device', '_connected_circuittermination__circuit', 'cable', From 967073eaaf6764096f603df354c63d6b7656760b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 09:54:45 -0400 Subject: [PATCH 22/65] Fixes #5081: Fix exception during webhook processing with custom select field --- docs/release-notes/version-2.9.md | 1 + netbox/extras/api/customfields.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index bfc5642af..aec9817f2 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -6,6 +6,7 @@ * [#5063](https://github.com/netbox-community/netbox/issues/5063) - Fix "add device" link in rack elevations for opposite side of half-depth devices * [#5074](https://github.com/netbox-community/netbox/issues/5074) - Fix inclusion of VC member interfaces when viewing VC master +* [#5081](https://github.com/netbox-community/netbox/issues/5081) - Fix exception during webhook processing with custom select field --- diff --git a/netbox/extras/api/customfields.py b/netbox/extras/api/customfields.py index 5ef983977..f096fb4a6 100644 --- a/netbox/extras/api/customfields.py +++ b/netbox/extras/api/customfields.py @@ -158,7 +158,7 @@ class CustomFieldModelSerializer(ValidatedModelSerializer): instance.custom_fields = {} for field in custom_fields: value = instance.cf.get(field.name) - if field.type == CustomFieldTypeChoices.TYPE_SELECT and value is not None: + if field.type == CustomFieldTypeChoices.TYPE_SELECT and value: instance.custom_fields[field.name] = CustomFieldChoiceSerializer(value).data else: instance.custom_fields[field.name] = value From 7dbeaf7a0108e393ceaeefd6d3911c8fc79b24b6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 10:19:28 -0400 Subject: [PATCH 23/65] Fixes #5078: Fix assignment of existing IP addresses to interfaces via web UI --- docs/release-notes/version-2.9.md | 1 + netbox/ipam/tables.py | 6 +----- netbox/ipam/views.py | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index aec9817f2..17b2ddffe 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -6,6 +6,7 @@ * [#5063](https://github.com/netbox-community/netbox/issues/5063) - Fix "add device" link in rack elevations for opposite side of half-depth devices * [#5074](https://github.com/netbox-community/netbox/issues/5074) - Fix inclusion of VC member interfaces when viewing VC master +* [#5078](https://github.com/netbox-community/netbox/issues/5078) - Fix assignment of existing IP addresses to interfaces via web UI * [#5081](https://github.com/netbox-community/netbox/issues/5081) - Fix exception during webhook processing with custom select field --- diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 7b4aa44ba..a16dcf333 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -67,11 +67,7 @@ IPADDRESS_LINK = """ """ IPADDRESS_ASSIGN_LINK = """ -{% if request.GET %} - {{ record }} -{% else %} - {{ record }} -{% endif %} +{{ record }} """ VRF_LINK = """ diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 68f7da8ad..1f0e2607e 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -582,7 +582,7 @@ class IPAddressAssignView(ObjectView): def dispatch(self, request, *args, **kwargs): # Redirect user if an interface has not been provided - if 'interface' not in request.GET: + if 'interface' not in request.GET and 'vminterface' not in request.GET: return redirect('ipam:ipaddress_add') return super().dispatch(request, *args, **kwargs) @@ -609,7 +609,7 @@ class IPAddressAssignView(ObjectView): return render(request, 'ipam/ipaddress_assign.html', { 'form': form, 'table': table, - 'return_url': request.GET.get('return_url', ''), + 'return_url': request.GET.get('return_url'), }) From b3b7e08c50583fe06be1bef1083c0994e00abbf9 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 10:24:17 -0400 Subject: [PATCH 24/65] Closes #5076: Specify pip3 --- 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 05f6d825e..235e39a8f 100644 --- a/docs/installation/3-netbox.md +++ b/docs/installation/3-netbox.md @@ -25,7 +25,7 @@ Begin by installing all system packages required by NetBox and its dependencies. Before continuing with either platform, update pip (Python's package management tool) to its latest release: ```no-highlight -# pip install --upgrade pip +# pip3 install --upgrade pip ``` ## Download NetBox From a0103036e4a90eddb6d955c239a15d8a1bc10764 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 13:59:50 -0400 Subject: [PATCH 25/65] Fixes #5087: Restore label field when editing console server ports, power ports, and power outlets --- docs/release-notes/version-2.9.md | 1 + netbox/dcim/forms.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 17b2ddffe..18881d7c1 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -8,6 +8,7 @@ * [#5074](https://github.com/netbox-community/netbox/issues/5074) - Fix inclusion of VC member interfaces when viewing VC master * [#5078](https://github.com/netbox-community/netbox/issues/5078) - Fix assignment of existing IP addresses to interfaces via web UI * [#5081](https://github.com/netbox-community/netbox/issues/5081) - Fix exception during webhook processing with custom select field +* [#5087](https://github.com/netbox-community/netbox/issues/5087) - Restore label field when editing console server ports, power ports, and power outlets --- diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index b6ba55d6d..43f77de51 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2317,7 +2317,7 @@ class ConsoleServerPortForm(BootstrapMixin, forms.ModelForm): class Meta: model = ConsoleServerPort fields = [ - 'device', 'name', 'type', 'description', 'tags', + 'device', 'name', 'label', 'type', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), @@ -2390,7 +2390,7 @@ class PowerPortForm(BootstrapMixin, forms.ModelForm): class Meta: model = PowerPort fields = [ - 'device', 'name', 'type', 'maximum_draw', 'allocated_draw', 'description', 'tags', + 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), @@ -2479,7 +2479,7 @@ class PowerOutletForm(BootstrapMixin, forms.ModelForm): class Meta: model = PowerOutlet fields = [ - 'device', 'name', 'type', 'power_port', 'feed_leg', 'description', 'tags', + 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'tags', ] widgets = { 'device': forms.HiddenInput(), From 6305a35a4f5e2c75e0fb5f95b8bdbf5e0ed23391 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 15:18:47 -0400 Subject: [PATCH 26/65] Fixes #5085: Fix ordering by assignment in IP addresses table --- docs/release-notes/version-2.9.md | 1 + netbox/ipam/tables.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 18881d7c1..12a50880c 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -8,6 +8,7 @@ * [#5074](https://github.com/netbox-community/netbox/issues/5074) - Fix inclusion of VC member interfaces when viewing VC master * [#5078](https://github.com/netbox-community/netbox/issues/5078) - Fix assignment of existing IP addresses to interfaces via web UI * [#5081](https://github.com/netbox-community/netbox/issues/5081) - Fix exception during webhook processing with custom select field +* [#5085](https://github.com/netbox-community/netbox/issues/5085) - Fix ordering by assignment in IP addresses table * [#5087](https://github.com/netbox-community/netbox/issues/5087) - Restore label field when editing console server ports, power ports, and power outlets --- diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index a16dcf333..32af7c262 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -415,6 +415,10 @@ class IPAddressDetailTable(IPAddressTable): tenant = tables.TemplateColumn( template_code=COL_TENANT ) + assigned = tables.BooleanColumn( + accessor='assigned_object_id', + verbose_name='Assigned' + ) tags = TagColumn( url_name='ipam:ipaddress_list' ) From 5d7935c8556bc540aeea6c0de49b8214be5a12bf Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 16:28:11 -0400 Subject: [PATCH 27/65] Fixes #5090: Fix status display for console/power/interface connections --- docs/release-notes/version-2.9.md | 1 + netbox/dcim/tables.py | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 12a50880c..14a15fc3f 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -10,6 +10,7 @@ * [#5081](https://github.com/netbox-community/netbox/issues/5081) - Fix exception during webhook processing with custom select field * [#5085](https://github.com/netbox-community/netbox/issues/5085) - Fix ordering by assignment in IP addresses table * [#5087](https://github.com/netbox-community/netbox/issues/5087) - Restore label field when editing console server ports, power ports, and power outlets +* [#5090](https://github.com/netbox-community/netbox/issues/5090) - Fix status display for console/power/interface connections --- diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index 78fa1dea6..9afdd7fff 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -152,6 +152,10 @@ INTERFACE_TAGGED_VLANS = """ {% endfor %} """ +CONNECTION_STATUS = """ +{{ record.get_connection_status_display }} +""" + # # Regions @@ -916,7 +920,10 @@ class ConsoleConnectionTable(BaseTable): name = tables.Column( verbose_name='Console Port' ) - connection_status = BooleanColumn() + connection_status = tables.TemplateColumn( + template_code=CONNECTION_STATUS, + verbose_name='Status' + ) class Meta(BaseTable.Meta): model = ConsolePort @@ -941,6 +948,10 @@ class PowerConnectionTable(BaseTable): name = tables.Column( verbose_name='Power Port' ) + connection_status = tables.TemplateColumn( + template_code=CONNECTION_STATUS, + verbose_name='Status' + ) class Meta(BaseTable.Meta): model = PowerPort @@ -972,6 +983,10 @@ class InterfaceConnectionTable(BaseTable): args=[Accessor('_connected_interface__pk')], verbose_name='Interface B' ) + connection_status = tables.TemplateColumn( + template_code=CONNECTION_STATUS, + verbose_name='Status' + ) class Meta(BaseTable.Meta): model = Interface From 268aa755c470a1d7577bfa63f1d6d5c2ac79158c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 10:21:22 -0400 Subject: [PATCH 28/65] Closes #5080: Add 8P6C, 8P4C, 8P2C port types --- docs/release-notes/version-2.9.md | 4 ++++ netbox/dcim/choices.py | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 14a15fc3f..19218732a 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -2,6 +2,10 @@ ## v2.9.3 (FUTURE) +### Enhancements + +* [#5080](https://github.com/netbox-community/netbox/issues/5080) - Add 8P6C, 8P4C, 8P2C port types + ### Bug Fixes * [#5063](https://github.com/netbox-community/netbox/issues/5063) - Fix "add device" link in rack elevations for opposite side of half-depth devices diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index dc12e686e..fa4f81792 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -814,6 +814,9 @@ class InterfaceModeChoices(ChoiceSet): class PortTypeChoices(ChoiceSet): TYPE_8P8C = '8p8c' + TYPE_8P6C = '8p6c' + TYPE_8P4C = '8p4c' + TYPE_8P2C = '8p2c' TYPE_110_PUNCH = '110-punch' TYPE_BNC = 'bnc' TYPE_MRJ21 = 'mrj21' @@ -833,6 +836,9 @@ class PortTypeChoices(ChoiceSet): 'Copper', ( (TYPE_8P8C, '8P8C'), + (TYPE_8P6C, '8P6C'), + (TYPE_8P4C, '8P4C'), + (TYPE_8P2C, '8P2C'), (TYPE_110_PUNCH, '110 Punch'), (TYPE_BNC, 'BNC'), (TYPE_MRJ21, 'MRJ21'), From b559c827d24059af92779b2988b111da1fc1bbb6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 13:30:19 -0400 Subject: [PATCH 29/65] Fixes #5091: Avoid KeyError when handling invalid table preferences --- docs/release-notes/version-2.9.md | 1 + netbox/utilities/tables.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 19218732a..f5705bca8 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -15,6 +15,7 @@ * [#5085](https://github.com/netbox-community/netbox/issues/5085) - Fix ordering by assignment in IP addresses table * [#5087](https://github.com/netbox-community/netbox/issues/5087) - Restore label field when editing console server ports, power ports, and power outlets * [#5090](https://github.com/netbox-community/netbox/issues/5090) - Fix status display for console/power/interface connections +* [#5091](https://github.com/netbox-community/netbox/issues/5091) - Avoid KeyError when handling invalid table preferences --- diff --git a/netbox/utilities/tables.py b/netbox/utilities/tables.py index 0144ea2d1..6df6b2e26 100644 --- a/netbox/utilities/tables.py +++ b/netbox/utilities/tables.py @@ -44,7 +44,7 @@ class BaseTable(tables.Table): self.columns.show(name) else: self.columns.hide(name) - self.sequence = columns + self.sequence = [c for c in columns if c in self.base_columns] # Always include PK and actions column, if defined on the table if pk: From babdc1db3806ab701ebfa9a06e4a57776b924b05 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 13:33:59 -0400 Subject: [PATCH 30/65] Link to console/power ports in connection views --- netbox/dcim/tables.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index 9afdd7fff..371eff9db 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -912,12 +912,14 @@ class ConsoleConnectionTable(BaseTable): verbose_name='Console Server' ) connected_endpoint = tables.Column( + linkify=True, verbose_name='Port' ) device = tables.Column( linkify=True ) name = tables.Column( + linkify=True, verbose_name='Console Port' ) connection_status = tables.TemplateColumn( @@ -940,12 +942,14 @@ class PowerConnectionTable(BaseTable): ) outlet = tables.Column( accessor=Accessor('_connected_poweroutlet'), + linkify=True, verbose_name='Outlet' ) device = tables.Column( linkify=True ) name = tables.Column( + linkify=True, verbose_name='Power Port' ) connection_status = tables.TemplateColumn( From d289b260340b2386077a1b9f8cf77f5a0684f3cb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 13:45:15 -0400 Subject: [PATCH 31/65] Fixes #5089: Redirect to device view after editing component --- docs/release-notes/version-2.9.md | 1 + netbox/templates/dcim/inc/consoleport.html | 2 +- netbox/templates/dcim/inc/consoleserverport.html | 2 +- netbox/templates/dcim/inc/devicebay.html | 2 +- netbox/templates/dcim/inc/poweroutlet.html | 2 +- netbox/templates/dcim/inc/powerport.html | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index f5705bca8..0b6b80b62 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -14,6 +14,7 @@ * [#5081](https://github.com/netbox-community/netbox/issues/5081) - Fix exception during webhook processing with custom select field * [#5085](https://github.com/netbox-community/netbox/issues/5085) - Fix ordering by assignment in IP addresses table * [#5087](https://github.com/netbox-community/netbox/issues/5087) - Restore label field when editing console server ports, power ports, and power outlets +* [#5089](https://github.com/netbox-community/netbox/issues/5089) - Redirect to device view after editing component * [#5090](https://github.com/netbox-community/netbox/issues/5090) - Fix status display for console/power/interface connections * [#5091](https://github.com/netbox-community/netbox/issues/5091) - Avoid KeyError when handling invalid table preferences diff --git a/netbox/templates/dcim/inc/consoleport.html b/netbox/templates/dcim/inc/consoleport.html index dc2111b8a..6fa5e8b91 100644 --- a/netbox/templates/dcim/inc/consoleport.html +++ b/netbox/templates/dcim/inc/consoleport.html @@ -66,7 +66,7 @@ {% endif %} {% if perms.dcim.change_consoleport %} - + {% endif %} diff --git a/netbox/templates/dcim/inc/consoleserverport.html b/netbox/templates/dcim/inc/consoleserverport.html index dcf168ae7..fca1fa5f4 100644 --- a/netbox/templates/dcim/inc/consoleserverport.html +++ b/netbox/templates/dcim/inc/consoleserverport.html @@ -68,7 +68,7 @@ {% endif %} {% if perms.dcim.change_consoleserverport %} - + {% endif %} diff --git a/netbox/templates/dcim/inc/devicebay.html b/netbox/templates/dcim/inc/devicebay.html index ee6a66d8f..bde7b8641 100644 --- a/netbox/templates/dcim/inc/devicebay.html +++ b/netbox/templates/dcim/inc/devicebay.html @@ -52,7 +52,7 @@ {% endif %} - + {% endif %} diff --git a/netbox/templates/dcim/inc/poweroutlet.html b/netbox/templates/dcim/inc/poweroutlet.html index d9a77d647..5800f4b48 100644 --- a/netbox/templates/dcim/inc/poweroutlet.html +++ b/netbox/templates/dcim/inc/poweroutlet.html @@ -81,7 +81,7 @@ {% endif %} {% if perms.dcim.change_poweroutlet %} - + {% endif %} diff --git a/netbox/templates/dcim/inc/powerport.html b/netbox/templates/dcim/inc/powerport.html index 58eed145a..b30fc8456 100644 --- a/netbox/templates/dcim/inc/powerport.html +++ b/netbox/templates/dcim/inc/powerport.html @@ -78,7 +78,7 @@ {% endif %} {% if perms.dcim.change_powerport %} - + {% endif %} From bbbfc2759397b9a5cf41f52094d041c60d9a0ac0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 16:10:07 -0400 Subject: [PATCH 32/65] Fixes #5072: Add REST API filters for image attachments --- docs/release-notes/version-2.9.md | 1 + netbox/extras/api/views.py | 1 + netbox/extras/filters.py | 10 +++- netbox/extras/tests/test_filters.py | 82 ++++++++++++++++++++++++++++- 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 0b6b80b62..5fa6fb6d2 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -4,6 +4,7 @@ ### Enhancements +* [#5072](https://github.com/netbox-community/netbox/issues/5072) - Add REST API filters for image attachments * [#5080](https://github.com/netbox-community/netbox/issues/5080) - Add 8P6C, 8P4C, 8P2C port types ### Bug Fixes diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 289a51c83..a63dbe44d 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -140,6 +140,7 @@ class ImageAttachmentViewSet(ModelViewSet): metadata_class = ContentTypeMetadata queryset = ImageAttachment.objects.all() serializer_class = serializers.ImageAttachmentSerializer + filterset_class = filters.ImageAttachmentFilterSet # diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index e8962da01..1af98e885 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -7,7 +7,7 @@ from tenancy.models import Tenant, TenantGroup from utilities.filters import BaseFilterSet from virtualization.models import Cluster, ClusterGroup from .choices import * -from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, JobResult, Tag +from .models import ConfigContext, CustomField, ExportTemplate, Graph, ImageAttachment, JobResult, ObjectChange, Tag __all__ = ( @@ -17,6 +17,7 @@ __all__ = ( 'CustomFieldFilterSet', 'ExportTemplateFilterSet', 'GraphFilterSet', + 'ImageAttachmentFilterSet', 'LocalConfigContextFilterSet', 'ObjectChangeFilterSet', 'TagFilterSet', @@ -104,6 +105,13 @@ class ExportTemplateFilterSet(BaseFilterSet): fields = ['id', 'content_type', 'name', 'template_language'] +class ImageAttachmentFilterSet(BaseFilterSet): + + class Meta: + model = ImageAttachment + fields = ['id', 'content_type', 'object_id', 'name'] + + class TagFilterSet(BaseFilterSet): q = django_filters.CharFilter( method='search', diff --git a/netbox/extras/tests/test_filters.py b/netbox/extras/tests/test_filters.py index 72db138e2..d6e077db4 100644 --- a/netbox/extras/tests/test_filters.py +++ b/netbox/extras/tests/test_filters.py @@ -1,11 +1,11 @@ from django.contrib.contenttypes.models import ContentType from django.test import TestCase -from dcim.models import DeviceRole, Platform, Region, Site +from dcim.models import DeviceRole, Platform, Rack, Region, Site from extras.choices import * from extras.filters import * from extras.utils import FeatureQuery -from extras.models import ConfigContext, ExportTemplate, Graph, Tag +from extras.models import ConfigContext, ExportTemplate, Graph, ImageAttachment, Tag from tenancy.models import Tenant, TenantGroup from virtualization.models import Cluster, ClusterGroup, ClusterType @@ -78,6 +78,84 @@ class ExportTemplateTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) +class ImageAttachmentTestCase(TestCase): + queryset = ImageAttachment.objects.all() + filterset = ImageAttachmentFilterSet + + @classmethod + def setUpTestData(cls): + + site_ct = ContentType.objects.get(app_label='dcim', model='site') + rack_ct = ContentType.objects.get(app_label='dcim', model='rack') + + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + ) + Site.objects.bulk_create(sites) + + racks = ( + Rack(name='Rack 1', site=sites[0]), + Rack(name='Rack 2', site=sites[1]), + ) + Rack.objects.bulk_create(racks) + + image_attachments = ( + ImageAttachment( + content_type=site_ct, + object_id=sites[0].pk, + name='Image Attachment 1', + image='http://example.com/image1.png', + image_height=100, + image_width=100 + ), + ImageAttachment( + content_type=site_ct, + object_id=sites[1].pk, + name='Image Attachment 2', + image='http://example.com/image2.png', + image_height=100, + image_width=100 + ), + ImageAttachment( + content_type=rack_ct, + object_id=racks[0].pk, + name='Image Attachment 3', + image='http://example.com/image3.png', + image_height=100, + image_width=100 + ), + ImageAttachment( + content_type=rack_ct, + object_id=racks[1].pk, + name='Image Attachment 4', + image='http://example.com/image4.png', + image_height=100, + image_width=100 + ) + ) + ImageAttachment.objects.bulk_create(image_attachments) + + def test_id(self): + params = {'id': self.queryset.values_list('pk', flat=True)[:2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Image Attachment 1', 'Image Attachment 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_content_type(self): + params = {'content_type': ContentType.objects.get(app_label='dcim', model='site').pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_content_type_and_object_id(self): + params = { + 'content_type': ContentType.objects.get(app_label='dcim', model='site').pk, + 'object_id': [Site.objects.first().pk], + } + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + class ConfigContextTestCase(TestCase): queryset = ConfigContext.objects.all() filterset = ConfigContextFilterSet From f92569d4688bf58758c0009a3bb13261d25033ac Mon Sep 17 00:00:00 2001 From: Simeon Keske Date: Wed, 2 Sep 2020 22:33:39 +0200 Subject: [PATCH 33/65] move redirect code to own function --- netbox/users/views.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/netbox/users/views.py b/netbox/users/views.py index 011281b45..46221f649 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -36,17 +36,12 @@ class LoginView(View): return super().dispatch(*args, **kwargs) def get(self, request): - if request.user.is_authenticated: - # Already logged-in, determine where to redirect - redirect_to = request.GET.get('next', reverse('home')) - if redirect_to and not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()): - logger.warning(f"Ignoring unsafe 'next' URL passed to login form: {redirect_to}") - redirect_to = reverse('home') - - return HttpResponseRedirect(redirect_to) - form = LoginForm(request) + if request.user.is_authenticated: + logger = logging.getLogger('netbox.auth.login') + return self.redirect_to_next(request, logger) + return render(request, self.template_name, { 'form': form, }) @@ -58,12 +53,6 @@ class LoginView(View): if form.is_valid(): logger.debug("Login form validation was successful") - # Determine where to direct user after successful login - redirect_to = request.POST.get('next', reverse('home')) - if redirect_to and not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()): - logger.warning(f"Ignoring unsafe 'next' URL passed to login form: {redirect_to}") - redirect_to = reverse('home') - # If maintenance mode is enabled, assume the database is read-only, and disable updating the user's # last_login time upon authentication. if settings.MAINTENANCE_MODE: @@ -75,8 +64,7 @@ class LoginView(View): logger.info(f"User {request.user} successfully authenticated") messages.info(request, "Logged in as {}.".format(request.user)) - logger.debug(f"Redirecting user to {redirect_to}") - return HttpResponseRedirect(redirect_to) + return self.redirect_to_next(request, logger) else: logger.debug("Login form validation failed") @@ -85,6 +73,19 @@ class LoginView(View): 'form': form, }) + def redirect_to_next(self, request, logger): + if request.method == "POST": + redirect_to = request.POST.get('next', reverse('home')) + else: + redirect_to = request.GET.get('next', reverse('home')) + + if redirect_to and not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()): + logger.warning(f"Ignoring unsafe 'next' URL passed to login form: {redirect_to}") + redirect_to = reverse('home') + + logger.debug(f"Redirecting user to {redirect_to}") + return HttpResponseRedirect(redirect_to) + class LogoutView(View): """ From de081d0205ac92f7107da4c93a847bd15f532799 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 3 Sep 2020 11:28:25 -0400 Subject: [PATCH 34/65] Fixes #5095: Fix display of assigned prefixes in VLANs list --- netbox/ipam/tables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 32af7c262..d7a64f7db 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -99,7 +99,7 @@ VLAN_LINK = """ """ VLAN_PREFIXES = """ -{% for prefix in record.prefixes.unrestricted %} +{% for prefix in record.prefixes.all %} {{ prefix }}{% if not forloop.last %}
{% endif %} {% empty %} — From dd0185816cc1beabe9bdae3d968a166e4cf005e0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 13:57:29 -0400 Subject: [PATCH 35/65] Changelog for #4977, #5095 --- docs/release-notes/version-2.9.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 5fa6fb6d2..d99b161e0 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -4,6 +4,7 @@ ### Enhancements +* [#4977](https://github.com/netbox-community/netbox/issues/4977) - Redirect authenticated users from login view * [#5072](https://github.com/netbox-community/netbox/issues/5072) - Add REST API filters for image attachments * [#5080](https://github.com/netbox-community/netbox/issues/5080) - Add 8P6C, 8P4C, 8P2C port types @@ -18,6 +19,7 @@ * [#5089](https://github.com/netbox-community/netbox/issues/5089) - Redirect to device view after editing component * [#5090](https://github.com/netbox-community/netbox/issues/5090) - Fix status display for console/power/interface connections * [#5091](https://github.com/netbox-community/netbox/issues/5091) - Avoid KeyError when handling invalid table preferences +* [#5095](https://github.com/netbox-community/netbox/issues/5095) - Avoid KeyError when handling invalid table preferences --- From 78d104e60c1e9e85aad50744c97cb2b0ca23b5d4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 14:13:35 -0400 Subject: [PATCH 36/65] Fixes #5046: Disabled plugin menu items are no longer clickable --- docs/plugins/development.md | 3 +++ docs/release-notes/version-2.9.md | 1 + netbox/templates/inc/plugin_menu_items.html | 28 ++++++++++++--------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/docs/plugins/development.md b/docs/plugins/development.md index b704ad7fc..f4db3c84d 100644 --- a/docs/plugins/development.md +++ b/docs/plugins/development.md @@ -328,6 +328,9 @@ A `PluginMenuButton` has the following attributes: * `color` - One of the choices provided by `ButtonColorChoices` (optional) * `permissions` - A list of permissions required to display this button (optional) +!!! note + Any buttons associated within a menu item will be shown only if the user has permission to view the link, regardless of what permissions are set on the buttons. + ## Extending Core Templates Plugins can inject custom content into certain areas of the detail views of applicable models. This is accomplished by subclassing `PluginTemplateExtension`, designating a particular NetBox model, and defining the desired methods to render custom content. Four methods are available: diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index d99b161e0..5505fed8f 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -10,6 +10,7 @@ ### Bug Fixes +* [#5046](https://github.com/netbox-community/netbox/issues/5046) - Disabled plugin menu items are no longer clickable * [#5063](https://github.com/netbox-community/netbox/issues/5063) - Fix "add device" link in rack elevations for opposite side of half-depth devices * [#5074](https://github.com/netbox-community/netbox/issues/5074) - Fix inclusion of VC member interfaces when viewing VC master * [#5078](https://github.com/netbox-community/netbox/issues/5078) - Fix assignment of existing IP addresses to interfaces via web UI diff --git a/netbox/templates/inc/plugin_menu_items.html b/netbox/templates/inc/plugin_menu_items.html index 0df4a5e8a..3d9a46a52 100644 --- a/netbox/templates/inc/plugin_menu_items.html +++ b/netbox/templates/inc/plugin_menu_items.html @@ -5,18 +5,22 @@ {% for section_name, menu_items in registry.plugin_menu_items.items %} {% for menu_item in menu_items %} - - {% if menu_item.buttons %} -
- {% for button in menu_item.buttons %} - {% if not button.permissions or request.user|has_perms:button.permissions %} - - {% endif %} - {% endfor %} -
- {% endif %} - {{ menu_item.link_text }} - + {% if not menu_item.permissions or request.user|has_perms:menu_item.permissions %} +
  • + {% if menu_item.buttons %} +
    + {% for button in menu_item.buttons %} + {% if not button.permissions or request.user|has_perms:button.permissions %} + + {% endif %} + {% endfor %} +
    + {% endif %} + {{ menu_item.link_text }} +
  • + {% else %} +
  • {{ menu_item.link_text }}
  • + {% endif %} {% endfor %} {% if not forloop.last %}
  • From f1877fcea9a6c4f7c59e82a8e2428a72c0cdb806 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:10:34 -0400 Subject: [PATCH 37/65] Closes #5048: Show the device/VM name when editing a component --- docs/release-notes/version-2.9.md | 1 + netbox/dcim/views.py | 7 +++++++ .../templates/dcim/device_component_edit.html | 16 +++++++++++++++ netbox/templates/dcim/interface_edit.html | 15 ++++++++++++++ netbox/templates/utilities/obj_edit.html | 4 +++- .../virtualmachine_component_add.html | 2 +- .../virtualization/vminterface_edit.html | 20 +++++++++++++++++++ 7 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 netbox/templates/dcim/device_component_edit.html diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 5505fed8f..09456ae14 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -5,6 +5,7 @@ ### Enhancements * [#4977](https://github.com/netbox-community/netbox/issues/4977) - Redirect authenticated users from login view +* [#5048](https://github.com/netbox-community/netbox/issues/5048) - Show the device/VM name when editing a component * [#5072](https://github.com/netbox-community/netbox/issues/5072) - Add REST API filters for image attachments * [#5080](https://github.com/netbox-community/netbox/issues/5080) - Add 8P6C, 8P4C, 8P2C port types diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 5b0a396bf..9f4dcc90e 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1233,6 +1233,7 @@ class ConsolePortCreateView(ComponentCreateView): class ConsolePortEditView(ObjectEditView): queryset = ConsolePort.objects.all() model_form = forms.ConsolePortForm + template_name = 'dcim/device_component_edit.html' class ConsolePortDeleteView(ObjectDeleteView): @@ -1292,6 +1293,7 @@ class ConsoleServerPortCreateView(ComponentCreateView): class ConsoleServerPortEditView(ObjectEditView): queryset = ConsoleServerPort.objects.all() model_form = forms.ConsoleServerPortForm + template_name = 'dcim/device_component_edit.html' class ConsoleServerPortDeleteView(ObjectDeleteView): @@ -1351,6 +1353,7 @@ class PowerPortCreateView(ComponentCreateView): class PowerPortEditView(ObjectEditView): queryset = PowerPort.objects.all() model_form = forms.PowerPortForm + template_name = 'dcim/device_component_edit.html' class PowerPortDeleteView(ObjectDeleteView): @@ -1410,6 +1413,7 @@ class PowerOutletCreateView(ComponentCreateView): class PowerOutletEditView(ObjectEditView): queryset = PowerOutlet.objects.all() model_form = forms.PowerOutletForm + template_name = 'dcim/device_component_edit.html' class PowerOutletDeleteView(ObjectDeleteView): @@ -1561,6 +1565,7 @@ class FrontPortCreateView(ComponentCreateView): class FrontPortEditView(ObjectEditView): queryset = FrontPort.objects.all() model_form = forms.FrontPortForm + template_name = 'dcim/device_component_edit.html' class FrontPortDeleteView(ObjectDeleteView): @@ -1620,6 +1625,7 @@ class RearPortCreateView(ComponentCreateView): class RearPortEditView(ObjectEditView): queryset = RearPort.objects.all() model_form = forms.RearPortForm + template_name = 'dcim/device_component_edit.html' class RearPortDeleteView(ObjectDeleteView): @@ -1679,6 +1685,7 @@ class DeviceBayCreateView(ComponentCreateView): class DeviceBayEditView(ObjectEditView): queryset = DeviceBay.objects.all() model_form = forms.DeviceBayForm + template_name = 'dcim/device_component_edit.html' class DeviceBayDeleteView(ObjectDeleteView): diff --git a/netbox/templates/dcim/device_component_edit.html b/netbox/templates/dcim/device_component_edit.html new file mode 100644 index 000000000..e0f1a2326 --- /dev/null +++ b/netbox/templates/dcim/device_component_edit.html @@ -0,0 +1,16 @@ +{% extends 'utilities/obj_edit.html' %} +{% load form_helpers %} + +{% block form_fields %} + {% if form.instance.device %} +
    + + +
    + {% endif %} + {% render_form form %} +{% endblock %} diff --git a/netbox/templates/dcim/interface_edit.html b/netbox/templates/dcim/interface_edit.html index eaffe2bca..7a5c99905 100644 --- a/netbox/templates/dcim/interface_edit.html +++ b/netbox/templates/dcim/interface_edit.html @@ -5,6 +5,16 @@
    Interface
    + {% if form.instance.device %} +
    + + +
    + {% endif %} {% render_field form.name %} {% render_field form.label %} {% render_field form.type %} @@ -14,6 +24,11 @@ {% render_field form.mtu %} {% render_field form.mgmt_only %} {% render_field form.description %} +
    +
    +
    +
    802.1Q Switching
    +
    {% render_field form.mode %} {% render_field form.untagged_vlan %} {% render_field form.tagged_vlans %} diff --git a/netbox/templates/utilities/obj_edit.html b/netbox/templates/utilities/obj_edit.html index 5230b2594..0bd051161 100644 --- a/netbox/templates/utilities/obj_edit.html +++ b/netbox/templates/utilities/obj_edit.html @@ -31,7 +31,9 @@
    {{ obj_type|capfirst }}
    - {% render_form form %} + {% block form_fields %} + {% render_form form %} + {% endblock %}
    {% endblock %} diff --git a/netbox/templates/virtualization/virtualmachine_component_add.html b/netbox/templates/virtualization/virtualmachine_component_add.html index aafefffa1..11b120ee0 100644 --- a/netbox/templates/virtualization/virtualmachine_component_add.html +++ b/netbox/templates/virtualization/virtualmachine_component_add.html @@ -2,7 +2,7 @@ {% load helpers %} {% load form_helpers %} -{% block title %}Create {{ component_type }} ({{ parent }}){% endblock %} +{% block title %}Create {{ component_type }}{% endblock %} {% block content %}
    diff --git a/netbox/templates/virtualization/vminterface_edit.html b/netbox/templates/virtualization/vminterface_edit.html index 6b0313284..12018ba5d 100644 --- a/netbox/templates/virtualization/vminterface_edit.html +++ b/netbox/templates/virtualization/vminterface_edit.html @@ -5,14 +5,34 @@
    Interface
    + {% if form.instance.virtual_machine %} +
    + + +
    + {% endif %} {% render_field form.name %} {% render_field form.enabled %} {% render_field form.mac_address %} {% render_field form.mtu %} {% render_field form.description %} +
    +
    +
    +
    802.1Q Switching
    +
    {% render_field form.mode %} {% render_field form.untagged_vlan %} {% render_field form.tagged_vlans %} +
    +
    +
    +
    Tags
    +
    {% render_field form.tags %}
    From 5f9e687c9cda136d4f08a92172bd41fa2b1dddbc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:45:23 -0400 Subject: [PATCH 38/65] Release v2.9.3 --- docs/release-notes/version-2.9.md | 2 +- netbox/netbox/settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 09456ae14..ef5c4326c 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -1,6 +1,6 @@ # NetBox v2.9 -## v2.9.3 (FUTURE) +## v2.9.3 (2020-09-04) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index bfffe7135..c48db1493 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.9.3-dev' +VERSION = '2.9.3' # Hostname HOSTNAME = platform.node() From 08b9eedcec42e4c95c0de7d5d6f4c9659d6ddd0f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:46:39 -0400 Subject: [PATCH 39/65] Correct changelog for #5095 --- docs/release-notes/version-2.9.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index ef5c4326c..a3d500094 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -21,7 +21,7 @@ * [#5089](https://github.com/netbox-community/netbox/issues/5089) - Redirect to device view after editing component * [#5090](https://github.com/netbox-community/netbox/issues/5090) - Fix status display for console/power/interface connections * [#5091](https://github.com/netbox-community/netbox/issues/5091) - Avoid KeyError when handling invalid table preferences -* [#5095](https://github.com/netbox-community/netbox/issues/5095) - Avoid KeyError when handling invalid table preferences +* [#5095](https://github.com/netbox-community/netbox/issues/5095) - Show assigned prefixes in VLANs list --- From 0c8d45f679806b21939f60700a8a70d47064ef0e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:57:28 -0400 Subject: [PATCH 40/65] Post-release version bump --- 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 c48db1493..8a8c47c75 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.9.3' +VERSION = '2.9.4-dev' # Hostname HOSTNAME = platform.node() From 695e9ec5d7ce3915cf6caf8f4131b5dc1d116747 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 09:52:57 -0400 Subject: [PATCH 41/65] Fixes #5111: Allow use of tuples when specifying ObjectVar query_params --- docs/release-notes/version-2.9.md | 8 ++++++++ netbox/utilities/forms/widgets.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index a3d500094..3d68b10ba 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -1,5 +1,13 @@ # NetBox v2.9 +## v2.9.4 (FUTURE) + +### Bug Fixes + +* [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params` + +--- + ## v2.9.3 (2020-09-04) ### Enhancements diff --git a/netbox/utilities/forms/widgets.py b/netbox/utilities/forms/widgets.py index 9996f7d11..cd6fb0fbb 100644 --- a/netbox/utilities/forms/widgets.py +++ b/netbox/utilities/forms/widgets.py @@ -141,7 +141,7 @@ class APISelect(SelectWithDisabled): key = f'data-query-param-{name}' values = json.loads(self.attrs.get(key, '[]')) - if type(value) is list: + if type(value) in (list, tuple): values.extend([str(v) for v in value]) else: values.append(str(value)) From 150965046269b5d0f2145f7bf8447ba2e35e6ed1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 10:00:50 -0400 Subject: [PATCH 42/65] Closes #5107: Add note about dropping backward compatibility for old REDIS configuration format --- docs/release-notes/version-2.9.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 3d68b10ba..dbafa21ac 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -129,6 +129,7 @@ Two new REST API endpoints have been added to facilitate the retrieval and manip * If using NetBox's built-in remote authentication backend, update `REMOTE_AUTH_BACKEND` to `'netbox.authentication.RemoteUserBackend'`, as the authentication class has moved. * If using LDAP authentication, set `REMOTE_AUTH_BACKEND` to `'netbox.authentication.LDAPBackend'`. (LDAP configuration parameters in `ldap_config.py` remain unchanged.) * `REMOTE_AUTH_DEFAULT_PERMISSIONS` now takes a dictionary rather than a list. This is a mapping of permission names to a dictionary of constraining attributes, or `None`. For example, `['dcim.add_site', 'dcim.change_site']` would become `{'dcim.add_site': None, 'dcim.change_site': None}`. +* Backward compatibility for the old `webhooks` Redis queue name has been dropped. Ensure that your `REDIS` configuration parameter specifies both the `tasks` and `caching` databases. ### REST API Changes From c891f43b144c82e8d7891b57ca113d5f8f1f156a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 10:29:17 -0400 Subject: [PATCH 43/65] Fixes #5050: Fix potential failure on 0016_replicate_interfaces schema migration from old release --- docs/release-notes/version-2.9.md | 1 + netbox/virtualization/migrations/0016_replicate_interfaces.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index dbafa21ac..a38e945f6 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -4,6 +4,7 @@ ### Bug Fixes +* [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params` --- diff --git a/netbox/virtualization/migrations/0016_replicate_interfaces.py b/netbox/virtualization/migrations/0016_replicate_interfaces.py index a9c474083..585f5b80c 100644 --- a/netbox/virtualization/migrations/0016_replicate_interfaces.py +++ b/netbox/virtualization/migrations/0016_replicate_interfaces.py @@ -83,6 +83,7 @@ def replicate_interfaces(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ + ('dcim', '0082_3569_interface_fields'), ('ipam', '0037_ipaddress_assignment'), ('virtualization', '0015_vminterface'), ] From 47a6fc19cab1a3f53f80855e1f6fa9288fc8cbaf Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 11:47:21 -0400 Subject: [PATCH 44/65] Fixes #5109: Fix representation of custom choice field values for webhook data --- docs/release-notes/version-2.9.md | 1 + netbox/extras/api/customfields.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index a38e945f6..19789149b 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -5,6 +5,7 @@ ### Bug Fixes * [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release +* [#5109](https://github.com/netbox-community/netbox/issues/5109) - Fix representation of custom choice field values for webhook data * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params` --- diff --git a/netbox/extras/api/customfields.py b/netbox/extras/api/customfields.py index f096fb4a6..ba59e529a 100644 --- a/netbox/extras/api/customfields.py +++ b/netbox/extras/api/customfields.py @@ -158,7 +158,7 @@ class CustomFieldModelSerializer(ValidatedModelSerializer): instance.custom_fields = {} for field in custom_fields: value = instance.cf.get(field.name) - if field.type == CustomFieldTypeChoices.TYPE_SELECT and value: + if field.type == CustomFieldTypeChoices.TYPE_SELECT and type(value) is CustomFieldChoice: instance.custom_fields[field.name] = CustomFieldChoiceSerializer(value).data else: instance.custom_fields[field.name] = value From 4466458076b4cfd1b3d97a234d7f34ef9e191e8c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 13:43:10 -0400 Subject: [PATCH 45/65] Fixes #5118: Specifying an empty list of tags should clear assigned tags (REST API) --- docs/release-notes/version-2.9.md | 1 + netbox/extras/api/serializers.py | 16 +++++++++++----- netbox/extras/tests/test_tags.py | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 19789149b..33f372f47 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -7,6 +7,7 @@ * [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release * [#5109](https://github.com/netbox-community/netbox/issues/5109) - Fix representation of custom choice field values for webhook data * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params` +* [#5118](https://github.com/netbox-community/netbox/issues/5118) - Specifying an empty list of tags should clear assigned tags (REST API) --- diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index aa8f6ba69..3cc2d1991 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -101,24 +101,30 @@ class TaggedObjectSerializer(serializers.Serializer): tags = NestedTagSerializer(many=True, required=False) def create(self, validated_data): - tags = validated_data.pop('tags', []) + tags = validated_data.pop('tags', None) instance = super().create(validated_data) - return self._save_tags(instance, tags) + if tags is not None: + return self._save_tags(instance, tags) + return instance def update(self, instance, validated_data): - tags = validated_data.pop('tags', []) + tags = validated_data.pop('tags', None) # Cache tags on instance for change logging - instance._tags = tags + instance._tags = tags or [] instance = super().update(instance, validated_data) - return self._save_tags(instance, tags) + if tags is not None: + return self._save_tags(instance, tags) + return instance def _save_tags(self, instance, tags): if tags: instance.tags.set(*[t.name for t in tags]) + else: + instance.tags.clear() return instance diff --git a/netbox/extras/tests/test_tags.py b/netbox/extras/tests/test_tags.py index 694cd77d9..39aae49dc 100644 --- a/netbox/extras/tests/test_tags.py +++ b/netbox/extras/tests/test_tags.py @@ -59,3 +59,21 @@ class TaggedItemTest(APITestCase): sorted([t.name for t in site.tags.all()]), sorted(["Foo", "Bar", "New Tag"]) ) + + def test_clear_tagged_item(self): + site = Site.objects.create( + name='Test Site', + slug='test-site' + ) + site.tags.add("Foo", "Bar", "Baz") + data = { + 'tags': [] + } + self.add_permissions('dcim.change_site') + url = reverse('dcim-api:site-detail', kwargs={'pk': site.pk}) + + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + self.assertEqual(len(response.data['tags']), 0) + site = Site.objects.get(pk=response.data['id']) + self.assertEqual(len(site.tags.all()), 0) From c5e82a389545ae5516577e452ddd9cb32fc0a185 Mon Sep 17 00:00:00 2001 From: John Anderson Date: Thu, 10 Sep 2020 17:43:41 -0400 Subject: [PATCH 46/65] fixes #5108 - correct the runreport management command to work with JobResults model --- .../extras/management/commands/runreport.py | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/netbox/extras/management/commands/runreport.py b/netbox/extras/management/commands/runreport.py index efc789021..b751118e0 100644 --- a/netbox/extras/management/commands/runreport.py +++ b/netbox/extras/management/commands/runreport.py @@ -1,7 +1,12 @@ +import time + +from django.contrib.contenttypes.models import ContentType from django.core.management.base import BaseCommand from django.utils import timezone -from extras.reports import get_reports +from extras.choices import JobResultStatusChoices +from extras.models import JobResult +from extras.reports import get_reports, run_report class Command(BaseCommand): @@ -24,11 +29,29 @@ class Command(BaseCommand): self.stdout.write( "[{:%H:%M:%S}] Running {}...".format(timezone.now(), report.full_name) ) - report.run() + + report_content_type = ContentType.objects.get(app_label='extras', model='report') + job_result = JobResult.enqueue_job( + run_report, + report.full_name, + report_content_type, + None + ) + + # Wait on the job to finish + while job_result.status not in JobResultStatusChoices.TERMINAL_STATE_CHOICES: + time.sleep(1) + job_result = JobResult.objects.get(pk=job_result.pk) # Report on success/failure - status = self.style.ERROR('FAILED') if report.failed else self.style.SUCCESS('SUCCESS') - for test_name, attrs in report.result.data.items(): + if job_result.status == JobResultStatusChoices.STATUS_FAILED: + status = self.style.ERROR('FAILED') + elif job_result == JobResultStatusChoices.STATUS_ERRORED: + status = self.style.ERROR('ERRORED') + else: + status = self.style.SUCCESS('SUCCESS') + + for test_name, attrs in job_result.data.items(): self.stdout.write( "\t{}: {} success, {} info, {} warning, {} failure".format( test_name, attrs['success'], attrs['info'], attrs['warning'], attrs['failure'] @@ -37,6 +60,9 @@ class Command(BaseCommand): self.stdout.write( "[{:%H:%M:%S}] {}: {}".format(timezone.now(), report.full_name, status) ) + self.stdout.write( + "[{:%H:%M:%S}] {}: Duration {}".format(timezone.now(), report.full_name, job_result.duration) + ) # Wrap things up self.stdout.write( From b1b63513e79d6b253492edbadab5e92c217f4e41 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 14 Sep 2020 10:41:04 -0400 Subject: [PATCH 47/65] Changelog for #5108 --- docs/release-notes/version-2.9.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 33f372f47..d469e4c0f 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -6,6 +6,7 @@ * [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release * [#5109](https://github.com/netbox-community/netbox/issues/5109) - Fix representation of custom choice field values for webhook data +* [#5108](https://github.com/netbox-community/netbox/issues/5108) - Fix execution of reports via CLI * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params` * [#5118](https://github.com/netbox-community/netbox/issues/5118) - Specifying an empty list of tags should clear assigned tags (REST API) From df6ad680ce300733157cb100f7627d45b1cb4db4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 14 Sep 2020 14:22:21 -0400 Subject: [PATCH 48/65] Closes #1755: Toggle order in which rack elevations are displayed --- docs/release-notes/version-2.9.md | 4 ++++ netbox/dcim/views.py | 6 ++++++ netbox/templates/dcim/rack_elevation_list.html | 12 +++++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index d469e4c0f..093dc34a7 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -2,6 +2,10 @@ ## v2.9.4 (FUTURE) +### Enhancements + +* [#1755](https://github.com/netbox-community/netbox/issues/1755) - Toggle order in which rack elevations are displayed + ### Bug Fixes * [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 9f4dcc90e..ab84ba64b 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -310,6 +310,11 @@ class RackElevationListView(ObjectListView): racks = filters.RackFilterSet(request.GET, self.queryset).qs total_count = racks.count() + # Determine ordering + reverse = bool(request.GET.get('reverse', False)) + if reverse: + racks = racks.reverse() + # Pagination per_page = request.GET.get('per_page', settings.PAGINATE_COUNT) page_number = request.GET.get('page', 1) @@ -330,6 +335,7 @@ class RackElevationListView(ObjectListView): 'paginator': paginator, 'page': page, 'total_count': total_count, + 'reverse': reverse, 'rack_face': rack_face, 'filter_form': forms.RackElevationFilterForm(request.GET), }) diff --git a/netbox/templates/dcim/rack_elevation_list.html b/netbox/templates/dcim/rack_elevation_list.html index e4949eb17..c39bcae75 100644 --- a/netbox/templates/dcim/rack_elevation_list.html +++ b/netbox/templates/dcim/rack_elevation_list.html @@ -3,12 +3,18 @@ {% load static %} {% block content %} -
    +

    {% block title %}Rack Elevations{% endblock %}

    From 03b207d1542e8ede4fd29035bb41b640f4d018d9 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 16 Sep 2020 11:10:30 -0400 Subject: [PATCH 49/65] Fixes #5105: Validation should fail when reassigning a primary IP from device to VM --- docs/release-notes/version-2.9.md | 1 + netbox/ipam/forms.py | 13 ++++--------- netbox/ipam/models.py | 22 +++++----------------- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 093dc34a7..6d4f56ed8 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -9,6 +9,7 @@ ### Bug Fixes * [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release +* [#5105](https://github.com/netbox-community/netbox/issues/5105) - Validation should fail when reassigning a primary IP from device to VM * [#5109](https://github.com/netbox-community/netbox/issues/5109) - Fix representation of custom choice field values for webhook data * [#5108](https://github.com/netbox-community/netbox/issues/5108) - Fix execution of reports via CLI * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params` diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 1e8e9038a..75a4caf10 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -641,11 +641,11 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel self.initial['primary_for_parent'] = True def clean(self): - super().clean() # Cannot select both a device interface and a VM interface if self.cleaned_data.get('interface') and self.cleaned_data.get('vminterface'): raise forms.ValidationError("Cannot select both a device interface and a virtual machine interface") + self.instance.assigned_object = self.cleaned_data.get('interface') or self.cleaned_data.get('vminterface') # Primary IP assignment is only available if an interface has been assigned. interface = self.cleaned_data.get('interface') or self.cleaned_data.get('vminterface') @@ -655,26 +655,21 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel ) def save(self, *args, **kwargs): - - # Set assigned object - interface = self.cleaned_data.get('interface') or self.cleaned_data.get('vminterface') - if interface: - self.instance.assigned_object = interface - ipaddress = super().save(*args, **kwargs) # Assign/clear this IPAddress as the primary for the associated Device/VirtualMachine. + interface = self.instance.assigned_object if interface and self.cleaned_data['primary_for_parent']: if ipaddress.address.version == 4: interface.parent.primary_ip4 = ipaddress else: - interface.primary_ip6 = ipaddress + interface.parent.primary_ip6 = ipaddress interface.parent.save() elif interface and ipaddress.address.version == 4 and interface.parent.primary_ip4 == ipaddress: interface.parent.primary_ip4 = None interface.parent.save() elif interface and ipaddress.address.version == 6 and interface.parent.primary_ip6 == ipaddress: - interface.parent.primary_ip4 = None + interface.parent.primary_ip6 = None interface.parent.save() return ipaddress diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 832e09330..c7955bcfa 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -726,30 +726,18 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): }) # Check for primary IP assignment that doesn't match the assigned device/VM - if self.pk and type(self.assigned_object) is Interface: + if self.pk: device = Device.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first() if device: - if self.assigned_object is None: + if getattr(self.assigned_object, 'device', None) != device: raise ValidationError({ - 'interface': f"IP address is primary for device {device} but not assigned to an interface" + 'interface': f"IP address is primary for device {device} but not assigned to it!" }) - elif self.assigned_object.device != device: - raise ValidationError({ - 'interface': f"IP address is primary for device {device} but assigned to " - f"{self.assigned_object.device} ({self.assigned_object})" - }) - elif self.pk and type(self.assigned_object) is VMInterface: vm = VirtualMachine.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first() if vm: - if self.assigned_object is None: + if getattr(self.assigned_object, 'virtual_machine', None) != vm: raise ValidationError({ - 'vminterface': f"IP address is primary for virtual machine {vm} but not assigned to an " - f"interface" - }) - elif self.assigned_object.virtual_machine != vm: - raise ValidationError({ - 'vminterface': f"IP address is primary for virtual machine {vm} but assigned to " - f"{self.assigned_object.virtual_machine} ({self.assigned_object})" + 'vminterface': f"IP address is primary for virtual machine {vm} but not assigned to it!" }) # Validate IP status selection From 9d30712fb26503092e2ecd261c348f908213580b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 16 Sep 2020 11:20:00 -0400 Subject: [PATCH 50/65] Changelog for #5133 (fixed in #5105) --- docs/release-notes/version-2.9.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 6d4f56ed8..55c66cb6a 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -14,6 +14,7 @@ * [#5108](https://github.com/netbox-community/netbox/issues/5108) - Fix execution of reports via CLI * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params` * [#5118](https://github.com/netbox-community/netbox/issues/5118) - Specifying an empty list of tags should clear assigned tags (REST API) +* [#5133](https://github.com/netbox-community/netbox/issues/5133) - Fix disassociation of an IP address from a VM interface --- From 4d9da4a1f8c261e4aa6dae04a3cbcfb20a443c1f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 16 Sep 2020 12:44:49 -0400 Subject: [PATCH 51/65] Closes #5134: Display full hierarchy in breadcrumbs for sites/racks --- docs/release-notes/version-2.9.md | 1 + netbox/templates/dcim/device.html | 15 +++++++-------- netbox/templates/dcim/rack.html | 11 ++++++++++- netbox/templates/dcim/site.html | 4 ++-- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 55c66cb6a..fd7a99ff0 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -5,6 +5,7 @@ ### Enhancements * [#1755](https://github.com/netbox-community/netbox/issues/1755) - Toggle order in which rack elevations are displayed +* [#5134](https://github.com/netbox-community/netbox/issues/5134) - Display full hierarchy in breadcrumbs for sites/racks ### Bug Fixes diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index e97893c30..34d28179b 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -11,11 +11,8 @@
    @@ -87,7 +93,10 @@ Group {% if rack.group %} - {{ rack.group }} + {% for group in rack.group.get_ancestors %} + {{ group }} + {% endfor %} + {{ rack.group }} {% else %} None {% endif %} diff --git a/netbox/templates/dcim/site.html b/netbox/templates/dcim/site.html index d6c21bf92..f5823f721 100644 --- a/netbox/templates/dcim/site.html +++ b/netbox/templates/dcim/site.html @@ -12,7 +12,7 @@