'ping multiple ip and save it to one file in ansible

I want to ping several IPs with my linux server, namely:

  • ip 10.0.0.1 which is the host connected to the interface swp1
  • ip 10.0.0.2 which is the host connected to the interface swp2

with ip source 10.0.0.3 then the results are stored in a file. This command is executed through ansible with the following task:

- hosts: localhost
  connection: local
  gather_facts: yes
  tasks:
    - name: VERIFICATION // CONNECTIVITY BY PING
      shell: ping {{ item }} -c 2 -s 10.0.0.3 | grep -i received | awk '{print $4}'
      register: ping
      loop:
      - 10.0.0.1
      - 10.0.0.2

  - copy:
      content: "{{ ping.results | map(attribute='stdout') | join('\n') }}"
      dest: ping.txt

and the contents of the ping.txt as follows:

2
0

This task was executed successfully, but, how do I add the connected interface of the pinged host, so that the ping.txt become:

swp1 : 2
swp2 : 0

What script can be added to get this result?



Solution 1:[1]

Does this help? I needed to remove the "-s 10.0.0.3" from mine but updated and commented out the link in the playbook below. My -s is not the same I would image as it is for your OS.
- hosts: localhost
  connection: local
  gather_facts: yes
  tasks:
    - name: VERIFICATION // CONNECTIVITY BY PING
      #shell: ping {{ item.ip }} -c 2 -s 10.0.0.3 | grep -i received | awk '{print "{{item.name}}:"$4}'
      shell: ping {{ item.ip }} -c 2 | grep -i received | awk '{print "{{item.name}}:"$4}'
      register: ping
      loop:
      - { ip: '10.0.0.1', name: 'swp1'}
      - { ip: '10.0.0.2', name: 'swp2'}

    - copy:
        content: "{{ ping.results | map(attribute='stdout') | join('\n') }}"
        dest: ping.txt
My ping.txt:
swp1:2
swp2:0
You can adjust the spacing within the "awk" command to get "swp1 : 2"

Solution 2:[2]

The interfaces of an node are accessible in the ansible_facts of the host.
Each interface has an entry with its name being a property of the ansible_facts dictionary and a list of all the existing interfaces can be accessed under ansible_facts.interfaces.

Also, the item used to create a result from a loop in a registered command can be accessed via the item property of the dictionaries under the results list.

So, you can create an intermediary fact in order to find back the name of the interface based on its IP before dumping the result to a file.

Here would be the resulting fact and copy tasks:

- set_fact: 
    ping_results: >-
      {{
        ping_results | default([]) + [
          (
            _interfaces_ip | zip(_interfaces_names) 
            | selectattr("0", "eq", item.item) 
            | first
          ).1
          ~ ' : ' 
          ~ item.stdout
        ]
      }}
  loop: "{{ ping.results }}"
  loop_control:
    label: "{{ item.item }}"
  vars:
    _interfaces: >-
      {{
        ansible_facts 
        | dict2items 
        | selectattr('key', 'in', ansible_facts.interfaces) 
      }}
    _interfaces_names: >-
      {{
        _interfaces
        | map(attribute="key")
      }}
    _interfaces_ip: >-
      {{
        _interfaces
        | map(attribute="value.ipv4.address", default="n/a")
      }}

- copy:
    content: "{{ ping_results | join('\n') }}"
    dest: ping.txt

Your modified playbook, should then, yield, in your case:

TASK [Gathering Facts] ***************************************************
ok: [localhost]

TASK [VERIFICATION // CONNECTIVITY BY PING] ******************************
ok: [localhost]

TASK [set_fact] **********************************************************
ok: [localhost] => (item=10.0.0.1)
ok: [localhost] => (item=10.0.0.2)

TASK [copy] **************************************************************
ok: [localhost]

And your ping.txt would contains:

swp1 : 2
swp2 : 0

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Carl Andrews
Solution 2 β.εηοιτ.βε