1760 Commits
Author SHA1 Message Date
Blaine Gardner c29a096483 Merge pull request #18113 from BlaineEXE/fix-context-cancel-race
core: add workaround for ctx race after admin cephx rotation
2026-08-07 14:57:59 -06:00
Blaine Gardner 05ac850f7b core: add workaround for ctx race after admin cephx rotation
Add a workaround for https://github.com/rook/rook/issues/18112.

This is not a proper fix but is a quick fix that will prevent the race
involving operator reload and `ClusterController`'s near-global
context.Context from allowing multiple simultaneous CephCluster
reconciles of the same cluster object.

There may be other ways in which a CephCluster reconcile could enter
this race, but this workaround should reliably resolve the entry after
admin cephx key rotation.

Possible entry after this workaround is in place could involve systems
where the rook-ceph-operator pod is running on a node with high CPU load
which might prevent an ongoing CephCluster reconcile from getting CPU
cycles needed to exit following context cancellation before the sleep
added in this workaround.

Signed-off-by: Blaine Gardner <blaine.gardner@ibm.com>
2026-08-07 14:28:16 -06:00
Artem Torubarov 0c27a95097 osd: cleanup destroyed osd deployment if replacement failed
If osd-replacement fails during provisioning of the new device by the
osd-prepare job (can be the case if the new device is faulty), then
ceph-volume will run its internal rollback logic, which purges the
reserved osd id and its CRUSH position. After the faulty device is
replaced with a working one, rook will reprovision it correctly and
reuse the metadata device slot, but as a new OSD, so data will likely
be rebalanced. Ceph hands out the lowest free id, so the new OSD often
takes the same number back, and then the create path recreates the
deployment by itself. Otherwise, and until a working device arrives,
the downscaled deployment of the destroyed osd is left behind. This
commit handles that case by deleting downscaled ready-for-swap osd
deployments without a corresponding OSD in the osd dump.

Signed-off-by: Artem Torubarov <artem.torubarov@sap.com>
2026-08-04 11:28:21 +02:00
Artem Torubarov c9b1bfa805 osd: use a separate annotation to fence osd replacement instead of existing label
osd-replacement was relying on exising ceph.rook.io/do-not-reconcile
label for fencing osd destroy process owned by osd health goroutine from
controller. However, this label can be used but other components like
rook krew maintenance plugin and cannot be owned by osd-replacement
process. Added a separate osd.rook.io/replace-in-progress annotation for
that purpose.

Signed-off-by: Artem Torubarov <artem.torubarov@sap.com>
2026-07-29 11:03:29 +02:00
Artem Torubarov a0d215b428 osd: implement osd replacement health goroutine
A state machine for osd destroy phase of osd-replacement flow.
The state machine is implemented in OSD health goroutine, where each
step is handled on a separate tick. State machine is responsible
for draining, destroying OSD, and reserving its CRUSH position,
downscalling its deployment, and adding "readyForSwap" annotation.
Destroy phase does not zap the device on purpose. On disk signature
is kept to avoid automatic reprovisioning of destroyed OSD and to
detect physical swap.

Signed-off-by: Artem Torubarov <artem.torubarov@sap.com>
2026-07-27 18:42:07 +02:00
Artem Torubarov 514bd21552 osd: implement osd replacement controller
adds support of osd-replacement flow to cluster controller:
- predicate for osd deployment annotation
- validation of osd replacement annotation
- osd deployment recreation logic for replaced OSD

Signed-off-by: Artem Torubarov <artem.torubarov@sap.com>
2026-07-27 18:42:07 +02:00
Artem Torubarov c4727a0b21 osd: implement osd replacement crypto close job
defines a new entry point "close-encrypted-devices" in osd job.
The job is used by osd-replacement flow to close dm-crypt mappings
on host for destroyed encrypted OSDs. The job is owned by OSD
health goroutine implementing destroy phase of osd-replacement.

Signed-off-by: Artem Torubarov <artem.torubarov@sap.com>
2026-07-27 18:42:07 +02:00
Joshua Hoblitt 6fec883e62 Merge pull request #18013 from jhoblitt/ss-17966
osd: skip upgrades for OSDs pending migration when the last migration is incomplete
2026-07-23 07:52:49 -07:00
Joshua Hoblitt a9bd575002 Merge pull request #17968 from anxkhn/patch-21
mon: fix data race on failedMonSchedule during scheduling
2026-07-21 09:24:24 -07:00
Anas Khan 439b8c84d9 osd: skip upgrades for OSDs pending migration when the last migration is incomplete
startOSDMigration guards against upgrading OSDs while an OSD migration is
still in progress by returning the set of OSDs pending migration, which the
caller then removes from the update queue.

When the last migrated OSD's deployment has not been recreated yet,
isLastOSDMigrationComplete returns (false, nil). startOSDMigration then ran
return nil, errors.Wrapf(err, ...) with err already nil, and
errors.Wrapf(nil, ...) returns nil, so it returned (nil, nil), the same
value it uses to signal that no migration was requested. The caller
therefore skipped removing the pending OSDs from the update queue and could
upgrade and restart them mid-migration, which the pending-migration guard
was meant to prevent.

Return the freshly computed migration config in this case so the caller
still prunes the pending OSDs, without starting a new migration and without
aborting the reconcile. Aborting here would wedge the cluster because the
code that recreates the interrupted OSD runs later in Start, so an early
error return would leave that OSD deleted and block every later reconcile.
Letting the reconcile continue recreates the interrupted OSD and lets the
migration resume on a subsequent reconcile.

Also construct a non-nil error for the sibling unhealthy-PGs guard, which
wrapped a nil err in the same way.

Add a regression test asserting that startOSDMigration returns the pending
migration set, and does not delete another OSD deployment, while a previous
migration is still in progress.

Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
2026-07-20 17:51:30 -07:00
Joshua Hoblitt da490653a5 Merge pull request #17958 from anxkhn/patch-13
test: assert retained capacity LastUpdated in TestCephStatus
2026-07-20 17:29:56 -07:00
Anas Khan 0bbd5de84c mon: fix data race on failedMonSchedule during scheduling
assignMons schedules each mon in its own goroutine and shares a
failedMonSchedule bool to record whether any of them failed. The
resultLock mutex already guards the shared c.mapping.Schedule map
write, but the three failedMonSchedule = true assignments were done
without holding the lock. When two or more mons fail to schedule at
the same time (for example when waitForMonitorScheduling errors, the
node choice is nil, or getNodeInfoFromNode fails) their goroutines
write the flag concurrently, which is a write-write data race.

Guard the failedMonSchedule writes with the existing resultLock, the
same lock the goroutines already use for the map update. The post-Wait
read is left as is since the WaitGroup orders it after every write.

Add a regression test that fails scheduling for multiple mons at once
and confirms assignMons returns an error; run it with -race to catch
the race.

Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
2026-07-14 18:03:13 +05:30
Anas Khan 43464d81b7 mgr: use dashboard port 1024 as requested
Port 1024 is the lowest non-privileged port on Linux (privileged ports
are 0-1023), so it should be honored as-is like any port >= 1024. The
dashboardInternalPort guard used `<=` instead of `<`, which pushed a
requested Port of 1024 into the "privileged" branch and reset the
container/targetPort back to the default (7000/8443). That left the
Service Port at 1024 but its targetPort at the default, a mismatch that
contradicts the constant's comment and the identical Port 1025 case.

Change the comparison to `<` and add a boundary case to
TestStartSecureDashboard asserting both Port and targetPort are 1024.

Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
2026-07-14 16:49:32 +05:30
Anas Khan 71e688cf96 test: assert retained capacity LastUpdated in TestCephStatus
The capacity-retention case in TestCephStatus asserted
formatTime(now-1m) against formatTime(now-1m), comparing an
expression to itself. That assertion can never fail and never
looks at the value under test, so the branch in
toCustomResourceStatus that keeps the previous capacity when
newStatus.PgMap.TotalBytes is 0 was left unverified.

