Add verbose mode for detailed error messages

Added --verbose flag that enables detailed logging:
- log_error(): Always shown, critical errors
- log_warn(): Shown in verbose mode, potential issues
- log_info(): Shown in verbose mode, informational messages

Now provides helpful feedback for:
- SMART query failures with specific error messages
- Missing drive mappings for the current host
- Empty bays (no device at configured PCI path)
- Ceph command availability and query status
- Drive mapping statistics (mapped vs empty)

Color-coded output when using --color with --verbose.

Fixes: #14

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-05 11:39:12 -05:00
parent 0eb3e30dba
commit fa7fa296db

View File

@@ -28,6 +28,7 @@ OPTIONS:
-d, --debug Enable debug output (show drive mappings)
-s, --skip-smart Skip SMART data collection (faster)
-c, --color Enable colored output
--verbose Show detailed error messages and warnings
--no-ceph Skip Ceph OSD information
--show-pci Show PCI paths in output
@@ -35,6 +36,7 @@ EXAMPLES:
$(basename "$0") # Normal run with all features
$(basename "$0") --skip-smart # Fast run without SMART data
$(basename "$0") --color # Run with colored output
$(basename "$0") --verbose # Show all errors and warnings
$(basename "$0") --debug # Show mapping debug info
ENVIRONMENT VARIABLES:
@@ -51,6 +53,7 @@ SKIP_SMART=false
SKIP_CEPH=false
SHOW_PCI=false
USE_COLOR=false
VERBOSE=false
while [[ $# -gt 0 ]]; do
case "$1" in
@@ -82,6 +85,10 @@ while [[ $# -gt 0 ]]; do
USE_COLOR=true
shift
;;
--verbose)
VERBOSE=true
shift
;;
*)
echo "Unknown option: $1" >&2
echo "Use --help for usage information." >&2
@@ -175,6 +182,52 @@ colorize_header() {
fi
}
#------------------------------------------------------------------------------
# log_error
#
# Logs an error message to stderr. Always shown regardless of verbose mode.
# Args: $1 - error message
#------------------------------------------------------------------------------
log_error() {
if [[ "$USE_COLOR" == true ]]; then
echo -e "${COLOR_RED}ERROR:${COLOR_RESET} $1" >&2
else
echo "ERROR: $1" >&2
fi
}
#------------------------------------------------------------------------------
# log_warn
#
# Logs a warning message to stderr. Only shown in verbose mode.
# Args: $1 - warning message
#------------------------------------------------------------------------------
log_warn() {
if [[ "$VERBOSE" == true ]]; then
if [[ "$USE_COLOR" == true ]]; then
echo -e "${COLOR_YELLOW}WARN:${COLOR_RESET} $1" >&2
else
echo "WARN: $1" >&2
fi
fi
}
#------------------------------------------------------------------------------
# log_info
#
# Logs an informational message to stderr. Only shown in verbose mode.
# Args: $1 - info message
#------------------------------------------------------------------------------
log_info() {
if [[ "$VERBOSE" == true ]]; then
if [[ "$USE_COLOR" == true ]]; then
echo -e "${COLOR_CYAN}INFO:${COLOR_RESET} $1" >&2
else
echo "INFO: $1" >&2
fi
fi
}
#------------------------------------------------------------------------------
# Dependency Checks
# Verifies required commands are available before running
@@ -499,17 +552,28 @@ build_drive_map() {
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"
fi
done <<< "$mapping"
if [[ -z "$mapping" ]]; then
log_warn "No drive mapping found for host '$host'. Run diagnose-drives.sh to create one."
return
fi
local mapped_count=0
local empty_count=0
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"
((mapped_count++))
else
log_info "Bay $slot: No device at PCI path $path"
((empty_count++))
fi
done <<< "$mapping"
log_info "Mapped $mapped_count drives, $empty_count empty bays"
}
#------------------------------------------------------------------------------
@@ -530,9 +594,12 @@ build_ceph_cache() {
# Skip if ceph-volume is not available
if ! command -v ceph-volume &>/dev/null; then
log_info "ceph-volume not found, skipping Ceph OSD detection"
return
fi
log_info "Querying Ceph OSD information..."
# Parse ceph-volume lvm list output
# Format: blocks starting with "====== osd.X =======" followed by device info
local current_osd=""
@@ -549,9 +616,12 @@ build_ceph_cache() {
# Skip if ceph command is not available
if ! command -v ceph &>/dev/null; then
log_info "ceph CLI not found, skipping OSD status detection"
return
fi
log_info "Querying Ceph OSD status..."
# Parse ceph osd tree for status
# Format: ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT
while IFS= read -r line; do
@@ -607,7 +677,22 @@ get_drive_smart_info() {
local serial="-"
local warnings=""
smart_info="$(sudo smartctl -A -i -H "/dev/$device" 2>/dev/null)"
# Capture both stdout and stderr for better error reporting
local smart_stderr
smart_stderr="$(mktemp)"
smart_info="$(sudo smartctl -A -i -H "/dev/$device" 2>"$smart_stderr")"
local smart_exit=$?
if [[ $smart_exit -ne 0 && -s "$smart_stderr" ]]; then
log_warn "SMART query failed for $device: $(head -1 "$smart_stderr")"
fi
rm -f "$smart_stderr"
if [[ -z "$smart_info" ]]; then
log_info "No SMART data available for $device"
echo "HDD|-|✗|-|-|"
return
fi
# Temperature parsing - handles multiple formats:
# - SATA: "194 Temperature_Celsius ... 35" (value at end of line)