Skip to content

Cluster-wide HA status.

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

Bootstrap-admin endpoint returning the cluster’s HA topology and rolled-up state. A single-node install reports clusterState: single-node with haEnabled: false — the v1 shape, unchanged. An HA install reports the declared node membership (id, role, AZ, mgmt IP) and the cluster’s lifecycle state.

2.0 first slice: topology + config-level state. Live per-node health (reachable / draining / leader) joins the node registry in a follow-up; multi-node aggregation lands with the rest of the HA build.

Cluster HA status.

Media typeapplication/json
object
haEnabled
required

Whether the install is configured for HA (3+ nodes). False = single-node v1.

boolean
clusterState
required

Rolled-up cluster lifecycle state. single-node when HA is off; the others per the cluster-state table once HA is on.

string
Allowed values: single-node healthy degraded critical recovering maintenance
nodes
required
Array<object>
object
nodeId
required
string
role
required
string
Allowed values: control-plane hybrid hypervisor storage
az

Availability zone; empty on single-AZ installs.

string
mgmtIp

Management-plane address.

string
networks

The node’s traffic-class bindings, keyed by class (storage, overlay). Carried in the join bundle so a joiner’s ClusterConfig matches the founder’s.

Without it a joined node has no networks entry, so ClassAddr falls through to mgmt_ip and EVERY traffic class silently collapses onto the management plane. That put Ceph’s public_network — and therefore all client I/O — on the 1G mgmt NIC while only OSD replication used the 10G storage VLAN, with the cluster reporting HEALTH_OK throughout.

object
key
additional properties

One traffic class’s binding on a node (-TOPO-1).

object
ip
required

The address this class uses on the node (a bare IP, not a CIDR).

string
interface

Host interface carrying the class, when one is declared.

string
labels

The node’s DECLARED label map (topology.rack, topology.power, and any operator-namespace key). Carried in the join bundle so a joiner’s ClusterConfig matches the founder’s.

Without it a joined node has NO declared labels at all, and every consumer degrades to “the founder has a rack, nobody else does” — silently. Rack spread sees one value and two empties, so the anti-affinity guarantee reports success and places anywhere; a CRUSH hierarchy built from labels finds one rack and is refused as a half-declared topology; a rack failure domain can never be satisfied; and a taint declared on a joiner repels nothing.

topology.az is NOT carried here — the AZ rides its own az field, and two records of one fact is the bug each cost a session.

This is the THIRD field to go missing from this schema the same way (networks in the bundle, networks in the status report). A field added to config.ClusterNode does not reach a joiner unless someone remembers this file.

object
key
additional properties
string
bootState

Per-node boot progress, probed from the node’s /startupz. ready = serving; starting = still booting (see bootPhase); unreachable = the node didn’t answer (down, early-boot before the listener, or wedged). Lets the UI tell “booting / stuck / down” apart from a vague “unknown”. Omitted when the boot-health probe isn’t wired (single-node).

string
Allowed values: ready starting unreachable
bootPhase

The in-flight startup phase when bootState=starting (e.g. migrations).

string
bootElapseMs

How long the current boot phase has run (ms); climbs while a phase is stuck.

integer format: int64
readyAfterMs

The node’s last boot duration (ms), when bootState=ready.

integer format: int64
controlPlaneLeader

The node id of the current control-plane leader — the node holding the leader advisory lock, which runs the cluster-wide singleton operational surface. The API VIP follows this node. Empty on single-node or when the holder can’t be determined.

string
members

Live Patroni member state for the Postgres-HA cluster (M1). Empty on single-node, or when the live state can’t be reached. Joined to nodes by host/mgmtIp.

Array<object>
object
name
required

The member’s name (the node id).

string
host
required

The member’s Postgres host (its mgmt IP).

string
role
required

Patroni role.

string
Allowed values: leader sync_standby replica standby_leader demoted uninitialized
state
required

Patroni member state (running, streaming, stopped,…).

string
timeline

The member’s Postgres timeline; matches across in-sync members.

integer
lagMb

Replication lag in MB (0 on the leader + in-sync replicas). Null/absent if unknown.

integer
nullable
openbao

Live OpenBao integrated-storage raft state. Per-node leadership + seal status, probed from each CP node’s local OpenBao. Absent on single-node / when no node is reachable.

object
leaderNodeId

