Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Обычно мы можем встретить три проблемы при попытке запустить Python-скрипт на сети Huawei (впрочем, и на любой другой): это отсутствие L3 связности с устройством, это неверные имя пользователя или пароль, и это SSH-неполадки. Можно заметить, что любая из этих проблем остановит накат скрипта и сгенерирует один и тот же лог, большая часть из которого сложна для восприятия. В этой статье я постарался рассказать о небольшом улучшении предыдущего кода, которое сообщит о конкретной ошибке на устройстве, и продолжит накат скрипта дальше.
Запуск кода можно посмотреть на видео демонстрации.
Я буду использовать Python конструкцию try - except - continue. try позволяет протестировать блок кода на ошибки. except (exception или исключения) - это тип данных Python, который позволяет сообщить об ошибке. Большинство исключений уже описаны и встроены в Python, нужно лишь найти подходящий.
Я также буду использовать оператор continue, чтобы накат скрипта продолжился несмотря на возникновение ошибки. А функция print() выведет заданное сообщение, если сработает то или иное исключение (except). Иными словами, если не удастся подключиться к устройству из списка устройств, то скрипт выведет короткое сообщение почему именно не удалось подключиться, и попытается подключиться к следующему устройству и так далее. Если ошибки не возникает, то код except пропускается. Еще раз подчеркну, что возникновение ошибки без конструкции try - except - continue, во-первых, сразу останавливает накат скрипта, то есть попытки подключения к другим устройствам из списка не происходит, а во-вторых, сгенерированный лог сообщения является длинным и беcсодержательным.
Итак, Python имеет встроенные исключения (except), которые описывают конкретные ошибки. Например:
Ошибка аутентификации - AuthenticationException
Ошибка недоступности - NetMikoTimeoutException
Ошибка SSH - SSHException
Блок кода except срабатывает только, если происходит ошибка. В этот блок входит функция print() и оператор continue. Например, если указать неверный пароль, то на экран будет выведено сообщение “Неверные данные аутентификации: ip-адрес устройства”. Если ни одна из ошибок не случится, то все три блока кода except будут пропущены, и отработает только главное задание скрипта - send_config_set (последняя строчка кода на примере выше).
Все указанные исключения нужно импортировать через соответствующие модули:
from netmiko.ssh_exception import NetMikoTimeoutException
from paramiko.ssh_exception import SSHException
from netmiko.ssh_exception import AuthenticationException
Весь код приведу в конце статьи.
Теперь тест в eNSP. В топологии восемь CloudEngine Huawei коммутатор. Из них я включу только три, остальные пять останутся недоступными (при попытке подключиться к ним скрипт должен вывести сообщение “Нет ответа от устройства: ip-адрес”). Первый коммутатор оставлю без ошибок, то есть на нем должно отработать задание автоматизации (накат конфигурации), на втором изменю пароль, а на третьем отключу SSH.
Изменяю пароль на CE2:
<CE_2>sys
Enter system view, return user view with return command.
[~CE_2]aaa
[~CE_2-aaa]local-user vasyo1 password irreversible-cipher @ghjcnjnF3589866
[*CE_2-aaa]commit
Отключаю SSH на VTY линиях на CE_3:
<CE_3>sys
Enter system view, return user view with return command.
[~CE_3]user-interface vty 0 4
[~CE_3-ui-vty0-4]protocol inbound telnet
[*CE_3-ui-vty0-4]commit
Теперь запущу скрипт:
Первые строчки после Password - это содержание файлов в формате JSON, а именно файла, содержащего команды конфигурации, и файла, содержащего список IP-адресов устройств. Далее в первом красном прямоугольнике успешный накат конфигурации, во втором красном прямоугольнике сообщение о неверно введеных данных аутентификации (где я поменял пароль), и третий прямоугольник сообщает о недоступности SSH (где я разрешил использовать только telnet). Остальные пять коммутаторов: нет ответа от устройства и их IP-адреса (которые я и не включал).
Можно говорить об успешном применении конструкции try - except - continue.
Может посмотреть видео демонстарию наката, исходный код и его описание в статье: Мой друг Netmiko. Часть 2: Три улучшения Python-скрипта.
Полный код:
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 = f.read().splitlines()
print (config_lines)
with open('myswitches') as f:
ip_lines = f.read().splitlines()
print (ip_lines)
for device in ip_lines:
ip_address_of_device = device
CE = {
'device_type': 'huawei',
'ip': ip_address_of_device,
'username': username,
'password': password
}
try:
ssh_connect = ConnectHandler(**CE)
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
output = ssh_connect.send_config_set(config_lines)
print(f"\n\n-------------- CE_{CE['ip']} --------------")
print(output)
print("-------------------- End -------------------")
Литература:
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