autoNAS / scripts / autonas.sh
5bf8614 3 months ago History
1 contributor
1064 lines | 34.386kb
#!/bin/bash

# AutoNAS - Unified AutoNAS Management Tool
# Combines manager, configuration, and all other functionality into one script
# Usage: autonas <command> [options]

# Load core AutoNAS library
AUTONAS_RUNTIME_DIR="${AUTONAS_RUNTIME_DIR:-/usr/local/lib/xdev/autonas}"
AUTONAS_CORE_LIB="${AUTONAS_CORE_LIB:-${AUTONAS_RUNTIME_DIR}/autonas-core.sh}"
AUTONAS_DEFAULTS_FILE="${AUTONAS_DEFAULTS_FILE:-/etc/default/xdev-autonas}"
AUTONAS_MEDIA_IMPORTER="${AUTONAS_MEDIA_IMPORTER:-${AUTONAS_RUNTIME_DIR}/autonas-media-importer.sh}"

if [[ -f "${AUTONAS_CORE_LIB}" ]]; then
    source "${AUTONAS_CORE_LIB}"
else
    echo "Error: AutoNAS core library not found at ${AUTONAS_CORE_LIB}" >&2
    exit 1
fi

# Function to handle disk attachment
handle_attach() {
    local identifier="$1"

    log_message "AutoNAS attach operation started for identifier: $identifier"

    # Get configuration by UUID, name, or mount point
    local config
    config=$(resolve_config_identifier "$identifier")

    if [[ -z "$config" ]]; then
        log_message "No configuration found for identifier: $identifier - disk will be ignored"
        log_message "To configure this disk, run: autonas-config.sh add"
        return 1
    fi

    # Parse configuration
    local parsed
    parsed=($(parse_config "$config"))
    local cfg_uuid="${parsed[0]}"
    local name="${parsed[1]}"
    local ip="${parsed[2]}"
    local interface="${parsed[3]}"
    local mount_point="${parsed[4]}"
    local nfs_options="${parsed[5]}"

    log_message "Handling disk attachment for UUID: $cfg_uuid"
    log_message "Processing disk: $name (IP: $ip, Mount: $mount_point)"

    # Handle different disk types
    if [[ "$ip" == "IMPORT" && "$interface" == "IMPORT" ]]; then
        # Camera import workflow: mount temporarily, import, then unmount
        log_message "Detected camera import configuration for UUID: $cfg_uuid"

        # Mount disk for import
        if mount_disk "$cfg_uuid" "$mount_point"; then
            # Start import process
            handle_camera_import "$cfg_uuid" "$mount_point" "$nfs_options"
            return $?
        else
            log_message "Error: Failed to mount camera device" "err"
            return 1
        fi
    elif [[ "$ip" == "LOCAL" ]]; then
        # Local mount only (no network sharing)
        if mount_disk "$cfg_uuid" "$mount_point"; then
            log_message "Local disk mounted successfully at $mount_point"
            return 0
        else
            return 1
        fi
    else
        # Regular NFS workflow: activate IP, mount, export via NFS
        if activate_ip "$ip" "$interface"; then
            if mount_disk "$cfg_uuid" "$mount_point"; then
                if add_nfs_export "$mount_point" "$nfs_options"; then
                    log_message "Disk attached successfully: $name"
                    return 0
                else
                    log_message "Warning: Disk mounted but NFS export failed" "warning"
                    return 1
                fi
            else
                deactivate_ip "$ip" "$interface"
                return 1
            fi
        else
            return 1
        fi
    fi
}

# Function to handle disk detachment
handle_detach() {
    local identifier="$1"

    log_message "AutoNAS detach operation started for identifier: $identifier"

    # Get configuration by UUID, name, or mount point
    local config
    config=$(resolve_config_identifier "$identifier")

    if [[ -z "$config" ]]; then
        log_message "No configuration found for identifier: $identifier"
        return 1
    fi

    # Parse configuration
    local parsed
    parsed=($(parse_config "$config"))
    local cfg_uuid="${parsed[0]}"
    local name="${parsed[1]}"
    local ip="${parsed[2]}"
    local interface="${parsed[3]}"
    local mount_point="${parsed[4]}"
    local nfs_options="${parsed[5]}"

    log_message "Handling disk detachment for UUID: $cfg_uuid"
    log_message "Processing disk: $name (Mount: $mount_point)"
    
    # Remove NFS export (if applicable)
    if [[ "$ip" != "LOCAL" && "$ip" != "IMPORT" ]]; then
        remove_nfs_export "$mount_point"
    fi
    
    # Unmount disk
    if unmount_disk "$mount_point"; then
        # Deactivate IP (if applicable)
        if [[ "$ip" != "LOCAL" && "$ip" != "IMPORT" ]]; then
            deactivate_ip "$ip" "$interface"
        fi
        
        log_message "Disk detached successfully: $name"
        return 0
    else
        log_message "Error: Failed to detach disk: $name" "err"
        return 1
    fi
}

# Function to reload configuration
handle_reload() {
    log_message "Reloading AutoNAS configuration"
    
    log_message "Reloading udev rules"
    udevadm control --reload-rules
    udevadm trigger --subsystem-match=block
    
    log_message "Reloading NFS exports"
    exportfs -ra || log_message "Warning: Failed to reload NFS exports" "warning"

    local sync_script="${AUTONAS_RUNTIME_DIR}/autonas-sync-systemd-ordering.sh"
    if [[ -x "${sync_script}" ]]; then
        log_message "Refreshing self-hosted Proxmox shutdown ordering"
        "${sync_script}" || log_message "Warning: Failed to refresh self-hosted Proxmox shutdown ordering" "warning"
    fi
    
    log_message "Reloading systemd daemon"
    systemctl daemon-reload || log_message "Warning: Failed to reload systemd daemon" "warning"
    
    log_message "AutoNAS configuration reload completed"
    return 0
}

# Show usage information
show_usage() {
    cat << EOF
AutoNAS - Unified AutoNAS Management Tool

Usage: $0 <command> [options]

DISK OPERATIONS:
  attach <uuid|name|mount>   - Attach configured disk
  detach <uuid|name|mount>   - Detach configured disk
  import <uuid> <source> <dest> [script] - Run background import (internal use)
  reload                     - Reload AutoNAS configuration

CONFIGURATION MANAGEMENT:
  add [uuid]                 - Add new disk configuration
  remove [uuid|name|mount]   - Remove disk configuration
  list                       - List all configured disks
  test [uuid|name|mount]     - Test disk configuration
  show                       - Show available disks

MAINTENANCE:
  status                     - Show system status
  debug enable               - Enable debug mode (verbose logging)
  debug disable              - Disable debug mode
  debug status               - Show current debug status
  
Examples:
  $0 attach f6ac3d86-5681-4b33-bc64-aa272b333057
  $0 add 8765-4321
  $0 list
  $0 show
  $0 status

EOF
}

