Skip to content

Request a Day-2 Ceph cluster bootstrap (bootstrap-admin).

POST
/v1/admin/storage/ceph/bootstrap
Code sample: Shell / cURL
curl --request POST \
--url https://stratum.example.com/v1/admin/storage/ceph/bootstrap \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "image": "example", "publicNetwork": "example", "clusterNetwork": "example", "monCount": 1, "mgrCount": 1, "pgNum": 1, "osdDevices": "example", "osdPaths": [ { "host": "example", "devices": [ "example" ] } ], "placement": { "additionalProperty": { "hosts": [ "example" ], "label": "example" } }, "confirmWidenOsdDevices": true }'

Records the desired Ceph cluster (topology + storage networks) and returns 202; a reconciler converges the live cephadm cluster toward it asynchronously. Never runs at firstboot. All fields optional: image + mon/mgr counts default, and the networks default to the reconciler deriving them from each node’s storage traffic class. Idempotent — re-requesting updates the desired state. Install-scope; gates on storage:BootstrapCeph.

Media typeapplication/json

Day-2 bootstrap request. All fields optional — image + counts default, networks default to the reconciler deriving them from each node’s storage traffic class.

This is a FULL REPLACE. Anything omitted is set to its default, not preserved (the sole exception being the RGW fields, which are owned by POST /rgw and carried over). That is right for first bring-up and wrong for a Day-2 edit: sending {"placement": {...}} alone against a live cluster also resets osdDevices and blanks the networks. For any change after bootstrap use PATCH /v1/admin/storage/ceph/cluster, which leaves unmentioned fields alone.

object
image

Ceph container image pin (defaults to the Tentacle el10 image).

string
publicNetwork

Ceph public_network CIDR, e.g. 192.0.2.0/24.

string
clusterNetwork

Ceph cluster_network CIDR (OSD replication).

string
monCount

Monitor count (default 3).

integer
>= 1
mgrCount

Manager count (default 2).

integer
>= 1
pgNum

Pool placement-group count; 0 = the PG autoscaler picks.

integer
osdDevices

OSD disk selection. Omitted or empty: each member’s hardware-plan ceph-osd disks, by /dev/disk/by-id path, one OSD service per host (members that join later get theirs). all-available takes every blank disk on every host and only when asked for by name; model:<m> | size:<s> filter every host.

string
osdPaths

Explicit per-host OSD device paths. When set it takes precedence over osdDevices: each entry becomes a per-host cephadm drive-group with exactly these /dev paths — nothing else on the host is consumed.

The disks an install reserved for Ceph are listed by GET /v1/admin/storage/ceph/osd-candidates in this very shape; the console pre-fills osdPaths from it. Without osdPaths or osdDevices the selection is those same disks, from the hardware plan. A device the plan gives another role (system, compute, unused) is refused with 400; mark it ceph-osd in the node’s plan first.

Array<object>

One host’s explicit OSD device contribution.

object
host
required

Cephadm hostname (as reported by GET /ceph/hosts).

string
devices
required

Absolute /dev paths on that host to consume as OSDs.

Array<string>
placement

Optional per-daemon-kind placement, keyed by kind. Only mon and mgr are accepted: OSD placement follows the DEVICES, via osdDevices / osdPaths.

Omit it entirely for the default behavior, where cephadm’s own scheduler spreads the requested count over the enrolled hosts. That is correct on a small cluster where count == hosts; pin placement when the hosts are not interchangeable (“mons on the control nodes, never the storage-heavy ones”).

object
key
additional properties

Where one Ceph daemon kind may run.

Set exactly one of hosts or label. Both empty is rejected rather than treated as “anywhere”: an empty entry would render as a bare count, which is the opposite of what asking for a placement means.

The daemon COUNT still comes from monCount / mgrCount and is combined with this constraint, so a label matching five hosts still yields mgrCount managers rather than five.

object
hosts

Explicit cephadm host names. Validated against the enrolled member set — an unknown name is a 400, because cephadm itself accepts one and then simply never schedules the daemon, which is indistinguishable from “still converging”.

Array<string>
label

Cephadm host label to place on (ceph orch host label add <host> <label>). Mutually exclusive with hosts.

string
confirmWidenOsdDevices

Required when this request would set osdDevices to all-available over another selection; without it that specific transition is refused with 409. An omitted selector is the hardware plan’s disks, not all-available.

It is the one field here whose loss is not recoverable: the reconciler acts on a widened selector by consuming every blank disk on every node, and a disk consumed as an OSD has been written to. Everything else a full replace resets can simply be re-applied.

boolean

Example generated

{
"image": "example",
"publicNetwork": "example",
"clusterNetwork": "example",
"monCount": 1,
"mgrCount": 1,
"pgNum": 1,
"osdDevices": "example",
"osdPaths": [
{
"host": "example",
"devices": [
"example"
]
}
],
"placement": {
"additionalProperty": {
"hosts": [
"example"
],
"label": "example"
}
},
"confirmWidenOsdDevices": true
}

Bootstrap requested; desired state recorded.

Media typeapplication/json

Desired + observed Ceph cluster. configured=false before any bootstrap. exists, bootstrapFailed and rgwDeployed are the platform’s own answers, derived from the observed status, never from the desired row.

object
configured
required
boolean
desired

The operator’s desired Ceph cluster (singleton).

object
desiredEnabled
required
boolean
image
required
string
publicNetwork
string
clusterNetwork
string
monCount
required
integer
mgrCount
required
integer
pgNum
integer
osdDeviceSelector

“” = the members’ hardware-plan ceph-osd disks | all-available | model: | size:. What it resolves to is the view’s osdSelection.

string
osdPaths
Array<object>

One host’s explicit OSD device contribution.

object
host
required

Cephadm hostname (as reported by GET /ceph/hosts).

string
devices
required

Absolute /dev paths on that host to consume as OSDs.

Array<string>
rgwEnabled

Desired RADOS Gateway (S3 object storage) deployment. When true, the reconciler runs ceph orch apply rgw.

boolean
rgwServiceId

Cephadm rgw service name; empty = ‘stratum’.

string
rgwPlacementCount

Radosgw daemon count; 0 = default to mon count.

integer
rgwFrontendPort

Radosgw beast frontend port; 0 = default 7480.

integer
placement

The per-daemon-kind placement in effect, keyed by kind. Absent means bare counts: cephadm’s scheduler chooses the hosts.

object
key
additional properties

Where one Ceph daemon kind may run.

Set exactly one of hosts or label. Both empty is rejected rather than treated as “anywhere”: an empty entry would render as a bare count, which is the opposite of what asking for a placement means.

The daemon COUNT still comes from monCount / mgrCount and is combined with this constraint, so a label matching five hosts still yields mgrCount managers rather than five.

object
hosts

Explicit cephadm host names. Validated against the enrolled member set — an unknown name is a 400, because cephadm itself accepts one and then simply never schedules the daemon, which is indistinguishable from “still converging”.

Array<string>
label

Cephadm host label to place on (ceph orch host label add <host> <label>). Mutually exclusive with hosts.

string
createdAt
string format: date-time
updatedAt
string format: date-time
createdBy
string
status

The reconciler’s observed Ceph cluster state (singleton).

object
fsid
string
phase
required
string
Allowed values: unconfigured bootstrapping ready degraded error tearing-down
health
string
message
string
reportedAt
string format: date-time
reportedBy

The control plane (node id) that wrote this status.

string
rgwDaemonsRunning

The radosgw daemons the reconciler observed running at its last probe. Absent when not observed (no cluster answered, or the gateway listing failed): unknown, not zero.

integer
exists
required

A Ceph cluster runs, as last observed: an fsid, and a cluster that answered (phase ready or degraded, or error from a converge step on a cluster that answered). What S3, readiness and the RGW deploy act on.

boolean
bootstrapFailed
required

A requested bootstrap failed before any cluster existed (phase error, no fsid). Readiness raises CephBootstrapFailed and the ceph-bootstrap-failed alarm fires on it. Request the bootstrap again to retry.

boolean
rgwDeployed

The object gateway is deployed: the cluster exists, RGW is requested, and a radosgw daemon was observed running. Absent while unknown.

boolean
osdSelection

The disks the reconciler makes OSDs, and where they come from: the same selection it converges. Absent before any bootstrap request.

object
source
required

Hardware-plan: each member’s ceph-osd disks (the default); osd-paths: the request’s osdPaths; all-available: every blank disk, asked for by name; selector: a model:/size: filter on every host.

string
Allowed values: hardware-plan osd-paths all-available selector
selector

The model:/size: filter, for source selector.

string
paths
required

The per-host devices the OSD services name, for the hardware-plan and osd-paths sources (empty for the others). A member with no ceph-osd disk, or whose plan could not be read, has no entry.

Array<object>

One host’s explicit OSD device contribution.

object
host
required

Cephadm hostname (as reported by GET /ceph/hosts).

string
devices
required

Absolute /dev paths on that host to consume as OSDs.

Array<string>
refused

OsdPaths devices left out because the hardware plan gives the disk another role, as “host:device: role”.

Array<string>
bootstrapNode

The node that holds the bootstrap claim: the one node that runs cephadm bootstrap for this request. Absent before a reconcile pass has claimed it and after a teardown. It moves to another node only on a new request while it is not active.

string

Example

{
"status": {
"phase": "unconfigured"
},
"osdSelection": {
"source": "hardware-plan"
}
}

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

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