Backup automatizado de switches con python (versión 2)

Buenas tardes.

Tal y como ya publiqué en la entrada que podéis leer aquí, tengo un script de python para realizar backup automatizados de los switches HP Procurve (ahora Aruba).

Os dejo por aquí la segunda versión del script, ya que lo he modificado para que se puedan hacer backups de todos los switches sea cual sea su pantalla de login.

Cada switch pide una cosa distinta al conectar por telnet: unos nada más conectar piden usuario y password, otros sólo piden password, otros hay que pusar enter antes de que te pida user y password, o sólo password…

Con éste script se solucionan todas las combinaciones posibles (recordad modificar la indentación del texto…).

Un saludo.


#!/usr/bin/python

import telnetlib
import datetime
import time
import os
import sys
import subprocess
import zipfile
#import tftpy

now=datetime.datetime.now()

os.mkdir("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y"))

listado=[]
respuesta=""
index=-1

with open("/home/oscar/Backup_Switches/lista","r") as origen:
for line in origen:
listado.append(line[:-1])

for elemento in listado:

datos=elemento.split(",")

host = datos[0]
tn=telnetlib.Telnet(host)
print "Conectado a " + host + " (" + datos[1] + ")"
time.sleep(2)
respuesta=tn.read_very_eager()
index=respuesta.find("Username:")
if index!=-1:
tn.write(datos[2] + "\n")
time.sleep(2)
tn.read_until("Password:")
tn.write(datos[3] + "\n")
time.sleep(2)
else:
tn.write("\n")
time.sleep(2)
if datos[2]!="":
prueba=tn.read_very_eager()
index1=prueba.find("Username:")
if index1!=-1:
#tn.read_until("Username:")
tn.write(datos[2] + "\n")
time.sleep(2)
tn.read_until("Password:")
tn.write(datos[3] + "\n")
time.sleep(2)
else:
tn.write(datos[3] + "\n")
time.sleep(2)
tn.read_until(str(datos[1]) + "#")
tn.write("terminal length 1000\n")
tn.write("show run\n")
time.sleep(2)
tn.write("exit\n")
time.sleep(2)
tn.write("exit\n")
time.sleep(2)
tn.write("y")
output = tn.read_all()
tn.close()
filename = "tmp"
fp=open(filename,"w")
fp.write(output + "\n")
fp.close()
with open("tmp") as myfile:
suma = sum(1 for line in myfile)
myfile.close()
contador = 1
with open("tmp","r") as input:
with open("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y") + "/backup_" + datos[0] + "_" + now.strftime("%d%m%Y") + "_" + now.strftime("%H%M") + ".txt","wb") as output:
for line in input:
if contador!=1 and contador!=suma and contador!=suma-1:
output.write(line)
contador=contador+1
input.close()
output.close()
os.remove("tmp")

zf=zipfile.ZipFile("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y") + ".zip", "w")
for dirname, subdirs, files in os.walk("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y")):
zf.write(dirname)
for filename in files:
zf.write(os.path.join(dirname,filename))
zf.close()

for root, dirs, files in os.walk("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y"), topdown=False):
for name in files:
os.remove(os.path.join(root,name))
for name in dirs:
os.rmdir(os.path.join(root, name))
os.rmdir("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y"))

origen.close()
sys.exit()

Backup automatizado de switches HP ProCurve con Python

Buenos días.

Hoy os traigo otro nuevo avance en mi empeño por hacer cosas con Python.

En la empresa vamos ya por 42 switches gestionables en nuestra red (sólo en la localización de mi oficina y sólo los gestionables…), y no paramos de crecer y ampliarla. Ésto está muy bien y es divertido para los que nos gusta jugar con redes cableadas, inalámbricas y de fibra óptica, pero acaba dando algún que otro susto cuando se te olvida hacer backup de la configuración de alguno de ellos después de haber modificado esa vlan que era tan importante.

Como no tenemos mucho tiempo para realizar esas tareas y, la mitad de las veces se nos va el santo al cielo con la siguiente urgencia y no nos acordamos de hacerlo, decidí crear un script en Python (aprovechando que me cambié el ordenador de la oficina de Windows Server 2008 R2 a Ubuntu 14.04) que realizase la tarea por mí periódicamente.

La entrada hace referencia a switches “HP ProCurve” en concreto, ya que los 42 que tengo son de la misma familia, aunque es fácilmente modificable para aplicarlo a cualquier tipo de switch o dispositivo que sea accesible por telnet u otro protocolo similar vía consola.

Al final, ha quedado una cosa bastante curiosa que me gustaría compartir con vosotros (aunque ya sé que mi código no es el más depurado).

El script lo que hace básicamente es:

1.- Crea una carpeta nueva “Backup_Switches_DDMMYY” en la carpeta de Backups.

2.- Se va conectando por telnet a una lista de switches configurados en un archivo a tal efecto y va copiando el resultado del comando “show run”.

3.- Tiene en cuenta si el switch no tiene contraseña, si tiene contraseña, si hay que pulsar Intro o no hay que pulsarlo para acceder a la configuración. Funciona con todas las combinaciones posibles (entre tantos modelos tengo todas las variantes…). Ésto es porque hay switches que acceden directamente a la pantalla de “user” y “password”, en otros pone “Pulse Intro para continuar” y al pulsarlo es cuando te pregunta “user” y “password”… los que no piden contraseña y acceden directamente al prompt, los que no piden contraseña pero hay que pulsar Intro para acceder al prompt…

4.- Vuelca el contenido de la configuración en un archivo “Backup_IP_DDMMYY_HHMM.txt” dentro de dicha carpeta y lo modifica un poco (eliminando la primera y última líneas del archivo por ejemplo, que traen texto innecesario).

5.- Una vez se han tratado todos los switches de la lista, comprime la carpeta en formato “.zip” y elimina la carpeta con los archivos de configuración, dejando sólo el archivo comprimido.

6.- Si observáis el script, tengo comentada la librería y las líneas de código para hacer que suba los archivos a un TFTP, ya que es como lo ejecutaba al principio. Desde un qemu emulando una Raspberry a un TFTP que tenía en mi ordenador. Se puede hacer que lo suba a un TFTP, FTP, Mega, Dropbox, Drive… o lo que se os ocurra y se pueda programar en Python (vamos, casi todo…).

7.- Se puede programar con cron para que se ejecute cada día, semana, mes…

Pantalla de ejecución del script (conexión a los 2 primeros switches):

ejecucion_switches

Carpeta con la fecha para ir guardando los archivos individuales:

carpeta_switches

Detalle de los archivos de backup (los mismos 2 primeros switches):

archivos_switches

Lo único que necesita el script para trabajar es un archivo en el mismo directorio llamado “lista”, que contiene los datos necesarios para conectarse y obtener la configuración de los switches.

Se configura un switch por línea, y sólo es necesario 4 parámetros por switch (mínimo 2 obligatorios, máximo 4).

Los parámetros son: IP, hostname, [usuario, password]

En el siguiente ejemplo, el primer switch tiene como usuario “usuario” y como contraseña “password”, y el segundo no tiene usuario ni contraseña (nótese que tiene que estar la coma igualmente).

Archivo “lista”

192.168.46.181,HP ProCurve Switch 5308xl,usuario,password
192.168.38.182,SALANUEVA,,

Archivo “Backup_Switches.py”

#!/usr/bin/python

import telnetlib
import datetime
import time
import os
import sys
import subprocess
import zipfile
#import tftpy

now=datetime.datetime.now()

os.mkdir("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y"))

listado=[]
respuesta=""
index=-1

with open("lista","r") as origen:
	for line in origen:
		listado.append(line[:-1])

for elemento in listado:

	datos=elemento.split(",")

	host = datos[0]
	tn=telnetlib.Telnet(host)
	print "Conectado a " + host + " (" + datos[1] + ")"
	time.sleep(2)
	respuesta=tn.read_very_eager()
	index=respuesta.find("Username:")
	if index!=-1:
		tn.write(datos[2] + "\n")
		time.sleep(2)
		tn.read_until("Password:")
		tn.write(datos[3] + "\n")
		time.sleep(2)
	else:
		tn.write("\n")
		time.sleep(2)
		if datos[2]!="":
			tn.read_until("Username:")
			tn.write(datos[2] + "\n")
			time.sleep(2)
			tn.read_until("Password:")
			tn.write(datos[3] + "\n")
			time.sleep(2)
	tn.read_until(str(datos[1]) + "#")
	tn.write("terminal length 1000\n")
	tn.write("show run\n")
	time.sleep(2)
	tn.write("exit\n")
	time.sleep(2)
	tn.write("exit\n")
	time.sleep(2)
	tn.write("y")
	output = tn.read_all()
	tn.close()
	filename = "tmp"
	fp=open(filename,"w")
	fp.write(output + "\n")
	fp.close()
	with open("tmp") as myfile:
		suma = sum(1 for line in myfile)
	myfile.close()
	contador = 1
	with open("tmp","r") as input:
		with open("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y") + "/backup_" + datos[0] + "_" + now.strftime("%d%m%Y") + "_" + now.strftime("%H%M") + ".txt","wb") as output:
			for line in input:
				if contador!=1 and contador!=suma and contador!=suma-1:
					output.write(line)
				contador=contador+1
	input.close()
	output.close()	
	os.remove("tmp")

zf=zipfile.ZipFile("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y") + ".zip", "w")
for dirname, subdirs, files in os.walk("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y")):
	zf.write(dirname)
	for filename in files:
		zf.write(os.path.join(dirname,filename))
zf.close()

for root, dirs, files in os.walk("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y"), topdown=False):
	for name in files:
        	os.remove(os.path.join(root,name))
	for name in dirs:
                os.rmdir(os.path.join(root, name))
os.rmdir("/media/oscar/ALMACEN/Backups_Switches/Backup_Switches_" + now.strftime("%d%m%Y"))

origen.close()
sys.exit()

#client = tftpy.TftpClient("192.168.46.45",69)
#client.upload("backup_" + datos[0] + "_" + now.strftime("%d%m%Y") + "_" + now.strftime("%H%M") + ".txt","/home/pi/SAVE/backup")
#subprocess.call(["rm","backup"])

Espero vuestros comentarios así como las mejoras que se os ocurran (así las puedo implementar en producción yo también ;-D).

Un saludo y hasta la próxima.