Move to using verified_reboot to manage reboots for Bigboot; infra.lvm_snapshots is local for testing this
This commit is contained in:
parent
e4245dfb58
commit
6c69d48268
5
.gitignore
vendored
5
.gitignore
vendored
@ -5,6 +5,9 @@ misc
|
||||
filter_plugins/__pycache__
|
||||
filter_plugins/*.bak
|
||||
python/
|
||||
collections/ansible_collections
|
||||
collections/ansible_collections/ansible*
|
||||
collections/ansible_collections/community*
|
||||
collections/ansible_collections/rhc*
|
||||
roles/autofsck
|
||||
roles/verified_reboot
|
||||
*.bak
|
||||
|
@ -0,0 +1,8 @@
|
||||
download_url: https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/infra-lvm_snapshots-2.1.0.tar.gz
|
||||
format_version: 1.0.0
|
||||
name: lvm_snapshots
|
||||
namespace: infra
|
||||
server: https://galaxy.ansible.com/api/
|
||||
signatures: []
|
||||
version: 2.1.0
|
||||
version_url: /api/v3/plugin/ansible/content/published/collections/index/infra/lvm_snapshots/versions/2.1.0/
|
18
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/ansible-lint.yml
vendored
Normal file
18
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/ansible-lint.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
name: Ansible Lint
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
- workflow_call
|
||||
|
||||
jobs:
|
||||
ansible-lint:
|
||||
name: Ansible Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run ansible-lint
|
||||
uses: ansible/ansible-lint@main
|
15
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/codespell.yml
vendored
Normal file
15
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/codespell.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: CodeSpell
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
- workflow_call
|
||||
|
||||
jobs:
|
||||
codespell:
|
||||
name: Check for spelling errors
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: codespell-project/actions-codespell@master
|
59
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/pycodestyle.yml
vendored
Normal file
59
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/pycodestyle.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
name: PyCodeStyle
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
- workflow_call
|
||||
|
||||
jobs:
|
||||
python-3:
|
||||
name: PyCodeStyle
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install pylint
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pycodestyle
|
||||
|
||||
- name: Analysing the code with pylint
|
||||
run: |
|
||||
pycodestyle --config=./.pycodestyle .
|
||||
|
||||
python-2-7:
|
||||
name: PyCodeStyle
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: python:2.7.18-buster
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["2.7"]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install pylint
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pycodestyle
|
||||
|
||||
- name: Analysing the code with pylint
|
||||
run: |
|
||||
pycodestyle --config=./.pycodestyle .
|
59
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/pylint.yml
vendored
Normal file
59
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/pylint.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
name: PyLint
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
- workflow_call
|
||||
|
||||
jobs:
|
||||
python-3:
|
||||
name: PyLint
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install pylint
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pylint
|
||||
|
||||
- name: Analysing the code with pylint
|
||||
run: |
|
||||
find . -name '*.py' -exec pylint {} \;
|
||||
|
||||
python-2-7:
|
||||
name: PyLint
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: python:2.7.18-buster
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["2.7"]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install pylint
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pylint
|
||||
|
||||
- name: Analysing the code with pylint
|
||||
run: |
|
||||
find . -name '*.py' -exec pylint {} \;
|
140
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/release.yml
vendored
Normal file
140
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
name: Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
ansible-lint:
|
||||
uses: redhat-cop/infra.lvm_snapshots/.github/workflows/ansible-lint.yml@main
|
||||
pylint:
|
||||
uses: redhat-cop/infra.lvm_snapshots/.github/workflows/pylint.yml@main
|
||||
pycodestyle:
|
||||
uses: redhat-cop/infra.lvm_snapshots/.github/workflows/pycodestyle.yml@main
|
||||
shellcheck:
|
||||
uses: redhat-cop/infra.lvm_snapshots/.github/workflows/shellcheck.yml@main
|
||||
codespell:
|
||||
uses: redhat-cop/infra.lvm_snapshots/.github/workflows/codespell.yml@main
|
||||
prechecks:
|
||||
needs:
|
||||
- ansible-lint
|
||||
- pylint
|
||||
- pycodestyle
|
||||
- shellcheck
|
||||
- codespell
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: >-
|
||||
python -c "assert set([
|
||||
'${{ needs.ansible-lint.result }}',
|
||||
'${{ needs.pylint.result }}',
|
||||
'${{ needs.pycodestyle.result }}',
|
||||
'${{ needs.shellcheck.result }}',
|
||||
'${{ needs.codespell.result }}',
|
||||
]) == {'success'}"
|
||||
infra_release:
|
||||
needs:
|
||||
- prechecks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install Ansible
|
||||
run: pip install --upgrade ansible-core
|
||||
|
||||
- name: Update version in galaxy.yml
|
||||
run: sed -i 's/version:.*$/version:{{:dumb_space_issue:}}${{ github.ref_name }}/' galaxy.yml; sed -i 's/{{:dumb_space_issue:}}/ /' galaxy.yml
|
||||
|
||||
- name: Build collection
|
||||
run: ansible-galaxy collection build -vvv
|
||||
shell: bash
|
||||
working-directory: ${{ vars.GITHUB_PATH }}
|
||||
|
||||
- name: Get tar name
|
||||
run: echo "tar_file=$(ls | grep '.tar')" >> $GITHUB_OUTPUT
|
||||
id: build
|
||||
|
||||
- name: Get version
|
||||
run: echo "NUM=$(cat galaxy.yml | grep version | cut -d ':' -f 2 | awk '{print $1}')" >> $GITHUB_OUTPUT
|
||||
id: vers
|
||||
|
||||
- name: Install collection
|
||||
run: ansible-galaxy collection install ./infra-lvm_snapshots-${{ steps.vers.outputs.NUM }}.tar.gz -p /home/runner/collections
|
||||
shell: bash
|
||||
working-directory: ${{ vars.GITHUB_PATH }}
|
||||
|
||||
- name: Publish to Automation Hub
|
||||
run: |
|
||||
cat << EOF > ansible.cfg
|
||||
[galaxy]
|
||||
server_list = rh_automation_hub
|
||||
[galaxy_server.rh_automation_hub]
|
||||
url=https://cloud.redhat.com/api/automation-hub/
|
||||
auth_url=https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token
|
||||
token=${{ secrets.CONSOLE_API_KEY }}
|
||||
EOF
|
||||
ansible-galaxy collection publish ${{ steps.build.outputs.tar_file }}
|
||||
rm ansible.cfg
|
||||
|
||||
- name: Publish to galaxy
|
||||
run: ansible-galaxy collection publish --api-key=${{ secrets.GALAXY_INFRA_KEY }} ${{ steps.build.outputs.tar_file }}
|
||||
|
||||
- name: Upload files to tag
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ${{ steps.build.outputs.tar_file }}
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
changelog:
|
||||
needs:
|
||||
- infra_release
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ANSIBLE_FORCE_COLOR: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install Ansible
|
||||
run: pip install --upgrade ansible-core antsibull-changelog
|
||||
|
||||
- name: Update version in galaxy.yml
|
||||
run: sed -i 's/version:.*$/version:{{:dumb_space_issue:}}${{ github.ref_name }}/' galaxy.yml; sed -i 's/{{:dumb_space_issue:}}/ /' galaxy.yml
|
||||
|
||||
- name: Run changelog
|
||||
run: antsibull-changelog release --verbose --version ${{ github.ref_name }}
|
||||
|
||||
- name: Create Pull Request
|
||||
id: prcreate
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Update changelog ${{ github.ref_name }}
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
signoff: false
|
||||
base: main
|
||||
branch: changelog-patches
|
||||
delete-branch: true
|
||||
title: '[RELEASE] Update changelog ${{ github.ref_name }}'
|
||||
body: |
|
||||
Update changelog
|
||||
- Updated with changelog for release ${{ github.ref_name }}
|
||||
- Auto-generated by [create-pull-request][1]
|
||||
|
||||
[1]: https://github.com/peter-evans/create-pull-request
|
||||
labels: |
|
||||
changelog
|
||||
automated pr
|
||||
draft: false
|
||||
...
|
18
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/shellcheck.yml
vendored
Normal file
18
collections/ansible_collections/infra/lvm_snapshots/.github/workflows/shellcheck.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
name: ShellCheck
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
- workflow_call
|
||||
|
||||
jobs:
|
||||
shellcheck:
|
||||
name: Shellcheck
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run ShellCheck
|
||||
uses: ludeeus/action-shellcheck@master
|
@ -0,0 +1,2 @@
|
||||
[pycodestyle]
|
||||
max-line-length=120
|
@ -0,0 +1,137 @@
|
||||
=====================================
|
||||
LVM Snapshot Linux Role Release Notes
|
||||
=====================================
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
v2.0.3
|
||||
======
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix how locking is disabled for newer LVM versions
|
||||
- Fix missing role metadata
|
||||
- Fix potential space exhaustion when restoring previous initramfs
|
||||
|
||||
v2.0.2
|
||||
======
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add bigboot progress messages so inpatient operators don't think their server is hung
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Clean up bad math in bigboot.sh
|
||||
- Fix bigboot device not found error
|
||||
- Fix bigboot fail when autoactivation property not set
|
||||
- Fix vgs not found error
|
||||
- Round down requested size to multiple of extent size
|
||||
- Shorten bigboot.sh usage help message to not exceed the kmsg buffer
|
||||
- Use sectors with sfdisk
|
||||
|
||||
v2.0.1
|
||||
======
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add publish to Automation Hub to release workflow
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix release workflow prechecks
|
||||
|
||||
v2.0.0
|
||||
======
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- bigboot - Rename internal variables with role name prefix
|
||||
- initramfs - Rename internal variables with role name prefix
|
||||
- shrink_lv - Rename internal variables with role name prefix
|
||||
|
||||
Breaking Changes / Porting Guide
|
||||
--------------------------------
|
||||
|
||||
- Split lvm_snapshots role into snapshot_create, snapshot_revert and snapshot_remove
|
||||
|
||||
v1.1.2
|
||||
======
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Updated links in docs and workflows to reflect move to redhat-cop org
|
||||
|
||||
v1.1.1
|
||||
======
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix "Failed to list block device properties" error
|
||||
- Fix dracut path
|
||||
|
||||
v1.1.0
|
||||
======
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- New role, bigboot, to increase the boot partition while moving, and shrinking if needed, the adjacent partition
|
||||
- New role, initramfs, to execute an atomic flow of building and using a temporary initramfs in a reboot and restoring the original one
|
||||
- New role, shrink_lv, to decrease logical volume size along with the filesystem
|
||||
|
||||
v1.0.3
|
||||
======
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Changed the lvm_snapshots_boot_backup var default to false
|
||||
- Removed unimplemented lvm_snapshots_use_boom var from the docs
|
||||
- Revert - wait for snapshot to drain before returning
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add task to ensure tar package is present
|
||||
- Grub needs reinstall if /boot is on LVM
|
||||
- Wrong kernel version booting after rolling back
|
||||
|
||||
v1.0.2
|
||||
======
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Create snapshots with normalized sizes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Existing Snapshots with Different Name Cause verify_no_existing_snapshot.yml to Fail
|
||||
|
||||
v1.0.1
|
||||
======
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Initial MVP release
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add boot backup support
|
||||
- Add support for checking before resizing logical volumes
|
||||
|
||||
v1.0.0
|
||||
======
|
||||
|
@ -0,0 +1,3 @@
|
||||
@swapdisk
|
||||
@ygalblum
|
||||
@heatmiser
|
@ -0,0 +1,5 @@
|
||||
# Contributing
|
||||
|
||||
Thank you for your interest in contributing to the LVM Snapshots Collection. All we ask is that contributors please observe the [Ansible Community Guidelines](https://docs.ansible.com/ansible/devel/community/index.html) and follow the [Ansible Collections Contributor Guide](https://docs.ansible.com/ansible/devel/community/contributions_collections.html). We look forward to reviewing your pull request.
|
||||
|
||||
Everyone is invited to participate. We welcome first timers as well as experienced open source contributors. If you are unsure how to get started with your contribution, open a [new issue](https://github.com/redhat-cop/infra.lvm_snapshots/issues/new/choose) explaining what you want to do and we'll do our best to help!
|
670
collections/ansible_collections/infra/lvm_snapshots/FILES.json
Normal file
670
collections/ansible_collections/infra/lvm_snapshots/FILES.json
Normal file
@ -0,0 +1,670 @@
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"name": ".",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_remove",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_remove/tasks",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_remove/tasks/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "509ab8a1e07e4d71837884e88d8190ef13f58745ee10a8ade71e73e788308087",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_remove/README.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "5e2d063f1f2eb572281101338b21d84d0ec3cf171a7ade4cf456c54179f4f2e6",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_remove/meta",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_remove/meta/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "606e6e273462d94697558655fa3bfb1491e3474b112bd1e3a549115d50b44632",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/tasks",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/tasks/preflight.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "b1418bba68bd83500aee8fb067562e4cae27dd1c6585d74938f1d3b15a5c575a",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/tasks/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "6e33876d82d59a25393985cd9948ee16b6ab29a7585c8ba2b30197ab16f7a767",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/README.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "c628601c9a2f5c904131e0dc9c0e79f3c6f189b30bf64de651d95986f9bb9f02",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/meta",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/meta/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "825f9c7e7b25072c135162acead4ed57c8ab270b3dabc7b7eb626b6d35bdb050",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/defaults",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/initramfs/defaults/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "f201653d875b43e7915feb027605fc95b1955debe5535f131ac07821fb6bc878",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_revert",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_revert/tasks",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_revert/tasks/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "5c80af9b54761322d9c7fb7a5366f32784d455f417aa05545f64e8efd3350b08",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_revert/tasks/verify_snapshot_active.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "339d8c553502c3807457f2c3f9f7e8bfb136d260e73cc9e87e1990befacb69a5",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_revert/README.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "5d4174b8205d0a5c8c900a57260fd6ae66b84cdffd698eb44048bbfa58b2cff0",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_revert/meta",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_revert/meta/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "642e5210da82a46d6bf143c0dfcb40af3866057defe55e9cf268a2ff6a1e892e",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/tasks",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/tasks/create.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "4be981713a7b7c9b784fb60170c3aea095073cd35d591cca006a782f0f7b7356",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/tasks/check.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "d9fb57d25714b52d131ac49fc3471dd0e78a29fe39b4e853a880a8007ef92ca8",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/tasks/verify_volume_exists.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "87fb805b1619aa98d312deb540775a14c3282b6f4515ecdeaa1690fa51e73339",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/tasks/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "47495cf552f5c4038303911f8f7786a41c6397cea379ab0d70cb76fe015ebe10",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/tasks/verify_no_existing_snapshot.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "724a282c30555bd9e0950675885999537b9200de1e7823509f583f09195a938d",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/README.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "7c6e97382311dfee2ae894ad656fbe292a17d54c9029e5ce07c1587e09fe9c14",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/files",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/files/check.py",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "911f7680558f08a7bd2d415a250e7e2b7d60aef2a633f0ce4d6bfa87b08db076",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/meta",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/meta/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "d0c9faaf48633e7d073817625fbf0d95f975c69dd2201b99c52f557e15c6431e",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/defaults",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/snapshot_create/defaults/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "25d6004aad8f7ffa6417bb5be7e28a7c06f22c641ce4b66ef31afc67bc972312",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/templates",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/templates/shrink-start.sh.j2",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "aa1864ed4b3767f2c75b984d80a8a80667e0bbdba43ef049f03e9abbd4f6b030",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/tasks",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/tasks/preflight.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "97eb164e678d888f95513079d7d22001b0af23a17899b94bd82cafba3808eea1",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/tasks/main.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "2717ed24e19652be68fe5120f22f77e7b5fea969b8cb97257d77302710f0417d",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/tasks/check_device.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "201415597a64407c404134452f90b7ffe62370e10c245040cffb5c3be7d4ac2c",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/README.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "4da5f48565753fcfac29f1856454085f503c207578eb6c58d750e2c76baedcbb",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/files",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/files/shrink.sh",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "1bdf2d37411ea35c3e91c6427677775fee37c783bfb948d55cbfc6e11a0c89aa",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/files/module-setup.sh",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "b0b9d303e9b2ce57ce4b6e8ee801471b7ae2763d65912677ce2c6f6d1d2c3f09",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/meta",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/meta/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "31e41f67bd856b5055e161e55c013397a145d3170c612bd7999fd2e9a3706526",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/defaults",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/shrink_lv/defaults/main.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "ad38f2c50795ab06e4b13ffd6b78083c72508efc60e90681a85e2eb29f474a19",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/templates",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/templates/increase-boot-partition.sh.j2",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "3a2850a945c6e14103b119713f8b0e0d7d5c58dcf9853cb80587cdbb49e75a72",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/tasks",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/tasks/prep_lvm.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "e7ef8b4e143d1f04a71a91438606d8d5ef61186169dffa0661cdac5ac65c7c5d",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/tasks/prep_btrfs.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "e51169ec2589645540a59d49e91d35790d1f04bd60b9d2e0498d26a115bcbbf4",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/tasks/get_boot_device_info.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "6fefba635d26df89f1cf4308f93f82ead07e457e13d8a45c3eaa532c1338f9e7",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/tasks/do_bigboot_reboot.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "342d2c4bbd4d91590e62984ee7d4ed78cb5ca97e6970a7a4d071839e89cf46c5",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/tasks/main.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "dbd58033393e580312d40e2fed7a3dda261f26e8393d28830205c89b4b24c3a5",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/README.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "a8a1734d9f3803f6ccae7eb57531d04caf2da1be0adcfa41ed6c4d9b25dd85e1",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/files",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/files/module-setup.sh",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "0a3130bbbbda27623f91f00735285641f7480b75201df8f8252bc0b0e1215bfb",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/files/bigboot.sh",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "17e3dde12e2b102eb2eca1a11f2a62e0e4b6d8b982c75da0a2dd194bf8be3122",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/files/sfdisk.static",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "aebb9ea3b54f739dafef4b2e581ffbc6c72847487ba0dd6b1c7fceb26277985d",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/meta",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/meta/main.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "fafb7ac1801552bafb0a71a6d5ddea32ba4699acaa179a32689f316b47d7db07",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/defaults",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "roles/bigboot/defaults/main.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "2546f99a2ca7a0a9a7fc93efdb989581d5ae6b8c5dae798877fb6bbf48f597de",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "CONTRIBUTING.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "b380120df01b9bdb8d8a9db37688f9ca2d56de8d65fa26503156a6819371d487",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "README.md",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "ff0b7f4f22711076d82f03cf5f6fc77f947a4d4756e1292c9d1b9af116a2f935",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "LICENSE",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "aa611f74dc5804197879f24d3f192f438845fae8e1dda9053e8637fccda0d05a",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs/.plugin-cache.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "17bc457386b91d2469190e384af050f297d4109710d57bf686400ab53bab4c99",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs/config.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "7d9693a308a709ae4d30cde6a08ed9ebd9cd6f1222aa251c44e6122ea84a50d3",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs/fragments",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs/fragments/.gitkeep",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs/fragments/more_idempotent.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "2d436efd751cff9c1d021f6af4ef405cbf8182fdcb169e1873ff8e8735404fff",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs/fragments/btrfs_bigboot.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "3871d625e89227e10bd82c3a9ba3a16f5ff8f1d86887782f3ff971e13ac8e7f1",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "changelogs/changelog.yaml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "dcde0629116149ea3e53f2ea71ea4195c3dd560266cad9b28737cc1c424cd755",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github/workflows",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github/workflows/pylint.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "af052a539c6b2dcfa7c8388c599e9f0bc58b72f90ea1ad3f958a2e9f6c32a234",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github/workflows/ansible-lint.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "52b5b419c651b390716392600738b63b75d5b4431c127dab064fd39762cdf9f1",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github/workflows/shellcheck.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "2b8a5ab122a75643a2941d2fea2b876c8ef55f6eff41b20896e4ede9e76788c8",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github/workflows/codespell.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "de7825f066c930358517755935e05df6ac8a4566df9a4a7affc7ec8c12d64a77",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github/workflows/release.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "12387e85a382cf64ac8eed9e9c1282ae15e1d38c087efbc64f6ee16b7953367d",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".github/workflows/pycodestyle.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "016e1649c987f5265f14bbffd125e9cffdabb8a0adac1eb49fac556b3ca157d3",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "CHANGELOG.rst",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "6a37c02d6aa4fce47aa56689a5e9c0c1f681f65479ae589732017edab3e318aa",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "CODEOWNERS",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "a2277cb0ecb46693ddba53cff778757052e73481e7ac2cf623f1a3e327913117",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": ".pycodestyle",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "9bc6971355aed1f873d5daa68c393c84fa3c8ef26f71c975f4fd8afa3b690156",
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"ftype": "dir",
|
||||
"chksum_type": null,
|
||||
"chksum_sha256": null,
|
||||
"format": 1
|
||||
},
|
||||
{
|
||||
"name": "meta/runtime.yml",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "16fee19238e61fab14a7974fd79800cd659367bbc8b052d9f0b190108f6a2c53",
|
||||
"format": 1
|
||||
}
|
||||
],
|
||||
"format": 1
|
||||
}
|
21
collections/ansible_collections/infra/lvm_snapshots/LICENSE
Normal file
21
collections/ansible_collections/infra/lvm_snapshots/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Red Hat
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,35 @@
|
||||
{
|
||||
"collection_info": {
|
||||
"namespace": "infra",
|
||||
"name": "lvm_snapshots",
|
||||
"version": "2.1.0",
|
||||
"authors": [
|
||||
"Ygal Blum <yblum@redhat.com>",
|
||||
"Bob Mader <bob@redhat.com>"
|
||||
],
|
||||
"readme": "README.md",
|
||||
"tags": [
|
||||
"ansible",
|
||||
"lvm",
|
||||
"storage"
|
||||
],
|
||||
"description": "Ansible role for creating and rolling back LVM snapshots",
|
||||
"license": [],
|
||||
"license_file": "LICENSE",
|
||||
"dependencies": {
|
||||
"community.general": "*"
|
||||
},
|
||||
"repository": "https://github.com/redhat-cop/infra.lvm_snapshots",
|
||||
"documentation": "https://github.com/redhat-cop/infra.lvm_snapshots",
|
||||
"homepage": "https://github.com/redhat-cop/infra.lvm_snapshots",
|
||||
"issues": "https://github.com/redhat-cop/infra.lvm_snapshots/issues"
|
||||
},
|
||||
"file_manifest_file": {
|
||||
"name": "FILES.json",
|
||||
"ftype": "file",
|
||||
"chksum_type": "sha256",
|
||||
"chksum_sha256": "d5511e77f16eea344fcd5c4f879eae5752db76b5cdfc848ea541b2d8d02727bc",
|
||||
"format": 1
|
||||
},
|
||||
"format": 1
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
# LVM Snapshots Collection
|
||||
|
||||
[](https://github.com/redhat-cop/infra.lvm_snapshots/actions) [](https://github.com/redhat-cop/infra.lvm_snapshots/actions) [](https://www.bestpractices.dev/projects/8141)
|
||||
|
||||
## Overview
|
||||
|
||||
A reliable snapshot/rollback capability is a key feature required to enable the success of RHEL In-place Upgrade automation solutions. Without it, users will be wary of using the solution because of the potential risk that their applications may not function properly after the OS upgrade. Including automation so that snapshot creation happens right before the OS upgrade reduces this risk. If there are any application issues uncovered after the OS upgrade, a rollback playbook can be executed to instantly revert the environment back to the original state as it was before the upgrade. Application teams will no longer have an excuse not to use in-place upgrades to bring their RHEL estate into compliance.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Ansible Version
|
||||
|
||||
This collection requires ansible from version `2.14.0` and above
|
||||
|
||||
### Collections
|
||||
|
||||
This collection depends on the following collections
|
||||
|
||||
```yaml
|
||||
- "community.general": "*"
|
||||
```
|
||||
|
||||
## Roles
|
||||
|
||||
These are the roles included in the collection. Follow the links below to see the detailed documentation and example playbooks for each role.
|
||||
|
||||
- [`snapshot_create`](./roles/snapshot_create/) - controls the creation for a defined set of LVM snapshot volumes
|
||||
- [`snapshot_remove`](./roles/snapshot_remove/) - used to remove snapshots previously created using the `snapshot_create` role
|
||||
- [`snapshot_revert`](./roles/snapshot_revert/) - used to revert to snapshots previously created using the `snapshot_create` role
|
||||
- [`shrink_lv`](./roles/shrink_lv/) - controls decreasing logical volume size along with the filesystem
|
||||
- [`bigboot`](./roles/bigboot/) - controls increasing of the boot partition while moving, and shrinking if needed, the adjacent partition
|
||||
- [`initramfs`](./roles/initramfs/) - controls the atomic flow of building and using a temporary initramfs in a reboot and restoring the original one
|
||||
|
||||
## Installing the collection from Ansible Galaxy
|
||||
|
||||
Before using this collection, you need to install it with the Ansible Galaxy command-line tool:
|
||||
|
||||
```bash
|
||||
ansible-galaxy collection install infra.lvm_snapshots
|
||||
```
|
||||
|
||||
You can also include it in a `requirements.yml` file and install it with `ansible-galaxy collection install -r requirements.yml`, using the format:
|
||||
|
||||
```yaml
|
||||
---
|
||||
collections:
|
||||
- name: infra.lvm_snapshots
|
||||
```
|
||||
|
||||
Note that if you install the collection from Ansible Galaxy, it will not be upgraded automatically when you upgrade the `ansible` package. To upgrade the collection to the latest available version, run the following command:
|
||||
|
||||
```bash
|
||||
ansible-galaxy collection install infra.lvm_snapshots --upgrade
|
||||
```
|
||||
|
||||
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax to install version `1.0.0`:
|
||||
|
||||
```bash
|
||||
ansible-galaxy collection install infra.lvm_snapshots:==1.0.0
|
||||
```
|
||||
|
||||
See [Using Ansible collections](https://docs.ansible.com/ansible/devel/user_guide/collections_using.html) for more details.
|
||||
|
||||
## Contributing
|
||||
|
||||
We appreciate participation from any new contributors. Get started by opening an issue or pull request. Refer to our [contribution guide](CONTRIBUTING.md) for more information.
|
||||
|
||||
## Reporting issues
|
||||
|
||||
Please open a [new issue](https://github.com/redhat-cop/infra.lvm_snapshots/issues/new/choose) for any bugs or security vulnerabilities you may encounter. We also invite you to open an issue if you have ideas on how we can improve the solution or want to make a suggestion for enhancement.
|
||||
|
||||
## More information
|
||||
|
||||
This collection is just one building block of our larger initiative to make RHEL in-place upgrade automation that works at enterprise scale. Learn more about our end-to-end approach for automating RHEL in-place upgrades at this [blog post](https://red.ht/bobblog).
|
||||
|
||||
## Release notes
|
||||
|
||||
See the [changelog](https://github.com/redhat-cop/infra.lvm_snapshots/tree/main/CHANGELOG.rst).
|
||||
|
||||
## Licensing
|
||||
|
||||
MIT
|
||||
|
||||
See [LICENSE](LICENSE) to see the full text.
|
@ -0,0 +1,19 @@
|
||||
objects:
|
||||
role: {}
|
||||
plugins:
|
||||
become: {}
|
||||
cache: {}
|
||||
callback: {}
|
||||
cliconf: {}
|
||||
connection: {}
|
||||
filter: {}
|
||||
httpapi: {}
|
||||
inventory: {}
|
||||
lookup: {}
|
||||
module: {}
|
||||
netconf: {}
|
||||
shell: {}
|
||||
strategy: {}
|
||||
test: {}
|
||||
vars: {}
|
||||
version: 2.0.3
|
@ -0,0 +1,124 @@
|
||||
ancestor: null
|
||||
releases:
|
||||
1.0.0:
|
||||
release_date: '2023-08-03'
|
||||
1.0.1:
|
||||
changes:
|
||||
major_changes:
|
||||
- Initial MVP release
|
||||
minor_changes:
|
||||
- Add boot backup support
|
||||
- Add support for checking before resizing logical volumes
|
||||
fragments:
|
||||
- boot_backup.yml
|
||||
- check_before_resize.yml
|
||||
- release.yml
|
||||
release_date: '2023-08-04'
|
||||
1.0.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Existing Snapshots with Different Name Cause verify_no_existing_snapshot.yml
|
||||
to Fail
|
||||
minor_changes:
|
||||
- Create snapshots with normalized sizes
|
||||
fragments:
|
||||
- create_snapshots_with_normalized_sizes.yml
|
||||
- filtering_by_lvname_on_existing_snapshot_check.yml
|
||||
release_date: '2023-08-31'
|
||||
1.0.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add task to ensure tar package is present
|
||||
- Grub needs reinstall if /boot is on LVM
|
||||
- Wrong kernel version booting after rolling back
|
||||
minor_changes:
|
||||
- Changed the lvm_snapshots_boot_backup var default to false
|
||||
- Removed unimplemented lvm_snapshots_use_boom var from the docs
|
||||
- Revert - wait for snapshot to drain before returning
|
||||
fragments:
|
||||
- fix-lvm-grub.yml
|
||||
- minor-var-changes.yml
|
||||
- revert-wait-for-drain.yml
|
||||
- tar-present.yml
|
||||
- wrong-kernel.yml
|
||||
release_date: '2023-11-29'
|
||||
1.1.0:
|
||||
changes:
|
||||
major_changes:
|
||||
- New role, bigboot, to increase the boot partition while moving, and shrinking
|
||||
if needed, the adjacent partition
|
||||
- New role, initramfs, to execute an atomic flow of building and using a temporary
|
||||
initramfs in a reboot and restoring the original one
|
||||
- New role, shrink_lv, to decrease logical volume size along with the filesystem
|
||||
fragments:
|
||||
- add-bigboot-role.yml
|
||||
- add-shrink-lv.yml
|
||||
release_date: '2023-11-30'
|
||||
1.1.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix "Failed to list block device properties" error
|
||||
- Fix dracut path
|
||||
fragments:
|
||||
- fix_entries.yml
|
||||
- no_sbin_dracut.yml
|
||||
release_date: '2023-12-05'
|
||||
1.1.2:
|
||||
changes:
|
||||
minor_changes:
|
||||
- Updated links in docs and workflows to reflect move to redhat-cop org
|
||||
fragments:
|
||||
- update_links.yml
|
||||
release_date: '2023-12-13'
|
||||
2.0.0:
|
||||
changes:
|
||||
breaking_changes:
|
||||
- Split lvm_snapshots role into snapshot_create, snapshot_revert and snapshot_remove
|
||||
minor_changes:
|
||||
- bigboot - Rename internal variables with role name prefix
|
||||
- initramfs - Rename internal variables with role name prefix
|
||||
- shrink_lv - Rename internal variables with role name prefix
|
||||
fragments:
|
||||
- bigboot-internal-variable-names.yml
|
||||
- initramfs-internal-variable-names.yml
|
||||
- shrinklv-internal-variable-names.yml
|
||||
- split-lvm-snapshot_role.yml
|
||||
release_date: '2024-01-10'
|
||||
2.0.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix release workflow prechecks
|
||||
minor_changes:
|
||||
- Add publish to Automation Hub to release workflow
|
||||
fragments:
|
||||
- automation_hub_release.yml
|
||||
release_date: '2024-01-11'
|
||||
2.0.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Clean up bad math in bigboot.sh
|
||||
- Fix bigboot device not found error
|
||||
- Fix bigboot fail when autoactivation property not set
|
||||
- Fix vgs not found error
|
||||
- Round down requested size to multiple of extent size
|
||||
- Shorten bigboot.sh usage help message to not exceed the kmsg buffer
|
||||
- Use sectors with sfdisk
|
||||
minor_changes:
|
||||
- Add bigboot progress messages so inpatient operators don't think their server
|
||||
is hung
|
||||
fragments:
|
||||
- autoactivate.yml
|
||||
- fix_maths.yml
|
||||
- nvme_fix.yml
|
||||
release_date: '2024-03-07'
|
||||
2.0.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix how locking is disabled for newer LVM versions
|
||||
- Fix missing role metadata
|
||||
- Fix potential space exhaustion when restoring previous initramfs
|
||||
fragments:
|
||||
- autoactivate.yml
|
||||
- fix_image_copy.yml
|
||||
- fix_lvm_config.yml
|
||||
release_date: '2024-04-25'
|
@ -0,0 +1,32 @@
|
||||
changelog_filename_template: ../CHANGELOG.rst
|
||||
changelog_filename_version_depth: 0
|
||||
changes_file: changelog.yaml
|
||||
changes_format: combined
|
||||
ignore_other_fragment_extensions: true
|
||||
keep_fragments: false
|
||||
mention_ancestor: true
|
||||
new_plugins_after_name: removed_features
|
||||
notesdir: fragments
|
||||
prelude_section_name: release_summary
|
||||
prelude_section_title: Release Summary
|
||||
sanitize_changelog: true
|
||||
sections:
|
||||
- - major_changes
|
||||
- Major Changes
|
||||
- - minor_changes
|
||||
- Minor Changes
|
||||
- - breaking_changes
|
||||
- Breaking Changes / Porting Guide
|
||||
- - deprecated_features
|
||||
- Deprecated Features
|
||||
- - removed_features
|
||||
- Removed Features (previously deprecated)
|
||||
- - security_fixes
|
||||
- Security Fixes
|
||||
- - bugfixes
|
||||
- Bugfixes
|
||||
- - known_issues
|
||||
- Known Issues
|
||||
title: LVM Snapshot Linux Role
|
||||
trivial_section_name: trivial
|
||||
use_fqcn: true
|
@ -0,0 +1,5 @@
|
||||
major_changes:
|
||||
- add bigboot support for Btrfs next partition
|
||||
minor_changes:
|
||||
- show console log output from bigboot even if quiet kernel arg is set
|
||||
- do bigboot LVM changes with Ansible instead of pre-mount hook
|
@ -0,0 +1,2 @@
|
||||
minor_changes:
|
||||
- new bigboot_partition_size variable to make bigboot role more idempotent
|
@ -0,0 +1,2 @@
|
||||
---
|
||||
requires_ansible: '>=2.15.0'
|
@ -0,0 +1,85 @@
|
||||
# bigboot
|
||||
|
||||
The `bigboot` role is used to increase boot partition.
|
||||
|
||||
The role is designed to support the automation of RHEL in-place upgrades, but can also be used for other purposes.
|
||||
|
||||
## Contents
|
||||
|
||||
The role configures a dracut pre-mount hook that executes during a reboot to increase the size of the boot partition and filesystem. To make room for the boot size increase, the role first shrinks the size of the next partition after the boot partition. This next partition must contain either an LVM physical volume or a Btrfs filesystem volume. There must be sufficient free space in the LVM volume group or Btrfs filesystem to accommodate the reduced size.
|
||||
|
||||
> **WARNING!**
|
||||
>
|
||||
> All blocks of the partition above the boot partition are copied using `sfdisk` during the reboot and this can take several minutes or more depending on the size of that partition. The bigboot script periodically outputs progress messages to the system console to make it clear that the system is not in a "hung" state, but these progress messages may not be seen if `rhgb` or `quiet` kernel arguments are set. If the system is reset while the blocks are being copied, the partition will be irrcoverably corrupted. Do not assume the system is hung or force a reset during the bigboot reboot!
|
||||
|
||||
To learn more about how bigboot works, check out this [video](https://people.redhat.com/bmader/bigboot-demo.mp4).
|
||||
|
||||
## Role Variables
|
||||
|
||||
### `bigboot_partition_size` (String)
|
||||
|
||||
The variable `bigboot_partition_size` specifies the minimum required size of the boot partition. If the boot partition is already equal to or greater than the given size, the role will end gracefully making no changes. The value can be either in bytes or with optional single letter suffix (1024 bases) using [human_to_bytes](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/human_to_bytes_filter.html) filter plugin.
|
||||
|
||||
### `bigboot_size` (String)
|
||||
|
||||
This variable is deprecated and will be removed in a future release. Use `bigboot_partition_size` instead.
|
||||
|
||||
The variable `bigboot_size` specifies by how much the size of the boot partition is to be increased. The value can be either in bytes or with optional single letter suffix (1024 bases) using [human_to_bytes](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/human_to_bytes_filter.html) filter plugin.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The size increase may be slightly less than the specified value as the role will round down to the nearest multiple of the LVM volume group extent size or Btrfs sector size used for the next partition after the boot partition.
|
||||
|
||||
## Example playbook
|
||||
The following yaml demonstrates an example playbook that runs the role to increase the size of the target hosts boot partition to 1.5G:
|
||||
|
||||
```yaml
|
||||
- name: Extend boot partition playbook
|
||||
hosts: all
|
||||
vars:
|
||||
bigboot_partition_size: 1.5G
|
||||
roles:
|
||||
- bigboot
|
||||
```
|
||||
|
||||
# Validate execution
|
||||
The "Validate boot filesystem new size" task at the end of the run will indicate success or failure of the boot partition size increase. For example:
|
||||
|
||||
```
|
||||
TASK [bigboot : Validate boot filesystem new size] ****************************************
|
||||
ok: [fedora] => {
|
||||
"changed": false,
|
||||
"msg": "Boot filesystem size is now 1.44 GB (503.46 MB increase)"
|
||||
```
|
||||
|
||||
If the boot partition was already equal to or greater than the given size, the bigboot pre-mount hook configuration is skipped and the host will not reboot. In this case, the run will end with the "Validate increase requested" task indicating nothing happened. For example:
|
||||
|
||||
```
|
||||
TASK [bigboot : Validate increase requested] **********************************************
|
||||
ok: [fedora] => {
|
||||
"msg": "Nothing to do! Boot partition already equal to or greater than requested size."
|
||||
}
|
||||
```
|
||||
|
||||
During the reboot, the bigboot pre-mount hook logs progress messages to the console. After the reboot, `journalctl` can be used to review the log output. For example, a successful run will look similar to this:
|
||||
```bash
|
||||
# journalctl --boot --unit=dracut-pre-mount
|
||||
Jul 02 09:40:12 fedora systemd[1]: Starting dracut-pre-mount.service - dracut pre-mount hook...
|
||||
Jul 02 09:40:12 fedora dracut-pre-mount[498]: bigboot: Shrinking partition vda3 by 536870912
|
||||
Jul 02 09:40:12 fedora dracut-pre-mount[498]: bigboot: Moving up partition vda3 by 536870912
|
||||
Jul 02 09:40:16 fedora dracut-pre-mount[508]: bigboot: Partition move is progressing, please wait! (00:00:01)
|
||||
Jul 02 09:40:48 fedora dracut-pre-mount[498]: bigboot: Increasing boot partition vda2 by 536870912
|
||||
Jul 02 09:40:49 fedora dracut-pre-mount[498]: bigboot: Updating kernel partition table
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[498]: bigboot: Growing the /boot ext4 filesystem
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[528]: e2fsck 1.47.0 (5-Feb-2023)
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[528]: Pass 1: Checking inodes, blocks, and sizes
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[528]: Pass 2: Checking directory structure
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[528]: Pass 3: Checking directory connectivity
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[528]: Pass 4: Checking reference counts
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[528]: Pass 5: Checking group summary information
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[528]: /dev/vda2: 38/65536 files (10.5% non-contiguous), 83665/262144 blocks
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[529]: resize2fs 1.47.0 (5-Feb-2023)
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[529]: Resizing the filesystem on /dev/vda2 to 393216 (4k) blocks.
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[529]: The filesystem on /dev/vda2 is now 393216 (4k) blocks long.
|
||||
Jul 02 09:40:50 fedora dracut-pre-mount[493]: Boot partition vda2 successfully increased by 536870912 (38 seconds)
|
||||
```
|
@ -0,0 +1,2 @@
|
||||
bigboot_partition_size:
|
||||
bigboot_size:
|
@ -0,0 +1,121 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This is the new bigboot reboot script. Unlike the old script, this one
|
||||
# only deals with the partitioning and boot filesystem changes required.
|
||||
# The preparations to reduce the LVM physical volume or Btrfs filesystem
|
||||
# volume are now done in advance by Ansible before rebooting.
|
||||
#
|
||||
# This script performs the following steps in this order:
|
||||
#
|
||||
# 1. Move the end of the next partition to make it smaller
|
||||
# 2. Use sfdisk to copy the blocks of the next partition
|
||||
# 3. Move the end of the boot partition making it bigger
|
||||
# 4. Grow the boot filesystem
|
||||
#
|
||||
# Usage: bigboot.sh boot_partition_name next_partition_name boot_size_increase_in_bytes
|
||||
#
|
||||
# For example, this command would increase a /boot filesystem on /dev/sda1 by 500M:
|
||||
#
|
||||
# bigboot.sh sda1 sda2 524288000
|
||||
#
|
||||
|
||||
# Get input values
|
||||
boot_part_name="$1"
|
||||
next_part_name="$2"
|
||||
boot_size_increase_in_bytes="$3"
|
||||
|
||||
# Validate inputs
|
||||
name="bigboot"
|
||||
if [[ ! -b "/dev/$boot_part_name" ]]; then
|
||||
echo "$name: Boot partition is not a block device: $boot_part_name"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -b "/dev/$next_part_name" ]]; then
|
||||
echo "$name: Next partition is not a block device: $next_part_name"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! $boot_size_increase_in_bytes -gt 0 ]]; then
|
||||
echo "$name: Invalid size increase value: $boot_size_increase_in_bytes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Calculate device and partition details
|
||||
boot_disk_device=/dev/"$(/usr/bin/basename "$(readlink -f /sys/class/block/"$boot_part_name"/..)")"
|
||||
boot_part_num="$(</sys/class/block/"$boot_part_name"/partition)"
|
||||
next_part_num="$(</sys/class/block/"$next_part_name"/partition)"
|
||||
next_part_start="$(($(</sys/class/block/"$next_part_name"/start)*512))"
|
||||
next_part_size="$(($(</sys/class/block/"$next_part_name"/size)*512))"
|
||||
next_part_end="$((next_part_start+next_part_size-1))"
|
||||
next_part_new_end="$((next_part_end-boot_size_increase_in_bytes))"
|
||||
|
||||
# Validate boot filesystem
|
||||
eval "$(/usr/sbin/blkid /dev/"$boot_part_name" -o udev)"
|
||||
boot_fs_type="$ID_FS_TYPE"
|
||||
if [[ ! "$boot_fs_type" =~ ^ext[2-4]$|^xfs$ ]]; then
|
||||
echo "$name: Boot filesystem type is not extendable: $boot_fs_type"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate next partition
|
||||
eval "$(/usr/sbin/blkid /dev/"$next_part_name" -o udev)"
|
||||
if [[ "$ID_FS_TYPE" == "LVM2_member" ]]; then
|
||||
eval "$(/usr/sbin/lvm pvs --noheadings --nameprefixes -o vg_name /dev/"$next_part_name")"
|
||||
next_part_vg="$LVM2_VG_NAME"
|
||||
fi
|
||||
|
||||
# Shrink next partition
|
||||
echo "$name: Shrinking partition $next_part_name by $boot_size_increase_in_bytes"
|
||||
if ! ret=$(echo Yes | /usr/sbin/parted "$boot_disk_device" ---pretend-input-tty unit B resizepart "$next_part_num" "$next_part_new_end" 2>&1); then
|
||||
echo "$name: Failed shrinking partition $next_part_name: $ret"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Output progress messages to help impatient operators recognize the server is not "hung"
|
||||
( sleep 4
|
||||
while t="$(ps -C sfdisk -o cputime=)"; do
|
||||
echo "$name: Partition move is progressing, please wait! ($t)"
|
||||
sleep 120
|
||||
done ) &
|
||||
|
||||
# Shift next partition
|
||||
echo "$name: Moving up partition $next_part_name by $boot_size_increase_in_bytes"
|
||||
if ! ret=$(echo "+$((boot_size_increase_in_bytes/512))," | /usr/sbin/sfdisk --move-data "$boot_disk_device" -N "$next_part_num" --force 2>&1); then
|
||||
echo "$name: Failed moving up partition $next_part_name: $ret"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Increase boot partition
|
||||
echo "$name: Increasing boot partition $boot_part_name by $boot_size_increase_in_bytes"
|
||||
if ! ret=$(echo "- +" | /usr/sbin/sfdisk "$boot_disk_device" -N "$boot_part_num" --no-reread --force 2>&1); then
|
||||
echo "$name: Failed increasing boot partition $boot_part_name: $ret"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update kernel partition table
|
||||
echo "$name: Updating kernel partition table"
|
||||
[[ "$next_part_vg" ]] && /usr/sbin/lvm vgchange -an "$next_part_vg" && sleep 1
|
||||
/usr/sbin/partprobe "$boot_disk_device" && sleep 1
|
||||
[[ "$next_part_vg" ]] && /usr/sbin/lvm vgchange -ay "$next_part_vg" && sleep 1
|
||||
|
||||
# Grow the /boot filesystem
|
||||
echo "$name: Growing the /boot $boot_fs_type filesystem"
|
||||
if [[ "$boot_fs_type" =~ ^ext[2-4]$ ]]; then
|
||||
/usr/sbin/e2fsck -fy "/dev/$boot_part_name"
|
||||
if ! /usr/sbin/resize2fs "/dev/$boot_part_name"; then
|
||||
echo "$name: resize2fs error while growing the /boot filesystem"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ "$boot_fs_type" == "xfs" ]]; then
|
||||
tmp_dir=$(/usr/bin/mktemp -d)
|
||||
/usr/bin/mount -t xfs "/dev/$boot_part_name" "$tmp_dir"
|
||||
/usr/sbin/xfs_growfs "/dev/$boot_part_name"
|
||||
status=$?
|
||||
/usr/bin/umount "/dev/$boot_part_name"
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "$name: xfs_growfs error while growing the /boot filesystem"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||
|
||||
check(){
|
||||
return 0
|
||||
}
|
||||
|
||||
install() {
|
||||
inst_multiple -o /usr/bin/mount /usr/bin/umount /usr/sbin/parted /usr/bin/mktemp /usr/bin/date /usr/bin/basename /usr/sbin/resize2fs /usr/sbin/partprobe /usr/sbin/lvm /usr/sbin/blkid /usr/sbin/e2fsck /usr/sbin/xfs_growfs /usr/sbin/xfs_db
|
||||
# shellcheck disable=SC2154
|
||||
inst_hook pre-mount 99 "$moddir/increase-boot-partition.sh"
|
||||
inst_binary "$moddir/sfdisk.static" "/usr/sbin/sfdisk"
|
||||
inst_simple "$moddir/bigboot.sh" "/usr/bin/bigboot.sh"
|
||||
}
|
Binary file not shown.
@ -0,0 +1,14 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Ygal Blum, Bob Mader
|
||||
description: Increase the size of the boot partition
|
||||
company: Red Hat
|
||||
license: MIT
|
||||
min_ansible_version: "2.14"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags: []
|
||||
dependencies: []
|
||||
...
|
@ -0,0 +1,48 @@
|
||||
- name: Copy dracut pre-mount hook files
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: /usr/lib/dracut/modules.d/99extend_boot/
|
||||
mode: "0554"
|
||||
loop:
|
||||
- bigboot.sh
|
||||
- module-setup.sh
|
||||
- sfdisk.static
|
||||
|
||||
- name: Resolve and copy pre-mount hook wrapper script
|
||||
ansible.builtin.template:
|
||||
src: increase-boot-partition.sh.j2
|
||||
dest: /usr/lib/dracut/modules.d/99extend_boot/increase-boot-partition.sh
|
||||
mode: '0554'
|
||||
|
||||
- name: Create the initramfs and reboot to run the module
|
||||
vars:
|
||||
initramfs_add_modules: "extend_boot"
|
||||
ansible.builtin.include_role:
|
||||
name: initramfs
|
||||
|
||||
- name: Remove dracut extend boot module
|
||||
ansible.builtin.file:
|
||||
path: /usr/lib/dracut/modules.d/99extend_boot
|
||||
state: absent
|
||||
|
||||
- name: Retrieve mount points
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- "!all"
|
||||
- "!min"
|
||||
- mounts
|
||||
|
||||
- name: Capture boot filesystem new size
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_boot_fs_new_size: "{{ (ansible_facts.mounts | selectattr('mount', 'equalto', '/boot') | first).size_total | int }}"
|
||||
|
||||
- name: Validate boot filesystem new size
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- bigboot_boot_fs_new_size != bigboot_boot_fs_original_size
|
||||
fail_msg: >-
|
||||
Boot filesystem size '{{ bigboot_boot_fs_new_size }}' did not change
|
||||
success_msg: >-
|
||||
Boot filesystem size is now
|
||||
{{ bigboot_boot_fs_new_size | int | human_readable }}
|
||||
({{ (bigboot_boot_fs_new_size | int - bigboot_boot_fs_original_size | int) | human_readable }} increase)
|
@ -0,0 +1,57 @@
|
||||
- name: Find the boot mount entry
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_boot_mount_entry: "{{ ansible_facts.mounts | selectattr('mount', 'equalto', '/boot') | first | default('', true) }}"
|
||||
|
||||
- name: Validate boot mount entry
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- bigboot_boot_mount_entry.device is defined
|
||||
fail_msg: "No /boot mount point found."
|
||||
|
||||
- name: Calculate the partition to look for
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_boot_partition_name: "{{ (bigboot_boot_mount_entry.device | split('/'))[-1] }}"
|
||||
|
||||
- name: Find the boot device parent
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_boot_disk: "{{ item.key }}"
|
||||
with_dict: "{{ ansible_facts.devices }}"
|
||||
when: bigboot_boot_partition_name in item.value.partitions
|
||||
|
||||
- name: Capture boot device details
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_boot_device_name: "/dev/{{ bigboot_boot_disk }}"
|
||||
bigboot_boot_fs_original_size: "{{ bigboot_boot_mount_entry.size_total | int }}"
|
||||
bigboot_boot_device_sectors: "{{ ansible_facts.devices[bigboot_boot_disk].partitions[bigboot_boot_partition_name].sectors | int }}"
|
||||
bigboot_boot_device_sectorsize: "{{ ansible_facts.devices[bigboot_boot_disk].partitions[bigboot_boot_partition_name].sectorsize | int }}"
|
||||
|
||||
- name: Calculate boot device current size
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_boot_device_bytes: "{{ bigboot_boot_device_sectors | int * bigboot_boot_device_sectorsize | int }}"
|
||||
|
||||
- name: Find the next partition
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_next_partition_name: "{{ ansible_loop.nextitem.0 | default(omit, true) }}"
|
||||
when: item.0 == bigboot_boot_partition_name
|
||||
loop: "{{ ansible_facts.devices[bigboot_boot_disk].partitions | dictsort }}"
|
||||
loop_control:
|
||||
extended: true
|
||||
|
||||
- name: Validate next partition exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- bigboot_next_partition_name is defined
|
||||
fail_msg: "There is no partition found after the /boot partition."
|
||||
|
||||
- name: Find Btrfs or LVM
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_next_partition_btrfs: "{{ ansible_facts.mounts | selectattr('device', 'equalto', '/dev/' + bigboot_next_partition_name) |
|
||||
selectattr('fstype', 'equalto', 'btrfs') | map(attribute='mount') | first | default(omit, true) }}"
|
||||
bigboot_next_partition_vg: "{{ ansible_facts.lvm.pvs['/dev/' + bigboot_next_partition_name].vg | default(omit, true) }}"
|
||||
bigboot_next_partition_type_checked: true
|
||||
|
||||
- name: Validate next partition type
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- bigboot_next_partition_btrfs is defined or bigboot_next_partition_vg is defined
|
||||
fail_msg: "The partition after the /boot partition is neither LVM or Btrfs."
|
@ -0,0 +1,58 @@
|
||||
---
|
||||
- name: Make sure the required related facts are available
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- "!all"
|
||||
- "!min"
|
||||
- mounts
|
||||
- devices
|
||||
|
||||
- name: Validate initramfs preflight
|
||||
ansible.builtin.include_role:
|
||||
name: initramfs
|
||||
tasks_from: preflight
|
||||
|
||||
- name: Get boot device info
|
||||
ansible.builtin.include_tasks:
|
||||
file: get_boot_device_info.yml
|
||||
|
||||
- name: Convert bigboot_partition_size to bytes
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_partition_size_bytes: "{{ bigboot_partition_size | ansible.builtin.human_to_bytes }}"
|
||||
when: bigboot_partition_size | default('', true) | length > 0
|
||||
|
||||
- name: Convert bigboot_size to bytes
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_size_bytes: "{{ bigboot_size | ansible.builtin.human_to_bytes }}"
|
||||
when: bigboot_partition_size_bytes is undefined and bigboot_size | default('', true) | length > 0
|
||||
|
||||
- name: Calculate bigboot increase
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_increase_bytes: "{{ bigboot_partition_size_bytes | default(bigboot_boot_device_bytes, true) | int -
|
||||
bigboot_boot_device_bytes | int +
|
||||
bigboot_size_bytes | default('0', true) | int }}"
|
||||
|
||||
- name: Prepare Btrfs for bigboot
|
||||
ansible.builtin.include_tasks:
|
||||
file: prep_btrfs.yml
|
||||
when:
|
||||
- bigboot_increase_bytes | int > 0
|
||||
- bigboot_next_partition_btrfs is defined
|
||||
|
||||
- name: Prepare LVM for bigboot
|
||||
ansible.builtin.include_tasks:
|
||||
file: prep_lvm.yml
|
||||
when:
|
||||
- bigboot_increase_bytes | int > 0
|
||||
- bigboot_next_partition_vg is defined
|
||||
|
||||
- name: Configure pre-mount hook and reboot
|
||||
ansible.builtin.include_tasks:
|
||||
file: do_bigboot_reboot.yml
|
||||
when:
|
||||
- bigboot_increase_bytes | int > 0
|
||||
|
||||
- name: Validate increase requested
|
||||
ansible.builtin.debug:
|
||||
msg: "Nothing to do! Boot partition already equal to or greater than requested size."
|
||||
when: bigboot_increase_bytes | int <= 0
|
@ -0,0 +1,19 @@
|
||||
- name: Find Btrfs sector size
|
||||
ansible.builtin.slurp:
|
||||
src: "/sys/fs/btrfs/{{ ansible_facts.mounts | selectattr('mount', 'equalto', bigboot_next_partition_btrfs) | map(attribute='uuid') | first }}/sectorsize"
|
||||
register: sectorsize
|
||||
|
||||
- name: Align bigboot increase to sector size
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_increase_bytes: "{{ bigboot_increase_bytes | int - (bigboot_increase_bytes | int % sectorsize.content | b64decode | int) }}"
|
||||
|
||||
- name: Btrfs volume reduce
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
/usr/sbin/btrfs
|
||||
filesystem resize
|
||||
1:-{{ bigboot_increase_bytes }}
|
||||
{{ bigboot_next_partition_btrfs }}
|
||||
when: bigboot_increase_bytes | int > 0
|
||||
changed_when: true
|
||||
register: resize_cmd
|
@ -0,0 +1,54 @@
|
||||
- name: Find physical volume size
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
/usr/sbin/lvm pvs
|
||||
--noheadings --nosuffix --units b
|
||||
-o pv_size /dev/{{ bigboot_next_partition_name }}
|
||||
changed_when: false
|
||||
register: pv_size
|
||||
|
||||
- name: Find volume group extent size
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
/usr/sbin/lvm vgs
|
||||
--noheadings --nosuffix --units b
|
||||
-o vg_extent_size {{ bigboot_next_partition_vg }}
|
||||
changed_when: false
|
||||
register: vg_extent_size
|
||||
|
||||
- name: Align bigboot increase to extent size
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_increase_bytes: "{{ bigboot_increase_bytes | int - (bigboot_increase_bytes | int % vg_extent_size.stdout | int) }}"
|
||||
|
||||
- name: Test mode pvresize
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
/usr/sbin/lvm pvresize
|
||||
--test --yes
|
||||
--setphysicalvolumesize {{ pv_size.stdout | int - bigboot_increase_bytes | int }}B
|
||||
/dev/{{ bigboot_next_partition_name }}
|
||||
when: bigboot_increase_bytes | int > 0
|
||||
changed_when: false
|
||||
failed_when: pvresize_test.rc not in [0, 5]
|
||||
register: pvresize_test
|
||||
|
||||
- name: Evict extents from end of physical volume
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
/usr/sbin/lvm pvmove
|
||||
--alloc anywhere
|
||||
/dev/{{ bigboot_next_partition_name }}:{{ (((pv_size.stdout | int - bigboot_increase_bytes | int) / vg_extent_size.stdout | int) - 1) | int }}-
|
||||
when: pvresize_test.rc | default(0, true) == 5
|
||||
changed_when: true
|
||||
register: pvmove
|
||||
|
||||
- name: Real pvresize
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
/usr/sbin/lvm pvresize
|
||||
--yes
|
||||
--setphysicalvolumesize {{ pv_size.stdout | int - bigboot_increase_bytes | int }}B
|
||||
/dev/{{ bigboot_next_partition_name }}
|
||||
when: bigboot_increase_bytes | int > 0
|
||||
changed_when: true
|
||||
register: pvresize_real
|
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
main() {
|
||||
start=$(/usr/bin/date +%s)
|
||||
# run bigboot.sh to increase boot partition and file system size
|
||||
sh /usr/bin/bigboot.sh "{{ bigboot_boot_partition_name }}" "{{ bigboot_next_partition_name }}" "{{ bigboot_increase_bytes }}"
|
||||
status=$?
|
||||
end=$(/usr/bin/date +%s)
|
||||
# write the log file
|
||||
if [[ $status -eq 0 ]]; then
|
||||
echo "Boot partition {{ bigboot_boot_partition_name }} successfully increased by {{ bigboot_increase_bytes }} ("$((end-start))" seconds)"
|
||||
else
|
||||
echo "Failed to extend boot partition ("$((end-start))" seconds)"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$0" >&2
|
@ -0,0 +1,59 @@
|
||||
# initramfs
|
||||
|
||||
The `initramfs` role is included by the `shrink_lv` and `bigboot` roles to run an atomic flow of building and using a temporary initramfs in a reboot and restoring the original one.
|
||||
|
||||
The role is designed to be internal for this collection and support the automation of RHEL in-place upgrades, but can also be used for other purposes.
|
||||
|
||||
## Contents
|
||||
|
||||
To allow fast fail, the role provides a [`preflight.yml`](./tasks/preflight.yml) tasks file to be used at the start of the playbook.
|
||||
Please note that the [`main`](./tasks/main.yml) task file will not run the preflight checks
|
||||
|
||||
## Role Variables
|
||||
|
||||
All variables are optional
|
||||
|
||||
### `initramfs_add_modules`
|
||||
|
||||
`initramfs_add_modules` is a a space-separated list of dracut modules to be added to the default set of modules.
|
||||
See [`dracut`](https://man7.org/linux/man-pages/man8/dracut.8.html) `-a` parameter for details.
|
||||
|
||||
### `initramfs_backup_extension`
|
||||
|
||||
`initramfs_backup_extension` is the file extension for the backup initramfs file.
|
||||
|
||||
Defaults to `old`
|
||||
|
||||
### `initramfs_post_reboot_delay`
|
||||
|
||||
`initramfs_post_reboot_delay` sets the amount of Seconds to wait after the reboot command was successful before attempting to validate the system rebooted successfully.
|
||||
The value is used for [`post_reboot_delay`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/reboot_module.html#parameter-post_reboot_delay) parameter
|
||||
|
||||
Defaults to `30`
|
||||
|
||||
### `initramfs_reboot_timeout`
|
||||
|
||||
`initramfs_reboot_timeout` sets the maximum seconds to wait for machine to reboot and respond to a test command.
|
||||
The value is used for [`reboot_timeout`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/reboot_module.html#parameter-reboot_timeout) parameter
|
||||
|
||||
Defaults to `7200`
|
||||
|
||||
|
||||
## Example of a playbook to run the role
|
||||
The following yaml is an example of a playbook that runs the role against a group of hosts named `rhel` and increasing the size of its boot partition by 1G.
|
||||
The boot partition is automatically retrieved by the role by identifying the existing mounted partition to `/boot` and passing the information to the script using the `kernel_opts`.
|
||||
|
||||
```yaml
|
||||
- name: Extend boot partition playbook
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: Validate initramfs preflight
|
||||
ansible.builtin.include_role:
|
||||
name: initramfs
|
||||
tasks_from: preflight
|
||||
- name: Create the initramfs and reboot to run the module
|
||||
vars:
|
||||
initramfs_add_modules: "my_extra_module"
|
||||
ansible.builtin.include_role:
|
||||
name: initramfs
|
||||
```
|
@ -0,0 +1,4 @@
|
||||
initramfs_backup_extension: old
|
||||
initramfs_add_modules: ""
|
||||
initramfs_post_reboot_delay: 30
|
||||
initramfs_reboot_timeout: 7200
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Ygal Blum, Bob Mader
|
||||
description: Included by other roles to run an atomic flow of building and using a temporary initramfs in a reboot and restoring the original one
|
||||
company: Red Hat
|
||||
license: MIT
|
||||
min_ansible_version: "2.14"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags: []
|
||||
dependencies: []
|
||||
...
|
@ -0,0 +1,32 @@
|
||||
---
|
||||
- name: Make sure the required related facts are available
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- "!all"
|
||||
- "!min"
|
||||
- kernel
|
||||
|
||||
- name: Get kernel version
|
||||
ansible.builtin.set_fact:
|
||||
initramfs_kernel_version: "{{ ansible_facts.kernel }}"
|
||||
|
||||
- name: Create a backup of the current initramfs
|
||||
ansible.builtin.copy:
|
||||
remote_src: true
|
||||
src: /boot/initramfs-{{ initramfs_kernel_version }}.img
|
||||
dest: /boot/initramfs-{{ initramfs_kernel_version }}.img.{{ initramfs_backup_extension }}
|
||||
mode: "0600"
|
||||
|
||||
- name: Create a new initramfs with the optional additional modules
|
||||
# yamllint disable-line rule:line-length
|
||||
ansible.builtin.command: '/usr/bin/dracut {{ ((initramfs_add_modules | length) > 0) | ternary("-a", "") }} "{{ initramfs_add_modules }}" --kver {{ initramfs_kernel_version }} --force'
|
||||
changed_when: true
|
||||
|
||||
- name: Reboot host
|
||||
ansible.builtin.import_role:
|
||||
name: verified_reboot
|
||||
|
||||
- name: Restore previous initramfs
|
||||
# yamllint disable-line rule:line-length
|
||||
ansible.builtin.command: '/usr/bin/mv -f /boot/initramfs-{{ initramfs_kernel_version }}.img.{{ initramfs_backup_extension }} /boot/initramfs-{{ initramfs_kernel_version }}.img'
|
||||
changed_when: true
|
@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: Make sure the required related facts are available
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- "!all"
|
||||
- "!min"
|
||||
- kernel
|
||||
|
||||
- name: Get kernel version
|
||||
ansible.builtin.set_fact:
|
||||
initramfs_kernel_version: "{{ ansible_facts.kernel }}"
|
||||
|
||||
- name: Get default kernel
|
||||
ansible.builtin.command:
|
||||
cmd: /sbin/grubby --default-kernel
|
||||
register: initramfs_grubby_rc
|
||||
changed_when: false
|
||||
|
||||
- name: Parse default kernel version
|
||||
ansible.builtin.set_fact:
|
||||
initramfs_default_kernel: "{{ ((((initramfs_grubby_rc.stdout_lines[0] | split('/'))[2] | split('-'))[1:]) | join('-')) | trim }}"
|
||||
|
||||
- name: Check the values
|
||||
ansible.builtin.assert:
|
||||
that: initramfs_default_kernel == initramfs_kernel_version
|
||||
fail_msg: "Current kernel version '{{ initramfs_kernel_version }}' is not the default version '{{ initramfs_default_kernel }}'"
|
||||
success_msg: "Current kernel version {{ initramfs_kernel_version }} and default version {{ initramfs_default_kernel }} match"
|
@ -0,0 +1,55 @@
|
||||
# shrink_lv
|
||||
|
||||
The `shrink_lv` role is used to decrease the size of logical volumes and the file system within them.
|
||||
|
||||
The role is designed to support the automation of RHEL in-place upgrades, but can also be used for other purposes.
|
||||
|
||||
## Contents
|
||||
|
||||
The role contains the shell scripts to shrink the logical volume and file system, as well as the script wrapping it to run as part of the pre-mount step during the boot process.
|
||||
|
||||
## Role Variables
|
||||
|
||||
### `shrink_lv_devices`
|
||||
|
||||
The variable `shrink_lv_devices` is the list of logical volumes to shrink and the target size for those volumes.
|
||||
|
||||
#### `device`
|
||||
|
||||
The device that is mounted as listed under `/proc/mount`.
|
||||
If the same device has multiple paths, e.g. `/dev/vg/lv` and `/dev/mapper/vg/lv` pass the path that is mounted
|
||||
|
||||
#### `size`
|
||||
|
||||
The target size of the logical volume and filesystem after the role has completed.
|
||||
The value can be either in bytes or with optional single letter suffix (1024 bases).
|
||||
See `Unit options` type `iec` of [`numfmt`](https://man7.org/linux/man-pages/man1/numfmt.1.html)
|
||||
|
||||
## Example of a playbook to run the role
|
||||
|
||||
The following yaml is an example of a playbook that runs the role against all hosts to shrink the logical volume `lv` in volume group `vg` to 4G.
|
||||
|
||||
```yaml
|
||||
- name: Shrink Logical Volumes playbook
|
||||
hosts: all
|
||||
vars:
|
||||
shrink_lv_devices:
|
||||
- device: /dev/vg/lv
|
||||
size: 4G
|
||||
roles:
|
||||
- shrink_lv
|
||||
```
|
||||
|
||||
# Validate execution
|
||||
The script will add an entry to the kernel messages (`/dev/kmsg` or `/var/log/messages`) with success or failure.
|
||||
In case of failure, it may also include an error message retrieved from the execution of the script.
|
||||
|
||||
A successful execution will look similar to this:
|
||||
```bash
|
||||
[root@localhost ~]# cat /var/log/messages |grep Resizing -A 2 -B 2
|
||||
Oct 16 17:55:00 localhost /dev/mapper/rhel-root: 29715/2686976 files (0.2% non-contiguous), 534773/10743808 blocks
|
||||
Oct 16 17:55:00 localhost dracut-pre-mount: resize2fs 1.42.9 (28-Dec-2013)
|
||||
Oct 16 17:55:00 localhost journal: Resizing the filesystem on /dev/mapper/rhel-root to 9699328 (4k) blocks.#012The filesystem on /dev/mapper/rhel-root is now 9699328 blocks long.
|
||||
Oct 16 17:55:00 localhost journal: Size of logical volume rhel/root changed from 40.98 GiB (10492 extents) to 37.00 GiB (9472 extents).
|
||||
Oct 16 17:55:00 localhost journal: Logical volume rhel/root successfully resized.
|
||||
```
|
@ -0,0 +1 @@
|
||||
shrink_lv_backup_extension: old
|
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||
|
||||
check(){
|
||||
return 0
|
||||
}
|
||||
|
||||
install() {
|
||||
inst_multiple -o /usr/bin/numfmt /usr/bin/findmnt /usr/bin/lsblk /usr/sbin/lvm /usr/bin/awk /usr/bin/sed /usr/bin/sort /usr/bin/mktemp /usr/bin/date /usr/bin/head /usr/sbin/blockdev /usr/sbin/tune2fs /usr/sbin/resize2fs /usr/bin/cut /usr/sbin/fsadm /usr/sbin/fsck.ext4 /usr/libexec/lvresize_fs_helper /usr/sbin/cryptsetup /usr/bin/logger /usr/bin/basename /usr/bin/getopt
|
||||
# shellcheck disable=SC2154
|
||||
inst_hook pre-mount 99 "$moddir/shrink-start.sh"
|
||||
inst_simple "$moddir/shrink.sh" "/usr/bin/shrink.sh"
|
||||
}
|
@ -0,0 +1,253 @@
|
||||
#!/bin/bash
|
||||
VOLUME_SIZE_ALIGNMENT=4096
|
||||
|
||||
function get_device_name() {
|
||||
if [[ "$1" == "UUID="* ]]; then
|
||||
dev_name=$( parse_uuid "$1" )
|
||||
else
|
||||
dev_name=$(/usr/bin/cut -d " " -f 1 <<< "$1")
|
||||
fi
|
||||
status=$?
|
||||
if [[ status -ne 0 ]]; then
|
||||
return $status
|
||||
fi
|
||||
echo "$dev_name"
|
||||
return $status
|
||||
}
|
||||
|
||||
function ensure_size_in_bytes() {
|
||||
local expected_size
|
||||
expected_size=$(/usr/bin/numfmt --from iec "$1")
|
||||
(( expected_size=(expected_size+VOLUME_SIZE_ALIGNMENT)/VOLUME_SIZE_ALIGNMENT*VOLUME_SIZE_ALIGNMENT ))
|
||||
echo $expected_size
|
||||
}
|
||||
|
||||
function is_device_mounted() {
|
||||
/usr/bin/findmnt --source "$1" 1>&2>/dev/null
|
||||
status=$?
|
||||
if [[ status -eq 0 ]]; then
|
||||
echo "Device $1 is mounted" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function get_current_volume_size() {
|
||||
val=$(/usr/bin/lsblk -b "$1" -o SIZE --noheadings)
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
return $status
|
||||
fi
|
||||
echo "$val"
|
||||
return 0
|
||||
}
|
||||
|
||||
function is_lvm(){
|
||||
val=$( /usr/bin/lsblk "$1" --noheadings -o TYPE 2>&1)
|
||||
status=$?
|
||||
if [[ status -ne 0 ]]; then
|
||||
echo "Failed to list block device properties for $2: $val" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$val" != "lvm" ]]; then
|
||||
echo "Device $device_name is not of lvm type" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function parse_uuid() {
|
||||
uuid=$(/usr/bin/awk '{print $1}'<<< "$1"|/usr/bin/awk -F'UUID=' '{print $2}')
|
||||
val=$(/usr/bin/lsblk /dev/disk/by-uuid/"$uuid" -o NAME --noheadings 2>/dev/null)
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "Failed to retrieve device name for UUID=$uuid" >&2
|
||||
return $status
|
||||
fi
|
||||
echo "/dev/mapper/$val"
|
||||
return 0
|
||||
}
|
||||
|
||||
function shrink_volume() {
|
||||
/usr/sbin/lvm lvreduce "$NOLOCKING" --resizefs -L "$2"b "$1"
|
||||
return $?
|
||||
}
|
||||
|
||||
function check_volume_size() {
|
||||
current_size=$(get_current_volume_size "$1")
|
||||
if [[ $current_size -lt $2 ]];then
|
||||
echo "Current volume size for device $1 ($current_size bytes) is lower to expected $2 bytes" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ $current_size -eq $2 ]]; then
|
||||
echo "Current volume size for device $1 already equals $2 bytes" >&2
|
||||
return 1
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
function convert_size_to_fs_blocks(){
|
||||
local device=$1
|
||||
local size=$2
|
||||
block_size_in_bytes=$(/usr/sbin/tune2fs -l "$device" | /usr/bin/awk '/Block size:/{print $3}')
|
||||
echo $(( size / block_size_in_bytes ))
|
||||
}
|
||||
|
||||
function calculate_expected_resized_file_system_size_in_blocks(){
|
||||
local device=$1
|
||||
increment_boot_partition_in_blocks=$(convert_size_to_fs_blocks "$device" "$INCREMENT_BOOT_PARTITION_SIZE_IN_BYTES")
|
||||
total_block_count=$(/usr/sbin/tune2fs -l "$device" | /usr/bin/awk '/Block count:/{print $3}')
|
||||
new_fs_size_in_blocks=$(( total_block_count - increment_boot_partition_in_blocks ))
|
||||
echo $new_fs_size_in_blocks
|
||||
}
|
||||
|
||||
function check_filesystem_size() {
|
||||
local device=$1
|
||||
local new_fs_size_in_blocks=$2
|
||||
new_fs_size_in_blocks=$(calculate_expected_resized_file_system_size_in_blocks "$device")
|
||||
# it is possible that running this command after resizing it might give an even smaller number.
|
||||
minimum_blocks_required=$(/usr/sbin/resize2fs -P "$device" 2> /dev/null | /usr/bin/awk '{print $NF}')
|
||||
|
||||
if [[ "$new_fs_size_in_blocks" -le "0" ]]; then
|
||||
echo "Unable to shrink volume: New size is 0 blocks"
|
||||
return 1
|
||||
fi
|
||||
if [[ $minimum_blocks_required -gt $new_fs_size_in_blocks ]]; then
|
||||
echo "Unable to shrink volume: Estimated minimum size of the file system $1 ($minimum_blocks_required blocks) is greater than the new size $new_fs_size_in_blocks blocks" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function process_entry() {
|
||||
is_lvm "$1" "$3"
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
return "$status"
|
||||
fi
|
||||
expected_size_in_bytes=$(ensure_size_in_bytes "$2")
|
||||
check_filesystem_size "$1" "$expected_size_in_bytes"
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
return "$status"
|
||||
fi
|
||||
check_volume_size "$1" "$expected_size_in_bytes"
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
return "$status"
|
||||
fi
|
||||
is_device_mounted "$1"
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
return "$status"
|
||||
fi
|
||||
shrink_volume "$1" "$expected_size_in_bytes"
|
||||
return $?
|
||||
}
|
||||
|
||||
function display_help() {
|
||||
echo "Program to shrink ext4 file systems hosted in Logical Volumes.
|
||||
|
||||
Usage: '$(basename "$0")' [-h] [-d=|--device=]
|
||||
|
||||
Example:
|
||||
|
||||
where:
|
||||
-h show this help text
|
||||
-d|--device= name or UUID of the device that holds an ext4 and the new size separated by a ':'
|
||||
for example /dev/my_group/my_vol:2G
|
||||
Sizes will be rounded to be 4K size aligned"
|
||||
}
|
||||
|
||||
function parse_flags() {
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
-d=*|--device=*)
|
||||
entries+=("${i#*=}")
|
||||
;;
|
||||
-h)
|
||||
display_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
echo "Unknown flag $i"
|
||||
display_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [[ ${#entries[@]} == 0 ]]; then
|
||||
display_help
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
function parse_entry() {
|
||||
IFS=':'
|
||||
read -ra strarr <<< "$1"
|
||||
|
||||
if [[ ${#strarr[@]} != 2 ]]; then
|
||||
echo "Invalid device entry $1"
|
||||
display_help
|
||||
return 1
|
||||
fi
|
||||
|
||||
device="${strarr[0]}"
|
||||
expected_size="${strarr[1]}"
|
||||
}
|
||||
|
||||
function get_nolocking_opts() {
|
||||
local lvm_version
|
||||
lvm_version="$(/usr/sbin/lvm version | /usr/bin/grep 'LVM version:')"
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "Error getting LVM version '$lvm_version'"
|
||||
exit $status
|
||||
fi
|
||||
# true when LVM version is older than 2.03
|
||||
if echo -e "${lvm_version##*:}\n2.03" | /usr/bin/sed 's/^ *//' | /usr/bin/sort -V -C; then
|
||||
NOLOCKING='--config=global{locking_type=0}'
|
||||
else
|
||||
NOLOCKING='--nolocking'
|
||||
fi
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
||||
local -a entries=()
|
||||
local run_status=0
|
||||
|
||||
parse_flags "$@"
|
||||
get_nolocking_opts
|
||||
|
||||
for entry in "${entries[@]}"
|
||||
do
|
||||
local device
|
||||
local expected_size
|
||||
parse_entry "$entry"
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
run_status=$status
|
||||
continue
|
||||
fi
|
||||
device_name=$( get_device_name "$device" )
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
run_status=$status
|
||||
continue
|
||||
fi
|
||||
|
||||
process_entry "$device_name" "$expected_size" "$device"
|
||||
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
run_status=$status
|
||||
fi
|
||||
done
|
||||
|
||||
exit $run_status
|
||||
}
|
||||
|
||||
main "$@"
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Ygal Blum, Bob Mader
|
||||
description: Decrease logical volume size along with the filesystem
|
||||
company: Red Hat
|
||||
license: MIT
|
||||
min_ansible_version: "2.14"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags: []
|
||||
dependencies: []
|
||||
...
|
@ -0,0 +1,20 @@
|
||||
- name: Get the mount point info
|
||||
ansible.builtin.set_fact:
|
||||
shrink_lv_mount_info: "{{ ansible_facts.mounts | selectattr('device', 'equalto', item.device) }}"
|
||||
|
||||
- name: Assert that the mount point exists
|
||||
ansible.builtin.assert:
|
||||
that: (shrink_lv_mount_info | length) == 1
|
||||
fail_msg: "Mount point {{ item.device }} does not exist"
|
||||
|
||||
- name: Assert that the filesystem is supported
|
||||
ansible.builtin.assert:
|
||||
that: shrink_lv_mount_info[0].fstype in ['ext4']
|
||||
fail_msg: "Unsupported filesystem '{{ shrink_lv_mount_info[0].fstype }}' on '{{ item.device }}'"
|
||||
|
||||
- name: Assert that the filesystem has enough free space
|
||||
ansible.builtin.assert:
|
||||
that: shrink_lv_mount_info[0].block_size * shrink_lv_mount_info[0].block_used < (item.size | ansible.builtin.human_to_bytes)
|
||||
fail_msg: >
|
||||
Requested size {{ item.size }} is smaller than currently used
|
||||
{{ (shrink_lv_mount_info[0].block_size * shrink_lv_mount_info[0].block_used) | ansible.builtin.human_readable }}
|
@ -0,0 +1,54 @@
|
||||
---
|
||||
- name: Make sure the required facts are available
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- "!all"
|
||||
- "!min"
|
||||
- kernel
|
||||
- mounts
|
||||
|
||||
- name: Run preflight checks
|
||||
ansible.builtin.include_tasks: preflight.yaml
|
||||
|
||||
- name: Copy shrink LV dracut module
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: /usr/lib/dracut/modules.d/99shrink_lv/
|
||||
mode: "0554"
|
||||
loop:
|
||||
- module-setup.sh
|
||||
- shrink.sh
|
||||
|
||||
- name: Resolve and copy the shrink-start script
|
||||
ansible.builtin.template:
|
||||
src: shrink-start.sh.j2
|
||||
dest: /usr/lib/dracut/modules.d/99shrink_lv/shrink-start.sh
|
||||
mode: '0554'
|
||||
|
||||
- name: Create the initramfs and reboot to run the module
|
||||
vars:
|
||||
initramfs_add_modules: "shrink_lv lvm"
|
||||
ansible.builtin.include_role:
|
||||
name: initramfs
|
||||
|
||||
- name: Remove dracut extend boot module
|
||||
ansible.builtin.file:
|
||||
path: /usr/lib/dracut/modules.d/99shrink_lv
|
||||
state: absent
|
||||
|
||||
- name: Retrieve mount points
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- "!all"
|
||||
- "!min"
|
||||
- mounts
|
||||
|
||||
- name: Assert that the filesystem has shrunk
|
||||
ansible.builtin.assert:
|
||||
# yamllint disable-line rule:line-length
|
||||
that: (ansible_facts.mounts | selectattr('device', 'equalto', item.device) | map(attribute='size_total') | join | int) <= (item.size | ansible.builtin.human_to_bytes)
|
||||
fail_msg: >
|
||||
Logical Volume {{ item.device }} was not shrunk to {{ item.size }} as requested
|
||||
success_msg: >
|
||||
Logical Volume {{ item.device }} has been shrunk to {{ item.size }} as requested.
|
||||
loop: "{{ shrink_lv_devices }}"
|
@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: Assert shrink_lv_devices
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- shrink_lv_devices is defined
|
||||
- shrink_lv_devices | type_debug == "list"
|
||||
- shrink_lv_devices | length > 0
|
||||
fail_msg: shrink_lv_devices must be a list and include at least one element
|
||||
|
||||
- name: Validate initramfs preflight
|
||||
ansible.builtin.include_role:
|
||||
name: initramfs
|
||||
tasks_from: preflight
|
||||
|
||||
- name: Check all devices
|
||||
ansible.builtin.include_tasks: check_device.yaml
|
||||
loop: "{{ shrink_lv_devices }}"
|
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
activate_volume_groups(){
|
||||
for vg in `/usr/sbin/lvm vgs -o name --noheading 2>/dev/null`; do
|
||||
/usr/sbin/lvm vgchange -ay $vg
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
activate_volume_groups
|
||||
/usr/bin/shrink.sh {% for device in shrink_lv_devices %}--device={{ device.device }}:{{ device.size }} {% endfor %} 1>&2 >/dev/kmsg
|
||||
}
|
||||
|
||||
main "$0"
|
@ -0,0 +1,84 @@
|
||||
# snapshot_create role
|
||||
|
||||
|
||||
The `snapshot_create` role is used to control the creation for a defined set of LVM snapshot volumes.
|
||||
In addition, it can optionally save the Grub configuration and image files under /boot and configure settings to enable the LVM snapshot autoextend capability.
|
||||
The role will verify free space and should fail if there is not enough or if any snapshots already exist for the given `snapshot_create_set_name`.
|
||||
|
||||
The role is designed to support the automation of RHEL in-place upgrades, but can also be used to reduce the risk of more mundane system maintenance activities.
|
||||
|
||||
## Role Variables
|
||||
|
||||
### `snapshot_create_check_only`
|
||||
|
||||
When set to `true` the role will only verify there is enough free space for the specified snapshots and not create them.
|
||||
Default `false`
|
||||
|
||||
### `snapshot_create_set_name`
|
||||
|
||||
The variable `snapshot_create_set_name` is used to identify the list of volumes to be operated upon.
|
||||
The role will use the following naming convention when creating the snapshots:
|
||||
|
||||
`<Origin LV name>_<snapshot_create_set_name>`
|
||||
|
||||
### `snapshot_create_boot_backup`
|
||||
|
||||
Boolean to specify that the role should preserve the Grub configuration and image files under /boot required for booting the default kernel.
|
||||
The files are preserved in a compressed tar archive at `/root/boot-backup-<snapshot_create_set_name>.tgz`. Default is `false`.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> When automating RHEL in-place upgrades, do not perform a Grub to Grub2 migration as part of your upgrade playbook. It will invalidate your boot backup and cause a subsequent `revert` action to fail. For example, if you are using the [`upgrade`](https://github.com/redhat-cop/infra.leapp/tree/main/roles/upgrade#readme) role from the [`infra.leapp`](https://github.com/redhat-cop/infra.leapp) collection, do not set `update_grub_to_grub_2` to `true`. Grub to Grub2 migration should only be performed after the `remove` action has been performed to delete the snapshots and boot backup.
|
||||
|
||||
### `snapshot_create_snapshot_autoextend_threshold`
|
||||
|
||||
Configure the given `snapshot_create_autoextend_threshold` setting in lvm.conf before creating snapshots.
|
||||
|
||||
### `snapshot_create_snapshot_autoextend_percent`
|
||||
|
||||
Configure the given `snapshot_create_snapshot_autoextend_percent` setting in lvm.conf before creating snapshots.
|
||||
|
||||
### `snapshot_create_volumes`
|
||||
|
||||
This is the list of logical volumes for which snapshots are to be created and the size requirements for those snapshots. The volumes list is only required when the role is run with the check or create action.
|
||||
|
||||
### `vg`
|
||||
|
||||
The volume group of the origin logical volume for which a snapshot will be created.
|
||||
|
||||
### `lv`
|
||||
|
||||
The origin logical volume for which a snapshot will be created.
|
||||
|
||||
### `size`
|
||||
|
||||
The size of the logical volume according to the definition of the
|
||||
[size](https://docs.ansible.com/ansible/latest/collections/community/general/lvol_module.html#parameter-size)
|
||||
parameter of the `community.general.lvol` module.
|
||||
|
||||
To create thin provisioned snapshot of a thin provisioned volume, omit the `size` parameter or set it to `0`
|
||||
|
||||
## Example Playbooks
|
||||
|
||||
Perform space check and fail of there will not be enough space for all the snapshots in the set.
|
||||
If there is sufficient space, proceed to create snapshots for the listed logical volumes.
|
||||
Each snapshot will be sized to 20% of the origin volume size.
|
||||
Snapshot autoextend settings are configured to enable free space in the volume group to be allocated to any snapshot that may exceed 70% usage in the future.
|
||||
Files under /boot will be preserved.
|
||||
|
||||
```yaml
|
||||
- hosts: all
|
||||
roles:
|
||||
- name: snapshot_create
|
||||
snapshot_create_set_name: ripu
|
||||
snapshot_create_snapshot_autoextend_threshold: 70
|
||||
snapshot_create_snapshot_autoextend_percent: 20
|
||||
snapshot_create_boot_backup: true
|
||||
snapshot_create_volumes:
|
||||
- vg: rootvg
|
||||
lv: root
|
||||
size: 2G
|
||||
- vg: rootvg
|
||||
lv: var
|
||||
size: 2G
|
||||
```
|
@ -0,0 +1,2 @@
|
||||
snapshot_create_volumes: []
|
||||
snapshot_create_boot_backup: false
|
@ -0,0 +1,238 @@
|
||||
'''
|
||||
Check is there is enough space to created all the requested snapshots
|
||||
The input should be a json string array.
|
||||
Each element should have the following keys:
|
||||
- vg: Name of the volume group
|
||||
- lv: Name of the Logical Volume
|
||||
- size: The size of the requested snapshot.
|
||||
Follow (https://docs.ansible.com/ansible/latest/collections/community/general/lvol_module.html#parameter-size)
|
||||
without support for sign
|
||||
'''
|
||||
import argparse
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
_VGS_COMMAND = '/usr/sbin/vgs'
|
||||
_LVS_COMMAND = '/usr/sbin/lvs'
|
||||
|
||||
_EXIT_CODE_SUCCESS = 0
|
||||
_EXIT_CODE_VOLUME_GROUP_SPACE = 1
|
||||
_EXIT_CODE_FILE_SYSTEM_TYPE = 2
|
||||
_EXIT_CODE_VOLUME_SPACE = 3
|
||||
|
||||
_supported_filesystems = [
|
||||
'',
|
||||
'ext2',
|
||||
'ext3',
|
||||
'ext4'
|
||||
]
|
||||
|
||||
|
||||
class CheckException(Exception):
|
||||
""" Exception wrapper """
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('that', help='What should the script check', type=str, choices=['snapshots', 'resize'])
|
||||
parser.add_argument('volumes', help='Volumes JSON array in a string', type=str)
|
||||
|
||||
|
||||
def _main():
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
volumes = json.loads(args.volumes)
|
||||
except json.decoder.JSONDecodeError:
|
||||
print("Provided volume list '{volumes}' it not a valid json string".format(volumes=sys.argv[1]))
|
||||
sys.exit(1)
|
||||
|
||||
groups_names = set(vol['vg'] for vol in volumes)
|
||||
groups_info = {
|
||||
group: _get_group_info(group) for group in groups_names
|
||||
}
|
||||
|
||||
for vol in volumes:
|
||||
vol['normalized_size'] = _calc_requested_size(groups_info[vol["vg"]], vol)
|
||||
groups_info[vol["vg"]]['requested_size'] += vol['normalized_size']
|
||||
|
||||
if args.that == 'snapshots':
|
||||
exit_code = _check_free_size_for_snapshots(groups_info)
|
||||
if exit_code == _EXIT_CODE_SUCCESS:
|
||||
norm_vols = [
|
||||
{
|
||||
'vg': vol['vg'],
|
||||
'lv': vol['lv'],
|
||||
'size': "{size}B".format(size=vol['normalized_size'])
|
||||
} for vol in volumes
|
||||
]
|
||||
print(json.dumps(norm_vols))
|
||||
if args.that == 'resize':
|
||||
exit_code = _check_free_size_for_resize(volumes, groups_info)
|
||||
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
||||
def _check_free_size_for_snapshots(groups_info):
|
||||
return _check_requested_size(groups_info, 'free')
|
||||
|
||||
|
||||
def _check_free_size_for_resize(volumes, groups_info):
|
||||
exit_code = _check_requested_size(groups_info, 'size')
|
||||
if exit_code != _EXIT_CODE_SUCCESS:
|
||||
return exit_code
|
||||
|
||||
mtab = _parse_mtab()
|
||||
|
||||
for volume in volumes:
|
||||
mtab_entry = mtab.get("/dev/mapper/{vg}-{lv}".format(vg=volume['vg'], lv=volume['lv']))
|
||||
volume['fs_type'] = mtab_entry['type'] if mtab_entry else ''
|
||||
volume['fs_size'] = _calc_filesystem_size(mtab_entry) if mtab_entry else 0
|
||||
|
||||
filesystems_supported = all(volume['fs_type'] in _supported_filesystems for volume in volumes)
|
||||
if not filesystems_supported:
|
||||
exit_code = _EXIT_CODE_FILE_SYSTEM_TYPE
|
||||
|
||||
enough_space = all(vol['normalized_size'] > vol['fs_size'] for vol in volumes)
|
||||
if not enough_space:
|
||||
exit_code = _EXIT_CODE_VOLUME_SPACE
|
||||
|
||||
if exit_code != _EXIT_CODE_SUCCESS:
|
||||
print(json.dumps(_to_printable_volumes(volumes)))
|
||||
|
||||
return exit_code
|
||||
|
||||
|
||||
def _check_requested_size(groups_info, group_field):
|
||||
enough_space = all(group['requested_size'] <= group[group_field] for _, group in groups_info.items())
|
||||
if not enough_space:
|
||||
print(json.dumps(groups_info))
|
||||
return _EXIT_CODE_VOLUME_GROUP_SPACE
|
||||
return _EXIT_CODE_SUCCESS
|
||||
|
||||
|
||||
def _get_group_info(group):
|
||||
group_info_str = subprocess.check_output([_VGS_COMMAND, group, '-v', '--units', 'b', '--reportformat', 'json'])
|
||||
group_info_json = json.loads(group_info_str)
|
||||
group_info = group_info_json['report'][0]['vg'][0]
|
||||
return {
|
||||
'name': group,
|
||||
'size': _get_size_from_report(group_info['vg_size']),
|
||||
'free': _get_size_from_report(group_info['vg_free']),
|
||||
'extent_size': _get_size_from_report(group_info['vg_extent_size']),
|
||||
'requested_size': 0
|
||||
}
|
||||
|
||||
|
||||
def _calc_requested_size(group_info, volume):
|
||||
unit = 'm'
|
||||
requested_size = volume.get('size', 0)
|
||||
if requested_size == 0:
|
||||
# handle thin provisioning
|
||||
pass
|
||||
if isinstance(requested_size, int) or isinstance(requested_size, float):
|
||||
size = requested_size
|
||||
else:
|
||||
parts = requested_size.split('%')
|
||||
if len(parts) == 2:
|
||||
unit = 'b'
|
||||
percent = float(parts[0])
|
||||
percent_of = parts[1]
|
||||
if percent_of == 'VG':
|
||||
size = group_info['size'] * percent / 100
|
||||
elif percent_of == 'FREE':
|
||||
size = group_info['free'] * percent / 100
|
||||
elif percent_of == 'ORIGIN':
|
||||
origin_size = _get_volume_size(volume)
|
||||
size = origin_size * percent / 100
|
||||
else:
|
||||
raise CheckException("Unsupported base type {base_type}".format(base_type=percent_of))
|
||||
else:
|
||||
try:
|
||||
size = float(requested_size[:-1])
|
||||
unit = requested_size[-1].lower()
|
||||
except ValueError:
|
||||
raise CheckException('Failed to read requested size {size}'.format(size=requested_size))
|
||||
return _align_to_extent(_convert_to_bytes(size, unit), group_info['extent_size'])
|
||||
|
||||
|
||||
def _get_volume_size(vol):
|
||||
volume_info_str = subprocess.check_output(
|
||||
[_LVS_COMMAND, "{vg}/{lv}".format(vg=vol['vg'], lv=vol['lv']), '-v', '--units', 'b', '--reportformat', 'json']
|
||||
)
|
||||
volume_info_json = json.loads(volume_info_str)
|
||||
volume_info = volume_info_json['report'][0]['lv'][0]
|
||||
return _get_size_from_report(volume_info['lv_size'])
|
||||
|
||||
|
||||
def _get_size_from_report(reported_size):
|
||||
try:
|
||||
size = float(reported_size)
|
||||
unit = 'm'
|
||||
except ValueError:
|
||||
if reported_size[0] == '<':
|
||||
reported_size = reported_size[1:]
|
||||
size = float(reported_size[:-1])
|
||||
unit = reported_size[-1].lower()
|
||||
return _convert_to_bytes(size, unit)
|
||||
|
||||
|
||||
def _align_to_extent(size, extent_size):
|
||||
return math.ceil(size / extent_size) * extent_size
|
||||
|
||||
|
||||
def _calc_filesystem_size(mtab_entry):
|
||||
fs_stat = os.statvfs(mtab_entry['mount_point'])
|
||||
return (fs_stat.f_blocks - fs_stat.f_bfree) * fs_stat.f_bsize
|
||||
|
||||
|
||||
def _parse_mtab():
|
||||
mtab = {}
|
||||
with open('/etc/mtab') as f:
|
||||
for m in f:
|
||||
fs_spec, fs_file, fs_vfstype, _fs_mntops, _fs_freq, _fs_passno = m.split()
|
||||
mtab[fs_spec] = {
|
||||
'mount_point': fs_file,
|
||||
'type': fs_vfstype
|
||||
}
|
||||
return mtab
|
||||
|
||||
|
||||
def _convert_to_bytes(size, unit):
|
||||
convertion_table = {
|
||||
'b': 1024 ** 0,
|
||||
'k': 1024 ** 1,
|
||||
'm': 1024 ** 2,
|
||||
'g': 1024 ** 3,
|
||||
't': 1024 ** 4,
|
||||
'p': 1024 ** 5,
|
||||
'e': 1024 ** 6,
|
||||
}
|
||||
return size * convertion_table[unit]
|
||||
|
||||
|
||||
def _convert_to_unit_size(bytes):
|
||||
units = ['b', 'k', 'm', 'g', 't', 'p', 'e']
|
||||
i = 0
|
||||
while bytes >= 1024:
|
||||
i += 1
|
||||
bytes /= 1024
|
||||
# Round down bytes to two digits
|
||||
bytes = math.floor(bytes * 100) / 100
|
||||
return "{size}{unit}".format(size=bytes, unit=units[i])
|
||||
|
||||
|
||||
def _to_printable_volumes(volumes):
|
||||
return {
|
||||
volume['vg'] + "_" + volume['lv']: {
|
||||
'file_system_type': volume['fs_type'],
|
||||
'used': _convert_to_unit_size(volume['fs_size']),
|
||||
'requested_size': _convert_to_unit_size(volume['normalized_size'])
|
||||
} for volume in volumes
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
_main()
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Ygal Blum, Bob Mader
|
||||
description: Create a defined set of LVM snapshot volumes
|
||||
company: Red Hat
|
||||
license: MIT
|
||||
min_ansible_version: "2.14"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags: []
|
||||
dependencies: []
|
||||
...
|
@ -0,0 +1,26 @@
|
||||
- name: Verify that all volumes exist
|
||||
ansible.builtin.include_tasks: verify_volume_exists.yml
|
||||
loop: "{{ snapshot_create_volumes }}"
|
||||
|
||||
- name: Verify that there are no existing snapshots
|
||||
ansible.builtin.include_tasks: verify_no_existing_snapshot.yml
|
||||
loop: "{{ snapshot_create_volumes }}"
|
||||
|
||||
- name: Verify that there is enough storage space
|
||||
ansible.builtin.script: check.py snapshots '{{ snapshot_create_volumes | to_json }}'
|
||||
args:
|
||||
executable: "{{ ansible_python.executable }}"
|
||||
register: snapshot_create_check_status
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
|
||||
- name: Store check return in case of failure
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_create_check_failure_json: "{{ snapshot_create_check_status.stdout | from_json }}"
|
||||
when: snapshot_create_check_status.rc != 0
|
||||
|
||||
- name: Assert results
|
||||
ansible.builtin.assert:
|
||||
that: snapshot_create_check_status.rc == 0
|
||||
fail_msg: Not enough space in the Volume Groups to create the requested snapshots
|
||||
success_msg: The Volume Groups have enough space to create the requested snapshots
|
@ -0,0 +1,68 @@
|
||||
- name: Update lvm configuration
|
||||
block:
|
||||
- name: Stringify snapshot_autoextend_percent setting
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_create_snapshot_autoextend_percent_config: "activation/snapshot_autoextend_percent={{ snapshot_create_snapshot_autoextend_percent }}"
|
||||
when: snapshot_create_snapshot_autoextend_percent is defined
|
||||
- name: Stringify snapshot_autoextend_threshold setting
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_create_snapshot_autoextend_threshold_config: "activation/snapshot_autoextend_threshold={{ snapshot_create_snapshot_autoextend_threshold }}"
|
||||
when: snapshot_create_snapshot_autoextend_threshold is defined
|
||||
- name: Stringify the new config
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_create_new_lvm_config: >
|
||||
{{ snapshot_create_snapshot_autoextend_percent_config | default('') }}
|
||||
{{ snapshot_create_snapshot_autoextend_threshold_config | default('') }}
|
||||
- name: Set LVM configuration
|
||||
ansible.builtin.command: 'lvmconfig --mergedconfig --config "{{ snapshot_create_new_lvm_config }}" --file /etc/lvm/lvm.conf'
|
||||
changed_when: true
|
||||
when: ((snapshot_create_new_lvm_config | trim) | length) > 0
|
||||
|
||||
- name: Check for grubenv saved_entry
|
||||
ansible.builtin.lineinfile:
|
||||
name: /boot/grub2/grubenv
|
||||
regexp: ^saved_entry=
|
||||
state: absent
|
||||
check_mode: true
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: snapshot_create_grubenv
|
||||
|
||||
- name: Add grubenv saved_entry
|
||||
ansible.builtin.shell: 'grubby --set-default-index=$(grubby --default-index)'
|
||||
changed_when: true
|
||||
when: snapshot_create_grubenv.found is defined and snapshot_create_grubenv.found == 0
|
||||
|
||||
- name: Create snapshots
|
||||
community.general.lvol:
|
||||
vg: "{{ item.vg }}"
|
||||
lv: "{{ item.lv }}"
|
||||
snapshot: "{{ item.lv }}_{{ snapshot_create_set_name }}"
|
||||
size: "{{ item.size | default(omit) }}"
|
||||
loop: "{{ snapshot_create_volumes }}"
|
||||
|
||||
- name: Required packages are present
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- gzip
|
||||
- tar
|
||||
state: present
|
||||
|
||||
- name: Create boot backup
|
||||
community.general.archive:
|
||||
format: gz
|
||||
mode: '0644'
|
||||
dest: "/root/boot-backup-{{ snapshot_create_set_name }}.tgz"
|
||||
path:
|
||||
- "/boot/initramfs-{{ ansible_kernel }}.img"
|
||||
- "/boot/vmlinuz-{{ ansible_kernel }}"
|
||||
- "/boot/System.map-{{ ansible_kernel }}"
|
||||
- "/boot/symvers-{{ ansible_kernel }}.gz"
|
||||
- "/boot/config-{{ ansible_kernel }}"
|
||||
- "/boot/.vmlinuz-{{ ansible_kernel }}.hmac"
|
||||
- /boot/grub/grub.conf
|
||||
- /boot/grub2/grub.cfg
|
||||
- /boot/grub2/grubenv
|
||||
- /boot/loader/entries
|
||||
- /boot/efi/EFI/redhat/grub.cfg
|
||||
when: snapshot_create_boot_backup
|
@ -0,0 +1,8 @@
|
||||
- name: Check available disk space
|
||||
ansible.builtin.include_tasks: check.yml
|
||||
|
||||
- name: Create Snapshot
|
||||
vars:
|
||||
snapshot_create_volumes: "{{ snapshot_create_check_status.stdout | from_json }}"
|
||||
ansible.builtin.include_tasks: create.yml
|
||||
when: not (snapshot_create_check_only | default(false))
|
@ -0,0 +1,21 @@
|
||||
- name: Run lvs
|
||||
ansible.builtin.command: >
|
||||
lvs
|
||||
--select 'vg_name = {{ item.vg }}
|
||||
&& origin = {{ item.lv }}
|
||||
&& lv_name = {{ item.lv }}_{{ snapshot_create_set_name }}'
|
||||
--reportformat json
|
||||
register: snapshot_create_lvs_response
|
||||
changed_when: false
|
||||
|
||||
- name: Parse report
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_create_lv_snapshot_report_array: "{{ (snapshot_create_lvs_response.stdout | from_json).report[0].lv }}"
|
||||
|
||||
- name: Verify that the no snapshot exists for the volume
|
||||
ansible.builtin.assert:
|
||||
that: (snapshot_create_lv_snapshot_report_array | length) == 0
|
||||
fail_msg: >
|
||||
The volume '{{ item.lv }}' in volume group '{{ item.vg }}'
|
||||
already has at least one snapshot
|
||||
'{{ snapshot_create_lv_snapshot_report_array[0].lv_name | default('none') }}'
|
@ -0,0 +1,9 @@
|
||||
- name: Run lvs
|
||||
ansible.builtin.command: "lvs --select 'vg_name = {{ item.vg }} && lv_name = {{ item.lv }}' --reportformat json"
|
||||
register: snapshot_create_lvs_response
|
||||
changed_when: false
|
||||
|
||||
- name: Verify that the volume was found
|
||||
ansible.builtin.assert:
|
||||
that: (((snapshot_create_lvs_response.stdout | from_json).report[0].lv) | length) > 0
|
||||
fail_msg: "Could not find volume '{{ item.lv }}' in volume group '{{ item.vg }}'"
|
@ -0,0 +1,32 @@
|
||||
# snapshot_remove role
|
||||
|
||||
The `snapshot_remove` role is used to remove snapshots.
|
||||
In addition, it removes the Grub configuration and image files under /boot if it was previously backed up
|
||||
It is intended to be used along with the `snapshot_create` role.
|
||||
|
||||
The role is designed to support the automation of RHEL in-place upgrades, but can also be used to reduce the risk of more mundane system maintenance activities.
|
||||
|
||||
## Role Variables
|
||||
|
||||
### `snapshot_remove_set_name`
|
||||
|
||||
The variable `snapshot_remove_set_name` is used to identify the list of volumes to be operated upon.
|
||||
The role will use the following naming convention when reverting the snapshots:
|
||||
|
||||
`<Origin LV name>_<snapshot_remove_set_name>`
|
||||
|
||||
This naming convention will be used to identify the snapshots to be removed.
|
||||
|
||||
## Example Playbooks
|
||||
|
||||
### Commit
|
||||
|
||||
A commit playbook is used when users are comfortable the snapshots are not needed any longer.
|
||||
Each snapshot in the snapshot set is removed and the backed up image files from /boot are deleted.
|
||||
|
||||
```yaml
|
||||
- hosts: all
|
||||
roles:
|
||||
- name: snapshot_remove
|
||||
snapshot_remove_set_name: ripu
|
||||
```
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Ygal Blum, Bob Mader
|
||||
description: Remove snapshots previously created using the snapshot_create role
|
||||
company: Red Hat
|
||||
license: MIT
|
||||
min_ansible_version: "2.14"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags: []
|
||||
dependencies: []
|
||||
...
|
@ -0,0 +1,23 @@
|
||||
- name: Calculate the list of snapshots
|
||||
block:
|
||||
- name: Get list of volumes
|
||||
ansible.builtin.command: "lvs --select 'lv_name =~ {{ snapshot_remove_set_name }}$ && origin != \"\"' --reportformat json "
|
||||
register: snapshot_remove_lvs_response
|
||||
changed_when: false
|
||||
- name: Get LV dict List
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_remove_snapshots: "{{ (snapshot_remove_lvs_response.stdout | from_json).report[0].lv }}"
|
||||
|
||||
- name: Remove snapshots
|
||||
community.general.lvol:
|
||||
state: absent
|
||||
vg: "{{ item.vg_name }}"
|
||||
lv: "{{ item.origin }}"
|
||||
snapshot: "{{ item.lv_name }}"
|
||||
force: true
|
||||
loop: "{{ snapshot_remove_snapshots }}"
|
||||
|
||||
- name: Remove boot backup
|
||||
ansible.builtin.file:
|
||||
path: "/root/boot-backup-{{ snapshot_remove_set_name }}.tgz"
|
||||
state: absent
|
@ -0,0 +1,36 @@
|
||||
# snapshot_revert role
|
||||
|
||||
|
||||
The `snapshot_revert` role is used to merge snapshots to origin and reboot (i.e., rollback).
|
||||
The role will verify that all snapshots in the set are still in active state before doing any merges.
|
||||
This is to prevent rolling back if any snapshots have become invalidated in which case the role should fail.
|
||||
In addition, it restores the Grub configuration and image files under /boot is it was previously backed up
|
||||
It is intended to be used along with the `snapshot_create` role.
|
||||
|
||||
The role is designed to support the automation of RHEL in-place upgrades, but can also be used to reduce the risk of more mundane system maintenance activities.
|
||||
|
||||
## Role Variables
|
||||
|
||||
### `snapshot_revert_set_name`
|
||||
|
||||
The variable `snapshot_revert_set_name` is used to identify the list of volumes to be operated upon.
|
||||
The role will use the following naming convention when reverting the snapshots:
|
||||
|
||||
`<Origin LV name>_<snapshot_revert_set_name>`
|
||||
|
||||
This naming convention will be used to identify the snapshots to be merged.
|
||||
|
||||
The `revert` action will verify that all snapshots in the set are still active state before doing any merges. This is to prevent rolling back if any snapshots have become invalidated in which case the `revert` action should fail.
|
||||
|
||||
## Example Playbooks
|
||||
|
||||
This playbook rolls back the host using the snapshots created using the `snapshot_create` role.
|
||||
After verifying that all snapshots are still valid, each logical volume in the snapshot set is merged.
|
||||
The image files under /boot will be restored and then the host will be rebooted.
|
||||
|
||||
```yaml
|
||||
- hosts: all
|
||||
roles:
|
||||
- name: snapshot_revert
|
||||
snapshot_revert_set_name: ripu
|
||||
```
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Ygal Blum, Bob Mader
|
||||
description: Revert to snapshots previously created using the snapshot_create role
|
||||
company: Red Hat
|
||||
license: MIT
|
||||
min_ansible_version: "2.14"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags: []
|
||||
dependencies: []
|
||||
...
|
@ -0,0 +1,73 @@
|
||||
- name: Calculate the list of snapshots
|
||||
block:
|
||||
- name: Get list of volumes
|
||||
ansible.builtin.command: "lvs --select 'lv_name =~ {{ snapshot_revert_set_name }}$ && origin != \"\"' --reportformat json "
|
||||
register: snapshot_revert_lvs_response
|
||||
changed_when: false
|
||||
- name: Get LV dict List
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_revert_snapshots: "{{ (snapshot_revert_lvs_response.stdout | from_json).report[0].lv }}"
|
||||
|
||||
- name: Verify that all snapshots are active
|
||||
ansible.builtin.include_tasks: verify_snapshot_active.yml
|
||||
loop: "{{ snapshot_revert_snapshots }}"
|
||||
|
||||
- name: Required packages are present
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- gzip
|
||||
- tar
|
||||
state: present
|
||||
|
||||
- name: Check if Boot backup exists
|
||||
ansible.builtin.stat:
|
||||
path: "/root/boot-backup-{{ snapshot_revert_set_name }}.tgz"
|
||||
register: snapshot_revert_boot_archive_stat
|
||||
|
||||
- name: Restore boot backup
|
||||
ansible.builtin.unarchive:
|
||||
remote_src: true
|
||||
src: "{{ snapshot_revert_boot_archive_stat.stat.path }}"
|
||||
dest: /boot
|
||||
when: snapshot_revert_boot_archive_stat.stat.exists
|
||||
|
||||
- name: Revert to snapshots
|
||||
ansible.builtin.command: "lvconvert --merge /dev/{{ item.vg_name }}/{{ item.lv_name }}"
|
||||
loop: "{{ snapshot_revert_snapshots }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Reboot
|
||||
ansible.builtin.reboot:
|
||||
|
||||
- name: Check if /boot is on LVM
|
||||
ansible.builtin.command: "grub2-probe --target=abstraction /boot"
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: snapshot_revert_boot_abstraction
|
||||
|
||||
- name: Reinstall Grub to boot device
|
||||
when: snapshot_revert_boot_abstraction.stdout == 'lvm'
|
||||
block:
|
||||
- name: Get boot device
|
||||
ansible.builtin.shell: "lsblk -spnlo name $(grub2-probe --target=device /boot)"
|
||||
changed_when: false
|
||||
register: snapshot_revert_boot_dev_deps
|
||||
|
||||
- name: Run grub2-install
|
||||
ansible.builtin.command: "grub2-install {{ snapshot_revert_boot_dev_deps.stdout_lines | last }}"
|
||||
changed_when: true
|
||||
|
||||
- name: Remove boot backup
|
||||
ansible.builtin.file:
|
||||
path: "{{ snapshot_revert_boot_archive_stat.stat.path }}"
|
||||
state: absent
|
||||
when: snapshot_revert_boot_archive_stat.stat.exists
|
||||
|
||||
- name: Wait for the snapshot to drain
|
||||
ansible.builtin.command: "lvs --select 'vg_name = {{ item.vg_name }} && lv_name = {{ item.origin }}' --reportformat json"
|
||||
register: snapshot_revert_lv_drain_check
|
||||
until: (snapshot_revert_lv_drain_check.stdout | from_json).report[0].lv[0].data_percent == ""
|
||||
retries: 20
|
||||
delay: 30
|
||||
loop: "{{ snapshot_revert_snapshots }}"
|
||||
changed_when: false
|
@ -0,0 +1,14 @@
|
||||
- name: Run lvs
|
||||
ansible.builtin.command: "lvs --select 'lv_name = {{ item.lv_name }}' --reportformat json"
|
||||
register: snapshot_revert_lvs_response
|
||||
changed_when: false
|
||||
|
||||
- name: Parse report
|
||||
ansible.builtin.set_fact:
|
||||
snapshot_revert_lv_attr: "{{ (snapshot_revert_lvs_response.stdout | from_json).report[0].lv[0].lv_attr }}"
|
||||
|
||||
- name: Verify that the snapshot is active
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- snapshot_revert_lv_attr[0] == 's'
|
||||
- snapshot_revert_lv_attr[4] == 'a'
|
@ -16,5 +16,5 @@ collections:
|
||||
- name: ansible.posix
|
||||
version: 1.5.4
|
||||
|
||||
- name: infra.lvm_snapshots
|
||||
version: 2.1.0
|
||||
# - name: infra.lvm_snapshots
|
||||
# version: 2.1.0
|
||||
|
@ -3,3 +3,8 @@
|
||||
src: https://gitea.thezengarden.net/ansible_roles/autofsck.git
|
||||
scm: git
|
||||
version: main
|
||||
|
||||
- name: verified_reboot
|
||||
src: https://gitea.thezengarden.net/ansible_plays/verified_reboot.git
|
||||
scm: git
|
||||
version: main
|
||||
|
@ -2,34 +2,34 @@
|
||||
- name: Ensure service facts are available
|
||||
ansible.builtin.service_facts:
|
||||
|
||||
- name: Capture a list of running services
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_systemd_running_services:
|
||||
"{{ bigboot_systemd_running_services | default([]) + [item['key']] }}"
|
||||
loop: "{{ ansible_facts['services'] | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item['key'] }}"
|
||||
when:
|
||||
- "'running' in item['value']['state']"
|
||||
# - name: Capture a list of running services
|
||||
# ansible.builtin.set_fact:
|
||||
# bigboot_systemd_running_services:
|
||||
# "{{ bigboot_systemd_running_services | default([]) + [item['key']] }}"
|
||||
# loop: "{{ ansible_facts['services'] | dict2items }}"
|
||||
# loop_control:
|
||||
# label: "{{ item['key'] }}"
|
||||
# when:
|
||||
# - "'running' in item['value']['state']"
|
||||
|
||||
- name: Get the stop timeout value for running services
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
set -o pipefail
|
||||
systemctl show {{ item }} | grep TimeoutStopUSec
|
||||
changed_when: false
|
||||
register: bigboot_systemd_service_timeout
|
||||
loop: "{{ bigboot_systemd_running_services }}"
|
||||
# - name: Get the stop timeout value for running services
|
||||
# ansible.builtin.shell:
|
||||
# cmd: |
|
||||
# set -o pipefail
|
||||
# systemctl show {{ item }} | grep TimeoutStopUSec
|
||||
# changed_when: false
|
||||
# register: bigboot_systemd_service_timeout
|
||||
# loop: "{{ bigboot_systemd_running_services }}"
|
||||
|
||||
- name: Adding services exceeding the timeout threshold to the list of services to disable
|
||||
ansible.builtin.set_fact:
|
||||
bigboot_services_disabled: "{{ bigboot_services_disabled | default([]) + [item['item']] }}"
|
||||
loop: "{{ bigboot_systemd_service_timeout['results'] }}"
|
||||
loop_control:
|
||||
label: "{{ item['item'] }}"
|
||||
when:
|
||||
- item['item'] not in bigboot_protected_services
|
||||
- item['stdout'] | regex_replace('^.*=(.*$)', '\\1') | community.general.to_minutes >= bigboot_service_max_timeout | int
|
||||
# - name: Adding services exceeding the timeout threshold to the list of services to disable
|
||||
# ansible.builtin.set_fact:
|
||||
# bigboot_services_disabled: "{{ bigboot_services_disabled | default([]) + [item['item']] }}"
|
||||
# loop: "{{ bigboot_systemd_service_timeout['results'] }}"
|
||||
# loop_control:
|
||||
# label: "{{ item['item'] }}"
|
||||
# when:
|
||||
# - item['item'] not in bigboot_protected_services
|
||||
# - item['stdout'] | regex_replace('^.*=(.*$)', '\\1') | community.general.to_minutes >= bigboot_service_max_timeout | int
|
||||
|
||||
- name: Adding incompatible services to the list of services to disable
|
||||
ansible.builtin.set_fact:
|
||||
|
@ -11,15 +11,19 @@
|
||||
# - name: Reboot to run filesystem checks
|
||||
# ansible.builtin.reboot:
|
||||
|
||||
- name: Reboot to run filesystem checks
|
||||
ansible.builtin.command: /sbin/shutdown -r +1
|
||||
# - name: Reboot to run filesystem checks
|
||||
# ansible.builtin.command: /sbin/shutdown -r +1
|
||||
|
||||
- name: Wait for the reboot to complete
|
||||
ansible.builtin.wait_for_connection:
|
||||
connect_timeout: 20
|
||||
sleep: 10
|
||||
delay: "{{ bigboot_post_reboot_delay | default('70') }}"
|
||||
timeout: "{{ bigboot_reboot_timeout | default('1800') }}"
|
||||
# - name: Wait for the reboot to complete
|
||||
# ansible.builtin.wait_for_connection:
|
||||
# connect_timeout: 20
|
||||
# sleep: 10
|
||||
# delay: "{{ bigboot_post_reboot_delay | default('70') }}"
|
||||
# timeout: "{{ bigboot_reboot_timeout | default('1800') }}"
|
||||
|
||||
- name: Reboot host to run filesystem checks
|
||||
ansible.builtin.import_role:
|
||||
name: verified_reboot
|
||||
|
||||
- name: Disable Grub filesystem check
|
||||
ansible.builtin.import_role:
|
||||
|
Loading…
x
Reference in New Issue
Block a user