Chapter 20. Managing local storage using RHEL System Roles To manage LVM and local file systems (FS) using Ansible, you can use the storage role, which is one of the RHEL System Roles available in RHEL 8. Using the storage role enables you to automate administration of file systems on disks and logical volumes on multiple machines and across all versions of RHEL starting with RHEL 7.7. For more information about RHEL System Roles and how to apply them, see Introduction to RHEL System Roles . 20.1. Introduction to the storage RHEL System Role The storage role can manage: File systems on disks which have not been partitioned Complete LVM volume groups including their logical volumes and file systems MD RAID volumes and their file systems With the storage role, you can perform the following tasks: Create a file system Remove a file system Mount a file system Unmount a file system Create LVM volume groups Remove LVM volume groups Create logical volumes Remove logical volumes Create RAID volumes Remove RAID volumes Create LVM volume groups with RAID Remove LVM volume groups with RAID Create encrypted LVM volume groups Create LVM logical volumes with RAID 20.2. Parameters that identify a storage device in the storage RHEL System Role Your storage role configuration affects only the file systems, volumes, and pools that you list in the following variables. storage_volumes List of file systems on all unpartitioned disks to be managed. storage_volumes can also include raid volumes. Partitions are currently unsupported. storage_pools List of pools to be managed. Currently the only supported pool type is LVM. With LVM, pools represent volume groups (VGs). Under each pool there is a list of volumes to be managed by the role. With LVM, each volume corresponds to a logical volume (LV) with a file system. 20.3. Example Ansible playbook to create an XFS file system on a block device This section provides an example Ansible playbook. This playbook applies the storage role to create an XFS file system on a block device using the default parameters. Warning The storage role can create a file system only on an unpartitioned, whole disk or a logical volume (LV). It cannot create the file system on a partition. Example 20.1. A playbook that creates XFS on /dev/sdb The volume name ( barefs in the example) is currently arbitrary. The storage role identifies the volume by the disk device listed under the disks: attribute. You can omit the fs_type: xfs line because XFS is the default file system in RHEL 8. To create the file system on an LV, provide the LVM setup under the disks: attribute, including the enclosing volume group. For details, see Example Ansible playbook to manage logical volumes . Do not provide the path to the LV device. Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.4. Example Ansible playbook to persistently mount a file system This section provides an example Ansible playbook. This playbook applies the storage role to immediately and persistently mount an XFS file system. Example 20.2. A playbook that mounts a file system on /dev/sdb to /mnt/data This playbook adds the file system to the /etc/fstab file, and mounts the file system immediately. If the file system on the /dev/sdb device or the mount point directory do not exist, the playbook creates them. Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.5. Example Ansible playbook to manage logical volumes This section provides an example Ansible playbook. This playbook applies the storage role to create an LVM logical volume in a volume group. Example 20.3. A playbook that creates a mylv logical volume in the myvg volume group The myvg volume group consists of the following disks: /dev/sda /dev/sdb /dev/sdc If the myvg volume group already exists, the playbook adds the logical volume to the volume group. If the myvg volume group does not exist, the playbook creates it. The playbook creates an Ext4 file system on the mylv logical volume, and persistently mounts the file system at /mnt . Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.6. Example Ansible playbook to enable online block discard This section provides an example Ansible playbook. This playbook applies the storage role to mount an XFS file system with online block discard enabled. Example 20.4. A playbook that enables online block discard on /mnt/data/ Additional resources Example Ansible playbook to persistently mount a file system The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.7. Example Ansible playbook to create and mount an Ext4 file system This section provides an example Ansible playbook. This playbook applies the storage role to create and mount an Ext4 file system. Example 20.5. A playbook that creates Ext4 on /dev/sdb and mounts it at /mnt/data The playbook creates the file system on the /dev/sdb disk. The playbook persistently mounts the file system at the /mnt/data directory. The label of the file system is label-name . Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.8. Example Ansible playbook to create and mount an ext3 file system This section provides an example Ansible playbook. This playbook applies the storage role to create and mount an Ext3 file system. Example 20.6. A playbook that creates Ext3 on /dev/sdb and mounts it at /mnt/data The playbook creates the file system on the /dev/sdb disk. The playbook persistently mounts the file system at the /mnt/data directory. The label of the file system is label-name . Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.9. Example Ansible playbook to resize an existing Ext4 or Ext3 file system using the storage RHEL System Role This section provides an example Ansible playbook. This playbook applies the storage role to resize an existing Ext4 or Ext3 file system on a block device. Example 20.7. A playbook that set up a single volume on a disk If the volume in the example already exists, to resize the volume, you need to run the same playbook, just with a different value for the parameter size . For example: Example 20.8. A playbook that resizes ext4 on /dev/sdb The volume name (barefs in the example) is currently arbitrary. The Storage role identifies the volume by the disk device listed under the disks: attribute. Note Using the Resizing action in other file systems can destroy the data on the device you are working on. Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.10. Example Ansible playbook to resize an existing file system on LVM using the storage RHEL System Role This section provides an example Ansible playbook. This playbook applies the storage RHEL System Role to resize an LVM logical volume with a file system. Warning Using the Resizing action in other file systems can destroy the data on the device you are working on. Example 20.9. A playbook that resizes existing mylv1 and myvl2 logical volumes in the myvg volume group This playbook resizes the following existing file systems: The Ext4 file system on the mylv1 volume, which is mounted at /opt/mount1 , resizes to 10 GiB. The Ext4 file system on the mylv2 volume, which is mounted at /opt/mount2 , resizes to 50 GiB. Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.11. Example Ansible playbook to create a swap volume using the storage RHEL System Role This section provides an example Ansible playbook. This playbook applies the storage role to create a swap volume, if it does not exist, or to modify the swap volume, if it already exist, on a block device using the default parameters. Example 20.10. A playbook that creates or modify an existing XFS on /dev/sdb The volume name ( swap_fs in the example) is currently arbitrary. The storage role identifies the volume by the disk device listed under the disks: attribute. Additional resources The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.12. Configuring a RAID volume using the storage System Role With the storage System Role, you can configure a RAID volume on RHEL using Red Hat Ansible Automation Platform and Ansible-Core. Create an Ansible playbook with the parameters to configure a RAID volume to suit your requirements. Prerequisites The Ansible Core package is installed on the control machine. You have the rhel-system-roles package installed on the system from which you want to run the playbook. You have an inventory file detailing the systems on which you want to deploy a RAID volume using the storage System Role. Procedure Create a new playbook.yml file with the following content: --- - name: Configure the storage hosts: managed-node-01.example.com tasks: - name: Create a RAID on sdd, sde, sdf, and sdg include_role: name: rhel-system-roles.storage vars: storage_safe_mode: false storage_volumes: - name: data type: raid disks: [sdd, sde, sdf, sdg] raid_level: raid0 raid_chunk_size: 32 KiB mount_point: /mnt/data state: present Warning Device names might change in certain circumstances, for example, when you add a new disk to a system. Therefore, to prevent data loss, do not use specific disk names in the playbook. Optional: Verify the playbook syntax: Run the playbook: Additional resources Managing RAID The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file Preparing a control node and managed nodes to use RHEL System Roles . 20.13. Configuring an LVM pool with RAID using the storage RHEL System Role With the storage System Role, you can configure an LVM pool with RAID on RHEL using Red Hat Ansible Automation Platform. In this section you will learn how to set up an Ansible playbook with the available parameters to configure an LVM pool with RAID. Prerequisites The Ansible Core package is installed on the control machine. You have the rhel-system-roles package installed on the system from which you want to run the playbook. You have an inventory file detailing the systems on which you want to configure an LVM pool with RAID using the storage System Role. Procedure Create a new playbook.yml file with the following content: - hosts: all vars: storage_safe_mode: false storage_pools: - name: my_pool type: lvm disks: [sdh, sdi] raid_level: raid1 volumes: - name: my_pool size: "1 GiB" mount_point: "/mnt/app/shared" fs_type: xfs state: present roles: - name: rhel-system-roles.storage Note To create an LVM pool with RAID, you must specify the RAID type using the raid_level parameter. Optional. Verify playbook syntax. Run the playbook on your inventory file: Additional resources Managing RAID . The /usr/share/ansible/roles/rhel-system-roles.storage/README.md file. 20.14. Example Ansible playbook to compress and deduplicate a VDO volume on LVM using the storage RHEL System Role This section provides an example Ansible playbook. This playbook applies the storage RHEL System Role to enable compression and deduplication of Logical Volumes (LVM) using Virtual Data Optimizer (VDO). Example 20.11. A playbook that creates a mylv1 LVM VDO volume in the myvg volume group In this example, the compression and deduplication pools are set to true, which specifies that the VDO is used. The following describes the usage of these parameters: The deduplication is used to deduplicate the duplicated data stored on the storage volume. The compression is used to compress the data stored on the storage volume, which results in more storage capacity. The vdo_pool_size specifies the actual size the volume takes on the device. The virtual size of VDO volume is set by the size parameter. NOTE: Because of the Storage role use of LVM VDO, only one volume per pool can use the compression and deduplication. 20.15. Creating a LUKS2 encrypted volume using the storage RHEL System Role You can use the storage role to create and configure a volume encrypted with LUKS by running an Ansible playbook. Prerequisites Access and permissions to one or more managed nodes, which are systems you want to configure with the crypto_policies System Role. An inventory file, which lists the managed nodes. Access and permissions to a control node, which is a system from which Red Hat Ansible Core configures other systems. On the control node, the ansible-core and rhel-system-roles packages are installed. Important RHEL 8.0-8.5 provided access to a separate Ansible repository that contains Ansible Engine 2.9 for automation based on Ansible. Ansible Engine contains command-line utilities such as ansible , ansible-playbook , connectors such as docker and podman , and many plugins and modules. For information about how to obtain and install Ansible Engine, see the How to download and install Red Hat Ansible Engine Knowledgebase article. RHEL 8.6 and 9.0 have introduced Ansible Core (provided as the ansible-core package), which contains the Ansible command-line utilities, commands, and a small set of built-in Ansible plugins. RHEL provides this package through the AppStream repository, and it has a limited scope of support. For more information, see the Scope of support for the Ansible Core package included in the RHEL 9 and RHEL 8.6 and later AppStream repositories Knowledgebase article. Procedure Create a new playbook.yml file with the following content: You can also add the other encryption parameters such as encryption_key , encryption_cipher , encryption_key_size , and encryption_luks version in the playbook.yml file. Optional: Verify playbook syntax: Run the playbook on your inventory file: Verification View the encryption status: Verify the created LUKS encrypted volume: View the cryptsetup parameters in the playbook.yml file, which the storage role supports: Additional resources Encrypting block devices using LUKS /usr/share/ansible/roles/rhel-system-roles.storage/README.md file 20.16. Example Ansible playbook to express pool volume sizes as percentage using the storage RHEL System Role This section provides an example Ansible playbook. This playbook applies the storage System Role to enable you to express Logical Manager Volumes (LVM) volume sizes as a percentage of the pool's total size. Example 20.12. A playbook that express volume sizes as a percentage of the pool's total size This example specifies the size of LVM volumes as a percentage of the pool size, for example: "60%". Additionally, you can also specify the size of LVM volumes as a percentage of the pool size in a human-readable size of the file system, for example, "10g" or "50 GiB". 20.17. Additional resources /usr/share/doc/rhel-system-roles/storage/ /usr/share/ansible/roles/rhel-system-roles.storage/

Commands:
--- - hosts: all vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: xfs roles: - rhel-system-roles.storage
--- - hosts: all vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: xfs mount_point: /mnt/data roles: - rhel-system-roles.storage
- hosts: all vars: storage_pools: - name: myvg disks: - sda - sdb - sdc volumes: - name: mylv size: 2G fs_type: ext4 mount_point: /mnt/data roles: - rhel-system-roles.storage
--- - hosts: all vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: xfs mount_point: /mnt/data mount_options: discard roles: - rhel-system-roles.storage
--- - hosts: all vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: ext4 fs_label: label-name mount_point: /mnt/data roles: - rhel-system-roles.storage
--- - hosts: all vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: ext3 fs_label: label-name mount_point: /mnt/data roles: - rhel-system-roles.storage
--- - name: Create a disk device mounted on /opt/barefs - hosts: all vars: storage_volumes: - name: barefs type: disk disks: - /dev/sdb size: 12 GiB fs_type: ext4 mount_point: /opt/barefs roles: - rhel-system-roles.storage
--- - name: Create a disk device mounted on /opt/barefs - hosts: all vars: storage_volumes: - name: barefs type: disk disks: - /dev/sdb size: 10 GiB fs_type: ext4 mount_point: /opt/barefs roles: - rhel-system-roles.storage
--- - hosts: all vars: storage_pools: - name: myvg disks: - /dev/sda - /dev/sdb - /dev/sdc volumes: - name: mylv1 size: 10 GiB fs_type: ext4 mount_point: /opt/mount1 - name: mylv2 size: 50 GiB fs_type: ext4 mount_point: /opt/mount2 - name: Create LVM pool over three disks include_role: name: rhel-system-roles.storage
--- - name: Create a disk device with swap - hosts: all vars: storage_volumes: - name: swap_fs type: disk disks: - /dev/sdb size: 15 GiB fs_type: swap roles: - rhel-system-roles.storage
--- - name: Configure the storage hosts: managed-node-01.example.com tasks: - name: Create a RAID on sdd, sde, sdf, and sdg include_role: name: rhel-system-roles.storage vars: storage_safe_mode: false storage_volumes: - name: data type: raid disks: [sdd, sde, sdf, sdg] raid_level: raid0 raid_chunk_size: 32 KiB mount_point: /mnt/data state: present
ansible-playbook --syntax-check playbook.yml
ansible-playbook -i inventory.file /path/to/file/playbook.yml
- hosts: all vars: storage_safe_mode: false storage_pools: - name: my_pool type: lvm disks: [sdh, sdi] raid_level: raid1 volumes: - name: my_pool size: "1 GiB" mount_point: "/mnt/app/shared" fs_type: xfs state: present roles: - name: rhel-system-roles.storage
ansible-playbook --syntax-check playbook.yml
ansible-playbook -i inventory.file /path/to/file/playbook.yml
--- - name: Create LVM VDO volume under volume group 'myvg' hosts: all roles: -rhel-system-roles.storage vars: storage_pools: - name: myvg disks: - /dev/sdb volumes: - name: mylv1 compression: true deduplication: true vdo_pool_size: 10 GiB size: 30 GiB mount_point: /mnt/app/shared
- hosts: all vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: xfs fs_label: label-name mount_point: /mnt/data encryption: true encryption_password: your-password roles: - rhel-system-roles.storage
ansible-playbook --syntax-check playbook.yml
ansible-playbook -i inventory.file /path/to/file/playbook.yml
cryptsetup status sdb /dev/mapper/ sdb is active and is in use. type: LUKS2 cipher: aes-xts-plain64 keysize: 512 bits key location: keyring device: /dev/ sdb [...]
cryptsetup luksDump /dev/ sdb Version: 2 Epoch: 6 Metadata area: 16384 [bytes] Keyslots area: 33521664 [bytes] UUID: a4c6be82-7347-4a91-a8ad-9479b72c9426 Label: (no label) Subsystem: (no subsystem) Flags: allow-discards Data segments: 0: crypt offset: 33554432 [bytes] length: (whole device) cipher: aes-xts-plain64 sector: 4096 [bytes] [...]
cat ~/playbook.yml - hosts: all vars: storage_volumes: - name: foo type: disk disks: - nvme0n1 fs_type: xfs fs_label: label-name mount_point: /mnt/data encryption: true #encryption_password: passwdpasswd encryption_key: /home/passwd_key encryption_cipher: aes-xts-plain64 encryption_key_size: 512 encryption_luks_version: luks2 roles: - rhel-system-roles.storage
--- - name: Express volume sizes as a percentage of the pool's total size hosts: all roles - rhel-system-roles.storage vars: storage_pools: - name: myvg disks: - /dev/sdb volumes: - name: data size: 60% mount_point: /opt/mount/data - name: web size: 30% mount_point: /opt/mount/web - name: cache size: 10% mount_point: /opt/cache/mount