Add qvm clean; make rebuild produce VM runner; default qvm run to shell
This commit is contained in:
parent
e766c8466d
commit
601b4ab15e
7 changed files with 395 additions and 249 deletions
141
lib/common.sh
141
lib/common.sh
|
|
@ -23,6 +23,7 @@ readonly QVM_SSH_PORT_FILE="$QVM_STATE_DIR/ssh.port"
|
|||
readonly QVM_SERIAL_LOG="$QVM_STATE_DIR/serial.log"
|
||||
readonly QVM_WORKSPACES_FILE="$QVM_STATE_DIR/workspaces.json"
|
||||
readonly QVM_USER_FLAKE="$QVM_CONFIG_DIR/flake"
|
||||
readonly QVM_VM_RUNNER="$QVM_DATA_DIR/run-vm"
|
||||
|
||||
# Cache directories for 9p mounts (shared between host and VM)
|
||||
readonly QVM_CARGO_HOME="$QVM_CACHE_DIR/cargo-home"
|
||||
|
|
@ -30,17 +31,20 @@ readonly QVM_CARGO_TARGET="$QVM_CACHE_DIR/cargo-target"
|
|||
readonly QVM_PNPM_STORE="$QVM_CACHE_DIR/pnpm-store"
|
||||
readonly QVM_SCCACHE="$QVM_CACHE_DIR/sccache"
|
||||
|
||||
# Host config directories to mount in VM (read-write for tools that need it)
|
||||
readonly QVM_HOST_OPENCODE_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/opencode"
|
||||
|
||||
# Color codes (only used if stdout is a TTY)
|
||||
if [[ -t 1 ]]; then
|
||||
readonly COLOR_INFO='\033[0;36m' # Cyan
|
||||
readonly COLOR_WARN='\033[0;33m' # Yellow
|
||||
readonly COLOR_ERROR='\033[0;31m' # Red
|
||||
readonly COLOR_RESET='\033[0m' # Reset
|
||||
readonly COLOR_INFO='\033[0;36m' # Cyan
|
||||
readonly COLOR_WARN='\033[0;33m' # Yellow
|
||||
readonly COLOR_ERROR='\033[0;31m' # Red
|
||||
readonly COLOR_RESET='\033[0m' # Reset
|
||||
else
|
||||
readonly COLOR_INFO=''
|
||||
readonly COLOR_WARN=''
|
||||
readonly COLOR_ERROR=''
|
||||
readonly COLOR_RESET=''
|
||||
readonly COLOR_INFO=''
|
||||
readonly COLOR_WARN=''
|
||||
readonly COLOR_ERROR=''
|
||||
readonly COLOR_RESET=''
|
||||
fi
|
||||
|
||||
#
|
||||
|
|
@ -48,7 +52,7 @@ fi
|
|||
# Usage: log_info "message"
|
||||
#
|
||||
log_info() {
|
||||
echo -e "${COLOR_INFO}[INFO]${COLOR_RESET} $*" >&2
|
||||
echo -e "${COLOR_INFO}[INFO]${COLOR_RESET} $*" >&2
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -56,7 +60,7 @@ log_info() {
|
|||
# Usage: log_warn "message"
|
||||
#
|
||||
log_warn() {
|
||||
echo -e "${COLOR_WARN}[WARN]${COLOR_RESET} $*" >&2
|
||||
echo -e "${COLOR_WARN}[WARN]${COLOR_RESET} $*" >&2
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -64,7 +68,7 @@ log_warn() {
|
|||
# Usage: log_error "message"
|
||||
#
|
||||
log_error() {
|
||||
echo -e "${COLOR_ERROR}[ERROR]${COLOR_RESET} $*" >&2
|
||||
echo -e "${COLOR_ERROR}[ERROR]${COLOR_RESET} $*" >&2
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -72,8 +76,8 @@ log_error() {
|
|||
# Usage: die "error message"
|
||||
#
|
||||
die() {
|
||||
log_error "$@"
|
||||
exit 1
|
||||
log_error "$@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -81,14 +85,14 @@ die() {
|
|||
# Usage: ensure_dirs
|
||||
#
|
||||
ensure_dirs() {
|
||||
mkdir -p "$QVM_DATA_DIR" \
|
||||
"$QVM_STATE_DIR" \
|
||||
"$QVM_CACHE_DIR" \
|
||||
"$QVM_CONFIG_DIR" \
|
||||
"$QVM_CARGO_HOME" \
|
||||
"$QVM_CARGO_TARGET" \
|
||||
"$QVM_PNPM_STORE" \
|
||||
"$QVM_SCCACHE"
|
||||
mkdir -p "$QVM_DATA_DIR" \
|
||||
"$QVM_STATE_DIR" \
|
||||
"$QVM_CACHE_DIR" \
|
||||
"$QVM_CONFIG_DIR" \
|
||||
"$QVM_CARGO_HOME" \
|
||||
"$QVM_CARGO_TARGET" \
|
||||
"$QVM_PNPM_STORE" \
|
||||
"$QVM_SCCACHE"
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -97,21 +101,21 @@ ensure_dirs() {
|
|||
# Usage: if is_vm_running; then ... fi
|
||||
#
|
||||
is_vm_running() {
|
||||
if [[ ! -f "$QVM_PID_FILE" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local pid
|
||||
pid=$(cat "$QVM_PID_FILE")
|
||||
|
||||
# Check if process exists and is a QEMU process
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
return 0
|
||||
else
|
||||
# Stale PID file, remove it
|
||||
rm -f "$QVM_PID_FILE"
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -f "$QVM_PID_FILE" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local pid
|
||||
pid=$(cat "$QVM_PID_FILE")
|
||||
|
||||
# Check if process exists and is a QEMU process
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
return 0
|
||||
else
|
||||
# Stale PID file, remove it
|
||||
rm -f "$QVM_PID_FILE"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -120,10 +124,10 @@ is_vm_running() {
|
|||
# Usage: port=$(get_ssh_port)
|
||||
#
|
||||
get_ssh_port() {
|
||||
if [[ ! -f "$QVM_SSH_PORT_FILE" ]]; then
|
||||
die "SSH port file not found. Is the VM running?"
|
||||
fi
|
||||
cat "$QVM_SSH_PORT_FILE"
|
||||
if [[ ! -f "$QVM_SSH_PORT_FILE" ]]; then
|
||||
die "SSH port file not found. Is the VM running?"
|
||||
fi
|
||||
cat "$QVM_SSH_PORT_FILE"
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -133,8 +137,8 @@ get_ssh_port() {
|
|||
# Usage: hash=$(workspace_hash "/path/to/workspace")
|
||||
#
|
||||
workspace_hash() {
|
||||
local path="$1"
|
||||
echo -n "$path" | sha256sum | cut -c1-8
|
||||
local path="$1"
|
||||
echo -n "$path" | sha256sum | cut -c1-8
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -145,25 +149,36 @@ workspace_hash() {
|
|||
# Usage: wait_for_ssh "$port" 30
|
||||
#
|
||||
wait_for_ssh() {
|
||||
local port="${1:-}"
|
||||
local timeout="${2:-60}"
|
||||
local elapsed=0
|
||||
|
||||
if [[ -z "$port" ]]; then
|
||||
die "wait_for_ssh requires port argument"
|
||||
fi
|
||||
|
||||
log_info "Waiting for SSH on port $port (timeout: ${timeout}s)..."
|
||||
|
||||
while (( elapsed < timeout )); do
|
||||
if nc -z -w 1 localhost "$port" 2>/dev/null; then
|
||||
log_info "SSH is ready"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
(( elapsed++ ))
|
||||
done
|
||||
|
||||
log_error "SSH did not become available within ${timeout}s"
|
||||
return 1
|
||||
local port="${1:-}"
|
||||
local timeout="${2:-60}"
|
||||
local elapsed=0
|
||||
|
||||
if [[ -z "$port" ]]; then
|
||||
die "wait_for_ssh requires port argument"
|
||||
fi
|
||||
|
||||
log_info "Waiting for SSH on port $port (timeout: ${timeout}s)..."
|
||||
|
||||
while ((elapsed < timeout)); do
|
||||
# Actually attempt SSH connection to verify sshd is responding
|
||||
# nc -z only checks if port is open (QEMU opens it immediately)
|
||||
# We need to verify sshd is actually ready to accept connections
|
||||
if timeout 2 sshpass -p root ssh \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o LogLevel=ERROR \
|
||||
-o PubkeyAuthentication=no \
|
||||
-o PasswordAuthentication=yes \
|
||||
-o ConnectTimeout=1 \
|
||||
-p "$port" \
|
||||
root@localhost "true" 2>/dev/null; then
|
||||
log_info "SSH is ready"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
((elapsed++))
|
||||
done
|
||||
|
||||
log_error "SSH did not become available within ${timeout}s"
|
||||
return 1
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue