OpenWISP 26.09

This release brings major improvements to maps, firmware management, device location data, consistency, REST API endpoints, and bug fixes.

Highlights

Better geographic and indoor map experience

More flexible firmware upgrades

Richer device location data


Below you can find the detailed full change log for all the modules included in this release. Enjoy!

openwisp-users (v1.3)

Features

Changes

Other changes

Dependencies

  • Added dj-rest-auth>=7.2.0,<7.3.

  • Bumped django-organizations from >=2.5.0,<2.6.0 to >=2.7.0,<2.8.0.

  • Bumped django-extensions from >=3.2,<4.2 to >=4.1,<4.2.

  • Bumped django-allauth[socialaccount] from >=65.12.0,<65.14.0 to >=65.19.1,<65.20.0.

  • Bumped django-phonenumber-field from >=8.1.0,<8.2.0 to >=8.5.0,<8.6.0.

  • Bumped phonenumbers from >=9.0.10,<9.1.0 to >=9.0.38,<9.1.0.

  • Bumped django-reversion from ~=6.0.0 to ~=6.3.0.

  • Bumped django-redis from ~=6.0.0 to ~=7.0.0.

  • Bumped openwisp-utils[rest,celery] from ~=1.2.0 to ~=1.3.0.

  • Dropped support for Django 4.2.0.

  • Dropped support for Python 3.9.

Bugfixes

openwisp-notifications (v1.3)

Features

Changes

Backward-incompatible changes

Other changes

Dependencies

  • Bumped openwisp-users from ~=1.2.0 to ~=1.3.0.

  • Bumped openwisp-utils[rest,celery,channels] from ~=1.2.0 to ~=1.3.0.

  • Bumped django-redis from ~=6.0.0 to ~=7.0.0.

  • Bumped markdown from ~=3.9 to ~=3.10.

  • Dropped support for Django 4.2.

  • Dropped support for Python 3.9.

Bugfixes

openwisp-controller (v1.3)

Features

Changes

Other changes

  • Enforced the deactivated device state across OpenWISP Controller. Deactivated devices can no longer register, receive configuration updates, run remote commands, or receive automatically assigned templates. Cleanup and security operations continue to work normally.

  • Added VPN subnet and IP address details to the REST API.

  • Allowed deleting organizations containing active devices while displaying a warning about the active devices that will be affected.

  • Replaced the third-party jsonfield implementation with Django's built-in JSONField #1061, including migration handling for databases upgraded from older OpenWISP Controller versions.

  • Changed VPN synchronization errors and recovery events to use generic_message notifications #1049.

  • Improved command status visibility in the admin interface by highlighting statuses with different colors #812.

Dependencies

  • Bumped django-reversion from ~=6.0.0 to ~=6.3.0.

  • Bumped netjsonconfig from ~=1.2.0 to ~=1.3.0.

  • Bumped django-x509 from ~=1.3.0 to ~=1.4.0.

  • Bumped django-loci from ~=1.2.0 to ~=1.3.0.

  • Bumped django-flat-json-widget from ~=0.4.0 to ~=0.5.0.

  • Bumped openwisp-users from ~=1.2.0 to ~=1.3.0.

  • Bumped openwisp-utils[celery,channels] from ~=1.2.0 to ~=1.3.0.

  • Bumped openwisp-notifications from ~=1.2.0 to ~=1.3.0.

  • Bumped openwisp-ipam from ~=1.2.0 to ~=1.3.1.

  • Bumped djangorestframework-gis from ~=1.2.0 to ~=1.3.0.

  • Bumped paramiko from ~=4.0.0 to ~=5.0.0.

  • Bumped scp from ~=0.15.0 to ~=0.16.1.

  • Bumped django-import-export from ~=4.3.10 to ~=4.4.1.

  • Added geoip2>=5.3.0,<6.0.0.

  • Dropped support for Django 4.2.

  • Dropped support for Python 3.9.

Bugfixes

  • Fixed subnet-division rules allocating addresses already in use by respecting existing child prefixes and pre-allocated IP addresses.

  • Fixed background command and connection operations potentially restoring objects that had been deleted concurrently or causing foreign key errors.

  • Fixed VPN client synchronization when switching VPN templates, preventing inconsistent client state during repeated template updates.

  • Fixed SSH connections remaining open when update_config() failed.

  • Fixed malformed UUID URLs returning HTTP 500 instead of HTTP 404.

  • Fixed the Device admin delete confirmation page when OpenWISP Controller is extended by downstream applications.

  • Fixed a typo in the update_strategy validation error message.

openwisp-monitoring (v1.3)

Features

Changes

Other changes

Dependencies

  • Bumped openwisp-controller from ~=1.2.0 to ~=1.3.0.

  • Bumped django-nested-admin from ~=4.1.4 to ~=4.1.6.

  • Bumped python-dateutil from >=2.7.0,<3.0.0 to >=2.9.0.post0,<3.0.0.

  • Upgraded netjsongraph.js to 0.4.0.

  • Updated the bundled Plotly.js, Moment.js, and Leaflet Fullscreen libraries.

  • Dropped support for Django 4.2.

  • Dropped support for Python 3.9.

Bugfixes

openwisp-firmware-upgrader (v1.3)

Features

Changes

Other changes

Dependencies

  • Bumped openwisp-controller from ~=1.2.0 to ~=1.3.0.

  • Bumped django-private-storage from ~=3.1.0 to ~=3.1.3.

  • Dropped support for Django 4.2.

  • Dropped support for Python 3.9.

Bugfixes

openwisp-ipam (v1.3)

Features

Changes

Other changes

  • Improved address allocation graph performance by loading graph data asynchronously.

Dependencies

  • Bumped openwisp-users from ~=1.2.0 to ~=1.3.0.

  • Bumped openwisp-utils[rest] from ~=1.2.0 to ~=1.3.0.

  • Bumped django-reversion from ~=6.0.0 to ~=6.3.0.

  • Dropped support for Django 4.2.

  • Dropped support for Python 3.9.

Bugfixes

openwisp-network-topology (v1.3)

Changes

Other changes

Dependencies

  • Bumped openwisp-users from ~=1.2.0 to ~=1.3.0.

  • Bumped netdiff from ~=1.2.0 to ~=1.3.0.

  • Bumped django-flat-json-widget from ~=0.4.0 to ~=0.5.0.

  • Bumped openwisp-utils[celery,channels] from ~=1.2.0 to ~=1.3.0.

  • Upgraded netjsongraph.js to 0.4.0.

  • Dropped support for Django 4.2.

  • Dropped support for Python 3.9.

Bugfixes

  • Fixed malformed UUIDs causing errors when accessing views that accept UUID parameters.

openwisp-radius (v1.3)

Features

Changes

Backward-incompatible changes

Other changes

Dependencies

  • Bumped dj-rest-auth from >=6.0,<7.2 to >=6.0,<7.3.

  • Bumped django-redis from ~=6.0.0 to ~=7.0.0.

  • Bumped weasyprint from >=65,<68 to >=65,<70.

  • Bumped openwisp-notifications to ~=1.3.0.

  • Bumped openwisp-users to ~=1.3.0.

  • Bumped openwisp-utils[rest,celery] to ~=1.3.0.

  • Replaced Exscript with telnetlib3.

  • Dropped support for Django 4.2.

  • Dropped support for Python 3.9.

Bugfixes

openwisp-utils (v1.3)

Features

  • Implemented sub-filter functionality in Django admin #700

    Introduced SubFilterMixin to allow admin filters to be displayed and applied only when a parent filter has specific values. This enhances the admin interface by enabling hierarchical filtering.

    The filter rendering system has been updated to group parent filters with their sub-filters, displaying sub-filters vertically below their parents. Client-side JavaScript logic dynamically shows or hides sub-filters based on parent filter selections.

    Invalid sub-filter usage, such as providing a sub-filter value when its parent is inactive, will now raise IncorrectLookupParameters. Orphaned sub-filters with invalid configuration will be logged as errors and not rendered.

  • Add OpenWispPagination class with default values #586

    Introduces the OpenWispPagination class, inheriting from DRF's PageNumberPagination. This class provides sensible default values for pagination across OpenWISP modules, configurable via settings.

    The default page size is set to 10 and the maximum page size to 100. These can be overridden by OPENWISP_API_DEFAULT_PAGE_SIZE and OPENWISP_API_MAX_PAGE_SIZE respectively. Views can also set a pagination_page_size attribute to override the default for specific endpoints.

  • Added changelog entry bot #523

  • Automated issue assignment and removal #571

    Added auto-assignment bot with issue assignment, management of stale PR, reassignment on PR reopen and shared helpers in utils.py.

  • Added CI build failure bot #524

    When a CI workflow fails, the bot examines the failure logs and repository context with AI to offer specific guidance for fixing QA check issues, test failures and other common bugs.

  • Added reusable backport workflow #501

    Automates cherry-picking fixes to stable branches via [backport X.Y] in commit messages or /backport X.Y comments, with conflict notification.

  • Standardized commit messages using commitizen #110

    Commitizen has been integrated in openwisp-utils to standardize how commit messages are written across the project. It introduces an interactive commit workflow that guides contributors to use the correct OpenWISP commit format, ensures commit titles are properly structured, and enforces the presence of an issue reference. The commit message footer is generated automatically using the provided issue number, improving consistency and making commits easier to review and track.

  • Releaser: added support for non-python packages #522

Changes

Backward-incompatible changes

  • Removed deprecated UUIDAdmin class #328

    The deprecated UUIDAdmin class has been removed. For equivalent functionality, use CopyableFieldsAdmin with copyable_fields = ('uuid',).

Other changes

  • Included commit bodies in releaser changelog

  • Allowed cascade deletions in ReadOnlyAdmin

    ReadOnlyAdmin.has_delete_permission previously returned False unconditionally, which blocked cascade deletions from parent models (like Organization).

    Added openwisp_utils.admin.BlockDeleteAllowCascadeMixin to allow reusability of this logic in other OpenWISP modules.

  • Excluded local Python virtual environment directories from QA checks #720

  • Made menu item registration idempotent #641

    Previously, calling register_menu_group or register_menu_subitem twice with the same configuration at the same position would always raise an ImproperlyConfigured exception. This behavior prevented re-registration, even when an application registered the same menu items again during testing.

    This change modifies these functions to check if the configuration being registered is identical to the one already present at that position. If the configurations match, the function now logs an informational message and skips the re-registration instead of raising an error. This makes the menu item registration process idempotent and improves testability when applications start again.

  • Releaser: defined a generic package type to use as fallback

    The logic which detected OpenWrt packages has been generalized so that any file which doesn't fall under well defined categories like "python package", "npm package", "ansible role", etc., can fall under the "generic package" type, as long as a VERSION file is defined in the top level directory of the repository, the releaser tool will be able to deal with it, regardless of the tech stack used.

  • Made changelog bot model configurable and quota-resilient

    The changelog bot kept failing with Gemini free-tier quota errors (RequestsPerDayPerProjectPerModel, 20/day) and marked the workflow as failed, while the CI failure bot stayed green because it swallows the same error. The changelog bot also had no way to switch models and could spend up to three requests per pull request.

    Forward GEMINI_MODEL through the action and reusable workflow so a single variable controls both bots, harden model resolution so an empty value falls back to the default, lower the generation retries from three to two, and exit cleanly on quota errors so the workflow no longer turns red on exhaustion.

    Also document the GEMINI_MODEL variable for both bots.

  • SeleniumTestMixin now requires two successful retries after an initial failure

  • Added default uuid method to CopyableFieldsAdmin #328

    CopyableFieldsAdmin now ships with a default uuid() method that returns obj.pk and has short_description set to 'UUID'. This allows subclasses to use copyable_fields = ('uuid',) without defining their own uuid method when their model uses a UUID primary key.

    The uuid field is not automatically added to copyable_fields, that's still the developer's explicit decision.

  • Releaser: removed ChatGPT integration #645

  • Releaser: automated branch selection in changelog porting step #646

Dependencies

Bugfixes

  • Reload DRF settings after configuring defaults

    Bug: ApiAppConfig.configure_rest_framework_defaults updated Django's settings.REST_FRAMEWORK, but DRF's api_settings had already loaded its own copy of the configuration. As a result, changes made by apps initialized after rest_framework were not reflected in the settings actually used by DRF.

    Fix: Reload rest_framework.settings.api_settings after updating settings.REST_FRAMEWORK so DRF uses the latest configuration.

  • Prevented capture decorators from polluting exceptions

    CaptureOutput previously tried injecting streams and retried any TypeError. A real failure in a no-argument decorated test retained the expected signature mismatch as exception context, obscuring the regression traceback.

    The decorator now selects the valid call signature before executing the test, while preserving support for explicit captured streams, variable arguments, and stacked mock.patch decorators.

  • Prevented FallbackMixin from generating spurious migrations #1231

  • Collect Firefox console logs via WebDriver BiDi #696

    Firefox >= 135 no longer loads the Manifest v2 console-capture extension, and Manifest v3 content scripts are not granted host permissions for temporarily installed extensions, so the content script never runs. As a result get_browser_logs() returned undefined (which translated to None in Python) instead of the captured logs on modern Firefox versions, which in turn broke CI builds.

    The extension was replaced with WebDriver BiDi: a console message handler records every console entry, including those emitted during page load, and the log buffer is reset on each navigation to preserve the previous per-page semantics.

    This fixes console capture for every OpenWISP module that relies on SeleniumTestMixin without changing its public API.

  • Excluded node_modules dir and other hidden directories from the ReStructuredText QA check

  • Fixed ValidatedModelSerializer validation of PUT/PATCH and relationships #633

    Updated ValidatedModelSerializer.validate() to:

    • Use copy() for existing instances to avoid mutating the original.

    • Skip reverse relations (ForeignObjectRel) during setattr.

    • Skip nested relationships.

    • Convert Django ValidationError to DRF ValidationError so errors are properly serialized in API responses and work with the parallel test runner.

  • Triggered changelog bot for backward incompatible changes

    Accept [change!] entries in the changelog bot trigger and validation so backward incompatible PRs receive generated changelog suggestions.

  • Fixed double encoding of device model labels in dashboard #651

    Fixed the double-encoding issue in admin dashboard charts where device models with special characters (like &) generated malformed URLs.

  • Fixed broken skipped Selenium tests in Django parallel runner #619

  • Fixed Gemini call

  • Switched to django-minify-compress-staticfiles #565

    Replaced the unmaintained django-compress-staticfiles with the new django-minify-compress-staticfiles package for static file minification and compression.

  • Releaser: perform git pull --tags before changelog generation

openwisp-wifi-login-pages (v1.3)

Features

Changes

Other changes

Dependencies

Bugfixes

  • Fixed Social Login and SAML users being unable to change their password when it has expired.

  • Improved password reset error messages so invalid reset URLs and password validation errors are clearly reported.

  • Fixed organization-wide extra JavaScript files not being copied to the distribution build after upgrading copy-webpack-plugin.

  • Fixed JavaScript transpilation to ES5, restoring compatibility with older browsers.

openwisp-config (v1.3)

Features

Changes

Other changes

  • Added support for removing the default 6 GHz SSID when OpenWrt uses owe encryption, which is the default for 6 GHz radios.

Bugfixes

openwrt-openwisp-monitoring (v0.3.1)

Bugfixes

  • Switch to portable df output (df -P) #153.

  • Fixed issue where WiFi client data was sent even when no clients were connected.

  • Added check to ensure data file exists before sending to prevent errors #102.

  • Ignored duplicate IP addresses in network configuration.

ansible-openwisp2 (v26.09)

Features

Changes

  • Separated the Redis database used for sessions from the cache database. Deployments with a custom Redis cache URL should verify that it does not conflict with the updated Redis database assignments.

Other changes

Dependencies

  • Upgraded to OpenWISP Users 1.3.x (see change log).

  • Upgraded to OpenWISP Controller 1.3.x (see change log).

  • Upgraded to OpenWISP Monitoring 1.3.x (see change log).

  • Upgraded to OpenWISP Network Topology 1.3.x (see change log).

  • Upgraded to OpenWISP Firmware Upgrader 1.3.x (see change log).

  • Upgraded to OpenWISP RADIUS 1.3.x (see change log).

  • Upgraded to OpenWISP Notifications 1.3.x (see change log).

  • Upgraded to Netjsonconfig 1.3.x (see change log).

  • Bumped ansible-core from >=2.15,<2.19 to >=2.20.5,<2.22.

  • Bumped django-redis from >=6.0.0,<6.1.0 to >=7.0.0,<7.1.0.

  • Bumped mysqlclient from >=2.2,<2.3 to >=2.2.8,<2.3.

  • Bumped psycopg2 from >=2.9,<2.10 to >=2.9.12,<2.10.

  • Bumped uwsgi from >=2.0.30,<2.1.0 to >=2.0.31,<2.1.0.

  • Bumped django-celery-email-reboot from >=4.1,<4.2 to 4.2.1.

docker-openwisp (v26.09)

Features

Changes

Other changes

Dependencies

  • Upgraded to OpenWISP Users 1.3.x (see changelog).

  • Upgraded to OpenWISP Controller 1.3.x (see changelog).

  • Upgraded to OpenWISP Monitoring 1.3.x (see changelog).

  • Upgraded to OpenWISP Network Topology 1.3.x (see changelog).

  • Upgraded to OpenWISP Firmware Upgrader 1.3.x (see changelog).

  • Upgraded to OpenWISP RADIUS 1.3.x (see changelog).

  • Upgraded to OpenWISP Notifications 1.3.x (see changelog).

  • Upgraded to Netjsonconfig 1.3.x (see changelog).

  • Bumped docker from >=7.1.0,<7.2.0 to >=7.2.0,<7.3.0.

  • Bumped the Nginx image from 1.31.1-alpine to 1.31.5-alpine.

  • Bumped the OpenVPN image from lisenet/openvpn:2.7.3 to lisenet/openvpn:2.7.5.

  • Bumped the Postfix and NFS Alpine base images from 3.23 to 3.24.

  • Bumped the FreeRADIUS image from 3.2.8-alpine to 3.2.10-alpine.

  • Bumped tldextract from >=5.3.1,<5.4.0 to >=5.3.2,<5.4.0.

  • Bumped boto3 to >=1.43.84,<1.44.0.

Bugfixes