Utilizing Ansible looping thru fact_diff results

378 Views Asked by At

I am building a vCenter cluster using Ansible, as part of that I need to be able to find a new drive and add it as a datastore. The basic process I am following is:

  • get the ESXi facts ( community.vmware.vmware_host_disk_info
  • add the drive(s. Could be multiple.
  • scan the esxi storage (community.vmware.vmware_host_scanhba )
  • regather the esxi host facts.

I then use the fact_diff to get the difference and at that point I want to add the new drive. I have not included the esxi and rescan code, as it's kinda moot.

  - name: Show the difference between before and after rescan
    ansible.utils.fact_diff:
      before: "{{ host_facts_before|ansible.utils.to_paths }}"
      after: "{{ host_facts_after|ansible.utils.to_paths }}"
    register: disk_diff
  - debug:
     msg: "{{ disk_diff.diff_lines }}"

The output of this is pretty much a git style output.

--- before
+++ after
@@ -63,5 +63,12 @@
     "hosts_disk_info['10.10.20.137'][8].device_path": "/vmfs/devices/disks/naa.6000c29a016671a1ef4a4b5fc01703a0",
     "hosts_disk_info['10.10.20.137'][8].device_type": "disk",
     "hosts_disk_info['10.10.20.137'][8].disk_uid": "key-vim.host.ScsiDisk-02000000006000c29a016671a1ef4a4b5fc01703a0566972747561",
-    "hosts_disk_info['10.10.20.137'][8].display_name": "Local VMware Disk (naa.6000c29a016671a1ef4a4b5fc01703a0)"
+    "hosts_disk_info['10.10.20.137'][8].display_name": "Local VMware Disk (naa.6000c29a016671a1ef4a4b5fc01703a0)",
+    "hosts_disk_info['10.10.20.137'][9].canonical_name": "naa.6000c293214d38d992261b1d830f30d8",
+    "hosts_disk_info['10.10.20.137'][9].capacity_mb": 40960,
+    "hosts_disk_info['10.10.20.137'][9].device_ctd_list[0]": "vmhba0:C0:T8:L0",
+    "hosts_disk_info['10.10.20.137'][9].device_path": "/vmfs/devices/disks/naa.6000c293214d38d992261b1d830f30d8",
+    "hosts_disk_info['10.10.20.137'][9].device_type": "disk",
+    "hosts_disk_info['10.10.20.137'][9].disk_uid": "key-vim.host.ScsiDisk-02000000006000c293214d38d992261b1d830f30d8566972747561",
+    "hosts_disk_info['10.10.20.137'][9].display_name": "Local VMware Disk (naa.6000c293214d38d992261b1d830f30d8)"
 }

changed: [localhost]

TASK [debug] ************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "--- before",
        "+++ after",
        "@@ -63,5 +63,12 @@",
        "     \"hosts_disk_info['10.10.20.137'][8].device_path\": \"/vmfs/devices/disks/naa.6000c29a016671a1ef4a4b5fc01703a0\",",
        "     \"hosts_disk_info['10.10.20.137'][8].device_type\": \"disk\",",
        "     \"hosts_disk_info['10.10.20.137'][8].disk_uid\": \"key-vim.host.ScsiDisk-02000000006000c29a016671a1ef4a4b5fc01703a0566972747561\",",
        "-    \"hosts_disk_info['10.10.20.137'][8].display_name\": \"Local VMware Disk (naa.6000c29a016671a1ef4a4b5fc01703a0)\"",
        "+    \"hosts_disk_info['10.10.20.137'][8].display_name\": \"Local VMware Disk (naa.6000c29a016671a1ef4a4b5fc01703a0)\",",
        "+    \"hosts_disk_info['10.10.20.137'][9].canonical_name\": \"naa.6000c293214d38d992261b1d830f30d8\",",
        "+    \"hosts_disk_info['10.10.20.137'][9].capacity_mb\": 40960,",
        "+    \"hosts_disk_info['10.10.20.137'][9].device_ctd_list[0]\": \"vmhba0:C0:T8:L0\",",
        "+    \"hosts_disk_info['10.10.20.137'][9].device_path\": \"/vmfs/devices/disks/naa.6000c293214d38d992261b1d830f30d8\",",
        "+    \"hosts_disk_info['10.10.20.137'][9].device_type\": \"disk\",",
        "+    \"hosts_disk_info['10.10.20.137'][9].disk_uid\": \"key-vim.host.ScsiDisk-02000000006000c293214d38d992261b1d830f30d8566972747561\",",
        "+    \"hosts_disk_info['10.10.20.137'][9].display_name\": \"Local VMware Disk (naa.6000c293214d38d992261b1d830f30d8)\"",
        " }",
        ""
    ]
}

The question is - how do I take the results above and use to mount any new drives as datastores. The only piece of data I need is the canonical name and thinking of using the "[9]" as part of the name (e.g ds_9 )

  - name: Mount VMFS datastores to ESXi
    vars:
      ansible_python_interpreter: /usr/bin/python3
    community.vmware.vmware_host_datastore:
      validate_certs: no
      hostname: '{{ vcenter_hostname_pod }}'
      username: '{{ vcenter_username_pod }}'
      password: '{{ vcenter_password_pod }}'
      datastore_name: " {{ 'test_' + something??? }}"
      datastore_type: 'vmfs'
      vmfs_device_name: " {{ canonical_name }} "
      vmfs_version: 6
      esxi_hostname: '{{ esxi_hostname }}'
      state: present
    register: mount
  - debug:
      msg: "{{ mount }}"
1

There are 1 best solutions below

0
On

If I understand this right, then after adding a new disk, it will show up as a new key in hosts_disk_info['10.10.20.137'], ie. the 9 key in your above example.

You can use the difference filter on 2 lists to get the elements that exist in the first list and don't exist in second list. If we apply that on the list of keys representing the disks after/before:

{{ host_facts_after['hosts_disk_info']['10.10.20.137'].keys() | difference(host_facts_before['hosts_disk_info']['10.10.20.137'].keys()) }}

This should, using the data from your example, return [9]

Then you can loop over this resulting list running your mount

  ...
  community.vmware.vmware_host_datastore:
    ...
    datastore_name: "{{ 'ds_' + item | string }}"
    vmfs_device_name: "{{ host_facts_after['hosts_disk_info']['10.10.20.137'][item].canonical_name }}"
    ...
  loop: "{{ host_facts_after['hosts_disk_info']['10.10.20.137'].keys() | difference(host_facts_before['hosts_disk_info']['10.10.20.137'].keys()) }}"

Obviously, you don't want to hardcode the hostname/IP but you get the idea.