Мы уже разобрали в прошлых частях как накатить на сетевые устройства Huawei список команд из внешнего файла. И это работает, если у нас сеть состоит из одинаковых устройств. Конечно, в реальной практике такое встречается редко. В этой работе мы рассмотрим как использовать разные конфигурационные файлы для разных устройств Huawei, при этом не выходя за рамки одного скрипта. То есть у нас будет все тот же скрипт на основе Netmiko, но в зависимости от версии устройства, конфиг будет накатываться разный: один конфиг для коммутатора CloudEngine Huawei, другой конфиг для роутера AR3200 Huawei.
Как обычно, полный скрипт приведу в конце статьи, видеодемонстрация доступа по ссылке на Форуме Huawei ICT Club.
Чтобы наглядно продемонстрировать как сложна бывает жизнь сетевого инженера, нужно было найти пример задания, реализация которого отличалась бы в зависимости от вида устройства или программного обеспечения. Далеко ходить не пришлось: недавно на форуме Huawei ICT Club, в рамках создания материалов для HCIP Datacom, показывали как на коммутаторах серии S ограничить обработку ICMP запросов. Эта конфигурация для CloudEngine отличается от конфигурации для AR. Исходя из этого различия, я создал два конфигурационных файла. Один назвал “switch_file_config”, в котором прописал команды для CloudEngine:
icmp rate-limit threshold 5
commit
return
Другой назвал “router_file_config”, в котором прописал команды для AR-роутера:
icmp rate-limit enable
icmp rate-limit threshold 5
return
Как видите, для AR нужно сначала применить команду активации, а для CE нет. Кроме того, для CE важно завершать любую конфигурацию командой commit
, иначе конфиг не применится.
Теперь зададимся вопросом: каким будет логика скрипта?
Скрипт подключается к устройству и применяет команду display version
, затем ищет в полученном выводе точное совпадение из списка, который мы ему пропишем в переменной list_versions
:
list_versions = ['CE6800 V200R005C10SPC607B607',
'AR3200 V200R003C00'
]
При этом скрипт сначала выведет на экран надпись “Подключаюсь к устройству” + IP адрес устройства. Затем “Ищу версию ПО” + первое значение из списка list_versions
. Если версия совпадет, то скрипт выводит на экран “Найдена версия ПО” + совпавшее значение из списка list_versions
. Если не совпадет, то “Не смог найти” + значение из списка list_versions
. Реализуем это с помощью цикла for in
, который будет работать в основном цикле подключения к устройствам из списка devices, то есть делаем цикл в цикле. Затем используем условную инструкцию if-elif-else
для реализации логики «совпадает/не совпадает». И метод find()
, которое вернет значение -1, если значение не будет найдено.
# Проверка версии ПО
for software_ver in list_versions:
print ('Ищу версию ПО ' + software_ver)
output_version = ssh_connect.send_command('display version')
int_version = 0 # Сбрасываем цельночисловое значение
int_version = output_version.find(software_ver) # Проверка версии ПО
if int_version > 0:
print ('Найдена версия ПО ' + software_ver)
break
else:
print ('Не смог найти ' + software_ver)
Утверждение break
нужно для того, чтобы остановить цикл после успешного совпадения.
После этого остается только прописать за какими командами обращаться в зависимости от полученного результата, а именно: если версия CE6800, то обращаться к командам config_lines_switch
, а если AR3200, то к config_lines_router
:
if software_ver == 'CE6800 V200R005C10SPC607B607':
print ('Накатываю команды для ' + software_ver + '...')
output = ssh_connect.send_config_set(config_lines_switch)
elif software_ver == 'AR3200 V200R003C00':
print ('Накатываю команды для ' + software_ver + '...')
output = ssh_connect.send_config_set(config_lines_router)
print(f"\n\n-------------- Сетевое устройство {network_device['ip']} --------------")
print(output)
print("----------------------- Конец ----------------------")
Для эстетики вывода конфигурация будет замыкаться между надписями “Сетевое устройство” + IP, и “Конец”. Например, так:
Видеодемонстрацию наката конфигурации, как и говорил, можете посмотреть по ссылке.
Полный скрипт можно представить следующим образом:
from getpass import getpass
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoTimeoutException
from paramiko.ssh_exception import SSHException
from netmiko.ssh_exception import AuthenticationException
username = input('Введите имя пользователя SSH: ')
password = getpass()
with open('switch_file_config') as f:
config_lines_switch = f.read().splitlines()
with open('router_file_config') as f:
config_lines_router = f.read().splitlines()
with open('mydevices') as f:
ip_lines = f.read().splitlines()
for device in ip_lines:
print ('Подключаюсь к устройству: ' + device)
ip_address_of_device = device
network_device = {
'device_type': 'huawei',
'ip': ip_address_of_device,
'username': username,
'password': password
}
try:
ssh_connect = ConnectHandler(**network_device)
except (AuthenticationException):
print ('Неверные данные аутентификации: ' + ip_address_of_device)
continue
except (NetMikoTimeoutException):
print ('Нет ответа от устройства: ' + ip_address_of_device)
continue
except (SSHException):
print ('SSH недоступен. Проверьте включен ли SSH? ' + ip_address_of_device)
continue
# Виды устройств
list_versions = ['CE6800 V200R005C10SPC607B607',
'AR3200 V200R003C00'
]
# Проверка версии ПО
for software_ver in list_versions:
print ('Ищу версию ПО ' + software_ver)
output_version = ssh_connect.send_command('display version')
int_version = 0 # Сбрасываем цельночисловое значение
int_version = output_version.find(software_ver) # Проверка версии ПО
if int_version > 0:
print ('Найдена версия ПО ' + software_ver)
break
else:
print ('Не смог найти ' + software_ver)
if software_ver == 'CE6800 V200R005C10SPC607B607':
print ('Накатываю команды для ' + software_ver + '...')
output = ssh_connect.send_config_set(config_lines_switch)
elif software_ver == 'AR3200 V200R003C00':
print ('Накатываю команды для ' + software_ver + '...')
output = ssh_connect.send_config_set(config_lines_router)
print(f"\n\n-------------- Сетевое устройство {network_device['ip']} --------------")
print(output)
print("----------------------- Конец ----------------------")
Другие аспекты скрипта раскрыты в предыдущих постах:
Применение exception при накате Python-скрипта на Huawei
Мой друг Netmiko. Часть 2: Три улучшения Python-скрипта
Литература:
https://stackoverflow.com/questions/5563089/raw-input-function-in-python
https://pynet.twb-tech.com/blog/automation/netmiko.html
https://pyneng.readthedocs.io/en/latest/book/18_ssh_telnet/netmiko.html
https://github.com/ktbyers/netmiko
https://github.com/ktbyers/netmiko/blob/master/netmiko/ssh_dispatcher.py
Udemy.com - Python Network Programming for Network Engineers (Python 3) (David Bombal)
https://www.pythoncentral.io/pythons-range-function-explained
divaka
Пора, оставить netmiko (paramiko) и автоматизацию через CLI, в 2022 году надо использовать специальные интерфейсы для работы с сетевым оборудованием NETCONF, RESTCONF, REST. у Huawei есть хорошая дока Datacom-Network Automation Developer .
Современные коробки от Cisco, Huawei имеют на борту даже интерпретатор Python, а некоторые даже умеют и контейнеры с гостевыми OS.
https://e.huawei.com/en/talent/#/cert/product-details?certifiedProductId=357&authenticationLevel=CTYPE_CARE_HCIP&technicalField=IIC&version=1.0
vasyo Автор
Пока мои изыская в отношении RESTful на Postman или curl ни к чему не привели: просто нет документации даже, например к CloudEngine ничего не нашел. Если есть у вас опыт, то буду благодарен за инструкцию
divaka
Могу порекомендовать книг Натальи Самойленко Питон для сетевых инженеров и что то там про Ansible
У Huawei в разделе обучения есть специализация Network Automation Developer, закладка Learning, искать
Training materials: HCIP-Datacom-Network Automation Developer V1.0 Training material.pdf
Lab Guide: HCIP-Datacom-Network Automation Developer V1.0 Lab Guide.pdf
https://e.huawei.com/en/talent/#/cert/product-details?certifiedProductId=357&authenticationLevel=CTYPE_CARE_HCIP&technicalField=IIC&version=1.0
у Cisco есть тоже свое направление DevNET тут не подскажу, где брать.
vasyo Автор
Да, для Cisco, конечно, нет проблем найти информацию по настройке. Другое дело Huawei... этот гайд, что вы привели (и спасибо Вам за наводку) это официальная документация, которая имеет свои особенности и свой взгляд, она может хорошо подходить для сдачи экзамена, но не совсем подходить для реальной производственной практике. А ведь именно осмысленных и протестированных самими пользователями материалов и не хватает для Huawei. Опять же методичка Натальи писалась для Cisco и просто так на Huawei ее не перенести: все же логика Huawei от Cisco отличается. Этого может быть не видно на первый взгляд, но тот, кто покопался, знает, что многие вещи отличаются. Поэтому я бы не сравнивал два этих вендоров с точки зрения взаимоиспользования методичек, несмотря на то, что речь идёт об использовании стандартизированных протоколов.
divaka
Не соглашусь с вами что логика работы с Huawei сильно отключается от работы с Cisco, различаться команды и их вывод, сам подход к настройке каких либо фич. но это особенности OS, а вот сам порядок работы с CLI он один везде, отправили команду , ждем (и вот тут пробема как отловить конец ответа, к примеру netmiko запоминает промт, и ждем пока не появиться это приглашение, пример из мей практики после команды на смену контекста на Cisco ASA меняется, приглашение и netmmiko на этом валиться не получив ожидаемое приглашение,это решаеться путем доп. настройки что мы ждем перед отправкой комманд.) и парсим ответ.
вот тут и становятся полезны всякого рода высокоуровневые интерфейсы по типу napalm, Nornir. Они позволяют сосредоточиться на задаче и спрятать особенности OS под капотом. тот же Cisco NSO оперирует абстракциями, а работа с железом вынесена на драйверы.
vasyo Автор
Я про такие особенности и различия как, например, необходимость указывать в конце команду return при работе с Huawei и конфигурационным файлом, в то время как на Cisco такой дополнительной команды указывать не надо. А ведь на такие детали и мелочи и уходит больше всего времени траблшутинга: вроде бы ничего концептуально различного нет, но конфиг без этой небольшой команды не запустится. Спасибо, что подсказали посмотреть в сторону napalm, Nornir. Они решают такие проблемы в том числе? Я так понимаю, что такие решения зависят от того описана модель данных под конкретную задачу или нет?..
divaka
еще бы посоветовал, максимально использовать SNMP чтоб вычитывать версии софта, модели железа, имена устройств и прочее что стандартизировано, поможет избежать лишний парсинг ответа CLI и уменьшить вероятность ошибок. Тот же eSight максимально конфигурирует железо Huawei через SNMP.
Megakazbek
А работать приходится не с самым современным оборудованием, а с тем, какое есть. И активно появляться это начало совсем недавно и не везде - например, в энтерпрайз-сети на оборудовании Cisco, построенной всего пару лет назад никаких этих нетконфов нет и в помине.
vasyo Автор
Действительно, это только у маркетинга все хорошо и просто. А на деле, если продукт есть и есть документация под него, то ещё не факт, что все заработает. Это надо сидеть и колупаться. Restconf и netconf далеко не волшебные палочки. У Huawei, например, надо их ещё активировать на устройствах и SSL сертификат загрузить, а это та ещё задачка.
divaka
Соглашусь, что хватает морально устаревшего железа, но я за то чтоб современные задачи решать современными инструментами. я за Ansible, Napalm, pyATS.
из личного опыта Cisco вся линейка 9000 имеет API, ISG второго поколения умеют ASA имеет на борту REST API, NExus - там python основной язык конфигурации, Cisco свичи 3850 на борту есть python. Arista - REST api, Mikrotik - есть API.
В свое время сам съел пуд соли со всякими netmiko при автоматизации конфигурации Cisco ASA если там есть контексты то это пытка с их переключением и вводом команд, и нет 100% гарантированного результата. в итоге активировал REST API.
vasyo Автор
Я работал с Ansible и пришел к выводу, что он очень не гибкий. Во-первых, потому что модели YANG/Netconf пишутся только для Cloud Engine коммутаторов Huawei, а для стареньких моделей S приходится использовать cli. И разные операции в одну задачу не запихаешь: для включения интерфейса используется один модуль, а для ACL, например, другой, и для каждой задачи нужно делать свой накат. Поэтому, здесь Python+cli выигрывают: в один скрипт можно сразу много чего включить.
divaka
Хорошо кода вы сами писали и сами эксплуатируете скрипт, а вот придет другой специалист на ваше место и ему читать ваш код, он не разберётся и будет плодить свои скрипты. Ansible в этом плен удобней он описан есть сообщество, а то что каждая задача свой таск это я считаю за плюс. изменения в части одного таска гарантированно не затронет другие задачи. И разве при использовании playbook в каждом таске мы не указываем модуль который будем использовать ?
vasyo Автор
Да, я поддерживаю ваш взгляд на стандартизацию и с точки зрения управления проектами в длительной перспективе они решают может быть недостаток квалифицированных кадров. Netmiko в данном случае это скорее, да, индивидуальное решение, которое может помочь сетевому инженеру начать автоматизировать сеть самому и начать понимать и чувствовать логику этого процесса. Насчет Ansible, да, модули прописываются в playbook и их можно указать несколько, но дело в том, что одни модули работают только с netconf, а другие только с network_cli. Например, недавно я настраивал роутер, и вот для настройки интерфейсов модуль был для Netconf, а вот для настройки DHCP его уже не было и пришлось делать через network_cli. Ну а для того, чтобы поменять протокол нужно лезть в host файл. Отсюда и следует негибкость. Конечно, эта ограниченность связана только с отсутствием описанных моделей, но работа в этом направлении ведётся...