banger/packages.sh
Thales Maciel 3cf33d1e0a
Streamline VM overlays and rootfs packages
Move the default guest package list into a repo manifest and record a hash beside built rootfs images so run/make-rootfs can warn when the docker-ready image is stale.

Switch the Firecracker launch path to a single sparse root overlay per VM instead of separate /home and /var disks, so many VMs can share the same base image while still installing packages under /var and working from /root.

Keep older images bootable by masking stale home.mount and var.mount units at boot, and scrub those obsolete fstab entries when customize.sh rebuilds an image. Verified with bash -n on the updated scripts; no live VM boot was run in this environment.
2026-03-15 19:36:54 -03:00

115 lines
2.9 KiB
Bash

#!/usr/bin/env bash
BANGER_PACKAGES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BANGER_APT_PACKAGES_FILE="${BANGER_APT_PACKAGES_FILE:-$BANGER_PACKAGES_DIR/packages.apt}"
banger_packages_file() {
printf '%s' "$BANGER_APT_PACKAGES_FILE"
}
banger_packages_normalized_lines() {
local packages_file="${1:-$BANGER_APT_PACKAGES_FILE}"
[[ -f "$packages_file" ]] || return 1
awk '
{
sub(/\r$/, "")
sub(/[[:space:]]*#.*$/, "")
gsub(/^[[:space:]]+|[[:space:]]+$/, "")
if ($0 != "") print
}
' "$packages_file"
}
banger_packages_read_array() {
local -n out="$1"
local packages_file="${2:-$BANGER_APT_PACKAGES_FILE}"
mapfile -t out < <(banger_packages_normalized_lines "$packages_file")
(( ${#out[@]} > 0 ))
}
banger_packages_hash_stream() {
command -v sha256sum >/dev/null 2>&1 || return 1
sha256sum | awk '{print $1}'
}
banger_packages_manifest_hash() {
local packages_file="${1:-$BANGER_APT_PACKAGES_FILE}"
[[ -f "$packages_file" ]] || return 1
banger_packages_normalized_lines "$packages_file" | banger_packages_hash_stream
}
banger_rootfs_manifest_metadata_path() {
local rootfs_path="$1"
printf '%s.packages.sha256' "$rootfs_path"
}
banger_rootfs_manifest_recorded_hash() {
local rootfs_path="$1"
local metadata_file recorded_hash
metadata_file="$(banger_rootfs_manifest_metadata_path "$rootfs_path")"
[[ -f "$metadata_file" ]] || return 1
recorded_hash="$(head -n 1 "$metadata_file" | tr -d '[:space:]')"
[[ -n "$recorded_hash" ]] || return 1
printf '%s' "$recorded_hash"
}
banger_write_rootfs_manifest_metadata() {
local rootfs_path="$1"
local manifest_hash="$2"
local metadata_file
metadata_file="$(banger_rootfs_manifest_metadata_path "$rootfs_path")"
printf '%s\n' "$manifest_hash" > "$metadata_file"
}
banger_rootfs_manifest_status() {
local rootfs_path="$1"
local current_hash recorded_hash
if [[ ! -f "$rootfs_path" ]]; then
printf '%s' "missing-rootfs"
return 0
fi
if ! current_hash="$(banger_packages_manifest_hash)"; then
printf '%s' "unknown"
return 0
fi
if ! recorded_hash="$(banger_rootfs_manifest_recorded_hash "$rootfs_path")"; then
printf '%s' "missing-metadata"
return 0
fi
if [[ "$recorded_hash" == "$current_hash" ]]; then
printf '%s' "fresh"
else
printf '%s' "stale"
fi
}
banger_rootfs_manifest_warning() {
local rootfs_path="$1"
local status
status="$(banger_rootfs_manifest_status "$rootfs_path")"
case "$status" in
stale)
printf '%s was built with an older package manifest; rebuild it explicitly to pick up package changes' "$rootfs_path"
;;
missing-metadata)
printf '%s has no package manifest metadata; rebuild it explicitly to pick up package changes' "$rootfs_path"
;;
unknown)
printf 'unable to compare %s against %s; install sha256sum and verify the package manifest manually' "$rootfs_path" "$BANGER_APT_PACKAGES_FILE"
;;
*)
return 1
;;
esac
}