add script disk passthrough to ct

This commit is contained in:
MacRimi 2025-04-05 11:16:20 +02:00
parent 70b9ab37be
commit 36c926dd2f
7 changed files with 385 additions and 2125 deletions

View File

@ -1,478 +0,0 @@
#!/bin/bash
# Configuración
SCRIPT_VERSION="1.3"
LOG_FILE="/var/log/proxmox_backup_restore.log"
# Colores para salida
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
# Variable global para el modo de interfaz
INTERFACE_MODE=""
# Funciones de utilidad
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
echo -e "$1"
}
error() {
log "${RED}ERROR: $1${NC}"
if [ "$INTERFACE_MODE" = "whiptail" ]; then
whiptail --title "Error" --msgbox "$1" 8 78
else
echo -e "${RED}ERROR: $1${NC}"
fi
exit 1
}
success() {
log "${GREEN}$1${NC}"
if [ "$INTERFACE_MODE" = "whiptail" ]; then
whiptail --title "Éxito" --msgbox "$1" 8 78
else
echo -e "${GREEN}$1${NC}"
fi
}
warning() {
log "${YELLOW}ADVERTENCIA: $1${NC}"
if [ "$INTERFACE_MODE" = "whiptail" ]; then
whiptail --title "Advertencia" --msgbox "$1" 8 78
else
echo -e "${YELLOW}ADVERTENCIA: $1${NC}"
fi
}
# Función para seleccionar el modo de interfaz
select_interface_mode() {
if [ "$(tty)" = "/dev/tty1" ] || [ "$(tty)" = "/dev/console" ]; then
echo "Ejecutando en consola física. Usando interfaz de texto."
INTERFACE_MODE="echo"
elif command -v whiptail >/dev/null 2>&1; then
echo "Ejecutando en terminal remota. Usando interfaz whiptail."
INTERFACE_MODE="whiptail"
else
echo "whiptail no está disponible. Usando interfaz de texto."
INTERFACE_MODE="echo"
fi
}
# Función para mostrar el menú principal
show_main_menu() {
while true; do
if [ "$INTERFACE_MODE" = "whiptail" ]; then
CHOICE=$(whiptail --title "Proxmox Backup & Restore Tool" --menu "Seleccione una opción:" 15 60 3 \
"1" "Realizar copia de seguridad" \
"2" "Restaurar copia de seguridad" \
"3" "Salir" 3>&1 1>&2 2>&3)
else
echo "Proxmox Backup & Restore Tool"
echo "1. Realizar copia de seguridad"
echo "2. Restaurar copia de seguridad"
echo "3. Salir"
read -p "Seleccione una opción: " CHOICE
fi
case $CHOICE in
1) perform_backup ;;
2) perform_restore ;;
3) exit 0 ;;
*) echo "Opción no válida. Por favor, intente de nuevo." ;;
esac
done
}
# Función para seleccionar la ubicación de la copia de seguridad
select_backup_location() {
local options=()
local i=1
# Ubicaciones recomendadas
options+=("/root/backups/" "/var/lib/vz/dump/")
# Detectar discos USB
local usb_disks=$(lsblk -ndo NAME,TRAN,SIZE | awk '$2=="usb" {print "/dev/"$1}')
options+=($usb_disks)
# Otros discos disponibles
local other_disks=$(lsblk -ndo NAME,SIZE,FSTYPE | grep -vE "^(sd[a-z]|nvme[0-9]n[0-9])" | awk '$3!="" {print "/dev/"$1}')
options+=($other_disks)
if [ "$INTERFACE_MODE" = "whiptail" ]; then
BACKUP_LOCATION=$(whiptail --title "Seleccionar ubicación de copia de seguridad" \
--menu "Elija dónde guardar la copia de seguridad:" 20 78 10 \
$(for i in "${!options[@]}"; do echo "$i ${options[$i]}"; done) \
"C" "Introducir ruta personalizada" 3>&1 1>&2 2>&3)
else
echo "Seleccionar ubicación de copia de seguridad:"
for i in "${!options[@]}"; do
echo "$i. ${options[$i]}"
done
echo "C. Introducir ruta personalizada"
read -p "Elija dónde guardar la copia de seguridad: " BACKUP_LOCATION
fi
if [[ $BACKUP_LOCATION == "C" ]]; then
if [ "$INTERFACE_MODE" = "whiptail" ]; then
BACKUP_LOCATION=$(whiptail --inputbox "Introduzca la ruta personalizada:" 8 78 "/mnt/backup" --title "Ruta personalizada" 3>&1 1>&2 2>&3)
else
read -p "Introduzca la ruta personalizada: " BACKUP_LOCATION
fi
elif [[ $BACKUP_LOCATION =~ ^[0-9]+$ ]]; then
BACKUP_LOCATION=${options[$BACKUP_LOCATION]}
fi
echo "$BACKUP_LOCATION"
}
# Función para realizar la copia de seguridad
perform_backup() {
local BACKUP_LOCATION=$(select_backup_location)
if [ "$INTERFACE_MODE" = "whiptail" ]; then
local BACKUP_TYPE=$(whiptail --title "Tipo de copia de seguridad" --menu "Seleccione el tipo de copia de seguridad:" 15 60 2 \
"1" "Copia de seguridad total" \
"2" "Copia de seguridad personalizada" 3>&1 1>&2 2>&3)
else
echo "Tipo de copia de seguridad:"
echo "1. Copia de seguridad total"
echo "2. Copia de seguridad personalizada"
read -p "Seleccione el tipo de copia de seguridad: " BACKUP_TYPE
fi
local TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
local BACKUP_PATH="${BACKUP_LOCATION}/proxmox_backup_${TIMESTAMP}"
mkdir -p "$BACKUP_PATH" || error "No se pudo crear el directorio de copia de seguridad."
case $BACKUP_TYPE in
1) backup_total "$BACKUP_PATH" ;;
2) backup_personalizada "$BACKUP_PATH" ;;
*) error "Opción no válida." ;;
esac
# Guardar versión de Proxmox
pveversion > "$BACKUP_PATH/pve_version.txt"
# Guardar mapa de rutas de almacenamiento
pvesm status --output-format=json > "$BACKUP_PATH/storage_paths.json"
success "Copia de seguridad completada en $BACKUP_PATH"
}
# Función para realizar copia de seguridad total
backup_total() {
local BACKUP_PATH=$1
log "Iniciando copia de seguridad total..."
# Copiar configuraciones de Proxmox
cp -r /etc/pve "$BACKUP_PATH/etc_pve" || warning "Error al copiar /etc/pve"
cp -r /etc/network "$BACKUP_PATH/etc_network" || warning "Error al copiar /etc/network"
cp /etc/hostname "$BACKUP_PATH/etc_hostname" || warning "Error al copiar /etc/hostname"
cp /etc/hosts "$BACKUP_PATH/etc_hosts" || warning "Error al copiar /etc/hosts"
# Copiar logs relevantes
mkdir -p "$BACKUP_PATH/var_log"
cp /var/log/pveam.log "$BACKUP_PATH/var_log/" || warning "Error al copiar pveam.log"
cp /var/log/pvedaemon.log "$BACKUP_PATH/var_log/" || warning "Error al copiar pvedaemon.log"
# Copiar configuraciones de almacenamiento
cp /etc/pve/storage.cfg "$BACKUP_PATH/storage.cfg" || warning "Error al copiar storage.cfg"
# Copiar configuraciones de usuarios y permisos
cp /etc/pve/user.cfg "$BACKUP_PATH/user.cfg" || warning "Error al copiar user.cfg"
cp /etc/pve/groups.cfg "$BACKUP_PATH/groups.cfg" || warning "Error al copiar groups.cfg"
# Copiar configuraciones de firewall
cp -r /etc/pve/firewall "$BACKUP_PATH/firewall" || warning "Error al copiar configuraciones de firewall"
# Copiar metadatos de VMs y contenedores (sin incluir discos o snapshots)
mkdir -p "$BACKUP_PATH/vms_metadata"
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do
qm config $vmid > "$BACKUP_PATH/vms_metadata/vm_${vmid}.conf"
done
mkdir -p "$BACKUP_PATH/cts_metadata"
for ctid in $(pct list | awk '{if(NR>1) print $1}'); do
pct config $ctid > "$BACKUP_PATH/cts_metadata/ct_${ctid}.conf"
done
log "Copia de seguridad total completada."
}
# Función para realizar copia de seguridad personalizada
backup_personalizada() {
local BACKUP_PATH=$1
log "Iniciando copia de seguridad personalizada..."
local options=(
"1" "Configuración del sistema Proxmox" ON
"2" "Configuraciones de almacenamiento" ON
"3" "Configuraciones de red" ON
"4" "Usuarios y permisos" ON
"5" "Logs del sistema relevantes" OFF
"6" "Configuraciones de firewall" ON
"7" "Metadatos de VMs y contenedores" ON
)
local SELECTED_OPTIONS
if [ "$INTERFACE_MODE" = "whiptail" ]; then
SELECTED_OPTIONS=$(whiptail --title "Selección de componentes" \
--checklist "Seleccione los componentes a respaldar:" 20 78 7 \
"${options[@]}" 3>&1 1>&2 2>&3)
else
echo "Selección de componentes a respaldar:"
for ((i=0; i<${#options[@]}; i+=3)); do
echo "${options[i]}. ${options[i+1]}"
done
read -p "Ingrese los números de los componentes a respaldar (separados por espacio): " -a selections
for sel in "${selections[@]}"; do
SELECTED_OPTIONS+="$sel "
done
fi
for option in $SELECTED_OPTIONS; do
case $option in
1)
cp -r /etc/pve "$BACKUP_PATH/etc_pve" || warning "Error al copiar /etc/pve"
cp /etc/hostname "$BACKUP_PATH/etc_hostname" || warning "Error al copiar /etc/hostname"
cp /etc/hosts "$BACKUP_PATH/etc_hosts" || warning "Error al copiar /etc/hosts"
;;
2)
cp /etc/pve/storage.cfg "$BACKUP_PATH/storage.cfg" || warning "Error al copiar storage.cfg"
;;
3)
cp -r /etc/network "$BACKUP_PATH/etc_network" || warning "Error al copiar /etc/network"
;;
4)
cp /etc/pve/user.cfg "$BACKUP_PATH/user.cfg" || warning "Error al copiar user.cfg"
cp /etc/pve/groups.cfg "$BACKUP_PATH/groups.cfg" || warning "Error al copiar groups.cfg"
;;
5)
mkdir -p "$BACKUP_PATH/var_log"
cp /var/log/pveam.log "$BACKUP_PATH/var_log/" || warning "Error al copiar pveam.log"
cp /var/log/pvedaemon.log "$BACKUP_PATH/var_log/" || warning "Error al copiar pvedaemon.log"
;;
6)
cp -r /etc/pve/firewall "$BACKUP_PATH/firewall" || warning "Error al copiar configuraciones de firewall"
;;
7)
mkdir -p "$BACKUP_PATH/vms_metadata"
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do
qm config $vmid > "$BACKUP_PATH/vms_metadata/vm_${vmid}.conf"
done
mkdir -p "$BACKUP_PATH/cts_metadata"
for ctid in $(pct list | awk '{if(NR>1) print $1}'); do
pct config $ctid > "$BACKUP_PATH/cts_metadata/ct_${ctid}.conf"
done
;;
esac
done
log "Copia de seguridad personalizada completada."
}
# Función para restaurar desde una copia de seguridad
perform_restore() {
local BACKUP_LOCATION
if [ "$INTERFACE_MODE" = "whiptail" ]; then
BACKUP_LOCATION=$(whiptail --inputbox "Introduzca la ruta de la copia de seguridad:" 8 78 "/root/proxmox_backups" --title "Restauración" 3>&1 1>&2 2>&3)
else
read -p "Introduzca la ruta de la copia de seguridad: " BACKUP_LOCATION
fi
local backups=($(ls -d ${BACKUP_LOCATION}/proxmox_backup_* 2>/dev/null))
if [ ${#backups[@]} -eq 0 ]; then
error "No se encontraron copias de seguridad en $BACKUP_LOCATION"
fi
local SELECTED_BACKUP
if [ "$INTERFACE_MODE" = "whiptail" ]; then
local options=()
for i in "${!backups[@]}"; do
options+=("$i" "$(basename ${backups[$i]})")
done
SELECTED_BACKUP=$(whiptail --title "Seleccionar copia de seguridad" \
--menu "Elija la copia de seguridad a restaurar:" 20 78 10 \
"${options[@]}" 3>&1 1>&2 2>&3)
else
echo "Copias de seguridad disponibles:"
for i in "${!backups[@]}"; do
echo "$i. $(basename ${backups[$i]})"
done
read -p "Elija la copia de seguridad a restaurar: " SELECTED_BACKUP
fi
local BACKUP_PATH="${backups[$SELECTED_BACKUP]}"
# Verificar compatibilidad de versiones
if ! verify_pve_version "$BACKUP_PATH"; then
if [ "$INTERFACE_MODE" = "whiptail" ]; then
if ! whiptail --yesno "La versión de Proxmox es diferente. ¿Desea continuar con la restauración?" 8 78; then
error "Restauración cancelada debido a diferencia de versiones."
fi
else
read -p "La versión de Proxmox es diferente. ¿Desea continuar con la restauración? (s/n): " response
if [[ ! $response =~ ^[Ss]$ ]]; then
error "Restauración cancelada debido a diferencia de versiones."
fi
fi
fi
# Verificar cambios de hardware
if ! verify_hardware "$BACKUP_PATH"; then
warning "Se detectaron cambios en el hardware. Revise el informe en $BACKUP_PATH/hardware_changes.txt"
fi
# Verificar y ajustar paths de almacenamiento
if ! adjust_storage_paths "$BACKUP_PATH"; then
warning "Algunas rutas de almacenamiento han cambiado. Revise y ajuste manualmente si es necesario."
fi
# Realizar la restauración
restore_files "$BACKUP_PATH"
success "Restauración completada. Se recomienda reiniciar el sistema."
}
# Función para verificar la versión de Proxmox
verify_pve_version() {
local BACKUP_PATH=$1
local backup_version=$(cat "$BACKUP_PATH/pve_version.txt")
local current_version=$(pveversion | grep "pve-manager/")
if [ "$backup_version" != "$current_version" ]; then
warning "La versión de Proxmox actual ($current_version) es diferente de la versión del backup ($backup_version)."
return 1
fi
return 0
}
# Función para verificar cambios de hardware
verify_hardware() {
local BACKUP_PATH=$1
local current_hw=$(lshw -short)
local backup_hw_file="$BACKUP_PATH/hardware_info.txt"
if [ ! -f "$backup_hw_file" ]; then
warning "No se encontró información de hardware en la copia de seguridad."
return 1
fi
local backup_hw=$(cat "$backup_hw_file")
if [ "$current_hw" != "$backup_hw" ]; then
diff <(echo "$backup_hw") <(echo "$current_hw") > "$BACKUP_PATH/hardware_changes.txt"
return 1
fi
return 0
}
# Función para ajustar rutas de almacenamiento
adjust_storage_paths() {
local BACKUP_PATH=$1
local old_paths_file="$BACKUP_PATH/storage_paths.json"
local new_paths=$(pvesm status --output-format=json)
if [ ! -f "$old_paths_file" ]; then
warning "No se encontró información de rutas de almacenamiento en la copia de seguridad."
return 1
fi
local old_paths=$(cat "$old_paths_file")
if [ "$new_paths" != "$old_paths" ]; then
echo "Se detectaron cambios en las rutas de almacenamiento:"
diff <(echo "$old_paths") <(echo "$new_paths")
if [ "$INTERFACE_MODE" = "whiptail" ]; then
if whiptail --yesno "¿Desea ajustar automáticamente las rutas de almacenamiento?" 8 78; then
# Aquí iría la lógica para ajustar automáticamente las rutas
# Por ejemplo, actualizando los archivos de configuración relevantes
warning "Ajuste automático de rutas no implementado. Por favor, revise manualmente."
else
warning "Las rutas de almacenamiento deben ajustarse manualmente."
fi
else
read -p "¿Desea ajustar automáticamente las rutas de almacenamiento? (s/n): " response
if [[ $response =~ ^[Ss]$ ]]; then
# Aquí iría la lógica para ajustar automáticamente las rutas
warning "Ajuste automático de rutas no implementado. Por favor, revise manualmente."
else
warning "Las rutas de almacenamiento deben ajustarse manualmente."
fi
fi
return 1
fi
return 0
}
# Función para restaurar archivos
restore_files() {
local BACKUP_PATH=$1
log "Iniciando restauración de archivos..."
# Restaurar configuraciones de Proxmox
if [ -d "$BACKUP_PATH/etc_pve" ]; then
cp -r "$BACKUP_PATH/etc_pve"/* /etc/pve/ || warning "Error al restaurar /etc/pve"
fi
if [ -d "$BACKUP_PATH/etc_network" ]; then
cp -r "$BACKUP_PATH/etc_network"/* /etc/network/ || warning "Error al restaurar /etc/network"
fi
if [ -f "$BACKUP_PATH/etc_hostname" ]; then
cp "$BACKUP_PATH/etc_hostname" /etc/hostname || warning "Error al restaurar /etc/hostname"
fi
if [ -f "$BACKUP_PATH/etc_hosts" ]; then
cp "$BACKUP_PATH/etc_hosts" /etc/hosts || warning "Error al restaurar /etc/hosts"
fi
# Restaurar logs
if [ -d "$BACKUP_PATH/var_log" ]; then
cp "$BACKUP_PATH/var_log"/* /var/log/ || warning "Error al restaurar logs"
fi
# Restaurar configuraciones de almacenamiento
if [ -f "$BACKUP_PATH/storage.cfg" ]; then
cp "$BACKUP_PATH/storage.cfg" /etc/pve/storage.cfg || warning "Error al restaurar storage.cfg"
fi
# Restaurar configuraciones de usuarios y permisos
if [ -f "$BACKUP_PATH/user.cfg" ]; then
cp "$BACKUP_PATH/user.cfg" /etc/pve/user.cfg || warning "Error al restaurar user.cfg"
fi
if [ -f "$BACKUP_PATH/groups.cfg" ]; then
cp "$BACKUP_PATH/groups.cfg" /etc/pve/groups.cfg || warning "Error al restaurar groups.cfg"
fi
# Restaurar configuraciones de firewall
if [ -d "$BACKUP_PATH/firewall" ]; then
cp -r "$BACKUP_PATH/firewall"/* /etc/pve/firewall/ || warning "Error al restaurar configuraciones de firewall"
fi
# Restaurar metadatos de VMs y contenedores
if [ -d "$BACKUP_PATH/vms_metadata" ]; then
for conf in "$BACKUP_PATH/vms_metadata"/*.conf; do
vmid=$(basename "$conf" .conf | cut -d'_' -f2)
qm importconfig $vmid "$conf" || warning "Error al restaurar configuración de VM $vmid"
done
fi
if [ -d "$BACKUP_PATH/cts_metadata" ]; then
for conf in "$BACKUP_PATH/cts_metadata"/*.conf; do
ctid=$(basename "$conf" .conf | cut -d'_' -f2)
pct importconfig $ctid "$conf" || warning "Error al restaurar configuración de CT $ctid"
done
fi
log "Restauración de archivos completada."
}
# Iniciar el script
select_interface_mode
show_main_menu

View File

@ -1,100 +0,0 @@
#!/bin/bash
DUMP_DIR="/var/lib/vz/dump"
STORAGE_CFG="/etc/pve/storage.cfg"
# Función para realizar copia de seguridad del archivo storage.cfg
backup_storage_cfg() {
BACKUP_FILE="${DUMP_DIR}/storage.cfg_$(date +%Y%m%d%H%M%S).bak"
cp "$STORAGE_CFG" "$BACKUP_FILE"
whiptail --title "Copia de Seguridad" --msgbox "Se ha creado una copia de seguridad en: $BACKUP_FILE" 8 40
}
# Función para comprobar y reparar el archivo storage.cfg
reparar_storage_cfg() {
whiptail --title "Comprobación de Almacenamientos" --msgbox "Comprobando consistencia de los volúmenes de almacenamiento..." 8 40
VG_LIST=$(vgs --noheadings -o vg_name)
while read -r LINE; do
if [[ "$LINE" =~ vgname ]]; then
VG_NAME=$(echo "$LINE" | awk '{print $NF}')
if ! echo "$VG_LIST" | grep -q "$VG_NAME"; then
echo "El volumen $VG_NAME no existe, eliminando entrada..."
sed -i "/vgname $VG_NAME/,/nodes/d" "$STORAGE_CFG"
fi
fi
done < "$STORAGE_CFG"
whiptail --title "Reparación Completada" --msgbox "La comprobación de consistencia ha finalizado. Se eliminaron las entradas no válidas." 8 40
}
# Función para restaurar copia de seguridad del archivo storage.cfg
restaurar_backup() {
BACKUP_FILE=$(whiptail --title "Seleccionar Copia de Seguridad" --menu "Selecciona la copia de seguridad a restaurar:" 15 60 8 $(ls "$DUMP_DIR"/storage.cfg_*.bak 2>/dev/null) 3>&1 1>&2 2>&3)
if [ -z "$BACKUP_FILE" ]; then
whiptail --title "Error" --msgbox "No se seleccionó ninguna copia de seguridad." 8 40
exit 1
fi
cp "$BACKUP_FILE" "$STORAGE_CFG"
whiptail --title "Restauración Completada" --msgbox "Se ha restaurado el archivo storage.cfg desde la copia de seguridad: $BACKUP_FILE" 8 40
reparar_storage_cfg
}
# Función para reconectar los grupos de volúmenes
reconectar_volumenes() {
whiptail --title "Reconectar discos en Proxmox" --msgbox "Este proceso activará los volúmenes LVM y LVM-thin en su sistema." 12 60
VG_LIST=$(vgscan --ignorelockingfailure --reportformat json | jq -r '.report[0].vg[].vg_name')
if [ -z "$VG_LIST" ]; then
whiptail --title "Error" --msgbox "No se detectaron grupos de volúmenes LVM en el sistema." 8 40
exit 1
fi
VG_SELECCIONADOS=$(whiptail --title "Seleccionar Grupos de Volúmenes" --checklist "Selecciona los grupos de volúmenes que deseas activar:" 20 60 10 $(for vg in $VG_LIST; do echo "$vg OFF"; done) 3>&1 1>&2 2>&3)
if [ -z "$VG_SELECCIONADOS" ]; then
whiptail --title "Error" --msgbox "No se seleccionó ningún grupo de volúmenes." 8 40
exit 1
fi
for VG in $VG_SELECCIONADOS; do
VG=$(echo "$VG" | tr -d '"')
vgchange -ay "$VG"
done
whiptail --title "Volúmenes Activados" --msgbox "Los grupos de volúmenes seleccionados se activaron correctamente." 8 40
whiptail --title "Escanear VM" --infobox "Rescaneando las imágenes de disco y volúmenes..." 8 40
qm rescan
whiptail --title "Finalizado" --msgbox "Los volúmenes y las imágenes de disco fueron reconocidos y están disponibles para usar en Proxmox." 8 40
}
# Menú principal
OPTION=$(whiptail --title "Gestor de Almacenamiento Proxmox" --menu "Selecciona una opción:" 15 60 4 \
"1" "Realizar copia de seguridad del archivo storage.cfg" \
"2" "Restaurar copia de seguridad y comprobar consistencia" \
"3" "Reparar archivo storage.cfg si se han cambiado discos" \
"4" "Reconectar grupos de volúmenes LVM/LVM-thin" 3>&1 1>&2 2>&3)
case $OPTION in
1)
backup_storage_cfg
;;
2)
restaurar_backup
;;
3)
reparar_storage_cfg
;;
4)
reconectar_volumenes
;;
*)
exit 0
;;
esac

View File

@ -0,0 +1,385 @@
#!/bin/bash
# ==========================================================
# ProxMenu CT - A menu-driven script for Proxmox CT management
# ==========================================================
# Based on ProxMenu by MacRimi
# Modified for Proxmox Containers
# ==========================================================
# Description:
# This script allows users to assign physical disks to existing
# Proxmox containers (CTs) through an interactive menu.
# - Detects the system disk and excludes it from selection.
# - Lists all available CTs for the user to choose from.
# - Identifies and displays unassigned physical disks.
# - Allows the user to select multiple disks and attach them to a CT.
# - Configures the selected disks for the CT and verifies the assignment.
# ==========================================================
# Configuration ============================================
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
BASE_DIR="/usr/local/share/proxmenux"
UTILS_FILE="$BASE_DIR/utils.sh"
VENV_PATH="/opt/googletrans-env"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
load_language
initialize_cache
# ==========================================================
get_disk_info() {
local disk=$1
MODEL=$(lsblk -dn -o MODEL "$disk" | xargs)
SIZE=$(lsblk -dn -o SIZE "$disk" | xargs)
echo "$MODEL" "$SIZE"
}
CT_LIST=$(pct list | awk 'NR>1 {print $1, $3}')
if [ -z "$CT_LIST" ]; then
whiptail --title "$(translate "Error")" --msgbox "$(translate "No CTs available in the system.")" 8 40
exit 1
fi
CTID=$(whiptail --title "$(translate "Select CT")" --menu "$(translate "Select the CT to which you want to add disks:")" 15 60 8 $CT_LIST 3>&1 1>&2 2>&3)
if [ -z "$CTID" ]; then
whiptail --title "$(translate "Error")" --msgbox "$(translate "No CT was selected.")" 8 40
exit 1
fi
CTID=$(echo "$CTID" | tr -d '"')
msg_ok "$(translate "CT selected successfully.")"
CT_STATUS=$(pct status "$CTID" | awk '{print $2}')
if [ "$CT_STATUS" == "running" ]; then
whiptail --title "$(translate "Warning")" --msgbox "$(translate "The CT is powered on. Turn it off before adding disks.")" 12 60
exit 1
fi
##########################################
msg_info "$(translate "Detecting available disks...")"
USED_DISKS=$(lsblk -n -o PKNAME,TYPE | grep 'lvm' | awk '{print "/dev/" $1}')
MOUNTED_DISKS=$(lsblk -ln -o NAME,MOUNTPOINT | awk '$2!="" {print "/dev/" $1}')
ZFS_DISKS=""
ZFS_RAW=$(zpool list -v -H 2>/dev/null | awk '{print $1}' | grep -v '^NAME$' | grep -v '^-' | grep -v '^mirror')
for entry in $ZFS_RAW; do
path=""
if [[ "$entry" == wwn-* || "$entry" == ata-* ]]; then
if [ -e "/dev/disk/by-id/$entry" ]; then
path=$(readlink -f "/dev/disk/by-id/$entry")
fi
elif [[ "$entry" == /dev/* ]]; then
path="$entry"
fi
if [ -n "$path" ]; then
base_disk=$(lsblk -no PKNAME "$path" 2>/dev/null)
if [ -n "$base_disk" ]; then
ZFS_DISKS+="/dev/$base_disk"$'\n'
fi
fi
done
ZFS_DISKS=$(echo "$ZFS_DISKS" | sort -u)
is_disk_in_use() {
local disk="$1"
while read -r part fstype; do
case "$fstype" in
zfs_member|linux_raid_member)
return 0 ;;
esac
if echo "$MOUNTED_DISKS" | grep -q "/dev/$part"; then
return 0
fi
done < <(lsblk -ln -o NAME,FSTYPE "$disk" | tail -n +2)
if echo "$USED_DISKS" | grep -q "$disk" || echo "$ZFS_DISKS" | grep -q "$disk"; then
return 0
fi
return 1
}
FREE_DISKS=()
LVM_DEVICES=$(pvs --noheadings -o pv_name | xargs -n1 readlink -f | sort -u)
RAID_ACTIVE=$(grep -Po 'md\d+\s*:\s*active\s+raid[0-9]+' /proc/mdstat | awk '{print $1}' | sort -u)
while read -r DISK; do
[[ "$DISK" =~ /dev/zd ]] && continue
INFO=($(get_disk_info "$DISK"))
MODEL="${INFO[@]::${#INFO[@]}-1}"
SIZE="${INFO[-1]}"
LABEL=""
SHOW_DISK=true
IS_MOUNTED=false
IS_RAID=false
IS_ZFS=false
IS_LVM=false
while read -r part fstype; do
[[ "$fstype" == "zfs_member" ]] && IS_ZFS=true
[[ "$fstype" == "linux_raid_member" ]] && IS_RAID=true
[[ "$fstype" == "LVM2_member" ]] && IS_LVM=true
if grep -q "/dev/$part" <<< "$MOUNTED_DISKS"; then
IS_MOUNTED=true
fi
done < <(lsblk -ln -o NAME,FSTYPE "$DISK" | tail -n +2)
REAL_PATH=$(readlink -f "$DISK")
if echo "$LVM_DEVICES" | grep -qFx "$REAL_PATH"; then
IS_MOUNTED=true
fi
if $IS_RAID && grep -q "$DISK" <<< "$(cat /proc/mdstat)"; then
if grep -q "active raid" /proc/mdstat; then
SHOW_DISK=false
fi
fi
if $IS_ZFS; then
SHOW_DISK=false
fi
if $IS_MOUNTED; then
SHOW_DISK=false
fi
if pct config "$CTID" | grep -q "$DISK"; then
SHOW_DISK=false
fi
if $SHOW_DISK; then
[[ "$IS_RAID" == true ]] && LABEL+=" ⚠ with partitions"
[[ "$IS_LVM" == true ]] && LABEL+=" ⚠ LVM"
[[ "$IS_ZFS" == true ]] && LABEL+=" ⚠ ZFS"
DESCRIPTION=$(printf "%-30s %10s%s" "$MODEL" "$SIZE" "$LABEL")
FREE_DISKS+=("$DISK" "$DESCRIPTION" "OFF")
fi
done < <(lsblk -dn -e 7,11 -o PATH)
if [ "${#FREE_DISKS[@]}" -eq 0 ]; then
cleanup
whiptail --title "$(translate "Error")" --msgbox "$(translate "No disks available for this CT.")" 8 40
clear
exit 1
fi
msg_ok "$(translate "Available disks detected.")"
######################################################
MAX_WIDTH=$(printf "%s\n" "${FREE_DISKS[@]}" | awk '{print length}' | sort -nr | head -n1)
TOTAL_WIDTH=$((MAX_WIDTH + 20))
if [ $TOTAL_WIDTH -lt 70 ]; then
TOTAL_WIDTH=70
fi
SELECTED=$(whiptail --title "$(translate "Select Disks")" --radiolist \
"$(translate "Select the disks you want to add:")" 20 $TOTAL_WIDTH 10 "${FREE_DISKS[@]}" 3>&1 1>&2 2>&3)
if [ -z "$SELECTED" ]; then
whiptail --title "$(translate "Error")" --msgbox "$(translate "No disks were selected.")" 10 $TOTAL_WIDTH
clear
exit 1
fi
msg_ok "$(translate "Disks selected successfully.")"
DISKS_ADDED=0
ERROR_MESSAGES=""
SUCCESS_MESSAGES=""
msg_info "$(translate "Processing selected disks...")"
for DISK in $SELECTED; do
DISK=$(echo "$DISK" | tr -d '"')
DISK_INFO=$(get_disk_info "$DISK")
ASSIGNED_TO=""
RUNNING_CTS=""
while read -r CT_ID CT_NAME; do
if [[ "$CT_ID" =~ ^[0-9]+$ ]] && pct config "$CT_ID" | grep -q "$DISK"; then
ASSIGNED_TO+="$CT_ID $CT_NAME\n"
CT_STATUS=$(pct status "$CT_ID" | awk '{print $2}')
if [ "$CT_STATUS" == "running" ]; then
RUNNING_CTS+="$CT_ID $CT_NAME\n"
fi
fi
done < <(pct list | awk 'NR>1 {print $1, $3}')
if [ -n "$RUNNING_CTS" ]; then
ERROR_MESSAGES+="$(translate "The disk") $DISK_INFO $(translate "is in use by the following running CT(s):")\\n$RUNNING_CTS\\n\\n"
continue
fi
if [ -n "$ASSIGNED_TO" ]; then
cleanup
whiptail --title "$(translate "Disk Already Assigned")" --yesno "$(translate "The disk") $DISK_INFO $(translate "is already assigned to the following CT(s):")\\n$ASSIGNED_TO\\n\\n$(translate "Do you want to continue anyway?")" 15 70
if [ $? -ne 0 ]; then
sleep 1
exec "$0"
fi
fi
cleanup
MOUNT_POINT=$(whiptail --title "$(translate "Mount Point")" --inputbox "$(translate "Enter the mount point for the disk (e.g., /mnt/disk_passthrough):")" 10 60 "/mnt/disk_passthrough" 3>&1 1>&2 2>&3)
if [ -z "$MOUNT_POINT" ]; then
whiptail --title "$(translate "Error")" --msgbox "$(translate "No mount point was specified.")" 8 40
continue
fi
msg_ok "$(translate "Mount point specified: $MOUNT_POINT")"
whiptail --title "$(translate "Format Required")" --msgbox "$(translate "To use the disk with a mount point, it needs to be formatted.")" 8 70
FORMAT_TYPE=$(whiptail --title "$(translate "Select Format Type")" --menu "$(translate "Select the filesystem type for") $DISK_INFO:" 15 60 6 \
"ext4" "$(translate "Extended Filesystem 4 (recommended)")" \
"xfs" "$(translate "XFS Filesystem")" \
"btrfs" "$(translate "Btrfs Filesystem")" 3>&1 1>&2 2>&3)
if [ -z "$FORMAT_TYPE" ]; then
whiptail --title "$(translate "Format Cancelled")" --msgbox "$(translate "Format operation cancelled. The disk will not be added.")" 8 60
continue
fi
whiptail --title "$(translate "WARNING")" --yesno "$(translate "WARNING: This operation will FORMAT the disk") $DISK_INFO $(translate "with") $FORMAT_TYPE.\\n\\n$(translate "ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!")\\n\\n$(translate "Are you sure you want to continue?")" 15 70
if [ $? -ne 0 ]; then
whiptail --title "$(translate "Format Cancelled")" --msgbox "$(translate "Format operation cancelled. The disk will not be added.")" 8 60
continue
fi
if lsblk "$DISK" | grep -q "raid" || grep -q "${DISK##*/}" /proc/mdstat; then
whiptail --title "$(translate "RAID Detected")" --msgbox "$(translate "The disk") $DISK_INFO $(translate "is part of a RAID array and cannot be added.")\\n\\n$(translate "To use this disk, you must first stop the RAID array with:")\\n\\nmdadm --stop /dev/mdX\\nmdadm --zero-superblock $DISK\\n\\n$(translate "After removing the RAID metadata, run this script again to add the disk.")" 15 70
continue
fi
MOUNTED_PARTITIONS=$(lsblk -n -o NAME,MOUNTPOINT "$DISK" | awk '$2 != "" {print $1}')
if [ -n "$MOUNTED_PARTITIONS" ]; then
UNMOUNT_FAILED=false
if mount | grep -q "$DISK "; then
umount -f "$DISK" 2>/dev/null
if [ $? -ne 0 ]; then
umount -f -l "$DISK" 2>/dev/null
if [ $? -ne 0 ]; then
UNMOUNT_FAILED=true
fi
fi
fi
for PART in $MOUNTED_PARTITIONS; do
if [[ "$PART" == "${DISK##*/}"* ]]; then
PART_PATH="/dev/$PART"
else
PART_PATH="/dev/$PART"
fi
umount -f "$PART_PATH" 2>/dev/null
if [ $? -ne 0 ]; then
umount -f -l "$PART_PATH" 2>/dev/null
if [ $? -ne 0 ]; then
UNMOUNT_FAILED=true
fi
fi
done
if [ "$UNMOUNT_FAILED" = true ]; then
whiptail --title "$(translate "Unmount Failed")" --msgbox "$(translate "Failed to unmount") $DISK $(translate "or its partitions. Cannot format.")\\n\\n$(translate "The disk may be in use by the system or other processes.")" 12 70
continue
fi
fi
echo -e "$(translate "Removing partition table to ensure clean formatting...")"
dd if=/dev/zero of="$DISK" bs=512 count=1 conv=notrunc
partprobe "$DISK"
sleep 2
echo -e "$(translate "Formatting disk") $DISK_INFO $(translate "with") $FORMAT_TYPE..."
case "$FORMAT_TYPE" in
"ext4")
mkfs.ext4 -F "$DISK" ;;
"xfs")
mkfs.xfs -f "$DISK" ;;
"btrfs")
mkfs.btrfs -f "$DISK" ;;
esac
if [ $? -ne 0 ]; then
whiptail --title "$(translate "Format Failed")" --msgbox "$(translate "Failed to format disk") $DISK_INFO $(translate "with") $FORMAT_TYPE.\\n\\n$(translate "The disk may be in use by the system or have hardware issues.")" 12 70
continue
else
msg_ok "$(translate "Disk") $DISK_INFO $(translate "successfully formatted with") $FORMAT_TYPE."
partprobe "$DISK"
sleep 2
fi
INDEX=0
while pct config "$CTID" | grep -q "mp${INDEX}:"; do
((INDEX++))
done
##############################################################################
RESULT=$(pct set "$CTID" -mp${INDEX} "$DISK,mp=$MOUNT_POINT,backup=0" 2>&1)
##############################################################################
if [ $? -eq 0 ]; then
MESSAGE="$(translate "The disk") $DISK_INFO $(translate "has been successfully added to CT") $CTID $(translate "as a mount point at") $MOUNT_POINT."
if [ -n "$ASSIGNED_TO" ]; then
MESSAGE+="\\n\\n$(translate "WARNING: This disk is also assigned to the following CT(s):")\\n$ASSIGNED_TO"
MESSAGE+="\\n$(translate "Make sure not to start CTs that share this disk at the same time to avoid data corruption.")"
fi
SUCCESS_MESSAGES+="$MESSAGE\\n\\n"
((DISKS_ADDED++))
else
ERROR_MESSAGES+="$(translate "Could not add disk") $DISK_INFO $(translate "to CT") $CTID.\\n$(translate "Error:") $RESULT\\n\\n"
fi
done
msg_ok "$(translate "Disk processing completed.")"
if [ -n "$SUCCESS_MESSAGES" ]; then
MSG_LINES=$(echo "$SUCCESS_MESSAGES" | wc -l)
whiptail --title "$(translate "Successful Operations")" --msgbox "$SUCCESS_MESSAGES" 16 70
fi
if [ -n "$ERROR_MESSAGES" ]; then
whiptail --title "$(translate "Warnings and Errors")" --msgbox "$ERROR_MESSAGES" 16 70
fi
exit 0

