Migrate an instance to another node — cold (stopped) or live (running).
curl --request POST \ --url https://stratum.example.com/v1/projects/example/compute/instances/example/actions/migrate \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "targetNodeId": "example", "poolId": "example", "start": true, "mode": "cold" }'Operator-initiated migration to another node. mode selects which, and the
two have inverted prerequisites.
Cold (default,) requires the instance STOPPED and an lvm-thin
root volume: the node-local volume’s raw bytes stream over an mTLS
node-to-node channel, ownership re-points, and the domain is redefined on
the target and booted unless start:false. This is the no-Ceph path to
cluster mobility (maintenance evacuation, manual rebalance).
Live requires the instance RUNNING and a cluster-attachable (Ceph) root volume: no data moves, libvirt copies the guest’s memory peer-to-peer, and the process is preserved across the move. A node-local volume is rejected — it cannot follow the guest.
Provide the target as a raw targetNodeId OR a poolId (resolved to its
owner node; lvm-thin only). Returns 202 + the migration record; poll the
instance state (migrating until the move completes) or the fronting
operation.
On failure the guest is left where it is, running or stopped as it was,
with error on the migration record saying why. A
live migration that fails before the ownership flip never stopped the
source guest, so the instance returns to running on the source, not
stopped. A migration that stops making progress — a destination that dies
mid-copy, a wedged transport — is time-bounded: the platform aborts the
copy and returns the guest to the source rather than leaving it in
migrating indefinitely.
Live migration is not universally transparent — see mode on the
request body for the one connection shape that stalls.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”Migration target and mode. Provide either targetNodeId (a node) OR
poolId (resolved to its owner node; lvm-thin only).
mode selects cold (default) or live. Cold stops the guest: every TCP
connection drops and the OS resumes from boot, which on Ceph is fast but
is still a tenant-visible outage. Live preserves the running process.
Live migration is not universally transparent. A connection where the guest is an idle client waiting on a remote push stalls until the guest next transmits, because connection-tracking state does not move with the port; guests that transmit, and guests serving on a port their security group allows, are unaffected.
object
Destination node. XOR’d with poolId.
Destination pool; resolves to its owner node. XOR’d with targetNodeId.
Boot the instance on the target after the move (false leaves it stopped). Cold only — a live migration never stops the guest, so the value is meaningless there.
Cold requires a stopped instance; live requires a running one. Defaults to cold so an unqualified request never live-migrates a running guest by omission.
Responses
Section titled “Responses”Migration accepted; the leader orchestrator drives it.
A cold-migration record. Poll the instance state for completion.
object
Bytes of the volume copied so far during the streaming phase (the “X” against sizeBytes = “Y”). Absent until streaming starts.
Current copy rate in bytes/sec (for a rate + ETA). Absent until streaming.
When copiedBytes/throughput were last sampled.
When the migration first left pending. Absent on records written before this field existed, so treat its absence as unknown rather than zero.
When the migration reached done or failed. Absent while still in flight; present on a failure too, which is what distinguishes “never started” from “started and failed”.
The peak vCPU throttle libvirt applied to force convergence, as a percentage. Absent until auto-converge engages, which on a lightly dirtying guest is never.
This is the dominant effect a running workload feels during a live migration. The network cutover is around 0.22s and does not drop established connections; a throttled guest can run at a few percent of its normal throughput for tens of seconds, which to a client looks like the server hanging rather than a brief interruption.
Guest memory libvirt is copying.
Bytes still to copy. NOT monotonic: each pre-copy pass re-sends pages dirtied during the previous one, so this can rise. Do not render it as a progress bar that only moves forwards.
Example
{ "state": "pending"}Bad request.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Authenticated but not authorized.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Resource not found.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Conflicting state.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Upstream temporarily unavailable (driver / scheduler / dependency).
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}