From 943728e1a7b3a23e23b4e91118b162ff782f5ac3 Mon Sep 17 00:00:00 2001 From: Jemikwa <5904385+Jemikwa@users.noreply.github.com> Date: Tue, 11 Dec 2018 11:45:45 -0600 Subject: [PATCH 01/21] Updating LDAP documentation Adding information on service restarts and logging LDAP queries for troubleshooting. --- docs/installation/4-ldap.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/installation/4-ldap.md b/docs/installation/4-ldap.md index 892df2bd5..0f4ba25f9 100644 --- a/docs/installation/4-ldap.md +++ b/docs/installation/4-ldap.md @@ -113,3 +113,21 @@ AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600 * `is_active` - All users must be mapped to at least this group to enable authentication. Without this, users cannot log in. * `is_staff` - Users mapped to this group are enabled for access to the administration tools; this is the equivalent of checking the "staff status" box on a manually created user. This doesn't grant any specific permissions. * `is_superuser` - Users mapped to this group will be granted superuser status. Superusers are implicitly granted all permissions. + +# Troubleshooting LDAP +`supervisorctl restart netbox` restarts the Netbox service, and initiates any changes made to `ldap_config.py`. If there are syntax errors present, the Netbox process will not spawn an instance, and errors should be logged to `/var/log/supervisor/`. + + +For troubleshooting LDAP user/group queries, add the following lines to the start of `ldap_config.py` after `import ldap`. + +```python +import logging, logging.handlers +logfile = "/opt/netbox/logs/django-ldap-debug.log" +my_logger = logging.getLogger('django_auth_ldap') +my_logger.setLevel(logging.DEBUG) +handler = logging.handlers.RotatingFileHandler( + logfile, maxBytes=1024 * 500, backupCount=5) +my_logger.addHandler(handler) +``` + +Ensure the file and path specified in logfile exist and are write and executable by the application service account. Restart the netbox service and attempt to log into the site to trigger log entries to this file. From 57a20eda1b98d59b1c8ec63dc528283a9a910d20 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 13 Dec 2018 15:24:13 -0500 Subject: [PATCH 02/21] 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 49c619962..cc18bf4c4 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -22,7 +22,7 @@ except ImportError: ) -VERSION = '2.5.1' +VERSION = '2.5.2-dev' BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) From 65b87c36a3eb8e0ee9f6c87682c23919322d6435 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 09:36:45 -0500 Subject: [PATCH 03/21] Fixes #2707: Correct permission evaluation for circuit termination cabling --- CHANGELOG.md | 8 ++++++++ netbox/templates/circuits/inc/circuit_termination.html | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02ca1bd7b..7ddf44d21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +v2.5.2 (FUTURE) + +## Bug Fixes + +* [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling + +--- + v2.5.1 (2018-12-13) ## Enhancements diff --git a/netbox/templates/circuits/inc/circuit_termination.html b/netbox/templates/circuits/inc/circuit_termination.html index a3cb09b25..a3ca77279 100644 --- a/netbox/templates/circuits/inc/circuit_termination.html +++ b/netbox/templates/circuits/inc/circuit_termination.html @@ -53,7 +53,7 @@ {{ termination.connected_endpoint }} {% endif %} {% else %} - {% if perms.circuits.add_cable %} + {% if perms.dcim.add_cable %}
Connect From db17980703ccd135c9b2981c16ca74f5aef2e4a4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 10:02:18 -0500 Subject: [PATCH 04/21] Closes #2701: Enable filtering of prefixes by exact prefix value --- CHANGELOG.md | 4 ++++ netbox/ipam/filters.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ddf44d21..9a93302b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ v2.5.2 (FUTURE) +## Enhancements + +* [#2701](https://github.com/digitalocean/netbox/issues/2701) - Enable filtering of prefixes by exact prefix value + ## Bug Fixes * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling diff --git a/netbox/ipam/filters.py b/netbox/ipam/filters.py index abef95c45..22df1b1c9 100644 --- a/netbox/ipam/filters.py +++ b/netbox/ipam/filters.py @@ -112,6 +112,10 @@ class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet): method='search', label='Search', ) + prefix = django_filters.CharFilter( + method='filter_prefix', + label='Prefix', + ) within = django_filters.CharFilter( method='search_within', label='Within prefix', @@ -197,6 +201,15 @@ class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet): pass return queryset.filter(qs_filter) + def filter_prefix(self, queryset, name, value): + if not value.strip(): + return queryset + try: + query = str(netaddr.IPNetwork(value).cidr) + return queryset.filter(prefix=query) + except ValidationError: + return queryset.none() + def search_within(self, queryset, name, value): value = value.strip() if not value: From 28cd5a22ec467ebcdebf6eed91390d99acee8de6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 10:59:12 -0500 Subject: [PATCH 05/21] Fixes #2698: Remove pagination restriction on bulk component creation for devices/VMs --- CHANGELOG.md | 1 + netbox/dcim/views.py | 6 ++++++ .../templates/utilities/obj_bulk_add_component.html | 5 +++-- netbox/utilities/views.py | 12 ++++++++---- netbox/virtualization/views.py | 1 + 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a93302b0..2e191d934 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ v2.5.2 (FUTURE) ## Bug Fixes +* [#2698](https://github.com/digitalocean/netbox/issues/2698) - Remove pagination restriction on bulk component creation for devices/VMs * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling --- diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 632b58d23..1d74c1c85 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1530,6 +1530,7 @@ class DeviceBulkAddConsolePortView(PermissionRequiredMixin, BulkComponentCreateV form = forms.DeviceBulkAddComponentForm model = ConsolePort model_form = forms.ConsolePortForm + filter = filters.DeviceFilter table = tables.DeviceTable default_return_url = 'dcim:device_list' @@ -1541,6 +1542,7 @@ class DeviceBulkAddConsoleServerPortView(PermissionRequiredMixin, BulkComponentC form = forms.DeviceBulkAddComponentForm model = ConsoleServerPort model_form = forms.ConsoleServerPortForm + filter = filters.DeviceFilter table = tables.DeviceTable default_return_url = 'dcim:device_list' @@ -1552,6 +1554,7 @@ class DeviceBulkAddPowerPortView(PermissionRequiredMixin, BulkComponentCreateVie form = forms.DeviceBulkAddComponentForm model = PowerPort model_form = forms.PowerPortForm + filter = filters.DeviceFilter table = tables.DeviceTable default_return_url = 'dcim:device_list' @@ -1563,6 +1566,7 @@ class DeviceBulkAddPowerOutletView(PermissionRequiredMixin, BulkComponentCreateV form = forms.DeviceBulkAddComponentForm model = PowerOutlet model_form = forms.PowerOutletForm + filter = filters.DeviceFilter table = tables.DeviceTable default_return_url = 'dcim:device_list' @@ -1574,6 +1578,7 @@ class DeviceBulkAddInterfaceView(PermissionRequiredMixin, BulkComponentCreateVie form = forms.DeviceBulkAddInterfaceForm model = Interface model_form = forms.InterfaceForm + filter = filters.DeviceFilter table = tables.DeviceTable default_return_url = 'dcim:device_list' @@ -1585,6 +1590,7 @@ class DeviceBulkAddDeviceBayView(PermissionRequiredMixin, BulkComponentCreateVie form = forms.DeviceBulkAddComponentForm model = DeviceBay model_form = forms.DeviceBayForm + filter = filters.DeviceFilter table = tables.DeviceTable default_return_url = 'dcim:device_list' diff --git a/netbox/templates/utilities/obj_bulk_add_component.html b/netbox/templates/utilities/obj_bulk_add_component.html index 93c7060a4..fb9fb0418 100644 --- a/netbox/templates/utilities/obj_bulk_add_component.html +++ b/netbox/templates/utilities/obj_bulk_add_component.html @@ -2,7 +2,8 @@ {% load form_helpers %} {% block content %} -

Add {{ component_name|title }}

+

{% block title %}Add {{ model_name|title }}{% endblock %}

+

{{ table.rows|length }} {{ parent_model_name }} selected

{% csrf_token %} {% if request.POST.return_url %} @@ -27,7 +28,7 @@
{% endif %}
-
{{ component_name|title }} to Add
+
{{ model_name|title }} to Add
{% for field in form.visible_fields %} {% render_field field %} diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index ee13533bc..8838873de 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -789,9 +789,12 @@ class BulkComponentCreateView(GetReturnURLMixin, View): def post(self, request): + parent_model_name = self.parent_model._meta.verbose_name_plural + model_name = self.model._meta.verbose_name_plural + # Are we editing *all* objects in the queryset or just a selected subset? if request.POST.get('_all') and self.filter is not None: - pk_list = [obj.pk for obj in self.filter(request.GET, self.model.objects.only('pk')).qs] + pk_list = [obj.pk for obj in self.filter(request.GET, self.parent_model.objects.only('pk')).qs] else: pk_list = [int(pk) for pk in request.POST.getlist('pk')] @@ -829,9 +832,9 @@ class BulkComponentCreateView(GetReturnURLMixin, View): messages.success(request, "Added {} {} to {} {}.".format( len(new_components), - self.model._meta.verbose_name_plural, + model_name, len(form.cleaned_data['pk']), - self.parent_model._meta.verbose_name_plural + parent_model_name )) return redirect(self.get_return_url(request)) @@ -840,7 +843,8 @@ class BulkComponentCreateView(GetReturnURLMixin, View): return render(request, self.template_name, { 'form': form, - 'component_name': self.model._meta.verbose_name_plural, + 'parent_model_name': parent_model_name, + 'model_name': model_name, 'table': table, 'return_url': self.get_return_url(request), }) diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index b578cf455..aa8a585a9 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -369,5 +369,6 @@ class VirtualMachineBulkAddInterfaceView(PermissionRequiredMixin, BulkComponentC form = forms.VirtualMachineBulkAddInterfaceForm model = Interface model_form = forms.InterfaceForm + filter = filters.VirtualMachineFilter table = tables.VirtualMachineTable default_return_url = 'virtualization:virtualmachine_list' From 3fdeec2840cb18d060d3e067bffd9c61250d59c6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 12:17:40 -0500 Subject: [PATCH 06/21] Introduced fgcolor template filter to render ideal foreground color for any background color --- netbox/dcim/tables.py | 3 ++- netbox/utilities/templatetags/helpers.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index 0c88852f0..0ab1d594c 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -29,7 +29,8 @@ SITE_REGION_LINK = """ """ COLOR_LABEL = """ - +{% load helpers %} + """ DEVICE_LINK = """ diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index e7bc40846..11fa789ec 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -1,11 +1,13 @@ import datetime import json +import re from django import template from django.utils.safestring import mark_safe from markdown import markdown from utilities.forms import unpack_grouped_choices +from utilities.utils import foreground_color register = template.Library() @@ -152,6 +154,17 @@ def tzoffset(value): return datetime.datetime.now(value).strftime('%z') +@register.filter() +def fgcolor(value): + """ + Return black (#000000) or white (#ffffff) given an arbitrary background color in RRGGBB format. + """ + value = value.lower().strip('#') + if not re.match('^[0-9a-f]{6}$', value): + return '' + return '#{}'.format(foreground_color(value)) + + # # Tags # From 3716d78ee05fe29e40821f02d3588902d28dbdd0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 12:48:20 -0500 Subject: [PATCH 07/21] Fixes #2691: Cable trace should follow circuits --- CHANGELOG.md | 1 + netbox/dcim/api/views.py | 2 +- netbox/dcim/models.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e191d934..c4f051062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ v2.5.2 (FUTURE) ## Bug Fixes +* [#2691](https://github.com/digitalocean/netbox/issues/2691) - Cable trace should follow circuits * [#2698](https://github.com/digitalocean/netbox/issues/2698) - Remove pagination restriction on bulk component creation for devices/VMs * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 7e0179171..1b6e54580 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -60,7 +60,7 @@ class CableTraceMixin(object): # Initialize the path array path = [] - for near_end, cable, far_end in obj.trace(): + for near_end, cable, far_end in obj.trace(follow_circuits=True): # Serialize each object serializer_a = get_serializer_for_model(near_end, prefix='Nested') diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 756ae9be2..4dcd5f278 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -140,7 +140,7 @@ class CableTermination(models.Model): if peer_port is None: return path - next_segment = peer_port.trace(position) + next_segment = peer_port.trace(position, follow_circuits) if next_segment is None: return path + [(peer_port, None, None)] From d4cb07b61511df0556e10aed01b29d80f6fb2496 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 14:04:22 -0500 Subject: [PATCH 08/21] Fixes #2673: Fix exception on LLDP neighbors view for device with a circuit connected --- CHANGELOG.md | 1 + netbox/templates/dcim/device_lldp_neighbors.html | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4f051062..b192da35b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ v2.5.2 (FUTURE) ## Bug Fixes +* [#2673](https://github.com/digitalocean/netbox/issues/2673) - Fix exception on LLDP neighbors view for device with a circuit connected * [#2691](https://github.com/digitalocean/netbox/issues/2691) - Cable trace should follow circuits * [#2698](https://github.com/digitalocean/netbox/issues/2698) - Remove pagination restriction on bulk component creation for devices/VMs * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling diff --git a/netbox/templates/dcim/device_lldp_neighbors.html b/netbox/templates/dcim/device_lldp_neighbors.html index 78ec017ec..d2bba9562 100644 --- a/netbox/templates/dcim/device_lldp_neighbors.html +++ b/netbox/templates/dcim/device_lldp_neighbors.html @@ -22,13 +22,20 @@ {% for iface in interfaces %} {{ iface }} - {% if iface.connected_endpoint %} + {% if iface.connected_endpoint.device %} {{ iface.connected_endpoint.device }} {{ iface.connected_endpoint }} + {% elif iface.connected_endpoint.circuit %} + {% with circuit=iface.connected_endpoint.circuit %} + + + {{ circuit.provider }} {{ circuit }} + + {% endwith %} {% else %} None {% endif %} From 932468554d42985080e06233cfba3a31048516f0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 14:15:22 -0500 Subject: [PATCH 09/21] #2675: Added InventoryItem search form field for 'discovered' --- netbox/dcim/forms.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 86da72a88..2bb72afc1 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2703,6 +2703,12 @@ class InventoryItemFilterForm(BootstrapMixin, forms.Form): to_field_name='slug', null_label='-- None --' ) + discovered = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ) + ) # From e3fd34fb074e6709a4cf7e44d0bdd47a734dabbb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 16:13:04 -0500 Subject: [PATCH 10/21] Closes #2561: Add 200G and 400G interface types --- CHANGELOG.md | 1 + netbox/dcim/constants.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b192da35b..f41c4fe83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ v2.5.2 (FUTURE) ## Enhancements +* [#2561](https://github.com/digitalocean/netbox/issues/2561) - Add 200G and 400G interface types * [#2701](https://github.com/digitalocean/netbox/issues/2701) - Enable filtering of prefixes by exact prefix value ## Bug Fixes diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 8e5e09a26..8b3731cb1 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -82,6 +82,9 @@ IFACE_FF_100GE_CFP2 = 1510 IFACE_FF_100GE_CFP4 = 1520 IFACE_FF_100GE_CPAK = 1550 IFACE_FF_100GE_QSFP28 = 1600 +IFACE_FF_200GE_CFP2 = 1650 +IFACE_FF_200GE_QSFP28_DD = 1700 +IFACE_FF_400GE_QSFP56_DD = 1750 # Wireless IFACE_FF_80211A = 2600 IFACE_FF_80211G = 2610 @@ -153,9 +156,12 @@ IFACE_FF_CHOICES = [ [IFACE_FF_40GE_QSFP_PLUS, 'QSFP+ (40GE)'], [IFACE_FF_100GE_CFP, 'CFP (100GE)'], [IFACE_FF_100GE_CFP2, 'CFP2 (100GE)'], + [IFACE_FF_200GE_CFP2, 'CFP2 (200GE)'], [IFACE_FF_100GE_CFP4, 'CFP4 (100GE)'], [IFACE_FF_100GE_CPAK, 'Cisco CPAK (100GE)'], [IFACE_FF_100GE_QSFP28, 'QSFP28 (100GE)'], + [IFACE_FF_200GE_QSFP28_DD, 'QSFP28-DD (200GE)'], + [IFACE_FF_400GE_QSFP56_DD, 'QSFP56-DD (400GE)'], ] ], [ From 6b32d67b9a21325098b8b14cbf026ee7f32ad49c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 16:24:41 -0500 Subject: [PATCH 11/21] Closes #2537: Added AUTH_LDAP_MIRROR_GROUPS setting to LDAP docs --- docs/installation/4-ldap.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/installation/4-ldap.md b/docs/installation/4-ldap.md index 892df2bd5..0c1e4533c 100644 --- a/docs/installation/4-ldap.md +++ b/docs/installation/4-ldap.md @@ -95,6 +95,9 @@ AUTH_LDAP_GROUP_TYPE = GroupOfNamesType() # Define a group required to login. AUTH_LDAP_REQUIRE_GROUP = "CN=NETBOX_USERS,DC=example,DC=com" +# Mirror LDAP group assignments. +AUTH_LDAP_MIRROR_GROUPS = True + # Define special user types using groups. Exercise great caution when assigning superuser status. AUTH_LDAP_USER_FLAGS_BY_GROUP = { "is_active": "cn=active,ou=groups,dc=example,dc=com", From ebb5b60ab00f077cefde9015df59d3bc3f439240 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 19 Dec 2018 16:34:35 -0500 Subject: [PATCH 12/21] Fixes #2709: Update example report for compatibility with v2.5 --- docs/additional-features/reports.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/additional-features/reports.md b/docs/additional-features/reports.md index 234766639..2c73850eb 100644 --- a/docs/additional-features/reports.md +++ b/docs/additional-features/reports.md @@ -44,7 +44,7 @@ class DeviceConnectionsReport(Report): # Check that every console port for every active device has a connection defined. for console_port in ConsolePort.objects.select_related('device').filter(device__status=DEVICE_STATUS_ACTIVE): - if console_port.cs_port is None: + if console_port.connected_endpoint is None: self.log_failure( console_port.device, "No console connection defined for {}".format(console_port.name) @@ -63,7 +63,7 @@ class DeviceConnectionsReport(Report): for device in Device.objects.filter(status=DEVICE_STATUS_ACTIVE): connected_ports = 0 for power_port in PowerPort.objects.filter(device=device): - if power_port.power_outlet is not None: + if power_port.connected_endpoint is not None: connected_ports += 1 if power_port.connection_status == CONNECTION_STATUS_PLANNED: self.log_warning( From 576090e99ff1334e9dba1863decdf84b5ee8c7b2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 20 Dec 2018 09:18:18 -0500 Subject: [PATCH 13/21] Tweaked 200GE and 400GE interface type labels --- netbox/dcim/constants.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 8b3731cb1..ecb5f7b8d 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -83,8 +83,8 @@ IFACE_FF_100GE_CFP4 = 1520 IFACE_FF_100GE_CPAK = 1550 IFACE_FF_100GE_QSFP28 = 1600 IFACE_FF_200GE_CFP2 = 1650 -IFACE_FF_200GE_QSFP28_DD = 1700 -IFACE_FF_400GE_QSFP56_DD = 1750 +IFACE_FF_200GE_QSFP56 = 1700 +IFACE_FF_400GE_QSFP_DD = 1750 # Wireless IFACE_FF_80211A = 2600 IFACE_FF_80211G = 2610 @@ -160,8 +160,8 @@ IFACE_FF_CHOICES = [ [IFACE_FF_100GE_CFP4, 'CFP4 (100GE)'], [IFACE_FF_100GE_CPAK, 'Cisco CPAK (100GE)'], [IFACE_FF_100GE_QSFP28, 'QSFP28 (100GE)'], - [IFACE_FF_200GE_QSFP28_DD, 'QSFP28-DD (200GE)'], - [IFACE_FF_400GE_QSFP56_DD, 'QSFP56-DD (400GE)'], + [IFACE_FF_200GE_QSFP56, 'QSFP56 (200GE)'], + [IFACE_FF_400GE_QSFP_DD, 'QSFP-DD (400GE)'], ] ], [ From 9408e50eb4c9541c0a4a38cb956a7bf2628d3713 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 20 Dec 2018 09:54:59 -0500 Subject: [PATCH 14/21] Minor tweaks --- docs/installation/4-ldap.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation/4-ldap.md b/docs/installation/4-ldap.md index 766dbfb57..32623439a 100644 --- a/docs/installation/4-ldap.md +++ b/docs/installation/4-ldap.md @@ -118,8 +118,8 @@ AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600 * `is_superuser` - Users mapped to this group will be granted superuser status. Superusers are implicitly granted all permissions. # Troubleshooting LDAP -`supervisorctl restart netbox` restarts the Netbox service, and initiates any changes made to `ldap_config.py`. If there are syntax errors present, the Netbox process will not spawn an instance, and errors should be logged to `/var/log/supervisor/`. +`supervisorctl restart netbox` restarts the Netbox service, and initiates any changes made to `ldap_config.py`. If there are syntax errors present, the NetBox process will not spawn an instance, and errors should be logged to `/var/log/supervisor/`. For troubleshooting LDAP user/group queries, add the following lines to the start of `ldap_config.py` after `import ldap`. @@ -133,4 +133,4 @@ handler = logging.handlers.RotatingFileHandler( my_logger.addHandler(handler) ``` -Ensure the file and path specified in logfile exist and are write and executable by the application service account. Restart the netbox service and attempt to log into the site to trigger log entries to this file. +Ensure the file and path specified in logfile exist and are writable and executable by the application service account. Restart the netbox service and attempt to log into the site to trigger log entries to this file. From 68446533b311014d374cb0c86039b0b3db4df42b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 20 Dec 2018 15:33:53 -0500 Subject: [PATCH 15/21] Fixes #2712: Preserve list filtering after editing objects in bulk --- CHANGELOG.md | 1 + netbox/utilities/views.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f41c4fe83..24722f326 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ v2.5.2 (FUTURE) * [#2691](https://github.com/digitalocean/netbox/issues/2691) - Cable trace should follow circuits * [#2698](https://github.com/digitalocean/netbox/issues/2698) - Remove pagination restriction on bulk component creation for devices/VMs * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling +* [#2712](https://github.com/digitalocean/netbox/issues/2712) - Preserve list filtering after editing objects in bulk --- diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 8838873de..f52f4ea9e 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -55,8 +55,9 @@ class GetReturnURLMixin(object): def get_return_url(self, request, obj=None): - # First, see if `return_url` was specified as a query parameter. Use it only if it's considered safe. - query_param = request.GET.get('return_url') + # First, see if `return_url` was specified as a query parameter or form data. Use this URL only if it's + # considered safe. + query_param = request.GET.get('return_url') or request.POST.get('return_url') if query_param and is_safe_url(url=query_param, allowed_hosts=request.get_host()): return query_param From a4db71e803d56b07c556c8bfe353b6a3fb8209fb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 20 Dec 2018 15:49:35 -0500 Subject: [PATCH 16/21] Fixes #2704: Fix form select widget population on parent with null value --- CHANGELOG.md | 1 + netbox/project-static/js/forms.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24722f326..8700deb0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ v2.5.2 (FUTURE) * [#2673](https://github.com/digitalocean/netbox/issues/2673) - Fix exception on LLDP neighbors view for device with a circuit connected * [#2691](https://github.com/digitalocean/netbox/issues/2691) - Cable trace should follow circuits * [#2698](https://github.com/digitalocean/netbox/issues/2698) - Remove pagination restriction on bulk component creation for devices/VMs +* [#2704](https://github.com/digitalocean/netbox/issues/2704) - Fix form select widget population on parent with null value * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling * [#2712](https://github.com/digitalocean/netbox/issues/2712) - Preserve list filtering after editing objects in bulk diff --git a/netbox/project-static/js/forms.js b/netbox/project-static/js/forms.js index 89bc3aee1..fa23f1592 100644 --- a/netbox/project-static/js/forms.js +++ b/netbox/project-static/js/forms.js @@ -100,7 +100,7 @@ $(document).ready(function() { } else if (filter_field.val()) { rendered_url = rendered_url.replace(match[0], filter_field.val()); } else if (filter_field.attr('nullable') == 'true') { - rendered_url = rendered_url.replace(match[0], '0'); + rendered_url = rendered_url.replace(match[0], 'null'); } } From 0812c52495449fcd21f65375f31b4482af97cea0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Dec 2018 09:08:00 -0500 Subject: [PATCH 17/21] Fixes #2717: Fix bulk deletion of tags --- CHANGELOG.md | 1 + netbox/extras/urls.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8700deb0a..5899590c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ v2.5.2 (FUTURE) * [#2704](https://github.com/digitalocean/netbox/issues/2704) - Fix form select widget population on parent with null value * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling * [#2712](https://github.com/digitalocean/netbox/issues/2712) - Preserve list filtering after editing objects in bulk +* [#2717](https://github.com/digitalocean/netbox/issues/2717) - Fix bulk deletion of tags --- diff --git a/netbox/extras/urls.py b/netbox/extras/urls.py index 12a2fbf6b..35a6fb110 100644 --- a/netbox/extras/urls.py +++ b/netbox/extras/urls.py @@ -7,19 +7,19 @@ urlpatterns = [ # Tags url(r'^tags/$', views.TagListView.as_view(), name='tag_list'), + url(r'^tags/delete/$', views.TagBulkDeleteView.as_view(), name='tag_bulk_delete'), url(r'^tags/(?P[\w-]+)/$', views.TagView.as_view(), name='tag'), url(r'^tags/(?P[\w-]+)/edit/$', views.TagEditView.as_view(), name='tag_edit'), url(r'^tags/(?P[\w-]+)/delete/$', views.TagDeleteView.as_view(), name='tag_delete'), - url(r'^tags/delete/$', views.TagBulkDeleteView.as_view(), name='tag_bulk_delete'), # Config contexts url(r'^config-contexts/$', views.ConfigContextListView.as_view(), name='configcontext_list'), url(r'^config-contexts/add/$', views.ConfigContextCreateView.as_view(), name='configcontext_add'), url(r'^config-contexts/edit/$', views.ConfigContextBulkEditView.as_view(), name='configcontext_bulk_edit'), + url(r'^config-contexts/delete/$', views.ConfigContextBulkDeleteView.as_view(), name='configcontext_bulk_delete'), url(r'^config-contexts/(?P\d+)/$', views.ConfigContextView.as_view(), name='configcontext'), url(r'^config-contexts/(?P\d+)/edit/$', views.ConfigContextEditView.as_view(), name='configcontext_edit'), url(r'^config-contexts/(?P\d+)/delete/$', views.ConfigContextDeleteView.as_view(), name='configcontext_delete'), - url(r'^config-contexts/delete/$', views.ConfigContextBulkDeleteView.as_view(), name='configcontext_bulk_delete'), # Image attachments url(r'^image-attachments/(?P\d+)/edit/$', views.ImageAttachmentEditView.as_view(), name='imageattachment_edit'), From 07557e9699dd191ebc119b9db39f6e0a1c4ff25d Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Dec 2018 09:11:07 -0500 Subject: [PATCH 18/21] Fixes #2723: Correct permission evaluation when bulk deleting tags --- CHANGELOG.md | 1 + netbox/extras/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5899590c1..5a02a1464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ v2.5.2 (FUTURE) * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling * [#2712](https://github.com/digitalocean/netbox/issues/2712) - Preserve list filtering after editing objects in bulk * [#2717](https://github.com/digitalocean/netbox/issues/2717) - Fix bulk deletion of tags +* [#2723](https://github.com/digitalocean/netbox/issues/2723) - Correct permission evaluation when bulk deleting tags --- diff --git a/netbox/extras/views.py b/netbox/extras/views.py index e7087e511..713143af8 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -82,7 +82,7 @@ class TagDeleteView(PermissionRequiredMixin, ObjectDeleteView): class TagBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): - permission_required = 'circuits.delete_circuittype' + permission_required = 'taggit.delete_tag' queryset = Tag.objects.annotate( items=Count('taggit_taggeditem_items') ).order_by( From 03fe71220abf14ce01bf96ebb7c134e05551a32b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Dec 2018 10:54:20 -0500 Subject: [PATCH 19/21] Fixes #2721: Detect loops when tracing front/rear ports --- CHANGELOG.md | 1 + netbox/dcim/exceptions.py | 5 +++++ netbox/dcim/models.py | 16 ++++++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 netbox/dcim/exceptions.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a02a1464..2c3730f1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ v2.5.2 (FUTURE) * [#2707](https://github.com/digitalocean/netbox/issues/2707) - Correct permission evaluation for circuit termination cabling * [#2712](https://github.com/digitalocean/netbox/issues/2712) - Preserve list filtering after editing objects in bulk * [#2717](https://github.com/digitalocean/netbox/issues/2717) - Fix bulk deletion of tags +* [#2721](https://github.com/digitalocean/netbox/issues/2721) - Detect loops when tracing front/rear ports * [#2723](https://github.com/digitalocean/netbox/issues/2723) - Correct permission evaluation when bulk deleting tags --- diff --git a/netbox/dcim/exceptions.py b/netbox/dcim/exceptions.py new file mode 100644 index 000000000..e788c9b5f --- /dev/null +++ b/netbox/dcim/exceptions.py @@ -0,0 +1,5 @@ +class LoopDetected(Exception): + """ + A loop has been detected while tracing a cable path. + """ + pass diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 4dcd5f278..347f0c8b8 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -21,6 +21,7 @@ from utilities.managers import NaturalOrderingManager from utilities.models import ChangeLoggedModel 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 @@ -88,7 +89,7 @@ class CableTermination(models.Model): class Meta: abstract = True - def trace(self, position=1, follow_circuits=False): + def trace(self, position=1, follow_circuits=False, cable_history=None): """ Return a list representing a complete cable path, with each individual segment represented as a three-tuple: [ @@ -133,6 +134,13 @@ class CableTermination(models.Model): if not self.cable: return [(self, None, None)] + # Record cable history to detect loops + if cable_history is None: + cable_history = [] + elif self.cable in cable_history: + raise LoopDetected() + cable_history.append(self.cable) + far_end = self.cable.termination_b if self.cable.termination_a == self else self.cable.termination_a path = [(self, self.cable, far_end)] @@ -140,7 +148,11 @@ class CableTermination(models.Model): if peer_port is None: return path - next_segment = peer_port.trace(position, follow_circuits) + try: + next_segment = peer_port.trace(position, follow_circuits, cable_history) + except LoopDetected: + return path + if next_segment is None: return path + [(peer_port, None, None)] From 07ce4b4a7af8e4e2e75a254dd9578fe3d5bc27aa Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Dec 2018 11:09:44 -0500 Subject: [PATCH 20/21] Fixes #2724: Limit rear port choices to current device when editing a front port --- CHANGELOG.md | 1 + netbox/dcim/forms.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c3730f1c..204fb0434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ v2.5.2 (FUTURE) * [#2717](https://github.com/digitalocean/netbox/issues/2717) - Fix bulk deletion of tags * [#2721](https://github.com/digitalocean/netbox/issues/2721) - Detect loops when tracing front/rear ports * [#2723](https://github.com/digitalocean/netbox/issues/2723) - Correct permission evaluation when bulk deleting tags +* [#2724](https://github.com/digitalocean/netbox/issues/2724) - Limit rear port choices to current device when editing a front port --- diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 2bb72afc1..d02235277 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2098,6 +2098,15 @@ class FrontPortForm(BootstrapMixin, forms.ModelForm): 'device': forms.HiddenInput(), } + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Limit RearPort choices to the local device + if hasattr(self.instance, 'device'): + self.fields['rear_port'].queryset = self.fields['rear_port'].queryset.filter( + device=self.instance.device + ) + # TODO: Merge with FrontPortTemplateCreateForm to remove duplicate logic class FrontPortCreateForm(ComponentForm): From d47f700a1dbe34a42dd0b277cbb4ba110accb65f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Dec 2018 11:44:30 -0500 Subject: [PATCH 21/21] Release v2.5.2 --- CHANGELOG.md | 2 +- netbox/netbox/settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 204fb0434..f1f5ee223 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -v2.5.2 (FUTURE) +v2.5.2 (2018-12-21) ## Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index cc18bf4c4..bd4574487 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -22,7 +22,7 @@ except ImportError: ) -VERSION = '2.5.2-dev' +VERSION = '2.5.2' BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))