"暂停"为每个主人

时间:2016-02-03 05:27:02

标签: ansible ansible-playbook ansible-2.x

在滚动更新之前,我想为我们的监控工具中的每个主机设置停机时间。我为此创建了一个自定义模块。设置停机时间可能会出现问题,而我们无法解决这个问题。在这种情况下,我想让用户选择是否应该中止或继续部署而不设置停机时间。

所以,让我说我像这样打电话给我的模块:

- downtime:
    duration: 5m
    comment: whatever
  ignore_errors: true
  register: downtime

所以我忽略了能够继续的错误。否则,将无法再处理设置停机失败的主机。

在下一步中,我希望用户手动确认是否要为没有设置停机时间的每台主机进行操作。

- name: Request user confirmation to proceed in case downtime could not be set
  pause:
    prompt: 'Downtime could not be set for all hosts. Do you want to proceed? Press return to continue. Press Ctrl+c and then "a" to abort'
  when: "{{ downtime | failed }}"

不幸的是pause模块(实际上它是一个动作插件)只会暂停处理的第一个主机。因此,如果第一个主机发生故障,它将暂停,如果第一个主机通过而所有其他主机都发生故障,它将继续执行所有主机。

这似乎是预期的行为。来自docs

  

暂停模块无需任何特殊注意事项即可集成到异步/并行化播放簿中(另请参阅:滚动更新)。使用带有serial playbook参数的暂停时(如滚动更新),只会为当前主机组提示一次。

所以无论如何,即使我会使用serial: 1(在这种情况下这是不可能的)暂停也只会停在第一个主机上。

现在我只是在没有条件的情况下暂停,让用户决定是否继续,无论停机任务是否失败。但由于失败应该非常罕见,这是我想避免的手动步骤。

任何人都可以看到如何解决方案:

  • 暂停每个主机(失败)
  • 暂停一次,以防任何主机失败

2 个答案:

答案 0 :(得分:2)

This bug report给了我一个循环工作的灵感。以下解决方案要求分别确认每个失败的主机:

- downtime:
    duration: 5m
    comment: whatever
  ignore_errors: true
  register: downtime

- name: Saving downtime state
  set_fact:
    downtime_failed: "{{ downtime | failed }}"

- name: Request user confirmation to proceed in case downtime could not be set
  pause:
    prompt: 'Downtime could not be set for {{ item }}. Do you want to proceed? Press return to continue. Press Ctrl+c and then "a" to abort'
  when: "{{ hostvars[item]['downtime_failed'] }}"
  with_items: "{{ play_hosts }}"

由于pause模块仅针对清单中列出的第一个主机运行,因此我们遍历所有可用主机(play_hosts)。要从所有其他主机访问状态,我们首先需要将结果存储为事实(set_fact),然后我们可以通过hostvars访问它,它保存当前播放的所有主机的所有事实。

答案 1 :(得分:2)

要在一组主机上运行pause模块,我做了这个伎俩:

- pause:
    prompt: "{{ item }} will be restarted. Enter 'YES' to restart"
  register: input
  with_items: "{{ play_hosts }}"

- set_fact:
    user_input: "{{ item.user_input }}"
  with_items: "{{ hostvars[play_hosts.0].input.results }}"
  when: item.item == ansible_hostname|upper

正如udondan所说,pause模块在​​该组的第一个主机上运行。通过这两项任务,我们可以获得每个主机的输入,并为所有主机设置新的事实。