[Ansible] how to iterate over nested dictionary variable with the loop filter for a cartesian product to create disks in LVM?
[Ansible] how to iterate over nested dictionary variable with the loop filter for a cartesian product to create disks in LVM?
Hi guys,
I have the following variable in Ansible:
additional_lvm_disks:
persistent:
device: xvdb
part: 1
crypt: yes
logical_volumes:
persistent_data:
size: 100%VG
mount: /data
volatile_hdd:
device: xvdc
part: 1
crypt: yes
logical_volumes:
var_cache:
size: 50%VG
mount: /var/cache
var_log:
size: 50%VG
mount: /var/log
volatile_ssd:
device: xvde
part: 1
crypt: yes
logical_volumes:
tmp:
size: 30%VG
mount: /tmp
volatile_data:
size: 70%VG
mount: /media/volatile_data
Now I want to iterate over this structure and create encrypted disks with an LVM on top. I named the PVs according to the keys, so I came up with this (which, obviously, does not work properly):
- name: Install parted
apt:
name: [ 'parted' ]
state: present
- name: Install lvm2 dependency
package:
name: lvm2
state: present
- name: list the devices and mounts being specified
debug:
msg: "{{ item.device }} - {{ item.mount }}"
with_items: "{{ var_devices_mounts }}"
- name: Check if devices exist
fail:
msg: "device {{ item.value.device }} does not exist or is corrupted }} "
when: ansible_facts['devices'][item.value.device]['size'] | length == 0
loop: "{{ lookup('dict', additional_lvm_disks) }}"
- name: Check Secret File Creation
command: sh -c "dd if=/dev/urandom of={{ var_keyfile_path }} bs=1024 count=4"
args:
chdir: "{{ var_keyfile_dir }}"
creates: "{{ var_keyfile_path }}"
- name: Check Secret File Permissions
file:
state: file
path: "{{ var_keyfile_path }}"
owner: root
group: root
mode: "0400"
- name: Create Partition
parted:
device: "/dev/{{ item.value.device }}"
number: 1
flags: [ lvm ]
state: present
loop: "{{ lookup('dict', additional_lvm_disks) }}"
- name: Create LUKS container with a passphrase
luks_device:
device: "/dev/{{ item.value.device }}1"
state: "present"
passphrase: "123456789"
loop: "{{ lookup('dict', additional_lvm_disks) }}"
- name: Add keyfile to the LUKS container
luks_device:
device: "/dev/{{ item.value.device }}1"
new_keyfile: "{{ var_keyfile_path }}"
passphrase: "123456789"
loop: "{{ lookup('dict', additional_lvm_disks) }}"
- name: (Create and) open LUKS container
luks_device:
device: "/dev/{{ item.value.device }}1"
state: "opened"
name: "{{ item.value.device }}1_crypt"
keyfile: "{{ var_keyfile_path }}"
loop: "{{ lookup('dict', additional_lvm_disks) }}"
- name: Set the options explicitly a device which must already exist
crypttab:
name: "{{ item.value.device }}1_crypt"
backing_device: "/dev/{{ item.value.device }}1"
state: present
password: "{{ var_keyfile_path }}"
opts: luks
loop: "{{ lookup('dict', additional_lvm_disks) }}"
- name: Creating Volume Group
lvg:
vg: "{{ item.key }}"
pvs: "/dev/mapper/{{ item.value.device }}1_crypt"
loop: "{{ lookup('dict', additional_lvm_disks) }}"
- name: Creating Logical Volume
lvol:
vg: "{{ item.value.volume_group }}"
lv: "{{ item.key }}"
size: 100%VG
loop: "{{ lookup('dict', (additional_lvm_disks | dict2items | combine(recursive=True, list_merge='append')).value.logical_volumes) }}"
- name: create directorie(s)
file:
path: "{{ item.value.mount }}"
state: directory
loop: "{{ lookup('dict', (additional_lvm_disks | dict2items | combine(recursive=True, list_merge='append')).value.logical_volumes) }}"
- name: format the ext4 filesystem
filesystem:
fstype: ext4
dev: "/dev/{{ item.value.volume_group }}/{{ item.key }}"
loop: "{{ lookup('dict', (additional_lvm_disks | dict2items | combine(recursive=True, list_merge='append')).value.logical_volumes) }}"
- name: mount the lv
mount:
path: "{{ item.value.mount }}"
src: "/dev/{{ item.value.volume_group }}/{{ item.key }}"
fstype: ext4
state: mounted
loop: "{{ lookup('dict', (additional_lvm_disks | dict2items | combine(recursive=True, list_merge='append')).value.logical_volumes) }}"
I found that I probably need the product filter for a loop to create a cartesian product of all the volume groups and their disks as well as all the logical volumes and their volume groups, the latter looking something like this:
- { volume_group: volatile_hdd, logical_volume: var_cache, size: 50%VG }
- { volume_group: volatile_hdd, logical_volume: var_log, size: 50%VG }
Sadly I can't wrap my head around this and there are no good tutorials or examples I could find.
How do I iterate over the "monster dictionary" above to get what I want?