Snapshot a running VM
Checkpoints a running VM into a new snapshot. Creation is
synchronous; the 201 body is the persisted record, already in
state ready, with parent_snapshot_id pointing at the VM’s
previous ready snapshot. mode defaults to manual.
live: false (the default, and the value of an omitted body)
copies the rootfs and nothing else, so restoring cold-boots the
guest. live: true additionally captures the guest’s memory and
vCPU state inside a single pause window, so restoring resumes the
guest where it stopped. It costs the environment’s full configured
memory in bytes on every create, pauses the guest for the length
of the capture, and produces an artifact pinned to the host that
took it.
The response’s kind is what was actually written, not what was
requested. A host running an agent too old to know about live
snapshots answers live: true with a disk snapshot and the record
says disk, so a caller that depends on the memory being present
must read kind rather than assume the request was honoured.
Preconditions are reported as 4xx, not 5xx:
- 404
not_found— unknown VM. - 409
conflict— the VM is not running (e.g. draining), the per-tenant snapshot quota (count or bytes) is exhausted, or the VM holds a GPU passthrough device. A vfio device cannot be checkpointed, so GPU environments can never be snapshotted; this is permanent and must not be retried. A GPU VM asking forlive: truegets this same 409 and the same GPU-specific message, not the 501 below: the device is what cannot be checkpointed, so droppinglivewill not help. - 501
unimplemented— the provider has no snapshot support (e.g. the in-memory stub), orlive: truewas requested against a provider that supports disk snapshots but not live ones. The latter is not a conflict: nothing about the VM’s state is wrong and retrying it unchanged can never succeed, but the same call withoutlivewill, and the message says so. Only Firecracker hosts running an agent new enough to capture memory implement it.
Byte quotas were calibrated against rootfs-only snapshots, so a
workload that switches to live: true reaches the 409 quota case
far sooner than its snapshot count suggests.
/v1/environments/{vmId}/snapshotsAuthorizationBearer token · headerrequiredfuse_sessionAPI key · cookierequiredvmIdstringrequiredapplication/jsoncommentstringmodestringmanualautoretention_secondsinteger<int64>metadataobjectlayer_keystringlivebooleanexport_refstringexport_statusstringpendingreadyerroridstringrequiredvm_idstringrequiredtask_idstringtenant_idstringparent_snapshot_idstringmodestringstatestringcreatingreadyrestoringdeletingerrorcommentstringlayer_keystringarchstringamd64arm64digeststringkindstringdisklivesize_bytesinteger<int64>created_atstring<date-time>requiredupdated_atstring<date-time>retention_untilstring<date-time> | nulllast_errorstringexport_refstringexportsSnapshotExport[]Show propertiesHide properties
SnapshotExportdestinationstringrequiredstatusstringrequested_atstring<date-time>updated_atstring<date-time>last_errorstringerrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjectcurl -X POST "http://localhost:8080/v1/environments/string/snapshots" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"comment": "string",
"mode": "manual",
"retention_seconds": 0,
"metadata": {},
"layer_key": "string",
"live": false,
"export_ref": "string",
"export_status": "pending"
}'const response = await fetch("http://localhost:8080/v1/environments/string/snapshots", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"comment": "string",
"mode": "manual",
"retention_seconds": 0,
"metadata": {},
"layer_key": "string",
"live": false,
"export_ref": "string",
"export_status": "pending"
})
});import requests
response = requests.post(
"http://localhost:8080/v1/environments/string/snapshots",
headers={
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
json={
"comment": "string",
"mode": "manual",
"retention_seconds": 0,
"metadata": {},
"layer_key": "string",
"live": False,
"export_ref": "string",
"export_status": "pending"
},
){
"id": "string",
"vm_id": "string",
"task_id": "string",
"tenant_id": "string",
"parent_snapshot_id": "string",
"mode": "manual",
"state": "creating",
"comment": "string",
"layer_key": "string",
"arch": "amd64",
"digest": "string",
"kind": "disk",
"size_bytes": 0,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"retention_until": "2024-01-01T00:00:00Z",
"last_error": "string",
"export_ref": "string",
"exports": [
{
"destination": "string",
"status": "pending",
"requested_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"last_error": "string"
}
]
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}