Backup automático de switches Cisco con Ansible

Buenos días a tod@as!!

En el post de hoy, voy a dejaros un pequeño playbook que estoy utilizando para realizar backups automaticamente de algunas configuraciones de switches cisco, tanto de la gama Catalyst (IOS) como Nexus (NXOS)

Lo primero que necesitaremos es disponer del fichero de inventario correspondiente, con todas las IPs y variables que necesitaremos mas adelante en el playbook.

Inventario

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
all:vars]
ansible_connection=local

[CPD-1:vars]
username=admin
password=MySuperSecretPassword
backup_folder=/etc/ansible/00-backups-nexus/
cisco_os=nxos

[CPD-2:vars]
username=admin
password=MySuperSecretPassword
backup_folder=/etc/ansible/00-backups-nexus/
cisco_os=nxos

[CPD-3:vars]
username=admin
password=MySuperSecretPassword
backup_folder=/etc/ansible/00-backups-nexus/
cisco_os=nxos

[CPD-4:vars]
username=admin
password=MySuperSecretPassword
backup_folder=/etc/ansible/00-backups-catalyst/
cisco_os=ios

[CPD-1]
NX1-CPD1 host=10.30.30.76
NX2-CPD1 host=10.30.30.75

[CPD-2]
URNX01 host=10.30.30.110
URNX02 host=10.30.30.111
URNX03 host=10.30.30.112
URNX04 host=10.30.30.113

[CPD-3]
CPD3-N5K01 host=10.69.69.220
CPD3-N5K02 host=10.69.69.221
CPD3-N5K01 host=10.69.69.120
CPD3-N5K02 host=10.69.69.121

[CPD-4]
CONTROL01 host=10.30.30.181

¿Qué son estas variables?

En este inventario, tendremos que definir las siguientes variables:

  • host La IP de management del SW

  • username Usuario con privilegios para ejecutar comandos

  • password Contraseña del usuario proporcionado en la variable anterior

  • backup_folder Ruta que se creará y donde se almacenaran los ficheros con la información que devuelvan los comandos

  • cisco_os SO que tienen nuestros SW, utilizaremos esta variable como condicional para ejecutar comandos ios o nxos.

En mi caso, el fichero de inventario se llama cisco (lo sé, soy muy original..)

El playbook

A continuacion os paso el playbook cisco_backup.yml e intento explicar que hace cada play:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
---

