diff --git a/run.sh b/run.sh index 24e38c5..32c57e0 100755 --- a/run.sh +++ b/run.sh @@ -86,19 +86,22 @@ vm_create_disk() { # Create and start VM vm_create() { - log_info "Creating VM: $VM_NAME" - - # Destroy existing VM if present - virsh destroy "$VM_NAME" 2>/dev/null || true - virsh undefine "$VM_NAME" 2>/dev/null || true - + # Define libvirt session URI (use session for user-mode, avoids sudo) + local LIBVIRT_URI="qemu:///session" + + log_info "Creating VM: $VM_NAME (libvirt: $LIBVIRT_URI)" + + # Destroy existing VM if present (in session libvirt) + virsh -c "$LIBVIRT_URI" destroy "$VM_NAME" 2>/dev/null || true + virsh -c "$LIBVIRT_URI" undefine "$VM_NAME" --nvram 2>/dev/null || true + # Create disk vm_create_disk - + # Find UEFI firmware with Secure Boot support (REQUIRED) local uefi_code="" local uefi_vars="" - + # Prefer Secure Boot enabled firmware for fw_dir in /usr/share/OVMF /usr/share/qemu; do if [[ -f "$fw_dir/OVMF_CODE_4M.secboot.fd" ]]; then @@ -115,116 +118,129 @@ vm_create() { break fi done - + if [[ -z "$uefi_code" || ! -f "$uefi_code" ]]; then log_error "UEFI firmware with Secure Boot (OVMF) not found" log_error "Install required: sudo apt install ovmf" log_error "UEFI with Secure Boot is REQUIRED for KNEL-Football testing" return 1 fi - + # Create copy of OVMF_VARS for this VM (Secure Boot state stored here) - local vm_vars="/tmp/${VM_NAME}_OVMF_VARS.fd" + local vm_vars="/tmp/${VM_NAME}_VARS.fd" cp "$uefi_vars" "$vm_vars" - + if [[ "$uefi_code" == *".secboot.fd" ]]; then log_info "Using UEFI firmware with Secure Boot: $uefi_code" else log_warn "Using UEFI firmware WITHOUT Secure Boot: $uefi_code" log_warn "For full Secure Boot testing, install: sudo apt install ovmf" fi - - # Try virt-install first, fall back to direct QEMU - if virt-install \ - --connect qemu:///session \ - --name "$VM_NAME" \ - --ram "$VM_RAM" \ - --vcpus "$VM_CPUS" \ - --disk path="$VM_DISK_PATH",format=qcow2 \ - --cdrom "$ISO_PATH" \ - --os-variant debian12 \ - --network user \ - --graphics vnc,listen=0.0.0.0 \ - --boot uefi \ - --noautoconsole \ - --virt-type kvm 2>&1; then - log_info "VM created via virt-install (UEFI mode)" - else - log_warn "virt-install failed, using direct QEMU with UEFI..." - - # Use QEMU directly with UEFI firmware - qemu-system-x86_64 \ - -name "$VM_NAME" \ - -m "$VM_RAM" \ - -smp "$VM_CPUS" \ - -drive file="$VM_DISK_PATH",format=qcow2,if=virtio \ - -cdrom "$ISO_PATH" \ - -netdev user,id=net0 \ - -device virtio-net-pci,netdev=net0 \ - -vnc :0 \ - -drive if=pflash,format=raw,readonly=on,file="$uefi_code" \ - -drive if=pflash,format=raw,file="$vm_vars" \ - -enable-kvm \ - -daemonize \ - -pidfile "/tmp/${VM_NAME}.pid" - log_info "VM started via QEMU with UEFI (PID: $(cat /tmp/${VM_NAME}.pid 2>/dev/null || echo 'unknown'))" + + # Determine secure boot setting + local secure_boot="no" + if [[ "$uefi_code" == *".secboot.fd" ]]; then + secure_boot="yes" fi + + # Use persisted XML template + local template="${SCRIPT_DIR}/vm/template.xml" + if [[ ! -f "$template" ]]; then + log_error "VM template not found: $template" + return 1 + fi + + # Generate dynamic values + local vm_uuid + if command -v uuidgen &> /dev/null; then + vm_uuid=$(uuidgen) + else + vm_uuid=$(cat /proc/sys/kernel/random/uuid) + fi + local mac_address="52:54:00:$(od -An -N3 -tx1 /dev/urandom | tr ' ' ':' | cut -c2-13)" + + # Create VM XML from template + local vm_xml="/tmp/${VM_NAME}.xml" + sed -e "s|@VM_NAME@|${VM_NAME}|g" \ + -e "s|@VM_UUID@|${vm_uuid}|g" \ + -e "s|@VM_RAM@|${VM_RAM}|g" \ + -e "s|@VM_CPUS@|${VM_CPUS}|g" \ + -e "s|@SECURE_BOOT@|${secure_boot}|g" \ + -e "s|@UEFI_CODE@|${uefi_code}|g" \ + -e "s|@UEFI_VARS@|${vm_vars}|g" \ + -e "s|@VM_DISK@|${VM_DISK_PATH}|g" \ + -e "s|@ISO_PATH@|${ISO_PATH}|g" \ + -e "s|@MAC_ADDRESS@|${mac_address}|g" \ + "$template" > "$vm_xml" + + # Define and START the VM + if ! virsh -c "$LIBVIRT_URI" define "$vm_xml"; then + log_error "Failed to define VM from XML" + return 1 + fi + + if ! virsh -c "$LIBVIRT_URI" start "$VM_NAME"; then + log_error "Failed to start VM" + return 1 + fi + + # Get VNC display info + local vnc_display + vnc_display=$(virsh -c "$LIBVIRT_URI" vncdisplay "$VM_NAME" 2>/dev/null) + + log_info "VM created and STARTED successfully" + log_info "VNC display: $vnc_display" + log_info "" + log_info "To connect in virt-manager:" + log_info " 1. Open virt-manager" + log_info " 2. File → Add Connection" + log_info " 3. Enter URI: qemu:///session" + log_info " 4. Connect and double-click '$VM_NAME'" } # Connect to VM console vm_console() { + local LIBVIRT_URI="qemu:///session" log_info "Connecting to VM console..." - virsh console "$VM_NAME" + virsh -c "$LIBVIRT_URI" console "$VM_NAME" } # Get VM status vm_status() { + local LIBVIRT_URI="qemu:///session" log_info "VM Status for: $VM_NAME" - virsh dominfo "$VM_NAME" 2>/dev/null || log_error "VM not running" + virsh -c "$LIBVIRT_URI" dominfo "$VM_NAME" 2>/dev/null || log_error "VM not running" } # Check if VM is running vm_is_running() { - # Check virsh first - if virsh domstate "$VM_NAME" 2>/dev/null | grep -q "running"; then + local LIBVIRT_URI="qemu:///session" + # Check virsh session + if virsh -c "$LIBVIRT_URI" domstate "$VM_NAME" 2>/dev/null | grep -q "running"; then return 0 fi - # Check QEMU pidfile - if [[ -f "/tmp/${VM_NAME}.pid" ]]; then - local pid - pid=$(cat "/tmp/${VM_NAME}.pid") - if kill -0 "$pid" 2>/dev/null; then - return 0 - fi - fi return 1 } # Capture boot screenshot vm_capture_screen() { + local LIBVIRT_URI="qemu:///session" local output_dir="${SCRIPT_DIR}/tmp/vm-screenshots" mkdir -p "$output_dir" - + log_info "Capturing boot screen..." - virsh screenshot "$VM_NAME" "${output_dir}/boot-screen.ppm" 2>/dev/null || { + virsh -c "$LIBVIRT_URI" screenshot "$VM_NAME" "${output_dir}/boot-screen.ppm" 2>/dev/null || { log_warn "Could not capture screenshot" } } # Destroy VM and cleanup vm_destroy() { + local LIBVIRT_URI="qemu:///session" log_info "Destroying VM: $VM_NAME" - # Try virsh first - virsh destroy "$VM_NAME" 2>/dev/null || true - virsh undefine "$VM_NAME" 2>/dev/null || true - # Kill QEMU process if running - if [[ -f "/tmp/${VM_NAME}.pid" ]]; then - local pid - pid=$(cat "/tmp/${VM_NAME}.pid") - kill "$pid" 2>/dev/null || true - rm -f "/tmp/${VM_NAME}.pid" - fi - rm -f "$VM_DISK_PATH" + virsh -c "$LIBVIRT_URI" destroy "$VM_NAME" 2>/dev/null || true + virsh -c "$LIBVIRT_URI" undefine "$VM_NAME" --nvram 2>/dev/null || true + rm -f "$VM_DISK_PATH" "/tmp/${VM_NAME}_VARS.fd" "/tmp/${VM_NAME}.xml" log_info "Cleanup complete" } diff --git a/vm/template.xml b/vm/template.xml new file mode 100644 index 0000000..ab31872 --- /dev/null +++ b/vm/template.xml @@ -0,0 +1,55 @@ + + @VM_NAME@ + @VM_UUID@ + @VM_RAM@ + @VM_RAM@ + @VM_CPUS@ + + hvm + @UEFI_CODE@ + @UEFI_VARS@ + + + + + + + + + + + + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + + + + + + + + + + + + +