Wednesday, June 13, 2018

Network Automation 01 - Ansible Play book for Cisco configuration backup

In this blog, I would like to introduce one of my Ansible playbooks. The function of this playbook is to collect the updated Cisco IOS device configurations in a defined interval. Only the updated configuration file will be kept.

1. Create a vault password file

echo "myvault" > ~/.vault_pass.txt
chomd 0600 ~/.vault_pass.txt

So this "vault_pass.txt" file has the "0600" privilege for the current user. And the "myvault" is the encryption key to encrypt other device login details which we will use later on.

2. Put the file path in the “ansible.cfg”

vault_password_file = ~/vault_pass.txt

Step 1: Configure the hosts file:

A-RTR01 ansible_host= ansible_hostname=A-RTR01

A-SWT01 ansible_host= ansible_hostname=A-SWT01


B-SWT01 ansible_host= ansible_hostname=B-SWT01
B-SWT02 ansible_host= ansible_hostname=B-SWT02
B-SWT03 ansible_host= ansible_hostname=B-SWT03


Step 2: Create the login detail file which encryption

cd /etc/ansible/group_vars/all/
ansible-vault create vault

******* the following is the content of the vault file *******

  customerA_ssh_username: cisco
  customerA_ssh_pass: ciscoA
  customerA_enable_pass: ciscoA

  customerB_ssh_username: cisco
  customerB_ssh_pass: cisco
  customerB_enable_pass: cisco

Step 3: Create the Group Var files

Ansible will try to find the Group Vars for the groups in the Inventory file under the “/group_vars” folder. In this example, we have “customerA” & “customerB” groups in the hosts file. So we can setup two vars files with the same name under the “/etc/ansible/group_vars/”.

cd /etc/ansible/group_vars/
vi customerA

    host: "{{ ansible_host }}"
    username: "{{ customerA_ssh_username }}"
    password: "{{ customerA_ssh_pass }}"
    auth_pass: "{{ customerA_enable_pass }}"
    transport: cli

cd /etc/ansible/group_vars/
vi customerB

    host: "{{ ansible_host }}"
    username: "{{ customerB_ssh_username }}"
    password: "{{ customerB_ssh_pass }}"
    auth_pass: "{{ customerB_enable_pass }}"
    transport: cli

Step 4: Create a site yml file
You can execute the role by:

ansible-playbook sc.yml

vi sc.yml

  - hosts: customerA
    gather_facts: no
    connection: local
      - saveconfig

  - hosts: customerB
    gather_facts: no
    connection: local
      - saveconfig

Step 5: Initial the Ansible Role

ansible-galaxy init saveconfig

Step 6: Setup the default variable in the "saveconfig" role

The default variable we would like to setup is the backup folder on the local server.

vi main.yml

  backupdir: /etc/ansible/backup

Step 7: Tasks in the roles (save configuration on the local Ansible server)

vi main.yml

# tasks file for saveconfig

# get the time for the current save file
  - name: get time
    local_action: command date +%Y%m%d%H%M%S
    register: time

# get the current running config form the destination device
  - name: run 'show run'
      provider: "{{provider}}"
      authorize: yes
        - show run
    register: config

# if there is not an existing folder for the destination device, create one
  - name: ensure the directory exists
      path: "{{backupdir}}/{{inventory_hostname}}"
      recurse: yes
      state: directory

# get the file list from the destination device folder
  - name: Get files in a folder
      paths: "{{backupdir}}/{{inventory_hostname}}"
    register: found_files

# get the latest file attributes if the folder is not empty
  - name: get the latest old file
      latest_file: "{{ found_files.files | sort(attribute='mtime',reverse=true) | first }}"
    when: found_files.matched != 0

# get the stat of the latest old config
  - name: get the stat of the old config
      path: "{{latest_file.path}}"
    register: oldconfig_stat
    when: found_files.matched != 0

# save the new config file to folder
  - name: save output to {{backupdir}}
      content: "{{config.stdout[0]}}"
      dest: "{{backupdir}}/{{inventory_hostname}}/config_{{inventory_hostname}}_{{time.stdout}}.txt"

# get the stat of the new config
  - name: get the stat of the new config
      path: "{{backupdir}}/{{inventory_hostname}}/config_{{inventory_hostname}}_{{time.stdout}}.txt"
    register: newconfig_stat
    when: found_files.matched != 0

# if the new config is the same as the latest old config, delete the new config file, delete the new file if it's the same
  - name: compare the new config and the latest old config
      state: absent
      path: "{{backupdir}}/{{inventory_hostname}}/config_{{inventory_hostname}}_{{time.stdout}}.txt"
      - found_files.matched != 0
      - newconfig_stat.stat.checksum == oldconfig_stat.stat.checksum

# if the new config is different than the latest old config, do nothing

Step 8: Setup the CRON

crontab /etc/crontab

 vi /etc/crontab

*/15 * * * * ansible-playbook /etc/ansible/sc.yml
# every 15 minutes


In this playbook, we achieve the gold to save the updated configuration in every 15 mins. But this playbook is not perfect as users have to login to the local Ansible server to get the configuration files. In the next post, I will introduce another play book to synchronise the configuration files to the central file server. So users only have to access the central file server.

No comments:

Post a Comment

NSX Load Balancer "Application Rules" Examples:

Load Balancing is one of the features provided by the NSX Edge Services Gateway (ESG). It can provide L7 Load Balancing by utilizing the HA...