Skip to content

feat: backup and restore (vault + mysql) - #876

Open
Deezzir wants to merge 13 commits into
canonical:mainfrom
Deezzir:feat/backup-restore
Open

Deezzir wants to merge 13 commits into
canonical:mainfrom
Deezzir:feat/backup-restore

Conversation

@Deezzir

@Deezzir Deezzir commented Jul 6, 2026

Copy link
Copy Markdown

Overview

  • Adds sunbeam backup, sunbeam list-backups, and sunbeam restore commands for stateful workloads in the OpenStack model.
  • Introduces a component-driven backup/restore framework (BackupComponent) so command flow is generic while component specifics (target resolution, parse/list/restore plans) stay in one registry.
  • Supports MySQL and Vault, including backup inventory listing, restore execution, and manifest output.

Automation

In addition to the new commands, I am working on an experimental feature to automate the deployment and configuration of the s3-integrator charm for each MySQL and Vault component detected in the cluster. The branch is currently based on the current changes.

See: #890

The feature, at a minimum, deploys the s3-integrator for each target application, but the operator can choose to interactively set up the S3 location (single for all integrators).

Prerequisites

The current changes are blocked by the sunbeam-charms feature introduced in the PR, adding the pause/resume actions for the control plane services, like keystone, cinder, etc. The feature allows stopping the control-plane service's communication with the corresponding databases, so the restore can complete without concurrent writes.

QA

The new commands were validated end-to-end on a new Sunbeam Cluster (MAAS) on the personal SE-Cloud.

Demo

Backup

image

List Backups

image

Restore

image

@gboutry
gboutry self-requested a review July 9, 2026 11:45
@hmlanigan
hmlanigan requested a review from freyes July 10, 2026 19:06
@Deezzir
Deezzir force-pushed the feat/backup-restore branch 21 times, most recently from 0aab721 to 7338fbe Compare July 20, 2026 05:09
params[self.component.backup_id_param] = latest

try:
tenacity.Retrying(

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I found a race condition during a MySQL component restore. After the corresponding control-plane service is paused, there is a brief window during which MySQL may have dangling client connections, so the restore action will fail to close them. Having a retry here solves the issue, but I would like to come up with something more robust and reliable. Open to suggestions

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.

issue: I find this aggressive retry policy a bit concerning.

Was this tested with applications unpaused?

@Deezzir
Deezzir force-pushed the feat/backup-restore branch from c1983b3 to 434862a Compare July 20, 2026 07:05
@Deezzir
Deezzir marked this pull request as ready for review July 20, 2026 07:06

@gboutry gboutry 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.

I think this PR needs another pass with a more holistic view of the backup and restore workflows.

There is a lot of indirection, which makes the operational sequence and its safety properties difficult to reason about. In particular, BackupComponent does not appear to simplify the implementation: component-specific behavior still leaks into generic steps, especially around action parameters, point-in-time restore, pause/resume coordination, and failure recovery.

The force handling illustrates the problem. It is propagated through several layers without a clear definition of what it is supposed to bypass. In some paths it has no effect, while in others it becomes an action parameter even when the target charm does not support that parameter. This makes --force both unreliable and capable of breaking otherwise valid operations.

Before adding more fixes, I think we should simplify the design around explicit MySQL and Vault workflows, define the guarantees for backup, restore, rollback, and force behavior, and then test those workflows against the actual charm action contracts and supported database topologies. The current mock-heavy tests pass while still encoding assumptions that are invalid with Juju.

params[self.component.backup_id_param] = latest

try:
tenacity.Retrying(

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.

issue: I find this aggressive retry policy a bit concerning.

Was this tested with applications unpaused?

return sorted(successful, key=lambda b: b.backup_id)[-1].backup_id


def _api_app_for_mysql(app_name: str) -> str:

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.

The default MySQL topology is single MySQL app, and if we follow this Pull request, then, to which application is mysql tied to?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed in 80c3324

Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
@Deezzir

Deezzir commented Jul 22, 2026

Copy link
Copy Markdown
Author

@gboutry I've refactored the logic:

  1. Explicit VaultBackupComponent and MySQLBackupComponent classes that encapsulate the per-component backup/restore logic.
  2. Cleaned up stale step inputs (parameters)
  3. Removed tenacity retry in the Restore step; to fight the race condition, the MySQL restore plan now scales all mysql-router apps to clean up the stale client connections and proceed to restore.
  4. Cleaned up generic exceptions.
  5. Added logic to handle multi/single MySQL cluster topology

The 80c3324 commit should address all comments and change requests above

@Deezzir

Deezzir commented Aug 19, 2026

Copy link
Copy Markdown
Author

@hemanthnakkina I don't usually resolve the comments by myself, and they are from @gboutry. Should I resolve?

@hemanthnakkina

Copy link
Copy Markdown
Collaborator

ly resolve the comments by myself, and th

Atleast leave a comment against each conversation thread so that we know the comments are handled

@Deezzir

Deezzir commented Aug 21, 2026

Copy link
Copy Markdown
Author

@hemanthnakkina I've tried to handle requests in the latest commit, #876 (comment)

@Deezzir
Deezzir force-pushed the feat/backup-restore branch from 80c3324 to 9ddff30 Compare August 29, 2026 22:08
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>
@Deezzir
Deezzir force-pushed the feat/backup-restore branch from 9ddff30 to 1e32c98 Compare September 2, 2026 19:21
hemanthnakkina
hemanthnakkina previously approved these changes Sep 4, 2026

@hemanthnakkina hemanthnakkina 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.

LGTM

@gboutry gboutry 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.

Two restore defects found at this revision; details inline. The 92 targeted backup/restore unit tests passed using the project's native uv invocation. Separate mocked reproductions confirmed the uncaught exception paths and the stale-unit backup lookup.

Comment thread sunbeam-python/sunbeam/steps/backup_restore.py
Comment on lines +472 to +474
params = self.component.restore_params(
self.jhelper,
self.target,

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.

[P2] Use the refreshed leader for the backup lookup

The leader is refreshed at line 467, but restore_params() still receives the original self.target. For a latest-backup restore, latest_backup_params() runs list-backups on that original target.unit. If scale-down removed the previously selected leader, backup lookup targets a removed unit and fails before the restore action, which correctly uses the refreshed leader. Pass a target containing the refreshed leader when resolving backup parameters. A mocked leader-change reproduction confirmed list-backups targets the old unit while restore targets the refreshed leader.

@Deezzir Deezzir Sep 8, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed in ee47529

Signed-off-by: Deezzir <yurii.kondrakov@canonical.com>

@hemanthnakkina hemanthnakkina 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.

Overall LGTM, minor comments inline

Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
Comment thread sunbeam-python/sunbeam/steps/backup_restore.py Outdated
@hemanthnakkina
hemanthnakkina self-requested a review September 16, 2026 04:54

@gboutry gboutry 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.

Is there a plan for acceptance suite test integration?

@hmlanigan hmlanigan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Putting a hold on this PR until we resolve the feature freeze exception question, acceptance tests and documenation.

@Deezzir

Deezzir commented Sep 18, 2026

Copy link
Copy Markdown
Author

@hmlanigan @gboutry I don't completely understand what is being requested and why was it put on hold

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.

4 participants