There are a few issues with your playbook. The first is that you're trying to execute both a shell
and a setup
task on the remote host, which of course isn't going to work if that host isn't available.
It doesn't even make sense to run ping
task on the remote host: you want to run that on your local host, using delegation. We can do something like this to record the availability of each host as a host variable:
---
- hosts: all
gather_facts: false
tasks:
- delegate_to: localhost
command: ping -c1 "{{ hostvars[inventory_hostname].ansible_host|default(inventory_hostname) }}"
register: ping
ignore_errors: true
- set_fact:
available: "{{ ping.rc == 0 }}"
You're trying to run the setup
module against your remote host, but that only makes sense if the remote host is available, so we need to make that conditional on the result of our ping
task:
- setup:
filter: "ansible_*"
when: ping.rc == 0
With that in place, we can generate a file with information about the availability of each host. I'm using lineinfile
here because that's what you used in your example, but if I were writing this myself I would probably use a template
task:
- hosts: localhost
gather_facts: false
tasks:
- lineinfile:
dest: ./available.txt
line: "Host: {{ item }}, connection={{ hostvars[item].available }}"
regexp: "Host: {{ item }}"
create: true
loop: "{{ groups.all }}"
Of course, in your example you're attempting to include a variety of other facts about the host:
line: 'Host:{{ inventory_hostname }},OS:{{ ansible_distribution }},Kernel:{{ansible_kernel}},OSVersion:{{ansible_distribution_version}},FreeMemory:{{ansible_memfree_mb}},connection:{{ping_status.rc}}'
Those facts won't be available if the target host wasn't available, so you need to make all of that conditional using a {% if <condition> %}...{% endif %}
construct:
line: "Host:{{ item }},connection:{{ hostvars[item].available }}{% if hostvars[item].available %},OS:{{ hostvars[item].ansible_distribution }},Kernel:{{ hostvars[item].ansible_kernel }},OSVersion:{{ hostvars[item].ansible_distribution_version }},FreeMemory:{{ hostvars[item].ansible_memfree_mb }}{% endif %}"
This makes the final playbook look like this:
---
- hosts: all
gather_facts: false
tasks:
- delegate_to: localhost
command: ping -c1 "{{ hostvars[inventory_hostname].ansible_host|default(inventory_hostname) }}"
register: ping
ignore_errors: true
- set_fact:
available: "{{ ping.rc == 0 }}"
- setup:
when: ping.rc == 0
- hosts: localhost
gather_facts: false
tasks:
- lineinfile:
dest: ./available.txt
line: "Host:{{ item }},connection:{{ hostvars[item].available }}{% if hostvars[item].available %},OS:{{ hostvars[item].ansible_distribution }},Kernel:{{ hostvars[item].ansible_kernel }},OSVersion:{{ hostvars[item].ansible_distribution_version }},FreeMemory:{{ hostvars[item].ansible_memfree_mb }}{% endif %}"
regexp: "Host: {{ item }}"
create: true
loop: "{{ groups.all }}"