Files
ubuntu-volume-exporter/exportdisk.sh
2026-02-03 12:23:10 +01:00

224 lines
7.2 KiB
Bash

#!/bin/bash
#
# VM Export Script - Tim Cloud Flex to ESXi Migration
# Rileva automaticamente i dischi e li esporta verso server remoto
#
set -e # Exit on error
# File di configurazione
CONFIG_FILE="${1:-./exportdisk.conf}"
# Verifica esistenza file di configurazione
if [[ ! -f "$CONFIG_FILE" ]]; then
echo "Errore: File di configurazione non trovato: $CONFIG_FILE"
echo "Uso: $0 [percorso-config-file]"
echo "Se non specificato, cerca ./exportdisk.conf"
exit 1
fi
# Carica configurazione
echo "Caricamento configurazione da: $CONFIG_FILE"
source "$CONFIG_FILE"
# Verifica parametri obbligatori
if [[ -z "$REMOTE_USER" ]] || [[ -z "$REMOTE_HOST" ]] || [[ -z "$REMOTE_PATH" ]]; then
echo "Errore: Parametri obbligatori mancanti nel file di configurazione"
echo "Richiesti: REMOTE_USER, REMOTE_HOST, REMOTE_PATH"
exit 1
fi
# Imposta valori di default se non specificati
EXCLUDE_DEVICES="${EXCLUDE_DEVICES:-loop|sr|dm-}"
MIN_DISK_SIZE_GB="${MIN_DISK_SIZE_GB:-1}"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Colori per output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}VM Disk Export Script${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
# Verifica se eseguito come root
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}Questo script deve essere eseguito come root${NC}"
exit 1
fi
# Funzione per rilevare i dischi
detect_disks() {
local disks=()
# Scansiona tutti i tipi di device: sd* (SCSI/SATA), vd* (virtio), xvd* (Xen), nvme* (NVMe)
for device in /sys/block/sd* /sys/block/vd* /sys/block/xvd* /sys/block/nvme*; do
if [[ ! -d "$device" ]]; then
continue
fi
disk_name=$(basename "$device")
# Esclude dispositivi specifici
if echo "$disk_name" | grep -qE "$EXCLUDE_DEVICES"; then
continue
fi
# Per NVMe, considera solo i namespace principali (nvme0n1, nvme1n1, ecc.)
if [[ "$disk_name" == nvme* ]] && [[ ! "$disk_name" =~ ^nvme[0-9]+n[0-9]+$ ]]; then
continue
fi
# Verifica se il disco è removibile (esclude USB, ecc.)
if [[ -f "$device/removable" ]] && [[ $(cat "$device/removable") -eq 1 ]]; then
continue
fi
# Ottieni dimensione del disco
if [[ -f "$device/size" ]]; then
sectors=$(cat "$device/size")
# Calcola dimensione in GB (settori * 512 byte / 1024^3)
size_gb=$(awk "BEGIN {printf \"%.2f\", $sectors * 512 / 1024 / 1024 / 1024}")
# Verifica dimensione minima
if (( $(echo "$size_gb >= $MIN_DISK_SIZE_GB" | bc -l) )); then
disks+=("/dev/$disk_name:$size_gb")
echo " [OK] Rilevato: /dev/$disk_name (${size_gb} GB)" >&2
fi
fi
done
if [[ ${#disks[@]} -eq 0 ]]; then
echo "Errore: Nessun disco rilevato" >&2
exit 1
fi
echo "" >&2
echo "Dischi da esportare: ${#disks[@]}" >&2
printf '%s\n' "${disks[@]}"
}
# Rileva i dischi
echo -e "${YELLOW}[1/6] Rilevamento dischi...${NC}"
mapfile -t DISKS < <(detect_disks)
# Verifica se pv è installato
echo -e "${YELLOW}[2/6] Verifica dipendenze...${NC}"
if ! command -v pv &> /dev/null; then
echo -e "${YELLOW}pv (Pipe Viewer) non è installato. Installazione in corso...${NC}"
apt-get update -qq && apt-get install -y pv || yum install -y pv || {
echo -e "${RED}Impossibile installare pv. Installa manualmente: apt-get install pv${NC}"
exit 1
}
fi
# Verifica bc per i calcoli
if ! command -v bc &> /dev/null; then
echo -e "${YELLOW}bc non è installato. Installazione in corso...${NC}"
apt-get update -qq && apt-get install -y bc || yum install -y bc || {
echo -e "${RED}Impossibile installare bc. Installa manualmente: apt-get install bc${NC}"
exit 1
}
fi
echo -e "${GREEN}✓ Dipendenze OK${NC}"
echo ""
# Verifica connettività SSH
echo -e "${YELLOW}[3/6] Verifica connettività verso ${REMOTE_HOST}...${NC}"
if ! ssh -o ConnectTimeout=5 ${REMOTE_USER}@${REMOTE_HOST} "echo 'OK'" &> /dev/null; then
echo -e "${RED}Errore: Impossibile connettersi a ${REMOTE_USER}@${REMOTE_HOST}${NC}"
echo "Assicurati che SSH sia configurato e che la chiave pubblica sia installata."
exit 1
fi
echo -e "${GREEN}✓ Connessione SSH OK${NC}"
echo ""
# Verifica spazio su destinazione
echo -e "${YELLOW}[4/6] Verifica spazio disponibile su ${REMOTE_HOST}...${NC}"
REMOTE_SPACE=$(ssh ${REMOTE_USER}@${REMOTE_HOST} "df -BG ${REMOTE_PATH} | tail -1 | awk '{print \$4}' | sed 's/G//'")
echo -e "Spazio disponibile: ${REMOTE_SPACE} GB"
if [[ $REMOTE_SPACE -lt 30 ]]; then
echo -e "${RED}Attenzione: Spazio insufficiente (minimo 30GB consigliato)${NC}"
read -p "Continuare comunque? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
echo -e "${GREEN}✓ Spazio OK${NC}"
echo ""
# Crea directory backup se non esiste
echo -e "${YELLOW}[5/6] Preparazione directory remota...${NC}"
ssh ${REMOTE_USER}@${REMOTE_HOST} "mkdir -p ${REMOTE_PATH}"
echo -e "${GREEN}✓ Directory pronta${NC}"
echo ""
# Export di tutti i dischi rilevati
echo -e "${YELLOW}[6/6] Esportazione dischi...${NC}"
echo ""
disk_counter=1
total_disks=${#DISKS[@]}
for disk_info in "${DISKS[@]}"; do
disk=$(echo "$disk_info" | cut -d':' -f1)
disk_name=$(basename "$disk")
echo -e "${BLUE}[$disk_counter/$total_disks] Esportazione $disk ...${NC}"
echo -e "Destinazione: ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/${disk_name}_${TIMESTAMP}.img.gz"
echo ""
# Ottieni dimensione del disco
DISK_SIZE=$(blockdev --getsize64 "$disk")
# Esegui export
dd if="$disk" bs=16M conv=sync,noerror 2>/dev/null | \
pv -s ${DISK_SIZE} -N "$disk_name" -p -t -e -r -b | \
gzip -1 | \
ssh ${REMOTE_USER}@${REMOTE_HOST} "cat > ${REMOTE_PATH}/${disk_name}_${TIMESTAMP}.img.gz"
echo -e "\n${GREEN}$disk esportato con successo${NC}"
echo ""
((disk_counter++))
done
# Summary
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Esportazione completata!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "File creati su ${REMOTE_HOST}:"
ssh ${REMOTE_USER}@${REMOTE_HOST} "ls -lh ${REMOTE_PATH}/*${TIMESTAMP}*.gz"
echo ""
echo -e "${YELLOW}Prossimi passi:${NC}"
echo "1. Decomprimere i file sul server remoto:"
for disk_info in "${DISKS[@]}"; do
disk_name=$(basename $(echo "$disk_info" | cut -d':' -f1))
echo " gunzip ${REMOTE_PATH}/${disk_name}_${TIMESTAMP}.img.gz"
done
echo ""
echo "2. Convertire in VMDK:"
for disk_info in "${DISKS[@]}"; do
disk_name=$(basename $(echo "$disk_info" | cut -d':' -f1))
echo " qemu-img convert -p -f raw -O vmdk -o subformat=monolithicSparse ${disk_name}_${TIMESTAMP}.img ${disk_name}.vmdk -p"
done
echo ""
echo "3. Trasferire i VMDK su ESXi e convertire in thin provisioning:"
for disk_info in "${DISKS[@]}"; do
disk_name=$(basename $(echo "$disk_info" | cut -d':' -f1))
echo " vmkfstools -i /vmfs/volumes/<datastore>/${disk_name}.vmdk -d thin /vmfs/volumes/<datastore>/${disk_name}-thin.vmdk"
done
echo ""
echo "4. Importare la VM su ESXi"
echo ""
exit 0