Listing the Kernel Versions of All Your Hosts With Ansible

Posted by Fulvio Casali at Feb 02, 2018 10:25 AM |

If you want to quickly find the exact kernel versions of a large number of hosts, Ansible is the perfect tool.  It will save you from having to manually log in and run uname -ir on each one, and copy and paste the results in some local file.

I am going to share a little Ansible playbook below, which I came up with just the other day.  The impetus came in the form of an announcement from DigitalOcean about the Spectre and Meltdown vulnerabilities.

While tinkering with Ansible, I discovered the hostvars dictionary, an awesome data structure containing every last detail about the operating system of each host in the playbook's inventory.  hostvars is populated in the gather_facts step of a playbook execution.  There are two items in a host's hostvars data  which I  needed:

  • ansible_distribution_version:  this contains the version of the host's particular OS distribution.  All my hosts are running Ubuntu, and the values for me are 14.04, 15.04 and 16.04.
  • ansible_kernel:  this is the kernel version currently running, e.g. 3.13.0-141-generic.

The playbook contains two hosts sections. One for all, the only purpose of which is go through the gather_facts step.  The second hosts section is for localhost.

Starting from the bottom, the end result we are going for is to write the distribution version and the kernel version for each host into a local file. We can create a file using the template action and an appropriate jinja2 template. We only want one file, and we want it locally, hence the first reason for this hosts: localhost section. Otherwise, we would create a file on each of the remote hosts in the inventory.

We want our template to render the contents of a dictionary into which we have stored all the version information we have gathered from our hosts. So let's create this dictionary with a set_fact: task. We can use the with_inventory_hostnames iterator, which lets us loop over all the hosts and puts each hostname in the item variable. In this loop, we update the versions dict using the following syntax:

{{ versions | combine( { item: somevalue } ) }}

The python equivalent would be:

versions.update( { item: somevalue } )

or in other words:

versions[item] = somevalue

Remember, item is a hostname, and in place of somevalue we want to put a string containing both the distribution and the kernel version.

If we remember to initialize the versions variable to be an empty dict at the beginning, we have all the pieces we need.

playbook

The dumpall.j2 template is very simple:

template

Download them both:

The output looks something like this:

output

I heavily borrowed from these StackOverflow posts: