Search code examples
linuxansible

How do I get the root device through Ansible?


Depending on what system I run my Ansible against, the root device might be different. On some systems, it's /dev/sda. On others (Raspberry PIs), it's /dev/mmcblk0. I want Ansible to take a look at what device / is mounted on, and figure it out.

If I look at the facts gathered by Ansible's setup module, I see that ansible_mounts is a list, and one of the list items contains mount: /.

Unfortunately:

  1. I'm not sure how to tell Ansible that I'm looking for the list item that contains mount: /
  2. On a Raspberry Pi, that list item shows device: /dev/root
    • Even running df on the system shows /dev/root mounted to /
    • /dev/root doesn't even exist. Apparently it's something left behind by initrd during the boot process

Is there a reliable way to determine exactly what device / is using?


Solution

  • (updated in Ansible 2.16)

    • Use the filter json_query
    root_dev: "{{ ansible_mounts | json_query('[?mount == `/`].device') }}"
    

    gives for example, on Ubuntu

    root_dev:
      - /dev/sda3
    

    This is correct

    shell> df -h
    Filesystem      Size  Used Avail Use% Mounted on
      ...
    /dev/sda3       687G   26G  626G   4% /
      ...
    
    • Optionally, the expression below gives the same result
    root_dev: "{{ ansible_mounts | selectattr('mount', '==', '/')|
                                   map(attribute='device') }}"
    

    The same expressions give correct results also on FreeBSD

    root_dev:
      - /dev/ada0s1a
    
    • CentOS VM
    root_dev:
      - /dev/mapper/cl-root
    
    • and Raspberry Pi
    shell> ssh admin@rp2 uname -a
    FreeBSD rp2.example.org 13.2-RELEASE FreeBSD 13.2-RELEASE releng/13.2-n254617-525ecfdad597 RPI-B arm
    
    shell> ssh admin@rp2 df
    Filesystem             1K-blocks    Used   Avail Capacity  Mounted on
    /dev/ufs/rootfs          7448796 2673624 4179272    39%    /
    devfs                          1       1       0   100%    /dev
    /dev/msdosfs/MSDOSBOOT     51140   14132   37008    28%    /boot/msdos
    tmpfs                     360036       8  360028     0%    /tmp
    
      root_dev:
      - /dev/ufs/rootfs
    

    Example of a complete playbook for testing

    - hosts: all
      
      vars:
    
        root_dev1: "{{ ansible_mounts | json_query('[?mount == `/`].device') }}"
        root_dev2: "{{ ansible_mounts | selectattr('mount', '==', '/') |
                                        map(attribute='device') }}"
    
      tasks:
    
        - setup:
            gather_subset: mounts
    
        - debug:
            var: root_dev1
        - debug:
            var: root_dev2