qvm/bin/qvm-rebuild

151 lines
4.5 KiB
Bash
Executable file

#!/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 "$@"