Практическое руководство по Netmiko и TextFSM

Практическое руководство по Netmiko и TextFSM

Rick Donato, вольный перевод Emil Garipov

Введение

В этой статье мы рассмотрим два инструмента, используемых в мире сетевой автоматизации - Netmiko и TextFSM.

Наши примеры будут основаны на небольшой топологии, состоящей из 3 устройств Arista, Cisco NXOS9K и маршрутизатора Cisco IOS. Ниже показана топология

Рисунок 1: Топология

Netmiko

Netmiko - это библиотека SSH Python с поддержкой нескольких вендоров, которая упрощает процесс подключения к сетевым устройствам через SSH. Эта библиотека добавляет специфическую логику производителя к paramiko, которая является де-факто SSH библиотекой в Python[1].

Установка

Netmiko может быть установлен через менеджер пакетов Python - pip. Вот так:

  $ pip3 install netmiko

Подключение

Для подключения к устройству мы используем ConnectHandler, которому передаем свои данные подключения. Следующим образом:

from netmiko import ConnectHandler

arista = {
   'device_type': 'arista_eos', 
   'host': '172.29.133.1', 
   'username': 'rick', 
   'password': 'abc123',  
}

cisco = {
   'device_type': 'cisco_ios', 
   'host': '172.29.133.2', 
   'username': 'rick', 
   'password': 'abc123',  
}

nxos = {
   'device_type': 'cisco_nxos', 
   'host': '172.29.133.3', 
   'username': 'rick', 
   'password': 'abc123',  
}

net_connect_arista = ConnectHandler(**arista)
net_connect_cisco = ConnectHandler(**cisco)
net_connect_nxos = ConnectHandler(**nxos)

Вывод на экран

Теперь, когда у нас есть соединение, установленное с нашими устройствами, мы можем начать выполнение некоторых задачи. Небольшая задача, с которой мы можем начать, это отображение диалогового окна для каждого устройства. Следующим образом:

  >>> for device in [net_connect_arista, net_connect_cisco, net_connect_nxos]:
...   device.find_prompt()
...
'veos>'
'viosl3#'
'nxos#'

Отправка команды

Давайте отправим команду на каждое из устройств. Поскольку каждое устройство использует OSPF, давайте проверим таблицу соседей OSPF. Следующим образом:

  >>> for device in [net_connect_arista, net_connect_cisco, net_connect_nxos]:
...   output = device.send_command('show ip ospf neighbor')
...   print("----{}----".format(device))
...   print(output)
...   print("\n")

----<netmiko.arista.arista.AristaSSH object at 0x7f9713239278>----
Neighbor ID  VRF      Pri State      Dead Time   Address     Interface   
2.2.2.2     default   1  FULL/DR     00:00:35    10.1.1.2    Ethernet3

----<netmiko.cisco.cisco_ios.CiscoIosSSH object at 0x7f9713233978>----
Neighbor ID   Pri State     Dead Time   Address      Interface   
3.3.3.3       1  FULL/BDR   0:00:36     10.2.1.1     GigabitEthernet0/2
1.1.1.1       1  FULL/BDR   0:00:37     10.1.1.1     GigabitEthernet0/1

--<netmiko.cisco.cisco_nxos_ssh.CiscoNxosSSH object at 0x7f97132334a8>-
OSPF Process ID 1 VRF default
Total number of neighbors: 1
Neighbor ID   Pri State    UP Time      Address      Interface   
2.2.2.2       1  FULL/DR   04:25:36     10.2.1.2     GigabitEthernet0/2

Обновление конфигурации

Допустим, мы хотим отредактировать/внести изменения в некоторые настройки. Это достигается с помощью метода send_config_set. Этот метод принимает список() команд, которые будут отправлены на устройство.

# pre config
>>> print(net_connect_cisco.send_command('show run | sec ospf'))
router ospf 1
 router-id 2.2.2.2
 redistribute connected subnets
 network 10.1.1.0 0.0.0.255 area 0
 network 10.2.1.0 0.0.0.255 area 0

# update config
>>> output = net_connect_cisco.send_config_set(['router ospf 1', 'no redistribute connected subnets'])
>>> print(output)
config term
Enter configuration commands, one per line. End with CNTL/Z.
viosl3(config)#router ospf 1
viosl3(config-router)#no redistribute connected subnets
viosl3(config-router)#end
viosl3#


# post config
>>> print(net_connect_cisco.send_command('show run | sec ospf'))
router ospf 1
 router-id 2.2.2.2
 network 10.1.1.0 0.0.0.255 area 0
 network 10.2.1.0 0.0.0.255 area 0

TextFSM

