Script to create Jump VM that loaded tk2s.org SSH private key
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
#!/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."
|
||||
Reference in New Issue
Block a user