The node id of the current OpenBao raft leader (the node whose /v1/sys/leader reports is_self, or that the others name as leader_address). The OpenBao VIP follows this node. Empty when no leader is reachable.

string
members

Per-CP-node OpenBao state (one entry per probed node).

Array<object>
object
nodeId
required

The CP node this entry describes.

string
reachable
required

Whether the control plane could reach this node’s OpenBao.

boolean
isLeader

Whether this node is the OpenBao raft leader (is_self=true).

boolean
sealed

Whether this node’s OpenBao is sealed. A sealed node can’t serve secrets; on a healthy cluster every node is unsealed (auto-unseal via TPM at boot,). Absent when unreachable.

boolean
nullable
ovn

OVN central (NB/SB) leadership. Single-instance until OVN raft — singleInstance=true then means leaderNodeId is the node running ovn-central, not a raft leader.

object
leaderNodeId

The node id leading OVN central — the NB raft leader (the OVN VIPs follow it). Empty when not determinable. (Convenience alias of nbLeaderNodeId for callers that want a single “OVN leader”.)

string
nbLeaderNodeId

The OVN_Northbound raft leader node id. Empty if unknown.

string
sbLeaderNodeId

The OVN_Southbound raft leader node id. May differ from the NB leader. Empty if unknown.

string
singleInstance

True while OVN central is single-instance (pre-): the UI should show “active” rather than “leader”. False once OVN runs as a 3-node raft.

boolean
members

Per-CP-node OVN raft state; empty single-instance.

Array<object>
object
nodeId
required

The CP node this entry describes.

string
reachable
required

Whether the control plane could reach this node’s OVN DBs.

boolean
nbIsLeader

Whether this node leads the OVN_Northbound raft.

boolean
sbIsLeader

Whether this node leads the OVN_Southbound raft.

boolean
chassisQueried

Whether the OVN Southbound DB Chassis table was successfully read this pass. When false the chassis list is unknown (the probe failed/timed out) and consumers MUST NOT infer a dataplane outage from an empty chassis.

boolean
chassis

Registered ovn-controller chassis, read from the OVN Southbound DB. One row per node whose ovn-controller is connected to the SB DB; a node missing here has a down/disconnected dataplane agent (no OVS flows, no FIP GARP) — a silent outage the raft-leadership rollup misses. Only meaningful when chassisQueried=true.

Array<object>
object
name
required

The chassis name — the node’s OVN system-id.

string
hostname

The hostname ovn-controller registered for this chassis.

string
vips

The cluster’s service VIPs and which node currently holds each. The Postgres VIP follows the Patroni primary, so its holder is the leader; other VIP holders are reported when known.

Array<object>
object
name
required

Which VIP (api / postgres / openbao / ovnNb / ovnSb / vmselect / providerGw).

string
Allowed values: api postgres openbao ovnNb ovnSb vmselect providerGw
address
required

The VIP address.

string
holder

The node id currently holding this VIP, when known: the node whose own underlay report (at most 5 minutes old) has the address on a link, for every VIP vmselect included; else the leader the VIP follows (the Patroni leader for Postgres, the raft leaders for OpenBao and OVN, the control-plane leader for the API). providerGw follows the active VPC gateway chassis. Empty when neither is known.

string
failoverEvents

The Postgres cluster’s promotion history, newest first — each timeline bump is a promotion, a planned switchover or a failover: Postgres records them alike. Sourced from Patroni’s /history.

Array<object>
object
timeline
required

The Postgres timeline this promotion created.

integer
newLeader
required

The member promoted to leader at this timeline.

string
timestamp
required

When the promotion happened (RFC3339).

string
reason

The recorded reason for the timeline switch, when there is one. Absent for Postgres’s default “no recovery target specified”, which it writes for every switchover and failover alike.

string

Example

{
"clusterState": "single-node",
"nodes": [
{
"nodeId": "n-abc12def",
"role": "control-plane",
"networks": {
"additionalProperty": {
"ip": "192.0.2.111",
"interface": "vlan90"
}
},
"bootState": "ready",
"bootPhase": "migrations"
}
],
"members": [
{
"name": "n-c6ttm6tl",
"host": "192.0.2.196",
"role": "leader",
"state": "streaming"
}
],
"vips": [
{
"name": "api"
}
]
}

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