Ansible:如何为游戏的所有主机调用模块“add_host”

Ansible: how to call module `add_host` for all hosts of the play

我正在用这个剧本制作剧本:

在主机上 hypervisors:

我的库存:

[hypervisors]
host1
host2

我的剧本:

- hosts: hypervisors
  - shell: virsh list | awk 'NR>2' | awk '{print }'
    register: result_virsh
  - add_host:
      name: "{{ item }}"
      group: "guests"
    with_items: "{{ result_virsh.stdout_lines }}"

模块 add_host bypasses the play host loop and only runs once for all the hosts in the play.

然后它被调用一次(对于host1),它是使用这个模块的一个特殊情况(见上面的link),就好像变量run_once被隐式固定为true.

如何将它用于组 hypervisors 中的所有主机?

编辑:仅使用 localhost

在您的计算机上重现它的示例

创建文件 /tmp/host1_test 来模拟 return 来宾 vm1vm2 :

vm1
vm2

创建文件 /tmp/host2_test 来模拟 return 来宾 vm3vm4 :

vm3
vm4

将此清单 (test_add_host.ini) 用于两台主机,均具有固定 IP 地址 127.0.0.1:

[hypervisors]
host1 ansible_host=127.0.0.1 test_filename=/tmp/host1_test
host2 ansible_host=127.0.0.1 test_filename=/tmp/host2_test

使用这个剧本(test_add_host.yml):

- hosts: hypervisors
  gather_facts: no
  tasks:
  - shell: "cat {{ test_filename }}"
    register: result_virsh
  - add_host:
      name: "{{ item }}"
      group: "guests"
    with_items: "{{ result_virsh.stdout_lines }}"

- hosts: guests
  gather_facts: no
  tasks:
  - local_action: ping

使用以下命令在本地调用此剧本:

ansible-playbook -c local -i test_add_host.ini test_add_host.yml

怎么调用所有主机(vm1, vm2, vm3 and vm4) 第二场 ?

我使用以下剧本解决了这个问题(使用我的本地主机示例)。这个解决方案很复杂,如果你有更简单的,分享一下!

I didn't want to use dynamic inventories

# Get list of virtual machines in hostvars[inventory_hostname].vms
- hosts: hypervisors
  gather_facts: no
  tasks:
    - shell: "cat {{ test_filename }}"
      register: result_virsh
    - set_fact:
        vms: "{{ result_virsh.stdout_lines }}"

# Remove previous vm_hosts file
- hosts: localhost
  gather_facts: no
  tasks:
    - file:
        path: /tmp/vm_hosts
        state: absent

# Build file vm_hosts with list of virtual machines in serial (working in parallele with same file cause some troubles)
- hosts: hypervisors
  gather_facts: no
  serial: 1
  tasks:
    - block:
        - file:
            path: /tmp/vm_hosts
            mode: 0644
            state: touch
          run_once: yes
        - lineinfile:
            dest: /tmp/vm_hosts
            line: '{{ item }}'
          with_items: "{{ hostvars[inventory_hostname].vms }}"
      delegate_to: localhost

# Add list of virtual machines from file vm_hosts to in-memory inventory
- hosts: localhost
  gather_facts: no
  tasks:
  - add_host:
      name: "{{ item }}"
      group: "guests"
    with_lines: cat /tmp/vm_hosts

- hosts: guests
  gather_facts: no
  tasks:
    - local_action: ping

如您所述,add_host 有一点:BYPASS_HOST_LOOP = True
所以是一种被逼的run_once.

如果您不介意按顺序 运行 超过 hypervisors,您可以简单地使用 serial: 1:

- hosts: hypervisors
  serial: 1
  tasks:
    - shell: virsh list | awk 'NR>2' | awk '{print }'
      register: result_virsh
    - add_host:
        name: "{{ item }}"
        group: "guests"
      with_items: "{{ result_virsh.stdout_lines }}"

这确保每个播放批次只包含一个主机,因此 add_host 对每个主机执行。

如果您不想 运行 连续播放,您可以使用 ansible_play_hostsmap 汇总结果。可以在接下来的比赛中使用结果。

- hosts: all
  gather_facts: false
  tasks:
    - shell: virsh list | awk 'NR>2' | awk '{print }'
      register: result_virsh
      changed_when: false

    - add_host:
        name: "{{ item }}"
        group: guests
      changed_when: false
      loop: "{{ ansible_play_hosts | map('extract', hostvars, 'result_virsh') | map(attribute='stdout_lines') | flatten }}"

- hosts: guests
  gather_facts: false
  tasks:
    - ping:

此答案来自