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:
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.
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