Commit graph

18 commits

Author SHA1 Message Date
Till Wegmueller
4c73599379 Add with_data_dir constructor to RouterHypervisor
Allows callers to specify a custom data directory for VM work files
(overlays, sockets, console logs) instead of using the default
~/.local/share/vmctl/vms/ path. Needed for container deployments
where the work dir is a mounted volume.
2026-04-07 17:44:53 +02:00
Till Wegmueller
633e76bad1
Add console log tailing module
New `console` module providing `ConsoleTailer` for async serial console
log streaming from VM backends:
- Connects to QEMU's Unix domain socket console
- Streams lines via tokio mpsc channel
- Retries connection (500ms intervals, 30s timeout)
- Graceful shutdown via watch channel
- Fallback `read_console_log()` for post-mortem log file reading

Signed-off-by: Till Wegmueller <toasterson@gmail.com>
2026-04-07 17:18:53 +02:00
Till Wegmueller
245e71fac7 Add console log tailing module
New `console` module providing `ConsoleTailer` for async serial console
log streaming from VM backends:
- Connects to QEMU's Unix domain socket console
- Streams lines via tokio mpsc channel
- Retries connection (500ms intervals, 30s timeout)
- Graceful shutdown via watch channel
- Fallback `read_console_log()` for post-mortem log file reading
2026-04-07 15:41:25 +02:00
Till Wegmueller
302f375f19
Add SSH download function for SFTP file retrieval
Add download() to the ssh module, mirroring the existing upload()
function. Reads a remote file via SFTP and writes it to a local path,
creating parent directories as needed. Used by forge-builder to retrieve
build artifacts from builder VMs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 17:17:38 +01:00
Till Wegmueller
4b29883247
Add OCI artifact pull support for QCOW2 images
- Add oci module with pull_qcow2 using oci-client and custom
  QCOW2 media types (vnd.cloudnebula.qcow2.layer.v1)
- Add ImageSource::Oci variant with oci:// URI scheme parsing
- Add pull_oci method to ImageManager with caching
- Add OciPullFailed error variant with miette diagnostics
- Resolves GITHUB_TOKEN auth automatically for ghcr.io

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:29:16 +01:00
Till Wegmueller
33383e37e9
Fix forger version check to use absolute path
The freshly installed binary may not be in PATH yet during
provisioning, so use the full path to /usr/local/bin/forger.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:46:12 +01:00
Till Wegmueller
2265fca023
Remove docs build output and gitignore docs/book/
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:38:05 +01:00
Till Wegmueller
b37beea0f5
Add mdbook documentation for vmctl and vm-manager
Comprehensive docs covering CLI reference, VMFile.kdl format,
architecture, library API, tutorials, and advanced topics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:37:22 +01:00
Till Wegmueller
7f65305fb8
Fix exec_streaming blocking: run channel.exec() before switching to non-blocking mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:18:02 +01:00
Till Wegmueller
9274f7c47e
Clean up tracing output and infer VM name for ssh command
- Remove timestamps and module targets from tracing output for
  a cleaner CLI experience.
- vmctl ssh now infers the VM name from VMFile.kdl when only one
  VM is defined, so `vmctl ssh` works without arguments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:10:55 +01:00
Till Wegmueller
7cf207a9ec
Stream provision output live and fix generated key permissions
- Add ssh::exec_streaming() that prints stdout/stderr as data arrives
  instead of buffering until command completion. Provision scripts now
  show output in real time without tracing annotation.
- Set 0600 permissions on generated SSH private keys so OpenSSH
  accepts them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:06:06 +01:00
Till Wegmueller
acdf43ae5a
Add console and provision logging, vmctl log command, fix ssh user
- QEMU serial console now logs to console.log in the VM's work
  directory via chardev logfile, so boot and cloud-init output can
  be reviewed after the fact.
- Provision steps stream stdout/stderr through tracing and append
  to provision.log in the work directory.
- vmctl ssh now reads the VMFile ssh block to resolve the user
  (e.g. "smithy") instead of always defaulting to "vm".
- New vmctl log command shows console and/or provision logs with
  optional --tail support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:01:25 +01:00
