Ansible network 101 : Cisco device facts collection and save to a csv file (New method)

Description: Needed to develop device information collections tool based on Ansible. The YAML will run and save the file into a nice csv format. Since we are using the new method with gather_facts: yes, the work is easy!

ansible.cfg file


[defaults]
inventory=inventory
host_key_checking=False
#timeout = 30
nocows = 1
deprecation_warnings = False
retry_files_enabled = False
log_path = ./csr1k_ansible.log
forks = 30
interpreter_python=auto_silent
#ansible_python_interpreter: /usr/bin/python3
#host_key_check = False

Inventory file

[ios:vars]
ansible_network_os=ios
ansible_user=jdoe
ansible_password=cisco123

[ios:children]
routers
switches

[routers]
crs1kv01 ansible_host=192.168.0.181
crs1kv02 ansible_host=192.168.0.182

[switches]
c8kv01 ansible_host=192.168.0.191
#c8kv02 ansible_host=192.168.0.192

#[wlcs]
#wlc01 ansible_host= 192.168.0.241

Ansible YAML file

jdoe@u20s:~/cisco_csr1k$ cat test_fact_to_csv_v0.3a.yml

---
- name: GATHER FACTS FOR IOS
  hosts: all
  connection: network_cli
  gather_facts: yes    # Gather Facts Enabled

  vars:
    output_path: "./csv/"
    filename: "network_device_info_{{ date }}.csv"

  tasks:
    - name: Get Date for folder creation
      set_fact: date="{{lookup('pipe','date +%Y%m%d')}}"
      tags: date_stamp
      run_once: true

#This will extract vavlues from the ios_facts and conver into csv_data
    - name: Get the values
      set_fact:
        csv_data: >
          {{ ansible_net_hostname }},{{ ansible_net_all_ipv4_addresses }},{{ ansible_net_all_ipv6_addresses }},
          {{ ansible_net_model }},{{ ansible_net_serialnum }},{{ ansible_net_version }},
          {{ ansible_net_image }},{{ ansible_net_iostype }},{{ ansible_net_filesystems }},
          {{ ansible_net_filesystems_info['bootflash:']['spacetotal_kb'] }},{{ ansible_net_filesystems_info['bootflash:']['spacefree_kb'] }},
          {{ ansible_net_memtotal_mb }},{{ ansible_net_memfree_mb }},{{ ansible_net_neighbors }},
          {{ ansible_net_system }},{{ ansible_net_api }},{{ ansible_net_python_version }}

#Create a csv file and add the header, only runs once on the first node
    - name: Create a csv file and put headers
      lineinfile:
        dest: "{{ output_path }}/{{ filename }}"
        line: >
          hostname,all_ipv4_addresses,all_ipv6_addresses,
          model,serialnum,version,
          image,iostype,filesystems,
          filesystems_info_spacetotal_kb,filesystems_info_spacefree_kb,
          memtotal_mb,memfree_mb,neighbors,
          system,api,python_version
        create: yes
        state: present
      when: inventory_hostname == groups.all[0]

#Write the device facts to CSV file
    - name: Output Information to CSV file
      lineinfile:
        dest: "{{ output_path }}/{{ filename }}"
        line: "{{ csv_data }}"
      when: ansible_net_iostype == 'IOS-XE'

    - name: Output Information to CSV file
      lineinfile:
        dest: "{{ output_path }}/{{ filename }}"
        line: "{{ csv_data }}"
      when: ansible_net_iostype == 'IOS'

#Remove any blank newlines from the file, only runs once on the first node
    - name: Remove blank lines from csv file
      lineinfile:
        path: "./{{ output_path }}/{{ filename }}"
        state: absent
        regex: '^\s*$'
      when: inventory_hostname == groups.all[0]

Run the playbook

jdoe@u20s:~/cisco_csr1k$ ansible-playbook test_fact_to_csv_v0.3a.yml


PLAY [GATHER FACTS FOR IOS] ******************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************
[WARNING]: Ignoring timeout(10) for ios_facts
[WARNING]: Ignoring timeout(10) for ios_facts
[WARNING]: Ignoring timeout(10) for ios_facts
[WARNING]: default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards
ok: [crs1kv01]
ok: [c8kv01]
ok: [crs1kv02]

TASK [Get Date for folder creation] **********************************************************************************************************************************************************************************************
ok: [crs1kv01]

TASK [Get the values] ************************************************************************************************************************************************************************************************************
ok: [crs1kv01]
ok: [crs1kv02]
ok: [c8kv01]

TASK [Create a csv file and put headers] *****************************************************************************************************************************************************************************************
skipping: [crs1kv02]
skipping: [c8kv01]
changed: [crs1kv01]

TASK [Output Information to CSV file] ********************************************************************************************************************************************************************************************
changed: [c8kv01]
changed: [crs1kv01]
changed: [crs1kv02]

TASK [Output Information to CSV file] ********************************************************************************************************************************************************************************************
skipping: [crs1kv02]
skipping: [crs1kv01]
skipping: [c8kv01]

TASK [Remove blank lines from csv file] ******************************************************************************************************************************************************************************************
skipping: [crs1kv02]
skipping: [c8kv01]
changed: [crs1kv01]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
c8kv01                     : ok=3    changed=1    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0
crs1kv01                   : ok=6    changed=3    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
crs1kv02                   : ok=3    changed=1    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0

The end product

jdoe@u20s:~/cisco_csr1k$ pwd
/home/jdoe/cisco_csr1k

jdoe@u20s:~/cisco_csr1k$ ls -lh csv/
total 4.0K
-rw-rw-r– 1 jdoe jdoe 772 Jul 8 07:29 network_device_info_20210708.csv

jdoe@u20s:~/cisco_csr1k$ cat csv/network_device_info_20210708.csv


hostname,all_ipv4_addresses,all_ipv6_addresses, model,serialnum,version, image,iostype,filesystems, filesystems_info_spacetotal_kb,filesystems_info_spacefree_kb, memtotal_mb,memfree_mb,neighbors, system,api,python_version
c8kv01,['192.168.0.191'],[], C8000V,99FEVAS4IJA,17.04.01b, bootflash:packages.conf,IOS-XE,['bootflash:'], 11304176.0,9857952.0, 2036243.12109375,1851416.61328125,{}, ios,cliconf,3.8.10
csr1k02,['192.168.0.182'],[], CSR1000V,9UX7R8P8L4L,16.08.02, bootflash:packages.conf,IOS-XE,['bootflash:'], 7712692.0,6350192.0, 2185996.90625,1904821.1796875,{}, ios,cliconf,3.8.10
csr1kv01,['192.168.0.181'],[], CSR1000V,9TEBYHVW5FU,16.08.02, bootflash:packages.conf,IOS-XE,['bootflash:'], 7712692.0,6352600.0, 2185996.90625,1906702.1015625,{}, ios,cliconf,3.8.10

Now run this to tens and hundreds of devices.

Leave a comment