- hosts: "{{ sw }}"
  gather_facts: no
  ignore_errors: yes
  serial: 1
  vars:
    creds:
      host: "{{ host }}"
      username: "{{ username }}"
      password: "{{ password }}"
  tasks:
    - name: Create root directory if don't exist
      file:
        path: "{{ backup_folder }}"
        state: directory
        mode: 0755
    
    - name: Create individual device folder if don't exist
      file:
        path: "{{ backup_folder }}{{ inventory_hostname }}"
        state: directory
        mode: 0755

    - name: Register timestamp variable
      local_action: command date +%Y%m%d-%H:%M
      register: timestamp

    - name: Execute IOS commands
      ios_command:
        provider: "{{ creds }}"
        commands: "{{ item  }}"
      register: commands_output
      with_items:
        - show run
        - write
        - show vlan
        - show interfaces status
        - show etherchannel summary
        - show logging
        - show version
        - show spanning-tree
        - show spanning-tree blockedports
      when: 
        - cisco_os == 'ios'
    
    - name: Create IOS command folder if don't exist
      file:
        path: "{{ backup_folder }}{{ inventory_hostname }}/{{ commands_output.results[item].item }}"
        state: directory
        mode: 0755
      with_items:
        - 0
        - 1
        - 2 
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
      when:
        - cisco_os == 'ios'
    
    - name: Save IOS command output on destination file
      copy:
        content: "{{ commands_output.results[item].stdout[0] }}"
        dest:  "{{ backup_folder }}{{ inventory_hostname }}/{{ commands_output.results[item].item }}/{{ inventory_hostname }}_{{ commands_output.results[item].item }}_{{ timestamp.stdout }}.txt"
      with_items:
        - 0
        - 1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8 
      when:
        - cisco_os == 'ios'


    - name: Execute NXOS commands
      nxos_command:
        provider: "{{ creds }}"
        commands: "{{ item  }}"
      register: commands_output
      with_items:
        - show run
        - show vlan
        - show interface status
        - show interface brief
        - show port-channel summary
        - show vpc
        - show vpc peer-keepalive
        - show logging last 100
        - copy r s
        - show version
        - show spanning-tree
        - show spanning-tree blockedports
        - show vpc consistency-parameters global
        - show cdp neighbors
        - show flogi database
        - show zoneset active
        - show fcdomain vsan 13 #Fabric1 URNIETA
        - show fcdomain vsan 24 #Fabric2 URNIETA
        - show fcdomain vsan 10 #Fabric1 TA-SA
        - show fcdomain vsan 20 #Fabric2 TA-SA
      when: 
        - cisco_os == 'nxos'

    - name: Create NXOS command folder if don't exist
      file:
        path: "{{ backup_folder }}{{ inventory_hostname }}/{{ commands_output.results[item].item }}"
        state: directory
        mode: 0755
      with_items:
        - 0
        - 1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        - 10
        - 11
        - 12
        - 13
        - 14
        - 15
        - 16
        - 17
        - 18
        - 19
      when:
        - cisco_os == 'nxos' 

    - name: Save NXOS command output on destination file
      copy:
        content: "{{ commands_output.results[item].stdout[0] }}"
        dest:  "{{ backup_folder }}{{ inventory_hostname }}/{{ commands_output.results[item].item }}/{{ inventory_hostname }}_{{ commands_output.results[item].item }}_{{ timestamp.stdout }}.txt"
      with_items:
        - 0
        - 1 
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        - 10
        - 11
        - 12
        - 13
        - 14
        - 15
        - 16
        - 17
        - 18
        - 19
      when:
        - cisco_os == 'nxos'

¿Qué hace cada play?

  • Create root directory if don't exist Nos creará la carpeta que utilizaremos como raíz para guardar los backups. La variable estará definida en el fichero de inventario.

  • Create individual device folder if don't exist En caso de que no exista, dentro del root directory, nos creará una carpeta con el nombre de cada SW

  • Register timestamp variable Simplemente creará una variable para guardar una marca temporal

  • Execute IOS commands Aquí es donde ejecutamos todos los comandos IOS sobre nuestros SW y guardamos los resultados en una variable.

  • Create IOS command folder if don't exist Dentro de la carpeta de cada SW, crearemos otra carpeta con el nombre del comando ejecutado previamente.

  • Save IOS command output on destination file Guardamos el valor de la variale (dónde está la salida de cada comando) en un fichero .txt en la carpeta formada por /root_dorectory/nombre_sw/nombre_comando/nombre_sw_nombre_comando_timestamp.txt

  • Execute NXOS commands Lo mismo que hemos explicado para IOS

  • Create NXOS command folder if don't exist Lo mismo que hemos explicado para IOS

  • Save NXOS command output on destination file Lo mismo que hemos explicado para IOS

¿Y ahora, cómo lo ejecuto?

Para ejecutar este playbook, lo llamaremos de la siguiente manera:

ansible-playbook /etc/ansible/playbooks/cisco_backup.yml -i /etc/ansible/inventory/cisco -e "sw=nombre_sw_o_grupo"

la variable sw hace raferencia a los equipos o grupos que hemos definido en el fichero de inventario. Por ejemplon CPD-1

¿Y si lo quiero programar periodicamente?

Y si queremos programarlo, lo añadiremos al cron de nuestro usuario tal que así:

crontab

Los resultados

Finalmente, así quedaria nuestra estructura de carpetas con los correspondientes .txt que guardan la salida de la ejecución de cada comando.

output-backup-nexus

En un próximo post, veremos como visualizar facilmente esta información a través de un navegador web ;-)

Espero que os sirva.

Un saludo!

Miquel.

0%