Friday, April 17, 2026

Automating Dynamic Disk Detection and LVM Setup Using Ansible | Anisle Automation Platform

 In modern infrastructure environments, storage requirements are dynamic—new disks are frequently added to systems, especially in cloud and virtualized environments. Manually detecting, configuring, and mounting these disks is time-consuming and error-prone.

This blog walks through an automated approach using Ansible to dynamically detect new disks and configure them with Logical Volume Manager (LVM)—end-to-end, without manual intervention.


Why Automate Disk Provisioning?

Traditionally, storage provisioning involves multiple manual steps:

  • Identifying unused disks
  • Creating physical volumes (PV)
  • Creating volume groups (VG)
  • Creating logical volumes (LV)
  • Formatting and mounting

Automation helps:

  • Reduce human errors
  • Ensure consistency across systems
  • Speed up provisioning (seconds vs minutes)
  • Enable event-driven infrastructure

Solution Overview

This playbook automates the complete lifecycle:

  1. Detect unpartitioned disks
  2. Filter valid target disks
  3. Install required dependencies
  4. Create LVM structure (PV → VG → LV)
  5. Format filesystem
  6. Mount and persist configuration

Key Components Explained

1. Dynamic Disk Detection

The playbook leverages Ansible facts (ansible_devices) to identify disks with no partitions:

unpartitioned_disks: "{{ ansible_devices | dict2items | selectattr('value.partitions', 'equalto', {}) }}"

This ensures only unused disks are considered.


2. Intelligent Disk Filtering

Not all devices should be used. The playbook excludes:

  • Device mapper entries (dm-*)
  • CD-ROM devices (sr*)
reject('match', '^dm-.*')
reject('match', '^sr.*')

This avoids accidental modification of system-critical or virtual devices.


3. Dependency Installation

Before performing LVM operations, required packages are installed:

  • lvm2 → LVM management
  • xfsprogs → Filesystem tools
  • sg3_utils → SCSI utilities

This ensures the system is ready for storage operations.


4. Safety Check

The playbook includes a fail-safe:

- name: Fail if no suitable empty disk was found

This prevents unintended execution when no valid disk is available.


5. LVM Creation Workflow

The playbook automates:

  • Physical Volume (PV) creation
  • Volume Group (VG) creation
  • Logical Volume (LV) allocation (100% of space)

Using Ansible modules:

  • community.general.lvg
  • community.general.lvol

This ensures idempotent and repeatable execution.


6. Filesystem Creation

A filesystem (default: XFS) is created:

fstype: xfs

XFS is widely used in enterprise Linux environments due to its scalability and performance.


7. Mounting and Persistence

Finally:

  • Mount point is created
  • Filesystem is mounted
  • /etc/fstab is updated automatically

This guarantees persistence across reboots.


End-to-End Workflow Visualization

New Disk → Detect → Filter → Validate
→ Create PV → Create VG → Create LV
→ Format → Mount → Persist

Key Benefits of This Approach

Fully Automated

No manual intervention required after disk attachment.

Idempotent

Safe to run multiple times—no duplicate configurations.

Scalable

Works across hundreds or thousands of servers.

Error-Resilient

Built-in checks prevent misconfiguration.

Standardized

Enforces consistent naming and structure.

Sample playbook

---

- name: Dynamic Disk Detection and LVM Setup

  hosts: all

  become: true

  vars:

    vg_name: "data_vg"

    lv_name: "data_lv"

    mount_path: "/mnt/data"

    fs_type: "xfs"

  tasks:

    - name: Find unpartitioned disks

      set_fact:

        unpartitioned_disks: "{{ ansible_devices | dict2items | selectattr('value.partitions', 'equalto', {}) | map(attribute='key') | list }}"


    - name: Filter for actual physical/virtual disks

      set_fact:

        target_disk: "{{ ansible_devices | dict2items | selectattr('value.partitions', 'equalto', {}) | 

                        map(attribute='key') | list |

                        reject('match', '^dm-.*') | 

                        reject('match', '^sr.*') | 

                        list }}"

        

    - name: Show the real new disk

      debug:

        msg: "The actual new disk is: /dev/{{ target_disk | first }}"

      

    - name: Install required packages for LVM and filesystem management

      ansible.builtin.package:

        name:

          - lvm2

          - xfsprogs

          - sg3_utils

        state: present


    - name: Fail if no suitable empty disk was found

      ansible.builtin.fail:

        msg: "No unpartitioned disks found on the system."

      when: target_disk is not defined


    - name: Create Physical Volume and Volume Group

      community.general.lvg:

        vg: "{{ vg_name }}"

        pvs: "/dev/{{ target_disk | first }}"

        state: present


    - name: Create Logical Volume (100% of VG space)

      community.general.lvol:

        vg: "{{ vg_name }}"

        lv: "{{ lv_name }}"

        size: 100%FREE

        state: present


    - name: Create Filesystem on Logical Volume

      community.general.filesystem:

        fstype: "{{ fs_type }}"

        dev: "/dev/{{ vg_name }}/{{ lv_name }}"


    - name: Ensure Mount Directory exists

      ansible.builtin.file:

        path: "{{ mount_path }}"

        state: directory

        mode: '0755'


    - name: Mount the volume and update fstab

      ansible.builtin.mount:

        path: "{{ mount_path }}"

        src: "/dev/{{ vg_name }}/{{ lv_name }}"

        fstype: "{{ fs_type }}"

        state: mounted

No comments:

Post a Comment