Crates.io | caterpillar |
lib.rs | caterpillar |
version | 0.2.0 |
source | src |
created_at | 2023-09-06 15:38:48.729334 |
updated_at | 2023-09-28 13:28:29.046888 |
description | Detect and apply RAUC update bundles during boot |
homepage | |
repository | https://github.com/dvzrv/caterpillar |
max_upload_size | |
id | 965410 |
size | 337,595 |
A tool for the detection and installation of RAUC update bundles found on attached block devices. RAUC is a way to update firmware on embedded devices.
Caterpillar makes use of D-Bus to communicate with
The application also exposes its own D-Bus interface. More information on how to use it can be found in the interactive update section.
Some aspects of caterpillar
's behavior can be configured using a configuration file in /etc/caterpillar/caterpillar.toml
.
It is also possible to override behavior using environment variables in all caps, prefixed with CATERPILLAR_
(e.g. autorun = true
-> CATERPILLAR_AUTORUN=true
).
Caterpillar supports two modes of operation, non-interactive and interactive, which are explained in more detail in the sections below.
The application is run in the background using the caterpillar.service
systemd unit.
Other applications running as root
can communicate with it over D-Bus.
Caterpillar takes care of detecting all attached block devices and mounts compatible filesystems found on them.
In the top-level directory of each mounted filesystem it searches for compatible RAUC update bundles with a version higher than the current system version and allows for installing them.
When placing a single compatible bundle in a configurable override directory, caterpillar
is able to install bundles of lower version as well.
NOTE: Only semver version comparison is supported!
After successful update, caterpillar
unmounts all previously mounted devices and can optionally trigger a reboot of the system (to boot into the updated system).
A rough overview of caterpillar
's interaction with rauc
and udisks2
is outlined in the below diagram:
Caterpillar exposes a D-Bus interface, which allows external applications running as root
to communicate with it.
The application starts in idle
mode, waiting on external input.
[root@system ~]# busctl introspect de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.InstallUpdate method bb - -
.SearchForUpdate method - - -
.MarkedForReboot property b false emits-change
.State property s "idle" emits-change
.Updated property b false emits-change
.UpdateFound signal a(sssb) - -
NOTE: It is advised to subscribe to the UpdateFound
signal, which will propagate a found update.
Using the SearchForUpdate
method, caterpillar
can be requested to search for compatible updates:
[root@system ~]# busctl call de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar SearchForUpdate
If a compatible update is found, caterpillar
's State
property changes to updatefound
(noupdatefound
, if no update is found, shortly after which it unmounts mounted devices again and returns to idle
).
[root@system ~]# busctl introspect de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.InstallUpdate method bb - -
.SearchForUpdate method - - -
.MarkedForReboot property b false emits-change
.State property s "updatefound" emits-change
.Updated property b false emits-change
.UpdateFound signal a(sssb) - -
The UpdateFound
signal is emitted, providing an array of length one with information on the available update:
[root@system ~]# dbus-monitor --system "type='signal',path='/de/sleepmap/Caterpillar',interface='de.sleepmap.Caterpillar',member='UpdateFound'"
signal time=1695853835.109057 sender=:1.37 -> destination=(null destination) serial=8 path=/de/sleepmap/Caterpillar; interface=de.sleepmap.Caterpillar; member=UpdateFound
array [
struct {
string "/run/media/root/bundle_disk_btrfs/update.raucb"
string "0.0.0"
string "1.0.0"
boolean false
}
]
Using the InstallUpdate
method, caterpillar
can be triggered to either install (and optionally reboot) or skip a found update.
When requesting to skip the update and not reboot (requesting to reboot has no effect when not also updating), caterpillar
unmounts all previously mounted devices and returns to its idle
state (with the Updated
property unchanged).
[root@system ~]# busctl call de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar InstallUpdate bb false false
[root@system ~]# busctl introspect de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.InstallUpdate method bb - -
.SearchForUpdate method - - -
.MarkedForReboot property b false emits-change
.State property s "idle" emits-change
.Updated property b false emits-change
.UpdateFound signal a(sssb) - -
When requested to update but not reboot, caterpillar
updates the system, unmounts all previously mounted devices and returns to its idle
state, setting its Updated
property to true
on successful update.
[root@system ~]# busctl call de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar InstallUpdate bb true false
[root@system ~]# busctl introspect de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.InstallUpdate method bb - -
.SearchForUpdate method - - -
.MarkedForReboot property b false emits-change
.State property s "updating" emits-change
.Updated property b false emits-change
.UpdateFound signal a(sssb) - -
[root@system ~]# busctl introspect de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.InstallUpdate method bb - -
.SearchForUpdate method - - -
.MarkedForReboot property b false emits-change
.State property s "idle" emits-change
.Updated property b true emits-change
.UpdateFound signal a(sssb) - -
When requested to update and reboot, caterpillar
updates the system, unmounts all previously mounted devices and goes to done
state. Its Updated
and MarkedForReboot
properties are both set to true
.
[root@system ~]# busctl call de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar InstallUpdate bb true false
[root@system ~]# busctl introspect de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.InstallUpdate method bb - -
.SearchForUpdate method - - -
.MarkedForReboot property b true emits-change
.State property s "updating" emits-change
.Updated property b false emits-change
.UpdateFound signal a(sssb) - -
[root@system ~]# busctl introspect de.sleepmap.Caterpillar /de/sleepmap/Caterpillar de.sleepmap.Caterpillar
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.InstallUpdate method bb - -
.SearchForUpdate method - - -
.MarkedForReboot property b true emits-change
.State property s "done" emits-change
.Updated property b true emits-change
.UpdateFound signal a(sssb) - -
Caterpillar can be configured to run non-interactively the first time it is run, using the autorun
configuration option.
In this mode the application will automatically (without user input):
Caterpillar is written in Rust and built using cargo:
cargo build --frozen --release --all-features
Unit tests can be executed using
cargo test -- --skip integration
NOTE: The integration test setup requires quite some space (ca. 10 - 20 GiB) and can only be run serially (which takes quite long).
cargo test integration
The integration tests require the following tools to be available on the test system:
All code contributions are dual-licensed under the terms of the Apache-2.0 and MIT. For further information on licensing refer to the contributing guidelines.
This project has been made possible by the funding of Nonlinear Labs GmbH.