diff --git a/CHANGELOG.md b/CHANGELOG.md index 32764a69a1..556740e783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 This changelog format was introduced in NAV 5.4.0. Older changelogs can be found in the [HISTORY](HISTORY) file. +## [Unreleased] + +### Fixed + +- Allow admins to configure ports with invalid or unset native VLANs in PortAdmin ([#2477](https://github.com/Uninett/nav/issues/2477), [#2786](https://github.com/Uninett/nav/pull/2786)) +- Fix bug that caused PoE config to be completely disabled for Cisco devices where at least one port did not support PoE ([#2781](https://github.com/Uninett/nav/pull/2781)) +- Fix PortAdmin save button moving around for ports without PoE support ([#2782](https://github.com/Uninett/nav/pull/2782)) +- Fix PortAdmin bug that prevented switching PoE state back and forth without reloading entire page ([#2785](https://github.com/Uninett/nav/pull/2785)) +- Fix regression that caused maintenance tasks to be un-editable ([#2783](https://github.com/Uninett/nav/issues/2783), [#2784](https://github.com/Uninett/nav/pull/2784)) + ## [5.8.3] - 2023-12-01 ### Fixed diff --git a/python/nav/portadmin/handlers.py b/python/nav/portadmin/handlers.py index 5a2e8816a1..7c74e559df 100644 --- a/python/nav/portadmin/handlers.py +++ b/python/nav/portadmin/handlers.py @@ -352,7 +352,3 @@ class POEStateNotSupportedError(ManagementError): class XMLParseError(ManagementError): """Raised when failing to parse XML""" - - -class POEIndexNotFoundError(ManagementError): - """Raised when a PoE index could not be found for an interface""" diff --git a/python/nav/portadmin/snmp/cisco.py b/python/nav/portadmin/snmp/cisco.py index bbe1a9d18e..d2f4fa5b0c 100644 --- a/python/nav/portadmin/snmp/cisco.py +++ b/python/nav/portadmin/snmp/cisco.py @@ -28,7 +28,6 @@ PoeState, POEStateNotSupportedError, POENotSupportedError, - POEIndexNotFoundError, ) from nav.models import manage @@ -351,7 +350,7 @@ def _get_poe_indexes_for_interface( try: poeport = manage.POEPort.objects.get(interface=interface) except manage.POEPort.DoesNotExist: - raise POEIndexNotFoundError( + raise POENotSupportedError( "This interface does not have PoE indexes defined" ) unit_number = poeport.poegroup.index diff --git a/python/nav/web/maintenance/views.py b/python/nav/web/maintenance/views.py index 7d4d653e9f..9eab84a44b 100644 --- a/python/nav/web/maintenance/views.py +++ b/python/nav/web/maintenance/views.py @@ -252,9 +252,7 @@ def cancel(request, task_id): def edit(request, task_id=None, start_time=None, **_): account = get_account(request) quickselect = QuickSelect(service=True) - component_trail = None - component_keys = None - task = None + component_trail = component_keys_errors = component_data = task = None if task_id: task = get_object_or_404(MaintenanceTask, pk=task_id) diff --git a/python/nav/web/portadmin/utils.py b/python/nav/web/portadmin/utils.py index 221b06e170..072054b6bd 100644 --- a/python/nav/web/portadmin/utils.py +++ b/python/nav/web/portadmin/utils.py @@ -15,7 +15,7 @@ # """Util functions for the PortAdmin""" from __future__ import unicode_literals -from typing import List, Sequence, Dict, Any +from typing import List, Sequence, Dict, Any, Optional import re import logging from operator import attrgetter @@ -24,6 +24,7 @@ from nav.models import manage, profiles from nav.django.utils import is_admin +from nav.models.profiles import Account from nav.portadmin.config import CONFIG from nav.portadmin.management import ManagementFactory from nav.portadmin.handlers import ManagementHandler @@ -76,7 +77,7 @@ def find_and_populate_allowed_vlans( ): """Finds allowed vlans and indicate which interfaces can be edited""" allowed_vlans = find_allowed_vlans_for_user_on_netbox(account, netbox, handler) - set_editable_flag_on_interfaces(interfaces, allowed_vlans) + set_editable_flag_on_interfaces(interfaces, allowed_vlans, account) return allowed_vlans @@ -126,7 +127,9 @@ def find_allowed_vlans_for_user(account): def set_editable_flag_on_interfaces( - interfaces: Sequence[manage.Interface], vlans: Sequence[FantasyVlan] + interfaces: Sequence[manage.Interface], + vlans: Sequence[FantasyVlan], + user: Optional[Account] = None, ): """Sets the pseudo-attribute `iseditable` on each interface in the interfaces list, indicating whether the PortAdmin UI should allow edits to it or not. @@ -136,8 +139,13 @@ def set_editable_flag_on_interfaces( an uplink, depending on how portadmin is configured. """ vlan_tags = {vlan.vlan for vlan in vlans} + allow_everything = not should_check_access_rights(account=user) if user else False for interface in interfaces: + if allow_everything: + interface.iseditable = True + continue + vlan_is_acceptable = interface.vlan in vlan_tags is_link = bool(interface.to_netbox) refuse_link_edit = not CONFIG.get_link_edit() and is_link diff --git a/python/nav/web/portadmin/views.py b/python/nav/web/portadmin/views.py index 211910965a..e021807750 100644 --- a/python/nav/web/portadmin/views.py +++ b/python/nav/web/portadmin/views.py @@ -56,7 +56,6 @@ NoResponseError, ProtocolError, ManagementError, - POEIndexNotFoundError, XMLParseError, POEStateNotSupportedError, ) @@ -248,7 +247,6 @@ def populate_infodict(request, netbox, interfaces): messages.error(request, str(error)) except ( - POEIndexNotFoundError, XMLParseError, POEStateNotSupportedError, ) as error: diff --git a/python/nav/web/static/js/src/portadmin.js b/python/nav/web/static/js/src/portadmin.js index 4b1224d1d7..621b0c8864 100644 --- a/python/nav/web/static/js/src/portadmin.js +++ b/python/nav/web/static/js/src/portadmin.js @@ -482,6 +482,9 @@ require(['libs/spin.min', 'libs/jquery-ui.min'], function (Spinner) { if ('ifadminstatus' in data) { updateAdminStatusDefault($row, data.ifadminstatus); } + if ('poe_state' in data) { + updatePoeDefault($row, data.poe_state); + } } function updateIfAliasDefault($row, ifalias) { @@ -518,6 +521,15 @@ require(['libs/spin.min', 'libs/jquery-ui.min'], function (Spinner) { } } + function updatePoeDefault($row, new_value) { + var old_value = $row.find('option[data-orig]').val(); + if (old_value !== new_value) { + console.log('Updating PoE state default from ' + old_value + ' to ' + new_value); + $row.find('option[data-orig]').removeAttr('data-orig'); + $row.find('option[value=' + new_value + ']').attr('data-orig', new_value); + } + } + function removeFromQueue(id) { if (queue_data.hasOwnProperty(id)) { delete queue_data[id]; diff --git a/python/nav/web/templates/portadmin/portlist.html b/python/nav/web/templates/portadmin/portlist.html index e6f40e6a98..342e52033f 100644 --- a/python/nav/web/templates/portadmin/portlist.html +++ b/python/nav/web/templates/portadmin/portlist.html @@ -169,20 +169,19 @@ {# POE STATE #} {% if supports_poe %} - {% if interface.supports_poe %}