Files
tk2s.org/create_tk2s.org_jump_vm.sh
T

228 lines
8.0 KiB
Bash

#!/bin/bash
set -e
VM_NAME="vm-ubuntu2204"
VCPUS=16
RAM=16384
DISK_SIZE=50G
IMG_URL="https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
POOL_DIR="/var/lib/libvirt/images"
BASE_IMG="$POOL_DIR/jammy-base.img"
VM_DISK="$POOL_DIR/${VM_NAME}.qcow2"
SEED_ISO="$POOL_DIR/${VM_NAME}-seed.iso"
PASSWORD="ubuntu"
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')] [INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] [WARN]${NC} $1"; }
err() { echo -e "${RED}[$(date '+%H:%M:%S')] [ERROR]${NC} $1"; }
step() { echo -e "\n${GREEN}=========================================="; echo -e " $1"; echo -e "==========================================${NC}"; }
trap 'err "Script failed at line $LINENO. Aborting."' ERR
echo -e "${GREEN}"
echo "##############################################"
echo "# DEPLOY UBUNTU 22.04 VM ON KVM #"
echo "# VM: $VM_NAME | ${VCPUS} vCPU | $((RAM/1024))GB RAM | $DISK_SIZE #"
echo "##############################################"
echo -e "${NC}"
# ---------------------------------------------
step "STEP 0/6: ENVIRONMENT CHECKS"
# ---------------------------------------------
[ "$EUID" -eq 0 ] || { err "Must be run as root/sudo."; exit 1; }
log "Running as root: OK"
if grep -qE 'vmx|svm' /proc/cpuinfo; then
log "CPU supports hardware virtualization: OK"
else
err "CPU does not support VT-x/AMD-V, or it is disabled in BIOS."
exit 1
fi
HOST_CPU=$(nproc); HOST_RAM=$(free -m | awk '/^Mem:/{print $2}')
log "Host: ${HOST_CPU} CPUs, ${HOST_RAM} MB RAM"
[ "$HOST_CPU" -lt "$VCPUS" ] && warn "Host has only ${HOST_CPU} CPUs but VM requests ${VCPUS} (overcommit)."
[ "$HOST_RAM" -lt "$RAM" ] && warn "Host has only ${HOST_RAM} MB RAM but VM requests ${RAM} MB."
log "Free disk space: $(df -h /var/lib | awk 'NR==2{print $4}')"
# ---------------------------------------------
step "STEP 1/6: INSTALLING LIBVIRT / KVM"
# ---------------------------------------------
log "Updating apt index..."
apt-get update -qq
log "Installing packages: qemu-kvm, libvirt, virtinst, cloud-image-utils..."
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
qemu-kvm libvirt-daemon-system libvirt-clients \
virtinst bridge-utils cloud-image-utils wget whois \
libosinfo-bin osinfo-db-tools
log "Package installation complete."
log "Starting libvirtd..."
systemctl enable --now libvirtd
systemctl is-active --quiet libvirtd && log "libvirtd is running: OK" || { err "libvirtd failed to start."; exit 1; }
log "Versions: $(virsh --version) | $(kvm --version | head -1)"
log "Configuring 'default' NAT network..."
virsh net-start default 2>/dev/null && log "Started default network." || warn "Default network already running."
virsh net-autostart default >/dev/null 2>&1 || true
log "Network status:"
virsh net-list --all
# ---------------------------------------------
step "STEP 2/6: RESOLVING OS-VARIANT"
# ---------------------------------------------
os_exists() { osinfo-query os short-id="$1" 2>/dev/null | grep -qw "$1"; }
OS_VARIANT=""
log "Checking local osinfo database for ubuntu22.04..."
if os_exists ubuntu22.04; then
OS_VARIANT="ubuntu22.04"
log "Found ubuntu22.04 in osinfo database."
else
warn "ubuntu22.04 not found (Ubuntu 20.04 ships an older osinfo-db)."
log "Attempting to import an updated osinfo database..."
OSINFO_TAR="/tmp/osinfo-db.tar.xz"
if wget -q -O "$OSINFO_TAR" "https://releases.pagure.org/libosinfo/osinfo-db-20240701.tar.xz"; then
if osinfo-db-import --local "$OSINFO_TAR" >/dev/null 2>&1; then
log "osinfo database imported successfully."
else
warn "osinfo-db-import failed."
fi
rm -f "$OSINFO_TAR"
else
warn "Could not download osinfo-db (no network or URL changed)."
fi
log "Re-checking database after import..."
for v in ubuntu22.04 ubuntu20.04 ubuntu18.04 generic; do
if [ "$v" = "generic" ] || os_exists "$v"; then
OS_VARIANT="$v"; break
fi
done
fi
OS_VARIANT="${OS_VARIANT:-generic}"
log "Using --os-variant $OS_VARIANT"
[ "$OS_VARIANT" != "ubuntu22.04" ] && warn "Falling back to '$OS_VARIANT'. This only affects device/perf defaults; virtio + cloud image still works."
# ---------------------------------------------
step "STEP 3/6: PREPARING CLOUD IMAGE"
# ---------------------------------------------
if [ -f "$BASE_IMG" ]; then
log "Base image already exists ($(du -h "$BASE_IMG" | cut -f1)), skipping download."
else
log "Downloading Ubuntu 22.04 cloud image (~600MB)..."
log "URL: $IMG_URL"
wget -q --show-progress -O "$BASE_IMG" "$IMG_URL"
log "Download complete: $(du -h "$BASE_IMG" | cut -f1)"
fi
log "Base image info:"
qemu-img info "$BASE_IMG" | sed 's/^/ /'
# ---------------------------------------------
step "STEP 4/6: CREATING DISK AND CLOUD-INIT"
# ---------------------------------------------
log "Creating ${DISK_SIZE} overlay disk for the VM..."
rm -f "$VM_DISK"
qemu-img create -f qcow2 -F qcow2 -b "$BASE_IMG" "$VM_DISK" "$DISK_SIZE" >/dev/null
log "Disk created: $VM_DISK"
log "Generating password hash for root..."
HASH=$(mkpasswd -m sha-512 "$PASSWORD")
WORKDIR=$(mktemp -d)
log "Temp directory: $WORKDIR"
log "Writing user-data (enable root login, password auth)..."
cat > "$WORKDIR/user-data" <<EOF
#cloud-config
hostname: ${VM_NAME}
disable_root: false
ssh_pwauth: true
users:
- name: root
lock_passwd: false
hashed_passwd: "${HASH}"
shell: /bin/bash
chpasswd:
expire: false
list: |
root:${PASSWORD}
runcmd:
- sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
- sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
- systemctl restart ssh
EOF
log "Writing meta-data..."
cat > "$WORKDIR/meta-data" <<EOF
instance-id: ${VM_NAME}
local-hostname: ${VM_NAME}
EOF
log "Building seed ISO..."
cloud-localds "$SEED_ISO" "$WORKDIR/user-data" "$WORKDIR/meta-data"
log "Created: $SEED_ISO"
rm -rf "$WORKDIR"
log "Temp directory cleaned up."
# ---------------------------------------------
step "STEP 5/6: CREATING AND BOOTING THE VM"
# ---------------------------------------------
if virsh dominfo "$VM_NAME" >/dev/null 2>&1; then
warn "VM '$VM_NAME' already exists (possibly from a failed run). Removing it..."
virsh destroy "$VM_NAME" 2>/dev/null || true
virsh undefine "$VM_NAME" 2>/dev/null || true
log "Old VM removed."
fi
log "Running virt-install with --os-variant $OS_VARIANT ..."
virt-install \
--name "$VM_NAME" \
--memory "$RAM" \
--vcpus "$VCPUS" \
--cpu host-passthrough \
--disk path="$VM_DISK",device=disk,bus=virtio \
--disk path="$SEED_ISO",device=cdrom \
--os-variant "$OS_VARIANT" \
--network network=default,model=virtio \
--graphics none \
--console pty,target_type=serial \
--import \
--noautoconsole
log "VM defined and started."
virsh autostart "$VM_NAME" >/dev/null
log "Autostart enabled for the VM."
# ---------------------------------------------
step "STEP 6/6: WAITING FOR BOOT AND IP"
# ---------------------------------------------
log "Waiting for cloud-init to finish and the VM to get an IP (up to 120s)..."
IP=""
for i in $(seq 1 24); do
IP=$(virsh domifaddr "$VM_NAME" 2>/dev/null | awk '/ipv4/{split($4,a,"/"); print a[1]}')
if [ -n "$IP" ]; then
log "Got IP after $((i*5))s: $IP"
break
fi
echo -e "${YELLOW} ... waiting ($((i*5))s/120s)${NC}"
sleep 5
done
[ -z "$IP" ] && warn "No IP yet. Check later with: virsh domifaddr $VM_NAME"
# ---------------------------------------------
step "DONE"
# ---------------------------------------------
virsh dominfo "$VM_NAME" | sed 's/^/ /'
echo
log "VM Name : $VM_NAME"
log "vCPU/RAM : ${VCPUS} / $((RAM/1024))GB"
log "Disk : $VM_DISK ($DISK_SIZE)"
log "OS variant : $OS_VARIANT"
log "IP : ${IP:-<none>}"
log "Login : root / $PASSWORD"
echo
log "Console : virsh console $VM_NAME (exit: Ctrl+])"
[ -n "$IP" ] && log "SSH : ssh root@$IP"
warn "Cloud-init may need another 30-60s to finish SSH configuration."