TextFSM - это модуль Python, который позволяет брать неструктурированные данные и преобразовывать их в структурированные с помощью наборов шаблонов на основе regex.

Замечательно, что Netmiko обеспечивает прямую интеграцию с TextFSM, которую мы скоро покажем.

Шаблоны TextFSM

Чтобы подготовиться к работе, мы извлечем некоторые предварительно созданные шаблоны из репозитория github:

https://github.com/networktocode/ntc-templates.


root@dekstop:~# git clone https://github.com/networktocode/ntc-templates
Cloning into 'ntc-templates'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 4990 (delta 2), reused 6 (delta 1), pack-reused 4976
Receiving objects: 100% (4990/4990), 1.19 MiB | 2.29 MiB/s, done.
Resolving deltas: 100% (2749/2749), done.
Checking connectivity... done.

Применение TextFSM в Netmiko

Чтобы использовать TextFSM и ранее загруженные шаблоны, мы, как и прежде, просто используем команду send_command, установив атрибут use_textfsm равным True:

>>> from netmiko import ConnectHandler
>>> arista = {
...    'device_type': 'arista_eos',
...    'host': '172.29.133.1',
...    'username': 'rick',
...    'password': 'abc123',
... }

>>> net_connect_arista = ConnectHandler(**arista)

>>> output = net_connect_arista.send_command('sh ver', use_textfsm=True)

Если мы сейчас посмотрим на наш вывод, то увидим, что он теперь структурирован.

>>> import pprint
>>> pprint.pprint(output)
[{'free_memory': '121936',
  'hw_version': '',
  'image': '4.15.10M',
  'model': 'vEOS',
  'serial_number': '',
  'sys_mac': '5000.00d7.ee0b',
  'total_memory': '1897596'}]

>>> output[0]['model']
'vEOS'

Индексный файл

Пример хороший, но откуда Netmiko знает, какой шаблон использовать?

Это достигается с помощью индексного файла, который содержит привязку команд к шаблонам (фрагмент, показанный ниже). По умолчанию Netmiko настроен на автоматический поиск индексного файла в ~/ntc-template/templates/index. Однако его можно изменить на другой путь с помощью переменной окружения NET_TEXTFSM.

...
arista_eos_show_ip_route.template, .*, arista_eos, sh[[ow]] i[[p]] rou[[te]]
arista_eos_show_version.template, .*, arista_eos, sh[[ow]] ver[[sion]]
arista_eos_show_ip_arp.template, .*, arista_eos, sh[[ow]] i[[p]] ar[[p]]
arista_eos_show_ip_bgp.template, .*, arista_eos, sh[[ow]] i[[p]] bg[[p]] 
arista_eos_show_module.template, .*, arista_eos, sh[[ow]] modu[[le]]
...

Создание пользовательских шаблонов

Для создания собственного шаблона необходимо выполнить 2 шага - создание шаблона и обновление индекса. Чтобы продемонстрировать эти шаги, мы создадим шаблон для команды EOS show uptime.

Создание шаблона

Прежде всего, мы создадим новый файл шаблона. Название должно быть основано на следующей схеме:{{ vendor_name }}_{{show_command}}.template. Например, в нашем случае это будет шаблон arista_eos_show_uptime.template. Этот файл будет помещен в ntc-шаблоны/шаблоны.

Ниже показано содержимое шаблона. Различные опции написания шаблона TextFSM выходят за рамки этой статьи. Однако, в двух словах, мы разбиваем наш текст через regex, показанный внизу, используя Values для определения текста, который мы извлечем.

Value TIME (\S+)
Value UPTIME (\S+)
Value USERS (\d+)
Value LOAD_AVERAGE (\S+)
Start
 ^\s${TIME}\s+up\s+${UPTIME}.*${USERS}\s+.*load average.\s+${LOAD_AVERAGE} -> Record

Обновление индекса

Затем файл индекса будет обновлен, чтобы сопоставить наш шаблон с командой (см. ниже). Примечание: Это также позволит сократить время работы команды, например, sh uptime или sh up.

...
arista_eos_show_uptime.template, .*, arista_eos, sh[[ow]] up[[time]]

Тест

Быстрый тест показывает нам вывод команды в исходном состоянии и структурированный с помощью нашего недавно созданного шаблона.

>>> net_connect_arista.send_command('show uptime')
' 19:54:17 up 23 min,  1 user,  load average: 0.15, 0.15, 0.21'

>>> net_connect_arista.send_command('show uptime', use_textfsm=True)
[{'load_average': '0.15,', 'time': '19:54:20', 'users': '1', 'uptime': '23'}]

Подключайтесь к каналу - https://t.me/automate_net






Report Page