Ansible

How to Use Ansible to Manage VMware Infrastructure

In this article I will show how to install and configure Ansible to manage VMware infrastructure. I will then demonstrate how you can use Ansible to get information about vSphere nodes using two different methods (REST API and Community.VMware Ansible collection).

For my demonstration I used CentOS Stream 9 as my base OS.

You can download all the code and commands used in this article from my GitHub repository.

Install and Configure Ansible

First we need to install Python3 and then we can proceed to install Ansible:

sudo dnf install python3 python3-devel
pip install ansible
pip install ansible

If we intend to use Community.VMware collection (and we do intend if we want to manage VMware infrastructure) we need to run one more configuration step:

pip install --upgrade git+https://github.com/vmware/vsphere-automation-sdk-python.git 

As a final step, we can run our first Ansible command to check our installation:

ansible --version
ansible --version

Let’s Get Info

We now have a fully functional Ansible installation which we can use to manage our vSphere installation.

Let’s look a moment at my vCenter instance. I have a vCenter 8.0 with two datacenters. In the datacenter “PH”, I have a cluster “PH-cluster” with 2 ESXi hosts: esx0.cloudhat.local and nuc01.cloudhat.local.

Cluster details

Next, I will show two ways to use Ansible to get information about the vSphere nodes from the “PH-cluster” cluster.

The first option is to use REST API calls.

We first define few variables to use later in the playbook (rows 4-6). We then authenticate by performing a REST call to Create session endpoint (rows 9 to 18) – we provide a username and a password and in return we get a token which we will use in subsequent calls. Next call gathers the information returned by List Host endpoint (rows 20-28). In the end, we print the information received (rows 30-32).

---
- hosts: localhost
  vars:
    - vcenter_hostname: vcenter.cloudhat.local
    - vcenter_username: [email protected]
    - vcenter_password: VMware1!

  tasks:
    - name: Login to the vCenter instance
      uri:
        url: "https://{{ vcenter_hostname }}/api/session"
        force_basic_auth: yes
        method: POST
        user: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        status_code: 201
        validate_certs: no
      register: login

    - name: Gather hosts info using REST API
      uri:
        url: "https://{{ vcenter_hostname }}/api/vcenter/host"
        force_basic_auth: yes
        method: GET
        validate_certs: no
        headers:
          vmware-api-session-id: "{{ login.json }}"
      register: hosts_info

    - name: Print hosts info
      debug:
          var: hosts_info

Save the playbook with a name like get-hosts-info-REST.yml and then we can execute it:

ansible-playbook get-hosts-info-REST.yml

The result I got in my infrastructure (you can notice the data about the 2 ESXi servers I have):

[cloudhat@ansible ansible]$ ansible-playbook get-hosts-info-REST.yml

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

TASK [Gathering Facts] *********************************************************************************************************************
ok: [localhost]

TASK [Login to the vCenter instance] *******************************************************************************************************
ok: [localhost]

TASK [Gather hosts info using REST API] ****************************************************************************************************
ok: [localhost]

TASK [Print hosts info] ********************************************************************************************************************
ok: [localhost] => {
    "hosts_info": {
        "changed": false,
        "connection": "close",
        "content_type": "application/json",
        "cookies": {},
        "cookies_string": "",
        "date": "Sun, 29 Jan 2023 13:47:56 GMT",
        "elapsed": 0,
        "failed": false,
        "json": [
            {
                "connection_state": "CONNECTED",
                "host": "host-1006",
                "name": "nuc01.cloudhat.local",
                "power_state": "POWERED_ON"
            },
            {
                "connection_state": "CONNECTED",
                "host": "host-8",
                "name": "esx0.cloudhat.local",
                "power_state": "POWERED_ON"
            }
        ],
        "msg": "OK (unknown bytes)",
        "redirected": false,
        "status": 200,
        "transfer_encoding": "chunked",
        "url": "https://vcenter.cloudhat.local/api/vcenter/host",
        "x_envoy_upstream_service_time": "215"
    }
}

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

[cloudhat@ansible ansible]$

Let’s move now to the second way of getting the list of ESXi servers, using Community.VMware collection.

This time we will use vmware_cluster_info module from Community.VMware collection. We define the same variables as in the previous playbook (rows 4-6). We then run directly a task to extract the required data (rows 9-16). In the end, we print the information received (rows 18-20).

---
- hosts: localhost
  vars:
    - vcenter_hostname: vcenter.cloudhat.local
    - vcenter_username: [email protected]
    - vcenter_password: VMware1!

  tasks:
    - name: Gather hosts info using Community.VMware collection
      community.vmware.vmware_cluster_info:
        hostname: '{{ vcenter_hostname }}'
        username: '{{ vcenter_username }}'
        password: '{{ vcenter_password }}'
        validate_certs: no
        cluster_name: PH-cluster
      register: cluster_info

    - name: Print hosts info
      debug:
          var: cluster_info

Save the playbook with a name like get-hosts-info.yml and then we can execute it:

ansible-playbook get-hosts-info.yml

Let’s check the results from my infrastructure. Different set of data (more details than in the REST API call), but the vSphere nodes are there as well:

[cloudhat@ansible ansible]$ ansible-playbook get-hosts-info.yml

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

TASK [Gathering Facts] *********************************************************************************************************************
ok: [localhost]

TASK [Gather hosts info using Community.VMware collection] *********************************************************************************
ok: [localhost]

TASK [Print hosts info] ********************************************************************************************************************
ok: [localhost] => {
    "cluster_info": {
        "changed": false,
        "clusters": {
            "PH-cluster": {
                "datacenter": "PH",
                "drs_default_vm_behavior": "fullyAutomated",
                "drs_enable_vm_behavior_overrides": true,
                "drs_vmotion_rate": 3,
                "enable_ha": false,
                "enabled_drs": false,
                "enabled_vsan": false,
                "ha_admission_control_enabled": true,
                "ha_failover_level": 1,
                "ha_host_monitoring": "enabled",
                "ha_restart_priority": [
                    "medium"
                ],
                "ha_vm_failure_interval": [
                    30
                ],
                "ha_vm_max_failure_window": [
                    -1
                ],
                "ha_vm_max_failures": [
                    3
                ],
                "ha_vm_min_up_time": [
                    120
                ],
                "ha_vm_monitoring": "vmMonitoringDisabled",
                "ha_vm_tools_monitoring": [
                    "vmMonitoringDisabled"
                ],
                "hosts": [
                    {
                        "folder": "/PH/host/PH-cluster",
                        "name": "nuc01.cloudhat.local"
                    },
                    {
                        "folder": "/PH/host/PH-cluster",
                        "name": "esx0.cloudhat.local"
                    }
                ],
                "moid": "domain-c1001",
                "resource_summary": {
                    "cpuCapacityMHz": 22352,
                    "cpuUsedMHz": 837,
                    "memCapacityMB": 40805,
                    "memUsedMB": 27095,
                    "pMemAvailableMB": 0,
                    "pMemCapacityMB": 0,
                    "storageCapacityMB": 1022720,
                    "storageUsedMB": 197791
                },
                "tags": [],
                "vsan_auto_claim_storage": false
            }
        },
        "failed": false
    }
}

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

[cloudhat@ansible ansible]$

I demonstrated two ways to get the list of vSphere hosts using Ansible code. Usually, depending of what you want to accomplish, you will choose one way or the other to manage your VMware infrastructure. As a personal choice, if is there a Community.VMware module which can do the job I will choose it.

Constantin Ghioc

I usually play with vSphere API, Ansible, vRealize Automation, vRealize Orchestrator, and different AWS tools. In my other life I’m a husband and a father, an amateur photographer and a Go enthusiast.

Leave a Reply