driveAtlas: redraw the Sliger CX4712 as a real front elevation
Lint / Shell (shellcheck) (push) Successful in 10s

The old 10-bay render was a 138-column strip of ten wide horizontal boxes,
which is not what this chassis looks like. Sliger's own photos and CAD show
the ten 3.5" bays are a SINGLE ROW of ten with the drives mounted ON EDGE,
so from the front each bay is a tall narrow slot - ten thin vertical bars in
a row is the signature of the case. Drawn as stacked horizontal trays it was
simply wrong.

Redraw it as a true front elevation at the real proportions (4U, 431.8 x
176.8 mm, ~2.75:1 with rack ears):
  - two 5.25" filler blanks side by side directly above the bay row, spanning
    the same width (these are unused on all three nodes)
  - one row of ten vertical bay slots, solid when occupied, dim ghost when not
  - the narrow front I/O strip at the right: power ring, 2x USB-A, USB-C, and
    the drive-lock key cylinder
  - rack ears with vertical handles bracketing both edges
There are no front fans, no reset button, no badge and no per-bay LEDs on
this chassis, so none are drawn.

All text is pushed out of the picture into BAY/DEV caption rows column-aligned
under the slots, keeping the chassis a clean silhouette. M.2 and internal
drives are not on the front face, so they are listed as a legend beneath.

Also surface the two facts that actually matter for using this map: the case
has NO backplane (each bay is an individually hand-cabled SFF-8482 to SATA
adapter) and NO per-bay LEDs, so bay numbering is a LOCAL left-to-right
convention rather than a vendor one, and a drive can only be identified
physically by its serial - there is no bay LED to blink.

Fixed 88-column canvas, identical display width on every line in monochrome
and colour, colour runs coalesced per run of like bays to keep escape churn
low, SAFE width-1 glyphs only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 21:42:49 -04:00
co-authored by Claude Opus 4.8
parent 6b40ec801b
commit e474ec546c
+128 -53
View File
@@ -446,74 +446,149 @@ run_diagnose() {
#------------------------------------------------------------------------------
# generate_10bay_layout
#
# Generates ASCII art representation of a 10-bay hot-swap chassis (Sliger CX4712).
# Shows storage controllers, M.2 NVMe slot, and 10 front hot-swap bays.
# FRONT ELEVATION of a Sliger CX4712 4U rackmount chassis (faceplate removed).
# - 2x 5.25" filler blanks side by side, spanning the bay region
# - 10x 3.5" hot-swap bays in ONE row; drives sit on edge, so each bay reads
# as a tall narrow slot -- the signature of this chassis
# - narrow front I/O strip (power ring, 2x USB-A, USB-C, key lock)
# - rack ears with vertical handles on both sides
# Occupied bays are solid, empty bays are dim ghosts. M.2 / internal drives are
# not on the front face, so they are listed as a legend under the drawing.
#
# Chassis has NO backplane and NO per-bay LEDs: each bay is an individually
# hand-cabled SFF-8482 to SATA adapter, so bay numbering is a LOCAL
# left-to-right convention, not a vendor one, and a drive can only be
# identified physically by its SERIAL (there is no bay LED to blink).
#
# Args:
# $1 - Hostname to display in the layout header
# $1 - Hostname to display in the header
#
# Side effects: Calls build_drive_map() to populate DRIVE_MAP
#
# The art printfs embed our own ANSI colour vars (DA_*) and literal box-drawing
# in the format string by design; device names are passed as %s args.
#------------------------------------------------------------------------------
# shellcheck disable=SC2059
generate_10bay_layout() {
local hostname="$1"
build_drive_map
local host="${1:-unknown}"
local i j k n st run cell c s lp
# Box interior width = 136 (determined by 10 bay boxes: 4 + 10*13 + 2)
# Total box width = 138 (136 interior + 2 for │ borders)
# Main chassis section
printf "┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐\n"
printf "│ %-132s │\n" "$hostname - Sliger CX4712 (10x 3.5\" Hot-swap)"
printf "│%-136s│\n" ""
# Show storage controllers
printf "│ %-134s│\n" "Storage Controllers:"
while IFS= read -r ctrl; do
[[ -n "$ctrl" ]] && printf "│ %-134.134s│\n" "$ctrl"
done < <(get_storage_controllers)
printf "│%-136s│\n" ""
# M.2 NVMe slot if present
if [[ -n "${DRIVE_MAP[m2-1]}" ]]; then
printf "│ %-134s│\n" " M.2 NVMe: ${DRIVE_MAP[m2-1]}"
printf "│%-136s│\n" ""
if declare -F build_drive_map >/dev/null 2>&1; then
build_drive_map 2>/dev/null || true
fi
# Internal (non-bay) drives if present
local int_keys
int_keys="$(printf '%s\n' "${!DRIVE_MAP[@]}" | grep -E '^int-' | sort)"
if [[ -n "$int_keys" ]]; then
while IFS= read -r int_key; do
printf "│ %-134s│\n" " Internal (non-bay): ${DRIVE_MAP[$int_key]}"
done <<< "$int_keys"
printf "│%-136s│\n" ""
if ! declare -p DRIVE_MAP >/dev/null 2>&1; then
declare -g -A DRIVE_MAP=()
fi
printf "│ %-134s│\n" " Front Hot-swap Bays:"
printf "│%-136s│\n" ""
# Bay top borders
printf "│ "
for bay in {1..10}; do
printf "┌──────────┐ "
if declare -F da_color_init >/dev/null 2>&1; then da_color_init; fi
# make every palette global exist -- safe under `set -u`, no-op when set
for s in DA_ST DA_HL DA_DIM DA_OK DA_YEL DA_HOT DA_BLU DA_CYN DA_RST DA_SR; do
printf -v "$s" '%s' "${!s-}"
done
printf " │\n"
# Bay contents
printf "│ "
for bay in {1..10}; do
printf "│%-2d:%-7s│ " "$bay" "${DRIVE_MAP[$bay]:-EMPTY}"
# ---- geometry -----------------------------------------------------------
# display width 88 = |1| 1 ear 3 | 2 | bays 61 | 5 | I/O 8 | 2 | ear 3 | 1 |1|
# bay strip 61 = wall + 10 slots of 5 cols separated by 1 col + wall
local -a state=() namec=() numc=()
for ((i = 1; i <= 10; i++)); do
s="${DRIVE_MAP[$i]:-}"
if [ -n "$s" ]; then state[i]=on; else state[i]=off; s='--'; fi
printf -v c '%-5.5s' "$s" # hard truncate: borders can never move
s="${c%% *}"
lp=$(( (5 - ${#s}) / 2 ))
printf -v c '%*s%s%*s' "$lp" '' "$s" "$((5 - lp - ${#s}))" ''
namec[i]="$c"
s="$i"
lp=$(( (5 - ${#s}) / 2 ))
printf -v c '%*s%s%*s' "$lp" '' "$s" "$((5 - lp - ${#s}))" ''
numc[i]="$c"
done
printf " │\n"
# Bay bottom borders
printf "│ "
for bay in {1..10}; do
printf "└──────────┘ "
# ---- coalesced colour runs: one escape pair per RUN of like bays --------
local fillrow='' namerow='' numrow=''
i=1
while [ "$i" -le 10 ]; do
st="${state[i]}"
j="$i"
while [ "$j" -le 10 ] && [ "${state[j]}" = "$st" ]; do j=$((j + 1)); done
n=$((j - i))
if [ "$st" = on ]; then cell='█████'; c="$DA_OK"; else cell='░░░░░'; c="$DA_DIM"; fi
run=''
for ((k = 0; k < n; k++)); do [ "$k" -gt 0 ] && run+=' '; run+="$cell"; done
fillrow+="${c}${run}${DA_SR}"
run=''
for ((k = i; k < j; k++)); do [ "$k" -gt "$i" ] && run+=' '; run+="${namec[k]}"; done
namerow+="${c}${run}${DA_SR}"
if [ "$j" -le 10 ]; then fillrow+=' '; namerow+=' '; fi
i="$j"
done
for ((i = 1; i <= 10; i++)); do
[ "$i" -gt 1 ] && numrow+=' '
numrow+="${numc[i]}"
done
printf " │\n"
printf "└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\n"
# ---- header -------------------------------------------------------------
local hostp tail
printf -v hostp '%-24.24s' "$host"
printf -v tail '%-52.52s' 'Sliger CX4712 - 4U - 431.8 x 176.8 mm'
printf '\n'
printf "${DA_CYN}driveAtlas${DA_SR} ${DA_HL}%s${DA_SR} ${DA_ST}%s${DA_RST}\n" "$hostp" "$tail"
printf -v tail '%-88.88s' 'FRONT ELEVATION - mesh faceplate removed - drives mounted on edge'
printf "${DA_DIM}%s${DA_RST}\n" "$tail"
printf '\n'
# ---- chassis ------------------------------------------------------------
local T525='┌─────────────────────────────┬─────────────────────────────┐'
local M525='│ 5.25" FILLER │ 5.25" FILLER │'
local B525='└─────────────────────────────┴─────────────────────────────┘'
local TBAY='┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐'
local BBAY='└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘'
local GAP61=' '
local GAP74=' '
printf "${DA_ST}┌──────────────────────────────────────────────────────────────────────────────────────┐${DA_RST}\n"
printf "${DA_ST}${DA_HL}╭─╮${DA_SR} %s ${DA_HL}╭─╮${DA_SR}${DA_RST}\n" "$GAP74"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_DIM}%s${DA_SR} ┌──────┐ ${DA_HL}│ │${DA_SR}${DA_RST}\n" "$T525"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_DIM}%s${DA_SR}${DA_HL}(o)${DA_SR}${DA_HL}│ │${DA_SR}${DA_RST}\n" "$M525"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_DIM}%s${DA_SR} │ │ ${DA_HL}│ │${DA_SR}${DA_RST}\n" "$B525"
printf "${DA_ST}${DA_HL}│ │${DA_SR} %s │ ${DA_BLU}[A]${DA_SR}${DA_HL}│ │${DA_SR}${DA_RST}\n" "$GAP61"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}%s${DA_SR}${DA_BLU}[A]${DA_SR}${DA_HL}│ │${DA_SR}${DA_RST}\n" "$TBAY"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}${DA_SR}%s${DA_HL}${DA_SR}${DA_BLU}[C]${DA_SR}${DA_HL}│ │${DA_SR}${DA_RST}\n" "$fillrow"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}${DA_SR}%s${DA_HL}${DA_SR} │ │ ${DA_HL}│ │${DA_SR}${DA_RST}\n" "$fillrow"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}${DA_SR}%s${DA_HL}${DA_SR}${DA_DIM}(-)${DA_SR}${DA_HL}│ │${DA_SR}${DA_RST}\n" "$fillrow"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}${DA_SR}%s${DA_HL}${DA_SR} │ │ ${DA_HL}│ │${DA_SR}${DA_RST}\n" "$fillrow"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}${DA_SR}%s${DA_HL}${DA_SR} │ │ ${DA_HL}│ │${DA_SR}${DA_RST}\n" "$fillrow"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}${DA_SR}%s${DA_HL}${DA_SR} │ │ ${DA_HL}│ │${DA_SR}${DA_RST}\n" "$fillrow"
printf "${DA_ST}${DA_HL}│ │${DA_SR} ${DA_HL}%s${DA_SR} └──────┘ ${DA_HL}│ │${DA_SR}${DA_RST}\n" "$BBAY"
printf "${DA_ST}${DA_HL}╰─╯${DA_SR} %s ${DA_HL}╰─╯${DA_SR}${DA_RST}\n" "$GAP74"
printf "${DA_ST}└──────────────────────────────────────────────────────────────────────────────────────┘${DA_RST}\n"
# ---- captions, aligned under the ten slots ------------------------------
printf "${DA_ST} BAY %s${DA_ST} ${DA_RST}\n" "$numrow"
printf "${DA_ST} DEV %s${DA_ST} ${DA_RST}\n" "$namerow"
printf '\n'
# ---- off-panel drives + the one thing you must know ---------------------
local off='' v
[ -n "${DRIVE_MAP[m2-1]:-}" ] && off="M.2 ${DRIVE_MAP[m2-1]}"
for i in 1 2 3 4 5 6 7 8; do
v="${DRIVE_MAP[int-$i]:-}"
[ -n "$v" ] || continue
[ -n "$off" ] && off+=" "
off+="internal $v"
done
[ -n "$off" ] || off='none'
printf -v off '%-66.66s' "$off"
printf "${DA_ST} not on front face ${DA_CYN}%s${DA_RST}\n" "$off"
printf -v tail '%-88.88s' ' No backplane and no per-bay LEDs: every bay is a hand-cabled SFF-8482 to SATA lead.'
printf "${DA_DIM}%s${DA_RST}\n" "$tail"
printf -v tail '%-88.88s' ' Bay numbers are a LOCAL left-to-right convention - identify a drive by SERIAL.'
printf "${DA_DIM}%s${DA_RST}\n" "$tail"
if declare -F get_storage_controllers >/dev/null 2>&1; then
printf '\n'
printf " ${DA_HL}STORAGE CONTROLLERS${DA_RST}\n"
get_storage_controllers 2>/dev/null | sed 's/^/ /'
fi
}
#------------------------------------------------------------------------------