Ansible: send email on unreachable host

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












0















I'd like to get an email sent whenever one of the hosts in ansible cannot be reached through SSH.



I've tried to write a playbook to do this (see below). After gathering facts, any unreachable host is discarded, so my task sending the email is never executed for the unreachable hosts.




-name: Check host accessibility
hosts: all
tasks:
- local_action: shell ssh deploy@ansible_hostname echo OK
register: check_ssh
- local_action: debug msg="check_ssh.stdout"
when: check_ssh.stdout != "OK"


Thanks a lot.










share|improve this question


























    0















    I'd like to get an email sent whenever one of the hosts in ansible cannot be reached through SSH.



    I've tried to write a playbook to do this (see below). After gathering facts, any unreachable host is discarded, so my task sending the email is never executed for the unreachable hosts.




    -name: Check host accessibility
    hosts: all
    tasks:
    - local_action: shell ssh deploy@ansible_hostname echo OK
    register: check_ssh
    - local_action: debug msg="check_ssh.stdout"
    when: check_ssh.stdout != "OK"


    Thanks a lot.










    share|improve this question
























      0












      0








      0








      I'd like to get an email sent whenever one of the hosts in ansible cannot be reached through SSH.



      I've tried to write a playbook to do this (see below). After gathering facts, any unreachable host is discarded, so my task sending the email is never executed for the unreachable hosts.




      -name: Check host accessibility
      hosts: all
      tasks:
      - local_action: shell ssh deploy@ansible_hostname echo OK
      register: check_ssh
      - local_action: debug msg="check_ssh.stdout"
      when: check_ssh.stdout != "OK"


      Thanks a lot.










      share|improve this question














      I'd like to get an email sent whenever one of the hosts in ansible cannot be reached through SSH.



      I've tried to write a playbook to do this (see below). After gathering facts, any unreachable host is discarded, so my task sending the email is never executed for the unreachable hosts.




      -name: Check host accessibility
      hosts: all
      tasks:
      - local_action: shell ssh deploy@ansible_hostname echo OK
      register: check_ssh
      - local_action: debug msg="check_ssh.stdout"
      when: check_ssh.stdout != "OK"


      Thanks a lot.







      ansible






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 9 '15 at 16:23









      Lluís VilanovaLluís Vilanova

      1065




      1065




















          2 Answers
          2






          active

          oldest

          votes


















          0














          I've found that using a Python script is the easiest solution (easier than a callback plugin, at least on my ansible version 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()





          share|improve this answer























          • Unfortunately the Python API has changed in ansible >2.0 and this method is no longer valid. (ansible.runner is deprecated and no loger available in v2.4)

            – Hopobcn
            Jan 29 '18 at 14:07











          • Is there a new alternative?

            – Lluís Vilanova
            Jan 30 '18 at 16:31


















          0














          Here is my solution for 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 '
          body: 'Cannot login into the machine'
          when: inventory_hostname == "< hostname of main server here >"


          That's the best solution I've been able to produce so far. It's a pitty that ansible doesn't consider unreachable hosts as to be failed, so a rescue section is never called. I've overcomed that issue counting the number of host that executed the last task vs the total amount of hosts. If it's different it means that at least one host is unreachable, thus executing the assert and going to the rescue section. Then, the second problem is that the assert applies to all hosts, so we have to pick only one host to send the email (in this case I picked the server where ansible is installed).






          share|improve this answer






















            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "106"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f241880%2fansible-send-email-on-unreachable-host%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            I've found that using a Python script is the easiest solution (easier than a callback plugin, at least on my ansible version 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()





            share|improve this answer























            • Unfortunately the Python API has changed in ansible >2.0 and this method is no longer valid. (ansible.runner is deprecated and no loger available in v2.4)

              – Hopobcn
              Jan 29 '18 at 14:07











            • Is there a new alternative?

              – Lluís Vilanova
              Jan 30 '18 at 16:31















            0














            I've found that using a Python script is the easiest solution (easier than a callback plugin, at least on my ansible version 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()





            share|improve this answer























            • Unfortunately the Python API has changed in ansible >2.0 and this method is no longer valid. (ansible.runner is deprecated and no loger available in v2.4)

              – Hopobcn
              Jan 29 '18 at 14:07











            • Is there a new alternative?

              – Lluís Vilanova
              Jan 30 '18 at 16:31













            0












            0








            0







            I've found that using a Python script is the easiest solution (easier than a callback plugin, at least on my ansible version 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()





            share|improve this answer













            I've found that using a Python script is the easiest solution (easier than a callback plugin, at least on my ansible version 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()






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 9 '15 at 18:08









            Lluís VilanovaLluís Vilanova

            1065




            1065












            • Unfortunately the Python API has changed in ansible >2.0 and this method is no longer valid. (ansible.runner is deprecated and no loger available in v2.4)

              – Hopobcn
              Jan 29 '18 at 14:07











            • Is there a new alternative?

              – Lluís Vilanova
              Jan 30 '18 at 16:31

















            • Unfortunately the Python API has changed in ansible >2.0 and this method is no longer valid. (ansible.runner is deprecated and no loger available in v2.4)

              – Hopobcn
              Jan 29 '18 at 14:07











            • Is there a new alternative?

              – Lluís Vilanova
              Jan 30 '18 at 16:31
















            Unfortunately the Python API has changed in ansible >2.0 and this method is no longer valid. (ansible.runner is deprecated and no loger available in v2.4)

            – Hopobcn
            Jan 29 '18 at 14:07





            Unfortunately the Python API has changed in ansible >2.0 and this method is no longer valid. (ansible.runner is deprecated and no loger available in v2.4)

            – Hopobcn
            Jan 29 '18 at 14:07













            Is there a new alternative?

            – Lluís Vilanova
            Jan 30 '18 at 16:31





            Is there a new alternative?

            – Lluís Vilanova
            Jan 30 '18 at 16:31













            0














            Here is my solution for 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 '
            body: 'Cannot login into the machine'
            when: inventory_hostname == "< hostname of main server here >"


            That's the best solution I've been able to produce so far. It's a pitty that ansible doesn't consider unreachable hosts as to be failed, so a rescue section is never called. I've overcomed that issue counting the number of host that executed the last task vs the total amount of hosts. If it's different it means that at least one host is unreachable, thus executing the assert and going to the rescue section. Then, the second problem is that the assert applies to all hosts, so we have to pick only one host to send the email (in this case I picked the server where ansible is installed).






            share|improve this answer



























              0














              Here is my solution for 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 '
              body: 'Cannot login into the machine'
              when: inventory_hostname == "< hostname of main server here >"


              That's the best solution I've been able to produce so far. It's a pitty that ansible doesn't consider unreachable hosts as to be failed, so a rescue section is never called. I've overcomed that issue counting the number of host that executed the last task vs the total amount of hosts. If it's different it means that at least one host is unreachable, thus executing the assert and going to the rescue section. Then, the second problem is that the assert applies to all hosts, so we have to pick only one host to send the email (in this case I picked the server where ansible is installed).






              share|improve this answer

























                0












                0








                0







                Here is my solution for 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 '
                body: 'Cannot login into the machine'
                when: inventory_hostname == "< hostname of main server here >"


                That's the best solution I've been able to produce so far. It's a pitty that ansible doesn't consider unreachable hosts as to be failed, so a rescue section is never called. I've overcomed that issue counting the number of host that executed the last task vs the total amount of hosts. If it's different it means that at least one host is unreachable, thus executing the assert and going to the rescue section. Then, the second problem is that the assert applies to all hosts, so we have to pick only one host to send the email (in this case I picked the server where ansible is installed).






                share|improve this answer













                Here is my solution for 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 '
                body: 'Cannot login into the machine'
                when: inventory_hostname == "< hostname of main server here >"


                That's the best solution I've been able to produce so far. It's a pitty that ansible doesn't consider unreachable hosts as to be failed, so a rescue section is never called. I've overcomed that issue counting the number of host that executed the last task vs the total amount of hosts. If it's different it means that at least one host is unreachable, thus executing the assert and going to the rescue section. Then, the second problem is that the assert applies to all hosts, so we have to pick only one host to send the email (in this case I picked the server where ansible is installed).







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 30 '18 at 16:49









                HopobcnHopobcn

                1011




                1011



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Unix & Linux Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f241880%2fansible-send-email-on-unreachable-host%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown






                    Popular posts from this blog

                    Peggy Mitchell

                    Palaiologos

                    The Forum (Inglewood, California)