Skip to content

fix(rgw): make RGW disable converge when repeated or interrupted - #887

Open
johnramsden wants to merge 2 commits into
rgw-stack/06-tls-reusefrom
rgw-stack/07-disable
Open

johnramsden wants to merge 2 commits into
rgw-stack/06-tls-reusefrom
rgw-stack/07-disable

Conversation

@johnramsden

@johnramsden johnramsden commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Description

DisableRGW returned at the first file that was already missing, and removeServiceDatabase returned an error when the services row was already gone. Disabling RGW is not one atomic step: stopping the snap service, dropping two database rows, and deleting several files can each fail independently, and a disable interrupted partway, or simply repeated, could therefore never finish.

DisableRGW now takes serviceStartMu for the whole teardown, matching every other path that starts, stops or reconfigures a service on the member, and follows a fixed order: stop the service, drop the record, only then delete files. The record is dropped before any file so a failure there leaves files and record consistent — a well-defined point for a retry to resume from — and every removal past that point tolerates a file already being gone instead of failing at the first one. Remaining failures are collected rather than returned on the first hit, then joined into one error and wrapped in ErrPlacementOperationFailed.

removeServiceDatabase treats a not-found from database.DeleteService as success, but only for the rgw service: mon, mgr and mds keep the strict behaviour, since an absent row for those means a real inconsistency, not a convergent retry.

Stack: PR 7 of 13. Merge in order. Each PR is one logical change on top of the one before it.

  1. feat(db): add a table for each member's last applied RGW frontend #881 feat(db): add a table for each member's last applied RGW frontend
  2. fix(services): keep error classes through the service enable path #882 fix(services): keep error classes through the service enable path
  3. feat(api): describe an RGW placement as an object with explicit TLS intent #883 feat(api): describe an RGW placement as an object with explicit TLS intent
  4. feat(rgw): make the member-side RGW apply safe to repeat #884 feat(rgw): make the member-side RGW apply safe to repeat
  5. feat(rgw): wait until the gateway really serves the requested frontend #885 feat(rgw): wait until the gateway really serves the requested frontend
  6. feat(rgw): reuse the member's own pair when TLS is asked for without one #886 feat(rgw): reuse the member's own pair when TLS is asked for without one
  7. fix(rgw): make RGW disable converge when repeated or interrupted #887 fix(rgw): make RGW disable converge when repeated or interrupted (this PR)
  8. feat(placement): accept the RGW object in the policy and keep its secrets out #888 feat(placement): accept the RGW object in the policy and keep its secrets out
  9. feat(placement): reconcile RGW across the cluster #889 feat(placement): reconcile RGW across the cluster
  10. test(robot): add the single-VM RGW placement suite #890 test(robot): add the single-VM RGW placement suite
  11. test(robot): add the three-VM RGW placement suite #891 test(robot): add the three-VM RGW placement suite
  12. docs: keep the RGW placement contract in HACKING.md for now #892 docs: keep the RGW placement contract in HACKING.md for now
  13. fix(rgw): do not trust a pending-apply marker the operator completed by hand #893 fix(rgw): do not trust a pending-apply marker the operator completed by hand

Reviewer note: this makes DisableRGW convergent at the unit level only; nothing yet calls it from a reconciliation loop, and nothing exercises it against a real snap. 09-reconcile dispatches removal through this same path, and the Robot suite in 10-robot-single exercises the partial-cleanup and repeat cases live.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How has this been tested?

  • Unit tests pass at this stack's cumulative tip

Contributor checklist

Please check that you have:

  • self-reviewed the code in this PR
  • added code comments, particularly in less straightforward areas
  • checked and added or updated relevant documentation
  • checked and added or updated relevant release notes
  • added tests to verify effectiveness of this change

@johnramsden
johnramsden added this pull request to stack #894 September 23, 2026 04:20
@johnramsden johnramsden changed the title rgw stack/07 disable fix(rgw): make RGW disable converge when repeated or interrupted Sep 23, 2026
@johnramsden
johnramsden marked this pull request as ready for review September 23, 2026 04:30
@johnramsden
johnramsden force-pushed the rgw-stack/07-disable branch 2 times, most recently from 02a3a1e to 3c82483 Compare September 29, 2026 19:50

@sabaini sabaini left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tiny test nit

Comment thread microceph/ceph/services_placement_rgw_test.go Outdated
johnramsden added a commit that referenced this pull request Oct 1, 2026
Use Lstat so a dangling symlink cannot satisfy the cleanup assertion.

Review: #887 (comment)

Assisted-by: omp:openrouter/openai/gpt-6-astra
Signed-off-by: John Ramsden <john.ramsden@canonical.com>
@johnramsden
johnramsden force-pushed the rgw-stack/07-disable branch from 3c82483 to 0d9089a Compare October 1, 2026 18:07
@johnramsden
johnramsden requested a review from sabaini October 2, 2026 04:19

@sabaini sabaini left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty!

johnramsden and others added 2 commits October 5, 2026 17:46
DisableRGW in ceph/rgw.go returned at the first file that was already missing, and removeServiceDatabase in ceph/services.go returned an error when the services row was already gone. Disabling RGW is not one atomic step: stopping the snap service, dropping two database rows, and deleting several files can each fail independently, and a disable interrupted partway, or simply repeated, could therefore never finish.

DisableRGW now takes serviceStartMu for the whole teardown, matching every other path that starts, stops or reconfigures a service on the member, and follows a fixed order: stop the service, drop the record, only then delete files. The record is dropped before any file so a failure there leaves files and record consistent, a well-defined point for a retry to resume from, and every removal past that point tolerates a file already being gone (removeIgnoreMissing or os.RemoveAll) instead of failing at the first one. Remaining failures are collected rather than returned on the first hit, so a retry sees and fixes everything left over in one pass instead of one file per call, then joined into one error and wrapped in ErrPlacementOperationFailed.

removeServiceDatabase treats a NotFound from database.DeleteService as success, but only for the "rgw" service: mon, mgr and mds keep the strict behaviour, since an absent row for those means a real inconsistency, not a convergent retry, and still fail loudly. deleteServiceRecordFunc and deleteRGWFrontendFunc are injectable so this can be tested without dqlite.

This makes DisableRGW convergent at the unit level only; nothing yet calls it from a reconciliation loop, and nothing exercises it against a real snap. "feat(placement): reconcile RGW across the cluster" dispatches removal through this same path and relies on the guarantee added here, and the suite added in "test(robot): add the single-VM RGW placement suite" exercises the partial-cleanup and repeat cases live.

Co-authored-by: Peter Sabaini <peter.sabaini@canonical.com>
Assisted-by: claude-code:claude-fable-5-1
Assisted-by: pi:gpt-6-astra
Signed-off-by: John Ramsden <john.ramsden@canonical.com>
Use Lstat so a dangling symlink cannot satisfy the cleanup assertion.

Review: #887 (comment)

Assisted-by: omp:openrouter/openai/gpt-6-astra
Signed-off-by: John Ramsden <john.ramsden@canonical.com>
@johnramsden
johnramsden force-pushed the rgw-stack/07-disable branch from 0d9089a to 6443956 Compare October 6, 2026 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants