1

I created a role to create LVM VG(s) and to make it fully idempotent and fault proof i want to verify that the PV(s) exist and that the VG is not already defined.

roles/lvm/vars/main.yml

---
lvm_vgs:
  - vg_name: drbdpool
    vg_pvs: "{{ vg_drbdpool_pvs }}"

host_vars/hostname

---
vg_drbdpool_pvs: ['sdc1', 'sdd1']

roles/lvm/tasks/main.yml

- name: Create LVM VG(s)
  lvg:
    vg: "{{ item.vg_name }}"
    pvs: "{% for disk in item.vg_pvs %}/dev/{{ disk }}{% if not loop.last %},{% endif %}{% endfor %}"
    state: present
  when:
    - item.vg_name not in ansible_lvm.vgs
    - "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}"
  with_items: "{{ lvm_vgs }}"

To achieve this i added the condition "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}" but it doesn't work and i always get the following error:

TASK [lvm : Create LVM VG(s)] **************************************************
fatal: [hostname]: FAILED! => {"failed": true, "msg": "The conditional check '{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}' failed. The error was: unexpected '.'\n line 1\n\nThe error appears to have been in '/etc/ansible/roles/lvm/tasks/main.yml': line 80, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Create LVM VG(s)\n ^ here\n"}

How can I verify that the PVs (partitions) exist?

techraf
  • 64,883
  • 27
  • 193
  • 198
teissler
  • 113
  • 1
  • 3
  • 9

2 Answers2

0

Ansible assumes the argument of when is a bare Jinja2 expression (it implicitly adds {{ }} braces around), so you cannot use a statement {% ... %} inside.

A workaround is to define a variable in the task and use the variable name as the condition:

- name: Create LVM VG(s)
  lvg:
    vg: "{{ item.vg_name }}"
    pvs: "{% for disk in item.vg_pvs %}/dev/{{ disk }}{% if not loop.last %},{% endif %}{% endfor %}"
    state: present
  when:
    - item.vg_name not in ansible_lvm.vgs
    - partition_exists
  with_items: "{{ lvm_vgs }}"
  vars:
    partition_exists: "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}"

I have no way to test your actual condition, so I leave it intact.

techraf
  • 64,883
  • 27
  • 193
  • 198
0

techraf's answer brought me to the solution.

- name: Create LVM VG(s)
  lvg:
    vg: "{{ item.vg_name }}"
    pvs: "{% for disk in item.vg_pvs %}/dev/{{ disk }}{% if not loop.last %},{% endif %}{% endfor %}"
    state: present
  when:
    - item.vg_name not in ansible_lvm.vgs
    - partition_exists.split(';')
  with_items: "{{ lvm_vgs }}"
  vars:
    partition_exists: "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% if not loop.last %};{% endif %}{% endfor %}"
  tags: ['storage', 'lvm']

As item.vg_pvs may have more than one element, the variable partition_exists needs to be created as list.

teissler
  • 113
  • 1
  • 3
  • 9