View File

@ -1,366 +0,0 @@
#!/bin/bash
# Variables globales
CHANGES_MADE=0 # Inicializar cambios para verificar si es necesario reiniciar el contenedor
NEED_REBOOT=0 # Controla si se requiere reinicio completo del servidor
# Colores para salida
YW="\033[33m"
GN="\033[1;92m"
RD="\033[01;31m"
CL="\033[m"
# Funciones auxiliares
log() {
echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1"
}
msg_info() {
echo -ne " ${YW}[INFO] $1...${CL}"
}
msg_ok() {
echo -e " ${GN}[OK] $1${CL}"
}
msg_error() {
echo -e " ${RD}[ERROR] $1${CL}"
}
# Validar que el contenedor seleccionado es válido
validate_container_id() {
if [ -z "$CONTAINER_ID" ]; then
msg_error "ID del contenedor no definido. Asegúrate de seleccionar un contenedor primero."
exit 1
fi
}
# Verificar la versión de Proxmox
validate_pve_version() {
if ! pveversion | grep -Eq "pve-manager/(8\\.[0-9]+)"; then
msg_error "Esta versión de Proxmox no es compatible. Se requiere Proxmox VE 8.0 o superior."
exit 1
fi
msg_ok "Versión de Proxmox compatible."
}
# Función para reinicio
restart_prompt() {
if (whiptail --title "Reinicio requerido" --yesno "La instalación requiere un reinicio del servidor para que los cambios sean efectivos. ¿Deseas reiniciar ahora?" 8 58); then
msg_info "Reiniciando el servidor..."
reboot
else
msg_info "No se realizó el reinicio. Por favor, reinicia manualmente más tarde para aplicar los cambios."
fi
}
# Reinicio del servidor al final
final_restart_prompt() {
if [ "$NEED_REBOOT" -eq 1 ]; then
msg_info "Se recomienda reiniciar el servidor para aplicar los cambios correctamente."
restart_prompt
fi
}
# Selección del contenedor LXC
select_container() {
CONTAINERS=$(pct list | awk 'NR>1 {print $1, $3}' | xargs -n2)
if [ -z "$CONTAINERS" ]; then
msg_error "No hay contenedores disponibles en Proxmox."
exit 1
fi
CONTAINER_ID=$(whiptail --title "Seleccionar Contenedor" \
--menu "Selecciona el contenedor LXC:" 15 60 5 $CONTAINERS 3>&1 1>&2 2>&3)
if [ -z "$CONTAINER_ID" ]; then
msg_error "No se seleccionó ningún contenedor. Saliendo."
exit 1
fi
if ! pct list | awk 'NR>1 {print $1}' | grep -qw "$CONTAINER_ID"; then
msg_error "El contenedor con ID $CONTAINER_ID no existe. Saliendo."
exit 1
fi
msg_ok "Contenedor seleccionado: $CONTAINER_ID"
}
# Validar y cambiar a privilegiado si es necesario
ensure_privileged_container() {
validate_container_id
CONFIG_FILE="/etc/pve/lxc/${CONTAINER_ID}.conf"
if [ ! -f "$CONFIG_FILE" ]; then
msg_error "Archivo de configuración del contenedor $CONTAINER_ID no encontrado."
exit 1
fi
if grep -q "^unprivileged: 1" "$CONFIG_FILE"; then
msg_info "El contenedor es no privilegiado. Cambiando a privilegiado..."
sed -i "s/^unprivileged: 1/unprivileged: 0/" "$CONFIG_FILE"
STORAGE_TYPE=$(pct config "$CONTAINER_ID" | grep "^rootfs:" | awk -F, '{print $2}' | cut -d'=' -f2)
if [[ "$STORAGE_TYPE" == "dir" ]]; then
STORAGE_PATH=$(pct config "$CONTAINER_ID" | grep "^rootfs:" | awk '{print $2}' | cut -d',' -f1)
chown -R root:root "$STORAGE_PATH"
fi
msg_ok "Contenedor cambiado a privilegiado."
else
msg_ok "El contenedor ya es privilegiado."
fi
}
# Verificar y configurar repositorios en el host
verify_and_add_repos() {
msg_info "Verificando y configurando repositorios necesarios en el host..."
if ! grep -q "pve-no-subscription" /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null; then
echo "deb http://download.proxmox.com/debian/pve $(lsb_release -sc) pve-no-subscription" | tee /etc/apt/sources.list.d/pve-no-subscription.list
msg_ok "Repositorio pve-no-subscription añadido."
else
msg_ok "Repositorio pve-no-subscription ya configurado."
fi
if ! grep -q "non-free-firmware" /etc/apt/sources.list; then
echo "deb http://deb.debian.org/debian $(lsb_release -sc) main contrib non-free-firmware
deb http://deb.debian.org/debian $(lsb_release -sc)-updates main contrib non-free-firmware
deb http://security.debian.org/debian-security $(lsb_release -sc)-security main contrib non-free-firmware" | tee -a /etc/apt/sources.list
msg_ok "Repositorios non-free-firmware añadidos."
else
msg_ok "Repositorios non-free-firmware ya configurados."
fi
apt-get update
# apt-get update &>/dev/null
msg_ok "Repositorios verificados y actualizados."
}
# Configurar Coral TPU en el contenedor
configure_lxc_for_coral() {
ensure_privileged_container
CONFIG_FILE="/etc/pve/lxc/${CONTAINER_ID}.conf"
# Verificar y agregar configuraciones solo si no existen
if ! grep -Pq "^lxc.cgroup2.devices.allow: c 189:\* rwm # Coral USB$" "$CONFIG_FILE"; then
echo "lxc.cgroup2.devices.allow: c 189:* rwm # Coral USB" >> "$CONFIG_FILE"
fi
if ! grep -Pq "^lxc.mount.entry: /dev/bus/usb dev/bus/usb none bind,optional,create=dir$" "$CONFIG_FILE"; then
echo "lxc.mount.entry: /dev/bus/usb dev/bus/usb none bind,optional,create=dir" >> "$CONFIG_FILE"
fi
if ! grep -Pq "^lxc.mount.entry: /dev/apex_0 dev/apex_0 none bind,optional,create=file$" "$CONFIG_FILE"; then
echo "lxc.mount.entry: /dev/apex_0 dev/apex_0 none bind,optional,create=file" >> "$CONFIG_FILE"
fi
msg_ok "Configuración de Coral TPU (USB y M.2) añadida al contenedor $CONTAINER_ID."
}
# Configurar iGPU en el contenedor
configure_lxc_for_igpu() {
ensure_privileged_container
CONFIG_FILE="/etc/pve/lxc/${CONTAINER_ID}.conf"
# Verificar y agregar configuraciones solo si no existen
if ! grep -q "features: nesting=1" "$CONFIG_FILE"; then
echo "features: nesting=1" >> "$CONFIG_FILE"
fi
if ! grep -q "c 226:0 rwm" "$CONFIG_FILE"; then
echo "lxc.cgroup2.devices.allow: c 226:0 rwm # iGPU" >> "$CONFIG_FILE"
echo "lxc.cgroup2.devices.allow: c 226:128 rwm # iGPU" >> "$CONFIG_FILE"
echo "lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir" >> "$CONFIG_FILE"
echo "lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file" >> "$CONFIG_FILE"
fi
if ! grep -q "c 29:0 rwm # Framebuffer" "$CONFIG_FILE"; then
echo "lxc.cgroup2.devices.allow: c 29:0 rwm # Framebuffer" >> "$CONFIG_FILE"
fi
if ! grep -q "lxc.mount.entry: /dev/fb0" "$CONFIG_FILE"; then
echo "lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file" >> "$CONFIG_FILE"
fi
msg_ok "Configuración de iGPU añadida al contenedor $CONTAINER_ID."
}
# Instalar controladores iGPU en el contenedor
install_igpu_in_container() {
msg_info "Instalando controladores de iGPU dentro del contenedor..."
pct start "$CONTAINER_ID"
pct exec "$CONTAINER_ID" -- bash -c "
apt-get update && \
apt-get install -y va-driver-all ocl-icd-libopencl1 intel-opencl-icd vainfo intel-gpu-tools && \
chgrp video /dev/dri && chmod 755 /dev/dri && \
adduser root video && adduser root render
"
msg_ok "Controladores de iGPU instalados dentro del contenedor."
}
##########################################################
# Instalar TPU en host y verificación.
NEED_REBOOT=0
install_coral_host() {
FORCE_REINSTALL=$1
# Verificar si el controlador ya está instalado
if [ "$FORCE_REINSTALL" != "--force" ]; then
msg_info "Verificando si los controladores de Coral TPU ya están instalados..."
if dpkg -l | grep -qw gasket-dkms; then
msg_ok "Los controladores de Coral TPU ya están instalados."
return 0
fi
fi
msg_info "Instalando controladores de Coral TPU en el host..."
verify_and_add_repos
apt-get install -y git devscripts dh-dkms dkms pve-headers-$(uname -r)
# Clonar la rama predeterminada del repositorio
cd /tmp
rm -rf gasket-driver
msg_info "Clonando la rama predeterminada del repositorio de Google Coral..."
git clone https://github.com/google/gasket-driver.git
if [ $? -ne 0 ]; then
msg_error "No se pudo clonar el repositorio."
exit 1
fi
cd gasket-driver/
# Construir e instalar el paquete .deb
debuild -us -uc -tc -b
if [ $? -ne 0 ]; then
msg_error "Error al construir los paquetes del controlador."
exit 1
fi
dpkg -i ../gasket-dkms_*.deb
if [ $? -ne 0 ]; then
msg_error "Error al instalar los paquetes del controlador."
exit 1
fi
msg_ok "Controladores de Coral TPU instalados en el host desde la rama predeterminada."
NEED_REBOOT=1 # Marcar que se requiere reinicio completo del servidor
}
################################################
# Instalar controladores Coral TPU en el contenedor
install_coral_in_container() {
msg_info "Detectando dispositivos Coral TPU dentro del contenedor..."
CORAL_M2=$(lspci | grep -i "Global Unichip")
if [[ -n "$CORAL_M2" ]]; then
DRIVER_OPTION=$(whiptail --title "Seleccionar versión de controladores" \
--menu "Elige la versión de controladores para Coral M.2:\n\nPrecaución: El modo máximo genera más calor." 15 60 2 \
1 "libedgetpu1-std (rendimiento estándar)" \
2 "libedgetpu1-max (máximo rendimiento)" 3>&1 1>&2 2>&3)
case "$DRIVER_OPTION" in
1) DRIVER_PACKAGE="libedgetpu1-std" ;;
2) DRIVER_PACKAGE="libedgetpu1-max" ;;
*) DRIVER_PACKAGE="libedgetpu1-std" ;;
esac
else
DRIVER_PACKAGE="libedgetpu1-std"
fi
pct start "$CONTAINER_ID"
pct exec "$CONTAINER_ID" -- bash -c "
apt-get update && \
apt-get install -y gnupg python3 python3-pip python3-venv && \
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/coral-edgetpu.gpg && \
echo 'deb [signed-by=/usr/share/keyrings/coral-edgetpu.gpg] https://packages.cloud.google.com/apt coral-edgetpu-stable main' | tee /etc/apt/sources.list.d/coral-edgetpu.list && \
apt-get update && \
apt-get install -y $DRIVER_PACKAGE
"
msg_ok "Controladores de Coral TPU instalados dentro del contenedor."
}
# Menú principal
main_menu() {
OPTIONS=(
1 "Añadir aceleración gráfica HW iGPU"
2 "Añadir Coral TPU + HW iGPU"
)
OPTION=$(whiptail --title "Menú Principal" --menu "Selecciona los recursos a añadir a un LXC:" 15 60 2 "${OPTIONS[@]}" 3>&1 1>&2 2>&3)
case "$OPTION" in
1)
# Configuración solo para iGPU
configure_lxc_for_igpu
install_igpu_in_container
if pct status "$CONTAINER_ID" | grep -q "running"; then
pct restart "$CONTAINER_ID"
else
pct start "$CONTAINER_ID"
fi
msg_ok "El contenedor $CONTAINER_ID ha sido reiniciado para aplicar los cambios de iGPU."
;;
2)
if dpkg -l | grep -qw gasket-dkms; then
msg_info "Controladores de Coral ya están instalados en el host."
if (whiptail --title "Reinstalar controladores" --yesno "¿Quieres reinstalar los controladores de Coral en el servidor?\n(Esto solo es necesario en caso de error)" 10 60); then
msg_info "Reinstalando los controladores de Coral en el host..."
install_coral_host --force
configure_lxc_for_coral && CHANGES_MADE=1
install_coral_in_container && CHANGES_MADE=1
configure_lxc_for_igpu && CHANGES_MADE=1
install_igpu_in_container && CHANGES_MADE=1
msg_info "Reiniciando el servicio udev para aplicar cambios..."
systemctl restart udev
msg_ok "El servicio udev ha sido reiniciado con éxito. No se requiere reinicio completo del servidor."
else
configure_lxc_for_coral && CHANGES_MADE=1
install_coral_in_container && CHANGES_MADE=1
configure_lxc_for_igpu && CHANGES_MADE=1
install_igpu_in_container && CHANGES_MADE=1
if [ "$CHANGES_MADE" -eq 1 ]; then
if pct status "$CONTAINER_ID" | grep -q "running"; then
pct restart "$CONTAINER_ID"
else
pct start "$CONTAINER_ID"
fi
msg_ok "El contenedor $CONTAINER_ID ha sido reiniciado para aplicar los cambios de Coral TPU."
fi
fi
else
msg_info "Instalando controladores de Coral por primera vez en el host..."
install_coral_host
configure_lxc_for_coral && CHANGES_MADE=1
install_coral_in_container && CHANGES_MADE=1
configure_lxc_for_igpu && CHANGES_MADE=1
install_igpu_in_container && CHANGES_MADE=1
if pct status "$CONTAINER_ID" | grep -q "running"; then
pct restart "$CONTAINER_ID"
else
pct start "$CONTAINER_ID"
fi
fi
;;
*)
msg_error "Opción no válida. Saliendo."
exit 1
;;
esac
msg_ok "Configuración completada."
}
# Solicitar reinicio al final si es necesario
final_restart_prompt() {
if [ "$NEED_REBOOT" -eq 1 ]; then
msg_info "Se recomienda reiniciar el servidor para aplicar los cambios correctamente."
restart_prompt
fi
}
# Iniciar
validate_pve_version
select_container
main_menu
final_restart_prompt