# Function to show available disks
show_available_disks() {
    echo "=== Available Storage Devices ==="
    echo
    
    local found_devices=0
    local blkid_output
    
    # Get blkid output and process it
    if ! blkid_output=$(blkid 2>/dev/null); then
        echo "Error: Unable to scan for block devices (are you running as root?)"
        return 1
    fi
    
    while IFS= read -r blkid_line; do
        [[ -z "$blkid_line" ]] && continue
        
        local device=$(echo "$blkid_line" | cut -d: -f1)
        
        # Skip if device doesn't exist (shouldn't happen with blkid, but just in case)
        [[ ! -b "$device" ]] && continue
        
        # Skip loop devices, ram disks, and other virtual devices
        case "$device" in
            /dev/loop*|/dev/ram*|/dev/dm-*) continue ;;
        esac
        
        # Extract device information
        local uuid=$(echo "$blkid_line" | grep -o 'UUID="[^"]*"' | cut -d'"' -f2)
        local label=$(echo "$blkid_line" | grep -o 'LABEL="[^"]*"' | cut -d'"' -f2)
        local fstype=$(echo "$blkid_line" | grep -o 'TYPE="[^"]*"' | cut -d'"' -f2)
        local partuuid=$(echo "$blkid_line" | grep -o 'PARTUUID="[^"]*"' | cut -d'"' -f2)
        
        # Skip if no UUID (we need UUID for AutoNAS)
        [[ -z "$uuid" ]] && continue
        
        found_devices=$((found_devices + 1))
        
        # Get device size
        local size=""
        if [[ -b "$device" ]]; then
            size=$(lsblk -b -d -o SIZE "$device" 2>/dev/null | tail -n1)
            if [[ -n "$size" ]] && [[ "$size" =~ ^[0-9]+$ ]]; then
                # Convert to human readable
                size=$(numfmt --to=iec --suffix=B "$size" 2>/dev/null || echo "${size}B")
            fi
        fi
        
        # Display device information
        echo "Device: $device"
        [[ -n "$size" ]] && echo "  Size: $size"
        echo "  UUID: $uuid"
        [[ -n "$label" ]] && echo "  Label: $label"
        [[ -n "$fstype" ]] && echo "  Filesystem: $fstype"
        
        # Check if already configured
        if grep -q "^${uuid}:" "$CONFIG_FILE" 2>/dev/null; then
            local config_line=$(grep "^${uuid}:" "$CONFIG_FILE" 2>/dev/null)
            local config_name=$(echo "$config_line" | cut -d: -f2)
            echo "  Status: ✅ Configured as '$config_name'"
        else
            echo "  Status: ⚠️  Not configured"
        fi
        
        # Check if currently mounted
        local mount_info
        mount_info=$(findmnt -n -o TARGET "$device" 2>/dev/null)
        if [[ -n "$mount_info" ]]; then
            echo "  Mount: 🟢 $mount_info"
        else
            echo "  Mount: ⚪ Not mounted"
        fi
        
        echo
    done <<< "$blkid_output"
    
    if [[ $found_devices -eq 0 ]]; then
        echo "No storage devices with UUIDs found."
        echo "Make sure devices are connected and you're running as root."
    else
        echo "Found $found_devices storage device(s)"
        echo
        echo "To configure a device: autonas add <UUID>"
        echo "To list configured devices: autonas list"
    fi
    
    return 0
}

# Show usage information

# Function to check if UUID exists in configuration
check_uuid_exists() {
    local uuid="$1"
    grep -q "^${uuid}:" "$CONFIG_FILE" 2>/dev/null
}

# Function to get device information
get_device_info() {
    local uuid="$1"
    
    # Find device by UUID using blkid
    local device_line
    device_line=$(blkid | grep "UUID=\"$uuid\"")
    
    if [[ -z "$device_line" ]]; then
        return 1
    fi
    
    local device=$(echo "$device_line" | cut -d: -f1)
    local blkid_info=$(echo "$device_line" | cut -d: -f2-)
    
    echo "device:$device"
    echo "$blkid_info"
    return 0
}

