[fix] Record monitoring metrics for sessions closed via bulk updates#735
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR adds a Sequence Diagram(s)sequenceDiagram
participant AbstractRadiusAccounting
participant RadiusAccounting
participant transaction_on_commit
participant radius_accounting_closed
participant radius_accounting_closed_handler
participant post_save_radiusaccounting_delay
AbstractRadiusAccounting->>transaction_on_commit: schedule radius_accounting_closed after save
RadiusAccounting->>transaction_on_commit: emit_radius_accounting_closed(closed_sessions)
transaction_on_commit->>radius_accounting_closed: send(instance)
radius_accounting_closed->>radius_accounting_closed_handler: deliver instance
radius_accounting_closed_handler->>post_save_radiusaccounting_delay: enqueue metric with time=stop_time
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@openwisp_radius/base/models.py`:
- Around line 587-596: In close_previous_radius_accounting_sessions / the stale
session closing block, add an empty-list check before calling
cls.objects.bulk_update so the method consistently returns 0 when there are no
sessions to close. Use the closed_sessions list (and
emit_radius_accounting_closed only when it’s non-empty) to avoid calling
bulk_update([]), which can return None on older Django versions and causes
inconsistent closed_count behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 1de49c1a-ff2e-4a3c-a057-ec7ad3fa59e7
📒 Files selected for processing (8)
docs/developer/utils.rstopenwisp_radius/base/models.pyopenwisp_radius/integrations/monitoring/apps.pyopenwisp_radius/integrations/monitoring/receivers.pyopenwisp_radius/integrations/monitoring/tests/test_metrics.pyopenwisp_radius/receivers.pyopenwisp_radius/signals.pyopenwisp_radius/utils.py
📜 Review details
⏰ Context from checks skipped due to timeout. (7)
- GitHub Check: auto-assign-issue / run-bot
- GitHub Check: Python==3.10 | django~=5.1.0
- GitHub Check: Python==3.10 | django~=4.2.0
- GitHub Check: Python==3.13 | django~=5.1.0
- GitHub Check: Python==3.13 | django~=5.2.0
- GitHub Check: Python==3.12 | django~=5.1.0
- GitHub Check: Kilo Code Review
🧰 Additional context used
📓 Path-based instructions (2)
**/{docs,documentation}/**/*.{md,rst,adoc,html}
📄 CodeRabbit inference engine (Custom checks)
**/{docs,documentation}/**/*.{md,rst,adoc,html}: Documentation must be updated if a change affects behavior that is already documented
Feature documentation must mention the new feature. If the feature is heavily UI-related, a new section or page is appropriate
Files:
docs/developer/utils.rst
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Place imports at the top of the file. Only defer imports when necessary (e.g., Django model imports inside functions or methods where the app registry is not yet ready).
Avoid unnecessary blank lines inside function and method bodies.
Mark user-facing strings for translation with Django i18n helpers in Django code.
Write comments and docstrings only when they explain why code is shaped a certain way. Put comments before the relevant code block instead of scattering them inside it.
Files:
openwisp_radius/utils.pyopenwisp_radius/receivers.pyopenwisp_radius/signals.pyopenwisp_radius/integrations/monitoring/receivers.pyopenwisp_radius/base/models.pyopenwisp_radius/integrations/monitoring/apps.pyopenwisp_radius/integrations/monitoring/tests/test_metrics.py
🔇 Additional comments (9)
openwisp_radius/signals.py (1)
4-4: LGTM!openwisp_radius/utils.py (1)
37-42: LGTM!openwisp_radius/base/models.py (1)
58-58: LGTM!openwisp_radius/receivers.py (1)
15-15: LGTM!Also applies to: 129-129
openwisp_radius/integrations/monitoring/receivers.py (2)
7-12: 🎯 Functional CorrectnessConfirm metrics should no longer be written for open/interim accounting updates.
The new
instance.stop_time is Noneguard meanspost_save_radiusaccountingnow skips sessions without astop_time(open sessions and interim accounting updates), whereas previously everypost_saveenqueued a metric. This appears intentional (octets are cumulative, so recording only at close avoids over-counting) and is asserted bytest_post_save_radiusaccouting_open_session, but please confirm no downstream dashboards relied on interim-update metrics.
13-31: LGTM!openwisp_radius/integrations/monitoring/apps.py (1)
124-142: LGTM!openwisp_radius/integrations/monitoring/tests/test_metrics.py (1)
21-21: LGTM!Also applies to: 93-93, 144-144, 181-277, 307-307, 391-391, 468-468, 530-530, 580-580
docs/developer/utils.rst (1)
30-31: 📐 Maintainability & Code QualityThe section underline matches the title length exactly, so no Sphinx build warning will occur.
This does not appear to be an issue.
> Likely an incorrect or invalid review comment.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Nicely scoped fix. The new Verification notes:
Files Reviewed (8 files)
Reviewed by glm-5.2 · Input: 173K · Output: 18.8K · Cached: 592.4K |
Migrations Check FailedHello @nemesifier, The CI build failed because of a migrations check. The error message Fix: |
| ``radius_accounting_closed`` | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
There was a problem hiding this comment.
Will it make more sense to always send this signal when the RadiusAccounting session is closed? It will help in cleaner implementation downstream (openwisp-monitoring integration).
Right now, we will have to listen to two different signals, which is fine. but requires developers to be aware of the context.
| closed_sessions = list(stale_sessions) | ||
| stop_time = now() | ||
| for session in closed_sessions: | ||
| session.stop_time = stop_time | ||
| session.terminate_cause = "NAS-Reboot" | ||
| closed_count = cls.objects.bulk_update( | ||
| closed_sessions, fields=["stop_time", "terminate_cause"] | ||
| ) |
There was a problem hiding this comment.
We typically use iterator() with bulk_update with a chuksize of 1000 (default in Django). Right now, the code will load all the objects in the memory which is not ideal.
We can make the query efficient by only fetching the id in the queryset. We'll probably need to check that it does not increase the number of queries.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
openwisp_radius/integrations/monitoring/tests/test_metrics.py (1)
175-183: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winPatch
.delayin the open-session regression.Line 183 checks the task object itself, but the receiver calls
post_save_radiusaccounting.delay(...). This test still passes if.delay()is invoked, so it does not actually guard the “no metric for open sessions” path.Suggested fix
- `@patch`("openwisp_radius.integrations.monitoring.tasks.post_save_radiusaccounting") - def test_post_save_radiusaccouting_open_session(self, mocked_task): + `@patch`( + "openwisp_radius.integrations.monitoring.tasks.post_save_radiusaccounting.delay" + ) + def test_post_save_radiusaccouting_open_session(self, mocked_delay): """ Regression test ensuring open or interim accounting sessions do not write monitoring metrics before their cumulative octet values are final. """ radius_options = _RADACCT.copy() radius_options["unique_id"] = "117" session = self._create_radius_accounting(**radius_options) self.assertEqual(session.stop_time, None) - mocked_task.assert_not_called() + mocked_delay.assert_not_called()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@openwisp_radius/integrations/monitoring/tests/test_metrics.py` around lines 175 - 183, The open-session regression test is asserting on the task object instead of the actual async call, so it won’t fail when `post_save_radiusaccounting.delay(...)` is invoked; update the test to patch and assert the `.delay` method on the `post_save_radiusaccounting` symbol used by the receiver, so the “no metric for open sessions” path is properly guarded.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@openwisp_radius/base/models.py`:
- Around line 613-620: The NAS reboot closure path in the session bulk update is
overwriting rows that may have been closed concurrently because it only writes
by primary key after materializing `closed_sessions`. Update the logic around
the `while closed_sessions := list(islice(stale_sessions, 1000))` loop and
`cls.objects.bulk_update(...)` in `base/models.py` so the write still enforces
`stop_time__isnull=True` at update time or locks the selected rows before
loading them, and only emit `emit_radius_accounting_closed` for sessions that
were actually updated.
---
Outside diff comments:
In `@openwisp_radius/integrations/monitoring/tests/test_metrics.py`:
- Around line 175-183: The open-session regression test is asserting on the task
object instead of the actual async call, so it won’t fail when
`post_save_radiusaccounting.delay(...)` is invoked; update the test to patch and
assert the `.delay` method on the `post_save_radiusaccounting` symbol used by
the receiver, so the “no metric for open sessions” path is properly guarded.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 00e682bf-e14a-4b18-b165-2249b0bcd7e9
📒 Files selected for processing (8)
docs/developer/utils.rstopenwisp_radius/apps.pyopenwisp_radius/base/models.pyopenwisp_radius/integrations/monitoring/apps.pyopenwisp_radius/integrations/monitoring/receivers.pyopenwisp_radius/integrations/monitoring/tests/test_metrics.pyopenwisp_radius/receivers.pyopenwisp_radius/utils.py
💤 Files with no reviewable changes (1)
- openwisp_radius/integrations/monitoring/receivers.py
📜 Review details
⏰ Context from checks skipped due to timeout. (11)
- GitHub Check: Python==3.11 | django~=4.2.0
- GitHub Check: Python==3.13 | django~=5.2.0
- GitHub Check: Python==3.12 | django~=4.2.0
- GitHub Check: Python==3.11 | django~=5.1.0
- GitHub Check: Python==3.10 | django~=4.2.0
- GitHub Check: Python==3.10 | django~=5.1.0
- GitHub Check: Python==3.12 | django~=5.1.0
- GitHub Check: Python==3.10 | django~=5.2.0
- GitHub Check: Python==3.13 | django~=5.1.0
- GitHub Check: Python==3.11 | django~=5.2.0
- GitHub Check: Python==3.12 | django~=5.2.0
🧰 Additional context used
📓 Path-based instructions (2)
**/{docs,documentation}/**/*.{md,rst,adoc,html}
📄 CodeRabbit inference engine (Custom checks)
**/{docs,documentation}/**/*.{md,rst,adoc,html}: Documentation must be updated if a change affects behavior that is already documented
Feature documentation must mention the new feature. If the feature is heavily UI-related, a new section or page is appropriate
Files:
docs/developer/utils.rst
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Place imports at the top of the file. Only defer imports when necessary (e.g., Django model imports inside functions or methods where the app registry is not yet ready).
Avoid unnecessary blank lines inside function and method bodies.
Mark user-facing strings for translation with Django i18n helpers in Django code.
Write comments and docstrings only when they explain why code is shaped a certain way. Put comments before the relevant code block instead of scattering them inside it.
Files:
openwisp_radius/utils.pyopenwisp_radius/apps.pyopenwisp_radius/integrations/monitoring/apps.pyopenwisp_radius/receivers.pyopenwisp_radius/base/models.pyopenwisp_radius/integrations/monitoring/tests/test_metrics.py
🔇 Additional comments (3)
openwisp_radius/apps.py (1)
18-18: LGTM!Also applies to: 131-135
openwisp_radius/integrations/monitoring/apps.py (1)
14-14: LGTM!Also applies to: 123-134
openwisp_radius/integrations/monitoring/tests/test_metrics.py (1)
93-93: LGTM!Also applies to: 144-144, 188-331, 361-361, 445-445, 522-522, 584-584, 634-634
|
The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (1/3). |
| emit_radius_accounting_closed(closed_sessions) | ||
|
|
||
|
|
||
| def emit_radius_accounting_closed_on_save(instance, created, *args, **kwargs): |
There was a problem hiding this comment.
This is too AI sloppy, I will improve tomorrow.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@openwisp_radius/base/models.py`:
- Around line 540-543: The Session model __init__ currently calls
_set_initial_stop_time unconditionally, which forces deferred stop_time values
to be loaded when instances are built from _close_stale_sessions_on_nas_boot().
Update the __init__ / _set_initial_stop_time flow so it does not access
stop_time through the descriptor when the field is deferred; instead read from
__dict__ or skip cache initialization if stop_time is not already present. Keep
the fix localized to the Session initialization path and its stop-time cache
handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 454088db-8754-4169-9472-b85b55f7a4c9
📒 Files selected for processing (4)
openwisp_radius/base/models.pyopenwisp_radius/receivers.pyopenwisp_radius/tests/test_models.pyopenwisp_radius/utils.py
💤 Files with no reviewable changes (1)
- openwisp_radius/receivers.py
📜 Review details
⏰ Context from checks skipped due to timeout. (11)
- GitHub Check: Python==3.10 | django~=5.1.0
- GitHub Check: Python==3.11 | django~=4.2.0
- GitHub Check: Python==3.11 | django~=5.2.0
- GitHub Check: Python==3.13 | django~=5.1.0
- GitHub Check: Python==3.11 | django~=5.1.0
- GitHub Check: Python==3.13 | django~=5.2.0
- GitHub Check: Python==3.12 | django~=5.1.0
- GitHub Check: Python==3.10 | django~=4.2.0
- GitHub Check: Python==3.12 | django~=5.2.0
- GitHub Check: Python==3.12 | django~=4.2.0
- GitHub Check: Python==3.10 | django~=5.2.0
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Place imports at the top of the file. Only defer imports when necessary (e.g., Django model imports inside functions or methods where the app registry is not yet ready).
Avoid unnecessary blank lines inside function and method bodies.
Mark user-facing strings for translation with Django i18n helpers in Django code.
Write comments and docstrings only when they explain why code is shaped a certain way. Put comments before the relevant code block instead of scattering them inside it.
Files:
openwisp_radius/utils.pyopenwisp_radius/tests/test_models.pyopenwisp_radius/base/models.py
🔇 Additional comments (4)
openwisp_radius/tests/test_models.py (2)
159-225: LGTM!
827-827: LGTM!Also applies to: 862-862
openwisp_radius/utils.py (1)
39-45: LGTM!openwisp_radius/base/models.py (1)
628-635: 🗄️ Data Integrity & Integration | 🏗️ Heavy liftConcurrent close can still be overwritten. Rows are read while
stop_time IS NULLand written back by primary key only, so an Accounting-Stop that closes a session between read andbulk_updatewill be clobbered with NAS-reboot values and emit a secondradius_accounting_closed. This was raised on a prior commit and does not appear resolved.
a52f7f6 to
9f97063
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
3b481e8 to
036091a
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@openwisp_radius/base/models.py`:
- Around line 551-556: The AbstractRadiusAccounting.save() method backfills
start_time in memory, but when update_fields is provided without start_time
Django will not persist that change. Update the save() logic so that when
start_time is set inside save() it is also added to kwargs["update_fields"] in
the update_fields path before calling super(), ensuring the saved row and any
signals reflect the same persisted value.
In `@openwisp_radius/integrations/monitoring/tests/test_metrics.py`:
- Around line 173-183: The regression test is patching the task object instead
of the enqueue method, so it won’t catch accidental calls to
post_save_radiusaccounting.delay for open sessions. Update the test in
test_post_save_radiusaccouting_open_session to patch the .delay path on
post_save_radiusaccounting, then keep the assertion focused on verifying that
.delay is never invoked when _create_radius_accounting returns a session with no
stop_time.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 41f3315c-fbf8-4a2d-b5c8-ec3593a20c9a
📒 Files selected for processing (8)
docs/developer/utils.rstopenwisp_radius/base/models.pyopenwisp_radius/integrations/monitoring/apps.pyopenwisp_radius/integrations/monitoring/receivers.pyopenwisp_radius/integrations/monitoring/tests/test_metrics.pyopenwisp_radius/receivers.pyopenwisp_radius/signals.pyopenwisp_radius/tests/test_models.py
📜 Review details
⚠️ CI failures not shown inline (27)
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.10 django~=5.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.12 django~=5.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.10 django~=4.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.13 django~=5.1.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.13 django~=5.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.12 django~=4.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.11 django~=5.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.11 django~=5.1.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.12 django~=5.1.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.11 django~=4.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.10 django~=5.1.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
Post job cleanup.
[command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/openwisp-radius/openwisp-radius --files-from manifest.txt --use-compress-program zstdmt
/usr/bin/tar: ../../../../../var/cache/apt/archives/partial: Cannot open: Permission denied
/usr/bin/tar: ../../../../../var/cache/apt/archives/lock: Cannot open: Permission denied
/usr/bin/tar: Exiting with failure status due to previous errors
##[warning]Failed to save: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
GitHub Actions: OpenWISP RADIUS CI Build / 2_Python==3.13 django~=5.1.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
>openwisp-radius==1.3a0) (4.3.0)
Requirement already satisfied: celery~=5.6.1 in /opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.3)
Requirement already satisfied: billiard<5.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.2.4)
Requirement already satisfied: kombu>=5.6.0 in /opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.2)
Requirement already satisfied: vine<6.0,>=5.1.0 in /opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.1.0)
Requirement already satisfied: click<9.0,>=8.1.2 in /opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (8.4.2)
Requirement already satisfied: click-didyoumean>=0.3.0 in /opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages (from ce...
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.12 django~=5.1.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
mand).run_from_argv(self.argv)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/commands/test.py", line 24, in run_from_argv
super().run_from_argv(argv)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/base.py", line 413, in run_from_argv
self.execute(*args, **cmd_options)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/base.py", line 459, in execute
output = self.handle(*args, **options)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/commands/test.py", line 63, in handle
failures = test_runner.run_tests(test_labels)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 1073, in run_tests
result = self.run_suite(suite)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 1000, in run_suite
return runner.run(suite)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/runner.py", line 240, in run
test(result)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 516, in run
pool = multiprocessing.Pool(
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/context.py", line 119, in Pool
return Pool(processes, initializer, initargs, maxtasksperchild,
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/pool.py", line 215, in __init__
self._repopulate_pool()
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/pool.py", line 306, in _repopulate_pool
return self._repopulate_pool_static(self._ctx, self.Process,
F...
GitHub Actions: OpenWISP RADIUS CI Build / 1_Python==3.10 django~=5.2.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
penwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (2.7.0)
Requirement already satisfied: distro~=1.9.0 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (1.9.0)
Requirement already satisfied: celery~=5.6.1 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.3)
Requirement already satisfied: channels~=4.3.0 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from channels[daphne]~=4.3.0; extra == "channels"->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.2)
Requirement already satisfied: channels_redis<4.4.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.0)
Requirement already satisfied: djangorestframework~=3.17.1 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/ar...
GitHub Actions: OpenWISP RADIUS CI Build / 8_Python==3.12 django~=5.2.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
2.13/x64/lib/python3.12/site-packages (from channels[daphne]~=4.3.0; extra == "channels"->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.2)
Requirement already satisfied: channels_redis<4.4.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.0)
Requirement already satisfied: celery~=5.6.1 in /opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.3)
Requirement already satisfied: billiard<5.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.2.4)
Requirement already satisfied: kombu>=5.6.0 in /opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.2)
Requirement already satisfied: vine<6.0,>=5.1.0 in /opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3....
GitHub Actions: OpenWISP RADIUS CI Build / 5_Python==3.11 django~=5.1.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
aphne]~=4.3.0; extra == "channels"->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.2)
Requirement already satisfied: channels_redis<4.4.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.0)
Requirement already satisfied: celery~=5.6.1 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.3)
Requirement already satisfied: billiard<5.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.2.4)
Requirement already satisfied: kombu>=5.6.0 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.2)
Requirement already satisfied: vine<6.0,>=5.1.0 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from celery~=5.6.1->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.c...
GitHub Actions: OpenWISP RADIUS CI Build / 11_Python==3.10 django~=5.1.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
sp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (5.6.3)
Requirement already satisfied: djangorestframework~=3.17.1 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (3.17.1)
Requirement already satisfied: django-filter<26.0,>=25.1 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (25.2)
Requirement already satisfied: drf-yasg<1.22.0,>=1.21.14 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (1.21.15)
Requirement already satisfied: channels~=4.3.0 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from channels[daphne]~=4.3.0; extra == "channels"->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.2)
Requirement already satisfied: channels_redis<4.4.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/head...
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.11 django~=5.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
om_argv(self.argv)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/core/management/commands/test.py", line 24, in run_from_argv
super().run_from_argv(argv)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/core/management/base.py", line 420, in run_from_argv
self.execute(*args, **cmd_options)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/core/management/base.py", line 464, in execute
output = self.handle(*args, **options)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/core/management/commands/test.py", line 63, in handle
failures = test_runner.run_tests(test_labels)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/test/runner.py", line 1087, in run_tests
result = self.run_suite(suite)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/test/runner.py", line 1014, in run_suite
return runner.run(suite)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/unittest/runner.py", line 217, in run
test(result)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/test/runner.py", line 516, in run
pool = multiprocessing.Pool(
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/context.py", line 119, in Pool
return Pool(processes, initializer, initargs, maxtasksperchild,
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/pool.py", line 215, in __init__
self._repopulate_pool()
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/pool.py", line 306, in _repopulate_pool
return self._repopulate_pool_static(self._ctx, self.Process,
File "/opt/ho...
GitHub Actions: OpenWISP RADIUS CI Build / 9_Python==3.11 django~=4.2.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
1.15/x64/lib/python3.11/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (3.17.1)
Requirement already satisfied: django-filter<26.0,>=25.1 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (25.2)
Requirement already satisfied: drf-yasg<1.22.0,>=1.21.14 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (1.21.15)
Requirement already satisfied: channels~=4.3.0 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from channels[daphne]~=4.3.0; extra == "channels"->openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.2)
Requirement already satisfied: channels_redis<4.4.0,>=4.2.1 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[celery,rest] @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-radius==1.3a0) (4.3.0)
Requirement already satisfied: celery~=5.6.1 in /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages (from openwisp-utils @ https://github.com/openwisp/openwisp-utils/archive/refs/heads/1.3.tar.gz->openwisp-utils[cel...
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.12 django~=4.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
1043, in do_run
runner.run()
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/coverage/execfile.py", line 213, in run
exec(code, main_mod.__dict__)
File "/home/runner/work/openwisp-radius/openwisp-radius/runtests.py", line 24, in <module>
execute_from_command_line(args)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
utility.execute()
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/commands/test.py", line 24, in run_from_argv
super().run_from_argv(argv)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/base.py", line 412, in run_from_argv
self.execute(*args, **cmd_options)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/base.py", line 458, in execute
output = self.handle(*args, **options)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/core/management/commands/test.py", line 68, in handle
failures = test_runner.run_tests(test_labels)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 1061, in run_tests
result = self.run_suite(suite)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 983, in run_suite
return runner.run(suite)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/runner.py", line 240, in run
test(result)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
...
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.10 django~=4.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
subset(ttfont)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/fontTools/subset/__init__.py", line 3859, in subset
self._prune_post_subset(font)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/fontTools/subset/__init__.py", line 3841, in _prune_post_subset
table = font[tag]
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/fontTools/ttLib/ttFont.py", line 805, in __getitem__
table = self._readTable(tag)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/fontTools/ttLib/ttFont.py", line 821, in _readTable
log.debug("Decompiling '%s' table", tag)
Message: "Decompiling '%s' table"
Arguments: ('name',)
--- Logging error ---
Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/openwisp_utils/tests/utils.py", line 97, in wrapped_function
function(*args, **kwargs)
TypeError: TestCommands.test_prefix_add_users_command() takes 1 positional argument but 2 were given
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/logging/__init__.py", line 1103, in emit
stream.write(msg + self.terminator)
ValueError: I/O operation on closed file
Call stack:
File "/opt/hostedtoolcache/Python/3.10.20/x64/bin/coverage", line 6, in <module>
sys.exit(main())
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/coverage/cmdline.py", line 1164, in main
status = CoverageScript().command_line(argv)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/coverage/cmdline.py", line 853, in command_line
return self.do_run(options, args)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/coverage/cmdline.py", line 1043, in do_run
runner.run()
File "/opt/hostedtoolcache/Python/3...
GitHub Actions: OpenWISP RADIUS CI Build / Python==3.13 django~=5.2.0: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
s, **cmd_options)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/core/management/base.py", line 464, in execute
output = self.handle(*args, **options)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/core/management/commands/test.py", line 63, in handle
failures = test_runner.run_tests(test_labels)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/test/runner.py", line 1087, in run_tests
result = self.run_suite(suite)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/test/runner.py", line 1014, in run_suite
return runner.run(suite)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/unittest/runner.py", line 240, in run
test(result)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/test/runner.py", line 516, in run
pool = multiprocessing.Pool(
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/context.py", line 119, in Pool
return Pool(processes, initializer, initargs, maxtasksperchild,
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/pool.py", line 215, in __init__
self._repopulate_pool()
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/pool.py", line 306, in _repopulate_pool
return self._repopulate_pool_static(self._ctx, self.Process,
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/pool.py", line 329, in _repopulate_pool_static
w.start()
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/process.py", line 121, in start
self._popen = self._Popen(self)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/con...
GitHub Actions: OpenWISP RADIUS CI Build / 7_Python==3.12 django~=4.2.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
nit__
self._repopulate_pool()
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/pool.py", line 306, in _repopulate_pool
return self._repopulate_pool_static(self._ctx, self.Process,
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/pool.py", line 329, in _repopulate_pool_static
w.start()
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/process.py", line 121, in start
self._popen = self._Popen(self)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/context.py", line 282, in _Popen
return Popen(process_obj)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/popen_fork.py", line 19, in __init__
self._launch(process_obj)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/popen_fork.py", line 71, in _launch
code = process_obj._bootstrap(parent_sentinel=child_r)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/coverage/multiproc.py", line 51, in _bootstrap
return original_bootstrap(self, *args, **kwargs)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/process.py", line 314, in _bootstrap
self.run()
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 449, in _run_subsuite
result = runner.run(subsuite)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 366, in run
test(result)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/suite.py", line 84, in...
GitHub Actions: OpenWISP RADIUS CI Build / 10_Python==3.12 django~=5.1.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
ile "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/popen_fork.py", line 19, in __init__
self._launch(process_obj)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/popen_fork.py", line 71, in _launch
code = process_obj._bootstrap(parent_sentinel=child_r)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/coverage/multiproc.py", line 51, in _bootstrap
return original_bootstrap(self, *args, **kwargs)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/process.py", line 314, in _bootstrap
self.run()
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/multiprocessing/pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 454, in _run_subsuite
result = runner.run(subsuite)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/runner.py", line 369, in run
test(result)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/suite.py", line 122, in run
test(result)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/testcases.py", line 317, in __call__
self._setup_and_call(result)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/django/test/testcases.py", line 369, in _setup_and_call
super().__call__(result)
File "/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/unittest/case.py", line 690, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache...
GitHub Actions: OpenWISP RADIUS CI Build / 6_Python==3.13 django~=5.2.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
ent_sentinel=child_r)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/coverage/multiproc.py", line 51, in _bootstrap
return original_bootstrap(self, *args, **kwargs)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/process.py", line 313, in _bootstrap
self.run()
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/multiprocessing/pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/test/runner.py", line 454, in _run_subsuite
result = runner.run(subsuite)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/test/runner.py", line 369, in run
test(result)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/unittest/suite.py", line 122, in run
test(result)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/test/testcases.py", line 321, in __call__
self._setup_and_call(result)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/site-packages/django/test/testcases.py", line 376, in _setup_and_call
super().__call__(result)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/unittest/case.py", line 707, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/unittest/case.py", line 651, in run
self._callTestMethod(testMethod)
File "/opt/hostedtoolcache/Python/3.13.14/x64/lib/python3.13/unittest/case.py", line 606, in _callTestMethod
if method() is not None:
File "/opt/hostedtoolcache/Python/3.13.14/x6...
GitHub Actions: OpenWISP RADIUS CI Build / 3_Python==3.10 django~=4.2.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
ache/Python/3.10.20/x64/lib/python3.10/site-packages/django/core/management/__init__.py", line 436, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/django/core/management/commands/test.py", line 24, in run_from_argv
super().run_from_argv(argv)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/django/core/management/base.py", line 412, in run_from_argv
self.execute(*args, **cmd_options)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/django/core/management/base.py", line 458, in execute
output = self.handle(*args, **options)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/django/core/management/commands/test.py", line 68, in handle
failures = test_runner.run_tests(test_labels)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/django/test/runner.py", line 1061, in run_tests
result = self.run_suite(suite)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/django/test/runner.py", line 983, in run_suite
return runner.run(suite)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/unittest/runner.py", line 184, in run
test(result)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/django/test/runner.py", line 510, in run
pool = multiprocessing.Pool(
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/multiprocessing/context.py", line 119, in Pool
return Pool(processes, initializer, initargs, maxtasksperchild,
File "/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/multiprocessing/pool.py", line 215, in __init__
self._repopulate_pool()
File "/opt/hostedtoolcache/Python/3.10.20/x64/l...
GitHub Actions: OpenWISP RADIUS CI Build / 4_Python==3.11 django~=5.2.0.txt: [fix] Record monitoring metrics for sessions closed via bulk updates
Conclusion: failure
stedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/popen_fork.py", line 19, in __init__
self._launch(process_obj)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/popen_fork.py", line 71, in _launch
code = process_obj._bootstrap(parent_sentinel=child_r)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/coverage/multiproc.py", line 51, in _bootstrap
return original_bootstrap(self, *args, **kwargs)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/process.py", line 314, in _bootstrap
self.run()
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/multiprocessing/pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/test/runner.py", line 454, in _run_subsuite
result = runner.run(subsuite)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/test/runner.py", line 369, in run
test(result)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/unittest/suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/unittest/suite.py", line 122, in run
test(result)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/test/testcases.py", line 321, in __call__
self._setup_and_call(result)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/django/test/testcases.py", line 376, in _setup_and_call
super().__call__(result)
File "/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/unittest/case.py", line 678, in __call__
return self.run(*args, **kwds)
File "/opt/hostedtoolcache/Python/3.11...
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Place imports at the top of the file. Only defer imports when necessary (e.g., Django model imports inside functions or methods where the app registry is not yet ready).
Avoid unnecessary blank lines inside function and method bodies.
Mark user-facing strings for translation with Django i18n helpers in Django code.
Write comments and docstrings only when they explain why code is shaped a certain way. Put comments before the relevant code block instead of scattering them inside it.
Files:
openwisp_radius/signals.pyopenwisp_radius/receivers.pyopenwisp_radius/integrations/monitoring/receivers.pyopenwisp_radius/tests/test_models.pyopenwisp_radius/integrations/monitoring/apps.pyopenwisp_radius/integrations/monitoring/tests/test_metrics.pyopenwisp_radius/base/models.py
**/{docs,documentation}/**/*.{md,rst,adoc,html}
📄 CodeRabbit inference engine (Custom checks)
**/{docs,documentation}/**/*.{md,rst,adoc,html}: Documentation must be updated if a change affects behavior that is already documented
Feature documentation must mention the new feature. If the feature is heavily UI-related, a new section or page is appropriate
Files:
docs/developer/utils.rst
🪛 ast-grep (0.44.0)
openwisp_radius/integrations/monitoring/apps.py
[warning] 125-125: Loading a Keras model from an untrusted file can execute arbitrary code via Lambda layers or custom objects. Load only trusted models and avoid deserializing custom objects from untrusted sources.
Context: load_model("openwisp_radius", "RadiusAccounting")
Note: [CWE-502] Deserialization of Untrusted Data.
(keras-load-model-python)
🔇 Additional comments (4)
openwisp_radius/base/models.py (2)
644-651: The NAS-boot bulk-close race is still present.This still reads open sessions and later writes them back by primary key only, so a concurrent Accounting-Stop can be overwritten and re-emitted as closed a second time.
8-9: LGTM!Also applies to: 57-57, 541-550, 557-591, 631-643, 652-652
openwisp_radius/signals.py (1)
4-4: LGTM!docs/developer/utils.rst (1)
30-56: LGTM!
6c45a32 to
3b53645
Compare
The integration with OpenWISP Monitoring now is triggered exclusively when RADIUS accounting sessions close, instead of the previous approach which used the generic post_save signal and used custom logic to determine if the RADIUS session was being closed or not.
3bc8863 to
a9d9163
Compare
The RADIUS monitoring integration previously relied only on Django's ``post_save`` signal to write traffic snapshots. However, sessions closed via ``QuerySet.update()`` (``Accounting-On`` handling) and ``bulk_update()`` (``close_previous_radius_accounting_sessions``) bypassed this signal, causing traffic to be missing from RADIUS traffic charts. Sessions closed via ``QuerySet.update()`` and ``bulk_update()`` now emit the ``radius_accounting_closed`` signal, ensuring that traffic metrics are correctly snapshotted by the RADIUS monitoring integration. Closes #734
a9d9163 to
14b333b
Compare
Checklist
Reference to Existing Issue
Closes #734.
Description of Changes
The RADIUS monitoring integration only writes traffic snapshots when Django's
post_savesignal is emitted. However, two common session closure paths use bulk updates which bypass this signal:Accounting-On) closes stale sessions viaQuerySet.update().close_previous_radius_accounting_sessionsreceiver usesbulk_update().As a result, traffic from sessions closed through these paths is present in the SQL accounting table but missing from the RADIUS traffic chart, leading to undercounted totals.
This change introduces a new
radius_accounting_closedsignal and a helperemit_radius_accounting_closed()that integrations can call after bulk updates. The monitoring integration now listens to bothpost_saveand this new signal, ensuring every closed session is snapshotted.Additionally, the monitoring metric timestamp is now aligned with the session's
stop_timeinstead of the task execution time. This prevents traffic from being credited to the wrong time bucket when a session is closed or snapshotted later.Regression tests are added to ensure these paths dispatch the monitoring task correctly and use the correct timestamp.
Screenshot
Not applicable (no UI changes).