Work on Metal
Local setup is a work in progress
The host setup and integration steps are not fully verified. Use a disposable host and ask the team if a step fails.
Metal is the Go daemon on each physical host. Atlas decides where a VM belongs and sends the requested state. Metal saves that request, applies it with Firecracker, systemd, ZFS, and Linux networking, then reports what happened. Start with how a VM request works if this boundary is new.
Trace one VM request
The HTTP handler checks and passes the request to the VM manager. The manager writes the desired record before Metal returns success. The reconciler then applies host work and updates the observed record. A reply can arrive before the VM is ready. Reconciliation explains generations, retries, and failures.
For a VM change, start in internal/api, then follow internal/vm into the package that owns the host resource. cmd/metald connects those packages at startup. It should not contain VM policy.
Find the package that owns your change
| If you change... | Start here | Read |
|---|---|---|
| A route or request field | internal/api | Atlas to Metal rules, API reference |
| VM records, generations, or cleanup | internal/vm, internal/reconciler | Reconciliation |
| Boot, stop, console, or Firecracker | internal/firecracker, internal/console, internal/platform | Runtime, console |
| Disks, images, or snapshots | internal/storage | Host storage, host layout |
| Namespaces, routes, firewall, or mesh | internal/network | Host networking |
| Host inventory or capacity | internal/host | Host sync |
| Moving a running VM | internal/vm/migration | Host migration steps |
| Listeners, config, or worker lifetime | cmd/metald | Daemon and API |
Each package has a nearby SPEC.md with its code contract. The Metal specification has the import map. The code map links to entry files and tests.
Keep the ownership boundary clear
The API handles transport, the VM manager owns requested and observed state, and host packages own their resources. Put a rule where its owner can enforce it on every retry.
Build and check a change
Run Go commands from metal/. The eBPF object must exist before a direct Go test because the traffic package embeds it.
cd metal
make bpf
make test
make vet
go test -race ./...
make buildUse gofmt -w <changed-go-files> after editing Go files. make build regenerates Swagger and builds Linux binaries. make openapi generates only Swagger, which Git ignores. eBPF needs Clang 12 or newer and Linux/libbpf headers. TCX traffic monitoring needs Linux 6.6 or newer.
Unit tests can run without a VM host. Boot, network, and firewall checks need host features. The Metal host test guide has the setup and commands. It is still a work in progress.
Check host behavior when it matters
Test both first boot from a fresh clone and later boot from an existing disk. Shared warm memory is valid only for the first case. If your change touches lifecycle or console handling, also test explicit stop, daemon restart with console adoption, and idle save and restore.
Use a disposable host for integration work. The development script changes networking and creates a ZFS pool, systemd unit, guest image, and TLS credentials. Its file-backed pool is a development aid, not a host provisioning design.
Source code and tests
- Metal entry point creates services and listeners.
- VM manager owns accepted VM changes.
- VM reconciler schedules host work.
- Metal Makefile defines generation and checks.
- Host test guide names integration requirements and commands.