# Function to list configured disks
list_disks() {
    echo "AutoNAS Disk Configurations:"
    echo "============================"
    echo ""

    if [[ ! -f "$CONFIG_FILE" ]]; then
        echo "No configuration file found at: $CONFIG_FILE"
        echo "Use 'autonas add' to add your first disk configuration."
        return 1
    fi

    local config_count=0
    while IFS=':' read -r uuid name ip interface mount_point nfs_options; do
        # Skip empty lines and comments
        [[ -z "$uuid" || "$uuid" =~ ^# ]] && continue
        
        config_count=$((config_count + 1))
        
        echo "UUID: $uuid"
        echo "Name: $name"
        
        # Check if it's a local mount configuration
        if [[ "$ip" == "LOCAL" && "$interface" == "LOCAL" && "$nfs_options" == "LOCAL" ]]; then
            echo "Type: 📁 Local Mount (no network sharing)"
            echo "Mount Point: $mount_point"
        elif [[ "$ip" == "IMPORT" && "$interface" == "IMPORT" ]]; then
            echo "Type: 📷 Camera Import (mount, import, unmount)"
            echo "Import Destination: $nfs_options"
            echo "Import Script: ${AUTONAS_MEDIA_IMPORTER} (built-in, non-configurable)"
            echo "Temp Mount Point: $mount_point"
        else
            echo "Type: 🌐 NFS Network Share"
            echo "IP: $ip"
            echo "Interface: $interface"
            echo "Mount Point: $mount_point"
            echo "NFS Options: $nfs_options"
        fi
        
        # Check device status
        local device_info
        if device_info=$(get_device_info "$uuid" 2>/dev/null); then
            local device=$(echo "$device_info" | grep "^device:" | cut -d: -f2)
            echo "Status: ✅ Connected"
            
            # Check if mounted
            if mountpoint -q "$mount_point" 2>/dev/null; then
                echo "Mount Status: 🟢 Mounted"
                echo "Current Mount: $mount_point"
            else
                echo "Mount Status: 🔴 Not Mounted"
            fi
        else
            echo "Status: 🔴 Not Connected"
        fi
        
        echo "----"
    done < <(grep -v '^#' "$CONFIG_FILE" 2>/dev/null | grep -v '^$')

    if [[ $config_count -eq 0 ]]; then
        echo "No disk configurations found."
        echo "Use 'autonas add' to add your first disk configuration."
        return 1
    fi

    echo ""
    echo "Total configurations: $config_count"
    return 0
}

# Function to add disk configuration
add_disk() {
    local preset_uuid="$1"  # Optional UUID parameter

    echo "AutoNAS - Add New Disk Configuration"
    echo "===================================="
    echo ""

    # Show available disks first
    show_available_disks
    if [ $? -ne 0 ]; then
        echo "Cannot proceed without available disks."
        return 1
    fi

    echo "Please enter the configuration for your disk:"
    echo ""

    # Get UUID with validation
    local uuid="$preset_uuid"
    if [ -n "$uuid" ]; then
        echo "Using provided UUID: $uuid"

        if ! validate_uuid "$uuid"; then
            echo "Error: Invalid UUID format. Expected format: 12345678-1234-1234-1234-123456789abc"
            echo "Please run without UUID parameter to enter manually."
            return 1
        fi

        if check_uuid_exists "$uuid"; then
            echo "Error: UUID $uuid is already configured."
            echo "Use 'autonas remove $uuid' to remove existing configuration first."
            return 1
        fi
    else
        while true; do
            read -p "Enter disk UUID: " uuid
            if [ -z "$uuid" ]; then
                echo "Error: UUID cannot be empty"
                continue
            fi

            if ! validate_uuid "$uuid"; then
                echo "Error: Invalid UUID format. Expected format: 12345678-1234-1234-1234-123456789abc"
                continue
            fi

            if check_uuid_exists "$uuid"; then
                echo "Error: UUID $uuid is already configured."
                echo "Use 'autonas remove $uuid' to remove existing configuration first."
                continue
            fi

            break
        done
    fi

    # Get and validate disk name
    local name
    while true; do
        read -p "Enter disk name (letters, numbers, hyphens, underscores, @ allowed): " name
        if [ -z "$name" ]; then
            echo "Error: Disk name cannot be empty"
            continue
        fi

        if ! validate_disk_name_complete "$name"; then
            local validation_result=$?
            if [[ $validation_result -eq 2 ]]; then
                echo "Error: Disk name '$name' already exists. Please choose another name."
                echo ""
                list_existing_disk_names
                echo ""
                continue
            else
                echo "Error: Invalid disk name. Requirements:"
                echo "  - Max 50 characters"
                echo "  - Must start with letter or number"
                echo "  - Only letters, numbers, hyphens (-), underscores (_), and at symbol (@)"
                echo "  - Cannot be reserved names (root, home, tmp, etc.)"
                continue
            fi
        fi

        break
    done

    # Choose configuration type
    echo ""
    echo "Select disk type:"
    echo "1) NFS Network Share (default) - Share disk over network"
    echo "2) Camera Import - Import photos/videos from camera and unmount"
    echo "3) Local Mount - Mount locally without network sharing"
    echo ""
    
    local config_type
    read -p "Choose type [1-3] (default: 1): " config_type
    config_type=${config_type:-1}

    case "$config_type" in
        1)
            configure_nfs_disk "$uuid" "$name"
            ;;
        2)
            configure_import_disk "$uuid" "$name"
            ;;
        3)
            configure_local_disk "$uuid" "$name"
            ;;
        *)
            echo "Invalid choice. Using NFS Network Share (default)."
            configure_nfs_disk "$uuid" "$name"
            ;;
    esac
}

# Function to configure NFS disk
configure_nfs_disk() {
    local uuid="$1"
    local name="$2"
    
    echo ""
    echo "=== NFS Network Share Configuration ==="
    
    # Get IP address
    local ip
    while true; do
        read -p "Enter IP address for NFS sharing (e.g., 192.168.1.100): " ip
        if [ -z "$ip" ]; then
            echo "Error: IP address cannot be empty"
            continue
        fi
        
        # Basic IP validation
        if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            echo "Error: Invalid IP address format"
            continue
        fi
        
        # Check each octet
        local valid_ip=true
        IFS='.' read -ra OCTETS <<< "$ip"
        for octet in "${OCTETS[@]}"; do
            if [ "$octet" -lt 0 ] || [ "$octet" -gt 255 ]; then
                valid_ip=false
                break
            fi
        done
        
        if [ "$valid_ip" = false ]; then
            echo "Error: IP address octets must be between 0-255"
            continue
        fi
        
        break
    done
    
    # Get network interface
    local interface
    echo ""
    echo "Available network interfaces:"
    ip link show | grep "^[0-9]" | cut -d: -f2 | sed 's/^ *//' | grep -v "^lo$"
    echo ""
    
    while true; do
        read -p "Enter network interface (e.g., eth0, enp0s3): " interface
        if [ -z "$interface" ]; then
            echo "Error: Network interface cannot be empty"
            continue
        fi
        
        # Check if interface exists
        if ! ip link show "$interface" >/dev/null 2>&1; then
            echo "Error: Network interface '$interface' does not exist"
            echo "Available interfaces:"
            ip link show | grep "^[0-9]" | cut -d: -f2 | sed 's/^ *//' | grep -v "^lo$"
            continue
        fi
        
        break
    done
    
    # Generate mount point
    local mount_point="$MOUNT_BASE/$name"
    echo ""
    echo "Mount point will be: $mount_point"
    
    # Get NFS options
    local nfs_options
    echo ""
    echo "NFS Options (press Enter for default):"
    echo "Default: *(rw,all_squash,insecure,async,no_subtree_check,anonuid=0,anongid=0)"
    read -p "Enter custom NFS options or press Enter for default: " nfs_options
    
    if [ -z "$nfs_options" ]; then
        nfs_options="*(rw,all_squash,insecure,async,no_subtree_check,anonuid=0,anongid=0)"
    fi
    
    # Create configuration entry
    local config_entry="${uuid}:${name}:${ip}:${interface}:${mount_point}:${nfs_options}"
    
    # Show configuration summary
    echo ""
    echo "=== Configuration Summary ==="
    echo "UUID: $uuid"
    echo "Name: $name"
    echo "Type: NFS Network Share"
    echo "IP: $ip"
    echo "Interface: $interface"
    echo "Mount Point: $mount_point"
    echo "NFS Options: $nfs_options"
    echo ""
    
    # Confirm configuration
    read -p "Save this configuration? (Y/n): " confirm
    if [[ "$confirm" =~ ^[Nn]$ ]]; then
        echo "Configuration cancelled."
        return 1
    fi
    
    # Save configuration
    echo "$config_entry" >> "$CONFIG_FILE"
    echo ""
    echo "✅ Configuration saved successfully!"
    echo ""
    echo "To test this configuration: autonas test $uuid"
    echo "To attach this disk when connected: autonas attach $uuid"
    
    return 0
}

# Function to configure local disk
configure_local_disk() {
    local uuid="$1"
    local name="$2"
    
    echo ""
    echo "=== Local Mount Configuration ==="
    echo "This disk will be mounted locally without network sharing."
    echo ""
    
    # Generate mount point
    local mount_point="$MOUNT_BASE/$name"
    echo "Mount point will be: $mount_point"
    echo ""
    
    # Create configuration entry
    local config_entry="${uuid}:${name}:LOCAL:LOCAL:${mount_point}:LOCAL"
    
    # Show configuration summary
    echo "=== Configuration Summary ==="
    echo "UUID: $uuid"
    echo "Name: $name"
    echo "Type: Local Mount (no network sharing)"
    echo "Mount Point: $mount_point"
    echo ""
    
    # Confirm configuration
    read -p "Save this configuration? (Y/n): " confirm
    if [[ "$confirm" =~ ^[Nn]$ ]]; then
        echo "Configuration cancelled."
        return 1
    fi
    
    # Save configuration
    echo "$config_entry" >> "$CONFIG_FILE"
    echo ""
    echo "✅ Configuration saved successfully!"
    echo ""
    echo "To test this configuration: autonas test $uuid"
    echo "To attach this disk when connected: autonas attach $uuid"
    
    return 0
}

