Skip to content

List machines that registered to join (bootstrap-admin).

GET
/v1/admin/cluster/joins
Code sample: Shell / cURL
curl --request GET \
--url https://stratum.example.com/v1/admin/cluster/joins \
--header 'Authorization: Bearer <token>'

. Every registration, newest first, with its hardware, pairing code, state and steps. Gates on ha:DescribeNodeJoins.

The registrations.

Media typeapplication/json
object
items
required
Array<object>

A machine that registered to join, on the founder.

States: needs-upgrade (the machine runs an older release than the cluster’s, within its upgrade rules, and upgrades itself before it can be approved: upgrade says from and to, failedStep and failedError the last failure of its upgrade, which it retries by itself; it becomes pending when it registers again on the cluster’s release; approving it is refused, rejecting it is not); pending (registered, waiting for approval); approved (queued: one join runs at a time, only on a green cluster, and waitReason says what it waits for); delivering (its member row is written and its node.yaml and bundle are ready for it); installing (it reported progress); joined; failed (with the step and the error; retry queues it again); rejected; expired (nobody approved it within 24 hours of its code’s expiry).

object
id
required
string
codeId
required
string
state
required
string
Allowed values: needs-upgrade pending approved delivering installing joined failed rejected expired
pairingCode
required

Shown on the joiner’s console too. Approve the machine whose console shows the same code.

string
hostname
string
systemSerial
string
release

The release the joiner was installed from.

string
sourceAddr

The address it registered from.

string
keyFingerprint

SHA-256 of the joiner’s client key; every later call is pinned to it.

string
inventory

A joining machine’s hardware, as it reported it at registration (the inventory). The approval’s assignment is checked against it.

object
uefi
boolean
disks
Array<object>

One whole disk of a joining machine, as its discovery reports it.

object
name
required
string
path
required
string
byId
Array<string>
model
string
serial
string
wwn
string
transport
string
sizeBytes
integer format: int64
rotational
boolean
removable
boolean
readOnly
boolean
mountpoints

Live mounts on the disk or anything stacked on it. A mounted disk is the system disk.

Array<string>
holders

What already holds data on the disk. Empty means blank.

Array<object>
object
kind
required
string
device
required
string
detail
string
partitions

The disk’s partitions. On an OS disk they say what stage 1 left free at its end (the compute tail, or nothing with the whole-disk layout).

Array<object>
object
number
required
integer
name
required
string
path
required
string
sizeBytes
required
integer format: int64
fsType
string
label
string
partLabel
string
stack

Every md array and device-mapper device built on the disk, deepest first.

Array<object>
object
name
required
string
path
required
string
type
required
string
nics
Array<object>

One network interface of a joining machine.

object
name
required
string
mac
string
permanentMac
string
operState
string
link

up with a carrier, down without one, unknown.

string
speedMbps
integer format: int64
mtu
integer format: int64
driver
string
addresses
Array<string>
wireless
boolean
routes

The IPv4 destinations the main routing table sends out of this NIC (CIDRs; a host route as /32), without the default route.

Array<string>
cpu
object
model
string
sockets
integer
cores
integer
threads
integer
virtualization

vmx, svm, or empty.

string
memoryBytes
integer format: int64
osDiskLayout

How stage 1 laid out the OS disks, from the joiner’s install record: compute-tail keeps the end of each OS disk for the compute pool, whole-disk gives the disks whole to the system, so compute is a data disk (a compute pool, or Ceph on a disk marked ceph-osd). Absent on a machine with no record; the founder then reads it off the disks’ partitions.

string
Allowed values: compute-tail whole-disk
assignment

Everything about a joiner, chosen on the founder. It becomes the joiner’s node.yaml and its member row. What the cluster decides (region, parent domain, upstream DNS, floating IPs, the first admin, services, base images) is not here: the joiner adopts it.

object
name

Display name. Default the hostname.

string
role

Every joiner is hybrid (control plane, compute and Ceph together), the default. Any other role (a compute-only hypervisor, a storage-only node, control-plane) is refused at role: those nodes are not supported yet and are planned for a later release. The planned size (3 by default, set at install) is the plan, not a cap: a cluster takes joiners up to 5 control-plane nodes, and an approval that would pass 5 is refused at role.

string
Allowed values: hybrid
rack

The topology.rack label.

string
az
string
mgmt

The mgmt link. Default: the joiner’s NIC holding the address it registered from, and that address.

object
interface
string
address

An IP, or a CIDR when the address is new on that NIC (with gateway).

string
gateway
string
dns
Array<string>
links
Array<object>

One link of a joiner: an ethernet NIC, a bond, or a VLAN on either, and the purposes it carries. The same shape as a node.yaml network.connections entry; a bond member is an ethernet link naming its bond in controller. The oob link is the stage-1 NIC and is not listed.

object
name
required
string
kind

Default ethernet.

string
Allowed values: ethernet bond vlan
interface
required
string
parent

A VLAN’s parent device.

string
vlanId
integer
>= 1 <= 4094
controller

The bond this ethernet link is a member of.

string
bond
object
mode
required
string
Allowed values: active-backup 802.3ad
xmitHashPolicy
string
miimonMs
integer
lacpRate
string
addresses

Static CIDRs. Optional: a link that carries storage or overlay and names none gets the next free host address of each of those cluster networks (GET /v1/admin/cluster/networks), picked at approval and returned here with addressesAllocated. Free means no member, VIP or other approved, running or failed join holds it; a re-approval keeps the address it had while it is still free, and a retry installs the same one. A named address must be free and in the purpose’s network. None on a bond member or a provider-only link.

Array<string>
addressesAllocated

The founder picked addresses from the cluster’s networks. Ignored on input.

boolean
mtu

Default the largest MTU of the cluster networks the link carries.

integer
purposes
Array<string>
Allowed values: oob mgmt storage overlay provider
disks
Array<object>

What a joiner’s disk becomes. The system disk(s) were fixed by stage 1 and are not listed. A disk that holds data is wiped, so it needs confirm set to its key.

object
key
required

The disk’s WWN or one of its /dev/disk/by-id paths.

string
role
required
string
Allowed values: compute ceph-osd unused
pool

A compute disk’s pool name.

string
storageClass

A compute pool’s storage class. Default the pool’s name.

string
confirm

The typed wipe confirmation, the disk’s key, for a disk that holds data.

string
ntpServers

Only when this node’s NTP servers differ from the cluster’s (the founder’s), which it gets otherwise.

Array<string>
provider

The VM uplink: where the joiner’s floating IPs live and its VM traffic leaves. Default the cluster’s provider choice (GET /v1/admin/cluster/networks providerTopology, providerVlan, providerUpstreamInterface), recorded from the founder. Topology and VLAN are the cluster’s: a different value is refused at provider.topology / provider.vlan. The uplink NIC defaults to the interface of a link carrying provider, else the joiner’s NIC of the founder’s uplink’s purpose (providerUpstreamPurpose mgmt: its mgmt NIC), else the joiner’s NIC named like the founder’s. A bridged cluster refuses, at provider.upstreamInterface, a joiner without that NIC or whose uplink carries storage or overlay.

object
topology

Must equal the cluster’s providerTopology when set.

string
Allowed values: bridged routed-host
upstreamInterface

The joiner’s NIC (or bond) that carries the provider network. Default by the founder’s uplink (above).

string
vlan

Default the cluster’s provider VLAN; any other value is refused.

integer
copiedFrom

The node the assignment was copied from (copyFrom).

string
copyNotes

What the copy could not match and left for the operator.

Array<string>
nodeId

Assigned at approval.

string
waitReason
string
upgrade

The upgrade a joiner on an older release makes before it can register: from the release it was installed with to the release the cluster runs. Only a joiner that sent selfUpgrade: true is ever offered one; any other joiner on another release is refused with RELEASE_MISMATCH.

object
from
required

The release the joiner reported.

string
to
required

The release the cluster runs, which the joiner upgrades to.

string
source

Where the joiner fetches the release from (the release mirror’s URL of the release directory). Every file is checked against the release’s signed manifest. Empty when the founder names none.

string
served

The founder gives the release itself, when no release mirror can (a lab, an air gap): fetch it from GET /v1/join/registrations/{joinId}/release/{path} on the join listener, the release layout a mirror publishes (payload/manifest.json, os/blobs/..., sysext/...). source is then empty. Served only to this registration while it is needs-upgrade, read only, a few files at once (503 RELEASE_BUSY: retry); ranges are accepted so a download resumes. The joiner verifies the manifest’s signature against the release keys of its own OS and every file against the manifest, as it does from a mirror.

boolean
stalled
required

A running join whose joiner has been silent for 10 minutes.

boolean
approvedBy
string
approvedAt
string format: date-time
rejectedBy
string
rejectedAt
string format: date-time
reason
string
deliveredAt
string format: date-time
lastSeenAt
string format: date-time
currentStep
string
failedStep

The step that failed, as the joiner named it: a firstboot phase (storage), a join step (join/patroni), upgrade or upgrade/<step> while it upgrades itself, or join.

string
failedStepTitle

What a person is told failedStep is, e.g. “Upgrading to the cluster’s release” for upgrade. Set whenever failedStep is, for any step name, so a console needs no table of step names.

string
failedError
string
steps
required
Array<object>

One step of a join, as the joiner reported it.

object
name
required
string
title
required

What a person is told the step is, e.g. “Joining the OpenBao raft”.

string
status
required
string
Allowed values: running done failed
message
string
at
string format: date-time
logTail

The last lines of the joiner’s install log (the founder keeps 2,000). Only on a single join.

Array<string>
createdAt
required
string format: date-time
updatedAt
required
string format: date-time
expiresAt

When a pending join expires.

string format: date-time

Example

{
"items": [
{
"id": "nj-8w2k4m1p",
"state": "needs-upgrade",
"pairingCode": "4F7-K2Q",
"inventory": {
"disks": [
{
"name": "nvme1n1",
"path": "/dev/nvme1n1"
}
],
"nics": [
{
"name": "enp87s0"
}
],
"osDiskLayout": "compute-tail"
},
"assignment": {
"role": "hybrid",
"links": [
{
"name": "storage",
"kind": "ethernet",
"interface": "vlan90",
"bond": {
"mode": "active-backup"
},
"purposes": [
"oob"
]
}
],
"disks": [
{
"key": "/dev/disk/by-id/nvme-Samsung_SSD_980_PRO_2TB_S6B0NL0W123456",
"role": "compute"
}
],
"provider": {
"topology": "bridged"
}
},
"upgrade": {
"from": "0.5.0",
"to": "0.6.0",
"source": "https://mirror.example/releases/stratum/0.6.0/bundle"
},
"steps": [
{
"name": "join/raft-openbao",
"title": "Joining the OpenBao raft",
"status": "running"
}
]
}
]
}

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