TextFSM y Netmiko.

TextFSM es un módulo de Python que permite parsear texto semiformateado. TextFSM soporta la salida de múltiples comandos para equipos de redes de diferentes fabricantes. TextFSM requiere como entrada el   resultado de un comando (texto) y un template, que contiene las expresiones regulares necesarias para poder parsear el texto y devolver la información en un formato mas fácil de procesar. Cada template se corresponde con la salida de un comando específico. Para mayor información visitar la web de .

Netmiko es una libreria de redes multivendedores basada en Paramiko, que es una libreria estandar para las conexiones ssh Python. Con Netmiko como base, se pueden realizar programas y scripts que faciliten y mejoren la administracion de los equipos de redes. Netmiko incluye como opcion el uso de TextFSM para parsear la salida de los comandos y facilitar su uso posterior. Para mayor informacion visitar la web de Netmiko.

Objetivo: utilizar Netmiko para realizar la conexion a un router Cisco y TextFSM para pasear el resultado de los comandos.

Topología:
PC (tap0 – 192.168.46.1/24) <—>  (Eth0/0 – 192.168.46.2/24) router Cisco.

Escenario1: Netmiko con TextFSM.
Notas:

– Se utiliza Python3 y Netmiko 2.1.1. Para instalar la librería Netmiko utilizar pip install netmiko.
– Para utilizar TextFSM con Nemiko hay seguir una serie de pasos previos:
1ro – Crear la carpeta ntc_templates, dentro de la misma crear la carpeta templates.
2do – Del sitio de TextFSM en Github descargar el template correspondiente a la plataforma (Cisco) y al comando a utilizar (en este caso “show interfaces”)
3ro –  Del mismo sitio, descargar el fichero index y ponerlo dentro de la carpeta templates. También se puede crear el fichero, que debe tener como mínimo el siguiente contenido:

# First line is the header fields for columns and is mandatory.
# Regular expressions are supported in all fields except the first.
# Last field supports variable length command completion.
# abc[[xyz]] is expanded to abc(x(y(z)?)?)?, regexp inside [[]] is not supported
#
Template, Hostname, Vendor, Command
cisco_ios_show_interfaces.template, .*, Cisco, sh[[ow]] interfaces

4to – Ubicar la carpeta ntc_templates en el directorio home. Tambien se puede ubicar la carpeta en cualquier otro lugar, pero hay en setear la environment variable NET_TEXTFSM (export NET_TEXTFSM=/path/to/ntc-templates/templates/)

Codigo (netmiko1.py):

from netmiko import Netmiko
# getpass es una librería que permite preguntar por el password
from getpass import getpass
password = getpass()
my_device = {
 ’host’: “192.168.46.2”,
 ’username’: “pyclass”,
 ’password’: password,
 ’secret’: password,
 ’device_type’: “cisco_ios”
}
# crear la conexión de red con los datos del dispositivo (my_device)
net_connect = Netmiko(**my_device)
# send_command permite enviar un comando al router, en este caso “show interfaces”. La opción  use_textfsm es habilitada, por lo que el resultado del comando será parseado y devolverá una lista de diccionarios. Este formato facilita la manipulación de los datos y evita utilizar comandos y expresiones regulares adicionales.
output = net_connect.send_command(“show interfaces”, use_textfsm=True)
print(output)
# el resto del codigo permite realizar una mejor vizualizacion del resultado.
for i, elem in enumerate(output):
 print(“Interface {}”.format(i))
 for k, v in elem.items():
  print(“\t{}: {}”.format(k, v))

– Resultado sin el uso de la opcion TextFSM:
Ethernet0/0 is up, line protocol is up
 Hardware is AmdP2, address is 0203.e800.0a00 (bia 0203.e800.0a00)
 Internet address is 192.168.46.2/24
 MTU 1500 bytes, BW 10000 Kbit/sec, DLY 1000 usec,
 reliability 255/255, txload 1/255, rxload 1/255
 Encapsulation ARPA, loopback not set
 Keepalive set (10 sec)
 ARP type: ARPA, ARP Timeout 04:00:00
 Last input 00:00:00, output 00:00:00, output hang never
 Last clearing of “show interface” counters never
 Input queue: 1/75/0/0 (size/max/drops/flushes); Total output drops: 0
 Queueing strategy: fifo
 Output queue: 0/40 (size/max)
 5 minute input rate 1000 bits/sec, 1 packets/sec
 5 minute output rate 1000 bits/sec, 1 packets/sec
  2718 packets input, 285866 bytes, 0 no buffer
  Received 735 broadcasts (23 IP multicasts)
  0 runts, 0 giants, 0 throttles
  0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
  0 input packets with dribble condition detected
  4745 packets output, 613828 bytes, 0 underruns
  0 output errors, 0 collisions, 1 interface resets
  33 unknown protocol drops
  0 babbles, 0 late collision, 0 deferred
  0 lost carrier, 0 no carrier
  0 output buffer failures, 0 output buffers swapped out
