A few days ago I had to get some basic information from a handful of servers for an inventory report; just basic stuff like hostname, IP address, storage capacity, distro version, etc. I already manage all of my servers with Ansible, and there's a wealth of information available in Ansible's
setup module, so I knew there had to be a clever way to do this.
According to the documentation, the Python API is:
[...] very powerful, and is how the ansible CLI and ansible-playbook are implemented.
ansible.runner I whipped something up and extracted data from several dozen servers in just a few minutes (and I don't even know Python!):
$ ./ansible-runner.py mjanjavm10, 2, 30, Ubuntu 14.04, 192.168.7.34 mjanjavm14, 2, 30, Ubuntu 14.04, 192.168.7.37
I had to massage the data a bit to get clean numbers for RAM and storage capacity, but other than that it was extremely straightforward (as most things with Ansible generally are).
Here's the source code for the ansible-runner.py script above:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#!/usr/bin/env python import ansible.runner # hosts to contact hostlist = ['virtual'] # MiB -> GiB def mibs_to_gibs(mibs): return float(mibs) / 1024.0 # KiB -> GiB def kibs_to_gibs(kibs): return float(kibs) / 1024.0 / 1024.0 # bytes -> GiB def bytes_to_gibs(num_bytes): return float(num_bytes) / 1024.0 / 1024.0 / 1024.0 def parse_results(results): for (hostname, result) in results['contacted'].items(): memory = mibs_to_gibs(result['ansible_facts']['ansible_memtotal_mb']) # enumerate all disk devices to get total capacity disk_total_capacity = 0 for disk_device in result['ansible_facts']['ansible_devices'].iterkeys(): disk_sectors = float(result['ansible_facts']['ansible_devices'][disk_device]['sectors']) disk_sectors_size = float(result['ansible_facts']['ansible_devices'][disk_device]['sectorsize']) disk_bytes = disk_sectors * disk_sectors_size disk_total_capacity += bytes_to_gibs(disk_bytes) os = "%s %s" % (result['ansible_facts']['ansible_distribution'], result['ansible_facts']['ansible_distribution_version']) ip = "%s" % (result['ansible_facts']['ansible_default_ipv4']['address']) print "%s, %.0f, %2.0f, %s, %s" % (hostname, memory, disk_total_capacity, os, ip) if __name__ == '__main__': results = ansible.runner.Runner( module_name='setup', module_args='', remote_user='provisioning', sudo=False, pattern=hostlist, forks=5 ).run() parse_results(results) # vim: set sw=4 ts=4:
Feel free to use, improve, and share it.
This was originally posted on my personal blog; re-posted here for posterity.