← RHCE in Ansible: automation and operations
13 / 15 · 55 MIN

LVM, filesystem and persistent mounting

Plan capacity growth with confirmed identity and layer-specific validation.

Separate the layers

A reconciliation batch is approaching its space limit. Storage staff increased capacity presented to the VM, but df is unchanged. Diagnosis must locate the layer not yet expanded: device, PV, VG, LV or filesystem. Free VG capacity is not free filesystem space. Nor does every change require modifying every layer; an existing VG reserve may be sufficient. Record device and UUID, filesystem, mount, usage and free capacity before deciding. A name such as /dev/sdb can change between machines or boots and is not authorization to format a disk.

A repeatable target

The exercise uses an existing lab XFS LV mounted at /srv/dr-batch. Its name is labvg/batch and the target is at least 6 GiB. Before execution, confirm on a disposable RHEL 10 VM that the VG has enough capacity and the volume contains no data to retain. The playbook compares supplied and observed UUIDs and rejects another filesystem type or mount. size: 6g expresses an absolute target; size: +2g expresses an increment that may grow again on every repeat. shrink: false prevents reducing an already larger LV, so the contract is a lower bound rather than exactly 6 GiB.

Growth and recovery

resizefs requests filesystem growth along with the LV for supported types. Still confirm both outcomes: a failure can leave a larger LV without completing filesystem growth. Do not equate that partial state with automatic data loss or declare it resolved from LV size alone. For XFS, do not plan shrinking as a simple reversal of growth; RHEL documentation does not support that reduction. If requirements change to a smaller volume, prepare migration or restoration to an appropriate destination and validate the application. A snapshot alone does not replace a tested recovery plan and may depend on the same limited capacity.

Persistence and acceptance

state: mounted configures both persistent entry and current mount. present handles persistent configuration without guaranteeing the current mount; ephemeral provides a temporary mount without writing fstab. Choose the state matching the contract. To accept the exercise, compare lvs, findmnt and df, verify synthetic data writes and reads, and repeat the playbook. Then reboot the lab VM in a controlled manner and observe the same UUID at the same mountpoint again. An fstab line does not prove device availability at boot or application access through directories.

Exercise status

This example was checked for syntax and module resolution, not executed against actual LVM. Install the collections listed in requirements.yml and supply inventory rhel_lab, lab_confirmed=true and expected_uuid only after preparing the disposable VM. The example starts from an existing LV; it does not provision disks, PVs, VG or the initial filesystem. Those prerequisites and later observations are part of the practical work to perform.

# Exercise for a disposable RHEL 10 VM with an existing XFS lab LV.
# Syntax checked only; no LVM, mount or reboot execution is claimed.
- name: Grow an identified lab filesystem without allowing shrink
 hosts: rhel_lab
 become: true
 gather_facts: true
 vars:
 lab_vg: labvg
 lab_lv: batch
 lab_path: /srv/dr-batch
 pre_tasks:
 - name: Require an explicit disposable lab and expected UUID
 ansible.builtin.assert:
 that:
 - lab_confirmed | default(false) | bool
 - ansible_distribution == 'RedHat'
 - ansible_distribution_major_version == '10'
 - expected_uuid | default('') | length > 0
 - name: Read identity of the existing filesystem
 ansible.builtin.command:
 argv: [blkid, -s, UUID, -o, value, "/dev/{{ lab_vg }}/{{ lab_lv }}"]
 register: observed_uuid
 changed_when: false
 - name: Read existing filesystem type
 ansible.builtin.command:
 argv: [blkid, -s, TYPE, -o, value, "/dev/{{ lab_vg }}/{{ lab_lv }}"]
 register: observed_type
 changed_when: false
 - name: Reject unexpected volume identity or type before resizing
 ansible.builtin.assert:
 that:
 - observed_uuid.stdout | trim == expected_uuid
 - observed_type.stdout | trim == 'xfs'
 - name: Confirm that XFS is already mounted at the intended lab path
 ansible.builtin.command:
 argv: [findmnt, --noheadings, --source, "UUID={{ expected_uuid }}", --output, TARGET]
 register: current_mount
 changed_when: false
 - name: Reject unexpected mount identity before growth
 ansible.builtin.assert:
 that:
 - current_mount.stdout | trim == lab_path
 tasks:
 - name: Grow to at least six GiB without shrinking a larger LV
 community.general.lvol:
 vg: "{{ lab_vg }}"
 lv: "{{ lab_lv }}"
 size: 6g
 shrink: false
 resizefs: true
 state: present
 - name: Keep the identified filesystem mounted and configured
 ansible.posix.mount:
 path: "{{ lab_path }}"
 src: "UUID={{ expected_uuid }}"
 fstype: xfs
 opts: defaults
 state: mounted
IN PRACTICE

LV grows from 4 to 6 GiB but df still shows 4: confirm and address the filesystem layer.

Common pitfalls

Repeated increments; treating XFS reduction as rollback; fstab as reboot proof; assuming identity from a disk name.

Related topics: SELinux: mappings and effective state · Services, firewall and external validation

Take this idea with you

Confirm identity and measure capacity, filesystem, mounting and use separately.

Create account

Reference: Logical volume module · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned

Red Hat®, RHCE and Ansible are trademarks or registered trademarks of Red Hat, Inc. bigsavant.com is an independent preparation platform and is not affiliated with, associated with, sponsored, authorised or endorsed by Red Hat. Content and questions are original, are not official exam questions, and completing our tests does not award or guarantee any certification. Names are used only to identify the subject. All other trademarks belong to their respective owners.