Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions developer/gsoc-ideas-2026.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1039,3 +1039,164 @@ Expected Outcomes
- Comprehensive **documentation**, including setup guides and best
practices.
- A **short tutorial video** demonstrating installation and usage.

Persistent & Scheduled Firmware Upgrades
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. image:: ../images/gsoc/ideas/2023/firmware.jpg
Copy link

@coderabbitai coderabbitai bot Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the 2023 image exists
echo "=== Checking for firmware.jpg in images/gsoc/ideas/ ==="
fd -t f "firmware.jpg" images/gsoc/ideas/

# Check directory structure
echo ""
echo "=== Directory structure of images/gsoc/ideas/ ==="
fd -t d . images/gsoc/ideas/ 2>/dev/null | head -20

# List all files in 2023 directory if it exists
echo ""
echo "=== Files in images/gsoc/ideas/2023/ if it exists ==="
ls -la images/gsoc/ideas/2023/ 2>/dev/null || echo "Directory does not exist"

# List all files in 2026 directory if it exists
echo ""
echo "=== Files in images/gsoc/ideas/2026/ if it exists ==="
ls -la images/gsoc/ideas/2026/ 2>/dev/null || echo "Directory does not exist"

# Check for any year-named directories
echo ""
echo "=== Year-based directories in images/gsoc/ideas/ ==="
ls -d images/gsoc/ideas/20*/ 2>/dev/null || echo "No year-based directories found"

Repository: openwisp/openwisp-docs

Length of output: 1119


🏁 Script executed:

#!/bin/bash
# Read context around line 1046 to see the project idea
echo "=== Context around line 1046 in developer/gsoc-ideas-2026.rst ==="
sed -n '1030,1070p' developer/gsoc-ideas-2026.rst

# Also check if there are other 2023 image references in the 2026 file
echo ""
echo "=== All image references in developer/gsoc-ideas-2026.rst ==="
grep -n "image::" developer/gsoc-ideas-2026.rst

Repository: openwisp/openwisp-docs

Length of output: 2316


Update image path to use 2026 version

The image path at line 1046 references ../images/gsoc/ideas/2023/firmware.jpg but this is a 2026 project idea document. The correct 2026 firmware-upgrader image exists at ../images/gsoc/ideas/2026/firmware-upgrader-openwrt-image-metadata-extraction.webp and should be used instead.

Change line 1046 from:

.. image:: ../images/gsoc/ideas/2023/firmware.jpg

to:

.. image:: ../images/gsoc/ideas/2026/firmware-upgrader-openwrt-image-metadata-extraction.webp
🤖 Prompt for AI Agents
In `@developer/gsoc-ideas-2026.rst` at line 1046, Replace the outdated image
directive string ".. image:: ../images/gsoc/ideas/2023/firmware.jpg" with the
2026 image path ".. image::
../images/gsoc/ideas/2026/firmware-upgrader-openwrt-image-metadata-extraction.webp"
so the document references the correct 2026 firmware-upgrader image; locate the
exact directive line matching the original string and update it to the new path.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fine

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nemesifier, understood! I'll keep the existing image reference.

🐰


.. important::

Languages and technologies used: **Python**, **Django**, **Celery**,
**REST API**, **JavaScript**.

**Mentors**: *Federico Capoano*, *TBA*.

**Project size**: 350 hours.

**Difficulty rate**: medium.

This project aims to enhance `OpenWISP Firmware Upgrader
<https://github.com/openwisp/openwisp-firmware-upgrader>`__ with two
complementary features that improve reliability and operational
flexibility for mass firmware upgrades: **persistent retries** for offline
devices (`#379
<https://github.com/openwisp/openwisp-firmware-upgrader/issues/379>`__)
and **scheduled execution** for planned maintenance windows (`#380
<https://github.com/openwisp/openwisp-firmware-upgrader/issues/380>`__).

Currently, firmware upgrades in OpenWISP happen immediately via Celery
tasks. If a device is offline at the moment of upgrade, the task fails and
requires manual retry. In large deployments, this becomes unmanageable.
Additionally, network operators need the ability to schedule upgrades
during low-usage windows without manual intervention at execution time.

Expected outcomes
+++++++++++++++++

Introduce support for **persistent mass upgrades** that automatically
retry for offline devices and **scheduled mass upgrades** that execute at
a user-defined future time.

1. **Persistent mass upgrades** (`#379
<https://github.com/openwisp/openwisp-firmware-upgrader/issues/379>`__)

Mass upgrade operations should be able to retry indefinitely for
devices that are offline at the initial execution time.

- Add a ``persistent`` boolean field to mass upgrade operations
(visible in admin and REST API, checked by default, immutable after
creation).
- Track retry count and scheduled retry time in the
``UpgradeOperation`` model.
- Implement **device online detection**:

- Prefer using the ``health_status_changed`` signal from OpenWISP
Monitoring (with mocking for testing).
- Fallback: periodic retries with randomized exponential backoff
(configurable, max once every 12 hours).

- Implement **retry strategy**:

- Randomized exponential backoff with indefinite retries.
- Periodic reminders (default every 2 months) via
``generic_notification`` to admins about devices still pending
upgrade, with links filtering pending devices.
- Continue until admin cancels or all devices are upgraded.

- **Integration with Celery**: Use a new Celery task to "wake up"
pending upgrades, with randomized delays to prevent system overload.
- **Failure handling**: Use ``generic_notification`` for failures
requiring attention (devices offline too long, upgrade errors).
- **Edge cases**: Handle concurrent signal triggers, ensure only one
upgrade per device, no rollback support needed.

2. **Scheduled mass upgrades** (`#380
<https://github.com/openwisp/openwisp-firmware-upgrader/issues/380>`__)

Allow users to schedule mass upgrades for future execution.

- **UI**: Add optional datetime scheduling on mass upgrade confirmation
page. Default is immediate execution unless a future datetime is set.
- **Validation**: Scheduled datetime must be:

- In the future
- Respect minimum delay (e.g., 10 minutes)
- Not exceed maximum horizon (e.g., 6 months)

- **Timezone handling**: User input in browser timezone, storage in
UTC, server timezone clearly indicated in UI.
- **Status model**: Extend to include ``scheduled`` state with
transitions: scheduled → running, scheduled → canceled, scheduled →
failed.
- **Execution model**: Use Celery Beat periodic task (every minute) to
scan and execute due upgrades. **Avoid Celery eta/countdown** for
reliability with far-future tasks.
- **Runtime validation**: Re-evaluate devices, permissions, firmware
availability at execution time. Cancel with error if all targets
become invalid.
- **Conflict prevention**: Prevent creating conflicting mass upgrades
(scheduled or immediate) when one is already pending.
- **Notifications**: Send ``generic_notification`` when scheduled
upgrades start and complete.

3. **Combined features**

Scheduled upgrades should also support persistence. A scheduled upgrade
that starts but has offline devices should continue retrying according
to the persistence logic.

4. **General requirements**

- Operations editable only while in ``scheduled`` status.
- Clear exposure of scheduled status and datetime in admin list, detail
view, and REST API.
- Full feature parity between Django admin and REST API.

5. **Testing and documentation**

- Test coverage **must not decrease** from current levels.
- **Browser tests** for the scheduling UI and admin interface workflows
are required.
- Documentation has to be kept up to date, including:

- Usage instructions for persistent and scheduled upgrades.
- Updated screenshots reflecting UI changes.
- One short example usage video per each feature.

Prerequisites to work on this project
+++++++++++++++++++++++++++++++++++++

Applicants must demonstrate a solid understanding of:

- **Python**, **Django**, and **JavaScript**.
- REST APIs and background task processing (Celery, Celery Beat).
- Timezone handling and datetime management.
- Experience with `OpenWISP Firmware Upgrader
<https://github.com/openwisp/openwisp-firmware-upgrader>`__ is
essential. Contributions or resolved issues in this repository are
considered strong evidence of the required proficiency.

Open questions for contributors
+++++++++++++++++++++++++++++++

