diff --git a/meta-balena-common/recipes-containers/hostapp-update/files/hostapp-update b/meta-balena-common/recipes-containers/hostapp-update/files/hostapp-update index 9aa505c071..8448aae309 100644 --- a/meta-balena-common/recipes-containers/hostapp-update/files/hostapp-update +++ b/meta-balena-common/recipes-containers/hostapp-update/files/hostapp-update @@ -23,6 +23,43 @@ ERROR() { fi } +resolve_boot_dir_from_image() { + hostapp_image="$1" + overlay_root="${SYSROOT}/balena/overlay2" + layerdb_root="${SYSROOT}/balena/image/overlay2/layerdb/sha256" + + # We expect Hostapp images to be single-layer + # get the unique layer_id from the image + layer_id=$(balena inspect -f '{{index .RootFS.Layers 0}}' "$hostapp_image") + if [ -z "$layer_id" ]; then + ERROR "overlay2: image ${hostapp_image} has no RootFS layers" + exit 1 + fi + + # use cache-id to resolve boot dir + cache_id_path="${layerdb_root}/${layer_id#sha256:}/cache-id" + boot_dir="${overlay_root}/$(cat "$cache_id_path")/diff/boot" + if [ ! -d "$boot_dir" ]; then + ERROR "overlay2: failed to resolve boot dir for image ${hostapp_image}" + exit 1 + fi + + echo "$boot_dir" +} + +# Symlink hostapps boot to overlay2 layer diff/boot (no copy). +symlink_boot_from_overlay_layers() { + hostapp_new="${SYSROOT}/hostapps/.new" + + rm -rf "$hostapp_new" + mkdir -p "$hostapp_new" + + boot_dir=$(resolve_boot_dir_from_image "$HOSTAPP_IMAGE") + cache_id=$(basename "$(dirname "$(dirname "$boot_dir")")") + ln -sfn "../../balena/overlay2/${cache_id}/diff/boot" "${hostapp_new}/boot" + INFO "Symlinked ${hostapp_new}/boot -> ../../balena/overlay2/${cache_id}/diff/boot" +} + run_current_hooks_and_recover () { if [ "$hooks_rollback" = 1 ]; then # Run the current ones to cleanup the system. @@ -124,13 +161,9 @@ elif [ "$remote_image" != "" ]; then _out="$(balena pull "$HOSTAPP_IMAGE" 2>&1)" INFO "${_out}" fi -CONTAINER_ID=$(balena create --runtime="bare" --volume=/boot "$HOSTAPP_IMAGE" /bin/sh) -BOOTSTRAP=$(balena inspect -f "{{range .Mounts}}{{.Destination}} {{.Source}}{{end}}" "$CONTAINER_ID" | awk '$1 == "/boot" { print $2 }' | head -n1) +CONTAINER_ID=$(balena create --runtime="bare" "$HOSTAPP_IMAGE" /bin/sh) -# Create boot entry -rm -rf "$SYSROOT/hostapps/.new" -mkdir -p "$SYSROOT/hostapps/.new" -ln -sr "$BOOTSTRAP" "$SYSROOT/hostapps/.new/boot" +symlink_boot_from_overlay_layers sync -f "$SYSROOT" mv -T "$SYSROOT/hostapps/.new" "$SYSROOT/hostapps/$CONTAINER_ID" sync -f "$SYSROOT"