Generate version information for RAUC when rauc.db is empty (#3436)

RAUC currently doesn't know the version of the booted slot when booted for the
first time or after wiping the data partition. As a result `ha os info` is
missing this information too.

As there's no built-in mechanism for generating these data by RAUC itself, add
a oneshot service that checks if the boot slot information is contained in the
rauc.db and if not, then generate it.

RAUC seems to cope quite well even with bogus data contained in rauc.db but in
any case, a test has been added to check that everything works as expected.
This commit is contained in:
Jan Čermák 2024-06-20 16:50:14 +02:00 committed by GitHub
parent 87a6c84025
commit 6c7b6fdebe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 67 additions and 4 deletions

View File

@ -0,0 +1,12 @@
[Unit]
Description=Ensure rauc.db contains version information
After=rauc.service
Before=hassos-supervisor.service
RequiresMountsFor=/mnt/data
[Service]
Type=oneshot
ExecStart=/usr/libexec/raucdb-update
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,39 @@
#!/bin/sh
# shellcheck disable=SC1091
set -e
if grep -q 'slot\.boot\.0' /mnt/data/rauc.db; then
echo "[INFO] rauc.db already contains slot information"
exit 0
fi
echo "[INFO] Generating rauc.db from os-release data"
eval "$(rauc status --output-format=shell)"
if [ -z "${RAUC_SYSTEM_BOOTED_BOOTNAME}" ]; then
echo "[ERROR] RAUC_SYSTEM_BOOTED_BOOTNAME is empty"
exit 1
fi
CURRENT_SLOT_ID=$(test "${RAUC_SYSTEM_BOOTED_BOOTNAME}" = "A" && echo 0 || echo 1)
. /etc/os-release
cat >> /mnt/data/rauc.db <<EOF
[slot.boot.0]
bundle.compatible=${RAUC_SYSTEM_COMPATIBLE}
bundle.version=${VERSION_ID}
[slot.kernel.${CURRENT_SLOT_ID}]
bundle.compatible=${RAUC_SYSTEM_COMPATIBLE}
bundle.version=${VERSION_ID}
[slot.rootfs.${CURRENT_SLOT_ID}]
bundle.compatible=${RAUC_SYSTEM_COMPATIBLE}
bundle.version=${VERSION_ID}
EOF
/usr/bin/systemctl restart rauc.service

View File

@ -36,11 +36,23 @@ def test_init(shell):
@pytest.mark.dependency(depends=["test_init"]) @pytest.mark.dependency(depends=["test_init"])
def test_rauc_status(shell): def test_rauc_status(shell, shell_json):
output = shell.run_check("rauc status --output-format=shell") rauc_status = shell.run_check("rauc status --output-format=shell --detailed")
# RAUC_BOOT_PRIMARY won't be set if correct grub env is missing # RAUC_BOOT_PRIMARY won't be set if correct grub env is missing
assert "RAUC_BOOT_PRIMARY='kernel.0'" in output assert "RAUC_BOOT_PRIMARY='kernel.0'" in rauc_status
assert "rauc-WARNING" not in "\n".join(output) assert "rauc-WARNING" not in "\n".join(rauc_status)
os_info = shell_json("ha os info --no-progress --raw-json")
expected_version = os_info.get("data", {}).get("version")
assert expected_version is not None and expected_version != ""
boot_slots = filter(lambda x: "RAUC_SYSTEM_SLOTS=" in x, rauc_status)
boot_slots = next(boot_slots, "").replace("RAUC_SYSTEM_SLOTS='", "").replace("'", "")
assert boot_slots != ""
booted_idx = boot_slots.split(" ").index("kernel.0")
assert booted_idx >= 0
assert f"RAUC_SLOT_STATUS_BUNDLE_VERSION_{booted_idx + 1}='{expected_version}'" in rauc_status
@pytest.mark.dependency(depends=["test_init"]) @pytest.mark.dependency(depends=["test_init"])