Ansible:如何为播放的所有主机调用模块`add_host`

时间:2017-02-08 06:52:27

标签: ansible ansible-inventory

我正在用这个剧本创作一本剧本:

在主持人hypervisors上:

  • 从所有主机检索虚拟机列表
  • 使用模块add_host将所有这些广告组添加到名为guests
  • 的新广告资源组中

我的广告资源:

[hypervisors]
host1
host2

我的剧本:

- hosts: hypervisors
  - shell: virsh list | awk 'NR>2' | awk '{print $2}'
    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),这是使用此模块的一个特例(参见上面的链接),好像变量run_once被隐式固定到true

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

编辑:在仅使用localhost

的计算机上重现它的示例

创建文件 / tmp / host1_test 以模拟来宾 vm1 vm2 的返回:

vm1
vm2

创建文件 / tmp / host2_test 以模拟来宾 vm3 vm4 的返回:

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

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

ansible-playbook -c local -i test_add_host.ini test_add_host.yml
  • 首先播放主叫 host1 host2
  • 第二次播放主叫 vm1 vm2

如何在第二个时间内呼叫所有主机( vm1 vm2 vm3 vm4 )玩?

3 个答案:

答案 0 :(得分:5)

正如您所指出的那样,关于add_hostBYPASS_HOST_LOOP = True有一个问题 所以这是一种强迫run_once

如果您不介意以顺序方式运行hypervisors,则只需使用serial: 1

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

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

答案 1 :(得分:1)

如果您不想连续播放剧本,则可以使用ansible_play_hostsmap汇总结果。结果可以在下一场比赛中使用。

- hosts: all
  gather_facts: false
  tasks:
    - shell: virsh list | awk 'NR>2' | awk '{print $2}'
      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:

此答案来自Ansible: Accumulate output across multiple hosts on task run

答案 2 :(得分:0)

我用以下的playbook解决了这个问题(使用我的localhost示例)。这个解决方案非常复杂,如果你有一个更简单的解决方案,可以分享它!

  

我不想使用动态库存

# 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