Till Wegmueller
4cf35c99d0
Generate per-VM Ed25519 SSH keypairs instead of requiring user keys
libssh2 cannot handle all OpenSSH private key formats (e.g. passphrase-
protected or newer ed25519 keys), causing auth failures. Instead of
referencing the user's ~/.ssh keys, generate a fresh Ed25519 keypair at
resolve time when the VMFile omits ssh-key and private-key. The public
key is injected into cloud-init and the private PEM is persisted to the
VM's work directory so that provision, reload, and ssh commands can
reuse it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 23:05:28 +01:00
Till Wegmueller
d9a4206447
Add OmniOS builder VM definition and provisioning scripts
VMFile.kdl defines the omnios-builder VM with cloud-init, SSH config,
and a 3-stage provision pipeline (bootstrap packages + Rust, upload
forger source tarball, build and install forger). Makefile provides
convenience targets wrapping vmctl commands. pack-forger.sh creates a
minimal tarball of just the forger + spec-parser crates and image specs
from refraction-forger for upload to the VM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 22:03:08 +01:00
Till Wegmueller
eb78c24a8b
Add OmniOS builder VM definition and provisioning scripts
VMFile.kdl defines the omnios-builder VM with cloud-init, SSH config,
and a 3-stage provision pipeline (bootstrap packages + Rust, upload
forger source tarball, build and install forger). Makefile provides
convenience targets wrapping vmctl commands. pack-forger.sh creates a
minimal tarball of just the forger + spec-parser crates and image specs
from refraction-forger for upload to the VM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 21:56:43 +01:00
Till Wegmueller
38bc2fa6fb
Add VMFile.kdl declarative VM definitions with up/down/reload/provision commands
Introduce a Vagrantfile-like declarative config format using KDL for defining
multi-VM environments. Includes KDL parsing with validation, a provisioning
engine (shell inline/script + file upload over SSH), and four new CLI commands
for managing VM lifecycles from VMFile.kdl definitions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 20:48:12 +01:00
Till Wegmueller
407baab42f
Make QEMU backend fully functional end-to-end
The scaffolding compiled but couldn't actually run VMs because QEMU
was missing vCPU/memory/networking args, VmHandle didn't persist enough
state for restart, and CLI commands discarded updated handles after
operations.

Key changes:
- Add vcpus, memory_mb, disk_gb, network, ssh_host_port, mac_addr to
  VmHandle with serde(default) for backward compat
- Make NetworkConfig serializable with serde(tag = "type")
- Change Hypervisor trait: start/stop/suspend/resume return Result<VmHandle>
  so backends can return updated PID, VNC addr, etc.
- Complete QEMU start() with -smp, -m, tap/user-mode networking, stale
  socket cleanup, PID reading, and VNC querying via QMP
- Fix guest_ip() to return 127.0.0.1 for user-mode networking and
  filter ARP entries by bridge for tap mode
- Add QMP query_vnc() and fix unwrap() panics in send_command()
- All CLI commands now persist the updated VmHandle after operations
- Add input validation in create with miette diagnostics
- Atomic state persistence (write-to-tmp + rename)
- SSH: port-aware connections, try ed25519/ecdsa/rsa key types
- Enhanced status/list output with vCPUs, memory, network, SSH port
- New tests: NetworkConfig roundtrip, VmHandle roundtrip, backward compat

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 18:58:02 +01:00
Till Wegmueller
9dc492f90f
Add vm-manager library and vmctl CLI
Unified VM management consolidating QEMU-KVM (Linux) and Propolis/bhyve
(illumos) backends behind an async Hypervisor trait, with a vmctl CLI for
direct use and a library API for orchestrators.

- Core library: types, async Hypervisor trait, miette diagnostic errors
- QEMU backend: direct process management, raw QMP client, QCOW2 overlays
- Propolis backend: zone-based VMM with REST API control
- Shared infra: cloud-init NoCloud ISO generation, image download/cache,
  SSH helpers with retry
- vmctl CLI: create, start, stop, destroy, list, status, console, ssh,
  suspend, resume, image pull/list/inspect
- nebula-vm zone brand: lifecycle scripts and platform/config XML for
  illumos zone integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 18:25:17 +01:00