j4nvkvc
j4nvkvc

Reputation: 33

Ansible - check if disk is mounted, if not format it

I am looking for help because I have trouble to get this thing done :

---
- name: Check if /data is already mounted
  debug: msg="The mount point exists"
  with_items: "{{ ansible_mounts }}"
  when: item.mount == "/data"
  register: check_mount

- name: Create /data directory if not exists
  ansible.builtin.file:
    path: /data
    state: directory
    owner: root
    group: root
    mode: '0751'

- name: Create a xfs filesystem on /dev/sda5
  community.general.filesystem:
    force: yes
    fstype: xfs
    dev: /dev/sda5
  when: not check_mount

- name: Get the /dev/sda5's UUID
  shell: blkid -s UUID -o value /dev/sda5
  register: blkid_out
  when: not check_mount

- name: Mount up device by UUID
  ansible.posix.mount:
    path: /data
    src: UUID={{ blkid_out.stdout }}
    fstype: xfs
    opts: defaults
    state: mounted

What am I trying to do :

do nothing if mountpoint exist.

The problem I have is I guess my check doesnt do anything but I do not know how to make it right with ansible_mount only and not with stat.

The first run do exactly what I want but I need to be able to run the playbook over and over and it shows me an error after the second run

    TASK [setup_disk : Create a xfs filesystem on /dev/sda5] ***********************************************************************************************************************************************************************************
fatal: [blm-web-160]: FAILED! => {"changed": false, "cmd": "/usr/sbin/mkfs.xfs -f /dev/sda5", "msg": "mkfs.xfs: /dev/sda5 contains a mounted filesystem\nUsage: mkfs.xfs\n/* blocksize */\t\t[-b size=num]\n/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n\t\t\t    (sunit=value,swidth=value|su=num,sw=num|noalign),\n\t\t\t    sectsize=num\n/* force overwrite */\t[-f]\n/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\t\t\t    projid32bit=0|1,sparse=0|1]\n/* no discard */\t[-K]\n/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n\t\t\t    sunit=value|su=num,sectsize=num,lazy-count=0|1]\n/* label */\t\t[-L label (maximum 12 characters)]\n/* naming */\t\t[-n size=num,version=2|ci,ftype=0|1]\n/* no-op info only */\t[-N]\n/* prototype file */\t[-p fname]\n/* quiet */\t\t[-q]\n/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n/* sectorsize */\t[-s size=num]\n/* version */\t\t[-V]\n\t\t\tdevicename\n<devicename> is required unless -d name=xxx is given.\n<num> is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n      xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n<value> is xxx (512 byte blocks).", "rc": 1, "stderr": "mkfs.xfs: /dev/sda5 contains a mounted filesystem\nUsage: mkfs.xfs\n/* blocksize */\t\t[-b size=num]\n/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,\n\t\t\t    (sunit=value,swidth=value|su=num,sw=num|noalign),\n\t\t\t    sectsize=num\n/* force overwrite */\t[-f]\n/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\t\t\t    projid32bit=0|1,sparse=0|1]\n/* no discard */\t[-K]\n/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n\n\t\t\t    sunit=value|su=num,sectsize=num,lazy-count=0|1]\n/* label */\t\t[-L label (maximum 12 characters)]\n/* naming */\t\t[-n size=num,version=2|ci,ftype=0|1]\n/* no-op info only */\t[-N]\n/* prototype file */\t[-p fname]\n/* quiet */\t\t[-q]\n/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]\n/* sectorsize */\t[-s size=num]\n/* version */\t\t[-V]\n\t\t\tdevicename\n<devicename> is required unless -d name=xxx is given.\n<num> is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n      xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n<value> is xxx (512 byte blocks).\n", "stderr_lines": ["mkfs.xfs: /dev/sda5 contains a mounted filesystem", "Usage: mkfs.xfs", "/* blocksize */\t\t[-b size=num]", "/* metadata */\t\t[-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]", "/* data subvol */\t[-d agcount=n,agsize=n,file,name=xxx,size=num,", "\t\t\t    (sunit=value,swidth=value|su=num,sw=num|noalign),", "\t\t\t    sectsize=num", "/* force overwrite */\t[-f]", "/* inode size */\t[-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,", "\t\t\t    projid32bit=0|1,sparse=0|1]", "/* no discard */\t[-K]", "/* log subvol */\t[-l agnum=n,internal,size=num,logdev=xxx,version=n", "\t\t\t    sunit=value|su=num,sectsize=num,lazy-count=0|1]", "/* label */\t\t[-L label (maximum 12 characters)]", "/* naming */\t\t[-n size=num,version=2|ci,ftype=0|1]", "/* no-op info only */\t[-N]", "/* prototype file */\t[-p fname]", "/* quiet */\t\t[-q]", "/* realtime subvol */\t[-r extsize=num,size=num,rtdev=xxx]", "/* sectorsize */\t[-s size=num]", "/* version */\t\t[-V]", "\t\t\tdevicename", "<devicename> is required unless -d name=xxx is given.", "<num> is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),", "      xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).", "<value> is xxx (512 byte blocks)."], "stdout": "", "stdout_lines": []}

