Ansible – Manage multi-threading in playbooks

In this post, I will show an example on how to manage multi-threading in an Ansible playbook.

The playbook will perform the following steps:

  • Connect on the Service-Now API. Use the CMDB table and retrieve a server list. This server list will contain some attributes. You will have to adapt with your own value. In this example the Service-Now attributes will be: name, sys_id and snow_iloip.
  • The next step will perform a call to the HP iLO API using the specific Ansible module on each list entries. Each call will be launched as a new thread and will not wait the end to run the next call.
  • The next step will wait all the call have been finished and collecting the step output
  • Finally we display the job output in two different ways
---
- hosts: localhost
  gather_facts: no
  # uncomment if the host where the playbook is run required a proxy to reach the internet
  # vars:
    # proxysettings:
    #     http_proxy: http://10.20.30.40:8008/
    #     https_proxy: http://10.20.30.40:8008/

  tasks:
  - name: Get all server from Service Now CMDB
    # uncomment if the host where the playbook is run required a proxy to reach the internet
    # environment: "{{proxysettings}}"
    uri:
      url: https://yourcustom.service-now.com/cmdb_ci_server.do?JSONv2&sysparm_action=getRecords&sysparm_query=active
      return_content: yes
      headers:
         Content-Type: "application/json"
      user: "snow_username"
      password: "snow_password"
      status_code: 200
      method: GET
    register: exp_output

  - name: Call the HP iLO API using the Ansible module called hpilo_facts. We use the attribute called snow_iloip. Adapt with your own Service Now attribute
    hpilo_facts:
      host: "{{ item.snow_iloip }}"
      login: myilouseraccount
      password: myilopassword
    # 30 seconds is the average time to run this task
    async: 30
    # fire the task and "forget". When used in a loop, you can parallelize the tasks
    poll: 0
    loop: "{{ exp_output.json.records }}"
    loop_control:
      label: "{{ item.name }} {{ item.sys_id }}"
    register: async_loop

  - name: Wait. Collecting data...
    async_status:
      jid: "{{item.ansible_job_id}}"
      mode: status
    ignore_errors: yes
    # number of retries if the ansible job is not finished
    retries: 10
    # delay in seconds between retries
    delay: 5
    loop: "{{async_loop.results}}"
    loop_control:
      label: "{{ item.ansible_job_id }}"
    register: async_loop_jobs
    until: async_loop_jobs.finished
    
  - name: Display Firmware info when it is defined
    debug: 
      msg: "{{ item.ansible_facts.hw_health.firmware_information }}"
    when: item.ansible_facts.hw_health.firmware_information is defined
    loop: "{{ async_loop_jobs.results }}"
    loop_control:
      label: "HP iLO data for {{ item.item.item.name }} (iloip from Snow: {{ item.item.item.snow_iloip }} and serial from iLO: {{ item.ansible_facts.hw_system_serial }})"

  - name: Display all infos when firmware info is not available
    debug: 
      msg: "{{ item.ansible_facts }}"
    when: item.ansible_facts.hw_health.firmware_information is not defined
    loop: "{{ async_loop_jobs.results }}"
    loop_control:
      label: "HP iLO data for {{ item.item.item.name }} (iloip from Snow: {{ item.item.item.snow_iloip }} and serial from iLO: {{ item.ansible_facts.hw_system_serial }})"

Ansible – Manage multi-threading in playbooks

Leave a Reply

Your email address will not be published. Required fields are marked *