Adding state scripts to mender-configure artifacts generated via GUI

Good time of the day.

I have been working on Mender integration within the system I have on my end and came to a bit of a roadblock with mender-configure addon.

I found mender-configure addon to be quite useful for setting per-device timezones and hostnames (possibly, more things will be set later). Hence, I would like to keep the addon. However, it does seem to have some limitations. Let me elaborate.

Current system design:

  • dir update module is being used to release application-level updates.
  • rootfs update module is being used to release system-level updates.
  • mender-configure addon is being used to set hostname and timezones per-device.

Note: App is packed inside rootfs updates whenever a rootfs update is released.

Current boot up flow:

  • RPi boots up
  • Custom application boots up and goes into idle mode for 3 minutes. This allows mender-client to check for an update
  • In case update is available, Download_Enter rootfs state script sends a command to an application to be terminated. In case no update is available, application times out within 3 minutes and starts executing regular flow.

Because of aforementioned app termination in case of update availability, an application boot up must happen some time:

  • In terms of rootfs updates, system reboot will happen anyway to switch between A/B partitions. This will be sufficient to kickstart the bootup of a new app. (keeping in mind that new app is packed within rootfs update)
  • In case of dir update, no system reboot will happen but ArtifactCommit_Leave and ArtifactFailure_Leave state scripts will handle an application bootup.
  • In case of mender-configure update, there is no clear way of kickstarting an application.

So far, I think these are some possibilities:

  • Improve logic of Download_Enter state script by checking what type of deployment is pending. But for this, an ability to read deployment info is required. Is it possible to read deployment info from mender-client?
  • Attach a state script to mender-configure generated artifacts (to make it look similar to dir). However this note makes me thing this might be impossible. Is it possible to interact with the way mender-configure generates the artifacts on the backend?
  • Move ArtifactCommit_Leave and ArtifactFailure_Leave state scripts away from the artifacts and put them under rootfs. Will they even be run in such a case?

I am looking forward to any ideas at this stage.

Hi @dmitrijsan,

Thanks for reaching out and the perfect description. While I don’t have a direct solution for you, two pointers to possibly proceed:

  • it is possible to manually create mender-configure artifacts using the mender-artifact tool (in fact, this is required if you want to use signing). This way you can add state scripts.
  • alternatively, think about extending the mender-configure update module to suit your needs. The mechanism is invoked with the Update Module filename as the identification, so as long as you keep it you can modify it as you wish. This way you could both keep the UI mechanisms, as well as avoid shipping additional scripts.

Greetz,
Josef

Thanks for a prompt response, @TheYoctoJester.

I do like proposed solutions, however, both of them have limitations:

  • Using mender-artifact to create mender-configure update module artifact sound like the way with the most flexibility. However, this eliminates usage of GUI element of mender-configure - it becomes read-only thing.
  • In terms of modifying mender-configure update module - this allows to kind of “bake in” any type of state script I want into it (modification required somewhere here, i think). However, this creates a fork of current mender-configure, which needs to be kept up-to-date with the source.

While writing this message, I have realised one thing - since mender-configure does have an ability to execute scripts (i.e. to set the timezone or hostname via apply-device-config.d), why not create a script that boots up an application? This will kind of simulate a rootfs state script behaviour. And according to docs, it is possible to ensure the sequence of scripts executed within apply-device-config.d:

All scripts in /usr/lib/mender-configure/apply-device-config.d are run in lexicographic order.

Note to self:

  • 0,1,2,3,4,5,6,7,8,9,10 is NOT lexicographic order. Instead, 0,1,10,2,3,4,5,6,7,8,9 is the lexicographic order of numbers before.
  • 01,02,03,04,05,06,07,08,09,10 is lexicographic order.

Hence, by giving all of the scripts a sequence number (i.e. 00_hostname, 01_timezone, 02_something_else, … , 99_start_app), I can have a granular control of the time to start up the app.

Lastly, I have checked behaviour of apply-device-config.d in case one of scripts returns non-zero code. Seems like all of the scripts are being executed, while recording if any of them returned non-zero code (this is valid as of v1.1.1 of mender-configure available here). This is desired behaviour in my case - this will ensure that all scripts were run, no matter the return code, before starting the app.

Obviously, there is still a chance that one of the scripts within apply-device-config.d fails (returns non-zero code), app gets started by the last apply-device-config.d script, then mender-configure transitions to ArtifactRollback. This means that app will already be running even though mender-configure is still doing some work (ArtifactRollback in particular). However, since in my case, app is having initial 3 minute idle period, it will not affect app in any way.

Do you think it might be a viable option? If so, I have 3 different scenarios to test to see which one will be preferred in my case.

Again, thanks for such a prompt response and providing such an amazing product with so much customisation!

1 Like

Hi @dmitrijsan,

Yeah, sounds like a third option. If you happen to try all, let us know the outcome please. My personal favorite probably would be modifying the mender-configure Update Module. If you feel like not tinkering with the code in itself, you could also just rename it to configure-internal, and forward all calls from your own wrapper which takes the original name. This way you could have a clear separation between upstream and custom code while still extending it - and you immediately can catch all return conditions.

Greetz,
Josef

Hi, @TheYoctoJester

Thanks for providing prompt responses.

After careful considerations, a decision was made to utilise mender-artifact to generate mender-configure updates. This brings the most value:

  • It allows to use state scripts, which are required in my scenario
  • It allows to use artifact signing. Basically, inability to sign mender-configure artifacts via GUI was the only thing that was holding me back from using artifact signing in general.

Hence, I decided it is worth missing ability to use write option of mender-configure GUI for a benefit, described above.

Marking your response as a solution.

Thank you for hanging around and being responsive!

PS I will do some docs PR later - found some improvement possibilities.

1 Like