diff --git a/driveAtlas.sh b/driveAtlas.sh index 020884f..922030e 100644 --- a/driveAtlas.sh +++ b/driveAtlas.sh @@ -5,6 +5,84 @@ # Maps physical drive bays to logical device names using PCI paths #============================================================================== +VERSION="1.1.0" + +#------------------------------------------------------------------------------ +# show_usage +# +# Displays help message with usage information and available options. +#------------------------------------------------------------------------------ +show_usage() { + cat << EOF +Drive Atlas v${VERSION} - Server Drive Mapping Tool + +Maps physical drive bays to logical device names using PCI paths. +Displays visual chassis layouts and comprehensive drive information. + +USAGE: + $(basename "$0") [OPTIONS] + +OPTIONS: + -h, --help Show this help message and exit + -v, --version Show version information + -d, --debug Enable debug output (show drive mappings) + -s, --skip-smart Skip SMART data collection (faster) + --no-ceph Skip Ceph OSD information + --show-pci Show PCI paths in output + +EXAMPLES: + $(basename "$0") # Normal run with all features + $(basename "$0") --skip-smart # Fast run without SMART data + $(basename "$0") --debug # Show mapping debug info + +ENVIRONMENT VARIABLES: + DEBUG=1 Same as --debug flag + +For more information, see: https://code.lotusguild.org/LotusGuild/driveAtlas +EOF +} + +#------------------------------------------------------------------------------ +# Command Line Argument Parsing +#------------------------------------------------------------------------------ +SKIP_SMART=false +SKIP_CEPH=false +SHOW_PCI=false + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + show_usage + exit 0 + ;; + -v|--version) + echo "Drive Atlas v${VERSION}" + exit 0 + ;; + -d|--debug) + DEBUG=1 + shift + ;; + -s|--skip-smart) + SKIP_SMART=true + shift + ;; + --no-ceph) + SKIP_CEPH=true + shift + ;; + --show-pci) + SHOW_PCI=true + shift + ;; + *) + echo "Unknown option: $1" >&2 + echo "Use --help for usage information." >&2 + exit 1 + ;; + esac +done + #------------------------------------------------------------------------------ # Dependency Checks # Verifies required commands are available before running @@ -313,21 +391,27 @@ get_storage_controllers() { # Builds a global associative array mapping physical bay numbers to device names. # Uses PCI paths from SERVER_MAPPINGS to resolve current device assignments. # -# Sets: DRIVE_MAP (global associative array) -# Keys: Bay identifiers (1, 2, ..., m2-1, m2-2, etc.) -# Values: Device names (sda, nvme0n1, etc.) +# Sets: +# DRIVE_MAP (global associative array) +# Keys: Bay identifiers (1, 2, ..., m2-1, m2-2, etc.) +# Values: Device names (sda, nvme0n1, etc.) +# BAY_TO_PCI_PATH (global associative array) +# Keys: Bay identifiers +# Values: PCI path strings (for --show-pci option) #------------------------------------------------------------------------------ build_drive_map() { local host="$(hostname)" local mapping="${SERVER_MAPPINGS[$host]}" - # Declare global array directly instead of copying from local + # Declare global arrays directly declare -g -A DRIVE_MAP=() + declare -g -A BAY_TO_PCI_PATH=() if [[ -n "$mapping" ]]; then while read -r path slot; do [[ -z "$path" || -z "$slot" ]] && continue + BAY_TO_PCI_PATH[$slot]="$path" if [[ -L "/dev/disk/by-path/$path" ]]; then local drive="$(readlink -f "/dev/disk/by-path/$path" | sed 's/.*\///')" DRIVE_MAP[$slot]="$drive" @@ -509,11 +593,18 @@ esac #------------------------------------------------------------------------------ # Build Ceph OSD cache (single query instead of per-device) -build_ceph_cache +if [[ "$SKIP_CEPH" != true ]]; then + build_ceph_cache +fi printf "\n=== Drive Details with SMART Status (by Bay Position) ===\n" -printf "%-5s %-15s %-10s %-8s %-8s %-8s %-30s %-20s %-12s %-10s %-10s\n" "BAY" "DEVICE" "SIZE" "TYPE" "TEMP" "HEALTH" "MODEL" "SERIAL" "CEPH OSD" "STATUS" "USAGE" -echo "----------------------------------------------------------------------------------------------------------------------------------------------------" +if [[ "$SHOW_PCI" == true ]]; then + printf "%-5s %-15s %-10s %-8s %-8s %-8s %-30s %-20s %-12s %-10s %-10s %-40s\n" "BAY" "DEVICE" "SIZE" "TYPE" "TEMP" "HEALTH" "MODEL" "SERIAL" "CEPH OSD" "STATUS" "USAGE" "PCI PATH" + echo "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" +else + printf "%-5s %-15s %-10s %-8s %-8s %-8s %-30s %-20s %-12s %-10s %-10s\n" "BAY" "DEVICE" "SIZE" "TYPE" "TEMP" "HEALTH" "MODEL" "SERIAL" "CEPH OSD" "STATUS" "USAGE" + echo "----------------------------------------------------------------------------------------------------------------------------------------------------" +fi # Build reverse map: device -> bay declare -A DEVICE_TO_BAY @@ -530,22 +621,34 @@ all_bays=$(printf '%s\n' "${!DRIVE_MAP[@]}" | grep -E '^[0-9]+$' | sort -n; prin for bay in $all_bays; do device="${DRIVE_MAP[$bay]}" if [[ -n "$device" && "$device" != "EMPTY" && -b "/dev/$device" ]]; then - size=$(lsblk -d -n -o SIZE "/dev/$device" 2>/dev/null) - smart_info=$(get_drive_smart_info "$device") - IFS='|' read -r type temp health model serial <<< "$smart_info" + size="$(lsblk -d -n -o SIZE "/dev/$device" 2>/dev/null)" + + # Get SMART info (or defaults if skipped) + if [[ "$SKIP_SMART" == true ]]; then + type="-" + temp="-" + health="-" + model="-" + serial="-" + else + smart_info="$(get_drive_smart_info "$device")" + IFS='|' read -r type temp health model serial <<< "$smart_info" + fi # Check for Ceph OSD using cached data - osd_id="${CEPH_DEVICE_TO_OSD[$device]:-}" + osd_id="-" ceph_status="-" - - if [[ -n "$osd_id" ]]; then - # Get status from cached OSD tree data - osd_num="${osd_id#osd.}" - up_status="${CEPH_OSD_STATUS[$osd_num]:-unknown}" - in_status="${CEPH_OSD_IN[$osd_num]:-out}" - ceph_status="${up_status}/${in_status}" - else - osd_id="-" + if [[ "$SKIP_CEPH" != true ]]; then + osd_id="${CEPH_DEVICE_TO_OSD[$device]:-}" + if [[ -n "$osd_id" ]]; then + # Get status from cached OSD tree data + osd_num="${osd_id#osd.}" + up_status="${CEPH_OSD_STATUS[$osd_num]:-unknown}" + in_status="${CEPH_OSD_IN[$osd_num]:-out}" + ceph_status="${up_status}/${in_status}" + else + osd_id="-" + fi fi # Check mount points using lsblk (includes partitions) @@ -566,7 +669,12 @@ for bay in $all_bays; do fi fi - printf "%-5s %-15s %-10s %-8s %-8s %-8s %-30s %-20s %-12s %-10s %-10s\n" "$bay" "/dev/$device" "$size" "$type" "$temp" "$health" "$model" "$serial" "$osd_id" "$ceph_status" "$usage" + if [[ "$SHOW_PCI" == true ]]; then + pci_path="${BAY_TO_PCI_PATH[$bay]:-}" + printf "%-5s %-15s %-10s %-8s %-8s %-8s %-30s %-20s %-12s %-10s %-10s %-40s\n" "$bay" "/dev/$device" "$size" "$type" "$temp" "$health" "$model" "$serial" "$osd_id" "$ceph_status" "$usage" "$pci_path" + else + printf "%-5s %-15s %-10s %-8s %-8s %-8s %-30s %-20s %-12s %-10s %-10s\n" "$bay" "/dev/$device" "$size" "$type" "$temp" "$health" "$model" "$serial" "$osd_id" "$ceph_status" "$usage" + fi fi done