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.
Prerequisite:


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”




[defaults]
vault_password_file = ~/vault_pass.txt

Step 1: Configure the hosts file:


[customerArouter]
A-RTR01 ansible_host=192.168.199.249 ansible_hostname=A-RTR01

[customerAswitch]
A-SWT01 ansible_host=192.168.199.245 ansible_hostname=A-SWT01

[customerA:children]
customerArouter
customerAswitch

[customerBswitch]
B-SWT01 ansible_host=192.168.199.246 ansible_hostname=B-SWT01
B-SWT02 ansible_host=192.168.199.247 ansible_hostname=B-SWT02
B-SWT03 ansible_host=192.168.199.248 ansible_hostname=B-SWT03

[customerB:children]
customerBswitch

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

---
  provider:
    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

---
  provider:
    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


cd/etc/ansible/
vi sc.yml

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

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

Step 5: Initial the Ansible Role


cd/etc/ansible/roles/
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.


cd/etc/ansible/roles/saveconfig/default/
vi main.yml

---
  backupdir: /etc/ansible/backup

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


cd/etc/ansible/roles/saveconfig/tasks/
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'
    ios_command:
      provider: "{{provider}}"
      authorize: yes
      commands:
        - show run
    register: config

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

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

# get the latest file attributes if the folder is not empty
  - name: get the latest old file
    set_fact:
      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
    stat:
      path: "{{latest_file.path}}"
    register: oldconfig_stat
    when: found_files.matched != 0

# save the new config file to folder
  - name: save output to {{backupdir}}
    copy:
      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
    stat:
      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
    file:
      state: absent
      path: "{{backupdir}}/{{inventory_hostname}}/config_{{inventory_hostname}}_{{time.stdout}}.txt"
    when:
      - 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


Conclusion

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...