hdmistat/scripts/qemu-ubuntu-arm64.sh
2025-07-24 14:32:50 +02:00

315 lines
8.2 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# ARM64 Ubuntu QEMU setup with cloud-init for hdmistat testing
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
WORK_DIR="${PROJECT_DIR}/qemu-ubuntu-test"
CLOUD_INIT_DIR="${WORK_DIR}/cloud-init"
# QEMU settings
QEMU_MEM="2G"
QEMU_CPUS="4"
DISK_SIZE="8G"
VNC_PORT="5902"
# Ubuntu Cloud Image ARM64
UBUNTU_VERSION="22.04"
UBUNTU_IMAGE="ubuntu-${UBUNTU_VERSION}-server-cloudimg-arm64.img"
UBUNTU_URL="https://cloud-images.ubuntu.com/releases/${UBUNTU_VERSION}/release/${UBUNTU_IMAGE}"
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $*"
}
error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
exit 1
}
# Check dependencies
check_dependencies() {
log "Checking dependencies..."
local deps=("qemu-system-aarch64" "qemu-img" "wget" "genisoimage")
for dep in "${deps[@]}"; do
if ! command -v "$dep" &> /dev/null; then
error "$dep not found"
fi
done
log "Dependencies OK"
}
# Setup directories
setup_directories() {
log "Setting up directories..."
mkdir -p "$WORK_DIR"
mkdir -p "$CLOUD_INIT_DIR"
}
# Download Ubuntu cloud image
download_ubuntu() {
cd "$WORK_DIR"
if [ -f "$UBUNTU_IMAGE" ]; then
log "Ubuntu cloud image already exists"
return
fi
log "Downloading Ubuntu ${UBUNTU_VERSION} ARM64 cloud image..."
wget -O "$UBUNTU_IMAGE" "$UBUNTU_URL" || error "Failed to download Ubuntu image"
}
# Create working disk from cloud image
create_disk() {
cd "$WORK_DIR"
if [ -f "hdmistat-test.qcow2" ]; then
log "Working disk already exists"
return
fi
log "Creating working disk from cloud image..."
qemu-img create -f qcow2 -F qcow2 -b "$UBUNTU_IMAGE" hdmistat-test.qcow2 $DISK_SIZE
}
# Create cloud-init configuration
create_cloud_init() {
log "Creating cloud-init configuration..."
# Create meta-data
cat > "${CLOUD_INIT_DIR}/meta-data" << 'EOF'
instance-id: hdmistat-test-01
local-hostname: hdmistat-test
EOF
# Create user-data with hdmistat installation
cat > "${CLOUD_INIT_DIR}/user-data" << 'EOF'
#cloud-config
hostname: hdmistat-test
manage_etc_hosts: true
users:
- name: ubuntu
groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video]
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
lock_passwd: false
passwd: $6$rounds=4096$8VNRmFT9yR$7TVlOepTJjMW0CzBkpMrdWA7aH4rZ94pZng8XjqaY8d8qqBmFvO/hYL5L2gqJ5nKLhDR8Jz9Z9nqfHBl5kVZHe1
packages:
- git
- build-essential
- wget
- fbset
# Enable SSH (already enabled in cloud images)
ssh_pwauth: true
# Update system
package_update: true
package_upgrade: false
write_files:
- path: /tmp/install-go.sh
permissions: '0755'
content: |
#!/bin/bash
set -e
GO_VERSION="1.24.4"
wget -q -O /tmp/go.tar.gz "https://go.dev/dl/go${GO_VERSION}.linux-arm64.tar.gz"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf /tmp/go.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee -a /etc/profile
echo 'export GOPATH=$HOME/go' | sudo tee -a /etc/profile
echo 'export PATH=$PATH:$GOPATH/bin' | sudo tee -a /etc/profile
- path: /tmp/setup-hdmistat.sh
permissions: '0755'
content: |
#!/bin/bash
set -e
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
# Mount hdmistat source
sudo mkdir -p /mnt/hdmistat
sudo mount -t 9p -o trans=virtio,version=9p2000.L hdmistat /mnt/hdmistat || echo "Failed to mount hdmistat source"
# Build hdmistat
if [ -d "/mnt/hdmistat" ]; then
echo "Building hdmistat from mounted source..."
cd /mnt/hdmistat
make build
sudo cp hdmistat /usr/local/bin/
fi
# Create config
sudo mkdir -p /etc/hdmistat
sudo tee /etc/hdmistat/config.yaml << 'CONFIG_EOF'
framebuffer_device: /dev/fb0
rotation_interval: 10s
update_interval: 1s
log_level: info
width: 1024
height: 768
screens:
- overview
- top_cpu
- top_memory
CONFIG_EOF
# Enable framebuffer
echo "fbcon=map:10" | sudo tee -a /etc/default/grub
sudo update-grub || true
runcmd:
- /tmp/install-go.sh
- su - ubuntu -c /tmp/setup-hdmistat.sh
- echo "hdmistat setup complete! Use 'hdmistat daemon' to start"
final_message: "hdmistat test environment ready!"
EOF
# Create cloud-init ISO
log "Creating cloud-init ISO..."
cd "$WORK_DIR"
genisoimage -output cloud-init.iso -volid cidata -joliet -rock "${CLOUD_INIT_DIR}/user-data" "${CLOUD_INIT_DIR}/meta-data"
}
# Create run script
create_run_script() {
cat > "${WORK_DIR}/run-qemu.sh" << EOF
#!/bin/bash
cd "$WORK_DIR"
echo "Starting QEMU ARM64 Ubuntu with cloud-init..."
echo ""
echo "Login: ubuntu / ubuntu"
echo "SSH available on port 2223: ssh ubuntu@localhost -p 2223"
echo "VNC available on port $VNC_PORT"
echo ""
echo "hdmistat will be installed automatically via cloud-init"
echo "Check cloud-init status with: cloud-init status"
echo ""
echo "Press Ctrl+A, X to quit"
echo ""
# Find EFI firmware and vars
EFI_CODE=""
EFI_VARS=""
for dir in /nix/store/*/share/qemu /run/current-system/sw/share/qemu; do
if [ -f "\$dir/edk2-aarch64-code.fd" ]; then
EFI_CODE="\$dir/edk2-aarch64-code.fd"
if [ -f "\$dir/edk2-arm-vars.fd" ]; then
EFI_VARS="\$dir/edk2-arm-vars.fd"
fi
break
fi
done
# Create a copy of EFI vars if found
if [ -n "\$EFI_VARS" ] && [ ! -f "efivars.fd" ]; then
cp "\$EFI_VARS" efivars.fd
fi
BIOS_ARGS=""
if [ -n "\$EFI_CODE" ]; then
BIOS_ARGS="-bios \$EFI_CODE"
if [ -f "efivars.fd" ]; then
BIOS_ARGS="\$BIOS_ARGS -drive if=pflash,format=raw,file=efivars.fd"
fi
fi
qemu-system-aarch64 \\
-M virt \\
-accel hvf \\
-cpu host \\
-smp $QEMU_CPUS \\
-m $QEMU_MEM \\
-nographic \\
-drive file=hdmistat-test.qcow2,format=qcow2,if=virtio \\
-drive file=cloud-init.iso,format=raw,if=virtio \\
-netdev user,id=net0,hostfwd=tcp::2223-:22 \\
-device virtio-net-pci,netdev=net0 \\
-device virtio-gpu-pci \\
-display default,show-cursor=on \\
-vnc :2 \\
-serial mon:stdio \\
-virtfs local,path="${PROJECT_DIR}",mount_tag=hdmistat,security_model=none,id=hdmistat \\
\$BIOS_ARGS \\
\${@}
EOF
chmod +x "${WORK_DIR}/run-qemu.sh"
}
# Create helper scripts
create_helpers() {
# VNC viewer
cat > "${WORK_DIR}/view-vnc.sh" << EOF
#!/bin/bash
echo "Opening VNC viewer on localhost:$VNC_PORT"
vncviewer localhost:$VNC_PORT || open vnc://localhost:$VNC_PORT || echo "Connect to VNC at localhost:$VNC_PORT"
EOF
chmod +x "${WORK_DIR}/view-vnc.sh"
# SSH helper
cat > "${WORK_DIR}/ssh-ubuntu.sh" << EOF
#!/bin/bash
echo "Connecting to Ubuntu VM..."
echo "Password: ubuntu"
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@localhost -p 2223
EOF
chmod +x "${WORK_DIR}/ssh-ubuntu.sh"
}
# Print instructions
print_instructions() {
echo ""
echo "======================================="
echo "QEMU ARM64 Ubuntu Setup Complete!"
echo "======================================="
echo ""
echo "To start testing:"
echo " cd $WORK_DIR"
echo " ./run-qemu.sh"
echo ""
echo "Features:"
echo " - Ubuntu ${UBUNTU_VERSION} ARM64 with cloud-init"
echo " - Native ARM64 virtualization (hvf)"
echo " - Automatic hdmistat installation"
echo " - Framebuffer support"
echo " - SSH access on port 2223"
echo " - VNC access on port $VNC_PORT"
echo ""
echo "The cloud-init config is in: $CLOUD_INIT_DIR/"
echo "You can modify it and regenerate the ISO with:"
echo " genisoimage -output cloud-init.iso -volid cidata -joliet -rock user-data meta-data"
echo ""
}
# Main
main() {
log "Setting up QEMU ARM64 Ubuntu environment with cloud-init..."
check_dependencies
setup_directories
download_ubuntu
create_disk
create_cloud_init
create_run_script
create_helpers
print_instructions
log "Setup complete!"
}
main "$@"