Ethernet0/1 is administratively down, line protocol is down
 Hardware is AmdP2, address is aabb.cc00.0a10 (bia aabb.cc00.0a10)
 MTU 1500 bytes, BW 10000 Kbit/sec, DLY 1000 usec,
 reliability 255/255, txload 1/255, rxload 1/255
 Encapsulation ARPA, loopback not set
 Keepalive set (10 sec)
 ARP type: ARPA, ARP Timeout 04:00:00
 Last input never, output never, output hang never
 Last clearing of “show interface” counters never
 Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
 Queueing strategy: fifo
 Output queue: 0/40 (size/max)
 5 minute input rate 0 bits/sec, 0 packets/sec
 5 minute output rate 0 bits/sec, 0 packets/sec
  0 packets input, 0 bytes, 0 no buffer
  Received 0 broadcasts (0 IP multicasts)
  0 runts, 0 giants, 0 throttles
  0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
  0 input packets with dribble condition detected
  0 packets output, 0 bytes, 0 underruns
  0 output errors, 0 collisions, 0 interface resets
  0 unknown protocol drops
  0 babbles, 0 late collision, 0 deferred
  0 lost carrier, 0 no carrier
  0 output buffer failures, 0 output buffers swapped out

– Resultado con el uso de la opcion TextFSM:
[{‘address’: ‘0203.e800.0a00’, ‘mtu’: ‘1500’, ‘input_rate’: ‘1000’, ‘duplex’: ”, ‘delay’: ‘1000 usec’, ‘protocol_status’: ‘up ‘, ‘description’: ”, ‘bia’: ‘0203.e800.0a00’, ‘encapsulation’: ‘ARPA’, ‘queue_strategy’: ‘fifo’, ‘ip_address’: ‘192.168.46.2/24’, ‘bandwidth’: ‘10000 Kbit’, ‘speed’: ”, ‘hardware_type’: ‘AmdP2’, ‘interface’: ‘Ethernet0/0’, ‘link_status’: ‘up’, ‘output_rate’: ‘1000’}, {‘address’: ‘aabb.cc00.0a10’, ‘mtu’: ‘1500’, ‘input_rate’: ‘0’, ‘duplex’: ”, ‘delay’: ‘1000 usec’, ‘protocol_status’: ‘down ‘, ‘description’: ”, ‘bia’: ‘aabb.cc00.0a10’, ‘encapsulation’: ‘ARPA’, ‘queue_strategy’: ‘fifo’, ‘ip_address’: ”, ‘bandwidth’: ‘10000 Kbit’, ‘speed’: ”, ‘hardware_type’: ‘AmdP2’, ‘interface’: ‘Ethernet0/1’, ‘link_status’: ‘administratively’, ‘output_rate’: ‘0’}, {‘address’: ‘aabb.cc00.0a20’, ‘mtu’: ‘1500’, ‘input_rate’: ‘0’, ‘duplex’: ”, ‘delay’: ‘1000 usec’, ‘protocol_status’: ‘down ‘, ‘description’: ”, ‘bia’: ‘aabb.cc00.0a20’, ‘encapsulation’: ‘ARPA’, ‘queue_strategy’: ‘fifo’, ‘ip_address’: ”, ‘bandwidth’: ‘10000 Kbit’, ‘speed’: ”, ‘hardware_type’: ‘AmdP2’, ‘interface’: ‘Ethernet0/2’, ‘link_status’: ‘administratively’, ‘output_rate’: ‘0’}, {‘address’: ‘aabb.cc00.0a30’, ‘mtu’: ‘1500’, ‘input_rate’: ‘0’, ‘duplex’: ”, ‘delay’: ‘1000 usec’, ‘protocol_status’: ‘down ‘, ‘description’: ”, ‘bia’: ‘aabb.cc00.0a30’, ‘encapsulation’: ‘ARPA’, ‘queue_strategy’: ‘fifo’, ‘ip_address’: ”, ‘bandwidth’: ‘10000 Kbit’, ‘speed’: ”, ‘hardware_type’: ‘AmdP2’, ‘interface’: ‘Ethernet0/3’, ‘link_status’: ‘administratively’, ‘output_rate’: ‘0’}]

Este resultado mejora la consulta sobre los datos. Por ejemplo, para saber la dirección ip de cada interface se puede añadir el siguiente codigo al script:

for interface in output:
 print(“{}: {}”.format(interface[‘interface’], (interface[‘ip_address’])))

– Resultado:
Ethernet0/0: 192.168.46.2/24
Ethernet0/1:
Ethernet0/2:
Ethernet0/3:

Escenario2: TextFSM.

Si tenemos el resultado del comando “show interfaces” y no queremos utilizar Netmiko, podemos utilizar el modulo TextFSM para parsearlo. TextFSM devuelve el resultado parseado en forma de tabla.

Codigo (netmiko1.py):
# importar el modulo textfsm (primero instalar pip install textfsm)
import textfsm
template = open(“/home/xxx/ntc-templates/templates/cisco_ios_show_interfaces.template”)
re_table = textfsm.TextFSM(template)
data = re_table.ParseText(raw_cmd_data)
# Display result as CSV
# First the column headers
print(‘, ‘.join(re_table.header))
# Each row of the table
for row in data:
 print(‘, ‘.join(row))

– Resultado:
INTERFACE, LINK_STATUS, PROTOCOL_STATUS, HARDWARE_TYPE, ADDRESS, BIA, DESCRIPTION, IP_ADDRESS, MTU, DUPLEX, SPEED, BANDWIDTH, DELAY, ENCAPSULATION, QUEUE_STRATEGY, INPUT_RATE, OUTPUT_RATE
Ethernet0/0, up, up , AmdP2, 0203.e800.0a00, 0203.e800.0a00, , 192.168.46.2/24, 1500, , , 10000 Kbit, 1000 usec, ARPA, fifo, 1000, 1000
Ethernet0/1, administratively, down , AmdP2, aabb.cc00.0a10, aabb.cc00.0a10, , , 1500, , , 10000 Kbit, 1000 usec, ARPA, fifo, 0, 0
Ethernet0/2, administratively, down , AmdP2, aabb.cc00.0a20, aabb.cc00.0a20, , , 1500, , , 10000 Kbit, 1000 usec, ARPA, fifo, 0, 0
Ethernet0/3, administratively, down , AmdP2, aabb.cc00.0a30, aabb.cc00.0a30, , , 1500, , , 10000 Kbit, 1000 usec, ARPA, fifo, 0, 0

Si queremos un resultado similar al obtenido con Netmiko y TextFSM, podemos añadir este código y obtener una lista de diccionarios correspondientes a cada interface.

output = []
for row in data:
 obj = {}
 for i, header in enumerate(re_table.header):
  obj[header] = row[i]
  output.append(obj)
print(output)

– Resultado:
[{‘BIA’: ‘0203.e800.0a00’, ‘ADDRESS’: ‘0203.e800.0a00’, ‘QUEUE_STRATEGY’: ‘fifo’, ‘LINK_STATUS’: ‘up’, ‘DELAY’: ‘1000 usec’, ‘HARDWARE_TYPE’: ‘AmdP2’, ‘INTERFACE’: ‘Ethernet0/0’, ‘DUPLEX’: ”, ‘IP_ADDRESS’: ‘192.168.46.2/24’, ‘MTU’: ‘1500’, ‘PROTOCOL_STATUS’: ‘up ‘, ‘BANDWIDTH’: ‘10000 Kbit’, ‘DESCRIPTION’: ”, ‘ENCAPSULATION’: ‘ARPA’, ‘OUTPUT_RATE’: ‘1000’, ‘SPEED’: ”, ‘INPUT_RATE’: ‘1000’}, {‘BIA’: ‘aabb.cc00.0a10’, ‘ADDRESS’: ‘aabb.cc00.0a10’, ‘QUEUE_STRATEGY’: ‘fifo’, ‘LINK_STATUS’: ‘administratively’, ‘DELAY’: ‘1000 usec’, ‘HARDWARE_TYPE’: ‘AmdP2’, ‘INTERFACE’: ‘Ethernet0/1’, ‘DUPLEX’: ”, ‘IP_ADDRESS’: ”, ‘MTU’: ‘1500’, ‘PROTOCOL_STATUS’: ‘down ‘, ‘BANDWIDTH’: ‘10000 Kbit’, ‘DESCRIPTION’: ”, ‘ENCAPSULATION’: ‘ARPA’, ‘OUTPUT_RATE’: ‘0’, ‘SPEED’: ”, ‘INPUT_RATE’: ‘0’}, {‘BIA’: ‘aabb.cc00.0a20’, ‘ADDRESS’: ‘aabb.cc00.0a20’, ‘QUEUE_STRATEGY’: ‘fifo’, ‘LINK_STATUS’: ‘administratively’, ‘DELAY’: ‘1000 usec’, ‘HARDWARE_TYPE’: ‘AmdP2’, ‘INTERFACE’: ‘Ethernet0/2’, ‘DUPLEX’: ”, ‘IP_ADDRESS’: ”, ‘MTU’: ‘1500’, ‘PROTOCOL_STATUS’: ‘down ‘, ‘BANDWIDTH’: ‘10000 Kbit’, ‘DESCRIPTION’: ”, ‘ENCAPSULATION’: ‘ARPA’, ‘OUTPUT_RATE’: ‘0’, ‘SPEED’: ”, ‘INPUT_RATE’: ‘0’}, {‘BIA’: ‘aabb.cc00.0a30’, ‘ADDRESS’: ‘aabb.cc00.0a30’, ‘QUEUE_STRATEGY’: ‘fifo’, ‘LINK_STATUS’: ‘administratively’, ‘DELAY’: ‘1000 usec’, ‘HARDWARE_TYPE’: ‘AmdP2’, ‘INTERFACE’: ‘Ethernet0/3’, ‘DUPLEX’: ”, ‘IP_ADDRESS’: ”, ‘MTU’: ‘1500’, ‘PROTOCOL_STATUS’: ‘down ‘, ‘BANDWIDTH’: ‘10000 Kbit’, ‘DESCRIPTION’: ”, ‘ENCAPSULATION’: ‘ARPA’, ‘OUTPUT_RATE’: ‘0’, ‘SPEED’: ”, ‘INPUT_RATE’: ‘0’}]

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.