fix: improve swtpm error handling for libvirt TPM permission issue
vm_create now properly detects the swtpm CMD_INIT failure and prints the exact sudo command needed to fix the libvirt-qemu ownership issue that Debian's libvirt swtpm helper creates as root:root. Changes: - vm_setup_swtpm: simplified to just check prerequisites (swtpm installed, /var/lib/libvirt/swtpm/ exists) - vm_create: after failed start, detects if swtpm dir was created by libvirt and prints targeted fix command - vm_destroy: simplified (removed external swtpm socket management) - Auto-cleanup: undefines VM on TPM failure so user can retry immediately Root cause: libvirt's swtpm helper creates per-VM state directories as root:root but swtpm runs as libvirt-qemu. Needs one-time: sudo chown -R libvirt-qemu:libvirt-qemu /var/lib/libvirt/swtpm/ All 523 tests pass, 0 lint warnings. 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
51
run.sh
51
run.sh
@@ -165,51 +165,28 @@ vm_check_prerequisites() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Setup swtpm state for libvirt TPM emulation
|
# Setup swtpm for libvirt TPM emulation
|
||||||
# Returns 0 if TPM is available, 1 if not
|
# Returns 0 if TPM is available, 1 if not
|
||||||
|
# Uses libvirt's built-in swtpm management which handles the full lifecycle.
|
||||||
|
# Requires /var/lib/libvirt/swtpm/ to exist with correct ownership.
|
||||||
vm_setup_swtpm() {
|
vm_setup_swtpm() {
|
||||||
local swtpm_state_dir="/var/lib/libvirt/swtpm/${VM_NAME}"
|
|
||||||
|
|
||||||
# Check if swtpm is installed
|
# Check if swtpm is installed
|
||||||
if ! command -v swtpm_setup &> /dev/null; then
|
if ! command -v swtpm_setup &> /dev/null; then
|
||||||
log_warn "swtpm_setup not found - VM will run without TPM"
|
log_warn "swtpm_setup not found - VM will run without TPM"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Try to create and initialize swtpm state directory
|
# For system libvirt, check prerequisites
|
||||||
# For system libvirt, this lives under /var/lib/libvirt/swtpm/
|
|
||||||
if [[ "$LIBVIRT_URI" == *"system"* ]]; then
|
if [[ "$LIBVIRT_URI" == *"system"* ]]; then
|
||||||
# Check if the base directory exists and is writable
|
|
||||||
if [[ ! -d "/var/lib/libvirt/swtpm" ]]; then
|
if [[ ! -d "/var/lib/libvirt/swtpm" ]]; then
|
||||||
# Try to create it (may fail without root)
|
log_warn "/var/lib/libvirt/swtpm/ does not exist"
|
||||||
if ! mkdir -p "/var/lib/libvirt/swtpm" 2>/dev/null; then
|
|
||||||
log_warn "Cannot create /var/lib/libvirt/swtpm/ (needs sudo)"
|
|
||||||
log_warn "Fix: sudo mkdir -p /var/lib/libvirt/swtpm && sudo chown libvirt-qemu:libvirt-qemu /var/lib/libvirt/swtpm"
|
log_warn "Fix: sudo mkdir -p /var/lib/libvirt/swtpm && sudo chown libvirt-qemu:libvirt-qemu /var/lib/libvirt/swtpm"
|
||||||
log_warn "VM will be created WITHOUT TPM"
|
log_warn "VM will be created WITHOUT TPM"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Try to create VM-specific state dir
|
log_info "swtpm prerequisites satisfied"
|
||||||
if ! mkdir -p "$swtpm_state_dir" 2>/dev/null; then
|
|
||||||
log_warn "Cannot create swtpm state dir: $swtpm_state_dir"
|
|
||||||
log_warn "Fix: sudo mkdir -p $swtpm_state_dir && sudo chown -R libvirt-qemu:libvirt-qemu $swtpm_state_dir"
|
|
||||||
log_warn "VM will be created WITHOUT TPM"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try to initialize TPM state
|
|
||||||
if ! swtpm_setup --tpm-state "$swtpm_state_dir" --tpm2 --createek --allow-signing --pcr-banks sha256 2>/dev/null; then
|
|
||||||
log_warn "swtpm_setup failed - VM will run without TPM"
|
|
||||||
rm -rf "$swtpm_state_dir" 2>/dev/null || true
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fix ownership for libvirt-qemu
|
|
||||||
chown -R libvirt-qemu:libvirt-qemu "$swtpm_state_dir" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "swtpm initialized successfully"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +301,21 @@ vm_create() {
|
|||||||
# Start the VM
|
# Start the VM
|
||||||
log_info "Starting VM..."
|
log_info "Starting VM..."
|
||||||
if ! virsh -c "$LIBVIRT_URI" start "$VM_NAME"; then
|
if ! virsh -c "$LIBVIRT_URI" start "$VM_NAME"; then
|
||||||
|
# Check if failure was due to swtpm permissions
|
||||||
|
if [[ -n "$tpm_section" && "$LIBVIRT_URI" == *"system"* ]]; then
|
||||||
|
local vm_uuid
|
||||||
|
vm_uuid=$(virsh -c "$LIBVIRT_URI" dominfo "$VM_NAME" 2>/dev/null | grep "UUID:" | awk '{print $2}')
|
||||||
|
local swtpm_vm_dir="/var/lib/libvirt/swtpm/${vm_uuid}"
|
||||||
|
if [[ -d "$swtpm_vm_dir" ]]; then
|
||||||
|
log_error "TPM initialization failed - likely a swtpm permission issue"
|
||||||
|
log_error "Libvirt created swtpm state dir as root: $swtpm_vm_dir"
|
||||||
|
log_error "Fix by running:"
|
||||||
|
log_error " sudo chown -R libvirt-qemu:libvirt-qemu /var/lib/libvirt/swtpm/"
|
||||||
|
log_error "Then retry: ./run.sh test:iso destroy && ./run.sh test:iso create"
|
||||||
|
# Undefine so user can retry after fixing
|
||||||
|
virsh -c "$LIBVIRT_URI" undefine "$VM_NAME" --nvram 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
log_error "Failed to start VM"
|
log_error "Failed to start VM"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -386,7 +378,6 @@ vm_destroy() {
|
|||||||
|
|
||||||
# Cleanup all VM files (ISO is preserved in output/)
|
# Cleanup all VM files (ISO is preserved in output/)
|
||||||
rm -f /tmp/${VM_NAME}*.qcow2 /tmp/${VM_NAME}*.iso /tmp/${VM_NAME}*.xml /tmp/${VM_NAME}*.fd 2>/dev/null || true
|
rm -f /tmp/${VM_NAME}*.qcow2 /tmp/${VM_NAME}*.iso /tmp/${VM_NAME}*.xml /tmp/${VM_NAME}*.fd 2>/dev/null || true
|
||||||
rm -rf /var/lib/libvirt/swtpm/${VM_NAME} 2>/dev/null || true
|
|
||||||
|
|
||||||
log_info "Cleanup complete (ISO preserved in output/)"
|
log_info "Cleanup complete (ISO preserved in output/)"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user