Skip to content

A node's hardware plan next to what it reports (bootstrap-admin).

GET
/v1/admin/nodes/{nodeId}/hardware-plan
Code sample: Shell / cURL
curl --request GET \
--url https://stratum.example.com/v1/admin/nodes/example/hardware-plan \
--header 'Authorization: Bearer <token>'

. Each disk’s role (system, compute with its pool and class, ceph-osd, unused) and each link’s purposes, as the install recorded them and later edits changed them, next to what the node reports, with a mismatch flagged. Install-scope; gates on compute:DescribeNodeHardwarePlan. 404 for an unknown node, or a node whose control plane has not seeded its plan yet.

nodeId
required
string

The plan.

Media typeapplication/json

A node’s hardware plan: one record of what each disk and each link was installed as, next to what the node reports. Written once at install (the control plane imports the install’s record on its first start; a node installed before the plan gets one derived from what it has), shown in Admin > Metal (the Nodes page’s Disks and Network tabs) and edited there only where a reconciler applies the change.

object
nodeId
required
string
version
required

Bumped by every edit. Send it back in a PATCH to refuse an edit made against an older plan.

integer format: int64
>= 1
seededFrom
required

install — the install’s own record. upgrade — a node installed before the plan existed, derived once from its disks’ use, the install’s Ceph candidate record, its NIC roles and node.yaml’s connections.

string
Allowed values: install upgrade
createdAt
required
string format: date-time
updatedAt
required
string format: date-time
updatedBy
string
disks
required

Every disk the plan knows, plus any disk the node reports that it does not (inPlan false).

Array<object>

One disk’s planned role next to what the node reports.

object
key
required

The disk’s WWN, or its /dev/disk/by-id path when it has none. Names the disk in a PATCH.

string
wwn
string
byId

The /dev/disk/by-id path the plan records it by.

string
role
required

system — an OS disk (fixed at install). compute — a disk of the compute pool pool. ceph-osd — marked for a day-2 Ceph bootstrap: the Ceph page preselects it. unused — nothing.

string
Allowed values: system compute ceph-osd unused
pool

A compute disk’s pool; on a system disk, the pool on its carved tail.

string
storageClass
string
origin
required
string
Allowed values: install edit
updatedBy
string
updatedAt
required
string format: date-time
inPlan
required

False for a disk the node reports that the plan does not know (added after the install); shown as unused.

boolean
observed

What the node reports for a planned disk.

object
path
required
string
kernelName
required
string
sizeBytes
required
integer format: int64
rotational
required
boolean
model
string
serial
string
usage
required
string
Allowed values: available partitioned filesystem lvm-member ceph mounted
role
required

The role the node’s use of the disk shows (mounted is system, a pool’s PV compute, an OSD or a blank reserved disk ceph-osd).

string
Allowed values: system compute ceph-osd unused
pool
string
carries

What would be affected if this device died.

This is the field that makes a disk-health finding actionable. “nvme1n1 on stratum-02 is hot” is informational; “…and it backs osd.1” is what decides whether an operator can act tonight or must act now.

Absent when the device carries nothing known.

object
cephDaemons

Cephadm daemons whose data lives on this device (e.g. osd.1, mon.stratum-01). A mon on the OS disk is included: losing that device takes the mon with it.

Array<string>
volumeGroups

LVM volume groups with a physical volume on this device, including via a partition — a PV on /dev/nvme0n1p3 is attributed to nvme0n1, because the whole disk is what fails.

Array<string>
status
required

match — the node’s report agrees with the plan. mismatch — see statusReasons. missing — the node does not report the disk.

string
Allowed values: match mismatch missing
statusReasons
Array<string>
allowedRoles
required

The roles a PATCH can give the disk now. Empty with lockedReason when none.

Array<string>
Allowed values: compute ceph-osd unused
lockedReason
string
links
required

The lifelines (oob, mgmt; locked) first, then the declared underlay links.

Array<object>

One planned link: an ethernet NIC, a bond, or a VLAN on either, with its purposes, next to what the node reports. Lifelines (the stage-1 oob NIC and the mgmt NIC) are kept by the plan and locked; every other link is a declared underlay connection.

object
name
required

The link’s name (the underlay connection’s, or the lifeline’s NetworkManager id, oob / stratum).

string
kind
required
string
Allowed values: ethernet bond vlan
interface
required
string
permanentMac

An ethernet NIC’s burned-in MAC, which keys it (a renamed NIC is still found). On a link that is an underlay connection (a bond member, the provider NIC) it is the node inventory’s permanentMac for the NIC the link names: a bond member’s own, never the bond’s.

string
parent
string
vlanId
integer
controller
string
bond

802.3ad (or active-backup) aggregation for a bond connection.

xmitHashPolicy is required for 802.3ad and is not a tuning preference. Geneve puts every tunnel between a single MAC/IP pair, so the kernel default (layer2) hashes ALL overlay traffic onto one member: the bond reports UP, both links report UP, and half the fabric is unreachable.

object
mode
required
string
Allowed values: 802.3ad active-backup
xmitHashPolicy

Required for 802.3ad. Use layer3+4 so overlay traffic spreads across members.

string
miimonMs

Link-monitor interval in milliseconds, e.g. 100.

integer
lacpRate
string
Allowed values: slow fast
addresses
Array<string>
gateway
string
mtu
integer
zone
string
neverDefault
boolean
purposes
required
Array<string>
Allowed values: oob mgmt storage overlay provider
lifeline
boolean
origin
string
Allowed values: install edit
updatedBy
string
updatedAt
string format: date-time
observed
object
present
required
boolean
state
string
mac
string
mtu
integer
addresses
Array<string>
observedPurposes
required

The purposes the node’s running configuration shows on the link (its observed roles mapped onto purposes).

Array<string>
Allowed values: oob mgmt storage overlay provider
status
required

pending-ceph: the link’s storage purpose is not in use yet because Ceph is not set up; statusReasons says “Storage: not in use yet (Ceph not set up)”. Neutral, not a warning: the same verdict the underlay view’s purposeStatus and readiness give.

string
Allowed values: match mismatch unverified pending-ceph missing
statusReasons
Array<string>
lockedReason

Set when the link’s purposes cannot be edited here (oob and mgmt are install-managed lifelines).

string
history
required

The newest 50 versions, newest first.

Array<object>

One plan version.

object
version
required
integer format: int64
actor
required

Who made it; stratum-installer for the install’s record.

string
at
required
string format: date-time
summary
required
string
changes
required
Array<object>

One change of a plan version.

object
target
required
string
Allowed values: disk link
key
required

The disk’s key or the link’s name.

string
from
required
string
to
required
string
applied

What applied it (a pool registration, a wipe, the underlay reconciler), with the node storage intent to follow when it runs on another node.

string

Example

{
"seededFrom": "install",
"disks": [
{
"role": "system",
"origin": "install",
"observed": {
"usage": "available",
"role": "system"
},
"status": "match",
"allowedRoles": [
"compute"
]
}
],
"links": [
{
"kind": "ethernet",
"bond": {
"mode": "802.3ad",
"lacpRate": "slow"
},
"purposes": [
"oob"
],
"origin": "install",
"observedPurposes": [
"oob"
],
"status": "match"
}
],
"history": [
{
"changes": [
{
"target": "disk"
}
]
}
]
}

Authenticated but not authorized.

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"
}
]
}