Как стать автором
Обновить

Мой друг Netmiko. Часть 3: один скрипт для разных устройств Huawei

Время на прочтение5 мин
Количество просмотров4.3K

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

Мой друг Netmiko

Литература:

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

Теги:
Хабы:
Всего голосов 6: ↑6 и ↓0+6
Комментарии13

Публикации

Истории

Работа

Python разработчик
120 вакансий
Data Scientist
75 вакансий

Ближайшие события

15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань