From a5e1088f1f6961e6f5e87ffcdaeceb56b3b5e988 Mon Sep 17 00:00:00 2001 From: John Anderson Date: Thu, 18 Apr 2019 14:37:58 -0400 Subject: [PATCH 01/18] fixes #2621 - deletion issue in the changelog middleware --- CHANGELOG.md | 8 ++++++++ requirements.txt | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a19bc9870..634dd883b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +2.5.11 (FUTURE) + +## Bug Fixes + +* [#2621](https://github.com/digitalocean/netbox/issues/2621) - Upgrade Django requirement to 2.2 to fix object deletion issue in the changelog middleware + +--- + v2.5.10 (2019-04-08) ## Enhancements diff --git a/requirements.txt b/requirements.txt index f65328ecd..db95df5d1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django>=2.1.5,<2.2 +Django>=2,2,<2.3 django-cors-headers==2.4.0 django-debug-toolbar==1.11 django-filter==2.0.0 From 8b75969d1db28ad326fd4d295278eb9ae20985bb Mon Sep 17 00:00:00 2001 From: John Anderson Date: Thu, 18 Apr 2019 14:39:12 -0400 Subject: [PATCH 02/18] fix typo in requirements --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index db95df5d1..0bc96db8d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django>=2,2,<2.3 +Django>=2.2,<2.3 django-cors-headers==2.4.0 django-debug-toolbar==1.11 django-filter==2.0.0 From f4aec1e7d067108fb903be806f056a8493774d64 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 22 Apr 2019 07:47:16 -0400 Subject: [PATCH 03/18] Change VLAN view columns to a 4/8 split --- netbox/templates/ipam/vlan.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netbox/templates/ipam/vlan.html b/netbox/templates/ipam/vlan.html index 7798bf9e0..aa5869e5e 100644 --- a/netbox/templates/ipam/vlan.html +++ b/netbox/templates/ipam/vlan.html @@ -59,7 +59,7 @@ {% block content %}
-
+
VLAN @@ -136,7 +136,7 @@ {% include 'inc/custom_fields_panel.html' with obj=vlan %} {% include 'extras/inc/tags_panel.html' with tags=vlan.tags.all url='ipam:vlan_list' %}
-
+
Prefixes From f4636537ad72f8d776982eddc3090856e082467b Mon Sep 17 00:00:00 2001 From: rclerc Date: Wed, 24 Apr 2019 09:14:29 +0200 Subject: [PATCH 04/18] Add the decommissioning status for devices --- netbox/dcim/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index af2547bc4..578b1016d 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -318,6 +318,7 @@ DEVICE_STATUS_PLANNED = 2 DEVICE_STATUS_STAGED = 3 DEVICE_STATUS_FAILED = 4 DEVICE_STATUS_INVENTORY = 5 +DEVICE_STATUS_DECOMMISSIONING = 6 DEVICE_STATUS_CHOICES = [ [DEVICE_STATUS_ACTIVE, 'Active'], [DEVICE_STATUS_OFFLINE, 'Offline'], @@ -325,6 +326,7 @@ DEVICE_STATUS_CHOICES = [ [DEVICE_STATUS_STAGED, 'Staged'], [DEVICE_STATUS_FAILED, 'Failed'], [DEVICE_STATUS_INVENTORY, 'Inventory'], + [DEVICE_STATUS_DECOMMISSIONING, 'Decommissioning'], ] # Site statuses From 19d2850b2981c119efea8c5df9938e19d90f1b49 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 26 Apr 2019 16:41:01 -0400 Subject: [PATCH 05/18] Fixes #3112: Fix ordering of interface connections list by termination B name/device --- CHANGELOG.md | 1 + netbox/dcim/tables.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 634dd883b..5cabd9608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Bug Fixes * [#2621](https://github.com/digitalocean/netbox/issues/2621) - Upgrade Django requirement to 2.2 to fix object deletion issue in the changelog middleware +* [#3112](https://github.com/digitalocean/netbox/issues/3112) - Fix ordering of interface connections list by termination B name/device --- diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index dd1f4f5f1..a36b11e65 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -733,18 +733,18 @@ class InterfaceConnectionTable(BaseTable): ) device_b = tables.LinkColumn( viewname='dcim:device', - accessor=Accessor('connected_endpoint.device'), - args=[Accessor('connected_endpoint.device.pk')], + accessor=Accessor('_connected_interface.device'), + args=[Accessor('_connected_interface.device.pk')], verbose_name='Device B' ) interface_b = tables.LinkColumn( viewname='dcim:interface', - accessor=Accessor('connected_endpoint.name'), - args=[Accessor('connected_endpoint.pk')], + accessor=Accessor('_connected_interface'), + args=[Accessor('_connected_interface.pk')], verbose_name='Interface B' ) description_b = tables.Column( - accessor=Accessor('connected_endpoint.description'), + accessor=Accessor('_connected_interface.description'), verbose_name='Description' ) From d8c9b1af270c6bed70e47c7731238e3c22585862 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 26 Apr 2019 16:54:13 -0400 Subject: [PATCH 06/18] Fixes #3116: Fix tagged_items count in tags API endpoint --- CHANGELOG.md | 1 + netbox/extras/api/views.py | 4 +++- netbox/extras/views.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cabd9608..8d79d3492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * [#2621](https://github.com/digitalocean/netbox/issues/2621) - Upgrade Django requirement to 2.2 to fix object deletion issue in the changelog middleware * [#3112](https://github.com/digitalocean/netbox/issues/3112) - Fix ordering of interface connections list by termination B name/device +* [#3116](https://github.com/digitalocean/netbox/issues/3116) - Fix `tagged_items` count in tags API endpoint --- diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 30ef826e8..2150cb5b5 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -116,7 +116,9 @@ class TopologyMapViewSet(ModelViewSet): # class TagViewSet(ModelViewSet): - queryset = Tag.objects.annotate(tagged_items=Count('taggit_taggeditem_items')) + queryset = Tag.objects.annotate( + tagged_items=Count('taggit_taggeditem_items', distinct=True) + ) serializer_class = serializers.TagSerializer filterset_class = filters.TagFilter diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 713143af8..2f088eb77 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -30,7 +30,7 @@ from .tables import ConfigContextTable, ObjectChangeTable, TagTable, TaggedItemT class TagListView(ObjectListView): queryset = Tag.objects.annotate( - items=Count('taggit_taggeditem_items') + items=Count('taggit_taggeditem_items', distinct=True) ).order_by( 'name' ) From ca56871aaaa7afd5a28b029fc2172850303ccc5f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 26 Apr 2019 17:06:54 -0400 Subject: [PATCH 07/18] Changelog & CSS fix for #3070 --- CHANGELOG.md | 4 ++++ netbox/dcim/constants.py | 1 + 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d79d3492..5e4a2abb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ 2.5.11 (FUTURE) +## Enhancements + +* [#3070](https://github.com/digitalocean/netbox/issues/3070) - Add decommissioning status for devices + ## Bug Fixes * [#2621](https://github.com/digitalocean/netbox/issues/2621) - Upgrade Django requirement to 2.2 to fix object deletion issue in the changelog middleware diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 578b1016d..926b97130 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -347,6 +347,7 @@ STATUS_CLASSES = { 3: 'primary', 4: 'danger', 5: 'default', + 6: 'warning', } # Console/power/interface connection statuses From 245a97176a3b0c9ac89e994af70bcf06aef2436e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 26 Apr 2019 22:23:28 -0400 Subject: [PATCH 08/18] Closes #2986: Replace DeviceComponentManager with NaturalOrderingManager --- CHANGELOG.md | 1 + netbox/dcim/managers.py | 16 ---------------- netbox/dcim/models.py | 30 +++++++++++++++--------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e4a2abb9..e7cdcd33c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Enhancements +* [#2986](https://github.com/digitalocean/netbox/issues/2986) - Improve natural ordering of device components * [#3070](https://github.com/digitalocean/netbox/issues/3070) - Add decommissioning status for devices ## Bug Fixes diff --git a/netbox/dcim/managers.py b/netbox/dcim/managers.py index 9e4e5fca2..53f627a5b 100644 --- a/netbox/dcim/managers.py +++ b/netbox/dcim/managers.py @@ -14,22 +14,6 @@ CHANNEL_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^.*:(\d{{1,9}})(\.\d{{1,9}})?$') VC_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^.*\.(\d{{1,9}})$') AS integer), 0)" -class DeviceComponentManager(Manager): - - def get_queryset(self): - - queryset = super().get_queryset() - table_name = self.model._meta.db_table - sql = r"CONCAT(REGEXP_REPLACE({}.name, '\d+$', ''), LPAD(SUBSTRING({}.name FROM '\d+$'), 8, '0'))" - - # Pad any trailing digits to effect natural sorting - return queryset.extra( - select={ - 'name_padded': sql.format(table_name, table_name), - } - ).order_by('name_padded', 'pk') - - class InterfaceQuerySet(QuerySet): def connectable(self): diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 004d7b1aa..0b27e3110 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -23,7 +23,7 @@ from utilities.utils import serialize_object, to_meters from .constants import * from .exceptions import LoopDetected from .fields import ASNField, MACAddressField -from .managers import DeviceComponentManager, InterfaceManager +from .managers import InterfaceManager class ComponentTemplateModel(models.Model): @@ -1004,7 +1004,7 @@ class ConsolePortTemplate(ComponentTemplateModel): max_length=50 ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() class Meta: ordering = ['device_type', 'name'] @@ -1027,7 +1027,7 @@ class ConsoleServerPortTemplate(ComponentTemplateModel): max_length=50 ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() class Meta: ordering = ['device_type', 'name'] @@ -1050,7 +1050,7 @@ class PowerPortTemplate(ComponentTemplateModel): max_length=50 ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() class Meta: ordering = ['device_type', 'name'] @@ -1073,7 +1073,7 @@ class PowerOutletTemplate(ComponentTemplateModel): max_length=50 ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() class Meta: ordering = ['device_type', 'name'] @@ -1139,7 +1139,7 @@ class FrontPortTemplate(ComponentTemplateModel): validators=[MinValueValidator(1), MaxValueValidator(64)] ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() class Meta: ordering = ['device_type', 'name'] @@ -1188,7 +1188,7 @@ class RearPortTemplate(ComponentTemplateModel): validators=[MinValueValidator(1), MaxValueValidator(64)] ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() class Meta: ordering = ['device_type', 'name'] @@ -1211,7 +1211,7 @@ class DeviceBayTemplate(ComponentTemplateModel): max_length=50 ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() class Meta: ordering = ['device_type', 'name'] @@ -1742,7 +1742,7 @@ class ConsolePort(CableTermination, ComponentModel): blank=True ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = ['device', 'name'] @@ -1785,7 +1785,7 @@ class ConsoleServerPort(CableTermination, ComponentModel): blank=True ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = ['device', 'name'] @@ -1834,7 +1834,7 @@ class PowerPort(CableTermination, ComponentModel): blank=True ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = ['device', 'name'] @@ -1877,7 +1877,7 @@ class PowerOutlet(CableTermination, ComponentModel): blank=True ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = ['device', 'name'] @@ -2198,7 +2198,7 @@ class FrontPort(CableTermination, ComponentModel): blank=True ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = ['device', 'name', 'type', 'rear_port', 'rear_port_position', 'description'] @@ -2264,7 +2264,7 @@ class RearPort(CableTermination, ComponentModel): blank=True ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = ['device', 'name', 'type', 'positions', 'description'] @@ -2311,7 +2311,7 @@ class DeviceBay(ComponentModel): null=True ) - objects = DeviceComponentManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = ['device', 'name', 'installed_device'] From 6d778f686d67beb8b9239b1a94a618cb03e8dae4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 29 Apr 2019 10:07:08 -0400 Subject: [PATCH 09/18] Closes #3023: Add support for filtering cables by connected device --- CHANGELOG.md | 1 + netbox/dcim/filters.py | 20 ++++++++++++++++++++ netbox/dcim/models.py | 15 +++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7cdcd33c..a365a37c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Enhancements * [#2986](https://github.com/digitalocean/netbox/issues/2986) - Improve natural ordering of device components +* [#3023](https://github.com/digitalocean/netbox/issues/3023) - Add support for filtering cables by connected device * [#3070](https://github.com/digitalocean/netbox/issues/3070) - Add decommissioning status for devices ## Bug Fixes diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index dda904f1c..7c190176b 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -1,5 +1,7 @@ import django_filters from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist from django.db.models import Q from netaddr import EUI from netaddr.core import AddrFormatError @@ -967,6 +969,14 @@ class CableFilter(django_filters.FilterSet): color = django_filters.MultipleChoiceFilter( choices=COLOR_CHOICES ) + device = django_filters.CharFilter( + method='filter_connected_device', + field_name='name' + ) + device_id = django_filters.CharFilter( + method='filter_connected_device', + field_name='pk' + ) class Meta: model = Cable @@ -977,6 +987,16 @@ class CableFilter(django_filters.FilterSet): return queryset return queryset.filter(label__icontains=value) + def filter_connected_device(self, queryset, name, value): + if not value.strip(): + return queryset + try: + device = Device.objects.get(**{name: value}) + except ObjectDoesNotExist: + return queryset.none() + cable_pks = device.get_cables(pk_list=True) + return queryset.filter(pk__in=cable_pks) + class ConsoleConnectionFilter(django_filters.FilterSet): site = django_filters.CharFilter( diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 0b27e3110..f8e8a028e 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -1704,6 +1704,21 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): filter |= Q(device__virtual_chassis=self.virtual_chassis, mgmt_only=False) return Interface.objects.filter(filter) + def get_cables(self, pk_list=False): + """ + Return a QuerySet or PK list matching all Cables connected to a component of this Device. + """ + cable_pks = [] + for component_model in [ + ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, FrontPort, RearPort + ]: + cable_pks += component_model.objects.filter( + device=self, cable__isnull=False + ).values_list('cable', flat=True) + if pk_list: + return cable_pks + return Cable.objects.filter(pk__in=cable_pks) + def get_children(self): """ Return the set of child Devices installed in DeviceBays within this Device. From 3562b5552bfdc22a52f43763696865ddab942b67 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 29 Apr 2019 11:04:32 -0400 Subject: [PATCH 10/18] Fixes #3118: Disable last_login update on login when maintenance mode is enabled --- CHANGELOG.md | 1 + netbox/users/views.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a365a37c2..2ecdcd652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [#2621](https://github.com/digitalocean/netbox/issues/2621) - Upgrade Django requirement to 2.2 to fix object deletion issue in the changelog middleware * [#3112](https://github.com/digitalocean/netbox/issues/3112) - Fix ordering of interface connections list by termination B name/device * [#3116](https://github.com/digitalocean/netbox/issues/3116) - Fix `tagged_items` count in tags API endpoint +* [#3118](https://github.com/digitalocean/netbox/issues/3118) - Disable `last_login` update on login when maintenance mode is enabled --- diff --git a/netbox/users/views.py b/netbox/users/views.py index 6ec984936..0ff4a8049 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -1,7 +1,10 @@ +from django.conf import settings from django.contrib import messages from django.contrib.auth import login as auth_login, logout as auth_logout, update_session_auth_hash from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin +from django.contrib.auth.models import update_last_login +from django.contrib.auth.signals import user_logged_in from django.http import HttpResponseForbidden, HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse @@ -44,6 +47,11 @@ class LoginView(View): if not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()): 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: + user_logged_in.disconnect(update_last_login, dispatch_uid='update_last_login') + # Authenticate user auth_login(request, form.get_user()) messages.info(request, "Logged in as {}.".format(request.user)) From 39fceeb45569ab0fe68039e346ed82be22b2c99d Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 29 Apr 2019 11:29:07 -0400 Subject: [PATCH 11/18] Add device field on cable search form (#3023) --- netbox/dcim/forms.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index c81564b0c..71ad45409 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2766,6 +2766,10 @@ class CableFilterForm(BootstrapMixin, forms.Form): required=False, widget=ColorSelect() ) + device = forms.CharField( + required=False, + label='Device name' + ) # From 14912226426de00f8b3c4d2ad2a4097fef18a3a5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 29 Apr 2019 12:54:03 -0400 Subject: [PATCH 12/18] Fixes #3072: Preserve multiselect filter values when updating per-page count for list views --- CHANGELOG.md | 1 + netbox/templates/inc/paginator.html | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ecdcd652..bd7aaa31c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ## Bug Fixes * [#2621](https://github.com/digitalocean/netbox/issues/2621) - Upgrade Django requirement to 2.2 to fix object deletion issue in the changelog middleware +* [#3072](https://github.com/digitalocean/netbox/issues/3072) - Preserve multiselect filter values when updating per-page count for list views * [#3112](https://github.com/digitalocean/netbox/issues/3112) - Fix ordering of interface connections list by termination B name/device * [#3116](https://github.com/digitalocean/netbox/issues/3116) - Fix `tagged_items` count in tags API endpoint * [#3118](https://github.com/digitalocean/netbox/issues/3118) - Disable `last_login` update on login when maintenance mode is enabled diff --git a/netbox/templates/inc/paginator.html b/netbox/templates/inc/paginator.html index ac4648988..fe9177f87 100644 --- a/netbox/templates/inc/paginator.html +++ b/netbox/templates/inc/paginator.html @@ -20,9 +20,11 @@
- {% for k, v in request.GET.items %} + {% for k, v_list in request.GET.lists %} {% if k != 'per_page' %} - + {% for v in v_list %} + + {% endfor %} {% endif %} {% endfor %}