Seed a known LastUpdated on the current status alongside the
existing TotalBytes, then assert the aggregated status carries
that timestamp through. This checks that the prior capacity,
including its LastUpdated, is retained when total bytes drop to 0.
The sibling cases already assert Capacity.LastUpdated the same way.

Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
2026-07-14 15:21:19 +05:30
Artem Torubarov 75fe8db848 osd: rename internal OSD migration field to migrateOSD
Signed-off-by: Artem Torubarov <artem.torubarov@sap.com>
2026-07-10 11:45:47 +02:00
Parth Arora 6ee3198716 Merge pull request #17689 from subhamkrai/update-tnf-script-hostname
mon: update how hostname was set for drbd
2026-07-09 21:07:54 +05:30
subhamkrai c49ef5f079 mon: update how hostname was set for drbd
currently, drbd hostname was ready using command
but now the change we use kubernetes built-in api
to read hostname from `spec.nodeName`.`

Signed-off-by: subhamkrai <srai@redhat.com>
2026-07-07 08:45:28 +05:30
Anas Khan 47b4167b70 core: reconcile when node OSD topology labels change
shouldReconcileChangedNode only diffed the node spec, so changes to node
labels, including rook's own topology.rook.io/* labels, were never detected.
Relabeling a node therefore did not trigger a CephCluster reconcile until some
other condition eventually did.

Trigger a reconcile from the node update predicate when one of the OSD topology
labels rook cares about changes. The whitelist reuses the canonical label set
from topology.GetDefaultTopologyLabels() (the hostname, the Kubernetes
region/zone labels, and the topology.rook.io/* labels), so a reconcile is
scoped to topology changes instead of firing on any label or annotation change.
The UpdateFunc returns true directly for these changes because onK8sNode()
returns false for a node that is already an OSD host, which would otherwise
swallow the relabel.

Resolves #17652

Signed-off-by: Anas Khan <anas@anaskhan.me>
2026-07-07 07:38:15 +05:30
blackflytech c65663c529 core: use slices.Backward to simplify the code
Signed-off-by: blackflytech <blackflytech@outlook.com>
2026-07-01 00:37:50 +08:00
Joshua Hoblitt e5c6d75a73 core: narrow bare //nolint directives to specific linters
The //nolint directives at these sites omit the linter name, so each
suppresses every linter on its line rather than the one check it needs.
That hides any unrelated errcheck/gosec/govet finding later introduced
on the same line. Name the specific linter for each:

- staticcheck for the two operator sites: SA4004 (the intentional
  single-iteration loop in the OSD PVC host lookup) and SA1019 (the
  deliberate read of the deprecated S3.Enabled field in the RGW
  API-enable builder).
- errcheck for the rbd-mirror deferred token-file cleanup and the
  test-framework logging helpers (WriteString / writeHeader).

No behavior change.

Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
2026-06-29 16:32:59 -07:00
Joshua Hoblitt 993be34a24 Merge pull request #17834 from jhoblitt/docs/fix-stale-doc-comment-names
docs: fix function comments to match their declaration names
2026-06-29 12:04:25 -07:00
Blaine Gardner 485529056d Merge pull request #17764 from subhamkrai/mute-ceph-errors
core: add api changes to mute ceph warnings
2026-06-29 09:50:13 -06:00
Joshua Hoblitt 49612461a4 docs: fix function comments to match their declaration names
Several godoc comments led with a stale or incorrect identifier, left
over from renames, exported/unexported changes, copy-paste between
sibling declarations, or plain typos. As a result the documented name no
longer matched the function, method, type, or var it describes. Correct
each leading word to the name of the declaration it documents.

Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
2026-06-26 12:52:39 -07:00
pengqima 240c431f42 docs: fix function comment to match actual function name
Signed-off-by: pengqima <pengqima@outlook.com>
2026-06-26 23:43:22 +08:00
daixihegu 063dcad054 core: use slices.Contains to simplify code
Signed-off-by: daixihegu <daixihegu@163.com>
2026-06-25 10:17:53 +08:00
Travis Nielsen d9de5b1d6f Merge pull request #17758 from kavirakesh14/fix-17285-config-override-newline
ceph: ensure config overrides end with a trailing newline
2026-06-24 10:48:48 -06:00
subhamkrai 9a6c5842bc core: implement ceph health warning mute
this commit implement api to configure
ceph health warning mute/unmute.

Signed-off-by: subhamkrai <srai@redhat.com>
2026-06-24 21:10:54 +05:30
kavirakesh14 619b800b67 operator: fail reconcile if rook-config-override lacks trailing newline
Signed-off-by: kavirakesh14 <kavirakesh007@gmail.com>
2026-06-24 09:56:41 +00:00
Travis Nielsen 7803fac10d core: skip node watcher during initial cache sync
When the operator starts, there is no need to handle the
node watcher immediately while the controller runtime
cache is being initialized. The cluster will anyway be
fully reconciled and create new OSDs if needed. The node
watcher is only intended for triggering a reconcile when
a node is added or updated at a later time after a sync
would anyway be triggered.

Signed-off-by: Travis Nielsen <tnielsen@redhat.com>
2026-06-23 13:39:49 -06:00
Parth Arora 451c3f3d1b Merge pull request #17805 from parth-gr/drbd-mons
core: reduce the floating mon reschdule time
2026-06-23 20:55:48 +05:30
parth-gr 9e0b6e5bbe core: reduce the floating mon reschdule time
currently k8s add the default eviction time as 300 sec
setting it to 5 sec for the quick re-schedule

Signed-off-by: parth-gr <partharora1010@gmail.com>
2026-06-23 20:15:56 +05:30
Satoru Takeuchi a8398f9996 Merge pull request #17724 from jhoblitt/osd-activate-skip-rbd-scan
osd: do not scan rbd devices in raw activate fallback
2026-06-23 07:44:02 +09:00
Joshua Hoblitt da07f0c476 osd: do not scan rbd devices in raw activate fallback
When the OSD activate init container cannot match its configured
device, it falls back to a bare 'ceph-volume raw list', which
enumerates every block device on the node and opens each one to read
bluestore labels. Opening a krbd device whose backing cluster is
unhealthy can block in uninterruptible sleep; when that device's I/O
depends on the OSD being activated, activation deadlocks.

Build the fallback scan list explicitly with lsblk and exclude the
network-backed device types that can hang when their backing storage
is unavailable (rbd, nbd, drbd) along with zram (volatile RAM). Rook
never provisions OSDs on any of these, so the fallback can never
legitimately need to find an OSD on them. loop devices are kept,
since OSDs on loop devices are supported for CI and local testing.
Fail fast if the filtered list is empty rather than degenerating back
to a full scan.

Note this hardens only the rename-fallback path. The deadlock observed
in CI (kernel hung tasks under 'ceph-volume raw activate' opening a
stalled /dev/rbd0; actions runs 27325963851, 27333888237, and
27378983111, which reproduced it on this PR's own head) ultimately
originates inside ceph-volume: 'raw activate' runs an unconditional
LUKS2/TPM2 discovery sweep over all block devices even when given an
explicit --device. That requires a ceph-volume fix; this change makes
the Rook-controlled scan safe regardless of ceph version.

Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
2026-06-22 10:00:58 -07:00
Travis Nielsen 63eed4ed47 Merge pull request #17279 from sophotechlabs/test/osd-config-store
test: add unit tests for OSD store config parsing
2026-06-19 08:12:00 -06:00
subhamkrai ad26ebdab0 build: update ceph version to latest v20.2.2
updating the ceph version from v20.2.1 to v20.2.2

Signed-off-by: subhamkrai <srai@redhat.com>
2026-06-17 22:00:11 +05:30
Joshua Hoblitt 41c81a281c Merge pull request #17684 from jhoblitt/maint-remove-dead-osd-updatequeue-clear
osd: remove unused updateQueue.Clear method
2026-06-10 14:20:04 -07:00
Travis Nielsen a9235090f4 Merge pull request #17649 from yuxiang-he/node-label-device-class
osd: Support using node labels for OSD device class assignment
2026-06-08 16:07:07 -06:00
Joshua Hoblitt 50c95d343e osd: remove unused updateQueue.Clear method
The Clear method on updateQueue had no callers anywhere in the repo
(verified with grep, deadcode, and staticcheck). The queue is emptied via
Remove/Pop in practice. Remove the dead method.

Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
2026-06-08 15:01:15 -07:00
Joshua Hoblitt 80511ae2dc Merge pull request #17669 from jhoblitt/maint-remove-dead-ismoduleinspec
mgr: remove unused IsModuleInSpec function
2026-06-08 14:51:14 -07:00
Yuxiang He d9357dbfdc osd: support using node labels for OSD device class assignment
Add support for the osd.rook.io/device-class node label to assign
CRUSH device classes to all OSDs on a node.
The operator reads the label during OSD provisioning and
deployment reconciliation. If CR-level deviceClass conflicts
with the node label, the operator will skip reconciling the
node and logs an error.

Resolves: #17131
Signed-off-by: Yuxiang He <yuxiang@dropbox.com>
2026-06-08 13:21:05 -07:00
Joshua Hoblitt f8c0d36a50 mgr: remove unused IsModuleInSpec function
IsModuleInSpec has no callers anywhere in the repository (verified with
deadcode and grep). Remove the dead code.

Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
2026-06-08 08:54:43 -07:00
Sunnatillo f6fa25e844 osd: set require-osd-release from the health monitor
applyUpgradeOSDFunctionality() may run before all OSDs have registered
their new version, leaving require-osd-release unset and the cluster in
HEALTH_WARN.

Check for a single converged OSD version on each health-monitor tick and
set require-osd-release when it changes. The release name is cached to
avoid redundant ceph commands

Signed-off-by: Sunnatillo <sunnat.samadov@est.tech>
2026-06-04 16:54:36 +03:00
Artem Muterko 05da0d1294 test: add unit tests for OSD store config parsing
Signed-off-by: Artem Muterko <artem@sopho.tech>
2026-06-04 15:16:03 +02:00
Santosh 3e49c9f4cf osd: add cryptsetup resize for encrypted host based osds
when using encryptedDevice:true with host based (non pvc) osds, resizing
the underlying disk and restarting the OSD didn't expand the OSD because
the LUKS encryption layer was not resized.

This PR adds resize capabilities inside the activate container. Full
device stack must be resized: PV → LV → LUKS

Steps:
1. Run pvresize and lvextend to grow the LVM layers.
2. Retrieve the LUKS key from the Ceph config-key store using the
lockbox crednetials already available in the activate container
3. Pass the key explicitly to cryptsetup resize via --key-file.

Signed-off-by: Santosh <sapillai@redhat.com>
2026-05-29 12:09:17 +05:30
Joshua Hoblitt 8dd1778655 Merge pull request #17561 from jhoblitt/maint-ref-all-containers-by-name-instead-of-index
core: reference all containers in a spec by name instead of index
2026-05-26 12:10:09 -07:00
Joshua Hoblitt d059c351fc core: reference all containers in a spec by name instead of index
This changeset excludes converting _test.go code as there may be a
legitimate reasons (E.g. convenience) for unit test to be sensitive to
ordering.

Related to:
- https://github.com/rook/rook/issues/15291
- https://github.com/rook/rook/pull/16969

Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
2026-05-26 10:09:23 -07:00
Blaine Gardner 645aa741eb Merge pull request #17530 from rook/maint-rm-unused-consts-opus-4.7
core: rm unused consts
2026-05-20 09:01:05 -06:00
Travis Nielsen 67395ad5e4 Merge pull request #17545 from sp98/fix-TestAddRemoveNode-unit-test
osd: fix flaky TestAddRemoveNode failure
2026-05-15 13:39:11 -06:00
Sunnatillo 0bd299aa60 build: fix gosec and go vet lint errors for Go 1.26
Signed-off-by: Sunnatillo <sunnat.samadov@est.tech>
2026-05-15 21:45:06 +03:00
Santosh 6781d2e58d osd: fix flaky TestAddRemoveNode failure
User RaceFreeFakeWatcher isntead of FakeWatcher in TestAddRemoveNode
function. The test runs c.Start() in a goroutine whch stops the watcher
when done. If mockNodeOrchestrationCompeltion sends a watch ever after,
that, FakeWatcher panics with "send on a closed channel".
RaceFreeFakeWatcher safely ignores the sends on a stopped channel.

Signed-off-by: Santosh <sapillai@redhat.com>
2026-05-15 17:44:03 +05:30