90 lines
3.3 KiB
Bash
Executable File
90 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# spdk-ctl.sh — host-side fleet release ops for the LONG-LIVED SPDK target.
|
|
#
|
|
# Stages a release's artifacts into ./releases/<version>/ and adds/removes it on
|
|
# the running nvmf_tgt ONLINE — no container restart, no dropped connections.
|
|
# This is the operator entrypoint for rolling updates and cleanup; it wraps the
|
|
# in-container spdk-release control script (driven via `docker compose exec`).
|
|
#
|
|
# ./spdk-ctl.sh load <version> [oci_ref] # stage + add live (oci_ref default: $OCI_IMAGE:<version>)
|
|
# ./spdk-ctl.sh unload <version> [--force] # drain-gated remove + delete staged files
|
|
# ./spdk-ctl.sh list # served versions + connected hosts
|
|
#
|
|
# Typical rollout:
|
|
# ./spdk-ctl.sh load 1.3.0 # serve the new version alongside the old
|
|
# # ... reboot hosts onto 1.3.0 (deployment manifest digest bump) ...
|
|
# ./spdk-ctl.sh list # watch 1.2.0 CONNS fall to 0
|
|
# ./spdk-ctl.sh unload 1.2.0 # cleanup once drained (refuses if hosts remain)
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")"
|
|
RELEASES_DIR="${RELEASES_DIR:-./releases}"
|
|
SVC="${NVMEOF_SVC:-nvmeof}"
|
|
|
|
# Pull OCI_IMAGE default from the stack .env if present.
|
|
if [ -f ../.env ]; then
|
|
set -a; . ../.env; set +a
|
|
fi
|
|
|
|
# Run compose from the stack dir (one level up, where docker-compose.yml lives).
|
|
dc() { ( cd .. && docker compose "$@" ); }
|
|
|
|
usage() {
|
|
echo "usage: $0 {load <ver> [oci_ref] | unload <ver> [--force] | list}" >&2
|
|
exit 2
|
|
}
|
|
|
|
cmd_load() {
|
|
local v=${1:-}; [ -n "$v" ] || usage
|
|
local ref=${2:-}
|
|
if [ -z "$ref" ]; then
|
|
[ -n "${OCI_IMAGE:-}" ] || { echo "ERROR: set OCI_IMAGE in ../.env or pass an oci_ref" >&2; exit 1; }
|
|
ref="${OCI_IMAGE}:${v}"
|
|
fi
|
|
local dest="$RELEASES_DIR/$v"
|
|
if [ -s "$dest/verity.json" ]; then
|
|
echo "==> release $v already staged in $dest (skipping extract)"
|
|
else
|
|
echo "==> extracting $ref -> $dest"
|
|
mkdir -p "$dest"
|
|
local cid
|
|
cid=$(docker create "$ref")
|
|
# FROM-scratch artifact image: copy the three files the target needs.
|
|
docker cp "$cid:/artifacts/rootfs.erofs" "$dest/rootfs.erofs"
|
|
docker cp "$cid:/artifacts/rootfs.hash" "$dest/rootfs.hash"
|
|
docker cp "$cid:/artifacts/verity.json" "$dest/verity.json"
|
|
docker rm "$cid" >/dev/null
|
|
fi
|
|
echo "==> adding release $v on the live target (no restart)"
|
|
dc exec -T "$SVC" spdk-release add "$v"
|
|
dc exec -T "$SVC" spdk-release list
|
|
}
|
|
|
|
cmd_unload() {
|
|
local v="" force=""
|
|
local a
|
|
for a in "$@"; do
|
|
case "$a" in
|
|
--force) force="--force" ;;
|
|
*) v="$a" ;;
|
|
esac
|
|
done
|
|
[ -n "$v" ] || usage
|
|
echo "==> removing release $v from the live target"
|
|
if dc exec -T "$SVC" spdk-release remove "$v" ${force:+$force}; then
|
|
rm -rf "${RELEASES_DIR:?}/$v"
|
|
echo "==> staged artifacts for $v deleted from $RELEASES_DIR/$v"
|
|
else
|
|
echo "remove refused (version still has connected hosts?) — staged files left in place." >&2
|
|
echo "Drain those hosts first, or re-run with --force to evict them." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
case "${1:-}" in
|
|
load) shift; cmd_load "$@" ;;
|
|
unload|rm) shift; cmd_unload "$@" ;;
|
|
list|ls) dc exec -T "$SVC" spdk-release list ;;
|
|
*) usage ;;
|
|
esac
|