Skip to content

Conversation

@trgill
Copy link
Collaborator

@trgill trgill commented Apr 15, 2025

Snapshot Manager is available on Centos 10, RHEL 9.6 and later

Update to be compatiable with legacy code that is already deployed.

Enhancement:

Use Snapshot Manager as a interface to LVM volumes rather than the LVM CLI.
#96

Reason:

Snapshot Manager will allow support for more volume types that are not just LVM. (Stratis, BTRFS)

Result:

Issue Tracker Tickets (Jira or BZ if any):
RHEL-64447
RHEL-61488

Summary by Sourcery

Add support for using the Snapshot Manager library as a backend for snapshot operations and refactor the existing LVM-based implementation into a modular ansible module_utils package. Introduce a feature flag to prefer snapm when available, keep the legacy LVM CLI path as fallback, and adjust role defaults and test suites accordingly.

New Features:

  • Use the external snapm (Snapshot Manager) Python API if present and at a sufficient version for all snapshot actions

Enhancements:

  • Refactor monolithic library/snapshot.py into separate modules (consts, lvm_utils, utils, lvm, snapmgr, validate) under module_utils/snapshot_lsr
  • Dispatch snapshot, check, remove, revert, extend, list, mount, and unmount commands through snapshot manager or legacy LVM code via a unified snapshot_cmd_execute function
  • Update role’s vars to install snapm and boom-boot packages on RHEL ≥9.6 and CentOS 10 and merge extra packages conditionally

Tests:

  • Revise and expand test playbooks to cover mount/unmount flows with snapshot sets
  • Adjust existing snapshot and extend tests for new command dispatch logic, including updated size percentages and failure expectations

lv = list_item["lv"]
except KeyError:
vg = None
lv = None

Check notice

Code scanning / CodeQL

Unused local variable Note

Variable lv is not used.
@trgill trgill force-pushed the snapm_support branch 6 times, most recently from 985ca4d to 87263a3 Compare May 16, 2025 01:41
@trgill trgill marked this pull request as ready for review May 16, 2025 02:33
@trgill trgill requested a review from spetrosi as a code owner May 16, 2025 02:33
@sourcery-ai
Copy link

sourcery-ai bot commented May 16, 2025

Reviewer's Guide

This PR refactors the snapshot role to support an alternative Snapshot Manager backend while maintaining compatibility with the existing LVM-based implementation. The monolithic snapshot.py library is slimmed down into a lightweight wrapper that imports and delegates to new module_utils under snapshot_lsr; commands are routed via use_snapshot_manager() based on snapm availability. Core logic is split into dedicated lvm, utils, snapmgr, validate, and consts modules, tests are updated to cover mount/umount operations and edge cases, and variable files now conditionally include snapm packages on supported distributions.

File-Level Changes

Change Details Files
Refactor main library to delegate to modular implementations
  • Removed all inline LVM-specific functions from library/snapshot.py
  • Imported commands and utilities from ansible.module_utils.snapshot_lsr
  • Added snapshot_cmd_execute() to route operations to LVM or SnapM backends
library/snapshot.py
Extract and reorganize code into snapshot_lsr module_utils
  • Created consts, lvm, utils, snapmgr, validate, and lvm_utils modules
  • Moved LVM CLI wrapper functions and state classes into snapshot_lsr/lvm_utils
  • Isolated JSON parsing, argument validation, and shared constants
module_utils/snapshot_lsr/consts.py
module_utils/snapshot_lsr/lvm.py
module_utils/snapshot_lsr/utils.py
module_utils/snapshot_lsr/snapmgr.py
module_utils/snapshot_lsr/validate.py
module_utils/snapshot_lsr/lvm_utils.py
Introduce Snapshot Manager backend integration
  • Added use_snapshot_manager() guard to detect snapm availability and version
  • Implemented mgr_* command functions in snapmgr.py to call snapm.manager APIs
  • Updated snapshot_cmd_execute to prefer snapmgr paths when enabled
module_utils/snapshot_lsr/snapmgr.py
library/snapshot.py
Update tests to cover new mount, extend, and backend behavior
  • Added mount and umount test sequences and failure assertions
  • Adjusted extend/revert tests for new minimum snapshot sizes and changed flags
  • Renamed test names and updated expected regexes and parameters
tests/tests_set_mount_verify_fail.yml
tests/tests_set_extend.yml
tests/tests_extend_basic.yml
tests/tests_revert_basic.yml
tests/tests_set_extend_verify_fail.yml
tests/tests_no_space_fail.yml
tests/tests_set_snapshot_no_space_fail.yml
Revise variable definitions to include snapm packages
  • Split __snapshot_packages into base and extra lists
  • Conditionally append snapm and boom-boot on RHEL ≥9.6, Fedora ≥41, CentOS10
  • Updated RedHat_8/9/10 and CentOS_10 var files accordingly
vars/main.yml
vars/RedHat_8.yml
vars/RedHat_9.yml
vars/RedHat_10.yml
vars/CentOS_10.yml

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @trgill - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Incorrect signature for mgr_remove_cmd (link)

  • In snapshot_cmd_execute(), there’s no default branch if cmd doesn’t match any SnapshotCommand, which can lead to returning None—add a fallback or explicit error for unrecognized commands.

  • The removal of the LC_ALL and LVM_COMMAND_PROFILE exports risks breaking JSON output parsing for lvm fullreport—either restore these environment settings or clearly document that they must be set externally.

Here's what I looked at during the review
  • 🔴 General issues: 1 blocking issue, 8 other issues
  • 🟢 Review instructions: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +233 to +243
def snapshot_cmd_execute(cmd, module, module_args, snapset_dict, vg_include):
cmd_result = None

if module_args["snapshot_lvm_verify_only"]:
rc, message = extend_verify_snapshot_set(module, snapset_dict)
if use_snapm:
if cmd == SnapshotCommand.SNAPSHOT:
cmd_result = mgr_snapshot_cmd(module, module_args, snapset_dict)
elif cmd == SnapshotCommand.CHECK:
cmd_result = mgr_check_cmd(module, module_args, snapset_dict)
elif cmd == SnapshotCommand.REMOVE:
cmd_result = mgr_remove_cmd(module_args, snapset_dict)
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Handle unexpected commands in snapshot_cmd_execute

Add a default else branch to log or return an explicit error to avoid returning None.

elif cmd == SnapshotCommand.CHECK:
cmd_result = mgr_check_cmd(module, module_args, snapset_dict)
elif cmd == SnapshotCommand.REMOVE:
cmd_result = mgr_remove_cmd(module_args, snapset_dict)
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Incorrect signature for mgr_remove_cmd

Update the call to mgr_remove_cmd to pass module along with module_args and snapset_dict, matching the other manager functions.

Comment on lines +429 to +439
return (
SnapshotStatus.ERROR_EXTEND_NOT_SNAPSHOT,
"LV with name: " + vg_name + "/" + snapshot_name + " is not a snapshot",
changed,
)
else:
return (
SnapshotStatus.ERROR_EXTEND_NOT_FOUND,
"snapshot not found with name: " + vg_name + "/" + snapshot_name,
changed,
)
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Use f-string instead of string concatenation [×5] (use-fstring-for-concatenation)


rc, _vg_exists, lv_exists = lvm_lv_exists(module, vg, snapshot_name)
if rc != SnapshotStatus.SNAPSHOT_OK:
return (
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Use f-string instead of string concatenation [×5] (use-fstring-for-concatenation)

Comment on lines +650 to +659
if suffix:
suffix_len = len(suffix)
else:
suffix_len = 0

if len(lv_name) + suffix_len > MAX_LVM_NAME:
return (
SnapshotStatus.ERROR_NAME_TOO_LONG,
"resulting snapshot name would exceed LVM maximum: " + lv_name + suffix,
)
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:

)

if not lv_exists:
return (
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:

Comment on lines +767 to +775
return (
SnapshotStatus.ERROR_VG_NOTFOUND,
"source volume group does not exist: " + vg_name,
)
if lv_name and not lv_found:
return (
SnapshotStatus.ERROR_LV_NOTFOUND,
"source logical volume does not exist: " + vg_name + "/" + lv_name,
)
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Use f-string instead of string concatenation [×4] (use-fstring-for-concatenation)

@richm
Copy link
Contributor

richm commented May 16, 2025

[citest]

@richm
Copy link
Contributor

richm commented May 16, 2025

[citest]

@richm
Copy link
Contributor

richm commented May 16, 2025

Need to remove the package definitions from the vars/Platform_X.yml files - vars/main.yml has the logic to determine which packages are available for which platform + version

Need vars/CentOS_9.yml as a symlink to vars/RedHat_9.yml

Need vars/CentOS_10.yml as a symlink to vars/RedHat_10.yml

@richm
Copy link
Contributor

richm commented May 17, 2025

[citest]

Snapshot Manager is available on Centos 10, RHEL 9 and RHEL 10.

Update to be compatiable with legacy code that is already deployed.

Note that Snapshot Manager has minimum sizes for any
snapshot of an origin.  If the minimum size is used, an extend may
not expand the size if the additional space is still below the
minimum size.  Currently the minimum size for snapm is 512 MiB.
Future versions will decrease to 64 MiB.  Some adjustment to the
extend tests were made in this change to deal with failures of
verify expecting expand to return true when the requested size was still
below the minimum.

Signed-off-by: trgill <[email protected]>
Co-authored-by: Richard Megginson <[email protected]>
@richm
Copy link
Contributor

richm commented May 17, 2025

[citest]

@richm richm merged commit e72b648 into linux-system-roles:main May 17, 2025
33 checks passed
@codecov
Copy link

codecov bot commented May 17, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Please upload report for BASE (main@1d0944f). Learn more about missing BASE report.

Additional details and impacted files
@@         Coverage Diff          @@
##             main   #97   +/-   ##
====================================
  Coverage        ?     0           
====================================
  Files           ?     0           
  Lines           ?     0           
  Branches        ?     0           
====================================
  Hits            ?     0           
  Misses          ?     0           
  Partials        ?     0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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