# Function to configure import disk (camera)
configure_import_disk() {
    local uuid="$1"
    local name="$2"
    
    echo ""
    echo "=== Camera Import Configuration ==="
    echo "This device will be mounted temporarily, media imported, then unmounted."
    echo ""
    
    # Get destination path for import
    local destination_path
    while true; do
        read -p "Enter destination path for imported media: " destination_path
        if [ -z "$destination_path" ]; then
            echo "Error: Destination path cannot be empty"
            continue
        fi
        
        # Convert relative path to absolute
        if [[ ! "$destination_path" =~ ^/ ]]; then
            destination_path="$(pwd)/$destination_path"
        fi
        
        # Validate parent directory exists
        local parent_dir=$(dirname "$destination_path")
        if [ ! -d "$parent_dir" ]; then
            echo "Warning: Parent directory '$parent_dir' does not exist."
            read -p "Create parent directories? (Y/n): " create_dirs
            if [[ ! "$create_dirs" =~ ^[Nn]$ ]]; then
                if mkdir -p "$parent_dir" 2>/dev/null; then
                    echo "Created parent directories."
                else
                    echo "Error: Failed to create parent directories. Please check permissions."
                    continue
                fi
            else
                echo "Please enter a valid destination path."
                continue
            fi
        fi
        
        break
    done
    
    # Generate temporary mount point for import
    local temp_mount_point="$MOUNT_BASE/$name"
    
    # Create configuration entry (simplified format - no script path)
    local config_entry="${uuid}:${name}:IMPORT:IMPORT:${temp_mount_point}:${destination_path}"
    
    # Show configuration summary
    echo ""
    echo "=== Configuration Summary ==="
    echo "UUID: $uuid"
    echo "Name: $name"
    echo "Type: Camera Import (mount, import, unmount)"
    echo "Import destination: $destination_path"
    echo "Import script: ${AUTONAS_MEDIA_IMPORTER} (built-in, non-configurable)"
    echo "Temp mount point: $temp_mount_point"
    echo ""
    
    # Confirm configuration
    read -p "Save this configuration? (Y/n): " confirm
    if [[ "$confirm" =~ ^[Nn]$ ]]; then
        echo "Configuration cancelled."
        return 1
    fi
    
    # Save configuration
    echo "$config_entry" >> "$CONFIG_FILE"
    echo ""
    echo "✅ Configuration saved successfully!"
    echo ""
    echo "To test this configuration: autonas test $uuid"  
    echo "When camera is connected, media will be imported automatically to: $destination_path"
    
    return 0
}

# Function to remove disk configuration
remove_disk() {
    local identifier="$1"
    
    if [[ -z "$identifier" ]]; then
        echo "Usage: autonas remove <uuid|name|mount_point>"
        return 1
    fi
    
    if [[ ! -f "$CONFIG_FILE" ]]; then
        echo "No configuration file found."
        return 1
    fi
    
    local config
    config=$(resolve_config_identifier "$identifier")
    if [[ -z "$config" ]]; then
        echo "Error: Entry '$identifier' not found in configuration."
        return 1
    fi

    local parsed=($(parse_config "$config"))
    local uuid="${parsed[0]}"

    # Show current configuration
    echo "Current configuration for identifier: $identifier"
    echo "=================================="
    echo "Name: ${parsed[1]}"
    echo "Type: ${parsed[2]}:${parsed[3]}"
    echo "Mount: ${parsed[4]}"
    echo ""
    
    # Confirm removal
    read -p "Remove this configuration? (y/N): " confirm
    if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
        echo "Removal cancelled."
        return 1
    fi
    
    # Remove configuration
    local temp_file=$(mktemp)
    grep -v "^${uuid}:" "$CONFIG_FILE" > "$temp_file"
    mv "$temp_file" "$CONFIG_FILE"
    
    echo "✅ Configuration removed successfully!"
    return 0
}

# Function to test disk configuration
test_config() {
    local identifier="$1"

    if [[ -z "$identifier" ]]; then
        echo "Usage: autonas test <uuid|name|mount_point>"
        return 1
    fi
    
    echo "AutoNAS Configuration Test"
    echo "========================="
    echo ""
    
    # Check if configuration exists
    local config
    config=$(resolve_config_identifier "$identifier")

    if [[ -z "$config" ]]; then
        echo "❌ Configuration not found for identifier: $identifier"
        echo ""
        echo "Available configurations:"
        list_disks
        return 1
    fi
    
    # Parse configuration
    local parsed=($(parse_config "$config"))
    local cfg_uuid="${parsed[0]}"
    local name="${parsed[1]}"
    local ip="${parsed[2]}"
    local interface="${parsed[3]}"
    local mount_point="${parsed[4]}"
    local nfs_options="${parsed[5]}"

    echo "✅ Configuration found"
    echo "   UUID: $cfg_uuid"
    echo "   Identifier used: $identifier"
    echo "   Name: $name"
    echo "   Type: $ip:$interface"
    echo "   Mount Point: $mount_point"
    echo ""
    
    # Test device detection
    echo "🔍 Testing device detection..."
    local device_info
    if device_info=$(get_device_info "$cfg_uuid" 2>/dev/null); then
        local device=$(echo "$device_info" | grep "^device:" | cut -d: -f2)
        echo "✅ Device found: $device"
        
        # Show device details
        echo "$device_info" | grep -v "^device:" | while IFS= read -r line; do
            echo "   $line"
        done
    else
        echo "❌ Device not found or not connected"
        echo "   Make sure the device with UUID $cfg_uuid is connected"
        return 1
    fi
    echo ""
    
    # Test network configuration (if applicable)
    if [[ "$ip" != "LOCAL" && "$ip" != "IMPORT" ]]; then
        echo "🌐 Testing network configuration..."
        
        # Test interface
        if interface_exists "$interface"; then
            echo "✅ Network interface exists: $interface"
        else
            echo "❌ Network interface not found: $interface"
            echo "   Available interfaces:"
            ip link show | grep "^[0-9]" | cut -d: -f2 | sed 's/^ *//' | grep -v "^lo$" | sed 's/^/     /'
            return 1
        fi
        
        # Test IP configuration
        if is_ip_configured "$ip" "$interface"; then
            echo "✅ IP already configured: $ip on $interface"
        else
            echo "ℹ️  IP not currently configured: $ip on $interface"
            echo "   (This is normal - IP will be activated during attach)"
        fi
        echo ""
    fi
    
    # Test mount point
    echo "📁 Testing mount point..."
    if [[ -d "$mount_point" ]]; then
        if mountpoint -q "$mount_point" 2>/dev/null; then
            echo "✅ Mount point exists and is mounted: $mount_point"
            local mounted_device=$(findmnt -n -o SOURCE "$mount_point")
            echo "   Mounted device: $mounted_device"
        else
            echo "ℹ️  Mount point directory exists but not mounted: $mount_point"
        fi
    else
        echo "ℹ️  Mount point directory will be created: $mount_point"
    fi
    echo ""
    
    # Test import configuration (if applicable)
    if [[ "$ip" == "IMPORT" && "$interface" == "IMPORT" ]]; then
        echo "📷 Testing camera import configuration..."
        local destination="$nfs_options"
        
        if [[ -d "$destination" ]]; then
            echo "✅ Import destination exists: $destination"
            if [[ -w "$destination" ]]; then
                echo "✅ Import destination is writable"
            else
                echo "⚠️  Import destination is not writable"
                echo "   You may need to check permissions"
            fi
        else
            echo "ℹ️  Import destination will be created: $destination"
            local parent_dir=$(dirname "$destination")
            if [[ -d "$parent_dir" && -w "$parent_dir" ]]; then
                echo "✅ Parent directory exists and is writable"
            else
                echo "❌ Cannot create import destination"
                echo "   Parent directory: $parent_dir"
                return 1
            fi
        fi
        
        # Test import script
        if [[ -x "${AUTONAS_MEDIA_IMPORTER}" ]]; then
            echo "✅ Media import script is available and executable"
        else
            echo "❌ Media import script not found or not executable"
            echo "   Expected: ${AUTONAS_MEDIA_IMPORTER}"
            return 1
        fi
        echo ""
    fi
    
    echo "🎉 Configuration test completed successfully!"
    echo ""
    echo "You can now attach this disk with: autonas attach $cfg_uuid"
    return 0
}

# Main configuration functions would go here...

