Script para mover los discos virtuales de vm/ct a un nuevo almacenamiento

Como tenía varios discos de máquinas virtuales y contenedores de diferentes nodos Proxmox que quería mover al almacenamiento LVM_thin, decidí automatizar la tarea con un script.

A continuación pego el código:

#!/bin/bash
#
# proxmox-move-disk: move ct/vm disk to another storage
#
# Esteban M. Navas Martin
# algodelinux@gmail.com
#

# Verifica los argumentos
VMID="$1"
TARGET_STORAGE="$2"
EMAIL="$3"
LOG_FILE="/var/log/proxmox_disk_migration.log"

if [[ -z "$VMID" || -z "$TARGET_STORAGE" || -z "$EMAIL" ]]; then
  echo "Uso: $0 <vmid/lxcid> <target-storage> <email>"
  exit 1
fi

# Función para loguear
log_message() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Función para enviar correo
send_email() {
  SUBJECT="$1"
  BODY="$2"
  echo -e "$BODY" | mail -s "$SUBJECT" "$EMAIL"
}

# Enviar correo de inicio
send_email "Iniciando migración de disco en Proxmox" "Se ha iniciado la migración de disco para VM/Contenedor con ID $VMID hacia $TARGET_STORAGE."

log_message "Iniciando migración de disco para VM/Contenedor con ID $VMID hacia $TARGET_STORAGE."

# Detectar si es una VM o un contenedor
if qm status "$VMID" &>/dev/null; then
  TYPE="vm"
elif pct status "$VMID" &>/dev/null; then
  TYPE="lxc"
else
  log_message "Error: ID $VMID no corresponde a una VM ni a un contenedor."
  send_email "Error en la migración de disco" "El ID $VMID no corresponde a una VM ni a un contenedor."
  exit 1
fi

# Apagar si está corriendo
if [[ "$TYPE" == "vm" ]]; then
  STATE=$(qm status "$VMID" | awk '{print $2}')
  if [[ "$STATE" == "running" ]]; then
    log_message "Apagando VM $VMID..."
    qm shutdown "$VMID"
    while [[ "$(qm status "$VMID" | awk '{print $2}')" != "stopped" ]]; do sleep 2; done
    log_message "VM $VMID apagada."
  fi

  # Detectar discos primarios y secundarios
  DISK_IDS=$(qm config "$VMID" | grep -E '^(virtio|scsi|sata)[0-9]:' | cut -d':' -f1)

  if [[ -z "$DISK_IDS" ]]; then
    log_message "Error: No se detectaron discos válidos para la VM."
    send_email "Error en la migración de disco" "No se detectaron discos válidos para la VM $VMID."
    exit 1
  fi

  for DISK_ID in $DISK_IDS; do
    log_message "Moviendo disco $DISK_ID a $TARGET_STORAGE..."
    qm disk move "$VMID" "$DISK_ID" "$TARGET_STORAGE" --delete 1
  done
  qm start "$VMID"
  log_message "✅ Discos movidos y VM arrancada."
  send_email "Migración de disco completada" "La migración de discos de la VM $VMID a $TARGET_STORAGE ha sido completada con éxito."

elif [[ "$TYPE" == "lxc" ]]; then
  STATE=$(pct status "$VMID" | awk '{print $2}')
  if [[ "$STATE" == "running" ]]; then
    log_message "Apagando contenedor $VMID..."
    pct shutdown "$VMID"
    while [[ "$(pct status "$VMID" | awk '{print $2}')" != "stopped" ]]; do sleep 2; done
    log_message "Contenedor $VMID apagado."
  fi

  # Detectar disco del contenedor
  DISK_NAME=$(pct config "$VMID" | grep -E '^rootfs:' | cut -d',' -f1 | cut -d':' -f2)
  if [[ -z "$DISK_NAME" ]]; then
    log_message "Error: No se detectó el volumen rootfs del contenedor."
    send_email "Error en la migración de disco" "No se detectó el volumen rootfs del contenedor $VMID."
    exit 1
  fi

  log_message "Moviendo rootfs de contenedor $VMID a $TARGET_STORAGE..."
  pct move-volume "$VMID" rootfs "$TARGET_STORAGE" --delete
  pct start "$VMID"
  log_message "✅ Rootfs movido y contenedor arrancado."
  send_email "Migración de disco completada" "La migración del rootfs del contenedor $VMID a $TARGET_STORAGE ha sido completada con éxito."
fi

🧰 ¿Qué hace este script?

  1. Notificación por correo electrónico (opcional):
    • Si se proporciona un correo electrónico, el script enviará notificaciones por correo al inicio y al final de la migración (también enviará correos en caso de error).
    • Si no se proporciona un correo electrónico, no se enviarán correos.
  2. Soporte para mover discos adicionales:
    • Detecta discos secundarios como virtio1, scsi1, sata1 y los mueve de forma automática.
  3. Logs detallados: Registra todo el proceso en un archivo de log (/var/log/proxmox_disk_migration.log).
  4. Automatización: Apaga la VM o el contenedor si está en ejecución, realiza la migración de discos y luego lo vuelve a iniciar.

🔧 Uso del script:

Primero.- Hacerlo ejecutable:

chmod +x /usr/local/sbin/proxmox-move-disk

Segundo.- Ejecutar el script:

  • Sin realizar el envío de correo electrónico:
proxmox-move-disk 105 local-lvm

En este caso estamos solicitando que se mueva el disco virtual del contenedor o máquina virtual con ID 105 al almacenamiento local-lvm.

  • Realizando envío de correo electrónico.
proxmox-move-disk 105 local-lvm admin@example.com

En este segundo ejemplo estamos solicitando que se mueva el disco virtual del contenedor o máquina virtual con ID 105 al almacenamiento local-lvm y que se envíe información por e-mail al correo electrónico admin@example.com

📂 Ejemplo de entrada en el log:

El archivo de log (/var/log/proxmox_disk_migration.log) tendrá un formato como el siguiente:

2025-04-09 12:30:00 - Iniciando migración de disco para VM/Contenedor con ID 105 hacia local-lvm.
2025-04-09 12:30:05 - Apagando VM 105...
2025-04-09 12:30:10 - VM 105 apagada.
2025-04-09 12:30:15 - Moviendo disco virtio0 a local-lvm...
2025-04-09 12:30:30 - ✅ Discos movidos y VM arrancada.
Be the first to comment