'Ansible - Create Dynamic Inventory for ESXi Hosts via vCenter API

I had an ask to create a dynamic inventory of ESXi Hosts for each Cluster and I achieved that using the 'community.vmware.vmware_cluster_info' and doing some magic around extracting json values from register var in a playbook. I thought of sharing this with the community just in case anyone has got a similar task on hand.

FYI - There is an Ansible module for dynamic inventory but that is for VM's and NOT for ESXi Hosts inventory.

Step 1 - This is to get the Cluster info from vCenter and store/register the output in "cluster_info"

- name: Gather info about the cluster 
  community.vmware.vmware_cluster_info:
    hostname: "{{ vcenter_hostname }}"
    username: "{{ vcenter_username }}"
    password: "{{ vcenter_password)}}"
    cluster_name: "Cluster-Name"
    validate_certs: no
  delegate_to: localhost
  register: cluster_info

Step 2 - This is to filter out the ESXi Hosts value and store it as a 'fact' in cluster_hosts. We are using register value 'cluster_info' (from step 1) with dict to filter out the required info.

- name: Generate Dynamic Inventory for Cluster 
  set_fact:
    cluster_hosts: "{{ item.value.hosts | map(attribute='name') | list | sort }}"
  with_dict: "{{ cluster_info.clusters }}"
  loop_control:
    label: '{{ item.key }}'
  tags:
    - dynamic_inventory

Step 3 - Now we are using the list generated from Step 2 and looping it and creating a Host group (using 'add_host' module) containing those hosts that can be used for next task/playbook.

- name: Dynamic Inventory Group created
  add_host:
    hostname: "{{ item }}"
    groups: esxi_dynamic_inventory
  loop: "{{ cluster_hosts }}"
  tags:
    - dynamic_inventory

Any questions feel free to ask.



Solution 1:[1]

I faced the same situation a few years ago.

What I did is take the source code from Ansible for one of the vmware modules and write a module that returned the host list.

You can take any vmware module from Ansible (like https://github.com/ansible-collections/community.vmware/blob/98fb3fe441de096778a0bf4b5ba9c3d146c47f72/plugins/modules/vmware_guest_find.py) and adapt it with the following code.

It is a custom module, so you should place it somewhere in the library directory of the role or collection you are writing.

class PyVmomiHelper(PyVmomi):
    def __init__(self,module):
        super(PyVmomiHelper, self).__init__(module)
        cluster = self.params['cluster_name']
        self.host_obj_list = self.get_all_host_objs(cluster_name=cluster)

    def get_host_obj_list(self):
        results = dict(changed=False, result=dict())
        host_list = []
        for host in self.host_obj_list:
            host_list.append(host.name)
        results['result']["host_list"] = host_list
        self.module.exit_json(**results)

def main():
    argument_spec = vmware_argument_spec()
    argument_spec.update(dict(
        cluster_name=dict(type='str')
    ))

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=False,
                           required_one_of=[
                               ['cluster_name']
                           ])

    try:
        pyv = PyVmomiHelper(module)
        pyv.get_host_obj_list()
    except vmodl.RuntimeFault as runtime_fault:
        module.fail_json(msg=to_native(runtime_fault.msg))
    except vmodl.MethodFault as method_fault:
        module.fail_json(msg=to_native(method_fault.msg))
    except Exception as e:
        module.fail_json(msg=to_native(e))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jordi Molina