Search code examples
regexansiblecisco-ios

Ansible: ios upgrade router: check "spacefree_kb" prior to image copy


I'm writing a playbook for ios upgrade of multiple switches and have most pieces working with exception of the flash free check. Basically, I want to check if there is enough flash space free prior to copying the image.

I tried using the gather facts module but it is not working how I expected:

from gather facts I see this:

"ansible_net_filesystems_info": {
        "flash:": {
            "spacefree_kb": 37492,
            "spacetotal_kb": 56574

This is the check I want to do:

fail:
    msg: 'This device does not have enough flash memory to proceed.'
 when: "ansible_net_filesystems_info | json_query('*.spacefree_kb')|int  <  new_ios_filesize|int"

From doing some research I understand that any value returned by a jinja2 template will be a string so my check is failing:

Pass integer variable to task without losing the integer type

The solution suggested in the link doesn't seem to work for me even with ansible 2.7.

I then resorted to store the results of 'dir' in a register and tried using regex_search but can't seem to get the syntax right.

(similar to this : Ansible regex_findall multiple strings)

"stdout_lines": [
        [
            "Directory of flash:/",
            "",
            "    2  -rwx         785   Jul 2 2019 15:39:05 +00:00  dhcp-snooping.db",
            "    3  -rwx        1944  Jul 28 2018 20:05:20 +00:00  vlan.dat",
            "    4  -rwx        3096   Jul 2 2019 01:03:26 +00:00  multiple-fs",
            "    5  -rwx        1915   Jul 2 2019 01:03:26 +00:00  private-config.text",
            "    7  -rwx       35800   Jul 2 2019 01:03:25 +00:00  config.text",
            "    8  drwx         512  Apr 25 2015 00:03:16 +00:00  c2960s-universalk9-mz.150-2.SE7",
            "  622  drwx         512  Apr 25 2015 00:03:17 +00:00  dc_profile_dir",
            "",
            "57931776 bytes total (38391808 bytes free)"
        ]
    ]

Can anyone provide some insight to this seemingly simple task? I just want '38391808' as an integer from the example above (or any other suggestion). I'm fairly new to ansible.

Thanks in advance.


Solution

  • json_query wildcard expressions return a list. The tasks below

    - set_fact:
        free_space: "{{ ansible_net_filesystems_info|
                        json_query('*.spacefree_kb') }}"
    - debug:
        var: free_space
    

    give the list

        "free_space": [
        37492
    ]
    

    which neither can be converted to an integer nor can be compared to an integer. This is the reason for the problem.

    The solution is simple. Just take the first element of the list and the condition will start working

    - fail:
        msg: 'This device does not have enough flash memory to proceed.'
      when: ansible_net_filesystems_info|
            json_query('*.spacefree_kb')|
            first|
            int <  new_ios_filesize|int
    

    Moreover, json_query is not necessary. The attribute spacefree_kb can be referenced directly

    - fail:
        msg: 'This device does not have enough flash memory to proceed.'
      when: ansible_net_filesystems_info['flash:'].spacefree_kb|
            int <  new_ios_filesize|int