1. **Persistence implementation**: What is the optimal database schema for
tracking persistent upgrade state while maintaining compatibility with
existing upgrade operation models?
2. **Scheduling mechanism**: How exactly should the Celery Beat periodic
task be configured to reliably detect and execute due scheduled
upgrades without performance issues?
3. **Timezone UX**: What is the best way to handle timezone display and
input in the admin interface to minimize user confusion?
4. **Backoff strategy**: What are the optimal parameters for randomized
exponential backoff (initial delay, max delay, randomization factor)?
5. **Conflict detection**: How should conflicting operations be detected
and prevented? What defines a "conflict"?
6. **Monitoring integration**: How exactly should the
``health_status_changed`` signal from OpenWISP Monitoring be integrated
for optimal online detection?
7. **Notification frequency**: What are the optimal default periods for
reminder notifications about pending persistent upgrades?
8. **Edge case handling**: How should edge cases be handled, such as
devices that are offline for months, or mass upgrades with very large
device counts?
Comment on lines +1042 to +1202
Copy link

@coderabbitai coderabbitai bot Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for duplicates of the section title
echo "=== Searching for section title occurrences ==="
rg -n "Persistent & Scheduled Firmware Upgrades" developer/gsoc-ideas-2026.rst

echo ""
echo "=== File line count ==="
wc -l developer/gsoc-ideas-2026.rst

echo ""
echo "=== Checking if image file exists ==="
ls -la developer/images/gsoc/ideas/2023/firmware.jpg 2>&1 || echo "2023 image not found"
ls -la developer/images/gsoc/ideas/2026/firmware.jpg 2>&1 || echo "2026 image not found"
ls -la developer/images/gsoc/ideas/firmware.jpg 2>&1 || echo "Generic firmware image not found"

echo ""
echo "=== Checking context around lines 1042-1046 ==="
sed -n '1040,1050p' developer/gsoc-ideas-2026.rst

Repository: openwisp/openwisp-docs

Length of output: 960


Fix broken image reference: the image file does not exist at the specified path.

The reference ../images/gsoc/ideas/2023/firmware.jpg at line 1046 points to a non-existent file. The image must be either:

  • Added to the correct location in the repository, or
  • The path corrected to point to an existing image file

Verify the correct image path or provide the missing image file before merging.

🤖 Prompt for AI Agents
In `@developer/gsoc-ideas-2026.rst` around lines 1042 - 1202, The RST image
directive referencing '../images/gsoc/ideas/2023/firmware.jpg' inside the
"Persistent & Scheduled Firmware Upgrades" section is broken; either add the
missing image file at that path in the repo or update the image directive to
point to an existing image. Locate the image directive string
'../images/gsoc/ideas/2023/firmware.jpg' in developer/gsoc-ideas-2026.rst (under
the "Persistent & Scheduled Firmware Upgrades" heading) and either commit the
correct image file to that images folder or change the path to the correct
existing image filename, then verify Sphinx builds without missing-file
warnings.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The image exists.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the image exists at the correct resolved path
echo "=== Checking image at correct resolved path ==="
if [ -f "images/gsoc/ideas/2023/firmware.jpg" ]; then
    echo "✓ Image exists at: images/gsoc/ideas/2023/firmware.jpg"
    ls -lh images/gsoc/ideas/2023/firmware.jpg
else
    echo "✗ Image not found at: images/gsoc/ideas/2023/firmware.jpg"
fi

echo ""
echo "=== Listing contents of images/gsoc/ideas/2023/ ==="
ls -la images/gsoc/ideas/2023/ 2>&1 || echo "Directory does not exist"

echo ""
echo "=== Verifying relative path resolution ==="
echo "RST file location: developer/gsoc-ideas-2026.rst"
echo "Relative reference: ../images/gsoc/ideas/2023/firmware.jpg"
echo "Resolves to: images/gsoc/ideas/2023/firmware.jpg (from repo root)"

Length of output: 719


@nemesifier, you're absolutely right—I apologize for the incorrect flag. The image does exist at images/gsoc/ideas/2023/firmware.jpg and the relative reference ../images/gsoc/ideas/2023/firmware.jpg from developer/gsoc-ideas-2026.rst resolves correctly to this file. My initial script checked an incorrect path. The image reference is valid. ✓