Skip to content

Update a node's display name or its reservation.

PATCH
/v1/compute/nodes/{nodeId}
Code sample: Shell / cURL
curl --request PATCH \
--url https://stratum.example.com/v1/compute/nodes/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "name": "example", "reservedVCPUs": 1, "reservedMemoryBytes": 1, "reservationSource": "computed" }'

Mutates the name field on a registered node. Sticky: the controlplane writes the new value to /var/lib/stratum/node-name so the vmagent node_name label and downstream surfaces (log-stream displayName) reflect the change on next vmagent restart. Subsequent heartbeats from the hypervisor-agent preserve the new value — only this endpoint changes it.

On a single-node install it also sets the node’s reservation: reservedVCPUs / reservedMemoryBytes make it the operator’s, kept by the heartbeat and the reconciler alike, and reservationSource: computed hands it back to the computed default. Values below the floor of 1 vCPU and 4 GiB (the minimum for development; not recommended for production), above the node’s total, or on a clustered install are refused with 400. A reservation raised above what leaves room for the committed instances is accepted; readiness reports NodeCommittedOverAllocatable until it clears. The name needs compute:RenameNode, the reservation compute:UpdateNodeReservation.

Idempotent: PATCH-ing to the current name returns the unchanged row without auditing.

nodeId
required
string
/^n-[a-z0-9-]+$/
Media typeapplication/json

PATCH /v1/compute/nodes/{nodeId} body: the display name and, on a single-node install, the node’s reservation. Absent fields are unchanged; a body with none returns the current row.

object
name

New operator-friendly node display label. Omitted / absent fields are no-op (returns the current row).

string
>= 2 characters <= 64 characters /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,62}[a-zA-Z0-9]$/
reservedVCPUs

VCPUs to keep back from VMs. Makes the reservation the operator’s (reservationSource: operator), kept from then on. At least 1: the floor is the minimum for development, not recommended for production. At most the node’s total. Single-node installs only.

integer
>= 1
reservedMemoryBytes

Memory to keep back from VMs. Makes the reservation the operator’s, kept from then on. At least 4 GiB: the floor is the minimum for development, not recommended for production. At most the node’s total. Single-node installs only.

integer format: int64
>= 4294967296
reservationSource

computed hands the node back to the computed default (max(2, 6% of threads) vCPUs, max(6 GiB, 10% of RAM)); the values follow within a minute. Takes neither reservedVCPUs nor reservedMemoryBytes.

string
Allowed values: computed

The updated node.

Media typeapplication/json

Operator-facing inventory record Appendix A. widened the role enum from the original VM-hosting subset (hybrid, hypervisor) to all four master-plan D5 roles. Control-plane and storage nodes self-register so they appear in the Nodes page + capacity dashboards; the scheduler filters by role and never places instances on them.

object
id
required
string
/^n-[a-z0-9-]+$/
name
required

operator-friendly per-node display label (e.g. “stratum-01”). Independent of id: id is the canonical n- identity used for joins/counts/grouping; name is the cosmetic label surfaced on the Nodes page, log-stream selectors, and the vmagent node_name metric label. Settable via PATCH /v1/compute/nodes/{nodeId}; sticky across redeploys.

string
>= 2 characters <= 64 characters /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,62}[a-zA-Z0-9]$/
hostname
required
string
role
required

/ D5 node role. hybrid and hypervisor run VMs; control-plane and storage appear here for inventory + capacity visibility but never accept placement.

string
Allowed values: hybrid hypervisor control-plane storage
region
required
string
availabilityZone
required
string
architecture
required
string
Allowed values: amd64 arm64
state
required
string
Allowed values: ready draining cordoned maintenance unknown
totalVCPUs
integer
reservedVCPUs

VCPUs the node keeps for itself (kernel, control plane, substrate), taken off the total before the overcommit ratio. On a single-node install computed as max(2, 6% of the threads) unless an operator set it; see reservationSource.

integer
vcpuOvercommitRatio
number format: float
committedVCPUs
integer
totalMemoryBytes
integer format: int64
reservedMemoryBytes

Memory the node keeps for itself, taken off the total before the overcommit ratio. On a single-node install computed as max(6 GiB, 10% of RAM) unless an operator set it, and enforced there: system.slice gets MemoryMin/MemoryLow equal to it.

integer format: int64
memoryOvercommitRatio
number format: float
committedMemoryBytes
integer format: int64
reservationSource

Who wrote the reservation. reported: the heartbeat, on every heartbeat (every clustered node). computed: the single-node default, kept in step with the node’s size. operator: set through PATCH /v1/compute/nodes/{nodeId}, or chosen at install (node.yaml host_reservation,, written when the node first registers); nothing else changes it.

string
Allowed values: reported computed operator
allocatableVCPUs

VCPUs the node can have committed: floor((total - reserved) x overcommit), the scheduler’s own formula. Derived, never stored.

integer format: int64
allocatableMemoryBytes

Memory the node can have committed: floor((total - reserved) x overcommit), the scheduler’s own formula. Derived, never stored.

integer format: int64
capabilities

The node’s label map, all string-valued. Two key namespaces are reserved and defined by the platform; any other key is the operator’s own and is never interpreted here.

topology.* — where the machine physically sits. topology.az is published from the node’s declared availability zone; topology.rack and topology.power are declared by the operator in the cluster topology. An undeclared level simply does not exist for that cluster.

capability.* — what the hardware can do, detected by the node on every heartbeat so a hot-installed device is picked up without restarting it: capability.cpu.model, capability.cpu.sockets, capability.gpu.present, capability.mem.ecc, capability.sec.tpm, capability.virt.nested, and the rest of the detected set.

Each key has a kind, declared by the platform and never inferred from the value. Descriptive keys are matched by equality and consumed by nothing. Boolean keys are true or false. Countable keys carry a whole number and are consumed on placement: capability.net.sriov_vfs (virtual functions, each attaching to a single guest) and capability.mem.hugepages_1g. The accelerator namespaces capability.gpu.<vendor-model> and capability.accel.<vendor-model> are countable and open — a new model is data, not a schema change — and are declared by an operator until device enumeration ships.

capability.cpu.cores and capability.cpu.threads are descriptive, not countable: vCPU is accounted separately and with an overcommit ratio, so counting them here would account the same resource twice under two different rules.

A countable key that is absent is not zero. Absent means the node did not report it — the control plane runs in a container that often cannot read host sysfs — while zero means the node genuinely has none.

These keys are operational rather than physical:

  • capability.migration.transport — listening or down; whether this node can RECEIVE a live migration.
  • capability.host.binaries_commit — the git commit the node’s /usr/local/bin binaries were built from, mixed when they disagree with each other, or unknown when they are too old to report it.
  • capability.host.binaries_stale — true when those binaries are not the build the node should run: on a mutable node the deployed control plane’s (a control-plane deploy replaces a container image and does NOT touch host binaries, so they drift from the day a node is built), on an image-mode node the host binaries of the release the cluster runs, as the HostBinariesStale readiness finding judges them. capability.host.binaries_unknown names the ones that could not report at all — those are the binaries most likely to be missing a subcommand a runbook names.
  • capability.host.binaries_source — what fixes a stale node. control-plane-image on a mutable node: the host-helper installs the control plane’s copies on its next pass. os-image on an image-mode (bootc) node: the binaries are part of the read-only stratum-os image and nothing on the node changes them, so stale there lasts until an upgrade changes them. overlay on an image-mode node whose binaries were switched in live from a release: the next upgrade switches them again.
  • capability.host.dev_mode — true when the node’s control plane runs in dev mode (node.yaml dev_mode,): the substrate’s web UIs on loopback, the OpenBao UI, and credentials inline in the admin substrate-tools response. Reported by the control plane’s own heartbeat, so a node without a control plane has no key. Readiness lists each such node as DevModeOn.

Where a declared label and detection disagree the declared value wins and the override is logged.

Absent keys mean “not reported”, never “false” — a node whose host-helper has not run a pass publishes no capability.host.binaries_* keys at all.

renamed every key under these prefixes; the previous unprefixed names (hasGpu, cpuModel, migrationTransport,…) are no longer published.

object
key
additional properties
string
committedCapabilities