View File

@ -1,36 +0,0 @@
#!/bin/bash
# Mensaje inicial
whiptail --title "Reconectar discos en Proxmox" --msgbox "Este script te ayudará a reconectar los volúmenes LVM y LVM-thin en tu instalación de Proxmox recién restaurada." 12 60
# 1. Detectar grupos de volúmenes
VG_LIST=$(vgscan --ignorelockingfailure --reportformat json | jq -r '.report[0].vg[].vg_name')
if [ -z "$VG_LIST" ]; then
whiptail --title "Error" --msgbox "No se detectaron grupos de volúmenes LVM en el sistema." 8 40
exit 1
fi
# 2. Seleccionar grupo de volúmenes a activar
VG_SELECCIONADOS=$(whiptail --title "Seleccionar Grupos de Volúmenes" --checklist "Selecciona los grupos de volúmenes que deseas activar:" 20 60 10 $(for vg in $VG_LIST; do echo "$vg OFF"; done) 3>&1 1>&2 2>&3)
if [ -z "$VG_SELECCIONADOS" ]; then
whiptail --title "Error" --msgbox "No se seleccionó ningún grupo de volúmenes." 8 40
exit 1
fi
# 3. Activar los grupos de volúmenes seleccionados
for VG in $VG_SELECCIONADOS; do
VG=$(echo "$VG" | tr -d '"') # Eliminar comillas
vgchange -ay "$VG"
done
whiptail --title "Volúmenes Activados" --msgbox "Los grupos de volúmenes seleccionados se activaron correctamente." 8 40
# 4. Escanear volúmenes en Proxmox
whiptail --title "Escanear VM" --infobox "Rescaneando las imágenes de disco y volúmenes..." 8 40
qm rescan
# 5. Mensaje final
whiptail --title "Finalizado" --msgbox "Los volúmenes y las imágenes de disco fueron reconocidos y están disponibles para usar en Proxmox." 8 40
exit 0

View File

@ -1,61 +0,0 @@
#!/bin/bash
DUMP_DIR="/var/lib/vz/dump"
STORAGE_CFG="/etc/pve/storage.cfg"
# Función para comprobar y reparar después de la restauración
reparar_storage_cfg() {
whiptail --title "Comprobación de Almacenamientos" --msgbox "Comprobando consistencia de los volúmenes de almacenamiento..." 8 40
# Verificar grupos LVM
VG_LIST=$(vgs --noheadings -o vg_name)
while read -r LINE; do
if [[ "$LINE" =~ vgname ]]; then
VG_NAME=$(echo "$LINE" | awk '{print $NF}')
if ! echo "$VG_LIST" | grep -q "$VG_NAME"; then
echo "El volumen $VG_NAME no existe, eliminando entrada..."
sed -i "/vgname $VG_NAME/,/nodes/d" "$STORAGE_CFG"
fi
fi
done < "$STORAGE_CFG"
whiptail --title "Reparación Completada" --msgbox "La comprobación de consistencia ha finalizado. Se eliminaron las entradas no válidas." 8 40
}
# Restaurar copia de seguridad y comprobar
restaurar_backup() {
BACKUP_FILE=$(whiptail --title "Seleccionar Copia de Seguridad" --menu "Selecciona la copia de seguridad a restaurar:" 15 60 8 $(ls "$DUMP_DIR"/storage.cfg_*.bak) 3>&1 1>&2 2>&3)
if [ -z "$BACKUP_FILE" ]; then
whiptail --title "Error" --msgbox "No se seleccionó ninguna copia de seguridad." 8 40
exit 1
fi
cp "$BACKUP_FILE" "$STORAGE_CFG"
whiptail --title "Restauración Completada" --msgbox "Se ha restaurado el archivo storage.cfg desde la copia de seguridad: $BACKUP_FILE" 8 40
reparar_storage_cfg
}
# Menú principal
OPTION=$(whiptail --title "Gestor de Storage.cfg" --menu "Selecciona una opción:" 15 60 3 \
"1" "Realizar copia de seguridad del archivo storage.cfg" \
"2" "Restaurar copia de seguridad y comprobar consistencia" \
"3" "Reparar archivo storage.cfg si se han cambiado discos" 3>&1 1>&2 2>&3)
case $OPTION in
1)
BACKUP_FILE="${DUMP_DIR}/storage.cfg_$(date +%Y%m%d%H%M%S).bak"
cp "$STORAGE_CFG" "$BACKUP_FILE"
whiptail --title "Copia de Seguridad" --msgbox "Se ha creado una copia de seguridad en: $BACKUP_FILE" 8 40
;;
2)
restaurar_backup
;;
3)
reparar_storage_cfg
;;
*)
exit 0
;;
esac

File diff suppressed because it is too large Load Diff