Is your feature request related to a problem? Please describe.
openwisp-firmware-upgrader is gaining a "persistent mass upgrades" feature (parent issue openwisp/openwisp-firmware-upgrader#379, implementation in PR #436). The feature introduces two new Celery Beat tasks:
openwisp_firmware_upgrader.tasks.check_pending_upgrades — scans for offline-device upgrades whose next_retry_at has elapsed and dispatches retry workers (recommended cadence: 10 minutes).
openwisp_firmware_upgrader.tasks.send_pending_upgrade_reminders — scans for long-running persistent batches and fires a generic_message notification when each batch's reminder cadence has elapsed (recommended scan cadence: 7 days; per-batch reminders every 60 days, configurable via OPENWISP_FIRMWARE_UPGRADER_PERSISTENT_REMINDER_PERIOD).
The package only registers these tasks in its own test settings. On a docker-openwisp install, images/common/openwisp/celery.py builds beat_schedule by merging per-module dicts (radius_schedule, topology_schedule, notification_schedule, monitoring_schedule, metric_collection_schedule), and there is no firmware_schedule to merge in — firmware-upgrader currently only contributes task_routes entries inside the USE_OPENWISP_FIRMWARE block at lines 34-42. Without this wiring, neither the retry loop nor the reminder notifications ever fire on docker installs.
Describe the solution I would implement
I would like to add the firmware_schedule block alongside the existing per-module schedules, mirroring how monitoring_schedule is wired today.
-
In images/common/openwisp/celery.py:
- Add
firmware_schedule to the empty-dict init tuple at lines 10-15 (currently radius_schedule, topology_schedule, monitoring_schedule, metric_collection_schedule).
- Inside the existing
if env_bool(os.environ.get("USE_OPENWISP_FIRMWARE")) and env_bool(os.environ.get("USE_OPENWISP_CELERY_FIRMWARE")) block at lines 34-42, populate it:
firmware_schedule = {
"check_pending_upgrades": {
"task": "openwisp_firmware_upgrader.tasks.check_pending_upgrades",
"schedule": timedelta(
minutes=int(os.environ.get(
"OPENWISP_FIRMWARE_CHECK_PENDING_PERIOD_MINUTES", 10,
)),
),
},
"send_pending_upgrade_reminders": {
"task": "openwisp_firmware_upgrader.tasks.send_pending_upgrade_reminders",
"schedule": timedelta(
days=int(os.environ.get(
"OPENWISP_FIRMWARE_REMINDER_SCAN_PERIOD_DAYS", 7,
)),
),
},
}
- Spread
**firmware_schedule into the beat_schedule={...} argument at lines 90-96.
-
In .env, the .env defaults block and the ENV lines in images/openwisp_base/Dockerfile:
- Add both env vars alongside the existing
USE_OPENWISP_FIRMWARE / USE_OPENWISP_CELERY_FIRMWARE block:
OPENWISP_FIRMWARE_CHECK_PENDING_PERIOD_MINUTES=10
OPENWISP_FIRMWARE_REMINDER_SCAN_PERIOD_DAYS=7
- Defaults of 10 minutes and 7 days are the recommended cadences from the upstream feature design. Operators tuning for very large fleets can override them without rebuilding the image.
-
In docs/user/settings.rst:
- Document both env vars in the
USE_OPENWISP_CELERY_FIRMWARE section around line 340, following the same shape as the existing OPENWISP_CELERY_FIRMWARE_COMMAND_FLAGS entry — one short paragraph each saying what it controls and what the default is.
-
In tests/runtests.py:
- The
test_celery assertion at lines 340-412 iterates expected_output_list looking for every task the worker should have registered. The firmware section at lines 361-364 lists four tasks today. Add the three new ones:
"openwisp_firmware_upgrader.tasks.check_pending_upgrades",
"openwisp_firmware_upgrader.tasks.retry_pending_upgrade",
"openwisp_firmware_upgrader.tasks.send_pending_upgrade_reminders",
retry_pending_upgrade isn't on the Beat schedule itself (it's only invoked by check_pending_upgrades.apply_async), but it does need to be registered on the worker so the dispatch lands somewhere, which is what test_celery checks for.
Tracked under the persistent-mass-upgrades parent in openwisp-firmware-upgrader so the docs PR there can link back here for deployers.
Is your feature request related to a problem? Please describe.
openwisp-firmware-upgrader is gaining a "persistent mass upgrades" feature (parent issue openwisp/openwisp-firmware-upgrader#379, implementation in PR #436). The feature introduces two new Celery Beat tasks:
openwisp_firmware_upgrader.tasks.check_pending_upgrades— scans for offline-device upgrades whosenext_retry_athas elapsed and dispatches retry workers (recommended cadence: 10 minutes).openwisp_firmware_upgrader.tasks.send_pending_upgrade_reminders— scans for long-running persistent batches and fires ageneric_messagenotification when each batch's reminder cadence has elapsed (recommended scan cadence: 7 days; per-batch reminders every 60 days, configurable viaOPENWISP_FIRMWARE_UPGRADER_PERSISTENT_REMINDER_PERIOD).The package only registers these tasks in its own test settings. On a docker-openwisp install,
images/common/openwisp/celery.pybuildsbeat_scheduleby merging per-module dicts (radius_schedule,topology_schedule,notification_schedule,monitoring_schedule,metric_collection_schedule), and there is nofirmware_scheduleto merge in — firmware-upgrader currently only contributestask_routesentries inside theUSE_OPENWISP_FIRMWAREblock at lines 34-42. Without this wiring, neither the retry loop nor the reminder notifications ever fire on docker installs.Describe the solution I would implement
I would like to add the
firmware_scheduleblock alongside the existing per-module schedules, mirroring howmonitoring_scheduleis wired today.In
images/common/openwisp/celery.py:firmware_scheduleto the empty-dict init tuple at lines 10-15 (currentlyradius_schedule, topology_schedule, monitoring_schedule, metric_collection_schedule).if env_bool(os.environ.get("USE_OPENWISP_FIRMWARE")) and env_bool(os.environ.get("USE_OPENWISP_CELERY_FIRMWARE"))block at lines 34-42, populate it:**firmware_scheduleinto thebeat_schedule={...}argument at lines 90-96.In
.env, the.envdefaults block and theENVlines inimages/openwisp_base/Dockerfile:USE_OPENWISP_FIRMWARE/USE_OPENWISP_CELERY_FIRMWAREblock:In
docs/user/settings.rst:USE_OPENWISP_CELERY_FIRMWAREsection around line 340, following the same shape as the existingOPENWISP_CELERY_FIRMWARE_COMMAND_FLAGSentry — one short paragraph each saying what it controls and what the default is.In
tests/runtests.py:test_celeryassertion at lines 340-412 iteratesexpected_output_listlooking for every task the worker should have registered. The firmware section at lines 361-364 lists four tasks today. Add the three new ones:retry_pending_upgradeisn't on the Beat schedule itself (it's only invoked bycheck_pending_upgrades.apply_async), but it does need to be registered on the worker so the dispatch lands somewhere, which is whattest_celerychecks for.Tracked under the persistent-mass-upgrades parent in openwisp-firmware-upgrader so the docs PR there can link back here for deployers.