#!/bin/bash # KNEL-Football ISO Testing Script # Creates and boots a VM using libvirt/virsh to test the ISO # Runs on HOST system (not inside Docker) # Copyright © 2026 Known Element Enterprises LLC # License: GNU Affero General Public License v3.0 only set -euo pipefail # Configuration variables SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly SCRIPT_DIR readonly VM_NAME="knel-test-$(date +%Y%m%d-%H%M%S)" readonly ISO_PATH="${SCRIPT_DIR}/output/knel-football-secure-v1.0.0.iso" readonly DISK_SIZE="20G" readonly DISK_PATH="/var/lib/libvirt/images/${VM_NAME}.qcow2" readonly RAM="4096" # 4GB RAM readonly VCPUS="2" readonly NETWORK="default" readonly CPU_MODEL="host" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Logging functions log_info() { echo -e "${GREEN}[INFO]${NC} $*" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*" } log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2 } # Usage information usage() { cat < /dev/null; then log_error "virsh not found. Please install libvirt:" echo " Ubuntu/Debian: sudo apt install libvirt-daemon-system virtinst" echo " RHEL/CentOS: sudo yum install libvirt virt-install" exit 1 fi # Check if libvirtd is running if ! virsh list &> /dev/null; then log_error "libvirtd is not running. Please start it:" echo " sudo systemctl start libvirtd" exit 1 fi # Check if ISO exists if [[ ! -f "${ISO_PATH}" ]]; then log_error "ISO not found at: ${ISO_PATH}" log_warn "Please build the ISO first using: ./run.sh iso" exit 1 fi log_info "Prerequisites check passed" } # Create VM create_vm() { log_info "Creating VM: ${VM_NAME}" log_info "ISO: ${ISO_PATH}" log_info "Disk: ${DISK_SIZE} (${DISK_PATH})" log_info "RAM: ${RAM} MB, VCPUs: ${VCPUS}" # Create disk image log_info "Creating disk image..." sudo qemu-img create -f qcow2 "${DISK_PATH}" "${DISK_SIZE}" # Create VM definition log_info "Defining VM..." virt-install \ --name "${VM_NAME}" \ --memory "${RAM}" \ --vcpus "${VCPUS}" \ --cpu "${CPU_MODEL}" \ --disk path="${DISK_PATH}",format=qcow2,bus=virtio \ --cdrom "${ISO_PATH}" \ --network network="${NETWORK}",model=virtio \ --graphics spice \ --video qxl \ --channel unix,target_type=virtio,name=com.redhat.spice.0 \ --sound none \ --noautoconsole \ --os-variant debian12 \ --boot cdrom,hd \ --metadata description="KNEL-Football Secure OS Test VM" log_info "VM created successfully" log_info "Starting VM..." virsh start "${VM_NAME}" log_info "VM is now running" log_info "Connect to console with: $0 console ${VM_NAME}" } # Start VM start_vm() { log_info "Starting VM: ${VM_NAME}" virsh start "${VM_NAME}" log_info "VM started" } # Stop VM stop_vm() { log_info "Stopping VM: ${VM_NAME}" virsh shutdown "${VM_NAME}" log_info "VM shutdown signal sent" } # Connect to console connect_console() { log_info "Connecting to VM console: ${VM_NAME}" log_info "Press Ctrl+] to exit console" virsh console "${VM_NAME}" } # Destroy VM destroy_vm() { log_warn "This will permanently remove VM: ${VM_NAME}" # Check if VM is running if virsh domstate "${VM_NAME}" 2>/dev/null | grep -q "running"; then log_info "Stopping VM..." virsh destroy "${VM_NAME}" fi # Undefine VM log_info "Undefining VM..." virsh undefine "${VM_NAME}" # Remove disk if [[ -f "${DISK_PATH}" ]]; then log_info "Removing disk: ${DISK_PATH}" sudo rm -f "${DISK_PATH}" fi log_info "VM destroyed" } # Show VM status show_status() { log_info "VM Status: ${VM_NAME}" if ! virsh dominfo "${VM_NAME}" 2>/dev/null; then log_error "VM not found: ${VM_NAME}" exit 1 fi echo "" virsh dominfo "${VM_NAME}" echo "" log_info "VM interfaces:" virsh domiflist "${VM_NAME}" || log_warn "No interface information available" } # List all test VMs list_vms() { log_info "Listing KNEL-Football test VMs..." echo "" virsh list --all | grep "knel-test-" || log_warn "No test VMs found" echo "" log_info "Disk images:" sudo ls -lh /var/lib/libvirt/images/knel-test-*.qcow2 2>/dev/null || log_warn "No test disk images found" } # Parse command line arguments COMMAND="" CUSTOM_NAME="" while [[ $# -gt 0 ]]; do case $1 in -h | --help) usage exit 0 ;; -n | --name) CUSTOM_NAME="$2" shift 2 ;; -r | --ram) RAM="$2" shift 2 ;; -c | --cpus) VCPUS="$2" shift 2 ;; -d | --disk) DISK_SIZE="$2" shift 2 ;; create | start | stop | console | destroy | status | list) COMMAND="$1" shift ;; *) if [[ -z "${COMMAND}" ]]; then log_error "Unknown option: $1" usage exit 1 else # VM name for commands that take it CUSTOM_NAME="$1" shift fi ;; esac done # Use custom name if provided if [[ -n "${CUSTOM_NAME}" && "${COMMAND}" != "create" ]]; then VM_NAME="${CUSTOM_NAME}" fi # Set default command COMMAND="${COMMAND:-help}" # Main execution main() { case "${COMMAND}" in create) check_prerequisites create_vm ;; start) check_prerequisites start_vm ;; stop) check_prerequisites stop_vm ;; console) connect_console ;; destroy) destroy_vm ;; status) show_status ;; list) list_vms ;; help|*) usage ;; esac } main