Programmable infrastructure simulation for migration, export, and automation tests — without provisioning the real platform. A real govmomi client can log in, walk inventory, call ExportVm, wait on an HttpNfcLease and resume a broken VMDK download with HTTP Range/206, with Nutanix, Hyper-V, AWS and Azure protocol personas in the same engine.
5 provider personas · Real govmomi export path · Range/206 resume · Deterministic fault scenarios · Apache-2.0, single Go binary
📖 Read the docs — UX, provider architecture, Transiva recipes, and the test matrix.
Chimera is a programmable infrastructure simulation engine for integration-testing migration, discovery, export and automation software without provisioning the real infrastructure platform.
The architecture is provider-persona based: vSphere is the deepest persona (Command Center + govmomi), with Nutanix Prism v3, Hyper-V WS-Man, AWS EC2/EBS, and Azure ARM available as protocol surfaces. Proxmox VE and OpenStack remain on the roadmap.
One engine. Many infrastructure personalities.
Today, the vSphere persona is deliberately much deeper than a simple HTTP mock. A real govmomi client can authenticate with username/password, establish a session, traverse inventory, resolve VMs, create OVF descriptors, call ExportVm, wait on an HttpNfcLease, download a VMDK fixture, retry a broken transfer, and resume with HTTP Range/206 semantics.
Chimera is a test and compatibility appliance. It is not VMware, Nutanix, Microsoft, Amazon, Red Hat, Proxmox or cloud-vendor software, and it is not intended to host production workloads.
| AWS persona | EC2 Describe/Start/Stop, volumes, CreateSnapshot; EBS List/GetSnapshotBlock, SigV4 auth |
| Azure persona | ARM VM list/get/instanceView/start/powerOff; managed disk beginGetAccess + Range SAS, Bearer auth |
| Nutanix Prism v3 persona | Basic auth, cluster identity, VM list/detail, power-state tasks, deterministic disk export |
| Hyper-V WS-Man persona | Identify, Enumerate/Pull of Msvm_ComputerSystem, RequestStateChange |
| Command Center redesign | Multi-page dashboard with persona navigation, Fault Studio and the VMDK Library |
| When this happens… | Chimera gives you… |
|---|---|
| Your migration tool's integration tests need a vCenter nobody wants to license or maintain | A vSphere SOAP/VIM endpoint at /sdk that govmomi clients log into, inventory and export from |
The export code path (OVF, ExportVm, HttpNfcLease, NFC) is never exercised before production |
The exact boundaries implemented, with a generated or real VMDK fixture behind the NFC download |
| Retry and resume logic is only tested when a real transfer happens to break | Deterministic connection drops, 4xx/5xx faults, latency, bandwidth caps and a resume scenario that aborts after 2 MiB |
| You support more than vSphere | Nutanix Prism v3, Hyper-V WS-Man, AWS EC2/EBS and Azure ARM personas in the same engine |
| Downstream conversion needs a disk that actually boots | Real VMDK fixtures per VM, browser upload, and make fixtures for a checksummed Alpine cloud image |
| CI must drive the scenarios without a person in the loop | Admin APIs for faults, scenarios and resets, plus chimera selftest |
Chimera's vSphere persona embeds govmomi's simulator — the same project as vcsim — and builds the test appliance around it.
| Chimera | vcsim (govmomi's vCenter simulator) | |
|---|---|---|
| Form | Test appliance: one binary, .deb/.rpm, Docker, systemd unit |
Go library plus a vcsim binary |
| Platforms | vSphere, plus Nutanix Prism v3, Hyper-V WS-Man, AWS EC2/EBS, Azure ARM | vSphere / vCenter |
| vSphere API | govmomi simulator, plus the OVF / ExportVm / HttpNfcLease / NFC shim |
govmomi simulator |
| Fault injection | Fault Studio and admin API: latency, status codes, NFC failures, stream drops, bandwidth caps | Custom Go method handlers |
| Disk content | Generated stream or real VMDK per VM, browser upload, recursive directory scan | — |
| Dashboard | Embedded Command Center at /__chimera/ |
— |
| License | Apache-2.0 | Apache-2.0 (part of govmomi) |
| Choose vcsim when | Your tests are vSphere-only and you want a Go library inside your test process rather than an appliance |
Chimera is a small, open-source (Apache-2.0) test double for infrastructure platform protocols — it exists so migration/discovery/export/automation software can be integration-tested without a real vCenter, Nutanix cluster, Hyper-V host, AWS account, or Azure subscription. It is not a general HTTP mock framework and not a production infrastructure platform.
| Chimera | vcsim (govmomi's own vCenter simulator) | LocalStack (AWS) | WireMock / Testcontainers | |
|---|---|---|---|---|
| Primary scope | Multi-platform infra persona simulation (vSphere deepest, plus Nutanix/Hyper-V/AWS/Azure) | vSphere/vCenter only | AWS service emulation only | Generic HTTP mocking / real service containers |
| vSphere depth | Full govmomi session + inventory + ExportVm/HttpNfcLease/Range-206 VMDK download |
Similar depth, vSphere-only (from the same govmomi project) | N/A | N/A — you'd hand-write the mock |
| Multi-cloud/platform in one engine | Yes — one engine, five personas | No | No (AWS-only) | N/A (generic) |
| License | Apache-2.0 | Apache-2.0 (part of govmomi) | Apache-2.0 (core) | Apache-2.0 |
(General characterizations as of writing — verify current features against each project's own docs. vcsim specifically is worth evaluating side by side if your integration testing is vSphere-only — Chimera's value is specifically the multi-persona breadth in one engine.)
New here? docs/FAQ.md covers licensing, support, and
scope questions; docs/TROUBLESHOOTING.md
covers real issues with their fix.
+------------------------------------+
| Chimera Command Center |
| personas · inventory · faults · UI |
+------------------+-----------------+
|
/__chimera APIs
|
v
Client / migration tool ---> +---------------------------+
| Chimera public gateway |
| auth path · URL rewrite |
| Range/206 · faults · bw |
+-------------+-------------+
|
+-----------------+-----------------+
| |
v v
+---------------------+ +--------------------+
| vSphere persona | | HTTP personas |
| govmomi simulator | | Nutanix · Hyper-V |
| SOAP/VIM inventory | | AWS · Azure |
+----------+----------+ +--------------------+
| ^
v |
+---------------------+ +--------------------+
| export compatibility| | planned: PVE / |
| OVF · ExportVm · NFC| | OpenStack |
+----------+----------+ +--------------------+
|
v
fixture store
The provider contract and layout are documented in docs/PROVIDER_ARCHITECTURE.md.
cmd/chimera/ CLI: serve, selftest, print-config
internal/config/ config + environment overrides (incl. persona)
internal/lab/ simulator lifecycle + TLS + HTTP persona start
internal/exportshim/ current vSphere OVF/ExportVm/NFC compatibility
internal/fixture/ generated/real VMDK fixture registry
internal/gateway/ public proxy, APIs, Range, faults and embedded UX
internal/faults/ deterministic scenario state
internal/personas/ nutanix, hyperv, aws, azure + shared store
internal/selftest/ govmomi end-to-end probe
integration/ vSphere + Nutanix/Hyper-V + AWS/Azure compatibility tests
docs/ UX, architecture, Transiva guide, test matrix
scripts/ config, scenario, smoke, deploy and packaging helpers
systemd/ systemd unit (used by packages and deploy-remote.sh)
packaging/ nfpm config for .deb/.rpm builds
.github/workflows/ CI + tagged-release packaging
Requirements: Go 1.25+.
go mod tidy
go build -o bin/chimera ./cmd/chimera
./bin/chimera serve -config config.example.jsonExpected output:
Chimera ready
endpoint: http://localhost:8989/sdk
username: administrator@vsphere.local
password: vmware
admin: http://localhost:8989/__chimera/
login: admin / admin
token: chimera-admin
sample VM path: /DC0/vm/DC0_C0_RP0_VM0
⚠ Using default admin credentials (admin/admin), reachable on all interfaces by default —
set CHIMERA_ADMIN_USERNAME/CHIMERA_ADMIN_PASSWORD (or change it in the dashboard's Settings) to change them.
Open the Command Center — / also redirects here:
http://localhost:8989/__chimera/
The browser dashboard itself is a full-page login gate — nothing renders until you log in with admin/admin (printed at startup, changeable from the dashboard's Settings panel or CHIMERA_ADMIN_USERNAME/CHIMERA_ADMIN_PASSWORD). That's a frontend-only gate, though: the underlying read APIs (health, bootstrap, inventory, telemetry, VMDK list) stay public in the disposable lab regardless, so scripts/CI can still poll them directly without a token. Chimera listens on 0.0.0.0 by default, so change the admin login before exposing an instance beyond your own machine.
Run the end-to-end client probe:
./bin/chimera selftest \
-url http://localhost:8989/sdk \
-user administrator@vsphere.local \
-pass vmwareThe self-test performs login → datacenter discovery → VM inventory → ExportVm → lease wait → NFC read → lease complete. By default it only reads the first 4KB; pass -vm <name> to target a specific VM and -save <path> to download the complete disk instead (see scripts/verify-real-fixture.sh for a full worked example against a real fixture).
Prebuilt packages (Linux amd64/arm64): grab the .deb or .rpm from the latest release, then:
sudo apt install ./chimera_*.deb # Debian/Ubuntu
sudo dnf install ./chimera-*.rpm # Fedora/RHEL/Alma
sudo systemctl enable --now chimeraThis installs the binary to /usr/bin/chimera, a systemd unit (systemd/chimera.service), and an env file at /etc/chimera/chimera.env. Logs go to the journal (journalctl -u chimera or -t chimera).
Remote host, from source: ./scripts/deploy-remote.sh <host> [user] cross-compiles and installs Chimera as a systemd service over SSH — no Go toolchain needed on the target. See --help for options.
Build packages yourself: make package (needs nfpm) builds .deb/.rpm into dist/ from packaging/nfpm.yaml.
docker compose up --buildIf the client is in another container or host, set CHIMERA_PUBLIC_HOST to an address reachable from the client. Export lease URLs embed this value.
Open http://localhost:8989/__chimera/ after starting the engine.
The embedded, zero-dependency dashboard is a full infrastructure command center:
- premium dark control-plane shell with provider-persona navigation, a foldable sidebar, and full-width stacked panels for readability
- six live KPIs: requests, error rate, active sessions, transferred bytes, exports and response latency
- simulator health ring, uptime and build/version status
- visual datacenter → cluster → host → datastore topology, with a full-screen zoomable view
- traffic-activity donut driven by real gateway request classes
- live request feed with method, path, HTTP status and duration
- searchable/paginated VM inventory with power-state filters, export selection, and a per-VM Fixture badge (real file vs. synthetic)
- VMDK Library: upload a
.vmdkstraight from the browser, or browse and pin a file already staged on the host — with an optional manual VM assignment that overrides the automatic name/round-robin matching.fixture_vmdk_dirscanning recurses into subdirectories and supports additional read-only watch directories - deterministic scenario launcher for clean, slow, flaky and resume paths
- slide-over Fault Studio for latency, status codes, API/NFC failures, stream drops and bandwidth caps
- real username/password login (default
admin/admin, changeable from the dashboard's Settings panel) gating every mutating control - a Settings panel showing the listen address and letting an operator change the admin login live, no restart needed
- responsive desktop/tablet/mobile UI
- no Node/npm runtime and no external CDN dependencies
See docs/UX.md.
- vSphere SOAP/VIM endpoint at
/sdk - strict username/password authentication and session cookies
- service content + property collector
- datacenters, clusters, hosts, resource pools, datastores, networks and VMs
- VM discovery through govmomi
OvfManager.CreateDescriptorVirtualMachine.ExportVmHttpNfcLeaseready/completion/abort/progress behavior- generated or operator-supplied VMDK fixture
- NFC download URLs
- HTTP
Range/ 206 resume behavior - deterministic connection drops, 4xx/5xx faults, latency and bandwidth limits
- self-signed HTTPS option (
CHIMERA_TLS=true) - admin health/state/scenario APIs, gated by a real login (default
admin/admin, changeable)
Select with "persona" in config or CHIMERA_PERSONA. These serve protocol endpoints only (no Command Center yet):
| Persona | Endpoint | Coverage |
|---|---|---|
| Nutanix Prism | /api/nutanix/v3 |
Basic auth, cluster identity, VM list/detail, power-state tasks, deterministic disk export |
| Microsoft Hyper-V | /wsman |
WS-Man Identify, Enumerate/Pull of Msvm_ComputerSystem, RequestStateChange |
CHIMERA_PERSONA=nutanix CHIMERA_USERNAME=admin CHIMERA_PASSWORD=secret go run ./cmd/chimera serve
CHIMERA_PERSONA=hyperv CHIMERA_USERNAME=Administrator CHIMERA_PASSWORD=secret go run ./cmd/chimera serveProtocol-only cloud surfaces (SigV4 / Bearer). Details: docs/AWS_AZURE_PERSONAS.md.
| Persona | Auth | Coverage |
|---|---|---|
| AWS | SigV4 (CHIMERA_USERNAME=access key, CHIMERA_PASSWORD=secret) |
EC2 Describe/Start/Stop, volumes, CreateSnapshot; EBS List/GetSnapshotBlock |
| Azure | Bearer (CHIMERA_USERNAME=subscription ID, CHIMERA_PASSWORD=token) |
ARM VM list/get/instanceView/start/powerOff; managed disk beginGetAccess + Range SAS |
CHIMERA_PERSONA=aws CHIMERA_USERNAME=AKIDCHIMERA CHIMERA_PASSWORD=chimera-secret go run ./cmd/chimera serve
CHIMERA_PERSONA=azure CHIMERA_USERNAME=11111111-2222-3333-4444-555555555555 CHIMERA_PASSWORD=chimera-azure-token go run ./cmd/chimera serveTransiva's vSphere provider uses govmomi for normal login and inventory. Its export flow creates an OVF descriptor, calls vm.Export(), waits for the lease, and downloads each lease item. When a partial local file exists, Transiva sends Range: bytes=N-. Chimera implements those exact boundaries so Transiva can exercise its production code path without requiring a physical vCenter.
./scripts/make-transiva-config.sh > /tmp/transiva-chimera.yaml
cd ../transiva
./scripts/build.sh
./bin/hyperexport --config /tmp/transiva-chimera.yamlChoose DC0_C0_RP0_VM0 or another VM shown by the Command Center. See docs/TRANSIVA.md for detailed retry/resume recipes.
With fixture_vmdk empty, Chimera creates a deterministic byte stream of fixture_size_mb and exposes it as disk-0.vmdk. This is ideal for testing authentication, inventory, leases, parallel transfers, retries, checkpoints and HTTP Range behavior.
The generated bytes are intentionally not a valid VMDK.
To exercise downstream conversion paths such as qemu-img/h2kvm, supply a non-sensitive test VMDK:
CHIMERA_FIXTURE_VMDK=/lab/fixtures/ubuntu-test.vmdk \
./bin/chimera serve -listen 0.0.0.0:8989Chimera never modifies the supplied fixture.
Under the systemd unit installed by scripts/deploy-remote.sh, the fixture path must live outside /home and /root. The unit runs with DynamicUser=yes and ProtectHome=yes, which makes those trees invisible to the service regardless of file permissions — chimera.service will start fine but silently fall back to the generated fixture if CHIMERA_FIXTURE_VMDK/_DIR points under a user's home directory. Stage real fixtures somewhere like /opt/chimera-fixtures/ instead, set CHIMERA_FIXTURE_VMDK in /etc/chimera/chimera.env to that path, and systemctl restart chimera.
Point at a directory instead of a single file to give each simulated VM its own disk:
CHIMERA_FIXTURE_VMDK_DIR=/lab/fixtures \
./bin/chimera serve -listen 0.0.0.0:8989Matching is a three-pass process: any file explicitly pinned to a VM (see "Manual assignment" below) wins first; then a file named after a VM (e.g. DC0_C0_RP0_VM0.vmdk, matched on its own basename even when nested in a subdirectory) is assigned to that VM; any leftover files and VMs are then paired off in sorted order. VMs that still get nothing keep the default generated fixture. Mutually exclusive with fixture_vmdk. The directory is scanned recursively and re-scanned automatically every 5 seconds — drop in (or remove) a file anywhere under it, at any depth, and it's picked up without restarting the server. See the VMDK Library panel in the Command Center, or GET /__chimera/api/vmdks, to see the resulting assignment.
Additional read-only directories can be scanned the same way via fixture_vmdk_dirs / CHIMERA_FIXTURE_VMDK_DIRS (comma-separated) — useful when fixtures live in more than one place on the host. Uploads through the dashboard always land in the primary fixture_vmdk_dir; the extra directories only ever contribute files an operator staged there directly.
Manual assignment — from the dashboard's VMDK Library card, either upload a .vmdk directly from the browser, or browse and pick a file already staged on the host, and optionally assign it to a specific VM. That assignment overrides the automatic name/round-robin matching (reported as manual in GET /__chimera/api/vmdks) until cleared. The host browser is hard-scoped to the configured fixture directories — it can never reveal an arbitrary path on the host.
Don't have a real VMDK handy? make fixtures fetches a small, official, checksummed Alpine Linux cloud image and converts it to VMDK automatically (see scripts/fetch-sample-fixtures.sh):
make fixtures
CHIMERA_FIXTURE_VMDK_DIR=./fixtures ./bin/chimera serve -listen 0.0.0.0:8989scripts/verify-real-fixture.sh proves the whole path end-to-end: it exports the assigned VM's disk through the real NFC download (not just selftest's 4KB probe) and confirms qemu-img info recognizes the result as a valid disk image.
For the full downstream chain — Chimera → transiva-export → h2kvm conversion → libvirt boot — see ../transiva/scripts/e2e-chimera-migrate-remote.sh. It stages a real fixture (working around the ProtectHome restriction above), runs chimera selftest, exports the disk, and submits it to transivad as a normal migration job so h2kvmctl (not the script) owns conversion, emit_domain_xml, virsh_define and the post-boot check.
| JSON | Environment | Default |
|---|---|---|
persona |
CHIMERA_PERSONA |
vsphere (nutanix, hyperv, aws, azure) |
listen |
CHIMERA_LISTEN |
0.0.0.0:8989 |
public_host |
CHIMERA_PUBLIC_HOST |
listener address |
tls |
CHIMERA_TLS |
false |
username |
CHIMERA_USERNAME |
administrator@vsphere.local |
password |
CHIMERA_PASSWORD |
vmware |
datacenters |
CHIMERA_DATACENTERS |
1 |
clusters |
CHIMERA_CLUSTERS |
1 |
hosts_per_dc |
CHIMERA_HOSTS_PER_DC |
0 |
hosts_per_cluster |
CHIMERA_HOSTS_PER_CLUSTER |
1 |
datastores |
CHIMERA_DATASTORES |
1 |
vms_per_pool |
CHIMERA_VMS_PER_POOL |
3 |
soap_delay_ms |
CHIMERA_SOAP_DELAY_MS |
0 |
admin_token |
CHIMERA_ADMIN_TOKEN |
chimera-admin |
admin_username |
CHIMERA_ADMIN_USERNAME |
admin |
admin_password |
CHIMERA_ADMIN_PASSWORD |
admin |
fixture_vmdk |
CHIMERA_FIXTURE_VMDK |
generated fixture |
fixture_vmdk_dir |
CHIMERA_FIXTURE_VMDK_DIR |
generated fixture |
fixture_vmdk_dirs |
CHIMERA_FIXTURE_VMDK_DIRS (comma-separated) |
none |
fixture_size_mb |
CHIMERA_FIXTURE_SIZE_MB |
16 |
username/password are the simulated vCenter login used by API clients (govc, Transiva, etc.) — unrelated to admin_username/admin_password, which gate the Chimera dashboard's own login.
Public read endpoints (plus the login exchange below):
GET /__chimera/health
GET /__chimera/api/bootstrap
GET /__chimera/api/inventory
GET /__chimera/api/vmdks
GET /__chimera/api/telemetry
POST /__chimera/login
GET /__chimera/api/telemetry returns gateway-derived live metrics and a bounded recent-request feed. Dashboard polling under /__chimera is intentionally excluded from those counters so the UI does not create its own traffic metrics.
POST /__chimera/login exchanges an {"username","password"} body (default admin/admin) for the admin bearer token — this is what the dashboard's login form calls; scripts can call it directly too, or just use the token printed at startup.
Every other endpoint is protected and requires:
Authorization: Bearer chimera-admin
Available protected operations:
GET /__chimera/state
POST /__chimera/faults
POST /__chimera/reset
POST /__chimera/scenario/clean
POST /__chimera/scenario/slow
POST /__chimera/scenario/flaky
POST /__chimera/scenario/resume
POST /__chimera/admin/credentials # change the dashboard login: {"username","password"}
POST /__chimera/api/vmdks/upload # multipart "file" (+optional "vm_name") into fixture_vmdk_dir
GET /__chimera/api/vmdks/browse # ?root=<index>&path=<relative> — list files under a configured fixture root
POST /__chimera/api/vmdks/assign # {"root","file_name","vm_name"} — pin a file already on disk to a VM
Example fault policy:
curl -X POST \
-H 'Authorization: Bearer chimera-admin' \
-H 'Content-Type: application/json' \
http://localhost:8989/__chimera/faults \
-d '{
"latency_ms":250,
"fail_next":1,
"fail_status":503,
"nfc_fail_next":1,
"nfc_drop_next":1,
"nfc_drop_after_bytes":2097152,
"bandwidth_bytes_per_sec":1048576
}'Built-in scenarios:
./scripts/scenario.sh clean
./scripts/scenario.sh slow
./scripts/scenario.sh flaky
./scripts/scenario.sh resumeThe resume scenario aborts the next export stream after 2 MiB. A compatible client can retry with Range: bytes=N- and continue from the partial offset.
make test
make buildThen:
make run
./bin/chimera selftest \
-url http://localhost:8989/sdk \
-user administrator@vsphere.local \
-pass vmwareSee docs/TEST_MATRIX.md for the acceptance matrix.
docs/FAQ.md— licensing, support, scope questionsdocs/TROUBLESHOOTING.md— real issues, with the fix
Persona depth, stated honestly: only vSphere is deep today ("implemented" per the roadmap table below). Nutanix Prism v3, Hyper-V WS-Man, AWS EC2/EBS, and Azure ARM are "available" as protocol surfaces only — no Command Center yet. Proxmox VE and OpenStack remain on the roadmap, not started.
| Persona | Status | Target compatibility |
|---|---|---|
| VMware vSphere | Implemented | SOAP / VIM / OVF / HTTP NFC |
| Nutanix Prism | Available | Prism v3 auth / inventory / power / disk export |
| Microsoft Hyper-V | Available | WS-Man Identify / Enumerate / Pull / power |
| Amazon Web Services | Available | EC2 Query + EBS snapshot blocks (SigV4) |
| Microsoft Azure | Available | ARM Compute + managed disk SAS (Bearer) |
| Proxmox VE | Planned | PVE REST API / tasks / storage |
| OpenStack | Planned | Keystone / Nova / Glance / Cinder |
| Product | Role next to Chimera |
|---|---|
| Chimera | Infrastructure protocol simulator for integration tests |
| Transiva | VM migration; Chimera implements the exact govmomi export boundaries Transiva's vSphere provider uses (guide) |
| h2kvm | Disk conversion downstream of Transiva in the Chimera → Transiva → h2kvm → libvirt end-to-end chain |
| Argus | Autonomous QA; pairs with Chimera when the app under test talks to an infrastructure API |
Issues and PRs are welcome. make verify runs the same checks as CI (build, vet, tests, gofmt, and a syntax check on the embedded dashboard JS) — run it before opening a PR.
Free under Apache-2.0. If it helps you, you can donate any amount you like: https://rzp.io/rzp/utwdYh3. A donation is voluntary and supports development and maintenance. It is not a purchase: it buys no support, SLA, features, priority or license, and it is not tax-deductible (Zyvor AI Labs Private Limited is a company, not a charity). Support contracts are separate: sales@zyvor.dev.
Chimera is free and open source under the Apache License, Version 2.0 (see NOTICE). You may use, modify, and run it for personal, lab, and commercial production use at no charge, subject to Apache-2.0 (preserve notices / NOTICE where required). That does not change.
Zyvor Enterprise adds what production teams ask for: supported releases, deployment and upgrade guidance, priority incident triage, a named technical contact and 24x7 critical intake. Plans and terms: docs/SUBSCRIPTION-MODEL.md · Pricing · sales@zyvor.dev.
Social assets: docs/social/.