surely because it try to format somthing already in use.

It would be appreciated to have some tips from someone :)

Upvotes: 3

Views: 7591

Answers (1)

flowerysong
flowerysong

Reputation: 2899

Ansible modules are generally designed to be idempotent. Instead of doing extra checks to see if the filesystem already exists, you should use declarative tasks and the filesystem and mount modules will do the right thing.

- name: Create /data
  ansible.builtin.file:
    path: /data
    state: directory
    owner: root
    group: root
    mode: '0751'

- name: Create an xfs filesystem on /dev/sda5
  community.general.filesystem:
    fstype: xfs
    state: present
    dev: /dev/sda5

- name: Fetch the UUID of /dev/sda5
  command: blkid -s UUID -o value /dev/sda5
  changed_when: false
  register: blkid_out

- name: Mount /dev/sda5 by UUID
  ansible.posix.mount:
    path: /data
    src: UUID={{ blkid_out.stdout }}
    fstype: xfs
    opts: defaults
    state: mounted

First run:

ec2-user@pandora ~ $ ansible-playbook ~/test.yml

PLAY [localhost] ***************************************************************

TASK [Create /data] ************************************************************
changed: [localhost]

TASK [Create an xfs filesystem on /dev/sda5] ***********************************
changed: [localhost]

TASK [Fetch the UUID of /dev/sda5] *********************************************
ok: [localhost]

TASK [Mount /dev/sda5 by UUID] *************************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Second run:

ec2-user@pandora ~ $ ansible-playbook ~/test.yml

PLAY [localhost] ***************************************************************

TASK [Create /data] ************************************************************
changed: [localhost]

TASK [Create an xfs filesystem on /dev/sda5] ***********************************
ok: [localhost]

TASK [Fetch the UUID of /dev/sda5] *********************************************
ok: [localhost]

TASK [Mount /dev/sda5 by UUID] *************************************************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

If you really need to make it conditional you need to understand what the variables involved look like.

- name: Check if /data is already mounted
  debug: msg="The mount point exists"
  with_items: "{{ ansible_mounts }}"
  when: item.mount == "/data"
  register: check_mount

As you'll see if you debug it, the task result in check_mount contains the results for every loop item, so check_mount itself is always a truthy value. To see whether it ran anything, you need to use when: check_mount is not skipped, not when: check_mount.

However, this is not a good pattern for conditionals, because it requires an extra task with potentially a lot of looping output. It's better to directly check for the condition you want in your when statement.

- when: ansible_facts.mounts | selectattr('mount', '==', '/data') | length == 0
  block:
    - name: Create an xfs filesystem on /dev/sda5
      community.general.filesystem:
        state: present
        fstype: xfs
        dev: /dev/sda5

    - name: Fetch the UUID of /dev/sda5
      command: blkid -s UUID -o value /dev/sda5
      changed_when: false
      register: blkid_out

    - name: Mount /dev/sda5 by UUID
      ansible.posix.mount:
        path: /data
        src: UUID={{ blkid_out.stdout }}
        fstype: xfs
        opts: defaults
        state: mounted

Upvotes: 7

Related Questions