linuxnetwork-programmingansibledevopsicmp

Ansible: How to ICMP ping to check on host?


Im having some trouble with an Ansible setup. I need to check before executing my whole playbook if the host is available by ICMP, and if there's no reply, I want to skip that host from the execution of the playbook.

My current playbook is the following:

---
- name: Auto_backup_test
  gather_facts: False
  hosts: all
  become: false

  tasks:
    - name: Connection-ping
      delegate_to: localhost
      command: ping -c 2 "{{ inventory_hostname }}"
      register: router_ping

    - name: print_response
      ansible.builtin.debug:
        var: router_ping.rc
        verbosity: 2

So, the playbook should execute two ICMP pings requests, and save the result in the router_ping register.

After that I want it to check with the router_ping.rc value if the request failed and usig that I decide if the host is skipped or not.

When I execute the playbook using this command:

ansible-playbook -i /my_inventory/ playbook.yml -vvv

In my inventory I have 2 hosts, one that should be able to reply ICMP, and another IP that doesn't exist, so that host should fail.

The output is the following:

First host output

Second host output

As this can be seen, the host that replies the ICMP request works fine.

But when the host does not reply the ICMP request, the task ends failing and the register router_ping ends not being created, so I cannot use that register. The output of the second host is the what we want but, is not creating the register, so I cannot evaluate the router_ping.rc value to check if the host is available.

How could I be doing this to perform better?

I also tried using the ansible.builtin.ping module, but as this does not works as I thought as it always outputs SUCCESS, so it doesn't work for me.

I tried with this for a while to make it work, but I end always getting Success output even though the IP address of the host doesn't exist.


Solution

  • A minimal example playbook

    ---
    - hosts: test
      become: false
      gather_facts: false
    
      tasks:
    
      - name: ICMP ping from Control Node to Remote Node
        delegate_to: localhost # or controlnode.example.com
        command: ping -c 2 "{{ inventory_hostname }}"
        # Because it is an reporting task
        changed_when: false 
        check_mode: false
        failed_when: router_ping.rc == 1 or router_ping.rc > 2 # will result into success for rc 0 and rc 2
        register: router_ping
    
      - name: Show Return Code
        debug:
          msg: "{{ router_ping.rc }}"
    

    will result into an output of

    TASK [ICMP ping from Control Node to Remote Node] ******
    ok: [test1.example.com -> localhost]
    ok: [test1.nonexisting.example.com -> localhost]
    ok: [test2.example.com -> localhost]
    ok: [test2.nonexisting.example.com -> localhost]
    
    TASK [Show Return Code] ********************************
    ok: [test1.example.com] =>
      msg: '0'
    ok: [test1.nonexisting.example.com] =>
      msg: '2'
    ok: [test2.example.com] =>
      msg: '0'
    ok: [test2.nonexisting.example.com] =>
      msg: '2'
    
    PLAY RECAP **********************************************************************************************************
    test1.nonexisting.example.com : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    test1.example.com  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    test2.example.com : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    test2.nonexisting.example.com  : ok=2    changed=0    unreachable=0    failed=0
    

    With this (router_ping.rc) one could test if the host is resolvable and reachable (0) or not (2). However, this seems to be not a good practice for further playbook processing and since Ansible has already some handling for unreachable hosts implemented.

    Further Documentation

    and I like to recommend to read about

    Finally a somehow

    Similar Q&A