How many units of each countable capability are currently allocated on this node — capability.net.sriov_vfs, capability.mem.hugepages_1g, capability.gpu.<vendor-model> and the rest of the countable set.

Deliberately separate from capabilities: that map is what the node SAYS about itself, this is what the platform has handed out. Mixing them would make a node’s self-report depend on scheduling decisions it never made.

Free units are capabilities[key] - committedCapabilities[key]. An absent key means none are allocated, and a node holding nothing omits the object entirely.

A count here can exceed the declared total if an operator shrinks a declared capability below what is already allocated. That is a supported state, not a corruption: existing guests keep what they hold and nothing new is placed until reality catches up. Clamp at zero when computing free rather than rendering negative capacity.

object
key
additional properties
integer
powerAction

The node’s latest shutdown or reboot through the API, absent when it never had one. In progress while state is shutting-down, rebooting or off.

object
nodeId
required
string
action
required
string
Allowed values: shutdown reboot
state
required
  • shutting-down — recorded; the node powers off at notBefore.
  • rebooting — recorded; the node reboots at notBefore, and stays rebooting until it has booted again.
  • off — a shutdown whose node stopped heartbeating. It stays off until someone powers it on (see powerOn).
  • done — the node booted again after the action.
  • failed — the host did not power off or reboot; message says why.
string
Allowed values: shutting-down rebooting off done failed
generation
required

Bumped by every new action on the node.

integer format: int64
reason
string
force
boolean
requestedBy
required
string
requestedAt
required
string format: date-time
notBefore
required

When the host acts: a short delay after the request, so the 202 is answered before the node (and, on a single node, the API) goes down.

string format: date-time
offAt

When a shutdown’s node was seen gone.

string format: date-time
nullable
finishedAt
string format: date-time
nullable
message
required

What the action is doing or waiting for, or why it failed.

string
controlPlaneOffline
required

True when this node is the only control-plane node up (a single-node install, or the last node of a cluster): the console and the API go down with it, and nothing answers until it is back.

boolean
powerOn
required

How the node comes back after a shutdown: its power button, and Wake-on-LAN to its out-of-band NIC’s MAC when the node reported one.

string
lastSeenAt
required
string format: date-time
createdAt
required
string format: date-time
updatedAt
required
string format: date-time

Example

{
"role": "hybrid",
"architecture": "amd64",
"state": "ready",
"reservationSource": "reported",
"powerAction": {
"action": "shutdown",
"state": "shutting-down"
}
}

Bad request.

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
>= 400 <= 599
detail
string
instance
string format: uri-reference
requestId
required
string
code
required
string
issues

The findings of a rejected IAM policy document (custom and resource policies).

Array<object>

One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.

object
code
required

The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.

string
statement
required

Index of the statement at fault; -1 for the document as a whole.

integer
>= -1
detail
required
string
action

The offending action, where one is at fault (ACTION_NOT_APPLICABLE).

string
errors

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.

Array<object>

One field’s problem, the stage-2 installer API’s shape. field is the field’s path, message what is wrong with it.

object
field
required

The field’s path, e.g. links[0].interface, disks[1].confirm, mgmt.address or role; empty for the whole request.

string
message
required
string
details

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
key
additional properties
any

Example

{
"issues": [
{
"code": "ACTION_NOT_APPLICABLE",
"action": "compute:CreateVpc"
}
]
}

Resource not found.

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
>= 400 <= 599
detail
string
instance
string format: uri-reference
requestId
required
string
code
required
string
issues

The findings of a rejected IAM policy document (custom and resource policies).

Array<object>

One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.

object
code
required

The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.

string
statement
required

Index of the statement at fault; -1 for the document as a whole.

integer
>= -1
detail
required
string
action

The offending action, where one is at fault (ACTION_NOT_APPLICABLE).

string
errors

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.

Array<object>

One field’s problem, the stage-2 installer API’s shape. field is the field’s path, message what is wrong with it.

object
field
required

The field’s path, e.g. links[0].interface, disks[1].confirm, mgmt.address or role; empty for the whole request.

string
message
required
string
details

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
key
additional properties
any

Example

{
"issues": [
{
"code": "ACTION_NOT_APPLICABLE",
"action": "compute:CreateVpc"
}
]
}