My Ansible playbook to update VyOS system

I just want to share my playbook to upgrade VyOS image with Ansible.
This playbook copies local iso file, (version 1.2.8 in my playbook).
Installs system with add system image
Schedules a reboot at ~4:30 in the morning.
Clean up old installation file.

Tested with ansible 2.9.14

---
- name: VyOS - install new image and schedule machine reboot.
  gather_facts: False
  vars:
    vyos_version: 1.2.8
    vyos_dir: "files/"
    vyos_file: "vyos-{{vyos_version}}-amd64.iso"
  hosts:
    - vyosrouter

  tasks:
    - name: "Copying {{vyos_file}} to system"
      net_put:
        src: "{{ vyos_dir }}{{ vyos_file }}"
        dest: "{{ vyos_file }}"

    - name: "Installing {{vyos_version}} on system"
      cli_command:
        command: add system image "{{ vyos_file }}"
        newline: True
        check_all: True
        prompt:
        - 'What would you like to name this image'
        - 'directory and config file'
        - 'current configuration'
        answer:
        - "{{ vyos_version }}"
        - 'Yes'
        - 'Yes'

    - name: Schedule reboot around 04:30 tonight
      cli_command:
        command: "reboot at 04:{{ range(25,35) | random }}"

    - name: Cleanup installation file
      cli_command:
        command: "rm {{ vyos_file }}"
7 Likes

Bonus python script to cleanup old images.
This will keep atleast two images on the router, and will not ask to delete running or default boot.
tested with netmiko 3.3.0. (pip3 install netmiko)
Just run it with python3 thisscript.py vyos.router.lan router2.ext

from netmiko import ConnectHandler
from re import match
from sys import argv

if (len(argv) < 2):
    print(f"Give atleast one router as argument... python3 ./{argv[0]} vyosrouter.lan")
    quit()

device = {
    'device_type': 'vyos',
    'username': 'user',
    'use_keys': True,
    'ssh_config_file': '~/.ssh/config',
}
# Loop through given arguments
for router in argv[1:]:
    device['host'] = router
    print(f"Connecting to {device['host']}...")
    connection = ConnectHandler(**device)
    print("Connected... finding images...")
    output = connection.send_command("show system image").splitlines()

    images = []
    print("==========================")
    for line in output:
        if v := match(r"^\s+[0-9]+\:\s(\S+.*)", line):
            images.append(line)
            print(line)
    print("==========================")

    # Ask to delete images in reverse order.
    # Dont ask to delete if there are two or less.
    for i, line in reversed(list(enumerate(images))):
        if(i < 2):
            print("====================")
            print("Must keep atleast two images!!!....")
            break
        # Assumes no whitespace in version name.
        elif m := match(r"^\s+[0-9]+\:\s(\S+)$", line):
            a = input(f"Delete: {m.group(1)} ? [Yes]/No ")
            if a in {"Yes", "yes", "y", ""}:
                print(f"Deleting system image {m.group(1)}...")
                delete  = connection.send_command_timing("delete system image " + m.group(1))
                delete += connection.send_command_timing("Yes")
                print(f"Successfully deleted {m.group(1)} ")
        # Skipping lines that contains text after version, it indicates its running/default boot
        elif m := match(r"^\s+[0-9]+\:\s(\S+).(.*)$", line):
            print(f"Skipping: {m.group(1)} {m.group(2)} ...")

    print(connection.send_command("show system image"))
    print(f"Disconnecting from {device['host']}...")
    connection.disconnect()
    print("============================================================")

3 Likes

It is not working with vyos 1.3.x . Can’t put iso file to vyos.

Which directory do you use for destination file?
Do you see any errors?

@Viacheslav My ansible playbook is here

---
- name: VyOS - install new image and schedule machine reboot.
  gather_facts: False
  hosts: myhome-gw-192-168-11-1
  vars:
    vyos_version: 1.3.3
    vyos_dir: "files/"
    vyos_file: "vyos-{{vyos_version}}-amd64.iso"


  tasks:
    - name: Get config for VyOS devices
      vyos_facts:
        gather_subset: all
    - name: Display the config
      debug:
        msg: "The hostname is {{ ansible_net_hostname }} an the OS is {{ ansible_net_version }}"

    - name: "Copying {{vyos_file}} to system"
      net_put:
        src: "{{ vyos_dir }}{{ vyos_file }}"
        dest: "{{ vyos_file }}"

    - name: "Installing {{vyos_version}} on system"
      cli_command:
        command: add system image "{{ vyos_file }}"
        newline: True
        check_all: True
        prompt:
        - 'What would you like to name this image'
        - 'directory and config file'
        - 'current configuration'
        answer:
        - "{{ vyos_version }}"
        - 'Yes'
        - 'Yes'
        when: ansible_facts['ansible_net_version'] != "VyOS {{ vyos_version }}"


    - name: Schedule reboot around 04:30 tonight
      cli_command:
        command: "reboot at 04:{{ range(25,35) | random }}"

    - name: Cleanup installation file
      cli_command:
        command: "rm {{ vyos_file }}"
        when: ansible_facts['ansible_net_version'] != "VyOS {{ vyos_version }}"

After running with command ansible-playbook vyos_upgrade.yml -vvv
I got error like this

TASK [Copying vyos-1.3.3-amd64.iso to system] **********************************
task path: /Users/myname/repository/network-automation-ansible/vyos_upgrade.yml:19
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
redirecting (type: terminal) ansible.builtin.vyos to vyos.vyos.vyos
redirecting (type: cliconf) ansible.builtin.vyos to vyos.vyos.vyos
redirecting (type: modules) ansible.builtin.net_put to ansible.netcommon.net_put
redirecting (type: action) ansible.builtin.net_put to ansible.netcommon.net_put
redirecting (type: action) ansible.builtin.net_put to ansible.netcommon.net_put
fatal: [myhome-gw-192-168-11-1]: FAILED! => {
    "changed": false,
    "destination": "vyos-1.3.3-amd64.iso",
    "msg": "Exception received: unable to connect to socket /Users/myname/.ansible/pc/fc577831b8. See the socket path issue category in Network Debug and Troubleshooting Guide"
}

Works fine in my case

---

- hosts: r4

  gather_facts: 'no'

  vars:
    vyos_version: '1.3.3'
    vyos_dir: "files/"
    vyos_file: "vyos-{{vyos_version}}-amd64.iso"

  tasks:
    - name: Copying {{vyos_file}} to system
      net_put:
        src: "{{ vyos_dir }}{{ vyos_file }}"
        dest: "{{ vyos_file }}"

Execute playbook

$ ansible-playbook put_file.yml 

PLAY [r4] *******************************************************************************************************************************************************************

TASK [Copying vyos-1.3.3-amd64.iso to system] *******************************************************************************************************************************
changed: [r4]

PLAY RECAP ******************************************************************************************************************************************************************
r4                         : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

It looks like the problem is with your Ansible host.

1 Like

I run the playbook on MACOS, it truly has problems. After testing it on Debian 11, it works. Thanks, bro!