#!/bin/bash set -e set -o pipefail LOGFILE="extend-lvm.log" MODE="LIVE" USER_DISK="" GREEN="\e[32m" RESET="\e[0m" usage() { echo "Uso: $0 [test|--test] [--disk |--disk=]" echo "Esempi:" echo " $0 test" echo " $0 --disk /dev/sdb" echo " $0 --test --disk=sdb" } while [ $# -gt 0 ]; do case "$1" in test|--test) MODE="TEST" ;; --disk) shift if [ -z "$1" ]; then echo "ERRORE: --disk richiede un valore" >&2 usage >&2 exit 1 fi USER_DISK="$1" ;; --disk=*) USER_DISK="${1#*=}" ;; -h|--help) usage exit 0 ;; *) echo "ERRORE: argomento non riconosciuto: $1" >&2 usage >&2 exit 1 ;; esac shift done log() { echo "$(date '+%F %T') | $1" | tee -a "$LOGFILE" } run() { if [ "$MODE" == "TEST" ]; then log "[TEST] $*" else log "[RUN] $*" eval "$@" fi } log "==========================================" log "Avvio script LVM Auto Expand ($MODE)" if [ "$EUID" -ne 0 ]; then log "ERRORE: eseguire come root" exit 1 fi for cmd in lsblk df awk grep findmnt lvs pvcreate vgextend lvextend flock tr; do if ! command -v "$cmd" >/dev/null 2>&1; then log "ERRORE: comando richiesto non trovato: $cmd" exit 1 fi done LOCKFILE="/var/lock/auto-lvm-add-disk.lock" if [ ! -d "/var/lock" ]; then LOCKFILE="/tmp/auto-lvm-add-disk.lock" fi exec 200>"$LOCKFILE" if ! flock -n 200; then log "ERRORE: script già in esecuzione (lock: $LOCKFILE)" exit 1 fi log "Lock acquisito: $LOCKFILE" # --- Spazio iniziale --- START_SIZE=$(df -BG / | awk 'NR==2 {print $2}' | tr -d 'G') # --- Forza rescan SCSI --- log "Scansione bus SCSI..." for host in /sys/class/scsi_host/host*; do run "echo '- - -' > $host/scan" done sleep 2 # --- Trova disco nuovo --- log "Rilevo il nuovo disco..." DISK="" if [ -n "$USER_DISK" ]; then if [[ "$USER_DISK" == /dev/* ]]; then DISK="$USER_DISK" else DISK="/dev/$USER_DISK" fi if [ ! -b "$DISK" ]; then log "ERRORE: disco specificato non valido: $DISK" exit 1 fi DISK_TYPE=$(lsblk -ndo TYPE "$DISK") DISK_FSTYPE=$(lsblk -ndo FSTYPE "$DISK") if [ "$DISK_TYPE" != "disk" ]; then log "ERRORE: il device specificato non è un disco: $DISK" exit 1 fi if [ -n "$DISK_FSTYPE" ]; then log "ERRORE: il disco specificato contiene già un filesystem: $DISK" exit 1 fi if lsblk "$DISK" | grep -q part; then log "ERRORE: il disco specificato contiene partizioni: $DISK" exit 1 fi log "Disco specificato da CLI: $DISK" else NEW_DISK="" for d in $(lsblk -ndo NAME,TYPE,FSTYPE | awk '$2=="disk" && $3=="" {print $1}'); do if ! lsblk /dev/$d | grep -q part; then NEW_DISK="$d" break fi done if [ -z "$NEW_DISK" ]; then log "ERRORE: nessun disco nuovo trovato" exit 1 fi DISK="/dev/$NEW_DISK" fi DISK_SIZE=$(lsblk -ndo SIZE $DISK) log "Nuovo disco corretto: ${GREEN}$DISK ($DISK_SIZE)${RESET}" # --- VG e LV del mountpoint root --- ROOT_SOURCE=$(findmnt -n -o SOURCE /) if [ -z "$ROOT_SOURCE" ] || [[ "$ROOT_SOURCE" != /dev/* ]]; then log "ERRORE: impossibile determinare il device root da /" exit 1 fi ROOT_FSTYPE=$(findmnt -n -o FSTYPE /) LV="$ROOT_SOURCE" VG=$(lvs --noheadings -o vg_name "$LV" 2>/dev/null | awk '{$1=$1; print}') if [ -z "$VG" ]; then log "ERRORE: il device root ($LV) non risulta un Logical Volume LVM" exit 1 fi log "Volume Group: $VG" log "Logical Volume: $LV" log "Filesystem root: $ROOT_FSTYPE" # --- Operazioni --- run "pvcreate $DISK" run "vgextend $VG $DISK" run "lvextend -l +100%FREE $LV" case "$ROOT_FSTYPE" in ext2|ext3|ext4) if ! command -v resize2fs >/dev/null 2>&1; then log "ERRORE: resize2fs non trovato ma richiesto per filesystem $ROOT_FSTYPE" exit 1 fi run "resize2fs $LV" ;; xfs) if ! command -v xfs_growfs >/dev/null 2>&1; then log "ERRORE: xfs_growfs non trovato ma richiesto per filesystem xfs" exit 1 fi run "xfs_growfs /" ;; *) log "ERRORE: filesystem root non supportato: $ROOT_FSTYPE" exit 1 ;; esac # --- Spazio finale --- END_SIZE=$(df -BG / | awk 'NR==2 {print $2}' | tr -d 'G') DELTA=$((END_SIZE - START_SIZE)) echo -e "${GREEN}" echo "=====================================" echo " LVM EXTENSION COMPLETATA" echo "-------------------------------------" echo " Disco aggiunto : $DISK" echo " Dimensione : $DISK_SIZE" echo " Spazio prima : ${START_SIZE}G" echo " Spazio dopo : ${END_SIZE}G" echo " Aumento : +${DELTA}G" echo "=====================================" echo -e "${RESET}" log "Spazio iniziale: ${START_SIZE}G" log "Spazio finale : ${END_SIZE}G" log "Aumento : +${DELTA}G" log "Operazione completata" log "=========================================="