@shrug/xen-orchestra
Xen Orchestra (XO) / XCP-NG VM lifecycle swamp model. Provisions and
controls a VM on an XCP-NG host through XO's REST API (/rest/v0) so the VM is
a first-class swamp resource — created, started, stopped, snapshotted, and
destroyed through model methods rather than by hand. Built to stand up the
always-on swamp serve orchestrator VM (design:
design/serve-orchestrator-vm.md, Phase 0).
Structural sibling of @kneel/bugzilla: plain HTTPS through one injectable
fetch seam (xoRequest), a vaulted credential, and versioned snapshot
resources. No curl; TLS verification is always on.
Config
| arg | default | notes |
|---|---|---|
baseUrl |
https://localhost:3443 |
no trailing slash; REST lives under /rest/v0. Point at the hostname the cert is issued for (an SSH-tunnel localhost URL fails hostname verification once a real cert is in place). |
authToken |
— | sensitive; vault.get("xo-auth-token","token"). Sent as the authenticationToken cookie. Mint once out of band (see below). |
poolId |
"" |
XO pool UUID for create (resolve via listPools). |
caCert |
— | sensitive; PEM of a CA to trust (e.g. FreeIPA) for XOA's cert. Verification stays on. Unneeded for a publicly-trusted cert. |
requestTimeoutMs |
120000 |
per-request timeout (long create tasks). |
Minting an auth token
The REST API has an endpoint for it; basic auth is used only here, to bootstrap the token:
curl -u '<xo-user>:<xo-pass>' -X POST \
https://<xo-host>/rest/v0/users/authentication_tokens \
-H 'content-type: application/json' \
-d '{"description":"swamp xen-orchestra","expiresIn":"1 year"}'
→ 201 with the token. Or in the XO web UI: user menu → profile →
Authentication Tokens → New token. Store it in the vault; the extension
sends it as the authenticationToken cookie.
Methods
| method | REST | notes |
|---|---|---|
create |
POST /pools/{poolId}/actions/create_vm?sync=true |
clone a template, inject cloud-init (cloud_config/network_config), record the vm snapshot. sync=false polls a task instead. |
start |
POST /vms/{id}/actions/start |
then refresh the vm snapshot. |
stop |
POST /vms/{id}/actions/{clean,hard}_shutdown |
force=true → hard power-off. |
snapshot |
POST /vms/{id}/actions/snapshot |
body {name_label}. |
destroy |
DELETE /vms/{id} |
verifies the VM exists first (Rule 5). |
get |
GET /vms/{id} |
refresh the vm live-state snapshot. |
listTemplates / listPools / listSRs / listNetworks |
GET /vm-templates · /pools · /srs · /networks |
resolve UUIDs into an inventory snapshot rather than hardcoding. |
Resources
vm— a managed VM's normalized live state (uuid,name_label,power_state,mainIpAddress,cpus,memory,poolId,raw).inventory— a discovery listing (kind,count,items[{uuid,name_label}]) for UUID resolution.
Rocky Linux 9 bootstrap
create passes cloud_config (user-data: hostname, SSH keys, packages) and
network_config (static IP or DHCP) as cloud-init content strings. The
template must have cloud-init installed. Post-boot guest configuration (the
swamp serve systemd unit, EnvironmentFile, dnf) is handled separately over
SSH via @adam/cfgmgmt.
Testing
deno test -A extensions/models/xen_orchestra_test.ts
Every method is exercised through a mocked fetch seam — no live XO is
touched. A live smoke check (listTemplates against a real instance) confirms
auth + connectivity.