Skip to content

hawkbit-client: Add support for soft rollout action type with optional D-Bus readiness check#217

Open
a-elkaim wants to merge 2 commits into
rauc:masterfrom
a-elkaim:support-hawkbit-soft-rollouts
Open

hawkbit-client: Add support for soft rollout action type with optional D-Bus readiness check#217
a-elkaim wants to merge 2 commits into
rauc:masterfrom
a-elkaim:support-hawkbit-soft-rollouts

Conversation

@a-elkaim

Copy link
Copy Markdown

HawkBit supports four rollout action types: Forced, Soft, Time Forced, and Download Only.

Before this change, the updater did not distinguish between Forced and Soft, all deployments that reached the install step were treated identically regardless of whether hawkBit signalled the update as being at the device's discretion (soft mode).

So I made the following changes to support it:

  • Action type detection (src/hawkbit-client.c): The updater now infers the action type from the deployment handling fields (download/update) and logs it on each poll cycle. This makes behavior more transparent and is the foundation for type-specific handling.

  • Soft update readiness gate: For soft updates (DDI fields download=attempt, update=attempt), the updater can optionally call IsReadyForUpdate() on a configurable D-Bus service (system bus) before proceeding. The rationale is that hawkBit's Soft semantic explicitly leaves the installation decision to the device, so it is appropriate to let another application (such as a UI or workload manager) gate the update (e.g. to defer it until the device is idle or the user has consented).

    • If the service returns True, the update proceeds normally.

    • If it returns False, the update is silently skipped; no error is reported to hawkBit, so the action remains open and the check is retried on the next poll cycle (controlled by retry_wait).

      • Forced and Download Only updates bypass this check entirely — they are applied unconditionally as before.
      • Time Forced actions report as Soft until their deadline; hawkBit then transparently switches them to Forced, so they will bypass the check once forced.
  • New configuration keys (config.conf.example, include/config-file.h, src/config-file.c):

      [client]
      # D-Bus well-known name of the permission service (unset = no check)
      soft_update_check_dbus_service = de.example.SoftUpdateCheck
    
      # When the service is unreachable: true (default) = force the update, false = skip it
      soft_update_check_force_on_unavailable = true
    
  • Documentation (README.md): A new Soft Update Permission Check section documents the feature, the expected D-Bus interface, and the required system bus policy file.

  • Tests (test/test_soft.py, test/soft_update_check_dbus_dummy.py, test/conftest.py): Six integration tests cover the full matrix of scenarios:

    • Soft update with no check configured (unconditional install)
    • Check configured, service grants permission (install proceeds)
    • Check configured, service denies permission (update skipped, hawkBit action left open)
    • Check configured, service unreachable, force_on_unavailable=true (default — install forced through)
    • Check configured, service unreachable, force_on_unavailable=false (update skipped)
    • Forced update with a denying service configured (check bypassed, install proceeds)

A D-Bus dummy service (soft_update_check_dbus_dummy.py) is provided for use in tests and manual verification.

@a-elkaim a-elkaim force-pushed the support-hawkbit-soft-rollouts branch from 109f99c to b28cdb7 Compare April 20, 2026 07:58
@Bastian-Krause

Copy link
Copy Markdown
Member

Just skimming through this: I think this has some overlaps with #165, which implements the DBus interface on rauc-hawkbit-updater's side. Due to the size and limited time, we have not had the chance to review that unfortunately. But your approach seems interesting. Maybe @UVV-gh has an opinion on this one?

I guess you'll need some patience until this gets reviewed, #165 has priority because it's open for so long. Ideally, we find a common, consistent DBus concept for both of them until they are merged.

@Bastian-Krause Bastian-Krause added the enhancement New feature or request label May 19, 2026
@a-elkaim

Copy link
Copy Markdown
Author

Just skimming through this: I think this has some overlaps with #165, which implements the DBus interface on rauc-hawkbit-updater's side. Due to the size and limited time, we have not had the chance to review that unfortunately. But your approach seems interesting. Maybe @UVV-gh has an opinion on this one?

I guess you'll need some patience until this gets reviewed, #165 has priority because it's open for so long. Ideally, we find a common, consistent DBus concept for both of them until they are merged.

When looking at #165 I figured it was another feature, it wasn't clear to me if this was related to the soft/forced OTA types.

The end goal seems similar, so maybe we can indeed find a common, consistent DBus concept for both of them.

In the meantime, I am using my own branch to avoid having soft updates applied while the system is in use (I am working on a sort of video player that is using a schedule to play pre-defined content, if a soft OTA arrives, it should be applied outside of the active schedule).

Let me know if I can assist in further developments.

@UVV-gh

UVV-gh commented May 20, 2026

Copy link
Copy Markdown
Contributor

Yeah, it's ultimately the same goal just implemented differently. When I worked on it and discussed it with the maintainers I didn't get any semantics on the soft assignment behavior, therefore we opted for download-only path and a service that could communicate separately to the server when the update is installed.

The rationale is that hawkBit's Soft semantic explicitly leaves the installation decision to the device, so it is appropriate to let another application (such as a UI or workload manager) gate the update (e.g. to defer it until the device is idle or the user has consented).

Are you sure that's what Hawkbit expects? ;) The thing is it's hardly documented anywhere expect the actual source code state machine. What do you want to return to Hawkbit in https://hawkbit.eclipse.dev/rest-api/ddi.html#tag/DDI-Root-Controller/operation/postDeploymentBaseActionFeedback ?
I guess we decided to use download-only approach because there's a possibility in Hawkbit to switch from soft to force and that is unacceptable in our case. And later they introduced ConfirmationBase endpoint, which was enough for us.

@Bastian-Krause I'd say this PR complements mine, because "soft" rollouts are present in both, DeploymentBase and ConfirmationBase APIs. I'm still not sure what "soft" would mean in case of ConfirmationBase :)

Comment thread include/config-file.h
gboolean send_download_authentication; /**< Send security header in download requests */
gchar* soft_update_check_dbus_service; /**< D-Bus service name to call for soft update
permission; NULL disables the check */
gboolean soft_update_check_force_on_unavailable; /**< if TRUE (default), proceed with the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would actually prefer a safer default here, meaning false. And it looks like your commit message claims the opposite, or I'm misreading something.

@a-elkaim a-elkaim May 20, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch ! My first commit message was containing an error regarding the default value, it is now fixed :)

That being said, the logic I had in mind is the following:

  • If soft_update_check_force_on_unavailable is set to true, then a soft update could still be applied immediately upon failing to reach the service. The idea is not to block a potential critical update (one could argue that a critical update should be forced and not soft).

  • Else, if set to false, we can rely on soft_update_check_unavailable_max_retries (if set) to still apply an update after N consecutive failures.

What do you think ?

a-elkaim added 2 commits May 20, 2026 16:11
Previously all deployments ready to install were treated as forced.

Adds detection of soft actions and an optional config option to gate
installation via an external D-Bus service.

If the D-Bus service returns false, the update is silently deferred
to the next poll cycle. Otherwise, the update is applied.

An option also has been added to define fallback behavior when the
service is unreachable: true = force the update (default), false = skip
When soft_update_check_force_on_unavailable is false, a permanently
unreachable permission service would silently block updates forever.

Add soft_update_check_unavailable_max_retries (default 0, disabled):
when set to N, the client tracks consecutive poll cycles where the
service is unreachable and forces the update after N failures. The
counter resets when the service becomes reachable again or a new
deployment is received.
@a-elkaim a-elkaim force-pushed the support-hawkbit-soft-rollouts branch from 71fcead to 66acaa3 Compare May 20, 2026 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants