Python для сетевых инженеров: начало пути

    Наверное, многие сетевые инженеры уже поняли, что администрирование сетевого оборудования только через CLI слишком трудоёмко и непродуктивно. Особенно когда под управлением находятся десятки или сотни устройств, часто настроенных по единому шаблону. Удалить локального пользователя со всех устройств, проверить конфигурации всех маршрутизаторов на соответствие каким-то правилам, посчитать количество включенных портов на всех коммутаторах — вот примеры типовых задач, решать которые без автоматизации нецелесообразно.



    Эта статья в основном для сетевых инженеров, которые пока не знакомы или очень слабо знакомы с Python. Мы рассмотрим пример скрипта для решения некоторых практических задач, который вы сразу сможете применять в своей работе.


    Для начала расскажу, почему я выбрал Python.

    Во-первых, это легкий в освоении язык программирования, который позволяет решать очень широкий круг задач.

    Во-вторых, крупные производители сетевого оборудования, такие как Cisco, Juniper, Huawei, внедряют поддержку Python на своем оборудовании. У языка есть будущее в сетевой сфере, и его изучение не будет пустой тратой времени.

    В-третьих, язык очень распространен. Для него написано много полезных библиотек, есть большое сообщество программистов, и найти ответы на большинство вопросов в интернете можно в первых строках поисковой выдачи.

    Я занимаюсь проектированием и немного внедрением сетевых проектов. В одном из них потребовалось решить сразу две задачи.

    1. Пройтись по нескольким сотням филиальных маршрутизаторов и убедиться, что они настроены единообразно. Например, что для связи с ЦОД используется интерфейс Tunnel1, а не Tunnel0 или Tunnel99. И что эти интерфейсы настроены одинаково, за исключением их IP-адресов, естественно.
    2. Перенастроить все маршрутизаторы, в том числе добавить статический маршрут через IP-адрес местного провайдера. То есть эта команда будет уникальной для каждого маршрутизатора.

    На помощь пришел скрипт на Python. Его разработка и тестирование заняли один день.

    Первое, что нужно сделать, это установить Python и крайне желательно PyCharm CE. Скачиваем и устанавливаем Python 3 (сейчас последняя версия 3.6.2). При установке выбираем «Customize installation» и на этапе «Advanced Options» устанавливаем галку напротив «Add Python to environment variables».

    PyCharm CE — это бесплатная среда разработки с очень удобным отладчиком. Скачиваем и устанавливаем.

    Второй шаг — устанавливаем необходимую библиотеку netmiko. Она нужна для взаимодействия с устройствами по SSH или telnet. Библиотеку устанавливаем из командной строки:

    pip install netmiko

    Третьим шагом будет подготовка исходных данных и скрипта под наши задачи.

    В качестве входных данных будем использовать текстовый файл “ip.txt”. В каждой строчке файла должен быть IP-адрес устройства, к которому мы подключаемся. Через запятую можно указать логин и пароль для конкретного устройства. Если этого не сделать, то будут использоваться те, которые вы введёте при запуске скрипта. Пробелы будут проигнорированы. Если первый символ в строке «#», то она считается комментарием и игнорируется. Вот пример корректного файла:



    Сам скрипт логически состоит из двух частей: основной программы и функции doRouter(). Внутри неё выполняется подключение к маршрутизатору, отправка команд в CLI, получение и анализ ответов. Входными данными для функции являются: IP-адрес маршрутизатора, логин и пароль. При возникновении проблем функция вернёт IP-адрес маршрутизатора, мы его запишем в отдельный файл fail.txt. Если всё прошло хорошо, то будет просто выведено сообщение на экран.

    Почему нужно выносить взаимодействие с маршрутизаторами в отдельную функцию, а не выполнить всё в цикле в основной программе? Главная причина — продолжительность работы скрипта. Подключение поочередно ко всем маршрутизаторам заняло у меня 4 часа. В основном из-за того, что какие-то из них не отвечали и скрипт долго ждал истечения таймаута. Поэтому запускать мы будем параллельно по 10 экземпляров функций. В моём случае это сократило время выполнения скрипта до 10 минут.

    Рассмотрим теперь подробнее основную программу.

    Ради безопасности не будем хранить логин и пароль в скрипте. Поэтому выведим на экран приглашение для их ввода. Причем при вводе пароля он не будет отображаться. Эти глобальные переменные используем в процедуре doRouter. У меня были проблемы с работой getpass в PyCharm под Windows. Скрипт работал корректно, только если выполнять его в режиме Debug, а не Run. В командной строке всё работало без нареканий. Также скрипт тестировался в OS X, там проблем в PyCharm замечено не было.

    user_name = input("Enter Username: ")
    pass_word = getpass()

    Потом читаем файл с IP-адресами. Конструкция try…except позволит корректно обработать ошибку чтения файла. На выходе получим массив данных для подключения connection_data, содержащий IP-адрес, логин и пароль.

    try:
        f = open('ip.txt')
        connection_data=[]
        filelines = f.read().splitlines()
        for line in filelines:
    if line == "": continue
            if line[0] == "#": continue
            conn_data = line.split(',')
            ipaddr=conn_data[0].strip()
            username=global_username
            password=global_password
            if len(conn_data) > 1 and conn_data[1].strip() != "": username = conn_data[1].strip()
            if len(conn_data) > 2 and conn_data[2].strip() != "": password = conn_data[2].strip()
            connection_data.append((ipaddr, username, password))
        f.close()
    except:
        sys.exit("Couldn't open or read file ip.txt")

    Далее создаём список процессов и запускаем их. Метод создания процессов я задал как “spawn”, чтобы в Windows и OS X скрипт работал одинаково. Количество созданных процессов будет равно количеству IP-адресов. Но выполняться одновременно будут не более 10. В список routers_with_issues записываем то, что вернут функции doRouter. В нашем случае это IP-адреса маршрутизаторов, с которыми были проблемы.

    multiprocessing.set_start_method("spawn")
    with multiprocessing.Pool(maxtasksperchild=10) as process_pool:
        routers_with_issues = process_pool.map(doRouter, connection_data, 1)
        process_pool.close()
        process_pool.join()

    Команда process_pool.join() нужна для того, чтобы скрипт дождался завершения выполнения всех экземпляров функций doRouter() и только потом продолжил выполнять основную программу.

    В конце создаем/переписываем текстовый файл, в котором у нас будут IP-адреса ненастроенных маршрутизаторов. Также выводим этот список на экран.

    failed_file = open('fail.txt', 'w')
    for item in routers_with_issues:
        if item != None:
          failed_file.write("%s\n" % item)
          print(item)

    Теперь разберем процедуру doRouter(). Первое, что нужно сделать, — обработать входные данные. С помощью ReGex проверяем, что функции был передан корректный IP-адрес.

    ip_check = re.findall("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", ip_address)
    if ip_check == []:
        print(bcolors.FAIL + "Invalid IP - " + str(ip_address) + bcolors.ENDC)
        return ip_address

    Далее создаём словарь с необходимыми для подключения данными и подключаемся к маршрутизатору.

    device = {
        'device_type': 'cisco_ios',
        'ip': ip_address.strip(),
        'username': username,
        'password': password,
        'port': 22, }
    try:
        config_ok = True
    
        net_connect = ConnectHandler(**device)

    Отправляем команды и анализируем полученный ответ от маршрутизатора. Он будет помещён в переменную cli_response. В этом примере мы проверяем текущие настройки. Результат выводим на экран. Данную часть нужно менять под разные задачи. В этом скрипте проверяем текущую конфигурацию маршрутизатора. Если она корректная, то вносим изменения. Если при проверке обнаружены проблемы, то присваиваем переменной config_ok значение False и не применяем изменения.

    cli_response = net_connect.send_command("sh dmvpn | i Interface")
    cli_response = cli_response.replace("Interface: ", "")
    cli_response = cli_response.replace(", IPv4 NHRP Details", "").strip()
    if cli_response != "Tunnel1":
        print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - DMVPN not on Tunnel1.  " + cli_response+ " " + bcolors.ENDC)
        config_ok=False

    Тут будут полезны следующие операции работы со строками.

    Операция Описание Пример
    + Объединение строк s3 = s1 + s2
    >>> print('Happy New ' + str(2017) + ' Year')
    Happy New 2017 Year
    len(s) Определение длины строки
    [] Выделение подстроки (индекс начинается с нуля) s[5] — шестой символ
    s[5:7] — символы с шестого по восьмой
    s[-1] — последний символ, то же, что s[len(s)-1]
    s.split()
    s.join()
    Разделить строки
    Объединить строки
    >>> 'Петя, Лёша, Коля'.split(',')
    ['Петя', 'Лёша', 'Коля']

    >>> ','.join({'Петя', 'Лёша', 'Коля'})
    'Лёша, Петя, Коля'
    str(L)
    list(s)
    Преобразовать список в строку
    Преобразовать строку в список
    >>> str(['1', '2', '3'])
    "['1', '2', '3']"

    >>> list('Test')
    ['T', 'e', 's', 't']
    % Форматирование по шаблону >>> s1, s2 = 'Митя', 'Василиса'
    >>> '%s + %s = любовь' % (s1, s2)
    'Митя + Василиса = любовь'
    f Подстановка переменных >>> a='Максим'
    >>> f'Имя {a}'
    'Имя Максим'
    str.find(substr) Поиск подстроки substr в строке str
    Возвращает позицию первой найденной подстроки
    >>> 'This is a text'.find('a')
    8
    str.replace(old, new) Замена подстроки old на подстроку new в строке str >>> newstr = 'This is a text'.replace(' is ', ' is not ')
    >>> print(newstr)
    This is not a text
    str.strip()
    str.rstrip()
    Удалить пробелы и табуляции в начале и конце (или только в конце) >>> ' This is a text \t\t\t'.strip()
    'This is a text'

    Чтобы решить задачу по добавлению статического маршрута, для начала нужно определить IP-адрес next-hop. В моем случае самый простой способ — посмотреть адрес next-hop у существующих статических маршрутов.

    cli_response2=net_connect.send_command("sh run | i ip route 8.8.8.8 255.255.255.255")
    if cli_response2.strip() == "":
        print(str(ip_address)+" — " + bcolors.FAIL + "WARNING — couldn't find static route to 8.8.8.8" + bcolors.ENDC)
        config_ok=False
    
    ip_next_hop = ""
    if cli_response2 != "":
        ip_next_hop = cli_response2.split(" ")[4]
    
    if ip_next_hop == "":
        print(str(ip_address)+" — " + bcolors.FAIL + "WARNING — couldn't find next-hop IP address " + bcolors.ENDC)
        config_ok=False

    Можно отправлять одну или несколько конфигурационных команд сразу. У меня плохо работала отправка больше 5 команд одновременно, при необходимости можно просто повторить конструкцию несколько раз.

    config_commands = ['ip route 1.1.1.1 255.255.255.255 '+ip_next_hop,
                       'ip route 2.2.2.2 255.255.255.255 '+ip_next_hop]
    net_connect.send_config_set(config_commands)


    Полный скрипт.
    import sys
    from netmiko import ConnectHandler
    from getpass import getpass
    import time
    import multiprocessing
    import re
    
    start_time = time.time()
    
    class bcolors:
        HEADER = '\033[95m'
        OKBLUE = '\033[94m'
        OKGREEN = '\033[92m'
        WARNING = '\033[93m'
        FAIL = '\033[91m'
        ENDC = '\033[0m'
        BOLD = '\033[1m'
        UNDERLINE = '\033[4m'
    
    def doRouter(connection_data):
    
        ip_address = connection_data[0]
        username = connection_data[1]
        password = connection_data[2]
    
        ip_check = re.findall("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", ip_address)
        if ip_check == []:
            print(bcolors.FAIL + "Invalid IP - " + str(ip_address) + bcolors.ENDC)
            return ip_address
    
        device = {
            'device_type': 'cisco_ios',
            'ip': ip_address.strip(),
            'username': username,
            'password': password,
            'port': 22, }
        try:
            config_ok = True
    
            net_connect = ConnectHandler(**device)
    
            cli_response = net_connect.send_command("sh dmvpn | i Interface")
            cli_response = cli_response.replace("Interface: ", "")
            cli_response = cli_response.replace(", IPv4 NHRP Details", "").strip()
            if cli_response != "Tunnel1":
                print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - DMVPN not on Tunnel1.  " + cli_response+ " " + bcolors.ENDC)
                config_ok=False
    
            cli_response2=net_connect.send_command("sh run | i ip route 1.1.1.1 255.255.255.255")
            if cli_response2.strip() == "":
                print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - couldn't find static route to 8.8.8.8" + bcolors.ENDC)
                config_ok=False
    
            ip_next_hop = ""
            if cli_response2 != "":
                ip_next_hop = cli_response2.split(" ")[4]
    
            if ip_next_hop == "":
                print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - couldn't find next-hop IP address " + bcolors.ENDC)
                config_ok=False
    
    
            if config_ok:
                config_commands = ['ip route 1.1.1.1 255.255.255.255 '+ip_next_hop,
                                   'ip route 2.2.2.2 255.255.255.255 '+ip_next_hop]
             	    net_connect.send_config_set(config_commands)
                print(str(ip_address) + " - " + "Static routes added")
            else:
                print(str(ip_address) + " - " + bcolors.FAIL + "Routes weren't added because config is incorrect" + bcolors.ENDC)
                return ip_address
    
            if config_ok:
       	                  net_connect.send_command_expect('write memory')
                print(str(ip_address) + " - " + "Config saved")
    
            net_connect.disconnect()
        except:
            print(str(ip_address)+" - "+bcolors.FAIL+"Cannot connect to this device."+bcolors.ENDC)
            return ip_address
        print(str(ip_address) + " - " + bcolors.OKGREEN + "Router configured sucessfully" + bcolors.ENDC)
    
    
    if __name__ == '__main__':
    
        # Enter valid username and password. Note password is blanked out using the getpass library
        global_username = input("Enter Username: ")
        global_password = getpass()
    
        try:
            f = open('ip.txt')
            connection_data=[]
            filelines = f.read().splitlines()
            for line in filelines:
                if line == "": continue
                if line[0] == "#": continue
                conn_data = line.split(',')
                ipaddr=conn_data[0].strip()
                username=global_username
                password=global_password
                if len(conn_data) > 1 and conn_data[1].strip() != "": username = conn_data[1].strip()
                if len(conn_data) > 2 and conn_data[2].strip() != "": password = conn_data[2].strip()
                connection_data.append((ipaddr, username, password))
            f.close()
        except:
            sys.exit("Couldn't open or read file ip.txt")
    
        multiprocessing.set_start_method("spawn")
        with multiprocessing.Pool(maxtasksperchild=10) as process_pool:
            routers_with_issues = process_pool.map(doRouter, connection_data, 1)  # doRouter - function, iplist - argument
            process_pool.close()
            process_pool.join()
    
        print("\n")
        print("#These routers weren't configured#")
    
        failed_file = open('fail.txt', 'w')
        for item in routers_with_issues:
            if item != None:
              failed_file.write("%s\n" % item)
              print(item)
    
        #Completing the script and print running time
        print("\n")
        print("#This script has now completed#")
        print("\n")
        print("--- %s seconds ---" % (time.time() - start_time))

    После подготовки скрипта выполнить его можно из командной строки или из PyCharm CE. Из командной строки запускаем командой:

    python script.py

    Я рекомендую пользоваться PyCharm CE. Там создаём новый проект, файл Python (File → New…) и вставляем в него наш скрипт. В папку со скриптом кладем файл ip.txt и запускаем скрипт (Run → Run)

    Получаем следующий результат:

    bash ~/PycharmProjects/p4ne $ python3 script.py 
    Enter Username: cisco
    Password: 
    Invalid IP - 10.1.1.256
    127.0.0.1 - Cannot connect to this device.
    1.1.1.1 - Cannot connect to this device.
    10.10.100.227 - Static routes added
    10.10.100.227 - Config saved
    10.10.100.227 - Router configured sucessfully
    10.10.31.170 - WARNING - couldn't find static route to 8.8.8.8
    10.10.31.170 - WARNING - couldn't find next-hop IP address 
    10.10.31.170 - Routes weren't added because config is incorrect
    2.2.2.2 - Cannot connect to this device.
    
    
    #These routers weren't configured#
    10.1.1.256
    127.0.0.1
    217.112.31.170
    1.1.1.1
    2.2.2.2
    
    
    #This script has now completed#

    Пару слов о том, как отладить скрипт. Легче всего это делать в PyCharm. Отмечаем строчку, на которой хотим остановить выполнение скрипта, и запускаем выполнение в режиме отладки. После того, как скрипт остановится, можно будет посмотреть текущие значения всех переменных. Проверить, что передаются и принимаются корректные данные. Кнопками «Step Into» или «Step Into My Code» можно пошагово продолжить выполнение скрипта.



    Ограничения описанной версии скрипта:

    • тестировался только в Python 3
    • не умеет обрабатывать ситуацию, когда вы в первый раз подключаетесь к маршрутизатору и получаете вопрос вида:

      The authenticity of host '11.22.33.44 (11.22.33.44)' can't be established.
      RSA key fingerprint is SHA256:C+BHaMBjuMIoEewAbjbQbRGdVkjs&840Ve3z4aJo.
      Are you sure you want to continue connecting (yes/no)?

    Этот скрипт был написан для решения конкретных задач. Однако он универсален и, надеюсь, поможет ещё кому-нибудь в работе. А самое главное — послужит первым шагом в освоении Python.

    При написании скрипта использовались следующие ресурсы:


    Александр Гаршин, ведущий инженер-проектировщик систем передачи данных компании «Инфосистемы Джет»
    Инфосистемы Джет
    659,00
    Системный интегратор
    Поделиться публикацией

    Комментарии 45

      +1
      и чем он лучше paramiko?
      Здесь например показано jessenoller.com/blog/2009/02/05/ssh-programming-with-paramiko-completely-different как через AutoAddPolicy() решить вопрос с RSA key fingerprint
      Да, paramiko не умеет работать с telnet, но на большинстве коммутаторов, маршрутизаторов есть поддержка ssh
        0
        Paramiko хорошая альтернатива. Но конкретно мне нужен был telnet и SSHv1 для ASA, ввезённой без строгого шифрования.
          +1
          «netmiko» это по факту и есть оболочка для «paramiko» (название намекает).
          Просто в ней куски кода, которые сетевики писали раза от раза используя paramiko (распознование конца вывода, смена промпта, непосредственно процесс подключения и т.п.), объеденены в сподручные функции, и он из коробки довольно стабильно (у меня небыло глюков) работает с самыми распространенными осями сетевых устройств.
            0

            Пришёл разместить эту ссылку, а она уже здесь ;-)
            Хороший курс. Рекомендую.

            0
            Я тут недавно то же писал на эту тему.
              –3
              Извини «автор» но на рисунке тянущие телегу на квадратных колесах это похоже ваши сотрудники. А мужичек предлагающий колеса это тот кто знает: bash, command line utilities.
              Не гонитесь за популярностью изучайте классику.
                +2
                Если что-то изучать с нуля, то из бесплатных продуктов Python выглядит наиболее подходящим для сетевого инженера. Кроме изменения конфигурации через CLI его можно использовать для взаимодействия через RestAPI. Кроме того, у Cisco, Huawei и Juniper уже есть встроенный интерпретатор Python в некоторых маршрутизаторах и коммутаторах. Для Cisco это ISR 4000, Nexus 9000. Думаю, этот список будет расширяться.
                  0
                  а можно детальнее об этом:
                  python on Cisco это ISR 4000
                  ? настраивал ISR 4331 и не заметил ничего :(
                +1
                Тут ведь как — если у вас в руках молоток, любая проблема будет казаться гвоздём.
                Автор явно написал — ему нужно было «одинаково под Windows и Mac OS X». И какие есть возможности под Windows? Баша «из коробки» там нет, PowerShell — это свой отдельный мир, можно ещё cygwin поставить (большой, тяжёлый, со своими проблемами). Python в данном случае не худший выбор.
                  +2
                  Вот только сам Борн говорил в этом десятилетии, что решать сколько-нибудь большие задачи — не то, на что рассчитывались шелл-скрипты (в процессе дизайна, разработки языка), и рекомендовал избегать этого, иначе костылей в процессе собирается (и грабель проходится) немерено.

                  А в общем случае задачи системного администратора могут требовать довольно сложных комбинаций действий, и тогда становится и проще, и разумнее использовать тот же Python.
                  0
                  небольшой оффтопик: со стилем программирования на python от ученых и инженеров ничего не поделать, надо привыкать ;)
                    0
                    согласен, например это
                    print(bcolors.FAIL + "Invalid IP - " + str(ip_address) + bcolors.ENDC)

                    очень красиво можно сделать так
                    print("%s Invalid IP - %s %s "%(bcolors.FAIL,ip_address,bcolors.ENDC))
                      +1
                      да там много чего: несоблюдение pep8, общий except, открытие файла по-старому и т.д.
                        0
                        и файлики кошернее открывать через with :)
                          +2

                          или через format:


                          print('{} Invalid IP - {} {}'.format(bcolors.FAIL, ip_address, bcolors.ENDC))
                            +1
                            Раз уж на 3.6+
                            print(f'{bcolors.FAIL}Invalid IP - {ip_address}{bcolors.ENDC}')
                              0
                              Вот это действительно наглядно и красиво.
                            0
                            Спасибо за советы. Элегантность кода, надеюсь, появится с опытом.
                              0
                              Оно может и некрасиво, но это простительно — вы в конце концов не программист. Главное, чтоб оно корректно работало. а под стандарты и представления о прекрасном можно и потом подогнать, если очень припрет.
                              0
                              Мне одному написанное ниже кажется хуже читаемым?
                                0
                                возможно хуже, но правильней
                            0
                              0

                              Я склоняюсь к тому, что Lua удобнее во всех отношениях по сравнению с Python. Для задач администрирования.

                                +1
                                С Lua не работал, но насколько я знаю, там нет такого количества доступных библиотек, как для Python. В интернете по запросу cisco+lua находятся в основном статьи про SIP и CUCM. Не поделитесь ссылкой на какую-нибудь полезную статью про использование lua для работы с конфигами сетевых устройств? Будет интересно почитать.
                                  0
                                  Со стороны рынка и спроса — конечно Python несомненный лидер.

                                  С академической точки зрения — Python это бастард.
                                  К примеру Tcl, или Lua — то есть такие скриптовые языки,
                                  которые ни на что серьёзное не претендуют, оставаясь именно что языками
                                  командно-скриптовыми, предназначенными для управления другими программами.
                                  Опять же, в администрении всё-таки чаще применяется Bourne Shell (при всей
                                  его дубовости это однозначное must know для эксплуатационщика).
                                  С моей точки зрения Python не имеет права на существование, как и Perl, и
                                  Ruby, и вообще любой интерпретируемый (и тем более командно-скриптовой)
                                  язык, имеющий претензии на роль языка общего назначения.

                                  Но… рынок труда со мной не согласен. ;-)

                                  P.S.
                                  www.ibm.com/developerworks/ru/library/l-lua_3/index.html

                                  robot-develop.org/archives/3717

                                    +1
                                    Опять же, в администрении всё-таки чаще применяется Bourne Shell (при всей его дубовости это однозначное must know для эксплуатационщика).

                                    Достоинство у него ровно одно — в любой юникс-подобной операционке он есть «из коробки». Никакой алгоритм, подразумевающий работу с данными, организованными более сложно, чем последовательность строк, на нём реализовать невозможно, просто нет соответствующих средств.

                                    С моей точки зрения Python не имеет права на существование, как и Perl, и Ruby, и вообще любой интерпретируемый (и тем более командно-скриптовой)
                                    язык, имеющий претензии на роль языка общего назначения.


                                    А, собственно, почему? Даже спрошу иначе — а где, по вашему, проходит граница между компилируемым и интерпретируемым (Java какая?), а также командно-скриптовым и «не-скриптовым» языками (php какой)?
                                      +1
                                      Никакой алгоритм, подразумевающий работу с данными, организованными более сложно, чем последовательность строк, на нём реализовать невозможно, просто нет соответствующих средств.
                                      Да ладно вам. Я сам лично несколько лет назад писал скрипт, который олавливал зависимости между пакетами и делал удобный инсталлятор с помощью NSIS. Всё на bash, включая топологичествую сортировку, проверки зависимостей и прочее.

                                      Дополнительный плюс: за 5 лет скрипт никто так и не изуродовал, так как никто просто не знает — с какой стороны к нему подступиться.
                                0
                                А может перестать бояться, изобретать велосипед, и освоить настоящий инструмент? :)
                                docs.ansible.com/ansible/latest/list_of_network_modules.html
                                  –1
                                  ansible — это довольно кривая и хреново документированная надстройка над голым питоном ) вместо того чтоб изучать питон, придется изучать ансибл, причем изучать по слухам, т.к. нормальной информации о том как оно работает нету.
                                  нормальный инструмент называется HP Network Automation Tool
                                    +2
                                    Годный вброс, но не сработало :)
                                      0
                                      советую почитать на досуге www.allitebooks.com/ansible-for-devops
                                        0
                                        а эта книга актуальна для какой версии ansible?
                                          0
                                          Для любой, на всякий случай есть docs.ansible.com/ansible/latest/index.html где есть актуальная информация
                                            0
                                            уверены? там нет никакой актуальной информации про использование промежуточного hop-off сервера, например.
                                      +1
                                      Это следующий шаг для администрирования. Модули для Ansible пишутся в том числе и на Python, поэтому знакомство с ним лишним не будет. Python сам по себе более гибкий инструмент и позволяет решать более широкий спектр задач. Например, можно написать скрипт, собирающий с оборудования необходимые данные и записывающий их в Excel-файл. И это могут быть не только конфигурации устройств, но и таблицы mac, ARP, RIB, состояние сессий протоколов маршрутизаций.
                                        +1
                                        Можно еще fabric. Вопрос же про изобретение велосипеда :)
                                      +1
                                      Используйте библиотеки. Например, вместо regex проверки IP можно использовать docs.python.org/3/library/socket.html#socket.inet_aton
                                        0
                                        Я бы еще посмотрел в сторону NAPALM.
                                          0
                                          Сорри за дурацкий вопрос, а под Windows это вообще работоспособно? Сразу все упало с ModuleNotFoundError: No module named 'pyasn1' при том, что
                                          D:\PycharmProjects\cisco>«C:\Program Files\Python36\Scripts\pip.exe» install pyasn1
                                          Requirement already satisfied: pyasn1 in c:\program files\python36\lib\site-packages\pyasn1-0.3.3-py3.6.egg
                                          Долго и нудно с библиотеками шаманить надо?
                                            0
                                            Вопрос действительно дурацкий. Я думаю что мало кто подобные вещи в принципе пытается делать под Windows, соотвественно и откуда брать библиотеки — никто не знает. В PIPе pyasn1 есть, но работает ли оно на Windows… попробуйте и узнаете?
                                              0

                                              Нельзя не напомнить что в 10 можно включить линуксовый Шелл и установить в него линуксовый же пакеты и делать вот это все в нем.

                                              0
                                              Я использовал этот скрипт на Windows 10. Также перед публикацией пробовал запустить его на чистой Windows 7, действуя по шагам из статьи. То есть установив только Python 3.6 и библиотеку netmiko. К сожалению, такой ошибки ни разу не встречал. Pyasn1 нужен библиотеке paramiko, которая поставится сама при установке netmiko. Может, попробовать переустановить библиотеки pyasn1, netmiko и paramiko? (pip uninstall/pip install)

                                              Также выложил скрипт на GitHub. Предлагаю скопировать его оттуда. В скрипте из статьи могут быть лишние символы.
                                              https://github.com/aagarshin/habr/
                                                0
                                                Спасибо. банально поставил 3.6.2 вместо просто 3.6, который притащил PyCharm и переставил все библиотеки под него. Все заработало. Уже нарубил штук 10 скриптов для управления свей убогой инфраструктурой. Особенно порадовался когда туда ASA смог включить.

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое