2

I'm wrapping my head around something that I'm probably overcomplicating.

I need to check if any of my hosts has ansible_virtualization_type == "openvz"

If this is the case, ALL hosts should execute a specific task.

I'm now trying to set a fact (virt_list) containing a list of hosts with their virtualization_type on localhost:

- name: Set fuse on virtualization OpenVZ
  set_fact: 
    virt_list:
    host: "{{item}}"
    type: "openvz"
  when: hostvars[item].ansible_virtualization_type == "openvz"
  with_items: "{{ groups['all'] }}"
  delegate_to: localhost
  delegate_facts: true

but this doesn't work (both hosts in this play are on openvz):

TASK [roles/testvirt : debug vars ansible_virtualization_type ] ****************************
    ok: [host1] => {
        "ansible_virtualization_type": "openvz"
    }
    ok: [host2] => {
        "ansible_virtualization_type": "openvz"
    }

TASK [roles/testvirt : debug vars virt_list ] **********************************************
    ok: [host1] => {
        "msg": [
            {
                "host": "host1",
                "type": "openvz"
            }
        ]
    }
    ok: [host2] => {
        "msg": [
            {
                "host": "host2",
                "type": "openvz"
            }
        ]
    }

There should be a simpler way, maybe using jinjia2 to combine the lists directly.

Anyone has advices?

Aleritty
  • 25
  • 7

1 Answers1

1

Q: "If any of my hosts has ansible_virtualization_type == "openvz" ALL hosts should execute a specific task."

A: For example, given the inventory for testing

shell> cat hosts
host1 ansible_virtualization_type=xen
host2 ansible_virtualization_type=xen
host3 ansible_virtualization_type=openvz

extract the variables

    - debug:
        msg: "{{ ansible_play_hosts|
                 map('extract', hostvars, 'ansible_virtualization_type')|
                 list }}"
      run_once: true

gives

  msg:
  - xen
  - xen
  - openvz

Test if the type is present

    - debug:
        msg: OK. ALL hosts should execute a specific task.
      when: "'openvz' in vtypes"
      vars:
        vtypes: "{{ ansible_play_hosts|
                    map('extract', hostvars, 'ansible_virtualization_type')|
                    list }}"
      run_once: true

gives

  msg: OK. ALL hosts should execute a specific task.

If this is working as expected proceed with all hosts

    - set_fact:
        all_hosts_execute_specific_task: true
      when: "'openvz' in vtypes"
      vars:
        vtypes: "{{ ansible_play_hosts|
                    map('extract', hostvars, 'ansible_virtualization_type')|
                    list }}"
      run_once: true
    - debug:
        msg: Execute a specific task.
      when: all_hosts_execute_specific_task|default(false)

gives

TASK [set_fact] ************************************************************
ok: [host1]

TASK [debug] ***************************************************************
ok: [host1] => 
  msg: Execute a specific task.
ok: [host3] => 
  msg: Execute a specific task.
ok: [host2] => 
  msg: Execute a specific task.

The task will be skipped if the type is missing.

Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
  • That's it! Thank you! May I ask why you set a fact and only after that you do the task? It isn't faster to do directly the check on the debug task? – Aleritty Aug 18 '21 at 10:04
  • 1
    You're welcome! The condition in the task will be evaluated for each node, i.e. in the example, it will be evaluated three times because there are three nodes (host1, host2, host3). Each host keeps its own copy of the variable *all_hosts_execute_specific_task*. (You might want to test it.). The *set_fact* is running only once because of ``run_once: true``, i.e. in this case it does not matter which node is actually running the *set_fact*. All nodes will receive the same variable *all_hosts_execute_specific_task*. The answer is no, checking it directly in the debug task would make it slower. – Vladimir Botka Aug 18 '21 at 10:19