Adding spdk loader
This commit is contained in:
@@ -17,11 +17,15 @@
|
||||
# namespace UUIDs + subsystem NQN (written by scripts/extract-artifacts.sh) — so
|
||||
# the host's by-id verity refs and the target's namespace UUIDs always agree.
|
||||
#
|
||||
# JSON is parsed with python3 (always present — rpc.py runs on it), NOT jq, which
|
||||
# the SPDK image does not ship.
|
||||
#
|
||||
# Usage:
|
||||
# spdk-release add <version> # idempotent; live, no restart
|
||||
# spdk-release remove <version> [--force] # DRAIN-GATED unless --force
|
||||
# spdk-release list # served versions + connected hosts
|
||||
# spdk-release drain-status <version> # connected controller count
|
||||
# spdk-release drain-status <version> # connected controller count (human)
|
||||
# spdk-release count <version> # connected controller count (bare int; -1 if absent/error)
|
||||
# spdk-release reconcile # add every release under $RELEASES_DIR
|
||||
set -euo pipefail
|
||||
|
||||
@@ -30,17 +34,32 @@ TADDR="${TARGET_ADDR:-0.0.0.0}"
|
||||
TPORT="${TARGET_PORT:-4420}"
|
||||
SUBNQN_BASE="${SUBNQN_BASE:-nqn.2026-06.org.example.fleet:rootfs}"
|
||||
DISCOVERY_NQN="nqn.2014-08.org.nvmexpress.discovery"
|
||||
# Legacy fixed namespace UUIDs (pre per-version-UUID builds baked these into the
|
||||
# UKI cmdline). Used as a fallback when verity.json lacks the per-version pair.
|
||||
LEGACY_DATA_UUID="f1ee7000-0000-4000-8000-000000000001"
|
||||
LEGACY_HASH_UUID="f1ee7000-0000-4000-8000-000000000002"
|
||||
RPC=$(command -v rpc.py || echo /usr/libexec/spdk/scripts/rpc.py)
|
||||
PY=$(command -v python3 || echo python3)
|
||||
# Optional explicit RPC socket (shared between the long-lived target and the
|
||||
# loader container). Empty -> rpc.py's default socket (single-container case).
|
||||
RPC_SOCK="${RPC_SOCK:-}"
|
||||
|
||||
die() { echo "ERROR: $*" >&2; exit 1; }
|
||||
rpc() { "$RPC" "$@"; }
|
||||
# bdev names must be filesystem/identifier-safe; sanitise the version.
|
||||
rpc() { if [ -n "$RPC_SOCK" ]; then "$RPC" -s "$RPC_SOCK" "$@"; else "$RPC" "$@"; fi; }
|
||||
# bdev names must be identifier-safe; sanitise the version.
|
||||
san() { printf '%s' "$1" | tr -c 'A-Za-z0-9' '_'; }
|
||||
|
||||
# Read a field from a release's verity.json (empty if missing).
|
||||
# Read a top-level field from a release's verity.json (empty if missing/unreadable).
|
||||
vfield() {
|
||||
local v=$1 path=$2
|
||||
jq -r "$path // empty" "$RELEASES_DIR/$v/verity.json" 2>/dev/null || true
|
||||
local v=$1 key=${2#.}
|
||||
"$PY" -c '
|
||||
import json,sys
|
||||
try:
|
||||
d=json.load(open(sys.argv[1]))
|
||||
x=d.get(sys.argv[2],"")
|
||||
sys.stdout.write("" if x is None else str(x))
|
||||
except Exception:
|
||||
pass' "$RELEASES_DIR/$v/verity.json" "$key" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Per-version subsystem NQN: prefer the one baked into verity.json; otherwise
|
||||
@@ -53,15 +72,28 @@ release_nqn() {
|
||||
}
|
||||
|
||||
subsys_exists() {
|
||||
rpc nvmf_get_subsystems 2>/dev/null \
|
||||
| jq -e --arg n "$1" 'any(.[]; .nqn==$n)' >/dev/null 2>&1
|
||||
rpc nvmf_get_subsystems 2>/dev/null | "$PY" -c '
|
||||
import json,sys
|
||||
try:
|
||||
subs=json.load(sys.stdin)
|
||||
except Exception:
|
||||
sys.exit(1)
|
||||
sys.exit(0 if any(s.get("nqn")==sys.argv[1] for s in subs) else 1)' "$1"
|
||||
}
|
||||
|
||||
# Connected controllers on a subsystem (the drain gate). 0 if absent/none.
|
||||
# Connected controllers on a subsystem (the drain gate). >=0 when served; -1 if
|
||||
# the subsystem is absent or the RPC failed (so a poller never mistakes an error
|
||||
# for "drained" and reaps a live version).
|
||||
ctrl_count() {
|
||||
local n
|
||||
n=$(rpc nvmf_subsystem_get_controllers "$1" 2>/dev/null | jq 'length' 2>/dev/null || echo 0)
|
||||
printf '%s' "${n:-0}"
|
||||
local out
|
||||
if out=$(rpc nvmf_subsystem_get_controllers "$1" 2>/dev/null); then
|
||||
printf '%s' "$out" | "$PY" -c '
|
||||
import json,sys
|
||||
try: print(len(json.load(sys.stdin)))
|
||||
except Exception: print(-1)'
|
||||
else
|
||||
printf '%s' "-1"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_add() {
|
||||
@@ -74,8 +106,16 @@ cmd_add() {
|
||||
nqn=$(release_nqn "$v")
|
||||
du=$(vfield "$v" .data_ns_uuid)
|
||||
hu=$(vfield "$v" .hash_ns_uuid)
|
||||
[ -n "$du" ] && [ -n "$hu" ] \
|
||||
|| die "$dir/verity.json lacks data_ns_uuid/hash_ns_uuid (rebuild with the per-version UUID extract-artifacts.sh)"
|
||||
# LEGACY FALLBACK: artifacts built before the per-version-UUID change have no
|
||||
# data_ns_uuid/hash_ns_uuid in verity.json. Such a build's UKI cmdline baked
|
||||
# the fixed pair below, so serve it with exactly those. Two such LEGACY
|
||||
# versions can't be co-served (they'd collide on these fixed UUIDs) — rebuild
|
||||
# with the current extract-artifacts.sh for true multi-version serving.
|
||||
if [ -z "$du" ] || [ -z "$hu" ]; then
|
||||
du=${du:-$LEGACY_DATA_UUID}
|
||||
hu=${hu:-$LEGACY_HASH_UUID}
|
||||
echo "WARNING: $dir/verity.json lacks per-version namespace UUIDs — using the legacy fixed pair ($du / $hu). OK for a single legacy version; rebuild for multi-version." >&2
|
||||
fi
|
||||
|
||||
if subsys_exists "$nqn"; then
|
||||
echo "release $v already served ($nqn) — nothing to do"
|
||||
@@ -135,8 +175,13 @@ cmd_remove() {
|
||||
cmd_list() {
|
||||
local nqn n ver
|
||||
printf '%-26s %-7s %s\n' VERSION CONNS NQN
|
||||
rpc nvmf_get_subsystems 2>/dev/null \
|
||||
| jq -r '.[] | select(.nqn | test("discovery") | not) | .nqn' \
|
||||
rpc nvmf_get_subsystems 2>/dev/null | "$PY" -c '
|
||||
import json,sys
|
||||
try: subs=json.load(sys.stdin)
|
||||
except Exception: subs=[]
|
||||
for s in subs:
|
||||
n=s.get("nqn","")
|
||||
if "discovery" not in n: print(n)' \
|
||||
| while read -r nqn; do
|
||||
n=$(ctrl_count "$nqn")
|
||||
ver="${nqn##*:}" # strip the nqn.*: prefix for readability
|
||||
@@ -146,9 +191,20 @@ cmd_list() {
|
||||
|
||||
cmd_drain_status() {
|
||||
local v=${1:?usage: drain-status <version>}
|
||||
local nqn
|
||||
local nqn n
|
||||
nqn=$(release_nqn "$v")
|
||||
echo "$(ctrl_count "$nqn") connected controller(s) on $nqn"
|
||||
n=$(ctrl_count "$nqn")
|
||||
if [ "$n" -lt 0 ]; then
|
||||
echo "$nqn is not served (or target unreachable)"
|
||||
else
|
||||
echo "$n connected controller(s) on $nqn"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_count() {
|
||||
local v=${1:?usage: count <version>}
|
||||
ctrl_count "$(release_nqn "$v")"
|
||||
echo
|
||||
}
|
||||
|
||||
cmd_reconcile() {
|
||||
@@ -167,6 +223,7 @@ case "${1:-}" in
|
||||
remove|rm) shift; cmd_remove "$@" ;;
|
||||
list|ls) shift; cmd_list "$@" ;;
|
||||
drain-status|status) shift; cmd_drain_status "$@" ;;
|
||||
count) shift; cmd_count "$@" ;;
|
||||
reconcile) shift; cmd_reconcile "$@" ;;
|
||||
*) echo "usage: spdk-release {add <ver>|remove <ver> [--force]|list|drain-status <ver>|reconcile}" >&2; exit 2 ;;
|
||||
*) echo "usage: spdk-release {add <ver>|remove <ver> [--force]|list|drain-status <ver>|count <ver>|reconcile}" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user