#!/usr/bin/env bash # # qvm-rebuild - Build the base qcow2 image from user's flake # # This script builds the QVM base image by: # - Ensuring a user flake exists (copying default if needed) # - Running nix build on the user's flake configuration # - Copying the resulting qcow2 to the base image location # - Optionally warning if VM is running # set -euo pipefail # Source common library QVM_LIB_DIR="${QVM_LIB_DIR:-$(dirname "$(readlink -f "$0")")/../lib}" # shellcheck source=lib/common.sh source "$QVM_LIB_DIR/common.sh" # # ensure_user_flake - Ensure user's flake exists, copy default if missing # ensure_user_flake() { if [[ -f "$QVM_USER_FLAKE/flake.nix" ]]; then log_info "Using existing user flake: $QVM_USER_FLAKE/flake.nix" return 0 fi log_info "User flake not found, copying default template..." # Determine default flake location # In installed version: $QVM_LIB_DIR/../share/qvm/default-vm/ # In development: $(dirname "$0")/../flake/default-vm/ local default_flake_dir # Try installed location first ($QVM_LIB_DIR is $out/lib/qvm) if [[ -d "$QVM_LIB_DIR/../../share/qvm/default-vm" ]]; then default_flake_dir="$QVM_LIB_DIR/../../share/qvm/default-vm" else # Fall back to development location default_flake_dir="$(dirname "$(readlink -f "$0")")/../flake/default-vm" fi if [[ ! -d "$default_flake_dir" ]]; then die "Default flake template not found at: $default_flake_dir" fi if [[ ! -f "$default_flake_dir/flake.nix" ]]; then die "Default flake.nix not found at: $default_flake_dir/flake.nix" fi # Create user flake directory and copy template mkdir -p "$QVM_USER_FLAKE" cp -r "$default_flake_dir"/* "$QVM_USER_FLAKE/" log_info "Default flake copied to: $QVM_USER_FLAKE" echo "" echo "You can customize your VM by editing: $QVM_USER_FLAKE/flake.nix" echo "" } # # build_vm - Build the VM runner using nix # build_base_image() { log_info "Building VM from flake..." # Build the VM output from user's flake local build_result="$QVM_STATE_DIR/vm-result" if ! nix build "$QVM_USER_FLAKE#vm" --out-link "$build_result"; then die "Failed to build VM. Check your flake configuration at: $QVM_USER_FLAKE/flake.nix" fi # Verify the result contains the VM runner script local vm_runner="$build_result/bin/run-qvm-dev-vm" if [[ ! -f "$vm_runner" ]]; then # Try alternate name pattern vm_runner=$(find "$build_result/bin" -name "run-*-vm" -type f 2>/dev/null | head -1) if [[ -z "$vm_runner" || ! -f "$vm_runner" ]]; then die "Build succeeded but VM runner script not found in: $build_result/bin/" fi fi # Move the result symlink to data dir (keeps nix store reference) rm -f "$QVM_DATA_DIR/vm-result" mv "$build_result" "$QVM_DATA_DIR/vm-result" # Get the basename of the runner script and construct path in new location local runner_name runner_name=$(basename "$vm_runner") vm_runner="$QVM_DATA_DIR/vm-result/bin/$runner_name" # Create a symlink to the VM runner at our standard location log_info "Installing VM runner to: $QVM_VM_RUNNER" rm -f "$QVM_VM_RUNNER" ln -sf "$vm_runner" "$QVM_VM_RUNNER" log_info "VM built successfully" echo "" echo "VM runner: $QVM_VM_RUNNER" } # # warn_if_running - Warn user if VM is currently running # warn_if_running() { if is_vm_running; then log_warn "VM is currently running" echo "" echo "The new base image will only take effect after restarting the VM:" echo " qvm stop" echo " qvm start" echo "" echo "Note: Changes to your VM overlay will be preserved." echo " Use 'qvm reset' to start fresh with the new base image." echo "" fi } # # main - Main execution flow # main() { log_info "Rebuilding QVM base image..." # Ensure required directories exist ensure_dirs # Ensure user has a flake configuration ensure_user_flake # Build the base image build_base_image # Warn if VM is running warn_if_running # Print next steps echo "Next steps:" if is_vm_running; then echo " 1. Stop the VM: qvm stop" echo " 2. Start the VM: qvm start" else echo " - Start the VM: qvm start" fi echo " - Customize the VM: edit $QVM_USER_FLAKE/flake.nix" echo " - Reset to fresh state: qvm reset" } # Run main function main "$@"