La automatización de tareas en redes se ha vuelto fundamental para la eficiencia operativa. Python, junto con librerías especializadas como Netmiko, ofrece una solución robusta para interactuar con dispositivos de red. Este artículo explora cómo utilizar Netmiko para dos tareas comunes: la recopilación de información de transceptores ópticos, incluyendo sus números de serie (SN), y la realización de copias de seguridad de las configuraciones de los dispositivos.
Para la interacción con los dispositivos, se requiere un archivo ip_list.csv que contenga una lista de los dispositivos. Cada línea de este archivo debe tener el formato tipo_dispositivo,direccion_ip. Por ejemplo:
huawei,192.168.1.1
cisco_ios,192.168.1.2
h3c_comware,192.168.1.3
- Recopilación de Información de Módulos Ópticos
Esta función se encarga de conectar a los dispositivos de red especificados para extraer los números de serie (SN) de los módulos transceptores ópticos y las interfaces a las que están asociados. Los datos recopilados se organizan y se guardan en un archivo de Excel (.xls).
import os
from netmiko import ConnectHandler
import xlwt # xlwt se utiliza para generar archivos .xls
# Definición de las columnas para el archivo Excel
COL_IP = 0
COL_INTERFACE = 1
COL_TYPE = 2
COL_PN = 3
COL_SN = 4
def recopilar_informacion_opticos():
"""
Se conecta a dispositivos de red para recopilar números de serie (SN)
de módulos transceptores ópticos y sus interfaces,
guardando la información en un archivo Excel.
"""
print('-*- Por favor, ingrese el usuario y la contraseña de inicio de sesión del dispositivo -*-')
nombre_usuario = input('Usuario: ')
contrasena = input('Contraseña: ')
libro_excel = xlwt.Workbook()
hoja_datos = libro_excel.add_sheet('Datos de Módulos Ópticos')
hoja_datos.write(0, COL_IP, 'IP')
hoja_datos.write(0, COL_INTERFACE, 'Interfaz')
hoja_datos.write(0, COL_TYPE, 'Tipo')
hoja_datos.write(0, COL_PN, 'PN')
hoja_datos.write(0, COL_SN, 'SN')
print('Hoja de Excel creada con éxito!')
# Fila inicial para escribir datos en Excel, se actualiza globalmente
fila_inicial_escritura = 1
try:
with open(r".\ip_list.csv", encoding='utf-8') as archivo_dispositivos:
lineas_dispositivos = archivo_dispositivos.readlines()
except FileNotFoundError:
print("Error: El archivo 'ip_list.csv' no fue encontrado. Asegúrese de que existe en el mismo directorio.")
return
for info_linea in lineas_dispositivos:
detalles_dispositivo = info_linea.strip().split(',')
if len(detalles_dispositivo) < 2:
print(f"Advertencia: Línea inválida en ip_list.csv: '{info_linea.strip()}'. Saltando.")
continue
tipo_os = detalles_dispositivo[0].strip()
direccion_ip = detalles_dispositivo[1].strip()
config_dispositivo = {
"device_type": tipo_os,
"host": direccion_ip,
"port": "22",
"username": nombre_usuario,
"password": contrasena
}
print(f'\n>>> Iniciando procesamiento para {direccion_ip} <<<')
try:
with ConnectHandler(**config_dispositivo) as conexion:
print(f'{direccion_ip} Inicio de sesión exitoso. Por favor, espere...')
# Recopilar números de serie (SN)
# Comando modificado para ser más general, asumiendo salida tipo Huawei/H3C
output_sn = conexion.send_command_timing('display transceiver interface verbose')
if '---- More ----' in output_sn:
output_sn += conexion.send_command_timing(' ', normalize=False)
sn_list = []
interface_list = []
current_interface = 'N/A'
for linea in output_sn.splitlines():
linea_limpia = linea.strip()
if linea_limpia.startswith('Interface:'):
current_interface = linea_limpia.split(':', 1)[1].strip()
elif 'Serial Number' in linea_limpia:
sn_part = linea_limpia.split(':', 1)[1].strip()
sn_list.append(sn_part)
interface_list.append(current_interface) # Asociar SN con la interfaz actual
# Escribir los datos combinados en la hoja de Excel
num_entries = len(sn_list)
for i in range(num_entries):
current_row = fila_inicial_escritura + i
hoja_datos.write(current_row, COL_IP, direccion_ip)
hoja_datos.write(current_row, COL_INTERFACE, interface_list[i])
hoja_datos.write(current_row, COL_SN, sn_list[i])
# Tipo y PN no se recolectan directamente con este comando, se marcan como N/A
hoja_datos.write(current_row, COL_TYPE, 'N/A')
hoja_datos.write(current_row, COL_PN, 'N/A')
if num_entries > 0:
fila_inicial_escritura += num_entries
print(f'Transceptores del switch {direccion_ip}: {num_entries} unidades.')
else:
print(f'No se encontraron transceptores para {direccion_ip}.')
print(f'>>> Procesamiento para {direccion_ip} FINALIZADO <<<')
except Exception as e:
print(f'Ocurrió un error con {direccion_ip}: {e}')
print('**********************************************************')
continue
try:
libro_excel.save(r'.\informe_modulos_opticos.xls')
print(f'\nSe ha generado el informe de módulos ópticos en: informe_modulos_opticos.xls')
except Exception as e:
print(f"Error al guardar el archivo Excel: {e}")
- Copia de Seguridad de Configuraciones
Esta función se encarga de conectar a los dispositivos de red para obtener y guardar su configuración actual. Cada configuración se guarda en un archivo de texto individual dentro de una carpeta designada.
def realizar_copia_seguridad():
"""
Se conecta a dispositivos de red para realizar una copia de seguridad
de sus configuraciones actuales, guardándolas en archivos de texto.
"""
print('-*- Por favor, ingrese el usuario y la contraseña de inicio de sesión del dispositivo -*-')
nombre_usuario = input('Usuario: ')
contrasena = input('Contraseña: ')
directorio_respaldos = r'.\respaldos_config'
if not os.path.exists(directorio_respaldos):
os.makedirs(directorio_respaldos)
print(f"Directorio '{directorio_respaldos}' creado para guardar los respaldos.")
try:
with open(r".\ip_list.csv", encoding='utf-8') as archivo_dispositivos:
lineas_dispositivos = archivo_dispositivos.readlines()
except FileNotFoundError:
print("Error: El archivo 'ip_list.csv' no fue encontrado. Asegúrese de que existe en el mismo directorio.")
return
for info_linea in lineas_dispositivos:
detalles_dispositivo = info_linea.strip().split(',')
if len(detalles_dispositivo) < 2:
print(f"Advertencia: Línea inválida en ip_list.csv: '{info_linea.strip()}'. Saltando.")
continue
tipo_os = detalles_dispositivo[0].strip()
direccion_ip = detalles_dispositivo[1].strip()
config_dispositivo = {
"device_type": tipo_os,
"host": direccion_ip,
"port": "22",
"username": nombre_usuario,
"password": contrasena
}
print(f'\n>>> Iniciando copia de seguridad para {direccion_ip} <<<')
try:
with ConnectHandler(**config_dispositivo) as conexion:
print(f'{direccion_ip} Inicio de sesión exitoso. Recopilando configuración...')
# Se elige el comando de configuración según el tipo de OS
comando_config = 'display current-configuration' if tipo_os.lower() in ['huawei', 'h3c_comware'] else 'show running-config'
configuracion_salida = conexion.send_command_timing(comando_config)
# Manejo de paginación si '---- More ----' está presente (común en Huawei/H3C)
while '---- More ----' in configuracion_salida:
configuracion_salida += conexion.send_command_timing(' ', normalize=False)
# Limpiar indicadores de paginación
configuracion_limpia = configuracion_salida.replace('---- More ----', '').strip()
nombre_archivo = os.path.join(directorio_respaldos, f'{direccion_ip}.txt')
with open(nombre_archivo, 'w', encoding='utf-8') as archivo_config:
archivo_config.write(configuracion_limpia)
print(f'Configuración de {direccion_ip} guardada en {nombre_archivo}')
print(f'>>> Copia de seguridad para {direccion_ip} FINALIZADA <<<')
except Exception as e:
print(f'Ocurrió un error durante la copia de seguridad para {direccion_ip}: {e}')
print('**********************************************************')
continue
- Interfaz de Usuario para Selección de Tareas
El siguiente segmento de código proporciona un menú interactivo en la línea de comanods, permitiendo al usuario elegir entre las tareas de automatización de red implementadas.
def main():
"""
Función principal que presenta un menú al usuario para seleccionar
entre diferentes tareas de automatización de red.
"""
while True:
print('\n--- Selector de Tareas de Automatización de Red ---')
print('[1] Recopilar información de módulos ópticos (SN, Interfaz)')
print('[2] Realizar copia de seguridad de configuraciones')
print('[r] Salir')
opcion_seleccionada = input('>>> Por favor, elija una opción: ').strip().lower()
if opcion_seleccionada == '1':
recopilar_informacion_opticos()
elif opcion_seleccionada == '2':
realizar_copia_seguridad()
elif opcion_seleccionada == 'r':
print('¡Ha salido con éxito! ¡Gracias por usar el programa!')
break
else:
print('Opción inválida. Por favor, intente de nuevo o ingrese "r" para salir.')
if __name__ == '__main__':
main()