Мы уже разобрали в прошлых частях как накатить на сетевые устройства 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