Initial commit

This commit is contained in:
Guofang committed 2026-08-26 12:36:30 +08:00
commit 58a0a2d1ff
24 files changed
+1156

No files matched your search

+169
View File
@@ -0,0 +1,169 @@
#!/usr/bin/env bash
set -euo pipefail
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
if [[ -n "${VM_IMAGE_HELPER:-}" ]]; then
image_downloader="$VM_IMAGE_HELPER"
elif [[ -x "${script_dir}/vm-images/download-images.sh" ]]; then
image_downloader="${script_dir}/vm-images/download-images.sh"
else
image_downloader="${script_dir}/../vm-images/download-images.sh"
fi
uses_shared_base_image=false
if [[ -n "${ALMA_VM_BASE_IMAGE:-}" ]]; then
base_image="$ALMA_VM_BASE_IMAGE"
else
[[ -x "$image_downloader" ]] || { printf 'Error: shared image helper is unavailable: %s\n' "$image_downloader" >&2; exit 1; }
base_image="$("$image_downloader" --print-path almalinux10)"
uses_shared_base_image=true
fi
state_dir="${ALMA_VM_STATE_DIR:-${script_dir}/.vm/almalinux10}"
disk_image="${ALMA_VM_DISK_IMAGE:-${state_dir}/disk.qcow2}"
seed_image="${ALMA_VM_SEED_IMAGE:-$(dirname -- "$disk_image")/seed.iso}"
disk_size="${ALMA_VM_DISK_SIZE:-20G}"
memory="${ALMA_VM_MEMORY:-8G}"
cpus="${ALMA_VM_CPUS:-8}"
ssh_port="${ALMA_VM_SSH_PORT:-2223}"
uefi_code="${ALMA_VM_UEFI_CODE:-/usr/share/OVMF/OVMF_CODE_4M.fd}"
uefi_vars_template="${ALMA_VM_UEFI_VARS:-/usr/share/OVMF/OVMF_VARS_4M.fd}"
uefi_vars="${state_dir}/OVMF_VARS_4M.fd"
pid_file="${state_dir}/qemu.pid"
log_file="${state_dir}/console.log"
daemonize=false
extra_args=()
usage() {
cat <<EOF
Usage: $(basename "$0") [--daemon] [-- QEMU_ARGUMENT ...]
Start an AlmaLinux 10 Generic Cloud virtual machine. The launcher obtains a
missing base image through ../vm-images/download-images.sh and creates a
writable overlay under .vm/almalinux10/, leaving the base image unchanged.
Options:
--daemon Run in the background while keeping the graphical window
-h, --help Show this help
Environment variables:
ALMA_VM_MEMORY Guest memory (default: 8G)
ALMA_VM_CPUS Virtual CPU count (default: 8)
ALMA_VM_SSH_PORT Host port forwarded to guest SSH (default: 2223)
ALMA_VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper)
ALMA_VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk)
ALMA_VM_STATE_DIR Runtime state directory (default: .vm/almalinux10)
ALMA_VM_DISK_IMAGE Writable overlay path
ALMA_VM_DISK_SIZE New overlay virtual capacity (default: 20G)
ALMA_VM_UEFI_CODE OVMF read-only firmware path
ALMA_VM_UEFI_VARS OVMF variable-store template path
EOF
}
while (($#)); do
case "$1" in
--daemon)
daemonize=true
shift
;;
-h|--help)
usage
exit 0
;;
--)
shift
extra_args+=("$@")
break
;;
*)
printf 'Error: unknown option: %s\n' "$1" >&2
usage >&2
exit 2
;;
esac
done
for command_name in qemu-system-x86_64 qemu-img; do
if ! command -v "$command_name" >/dev/null 2>&1; then
printf 'Error: %s is not installed.\n' "$command_name" >&2
exit 1
fi
done
if [[ ! -f "$base_image" ]]; then
if [[ "$uses_shared_base_image" == true ]]; then
"$image_downloader" almalinux10
else
printf 'Error: AlmaLinux base image was not found: %s\n' "$base_image" >&2
exit 1
fi
fi
[[ -f "$base_image" ]] || { printf 'Error: downloader did not create: %s\n' "$base_image" >&2; exit 1; }
for firmware_file in "$uefi_code" "$uefi_vars_template"; do
[[ -f "$firmware_file" ]] || { printf 'Error: required UEFI firmware was not found: %s\n' "$firmware_file" >&2; exit 1; }
done
if [[ ! -f "$seed_image" ]]; then
seed_builder="${script_dir}/seediso/almalinux10/build-seed.sh"
if [[ ! -x "$seed_builder" ]]; then
printf 'Error: seed image is missing and builder is unavailable: %s\n' \
"$seed_builder" >&2
exit 1
fi
printf 'Seed image not found; building %s...\n' "$seed_image"
"$seed_builder" "$seed_image"
fi
mkdir -p "$state_dir"
[[ -f "$uefi_vars" ]] || cp -- "$uefi_vars_template" "$uefi_vars"
if [[ -f "$pid_file" ]]; then
old_pid="$(<"$pid_file")"
if [[ "$old_pid" =~ ^[0-9]+$ ]] && kill -0 "$old_pid" 2>/dev/null; then
printf 'Error: the AlmaLinux virtual machine is already running (PID %s).\n' \
"$old_pid" >&2
exit 1
fi
rm -f "$pid_file"
fi
if [[ ! -f "$disk_image" ]]; then
qemu-img create -q -f qcow2 -F qcow2 -b "$base_image" "$disk_image" "$disk_size"
printf 'Created writable disk overlay: %s\n' "$disk_image"
fi
qemu_args=(
-name almalinux10
-machine q35
-display gtk
-m "$memory"
-smp "$cpus"
-drive "if=pflash,format=raw,readonly=on,file=${uefi_code}"
-drive "if=pflash,format=raw,file=${uefi_vars}"
-drive "file=${disk_image},if=virtio,format=qcow2"
-drive "file=${seed_image},media=cdrom,readonly=on"
-nic "user,model=virtio-net-pci,hostfwd=tcp::${ssh_port}-:22"
)
if [[ -r /dev/kvm && -w /dev/kvm ]]; then
qemu_args+=(-enable-kvm -cpu host)
accelerator=KVM
else
qemu_args+=(-accel tcg -cpu max)
accelerator=TCG
fi
printf 'Starting AlmaLinux 10 with %s acceleration; SSH is forwarded to localhost:%s.\n' \
"$accelerator" "$ssh_port"
if [[ "$daemonize" == true ]]; then
: >"$log_file"
qemu_args+=(
-serial "file:${log_file}"
-monitor none
-daemonize
-pidfile "$pid_file"
)
qemu-system-x86_64 "${qemu_args[@]}" "${extra_args[@]}"
printf 'VM started (PID %s); console log: %s\n' "$(<"$pid_file")" "$log_file"
else
exec qemu-system-x86_64 "${qemu_args[@]}" "${extra_args[@]}"
fi