diff --git a/.gitignore b/.gitignore index b6a10c3..eccfda7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target other-codes/ +scripts/forger-src.tar.gz diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ba8d697 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +pack-forger: + ./scripts/pack-forger.sh + +up: + cargo run -p vmctl -- up + +down: + cargo run -p vmctl -- down + +provision: + cargo run -p vmctl -- provision + +reload: + cargo run -p vmctl -- reload + +.PHONY: pack-forger up down provision reload diff --git a/VMFile.kdl b/VMFile.kdl new file mode 100644 index 0000000..a9597a2 --- /dev/null +++ b/VMFile.kdl @@ -0,0 +1,32 @@ +vm "omnios-builder" { + image-url "https://downloads.omnios.org/media/stable/omnios-r151056.cloud.qcow2" + vcpus 4 + memory 4096 + disk 20 + + cloud-init { + hostname "omnios-builder" + ssh-key "~/.ssh/id_ed25519.pub" + } + + ssh { + user "smithy" + private-key "~/.ssh/id_ed25519" + } + + // Stage 1: System packages and Rust toolchain + provision "shell" { + script "scripts/bootstrap-omnios.sh" + } + + // Stage 2: Upload forger source + provision "file" { + source "scripts/forger-src.tar.gz" + destination "/tmp/forger-src.tar.gz" + } + + // Stage 3: Extract and build forger + provision "shell" { + script "scripts/install-forger.sh" + } +} diff --git a/scripts/bootstrap-omnios.sh b/scripts/bootstrap-omnios.sh new file mode 100755 index 0000000..0e4353b --- /dev/null +++ b/scripts/bootstrap-omnios.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -euo pipefail + +# OmniOS bootstrap: install system packages and Rust toolchain. +# Adapted from refraction-forger's bootstrap-illumos.sh. + +# --------------------------------------------------------------------------- +# Prefer GNU userland (find, xargs, etc.) on OmniOS. Native /usr/bin tools +# lack options like -maxdepth and xargs -r. +# --------------------------------------------------------------------------- +for d in \ + /usr/gnu/bin \ + /usr/local/gnu/bin \ + /opt/csw/gnu \ + /opt/csw/bin \ + /usr/sfw/bin +do + if [ -d "$d" ]; then + case ":$PATH:" in + *":$d:"*) ;; + *) PATH="$d:$PATH" ;; + esac + fi +done +export PATH + +# --------------------------------------------------------------------------- +# System packages via IPS (pkg) +# --------------------------------------------------------------------------- +if ! command -v pkg >/dev/null 2>&1; then + echo "[bootstrap] pkg not found — expected OmniOS with IPS." >&2 + exit 1 +fi + +echo "[bootstrap] Refreshing package catalog ..." +sudo pkg refresh --full + +echo "[bootstrap] Installing system prerequisites ..." +sudo pkg install -v \ + file/gnu-findutils \ + developer/gcc14 \ + developer/build/gnu-make \ + developer/pkg-config \ + library/security/openssl \ + web/curl \ + compress/unzip \ + developer/versioning/git \ + web/ca-bundle || true + +# --------------------------------------------------------------------------- +# Rust toolchain via rustup +# --------------------------------------------------------------------------- +if ! command -v cargo >/dev/null 2>&1; then + echo "[bootstrap] Installing Rust toolchain via rustup ..." + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ + | sh -s -- -y --profile minimal + # shellcheck disable=SC1091 + source "$HOME/.cargo/env" +fi + +export PATH="$HOME/.cargo/bin:$PATH" + +# --------------------------------------------------------------------------- +# Verify critical tools +# --------------------------------------------------------------------------- +echo "[bootstrap] Verifying installed tools ..." +for tool in gcc cargo rustc pkg-config git curl; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "[bootstrap] ERROR: $tool not found after installation." >&2 + exit 1 + fi + echo " $tool: $(command -v "$tool")" +done + +echo "[bootstrap] OmniOS bootstrap complete." diff --git a/scripts/install-forger.sh b/scripts/install-forger.sh new file mode 100755 index 0000000..c79abda --- /dev/null +++ b/scripts/install-forger.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Extract forger source, build, and install the binary. + +# --------------------------------------------------------------------------- +# Cargo environment +# --------------------------------------------------------------------------- +if [ -f "$HOME/.cargo/env" ]; then + # shellcheck disable=SC1091 + source "$HOME/.cargo/env" +fi +export PATH="$HOME/.cargo/bin:$PATH" + +ARCHIVE="/tmp/forger-src.tar.gz" +DEST="$HOME/forger" + +if [ ! -f "$ARCHIVE" ]; then + echo "[install-forger] Archive not found: $ARCHIVE" >&2 + exit 1 +fi + +# --------------------------------------------------------------------------- +# Extract +# --------------------------------------------------------------------------- +echo "[install-forger] Extracting $ARCHIVE -> $DEST ..." +rm -rf "$DEST" +mkdir -p "$DEST" +tar xzf "$ARCHIVE" -C "$DEST" + +# --------------------------------------------------------------------------- +# Build +# --------------------------------------------------------------------------- +echo "[install-forger] Building forger (release) ..." +cd "$DEST" +cargo build -p forger --release + +# --------------------------------------------------------------------------- +# Install +# --------------------------------------------------------------------------- +echo "[install-forger] Installing /usr/local/bin/forger ..." +sudo install -m 755 -d /usr/local/bin +sudo install -m 755 "$DEST/target/release/forger" /usr/local/bin/forger + +echo "[install-forger] Done." +forger --version || true diff --git a/scripts/pack-forger.sh b/scripts/pack-forger.sh new file mode 100755 index 0000000..5d86e10 --- /dev/null +++ b/scripts/pack-forger.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Pack the forger + spec-parser crates (and OmniOS image specs) into a tarball +# that can be uploaded to the OmniOS builder VM. + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +FORGER_ROOT="$PROJECT_ROOT/other-codes/refraction-forger" +OUTPUT="$SCRIPT_DIR/forger-src.tar.gz" + +if [ ! -d "$FORGER_ROOT" ]; then + echo "refraction-forger not found at $FORGER_ROOT" >&2 + exit 1 +fi + +STAGING="$(mktemp -d)" +trap 'rm -rf "$STAGING"' EXIT + +echo "[pack-forger] Staging forger source ..." + +# Copy crates +cp -a "$FORGER_ROOT/crates/forger" "$STAGING/crates/forger" +cp -a "$FORGER_ROOT/crates/spec-parser" "$STAGING/crates/spec-parser" + +# Copy image specs +cp -a "$FORGER_ROOT/images" "$STAGING/images" + +# Copy lockfile +cp "$FORGER_ROOT/Cargo.lock" "$STAGING/Cargo.lock" + +# Generate a minimal workspace Cargo.toml (only forger + spec-parser) +cat > "$STAGING/Cargo.toml" <<'TOML' +[workspace] +resolver = "2" +members = [ + "crates/forger", + "crates/spec-parser", +] + +[workspace.dependencies] +clap = { version = "4.5", features = ["derive", "env"] } +miette = { version = "7", features = ["fancy"] } +thiserror = "2" +knuffel = "3.2" +tracing = "0.1" +tracing-subscriber = "0.3" +serde = { version = "1.0", features = ["derive"] } +TOML + +echo "[pack-forger] Creating $OUTPUT ..." +tar czf "$OUTPUT" -C "$STAGING" . + +echo "[pack-forger] Done ($(du -h "$OUTPUT" | cut -f1))."