342 lines
9.9 KiB
Bash
Executable File
342 lines
9.9 KiB
Bash
Executable File
#!/bin/bash
|
||
# create-vm.sh
|
||
# Script per creare singole VM su Proxmox con parametri personalizzabili
|
||
# Uso: ./create-vm.sh <vm_id> <vm_name> [cores] [memory_mb] [disk_size]
|
||
# Esempio: ./create-vm.sh 203 web-server 4 8192 50G
|
||
|
||
set -e
|
||
|
||
# ==================== CONFIGURAZIONE ====================
|
||
|
||
# Parametri da riga di comando
|
||
if [ "$#" -lt 2 ]; then
|
||
echo "Uso: $0 <vm_id> <vm_name> [cores] [memory_mb] [disk_size]"
|
||
echo ""
|
||
echo "Parametri obbligatori:"
|
||
echo " vm_id - ID della VM Proxmox (es: 203)"
|
||
echo " vm_name - Nome della VM (es: web-server)"
|
||
echo ""
|
||
echo "Parametri opzionali (valori di default):"
|
||
echo " cores - Numero di CPU cores (default: 4)"
|
||
echo " memory_mb - RAM in MB (default: 8192)"
|
||
echo " disk_size - Dimensione disco con unità (default: 50G)"
|
||
echo ""
|
||
echo "Esempi:"
|
||
echo " $0 203 web-server # VM con valori default"
|
||
echo " $0 203 web-server 2 4096 30G # VM con 2 cores, 4GB RAM, 30GB disco"
|
||
echo ""
|
||
echo "Nota: L'IP sarà automaticamente 192.168.1.<vm_id>"
|
||
exit 1
|
||
fi
|
||
|
||
VM_ID=$1
|
||
VM_NAME=$2
|
||
VM_IP="192.168.1.${VM_ID}"
|
||
|
||
# Parametri opzionali con valori di default
|
||
CORES=${3:-2}
|
||
MEMORY=${4:-4096}
|
||
DISK_SIZE=${5:-20G}
|
||
|
||
# Configurazione Proxmox
|
||
PVE_NODE="server"
|
||
STORAGE="sddmirror" # Storage principale per i dischi VM (supporta Images)
|
||
BRIDGE="vmbr0"
|
||
|
||
# FIX: Due variabili per lo storage
|
||
CLOUDINIT_VOL_STORAGE="$STORAGE" # sddmirror: Useremo lo storage principale che supporta i volumi disco Cloud-Init (Images)
|
||
SNIPPET_STORAGE="local" # local: Manteniamo 'local' per i file snippet YAML
|
||
|
||
# Configurazione di rete
|
||
GATEWAY="192.168.1.1"
|
||
NETMASK="24"
|
||
DNS="8.8.8.8"
|
||
|
||
# Template
|
||
TEMPLATE_ID=9000
|
||
UBUNTU_IMAGE_URL="https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
|
||
UBUNTU_IMAGE_NAME="ubuntu-24.04-cloudimg.img"
|
||
|
||
# Credenziali
|
||
SSH_PUBLIC_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOyva+cul3WOW3ct53a0QMRTkhtKvA2QpJI0p8bv48tH alex@alex-XPS-15-9570"
|
||
ROOT_PASSWORD="TempProxmox123!"
|
||
|
||
# Directory applicazioni
|
||
APP_DIR="/opt/myapp"
|
||
|
||
# Directory per gli snippet
|
||
SNIPPETS_DIR="/var/lib/vz/snippets"
|
||
|
||
# Colors
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
# ==================== FUNZIONI ====================
|
||
|
||
print_header() {
|
||
echo -e "${BLUE}================================================${NC}"
|
||
echo -e "${BLUE}$1${NC}"
|
||
echo -e "${BLUE}================================================${NC}"
|
||
}
|
||
|
||
print_success() { echo -e "${GREEN}✓ $1${NC}"; }
|
||
print_warning() { echo -e "${YELLOW}⚠ $1${NC}"; }
|
||
print_error() { echo -e "${RED}✗ $1${NC}"; }
|
||
print_info() { echo -e "${BLUE}ℹ $1${NC}"; }
|
||
|
||
check_command() {
|
||
if ! command -v $1 &> /dev/null; then
|
||
print_error "$1 non trovato. Installalo: apt install $1"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Funzione per generare il file user-data YAML personalizzato (come snippet)
|
||
create_custom_user_data() {
|
||
local vm_name=$1
|
||
local output_file="/tmp/${vm_name}-user-data.yaml"
|
||
|
||
# Crea user-data YAML
|
||
cat > "$output_file" << EOF
|
||
#cloud-config
|
||
hostname: $vm_name
|
||
fqdn: ${vm_name}.local
|
||
manage_etc_hosts: true
|
||
|
||
users:
|
||
- name: root
|
||
ssh_authorized_keys:
|
||
- $SSH_PUBLIC_KEY
|
||
lock_passwd: false
|
||
shell: /bin/bash
|
||
|
||
chpasswd:
|
||
list: |
|
||
root:$ROOT_PASSWORD
|
||
expire: false
|
||
|
||
ssh_pwauth: true
|
||
disable_root: false
|
||
|
||
packages:
|
||
- curl
|
||
- wget
|
||
- git
|
||
- htop
|
||
- net-tools
|
||
- qemu-guest-agent
|
||
|
||
runcmd:
|
||
# Install Docker
|
||
- mkdir -p /etc/apt/keyrings
|
||
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||
- echo "deb [arch=\$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||
- apt-get update
|
||
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||
- systemctl enable docker
|
||
- systemctl start docker
|
||
- systemctl enable qemu-guest-agent
|
||
- systemctl start qemu-guest-agent
|
||
|
||
# Configure sysctl
|
||
- echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.conf
|
||
- echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
|
||
- sysctl -p
|
||
|
||
# Create app directory
|
||
- mkdir -p $APP_DIR
|
||
- chown -R root:root $APP_DIR
|
||
|
||
# Ensure SSH is properly configured
|
||
- sed -i 's/#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
||
- sed -i 's/#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
||
- systemctl restart sshd
|
||
|
||
power_state:
|
||
mode: reboot
|
||
timeout: 300
|
||
condition: true
|
||
EOF
|
||
|
||
echo "$output_file"
|
||
}
|
||
|
||
# ==================== SCRIPT PRINCIPALE ====================
|
||
|
||
print_header "CREAZIONE VM SU PROXMOX"
|
||
|
||
# Check prerequisites
|
||
print_info "Verifica prerequisiti..."
|
||
check_command "qm"
|
||
print_success "Prerequisiti OK"
|
||
|
||
# Validazione parametri
|
||
if ! [[ "$VM_ID" =~ ^[0-9]+$ ]]; then
|
||
print_error "VM_ID deve essere un numero valido"
|
||
exit 1
|
||
fi
|
||
|
||
if [ "$VM_ID" -eq "$TEMPLATE_ID" ]; then
|
||
print_error "VM_ID $VM_ID è riservato per il template"
|
||
exit 1
|
||
fi
|
||
|
||
if ! [[ "$CORES" =~ ^[0-9]+$ ]] || [ "$CORES" -lt 1 ]; then
|
||
print_error "CORES deve essere un numero positivo (valore fornito: $CORES)"
|
||
exit 1
|
||
fi
|
||
|
||
if ! [[ "$MEMORY" =~ ^[0-9]+$ ]] || [ "$MEMORY" -lt 512 ]; then
|
||
print_error "MEMORY deve essere almeno 512 MB (valore fornito: $MEMORY)"
|
||
exit 1
|
||
fi
|
||
|
||
if ! [[ "$DISK_SIZE" =~ ^[0-9]+[GMK]$ ]]; then
|
||
print_error "DISK_SIZE deve essere nel formato numero+unità (es: 50G, 500M) (valore fornito: $DISK_SIZE)"
|
||
exit 1
|
||
fi
|
||
|
||
print_info "Configurazione VM:"
|
||
print_info " ID: $VM_ID"
|
||
print_info " Nome: $VM_NAME"
|
||
print_info " IP: $VM_IP"
|
||
print_info " CPU Cores: $CORES"
|
||
print_info " RAM: ${MEMORY}MB"
|
||
print_info " Disco: $DISK_SIZE"
|
||
|
||
# Crea la directory snippet se non esiste
|
||
mkdir -p "$SNIPPETS_DIR"
|
||
|
||
# Verifica se la VM esiste già
|
||
if qm status $VM_ID &>/dev/null; then
|
||
print_warning "VM $VM_ID già esistente!"
|
||
read -p "Vuoi eliminarlo e ricrearlo? (y/N) " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
print_info "Arresto VM $VM_ID..."
|
||
qm stop $VM_ID || true
|
||
sleep 3
|
||
print_info "Eliminazione VM $VM_ID..."
|
||
qm destroy $VM_ID
|
||
# Pulizia dei file custom
|
||
rm -f "${SNIPPETS_DIR}/${VM_ID}-user-data.yaml"
|
||
print_success "VM $VM_ID eliminata"
|
||
else
|
||
print_error "Operazione annullata"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# ==================== VERIFICA/CREA TEMPLATE ====================
|
||
|
||
print_header "STEP 1: Verifica Template Cloud-Init"
|
||
|
||
if ! qm status $TEMPLATE_ID &>/dev/null; then
|
||
print_info "Template non trovato. Creazione in corso..."
|
||
cd /tmp
|
||
if [ ! -f "$UBUNTU_IMAGE_NAME" ]; then
|
||
print_info "Download Ubuntu Cloud Image..."
|
||
wget -q --show-progress $UBUNTU_IMAGE_URL -O $UBUNTU_IMAGE_NAME
|
||
fi
|
||
|
||
print_info "Creazione template VM..."
|
||
qm create $TEMPLATE_ID --name ubuntu-cloud-template --memory $MEMORY --net0 virtio,bridge=$BRIDGE --cores $CORES
|
||
|
||
# Importa il disco
|
||
qm importdisk $TEMPLATE_ID $UBUNTU_IMAGE_NAME $STORAGE &>/dev/null
|
||
qm set $TEMPLATE_ID --scsihw virtio-scsi-single --scsi0 ${STORAGE}:vm-${TEMPLATE_ID}-disk-0
|
||
|
||
# Configurazione Cloud-Init
|
||
qm set $TEMPLATE_ID --delete ide0 2>/dev/null || true
|
||
qm set $TEMPLATE_ID --delete ide2 2>/dev/null || true
|
||
|
||
# Aggiungi il drive per cloud-init
|
||
qm set $TEMPLATE_ID --ide2 ${CLOUDINIT_VOL_STORAGE}:cloudinit,format=raw
|
||
|
||
# Imposta configurazioni essenziali
|
||
qm set $TEMPLATE_ID --cpu x86-64-v2-AES
|
||
qm set $TEMPLATE_ID --agent enabled=1
|
||
qm set $TEMPLATE_ID --boot c --bootdisk scsi0
|
||
|
||
# Resize del disco del template
|
||
qm resize $TEMPLATE_ID scsi0 $DISK_SIZE &>/dev/null || true
|
||
|
||
qm template $TEMPLATE_ID
|
||
|
||
print_success "Template creato con successo"
|
||
else
|
||
print_success "Template già esistente"
|
||
fi
|
||
|
||
# ==================== CREA VM ====================
|
||
|
||
print_header "STEP 2: Creazione VM $VM_NAME (ID: $VM_ID, IP: $VM_IP)"
|
||
|
||
print_info "Clonazione template..."
|
||
qm clone $TEMPLATE_ID $VM_ID --name $VM_NAME --full
|
||
|
||
# 1. Crea il file user-data personalizzato
|
||
USER_DATA_FILE=$(create_custom_user_data $VM_NAME)
|
||
|
||
# 2. Crea il file SSH temporaneo
|
||
SSH_KEY_FILE="/tmp/${VM_NAME}_id_rsa.pub"
|
||
echo "$SSH_PUBLIC_KEY" > "$SSH_KEY_FILE"
|
||
print_info "Chiave SSH salvata in $SSH_KEY_FILE per l'iniezione."
|
||
|
||
# 3. Allega il file user-data personalizzato come snippet (cicustom)
|
||
SNIPPET_FILENAME="${VM_ID}-user-data.yaml"
|
||
|
||
# 4. Configura VM con tutti i dati di Cloud-Init
|
||
print_info "Iniezione configurazione Cloud-Init..."
|
||
qm set $VM_ID \
|
||
--ciuser root \
|
||
--sshkeys "$SSH_KEY_FILE" \
|
||
--ipconfig0 "ip=${VM_IP}/${NETMASK},gw=${GATEWAY}" \
|
||
--nameserver "${DNS}" \
|
||
--cicustom "user=${SNIPPET_STORAGE}:snippets/${SNIPPET_FILENAME}"
|
||
|
||
# 5. Sposta il file user-data nella directory snippets di Proxmox
|
||
mv "$USER_DATA_FILE" "${SNIPPETS_DIR}/${SNIPPET_FILENAME}"
|
||
|
||
# 6. PULIZIA: Rimuovi il file temporaneo della chiave SSH
|
||
rm "$SSH_KEY_FILE"
|
||
|
||
print_success "VM configurata e dati cloud-init iniettati"
|
||
|
||
# ==================== AVVIA VM ====================
|
||
|
||
print_header "STEP 3: Avvio della VM"
|
||
|
||
print_info "Avvio VM $VM_NAME ($VM_IP)..."
|
||
qm start $VM_ID
|
||
sleep 5
|
||
|
||
print_info "Attendo cloud-init (2-3 minuti). Il primo avvio può richiedere tempo per il resize e le installazioni."
|
||
sleep 180
|
||
|
||
# ==================== RIEPILOGO ====================
|
||
|
||
print_header "CREAZIONE VM COMPLETATA! 🎉"
|
||
|
||
print_info ""
|
||
print_info "Dettagli VM:"
|
||
print_info " Nome: $VM_NAME"
|
||
print_info " ID: $VM_ID"
|
||
print_info " IP: ${GREEN}$VM_IP${NC}"
|
||
print_info " Cores: $CORES"
|
||
print_info " Memory: ${MEMORY}MB"
|
||
print_info " Disk: $DISK_SIZE"
|
||
print_info ""
|
||
print_info "Credenziali:"
|
||
print_info " User: root"
|
||
print_info " Password: $ROOT_PASSWORD"
|
||
print_info " SSH Key: configurata"
|
||
print_info ""
|
||
print_info "Test connessione (attendere il riavvio causato da cloud-init se non funziona subito):"
|
||
print_info " ssh root@$VM_IP"
|
||
print_info ""
|
||
print_success "Setup completato! La VM ora ha IP statico $VM_IP, Docker installato e chiave SSH configurata."
|