# Main command dispatcher
case "${1:-}" in
    "attach")
        if [[ -z "$2" ]]; then
            echo "Error: UUID, disk name, or mount point required for attach command"
            show_usage
            exit 1
        fi
        handle_attach "$2"
        ;;
    "detach")
        if [[ -z "$2" ]]; then
            echo "Error: UUID, disk name, or mount point required for detach command"
            show_usage
            exit 1
        fi
        handle_detach "$2"
        ;;
    "import")
        # Internal use only - background import process
        if [[ -z "$4" ]]; then
            echo "Error: Missing arguments for import command"
            exit 1
        fi
        run_background_import "$2" "$3" "$4" "$5"
        ;;
    "reload")
        handle_reload
        ;;
    "add")
        add_disk "$2"
        ;;
    "remove")
        if [[ -z "$2" ]]; then
            echo "Error: UUID, disk name, or mount point required for remove command"
            show_usage
            exit 1
        fi
        remove_disk "$2"
        ;;
    "list")
        list_disks
        ;;
    "test")
        if [[ -z "$2" ]]; then
            echo "Error: UUID, disk name, or mount point required for test command"
            show_usage
            exit 1
        fi
        test_config "$2"
        ;;
    "show")
        show_available_disks
        ;;
    "status")
        echo "=== AutoNAS System Status ==="
        echo "Configuration file: $CONFIG_FILE"
        if [[ -f "$CONFIG_FILE" ]]; then
            count=$(grep -c "^[^#].*:.*:.*:" "$CONFIG_FILE" 2>/dev/null || echo "0")
            echo "Configured disks: $count"
        else
            echo "Configured disks: 0 (no config file)"
        fi
        echo "NFS server: $(systemctl is-active nfs-kernel-server 2>/dev/null || echo "unknown")"
        echo "AutoNAS service: $(systemctl is-active autonas 2>/dev/null || echo "unknown")"
        echo "Boot scan service: $(systemctl is-active autonas-boot-scan 2>/dev/null || echo "unknown")"
        echo ""
        echo "Recent logs:"
        journalctl -t autonas -n 5 --no-pager 2>/dev/null || echo "No recent logs found"
        ;;
    "debug")
        case "${2:-}" in
            "enable")
                if [ -f "${AUTONAS_DEFAULTS_FILE}" ]; then
                    sed -i 's/AUTONAS_DEBUG="false"/AUTONAS_DEBUG="true"/' "${AUTONAS_DEFAULTS_FILE}"
                    echo "✓ Debug mode enabled - verbose logging is now active"
                    echo "  All AutoNAS operations will produce detailed debug output"
                else
                    echo "Error: Configuration file ${AUTONAS_DEFAULTS_FILE} not found"
                    exit 1
                fi
                ;;
            "disable")
                if [ -f "${AUTONAS_DEFAULTS_FILE}" ]; then
                    sed -i 's/AUTONAS_DEBUG="true"/AUTONAS_DEBUG="false"/' "${AUTONAS_DEFAULTS_FILE}"
                    echo "✓ Debug mode disabled - normal logging restored"
                else
                    echo "Error: Configuration file ${AUTONAS_DEFAULTS_FILE} not found"
                    exit 1
                fi
                ;;
            "status")
                if [ -f "${AUTONAS_DEFAULTS_FILE}" ]; then
                    echo "=== AutoNAS Debug Configuration ==="
                    source "${AUTONAS_DEFAULTS_FILE}"
                    echo "Debug mode: ${AUTONAS_DEBUG:-false}"
                    echo "Log level: ${AUTONAS_LOG_LEVEL:-info}"
                    if [ "$AUTONAS_DEBUG" = "true" ]; then
                        echo "Status: 🟢 Debug logging is ENABLED"
                        echo "  - Verbose messages will appear in logs and stderr"
                        echo "  - All operations will be traced in detail"
                    else
                        echo "Status: 🔴 Debug logging is DISABLED"
                        echo "  - Only normal info/warning/error messages will appear"
                    fi
                else
                    echo "Error: Configuration file ${AUTONAS_DEFAULTS_FILE} not found"
                    exit 1
                fi
                ;;
            "")
                echo "Error: Debug command requires an argument"
                echo "Usage: $0 debug {enable|disable|status}"
                exit 1
                ;;
            *)
                echo "Error: Unknown debug command '$2'"
                echo "Usage: $0 debug {enable|disable|status}"
                exit 1
                ;;
        esac
        ;;
    "help"|"-h"|"--help"|"")
        show_usage
        ;;
    *)
        echo "Error: Unknown command '$1'"
        echo
        show_usage
        exit 1
        ;;
esac