Network Backup

 

With the network being the foundation of every business, it’s important to have back-ups of your network equipment.

Rapid advances in automation technologies are changing how networks are deployed, operated and backed up. The manual approach to managing networks cannot keep up and businesses need new tools to run their networks.

The Networks team at UKCloud uses Ansible for network automation for several reasons, including:

  • Free and open source software
  • Agentless– does not require installition of extra software agents on the endpoints, which means that we can easily automate any type of device with or without an API.
  • Extensible– over the past years there’s been an increase in the number of Ansible integrations developed by leading vendors and community independent users.
  • Integration with existing DevOps workflows– Ansible is used for application deployment in our organisation and we can integrate Ansible into workflows that already exist, as well as leveraging existing knowledge in the business.
  • Security – communicate securely with network hardware over SSH or HTTPS.
  • Community – benefit from community and vendor generated playbooks and roles to help accelerate automation projects.

Network backup with Ansible

We‘ve started using Ansible to back up the configuration of all our network devices for the following platforms:

  • Cisco NX-OS
  • Cisco IOS
  • Cisco IOS-XE
  • Cisco ASA (single context and multi-context)
  • Arista EOS

The playbook  we’re using expands on a Cisco role,  adding support for multi-context ASA and Arista EOS devices. You can find more information from Cisco here:

https://developer.cisco.com/codeexchange/github/repo/ciscops/ansible-network-backup/

To provide a real world example, this blog shows how we use YAML task files to back up each platform:

asa-back-up.yml

---
- name: ASA - Save the configuration
  asa_config:
    save: yes
  retries: 2

- name: ASA - Backup the config
  asa_config:
    backup: yes
  register: config_output
  retries: 2

- set_fact:
    temp_backup_file: "{{ config_output.backup_path }}"

eos-backup.yml

---
- name: EOS - Save the configuration
  eos_config:
    save_when: modified
  retries: 2
- name: EOS - Backup the config
  eos_config:
    backup: yes
  register: config_output
  retries: 2

- set_fact:
    temp_backup_file: "{{ config_output.backup_path }}"

 

ios-backup.yml

---
- name: IOS - Save the configuration
  ios_config:
    save_when: modified
  retries: 2

- name: IOS - Backup the config
  ios_config:
    backup: yes
  register: config_output
  retries: 2

- set_fact:
    temp_backup_file: "{{ config_output.backup_path }}"

nxos-backup.yml

---
- name: NXOS - Save the configuration
  nxos_config:
    save_when: modified
  retries: 2

- name: NXOS - Backup the config
  nxos_config:
    backup: yes
  register: config_output
  retries: 2

- set_fact:
    temp_backup_file: "{{ config_output.backup_path }}"

- name: NXOS - Delete the Time from the temp file
  replace:
    path: "{{ temp_backup_file }}"
    regexp: '^!Time.*$'
  changed_when: False
  delegate_to: localhost

 

system-backup.yml

---

- name: ASA SYSTEM CONTEXT - Backup the config
  asa_command:
    commands:
      - show run
    context: system
  register: config_output
  retries: 2

- copy:
    content: "{{ config_output.stdout[0] }}"
    dest: "{{ network_backup_file }}"

- set_fact:
    temp_backup_file: "{{ network_backup_file }}"

 

For all of these tasks we set up a value temp_backup_file, which stores the location where the files will be saved. Using the network_backup_file variable, we copy the files to a chosen location and clear the temp files inside the role.

main.yml 

---

- include_tasks: "{{ role_path }}/tasks/{{ ansible_network_os_type }}-backup.yml"

- name: Copy the temp to the destination
  copy:
    src: "{{ temp_backup_file }}"
    dest: "{{ network_backup_file }}"
  register: copy_result
  delegate_to: localhost

- name: Delete the temp file
  file:
    path: "{{ temp_backup_file }}"
    state: absent
  changed_when: False
  delegate_to: localhost

 

To run the backups, we call the role network_backup_directory for the location for the files to be saved in and the git repo if we want to use one.

backup.yml

---

- hosts: all
  connection: network_cli
  gather_facts: no
  become: true


  tasks:
  - include_role:
      name: network-backup
    vars:
      network_backup_repository: 'ssh://git@git/backup.git'

- hosts: localhost
  connection: local
  become: true

  tasks:
    - name: Moving Files
      shell: /usr/bin/python {{playbook_dir}}/move-files.py

For the anisble.cfg we use the following settings:

[defaults]

deprecation_warnings=False
gathering = explicit
retry_files_enabled = True

[paramiko_connection]
host_key_auto_add = True

[persistent_connection]
command_timeout=60
connect_timeout=60
connect_retry_timeout=60

 

This is what a run of the playbook looks like:

ansible-playbook backup.yml -i inventory.yml

This is what running the playbook looks like:

 

And this is what a change in the config looks like in version control:

After running the playbook, a local copy of the configured files is kept, and configs are uploaded to version control.  By having the config files in version control we can easily see the changes made to the configuration of any device on a day by day basis.