From ffdd31e9d00419dde7e658da7d24cb6c4732a03c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Aug 2020 12:58:48 -0400 Subject: [PATCH 01/73] Closes #4991: Add Python and NetBox versions to error page --- docs/release-notes/version-2.9.md | 8 ++++++++ netbox/templates/500.html | 5 ++++- netbox/utilities/views.py | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index cc38fdb5e..8bee68e8a 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.1 (FUTURE) + +### Enhancements + +* [#4991](https://github.com/netbox-community/netbox/issues/4991) - Add Python and NetBox versions to error page + +--- + ## v2.9.0 (2020-08-21) ### New Features diff --git a/netbox/templates/500.html b/netbox/templates/500.html index bd59b7233..61115cbab 100644 --- a/netbox/templates/500.html +++ b/netbox/templates/500.html @@ -31,7 +31,10 @@ The complete exception is provided below:

{{ exception }}
-{{ error }}
+{{ error }} + +Python version: {{ python_version }} +NetBox version: {{ netbox_version }}

If further assistance is required, please post to the NetBox mailing list.

diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index c7db2f649..079068648 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -1,8 +1,10 @@ import logging +import platform import re import sys from copy import deepcopy +from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import login_required from django.contrib.contenttypes.models import ContentType @@ -1421,6 +1423,8 @@ def server_error(request, template_name=ERROR_500_TEMPLATE_NAME): type_, error, traceback = sys.exc_info() return HttpResponseServerError(template.render({ + 'python_version': platform.python_version(), + 'netbox_version': settings.VERSION, 'exception': str(type_), 'error': error, })) From 53de24110cd759ca5cafcfffa0a7686f956f415a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Aug 2020 13:17:41 -0400 Subject: [PATCH 02/73] Closes #4540: Add IP address status type for SLAAC --- docs/models/ipam/ipaddress.md | 1 + docs/release-notes/version-2.9.md | 1 + netbox/ipam/choices.py | 2 ++ 3 files changed, 4 insertions(+) diff --git a/docs/models/ipam/ipaddress.md b/docs/models/ipam/ipaddress.md index 04ac417db..1ea613997 100644 --- a/docs/models/ipam/ipaddress.md +++ b/docs/models/ipam/ipaddress.md @@ -10,6 +10,7 @@ Each IP address can also be assigned an operational status and a functional role * Reserved * Deprecated * DHCP +* SLAAC (IPv6 Stateless Address Autoconfiguration) Roles are used to indicate some special attribute of an IP address; for example, use as a loopback or as the the virtual IP for a VRRP group. (Note that functional roles are conceptual in nature, and thus cannot be customized by the user.) Available roles include: diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 8bee68e8a..74095a7fe 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -4,6 +4,7 @@ ### Enhancements +* [#4540](https://github.com/netbox-community/netbox/issues/4540) - Add IP address status type for SLAAC * [#4991](https://github.com/netbox-community/netbox/issues/4991) - Add Python and NetBox versions to error page --- diff --git a/netbox/ipam/choices.py b/netbox/ipam/choices.py index 68fdfd9df..f3ff19ddc 100644 --- a/netbox/ipam/choices.py +++ b/netbox/ipam/choices.py @@ -41,12 +41,14 @@ class IPAddressStatusChoices(ChoiceSet): STATUS_RESERVED = 'reserved' STATUS_DEPRECATED = 'deprecated' STATUS_DHCP = 'dhcp' + STATUS_SLAAC = 'slaac' CHOICES = ( (STATUS_ACTIVE, 'Active'), (STATUS_RESERVED, 'Reserved'), (STATUS_DEPRECATED, 'Deprecated'), (STATUS_DHCP, 'DHCP'), + (STATUS_SLAAC, 'SLAAC'), ) From 65f94de68274e1fd1a9c253bbd6d8707f1a13a9b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Aug 2020 13:35:03 -0400 Subject: [PATCH 03/73] Closes #4814: Allow nested LAG interfaces --- docs/models/dcim/interface.md | 2 +- docs/release-notes/version-2.9.md | 1 + netbox/dcim/forms.py | 5 ++++- netbox/dcim/models/device_components.py | 16 +++++----------- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/models/dcim/interface.md b/docs/models/dcim/interface.md index be43ac2a6..756e320af 100644 --- a/docs/models/dcim/interface.md +++ b/docs/models/dcim/interface.md @@ -4,7 +4,7 @@ Interfaces in NetBox represent network interfaces used to exchange data with con Interfaces may be physical or virtual in nature, but only physical interfaces may be connected via cables. Cables can connect interfaces to pass-through ports, circuit terminations, or other interfaces. -Physical interfaces may be arranged into a link aggregation group (LAG) and associated with a parent LAG (virtual) interface. Like all virtual interfaces, LAG interfaces cannot be connected physically. +Physical interfaces may be arranged into a link aggregation group (LAG) and associated with a parent LAG (virtual) interface. LAG interfaces can be recursively nested to model bonding of trunk groups. Like all virtual interfaces, LAG interfaces cannot be connected physically. IP addresses can be assigned to interfaces. VLANs can also be assigned to each interface as either tagged or untagged. (An interface may have only one untagged VLAN.) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 74095a7fe..d42e35b92 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -5,6 +5,7 @@ ### Enhancements * [#4540](https://github.com/netbox-community/netbox/issues/4540) - Add IP address status type for SLAAC +* [#4814](https://github.com/netbox-community/netbox/issues/4814) - Allow nested LAG interfaces * [#4991](https://github.com/netbox-community/netbox/issues/4991) - Add Python and NetBox versions to error page --- diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 6dd5cb6bf..2b8bf4e9e 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2686,7 +2686,10 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): device_query = Q(device=device) if device.virtual_chassis: device_query |= Q(device__virtual_chassis=device.virtual_chassis) - self.fields['lag'].queryset = Interface.objects.filter(device_query, type=InterfaceTypeChoices.TYPE_LAG) + self.fields['lag'].queryset = Interface.objects.filter( + device_query, + type=InterfaceTypeChoices.TYPE_LAG + ).exclude(pk=self.instance.pk) # Add current site to VLANs query params self.fields['untagged_vlan'].widget.add_query_param('site_id', device.site.pk) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 92b0605e9..d7e077a16 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -702,18 +702,12 @@ class Interface(CableTermination, ComponentModel, BaseInterface): }) # A virtual interface cannot have a parent LAG - if self.type in NONCONNECTABLE_IFACE_TYPES and self.lag is not None: - raise ValidationError({ - 'lag': "{} interfaces cannot have a parent LAG interface.".format(self.get_type_display()) - }) + if self.type == InterfaceTypeChoices.TYPE_VIRTUAL and self.lag is not None: + raise ValidationError({'lag': "Virtual interfaces cannot have a parent LAG interface."}) - # Only a LAG can have LAG members - if self.type != InterfaceTypeChoices.TYPE_LAG and self.member_interfaces.exists(): - raise ValidationError({ - 'type': "Cannot change interface type; it has LAG members ({}).".format( - ", ".join([iface.name for iface in self.member_interfaces.all()]) - ) - }) + # A LAG interface cannot be its own parent + if self.pk and self.lag_id == self.pk: + raise ValidationError({'lag': "A LAG interface cannot be its own parent."}) # Validate untagged VLAN if self.untagged_vlan and self.untagged_vlan.site not in [self.parent.site, None]: From e1e8fb74e032ebb31c857966b7d496e82ac6f067 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Aug 2020 16:44:13 -0400 Subject: [PATCH 04/73] Add link to v2.9 release notes --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index a94aa3cc4..87962acc0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -76,6 +76,7 @@ nav: - User Preferences: 'development/user-preferences.md' - Release Checklist: 'development/release-checklist.md' - Release Notes: + - Version 2.9: 'release-notes/version-2.9.md' - Version 2.8: 'release-notes/version-2.8.md' - Version 2.7: 'release-notes/version-2.7.md' - Version 2.6: 'release-notes/version-2.6.md' From b95c6abcf974e46e7433a4c940d46816d66b0471 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sat, 22 Aug 2020 20:39:46 -0400 Subject: [PATCH 05/73] Closes #5033: Support backward compatibility for REMOTE_AUTH_BACKEND --- docs/release-notes/version-2.9.md | 4 +++- netbox/netbox/settings.py | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index d42e35b92..07b989588 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -7,6 +7,7 @@ * [#4540](https://github.com/netbox-community/netbox/issues/4540) - Add IP address status type for SLAAC * [#4814](https://github.com/netbox-community/netbox/issues/4814) - Allow nested LAG interfaces * [#4991](https://github.com/netbox-community/netbox/issues/4991) - Add Python and NetBox versions to error page +* [#5033](https://github.com/netbox-community/netbox/issues/5033) - Support backward compatibility for `REMOTE_AUTH_BACKEND` configuration parameter --- @@ -66,7 +67,8 @@ Two new REST API endpoints have been added to facilitate the retrieval and manip ### Configuration Changes -* If in use, LDAP authentication must be enabled by setting `REMOTE_AUTH_BACKEND` to `'netbox.authentication.LDAPBackend'`. (LDAP configuration parameters in `ldap_config.py` remain unchanged.) +* 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}`. ### REST API Changes diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index fd50f6b5a..e4ab844d0 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -142,6 +142,13 @@ if type(REMOTE_AUTH_DEFAULT_PERMISSIONS) is not dict: ) except TypeError: raise ImproperlyConfigured("REMOTE_AUTH_DEFAULT_PERMISSIONS must be a dictionary.") +# Backward compatibility for REMOTE_AUTH_BACKEND +if REMOTE_AUTH_BACKEND == 'utilities.auth_backends.RemoteUserBackend': + warnings.warn( + "RemoteUserBackend has moved! Please update your configuration to:\n" + " REMOTE_AUTH_BACKEND='netbox.authentication.RemoteUserBackend'" + ) + REMOTE_AUTH_BACKEND = 'netbox.authentication.RemoteUserBackend' # From c9210924097105adba5720bf405e503596ad1d71 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sat, 22 Aug 2020 20:53:21 -0400 Subject: [PATCH 06/73] Closes #5030: Call out required minimum versions for depdencies in upgrade documentation --- docs/installation/upgrading.md | 11 +++++++++-- docs/release-notes/version-2.9.md | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/installation/upgrading.md b/docs/installation/upgrading.md index 807b9b1e6..34274342c 100644 --- a/docs/installation/upgrading.md +++ b/docs/installation/upgrading.md @@ -4,8 +4,15 @@ Prior to upgrading your NetBox instance, be sure to carefully review all [release notes](../../release-notes/) that have been published since your current version was released. Although the upgrade process typically does not involve additional work, certain releases may introduce breaking or backward-incompatible changes. These are called out in the release notes under the version in which the change went into effect. -!!! note - Beginning with version 2.8, NetBox requires Python 3.6 or later. +## Update Dependencies to Required Versions + +NetBox v2.9.0 and later requires the following: + +| Dependency | Minimum Version | +|------------|-----------------| +| Python | 3.6 | +| PostgreSQL | 9.6 | +| Redis | 4.0 | ## Install the Latest Code diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 07b989588..a02bcf3ea 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -13,6 +13,8 @@ ## v2.9.0 (2020-08-21) +**Note:** Redis 4.0 or later is required for this release. + ### New Features #### Object-Based Permissions ([#554](https://github.com/netbox-community/netbox/issues/554)) From 10d053099c72e9a76988719b79be20d6f30a8a9c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sat, 22 Aug 2020 21:03:51 -0400 Subject: [PATCH 07/73] Release v2.9.1 --- 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 a02bcf3ea..549067b13 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.1 (FUTURE) +## v2.9.1 (2020-08-22) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index e4ab844d0..74cfcbd83 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-dev' +VERSION = '2.9.1' # Hostname HOSTNAME = platform.node() From a1e56acc9cd15c31c6bf21491c34459e12dfc4d3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sat, 22 Aug 2020 21:06:06 -0400 Subject: [PATCH 08/73] 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 bf50bd034dd690d75586a68d7c79415e49f7d994 Mon Sep 17 00:00:00 2001 From: Joakim Bakke Hellum Date: Sun, 23 Aug 2020 20:49:50 +0200 Subject: [PATCH 09/73] 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 9f18617627883fc7264779f6c599332e6aadf691 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 09:41:04 -0400 Subject: [PATCH 10/73] 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 035e509e913e8d5afeb98b649428390f0ca4be04 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:39:41 -0400 Subject: [PATCH 11/73] 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 f359e8087aed3762a51a5ff00ba550030935490e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:47:26 -0400 Subject: [PATCH 12/73] 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 36128e3fb35a7c818a3a793526d9e4f7193caf8e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:51:47 -0400 Subject: [PATCH 13/73] 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 fe4a3849a7908bceb684dfad49a05161cfb9b121 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 10:56:23 -0400 Subject: [PATCH 14/73] 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 e2d4760d2c56ce784a3b2441b407512bfc7804fc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 11:33:45 -0400 Subject: [PATCH 15/73] 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 a9eeb7b451d39d5b79259c6181e8b6bf99c3ea0c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 12:04:48 -0400 Subject: [PATCH 16/73] 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 7d64dff8ad64c721e8f815161539de967659f0d1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 24 Aug 2020 15:17:36 -0400 Subject: [PATCH 17/73] 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 647292aded949de0d85460eea8a2ffae2786fcb9 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 09:22:53 -0400 Subject: [PATCH 18/73] 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 399cc885e3988e43dbcff870643cd1a12ff6141c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 09:26:56 -0400 Subject: [PATCH 19/73] 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 90266eabf9ece5aaf9b5c3f48bfc55e05e003a38 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 09:43:20 -0400 Subject: [PATCH 20/73] 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 ebf8785c51d43c38733432c53c6eca0fc8f607b4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 11:27:17 -0400 Subject: [PATCH 21/73] 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 60b7d1c2e5724b622646037ffae7ac4f0e1554c1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 13:26:41 -0400 Subject: [PATCH 22/73] 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 8da55316b01af4b6626cca8680321845f7a53a4e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 13:46:31 -0400 Subject: [PATCH 23/73] 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 57e97d2dd0f83e06b08f290e541af1733d5572d0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 14:03:51 -0400 Subject: [PATCH 24/73] 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 26d4be2f0437c5299577a8ea1c04ac247ae5e5ce Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Aug 2020 14:15:09 -0400 Subject: [PATCH 25/73] 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 dfb213c08d196ac4e24aab855a04324c37a7a6d0 Mon Sep 17 00:00:00 2001 From: Simeon Keske Date: Sun, 30 Aug 2020 01:44:27 +0200 Subject: [PATCH 26/73] 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 76f5fdebee6ec900dcb3773e178902ce30b33418 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 31 Aug 2020 15:26:00 -0400 Subject: [PATCH 27/73] 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 c01a9eb5b8bc1c785b40b0cac5a054080bba244a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 31 Aug 2020 15:34:40 -0400 Subject: [PATCH 28/73] 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 8d0d2caad83f3367286f97491706f9c6147b3e1f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 09:54:45 -0400 Subject: [PATCH 29/73] 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 d06836c0f8174abd65a0360796ebf6de91379dc3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 10:19:28 -0400 Subject: [PATCH 30/73] 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 8121e815af930eae303c022e9ee96527654adf31 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 10:24:17 -0400 Subject: [PATCH 31/73] 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 d3f34daeb2cd27e908363f212175c37139eb7999 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 13:59:50 -0400 Subject: [PATCH 32/73] 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 d07e2c816276c899e8608cc631b38c5d95cdb7db Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 15:18:47 -0400 Subject: [PATCH 33/73] 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 e88e92d219ce0c7322602b3fb07f6a7a07dfebb4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 1 Sep 2020 16:28:11 -0400 Subject: [PATCH 34/73] 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 12d091cc545d09478cce8907d3e4367eda9d3c45 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 10:21:22 -0400 Subject: [PATCH 35/73] 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 ee26b919d124a8bc8cad4924a6afb788189cc853 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 13:30:19 -0400 Subject: [PATCH 36/73] 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 89972531e7469bc7293f52f412ea45eee0c100e4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 13:33:59 -0400 Subject: [PATCH 37/73] 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 188cb3bce01eeee5d7c9e0fe33c95d6a4fcb4c68 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 13:45:15 -0400 Subject: [PATCH 38/73] 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 ac3a30b6ffac6bb410101e598da95b3814c3bd48 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 2 Sep 2020 16:10:07 -0400 Subject: [PATCH 39/73] 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 ea66f329f23977e33311d3b44e0afce50ce74f7e Mon Sep 17 00:00:00 2001 From: Simeon Keske Date: Wed, 2 Sep 2020 22:33:39 +0200 Subject: [PATCH 40/73] 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 553693d330e59b599ca419359b18b252f30627f8 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 3 Sep 2020 11:28:25 -0400 Subject: [PATCH 41/73] 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 becae1d4d7e02f1f73faf816833eff8c014e3535 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 13:57:29 -0400 Subject: [PATCH 42/73] 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 8b4d2b6df99f7239c716b53fb45cb76105b08506 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 14:13:35 -0400 Subject: [PATCH 43/73] 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 a1ac172db445ba364dae909776ba53019e775b14 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:10:34 -0400 Subject: [PATCH 44/73] 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 ff145413d10544929b4a50e136c3fba6aa66da50 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:45:23 -0400 Subject: [PATCH 45/73] 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 1f19a2b0c821265fad0cd203b7afc30fc634b202 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:46:39 -0400 Subject: [PATCH 46/73] 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 9a00478c0ea6758d6bdeda929aec71bbddec2d7b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Sep 2020 15:57:28 -0400 Subject: [PATCH 47/73] 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 6212b323d0493cd813d7a9b8b8494e094598920c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 09:52:57 -0400 Subject: [PATCH 48/73] 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 d466eebbe71ded9e77e513c5191743e490c3ede5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 10:00:50 -0400 Subject: [PATCH 49/73] 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 d43cd1e522226895a75dee2985dc496ea94aafdb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 10:29:17 -0400 Subject: [PATCH 50/73] 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 9d799b757ab543c17baab6312bda0c0349dbedd1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 11:47:21 -0400 Subject: [PATCH 51/73] 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 2bc7f74d3ffcc34297cc8776f172915996cc9cd2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 9 Sep 2020 13:43:10 -0400 Subject: [PATCH 52/73] 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 f276dd1d63c90eab85231c45596941082e74a64f Mon Sep 17 00:00:00 2001 From: John Anderson Date: Thu, 10 Sep 2020 17:43:41 -0400 Subject: [PATCH 53/73] 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 eda19628c3027b8c232de9e7d3419ae772777fa2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 14 Sep 2020 10:41:04 -0400 Subject: [PATCH 54/73] 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 43a440ce911f00a9199c51754a4a99774182bf8f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 14 Sep 2020 14:22:21 -0400 Subject: [PATCH 55/73] 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 b572ddb8d20ec4feca237c451465fb7473352e81 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 16 Sep 2020 11:10:30 -0400 Subject: [PATCH 56/73] 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 7f6a26cc3d51044d0514d2d8a862dd80ec64e45e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 16 Sep 2020 11:20:00 -0400 Subject: [PATCH 57/73] 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 1cf1d550d4b77e02ca41c4742e421f34230a6b98 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 16 Sep 2020 12:44:49 -0400 Subject: [PATCH 58/73] 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 @@