7

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

在主机上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 绕过 play host 循环,只对 play 中的所有主机运行一次

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

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

编辑:仅使用 localhost 在您的计算机上重现它的示例

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

vm1
vm2

创建文件/tmp/host2_test以模拟来宾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

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

ansible-playbook -c local -i test_add_host.ini test_add_host.yml
  • 首先播放呼叫主机host1host2
  • 第二次播放呼叫主机vm1vm2

我应该怎么做才能在第二次播放中调用所有主机(vm1vm2vm3vm4)?

4

3 回答 3

12

正如你所指出的,有一个关于add_host:的事情BYPASS_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为每个主机执行。

于 2017-02-08T10:16:36.423 回答
1

如果您不想连续运行播放,您可以使用ansible_play_hosts和聚合结果map。结果可以在下一场比赛中使用。

- 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

于 2019-07-25T20:42:49.357 回答
0

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

我不想使用动态库存

# 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
于 2017-02-08T10:03:28.737 回答