Ansible:在无法访问的主机上发送电子邮件

Ansible:在无法访问的主机上发送电子邮件

当 ansible 中的主机无法通过 SSH 访问时,我希望收到一封电子邮件。

我试图写一本剧本来做到这一点(见下文)。收集事实后,任何无法访问的主机都会被丢弃,因此我的发送电子邮件的任务永远不会为无法访问的主机执行。

-name:检查主机可访问性
  主办方:全部
  任务:
    - local_action: shell ssh deploy@{{ansible_hostname}} echo OK
      注册:check_ssh
    - local_action:调试消息=“{{check_ssh.stdout}}”
      当:check_ssh.stdout!=“确定”

多谢。

答案1

这是我的解决方案ansible > 2.0

- name: Check host accessibility
  hosts: all
  user: deploy
  gather_facts: no
  tasks:
    - block:
        - command: echo OK

        - assert:
            that:
              - ansible_play_hosts == ansible_play_hosts_all
      rescue:

        - name: send email when something goes wrong (pe, cannot reach a machine)
          local_action:
            module: mail
            host: localhost
            to: < email here >
            from: < email here >
            subject: 'Host check - {{ (ansible_play_hosts_all | difference(ansible_play_hosts)) | first }}'
            body: 'Cannot login into the machine'
          when: inventory_hostname == "< hostname of main server here >"

这是迄今为止我能够提供的最佳解决方案。遗憾的是,它ansible不认为unreachable主机是failed,所以rescue永远不会调用一个部分。我已经解决了计算执行最后一个任务的主机数量与主机总数的问题。如果不同,则意味着至少有一台主机unreachable,因此执行断言并转到该rescue部分。然后,第二个问题是断言适用于所有主机,因此我们必须只选择一台主机来发送电子邮件(在本例中我选择了安装了ansible的服务器)。

答案2

我发现使用 Python 脚本是最简单的解决方案(比回调插件更容易,至少在我的 ansible 版本 1.7 上):

#!/usr/bin/env python

from __future__ import print_function
import ansible.inventory
import ansible.runner                                                                                   
from subprocess import Popen, PIPE
import sys


TO = "root"


def message(subject, body):
    p = Popen(["mail", "-s", subject, TO], stdin=PIPE)                                                  
    p.communicate(input=body)                                                                           
    res = p.wait()                                                                                      
    if res != 0:
        print("Failed to send message", file=sys.stderr)                                                


def main():
    im = ansible.inventory.Inventory()                                                                  
    runner = ansible.runner.Runner(                                                                     
        module_name='command',                                                                          
        module_args='sh -c "echo OK"',                                                                  
        sudo=True,
    )                                                                                                   
    run = runner.run()
    nosudo = set(run["dark"].keys())

    runner = ansible.runner.Runner(
        module_name='command',
        module_args='sh -c "echo OK"',                                                                  
        sudo=False,
        inventory=ansible.inventory.Inventory(list(nosudo)),                                            
    )   
    run = runner.run()                                                                                  
    nonet = set(run["dark"].keys()) 

    nosudo = nosudo - nonet

    for host in nosudo:                                                                                 
        message("Host check: %s" % host,
                "Cannot execute 'sudo -u root ...' as user 'deploy'.")                                  
    for host in nonet:
        message("Host check: %s" % host,
                "Cannot login into the machine.")


if __name__ == '__main__':                                                                              
    main()      

相关内容