editing pass option in /etc/fstab with ansible

59 Views Asked by At

I have an ansible playbook that runs for about 20 hosts. I'm trying to edit the pass option only for entries that are mounted as root ('/').

Here's what I had that changes every pass option that isn't '0', which I don't want.

- name: Modify mount options in /etc/fstab
  replace:
    path: /etc/fstab
    regexp: '(\b)0 0(\b)'
    replace: '\g<1>0 1\g<2>'
  when: ansible_distribution == 'Ubuntu'

ChatGPT suggests something like this but adding my values doesn't work. All of my filesystems have different naming formats so not all start with UUID.

- name: Change pass option
  lineinfile:
    path: /etc/fstab
    regexp: '^UUID=[a-f0-9-]+\s+/\s'
    line: 'UUID=your_uuid / ext4 defaults,pass=new_pass_option 0 0'
1

There are 1 best solutions below

5
Vladimir Botka On

For example, given the inventory

shell> cat hosts
test_01
test_02
test_03

and the files /tmp/fstab (all the same) for testing

shell> ssh admin@test_01 cat /tmp/fstab
UUID=423d168c-5a90-44f9-94b2-d2da9f0e1e4f /         ext4 errors=remount-ro 0 1
UUID=0F15-7883                            /boot/efi vfat umask=0077        0 1
/swapfile                                 none      swap sw                0 0

shell> ssh admin@test_02 cat /tmp/fstab
UUID=423d168c-5a90-44f9-94b2-d2da9f0e1e4f /         ext4 errors=remount-ro 0 1
UUID=0F15-7883                            /boot/efi vfat umask=0077        0 1
/swapfile                                 none      swap sw                0 0

shell> ssh admin@test_03 cat /tmp/fstab
UUID=423d168c-5a90-44f9-94b2-d2da9f0e1e4f /         ext4 errors=remount-ro 0 1
UUID=0F15-7883                            /boot/efi vfat umask=0077        0 1
/swapfile                                 none      swap sw                0 0
  • Declare the paths
    file_remote: /tmp/fstab
    file_dest: /tmp/ansible/fetch/

and fetch the files to the controller

    - fetch:
        src: "{{ file_remote }}"
        dest: "{{ file_dest }}"

This will create the files at the controller

shell> tree /tmp/ansible/fetch/
/tmp/ansible/fetch/
├── test_01
│   └── tmp
│       └── fstab
├── test_02
│   └── tmp
│       └── fstab
└── test_03
    └── tmp
        └── fstab
  • Parse fstab
    - set_fact:
        file_parsed: "{{ lookup('file', file_dest ~ inventory_hostname ~ file_remote) |
                         community.general.jc('fstab') }}"

gives

ok: [test_01] => 
  file_parsed:
  - fs_file: /
    fs_freq: 0
    fs_mntops: errors=remount-ro,pass=new_pass_option
    fs_passno: 1
    fs_spec: UUID=423d168c-5a90-44f9-94b2-d2da9f0e1e4f
    fs_vfstype: ext4
  - fs_file: /boot/efi
    fs_freq: 0
    fs_mntops: umask=0077
    fs_passno: 1
    fs_spec: UUID=0F15-7883
    fs_vfstype: vfat
  - fs_file: none
    fs_freq: 0
    fs_mntops: sw
    fs_passno: 0
    fs_spec: /swapfile
    fs_vfstype: swap
ok: [test_02] => 
  file_parsed:
  - fs_file: /
    fs_freq: 0
    fs_mntops: errors=remount-ro,pass=new_pass_option
    fs_passno: 1
    fs_spec: UUID=423d168c-5a90-44f9-94b2-d2da9f0e1e4f
    fs_vfstype: ext4
  - fs_file: /boot/efi
    fs_freq: 0
    fs_mntops: umask=0077
    fs_passno: 1
    fs_spec: UUID=0F15-7883
    fs_vfstype: vfat
  - fs_file: none
    fs_freq: 0
    fs_mntops: sw
    fs_passno: 0
    fs_spec: /swapfile
    fs_vfstype: swap
ok: [test_03] => 
  file_parsed:
  - fs_file: /
    fs_freq: 0
    fs_mntops: errors=remount-ro,pass=new_pass_option
    fs_passno: 1
    fs_spec: UUID=423d168c-5a90-44f9-94b2-d2da9f0e1e4f
    fs_vfstype: ext4
  - fs_file: /boot/efi
    fs_freq: 0
    fs_mntops: umask=0077
    fs_passno: 1
    fs_spec: UUID=0F15-7883
    fs_vfstype: vfat
  - fs_file: none
    fs_freq: 0
    fs_mntops: sw
    fs_passno: 0
    fs_spec: /swapfile
    fs_vfstype: swap
  • Use the module ansible.posix.mount to update what you want. For example, to add the option pass=new_pass_option for all / in all files
    - ansible.posix.mount:
        fstab: "{{ file_remote }}"
        path: "{{ my_item.fs_file }}"
        src:  "{{ my_item.fs_spec }}"
        fstype: "{{ my_item.fs_vfstype }}"
#       opts: "{{ my_item.fs_mntops }}"
        opts: "{{ [my_item.fs_mntops|split(','), 'pass=new_pass_option'] |
                  flatten |
                  unique |
                  join(',') }}"
        dump: "{{ my_item.fs_freq }}"
        passno: "{{ my_item.fs_passno }}"
        state: present
      vars:
        fs_file: /
        my_item: "{{ file_parsed |
                     selectattr('fs_file', 'eq', fs_file) |
                     first }}"

This will change the file only. If you want to update the current mount point use state: mounted. See state.


Example of a complete playbook for testing

- hosts: all

  vars:

    file_remote: /tmp/fstab
    file_dest: /tmp/ansible/fetch/
  
  tasks:

    - fetch:
        src: "{{ file_remote }}"
        dest: "{{ file_dest }}"

    - set_fact:
        file_parsed: "{{ lookup('file', file_dest ~ inventory_hostname ~ file_remote) |
                         community.general.jc('fstab') }}"
    - debug:
        var: file_parsed

    - ansible.posix.mount:
        fstab: "{{ file_remote }}"
        path: "{{ my_item.fs_file }}"
        src:  "{{ my_item.fs_spec }}"
        fstype: "{{ my_item.fs_vfstype }}"
#       opts: "{{ my_item.fs_mntops }}"
        opts: "{{ [my_item.fs_mntops|split(','), 'pass=new_pass_option'] |
                  flatten |
                  unique |
                  join(',') }}"
        dump: "{{ my_item.fs_freq }}"
        passno: "{{ my_item.fs_passno }}"
        state: present
      vars:
        fs_file: /
        my_item: "{{ file_parsed |
                     selectattr('fs_file', 'eq', fs_file) |
                     first }}"