Программирование для сетевых инженеров: работа с конфигурацией

    Даже в хорошей, с точки зрения дизайна, сети время от времени приходится проводить работы по актуализации конфигураций тех или иных сущностей. Среди наиболее веских и ожидаемых причин подобной активности можно отметить миграции для согласования физической и логической плоскостей, развитие сети в рамках процесса технологической эволюции, гармонизация архитектур присоединяемых сегментов и решение проблем роста. На самом деле, жизненный цикл сети, почти всегда представляет из себя изменения с тем или иным уровнем рисков и панируемого влияния на сервис, в оценке которого нельзя не учитывать человеческий фактор. Хотя, будет вполне уместным обобщить это описание на большинство областей человеческой деятельности, функционирование коммуникационных сетей обладает некоторыми особенностями, которые заслуживают понимания, или хотя бы внимания, — элементы коммуникационных сетей находятся в плотной связи, тесно взаимодействуют и оказывают не только прямое, но и косвенное воздействие друг на друга. Поэтому, грамотная стратегия проводимых работ станет только продуктивнее будучи подкреплённой механизмами, которые снижают, насколько это возможно, вероятность появления человеческих ошибок. В очередной статье цикла «Зачем сетевым инженерам программирование» я расскажу о вариантах применения автоматизации в одной задаче подобного рода.

    Во многих «букварях» по сетевой архитектуре термины large-scale networks и hierarchical networks используются почти как синонимы, применительно к дизайну IGP домена обозначен простой и, на первый взгляд, понятный дизайн – дробление домена на области. При этом, порог насыщения – вещь сугубо индивидуальная, в каких-то случаях в одной IGP области может нормально сосуществовать тысяча современных маршрутизаторов, в ином случае и трехсот достаточно чтобы существенно снизить эксплуатационные характеристики. По большей части этот порог определяется наложенными на IGP протоколами, поэтому в условиях некоторой вариативности и неопределенности границ и масштабов будущей сети, «зубры» индустрии находят более гибким путь построения плоского домена с последующей миграцией его сформировавшихся частей в отдельные области. Иными словами, если вы не можете «сегодня смотреть в завтрашний день», стройте плоскую сеть и дробите ее по факту появления первых признаков деградации времени сходимости или излишней сложности эксплуатации, потому-как отсутствие иерархии все-таки лучше, чем неправильно выбранная в условиях неопределенности структура [1, 2, 3].

    Довольно общих описаний и абстрактных примеров, предположим, что мы имеем дело с разросшейся областью OSPFv2 домена, топология физических волокон/каналов которого уже позволяет разглядеть в аморфной структуре границы будущих областей. Я не сторонник менять что-то по принципу «все или ничего», может так случится, что из-за непредвиденных обстоятельств пространство возможностей станет слишком узким, а ожидаемые риски слишком большими. Смена OSPFv2 области является деструктивной операцией, поэтому самая прямолинейная схема процесса миграции, которая заключается в последовательном переводе маршрутизаторов в новую область по пути от будущей границе вниз, удобна далеко во всех топологиях. К счастью, некоторое время назад в рекомендациях к развитию OSPF была обозначена возможность построения связности в рамках нескольких областей [4]. Пользуясь этой возможностью, мы можем разбить миграцию на три этапа:

    1. Построение дополнительной (secondary) связности в рамках новой области
    2. Перевод новой области в основной режим, а старой в дополнительный
    3. Удаление связности в рамках старой области

    На первом этапе топология новой области постепенно расширяется, на втором, топология старой области сужается. При соблюдении конгруэнтности топологий старой и новой областей, мы получим согласованную маршрутизацию между переведенными и не переведенными узлами, а это, в свою очередь, делает возможным деление этапов на независимые под-этапы, на каждом из которых работа может производится с некоторой частью узлов. К выбору узлов для работ в рамках под-этапа целесообразно подходить с точки зрения фактической утилизации каналов в конкретной сети, таким образом, чтобы не допускать перезагрузку на границе старой и новой областей. Несмотря на то, что статья посвящена программированию, думаю, не будет лишним сказать пару слов о поведении наложенных на IGP протоколов в контексте смены областей. LDP ведет себя довольно предсказуемо, плавность перевода достигается обеспечением IP связности между transport-address таргетированных и интерфейсных сессий. В силу того, что BGP очень гибкий протокол, стоит обратить пристальное внимание на эту плоскость. Хорошо, если на переводимых узлах BGP не привносит в выбор пути особенных вольностей в виде несогласованного между узлами изменения Local Preferences или других критериев, обуславливающих локальный routing decision. Иными словами, поведение BGP тоже является предсказуемым, в том случае если внутри области выбор маршрута не противоречил правилу follow IGP path. Есть тонкий момент, связанный с работой RSVP в период времени сосуществования двух областей. Почву для размышлений подбрасывает факт наполнения TED таблицы из двух источников с разной видимостью, например, вы вполне можете лишится механизмов FRR до полного окончания работ. Это может случится если маршрутизаторы с большей видимостью, которые находятся в двух областях, посчитают ERO через маршрутизатор с меньшей видимостью, т.е. через переведенный сегмент сети без топологической информации о другой области. Подобное нельзя назвать катастрофой, так как путь в итоге конечно будет установлен, но и забывать об этом не стоит. Особенного искусства требует совмещение работ по внедрению иерархий IGP с работами такого же рода в BGP плоскости, например, миграцией full-mesh в отражатели маршрутов. Внедрение иерархий в разных плоскостях лучше проводить последовательно, то же самое, по моему мнению, относится ко всем вещам, которые прячут маршрутную информацию, суммаризацию проще построить на стабильном фундаменте иерархического IGP, нежели совмещать эти этапы.

    Итак, общий план у нас есть, и, если вы еще не передумали, давайте поразмыслим над программной реализацией на Pyez, примерно такой как на этом рисунке.

    image

    Каждый красивый овал, может представлять из себя отдельную программную сущность, т.е. такую вещь, которая выполняет работу и готовит данные для следующего этапа. Под исходными данными подразумевается информация из сети, например, чтобы подготовить конфигурацию новой OSPF области, необходимо получить имена активных интерфейсов, принадлежащей старой области, и их веса, а значит нам пригодятся умения работы с Operation таблицами и представлениями. С этими понятиями можно познакомится в предыдущей статье цикла «Программирование для сетевых инженеров: первый кейс». На первом этапе генератор сохраняет в файлы команды необходимые для активации новой области, на втором – для удаления старой и перевода новой в основной режим, на третьем – команды по удалению старой области. Забегая вперед скажу, что для данной статьи я намеренно не пользуюсь визуализаторами шаблонов, наподобие Jinja2. Чтобы не отвлекаться от целевой темы код написан максимально просто. Если вот кому-то интересно документация по ссылке «Jinja2 Documentation».

    Код генерации конфигураций этапов
    import sys
    import yaml
    from jnpr.junos.factory.factory_loader import FactoryLoader
    from jnpr.junos import Device
    
    def getConnection(p_host, p_user):
    	acc = {'lab': 'lab123'}
    
    	try:
    		print '		DEBUG --- getting ssh connection to ' + p_host
    
    		l_dev = Device(host=p_host, user=p_user, password=acc[p_user], auto_probe=2, gather_facts=True, port=22)
    		l_dev.open()
    		if (l_dev.connected):
    			l_dev.timeout = 900
    			print '		DEBUG --- ssh cionnection to host ' + p_host + ' established'
    			print '		DEBUG --- connection ' + p_host + ' named ' + l_dev.facts['hostname'] + ' established ' 
    			return l_dev
    		else:
    			raise Exception('		DEBUG --- ssh connection to ' + p_host + ' was not established')
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- getConnection : connection to ' + p_host + ' was not established. ex:' + str(ex)
    		return
    
    def close_dev(d):
    	try:
    		d.close()
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- close_dev : connection to cant be closed. ex:' + str(ex)
    
    
    yml = '''
    ---
    OSPFInterface:
      rpc: get-ospf-interface-information
      args:
       area: '0.0.0.200'
       detail: True
      item: ospf-interface
      view: OSPFInterfaceView
      
    OSPFInterfaceView:
      fields:
       name: interface-name
       type: interface-type
       cost: interface-cost
    '''
    
    globals().update(FactoryLoader().load(yaml.load(yml)))
    
    node_list = ['10.83.20.68', '10.83.20.69', '10.83.20.70', '10.83.20.71']
    abr_list = ['10.83.20.66', '10.83.20.67']
    
    for node in node_list + abr_list:
        ddev = getConnection(node, 'lab')
        ospf_interfaces = OSPFInterface(ddev).get()
        
        with open('st1-' + node + '.txt', "w") as f_st1:
            for ospf_interface in ospf_interfaces:
                if ( 'ge' in ospf_interface.name ):
                    f_st1.write('set protocols ospf area 0.0.0.250 interface ' + ospf_interface.name + ' secondary' + '\n')
                    f_st1.write('set protocols ospf area 0.0.0.250 interface ' + ospf_interface.name + ' interface-type p2p' + '\n')
                    f_st1.write('set protocols ospf area 0.0.0.250 interface ' + ospf_interface.name + ' metric ' + ospf_interface.cost + '\n')
    
        with open('st2-' + node + '.txt', "w") as f_st1:
            f_st1.write('delete protocols ospf area 0.0.0.200' + '\n')
            f_st1.write('delete protocols ospf area 0.0.0.250' + '\n')
            for ospf_interface in ospf_interfaces:
                f_st1.write('set protocols ospf area 0.0.0.250 interface ' + ospf_interface.name + ' interface-type p2p' + '\n')            
                f_st1.write('set protocols ospf area 0.0.0.200 interface ' + ospf_interface.name + ' secondary' + '\n')
                f_st1.write('set protocols ospf area 0.0.0.200 interface ' + ospf_interface.name + ' interface-type p2p' + '\n')            
                if (ospf_interface.cost != '0'):
                    f_st1.write('set protocols ospf area 0.0.0.250 interface ' + ospf_interface.name + ' metric ' + ospf_interface.cost + '\n')
                    f_st1.write('set protocols ospf area 0.0.0.200 interface ' + ospf_interface.name + ' metric ' + ospf_interface.cost + '\n')
        
        with open('st3-' + node + '.txt', "w") as f_st1:
            f_st1.write('delete protocols ospf area 0.0.0.200' + '\n')
    
    


    Для наглядности я собрал в вот такую сеть на vMX.

    image

    vMX это полноценный программный маршрутизатор от Juniper Networks, во многом повторяющий поведение своего старшего, железного брата MX. Не то чтобы это был продукт, который нуждается в представлении, просто такие вещи полезно держать под рукой для упражнений в программировании или лабораторных испытаний. Триал, можно скачать тут «vMX Trial Download», а инструкцию по установке по этой ссылке «Preparing the System to Install vMX».

    Маршрутизаторы bb, abr1 и abr2 образуют нулевую область, маршрутизаторы r1, r2, r3 и r4 – должны быть перемещены из 200-й области в 250-ю.

    lab@bb> show configuration protocols
    bgp {
        group int {
            type internal;
            local-address 10.0.0.65;
            neighbor 10.0.0.66;
            neighbor 10.0.0.67;
            neighbor 10.0.0.68;
            neighbor 10.0.0.69;
            neighbor 10.0.0.70;
            neighbor 10.0.0.71;
        }
    }
    ospf {
        area 0.0.0.0 {
            interface lo0.0 {
                passive;
            }
            interface ge-0/0/3.0 {
                interface-type p2p;
            }
            interface ge-0/0/2.0 {
                interface-type p2p;
            }
        }                                   
    }
    



    lab@abr1> show configuration protocols
    bgp {
        group int {
            type internal;
            local-address 10.0.0.66;
            neighbor 10.0.0.65;
            neighbor 10.0.0.67;
            neighbor 10.0.0.68;
            neighbor 10.0.0.69;
            neighbor 10.0.0.70;
            neighbor 10.0.0.71;
        }
    }
    ospf {
        area 0.0.0.0 {
            interface lo0.0 {
                interface-type p2p;
            }
            interface ge-0/0/3.0 {
                interface-type p2p;
            }
            interface ge-0/0/0.0 {
                interface-type p2p;
            }
        }                                   
        area 0.0.0.200 {
            interface ge-0/0/1.0 {
                interface-type p2p;
            }
        }
    }
    


    lab@abr2> show configuration protocols
    bgp {
        group int {
            type internal;
            local-address 10.0.0.67;
            neighbor 10.0.0.65;
            neighbor 10.0.0.66;
            neighbor 10.0.0.68;
            neighbor 10.0.0.69;
            neighbor 10.0.0.70;
            neighbor 10.0.0.71;
        }
    }
    ospf {
        area 0.0.0.0 {
            interface lo0.0 {
                interface-type p2p;
            }
            interface ge-0/0/0.0 {
                interface-type p2p;
            }
            interface ge-0/0/2.0 {
                interface-type p2p;
            }
        }                                   
        area 0.0.0.200 {
            interface ge-0/0/1.0 {
                interface-type p2p;
            }
        }
    }
    



    lab@r1> show configuration protocols
    bgp {
        group int {
            type internal;
            local-address 10.0.0.68;
            neighbor 10.0.0.65;
            neighbor 10.0.0.66;
            neighbor 10.0.0.67;
            neighbor 10.0.0.69;
            neighbor 10.0.0.70;
            neighbor 10.0.0.71;
        }
    }
    ospf {
        area 0.0.0.200 {
            interface ge-0/0/1.0 {
                interface-type p2p;
            }
            interface ge-0/0/2.0 {
                interface-type p2p;
            }
            interface ge-0/0/3.0 {
                interface-type p2p;
            }
            interface lo0.0 {               
                interface-type p2p;
            }
        }
    }
    


    lab@r2> show configuration protocols
    bgp {
        group int {
            type internal;
            local-address 10.0.0.69;
            neighbor 10.0.0.65;
            neighbor 10.0.0.66;
            neighbor 10.0.0.67;
            neighbor 10.0.0.68;
            neighbor 10.0.0.70;
            neighbor 10.0.0.71;
        }
    }
    ospf {
        area 0.0.0.200 {
            interface ge-0/0/0.0 {
                interface-type p2p;
            }
            interface ge-0/0/3.0 {
                interface-type p2p;
            }
            interface lo0.0 {
                interface-type p2p;
            }
        }                                   
    }
    


    lab@r3> show configuration protocols
    bgp {
        group int {
            type internal;
            local-address 10.0.0.70;
            neighbor 10.0.0.65;
            neighbor 10.0.0.66;
            neighbor 10.0.0.67;
            neighbor 10.0.0.68;
            neighbor 10.0.0.69;
            neighbor 10.0.0.71;
        }
    }
    ospf {
        area 0.0.0.200 {
            interface ge-0/0/0.0 {
                interface-type p2p;
            }
            interface ge-0/0/3.0 {
                interface-type p2p;
            }
            interface lo0.0 {
                interface-type p2p;
            }
        }                                   
    }
    


    lab@r4> show configuration protocols
    
    bgp {
        group int {
            type internal;
            local-address 10.0.0.71;
            neighbor 10.0.0.65;
            neighbor 10.0.0.66;
            neighbor 10.0.0.67;
            neighbor 10.0.0.68;
            neighbor 10.0.0.69;
            neighbor 10.0.0.70;
        }
    }
    ospf {
        area 0.0.0.200 {
            interface ge-0/0/1.0 {
                interface-type p2p;
            }
            interface ge-0/0/2.0 {
                interface-type p2p;
            }
            interface ge-0/0/3.0 {
                interface-type p2p;
            }
            interface lo0.0 {               
                interface-type p2p;
            }
        }
    }


    Применительно к маршрутизатору r2, будет сгенерирован следующий набор команд.

    Для первого этапа
    set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 secondary
    set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 interface-type p2p
    set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 metric 1
    set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 secondary
    set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 interface-type p2p
    set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 metric 1
    set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 secondary
    set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 interface-type p2p
    set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 metric 1


    Для второго этапа
    delete protocols ospf area 0.0.0.200
    delete protocols ospf area 0.0.0.250
    set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 interface-type p2p
    set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 secondary
    set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 interface-type p2p
    set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 metric 1
    set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 metric 1
    set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 interface-type p2p
    set protocols ospf area 0.0.0.200 interface ge-0/0/2.0 secondary
    set protocols ospf area 0.0.0.200 interface ge-0/0/2.0 interface-type p2p
    set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 metric 1
    set protocols ospf area 0.0.0.200 interface ge-0/0/2.0 metric 1
    set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 interface-type p2p
    set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 secondary
    set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 interface-type p2p
    set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 metric 1
    set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 metric 1
    set protocols ospf area 0.0.0.250 interface lo0.0 interface-type p2p
    set protocols ospf area 0.0.0.200 interface lo0.0 secondary
    set protocols ospf area 0.0.0.200 interface lo0.0 interface-type p2p


    Для третьего этапа
    delete protocols ospf area 0.0.0.200


    Как я уже писал элементы сети обладают внутренним состоянием, вокруг и внутри них что-то постоянно происходит независимо от того хотим мы этого или нет. Появление таких событий как отказ трансивера, отключение питания на узле или обрыв оптического канала нужно воспринимать как должное и учитывать при проведении работ. Я предлагаю обратить внимание на этот факт в контексте выбора проверок успешности этапов миграции. Как бы парадоксально это не звучало, в данном случае нам не обязательно проверять появилось ли OSPF соседство на том или ином интерфейсе, так как причины его отсутствия могут находится совсем в другой плоскости. Кроме перечисленного выше в исходные данные всегда может попасть ошибка или неточность, например, например, в виде всеми забытого интерфейса, который подлежит удалению, а в данный момент смотрит в «пустоту». В процессе формирования проверок полезно подняться на уровень выше, чтобы посмотреть на сеть с точки зрения оказываемых услуг и наложенных протоколов, так как в конечном счете состояние только этих вещей позволяет принять обоснованное решение об успешности того или иного этапа. Мало кто из заказчиков соглашается на публичные статьи по результатам выполненных работ, еще и поэтому я собрал виртуальную среду для демонстрации. В рамках этой среды я ограничусь проверкой состояния BGP сессий, которые построены по схеме каждый-с-каждым между маршрутизаторами, это и будет нашими наложенными сервисами, и услугами. Если, после работ выполняются условия для их работоспособности в виде IP связности каждый-с-каждым, значит есть и основания полагать что работы проведены успешно. В реальных проектах проверки обычно ограничиваются тем объемом услуг и наложенных протоколов, которые обозначается как business critical в данной сети. К программированию это не относится, тем не менее я не могу не заострить внимание на этом вопросе, так как выбор критерия успешности — это залог спокойного сна после проведенных работ.

    Код проверки BGP сессий
    import sys
    import yaml
    from jnpr.junos.factory.factory_loader import FactoryLoader
    from jnpr.junos import Device
    
    def getConnection(p_host, p_user):
    	acc = {'lab': 'lab123'}
    
    	try:
    		print '		DEBUG --- getting ssh connection to ' + p_host
    
    		l_dev = Device(host=p_host, user=p_user, password=acc[p_user], auto_probe=2, gather_facts=True, port=22)
    		l_dev.open()
    		if (l_dev.connected):
    			l_dev.timeout = 900
    			print '		DEBUG --- ssh cionnection to host ' + p_host + ' established'
    			print '		DEBUG --- connection ' + p_host + ' named ' + l_dev.facts['hostname'] + ' established ' 
    			return l_dev
    		else:
    			raise Exception('		DEBUG --- ssh connection to ' + p_host + ' was not established')
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- getConnection : connection to ' + p_host + ' was not established. ex:' + str(ex)
    		return
    
    def close_dev(d):
    	try:
    		d.close()
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- close_dev : connection to cant be closed. ex:' + str(ex)
    
    ip_f_name = 'ip-list-1.txt'
    
    yml = '''
    ---
    BGPGroup:
      rpc: get-bgp-group-information
      args:
       group-name: 'int'
      item: bgp-group
      view: BGPGroupView
      
    BGPGroupView:
      fields:
       count: peer-count
       established: established-count
    '''
    
    globals().update(FactoryLoader().load(yaml.load(yml)))
    
    node_list = ['10.83.20.68', '10.83.20.69', '10.83.20.70', '10.83.20.71']
    abr_list = ['10.83.20.66', '10.83.20.67']
        
    for node in node_list + abr_list:
            ddev = getConnection(node, 'lab')
            bgp_group = BGPGroup(ddev).get()
    
            for group in bgp_group:
                    if (group.count != group.established):
                            print 'bgp connection lost' 
                    else:
                            print 'dont panic!' 
    


    Результаты его работы
    DEBUG — getting ssh connection to 10.83.20.68
    DEBUG — ssh cionnection to host 10.83.20.68 established
    DEBUG — connection 10.83.20.68 named r1 established
    dont panic!
    DEBUG — getting ssh connection to 10.83.20.69
    DEBUG — ssh cionnection to host 10.83.20.69 established
    DEBUG — connection 10.83.20.69 named r2 established
    dont panic!
    DEBUG — getting ssh connection to 10.83.20.70
    DEBUG — ssh cionnection to host 10.83.20.70 established
    DEBUG — connection 10.83.20.70 named r3 established
    dont panic!
    DEBUG — getting ssh connection to 10.83.20.71
    DEBUG — ssh cionnection to host 10.83.20.71 established
    DEBUG — connection 10.83.20.71 named r4 established
    dont panic!
    DEBUG — getting ssh connection to 10.83.20.66
    DEBUG — ssh cionnection to host 10.83.20.66 established
    DEBUG — connection 10.83.20.66 named abr1 established
    dont panic!
    DEBUG — getting ssh connection to 10.83.20.67
    DEBUG — ssh cionnection to host 10.83.20.67 established
    DEBUG — connection 10.83.20.67 named abr2 established
    dont panic!

    До текущего момента мы беседовали по большей части о каких-то сетевых вещах, но я еще ни словом ни обмолвился о программном коде, который вроде как должен быть в центре внимания в статье с таким названием. Во-первых, мне кажется, что мысли намного важнее кода, формализовав сущности в голове инженер сможет превратить их в инструмент и изложить в виде кода. Во-вторых, мне не хочется повторятся, все что может показаться не очевидным в этих примерах, а также минимально необходимые знания для начала работы с Python и Pyez, содержатся в предыдущей статье цикла. В-третьих, код подготовки конфигурации осуществляет свою работу, что называется в офлайне и не оказывает мгновенного воздействия на сеть, поэтому вряд ли может вызвать какой-то интерес. Несколько иначе обстоят дела с кодом имплементации этапа исполнения, разработка этих процедур ставит перед нами следующие вопросы:

    • Как проверить что весь объем команд адекватно восприняты интерпретатором?
    • Как проверить что вносимые в конфигурацию изменения были применены?
    • Как осуществить транзакционную схему внесения конфигурации?
    • Как сделать откат конфигурации в случае потери управления?
    • Как почистить за собой если в процессе передачи команд интерпретатор сообщил об ошибке?

    Чем больше внимания будет уделено этим вопросам, тем реже на этапе исполнения будут служатся неожиданности. Представьте каких хлопот может принести синтаксическая ошибка описания политики маршрутизации, когда классификаторы этой политики только частично одобрены интерпретатором. Если не проконтролировать построчно процесс слияния этой политики с текущей конфигураций можно одним нажатием клавиши перевести груду оборудования в неадекватное состояние. Поэтому, я придерживаюсь примерно такой блок схемы этапа исполнения.

    image

    Вооружившись документацией по Pyez был составлен следующий код универсального загрузчика конфигурации, который вы можете использовать в своей повседневной работе, так же как я использую его в своей.

    conf_change.py
    
    import sys
    import yaml
    from jnpr.junos.factory.factory_loader import FactoryLoader
    from jnpr.junos import Device
    from jnpr.junos.utils.config import Config
    import copy
    import re
    import traceback
    import time
    import random
    from jnpr.junos.exception import *
    import os.path
    
    yml = '''
    ---
    VersionInfo:
      rpc: get-software-information
      item: software-information
      view: VersionInfoView
    
    VersionInfoView:
      fields:
        name: host-name
    
    '''
    Device.auto_probe = 3
    
    ip_f_name = 'ip-list-1.txt'
    cur_stage='2'
    
    
    globals().update(FactoryLoader().load(yaml.load(yml)))
    
    def doTestOSPF(p_dev, p_node, f_do):
            print '		DEBUG --- doTestOSPF : at ' + p_node
            if ( p_dev == None ):
                    print '		DEBUG --- ERROR --- doTestOSPF : connection to ' + p_node + ' is None'
                    return
            else:
                    try:
                            d_conf = p_dev.cli("show configuration | display set").split('\n')
                            ret_val = True
                            set_found = 0
                            c_path = 'st' + cur_stage + '-' + p_node + '.txt'
                            with open(c_path, "r") as f:
                                    for line in f:
                                            c_line = line.replace('\n', '').replace('\r\n', '')
                                            if ('delete ' not in c_line):
                                                    set_found = 1
                                                    if ( (c_line not in d_conf) and (c_line != '')):
                                                            print '		DEBUG ---  doTestOSPF found missing line ' + c_line
                                                            ret_val = False
    
                                                    
                            f.close()
                            if ( (set_found == 0) and (f_do == True) ):
                                    return False
                            return ret_val
                    except Exception as ex:
                            print '		DEBUG --- ERROR --- doTestOSPF : connection to ' + p_node + ' was not established. ex:' + str(ex)
                            return
    
    def doTest(p_dev, p_node, f_do):
            return doTestOSPF(p_dev, p_node, f_do)
    
    def close_dev(d):
    	try:
    		d.close()
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- close_dev : connection to cant be closed. ex:' + str(ex)
    
    def getConnection(p_host, p_user):
    	acc = {'lab': 'lab123'}
    	
    	try:
    		print '		DEBUG --- getting ssh connection to ' + p_host
    
    		l_dev = Device(host=p_host, user=p_user, password=acc[p_user], auto_probe=2, gather_facts=True, port=22)
    		l_dev.open()
    		if (l_dev.connected):
    			l_dev.timeout = 900
    			print '		DEBUG --- ssh cionnection to host ' + p_host + ' established'
    			v = VersionInfo(l_dev).get()
    			print '		DEBUG --- connection ' + p_host + ' named ' + l_dev.facts['hostname'] + ' established ' 
    			return l_dev
    		else:
    			raise Exception('		DEBUG --- ssh connection to ' + p_host + ' was not established')
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- getConnection : connection to ' + p_host + ' was not established. ex:' + str(ex)
    		traceback.print_exc()
    		return
    
    def doCompare(p_conf, p_node):
    	try:
    		print '		DEBUG --- doCompare at ' + p_node
    		if ( p_conf.diff() == None ):
    			return False
    		else:
    			return True
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- doCompare : conf.diff at ' + p_node + ' ex:' + str(ex)
    		return
    
    def doLoad(p_conf, p_node):
            try:
                    print '		DEBUG --- doLoad at ' + p_node
    
                    c_path = 'st' + cur_stage + '-' + p_node + '.txt'
                    if (os.path.isfile(c_path)):
                            p_conf.load(path=c_path, format='set')
    
                    return True
            except Exception as ex:
                    print '		DEBUG --- ERROR --- doLoad : cant load config to ' + p_node + ' ex:' + str(ex)
                    return
    
    def doRollback(p_conf, p_node, p_r):
    	try:
    		print '		DEBUG --- doRollback at ' + p_node
    		if ( p_conf.rollback(rb_id=p_r) == True ):
    			return True
    		else:
    			return False
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- doRollback : cant rollback config to ' + p_node + ' ex:' + str(ex)
    		return None
    
    def doCommitCheck(p_conf, p_node):
    	try:
    		print '		DEBUG --- doCommitCheck at ' + p_node
    		p_conf.commit_check()
    		return True
    	except Exception as ex:
    		print '		DEBUG --- ERROR --- doCommitCheck : cant config commit check config to ' + p_node + ' ex:' + str(ex)
    		return None
    
    def doCommit(p_conf, p_node, p_confirm_m=None):
    	try:
    		print '		DEBUG --- doCommit at ' + p_node
    		commit_res = None
    		if (p_confirm_m == None):
    			commit_res = p_conf.commit(timeout=30)
    		else:
    			commit_res = p_conf.commit(confirm=p_confirm_m, timeout=30)
    
    		if (commit_res == True):
    			return True
    		else:
    			return False
    	except CommitError as c_ex:
    		print '		DEBUG --- ERROR --- doCommit : cant config commit at ' + p_node + ' ex:' + str(c_ex)
    		return None
    	except RpcTimeoutError as t_ex:
    		print '		DEBUG --- ERROR --- doCommit : config was commited at ' + p_node + ' with the following ex:' + str(t_ex)
    		return True
    
    def doJob(p_dev, p_node):
    	print '		DEBUG --- doJob at ' + p_node 
    	if ( p_dev == None ):
    		print '		DEBUG --- ERROR --- doJob : connection to ' + p_node + ' is None'
    		return
    	else:
    		try:
    			with Config(p_dev) as conf:
    				is_compare = doCompare(conf, node)
    				if ( is_compare == None ):
    					print '		DEBUG --- ERROR --- doJob : at config compare ' + node
    					return
    				if ( is_compare == True ):
    					print '		DEBUG --- ERROR --- doJob : configuration locked at ' + node
    					return False
    				print '		DEBUG --- starting to do config changes at ' + node
    				if ( doLoad(conf, node) != True ):
    					print '		DEBUG --- ERROR --- doJob : conf.load ' + node
    					if ( doCompare(conf, node) != False ):
    						print '		DEBUG --- doJob : doing rollback after load at ' + node + ' deleting :' + str(conf.diff())
    						doRollback(conf, node, 0)
    					return
    				print '		DEBUG --- commit check at ' + node
    				if (doCommitCheck(conf, node) != True):
    					print '		DEBUG --- ERROR --- doJob : conf.doCommitCheck failed at ' + node 
    					if ( doCompare(conf, node) != False ):
    						print '		DEBUG --- doJob : doing rollback after load at ' + node + ' deleting :' + str(conf.diff())
    						doRollback(conf, node, 0)
    					return
    				commit_m = 5
    				print  '		DEBUG --- commiting changes at ' + node
    				if (doCommit(conf, node, commit_m) != True):
    					print '		DEBUG --- ERROR --- doJob : conf.commit ' + node 
    					if ( doCompare(conf, node) != False ):
    						print '		DEBUG --- doJob : doing rollback after commit at ' + node + ' deleting :' + str(conf.diff())
    						doRollback(conf, node, 0)
    				return True
    		except Exception as ex:
    			print '		DEBUG --- ERROR --- doJob : cant do job ' + node + ' ex:' + str(ex)
    			return
    
    
    node_list = []
    result_list = {}
    
    with open(ip_f_name, "r") as f_ip:
    	for line in f_ip:
    		c_ip_line = line.replace('\n', '').replace('\r\n', '')
    		if (c_ip_line != ''):
    			node_list.append(c_ip_line)
        
    
    for node in node_list:
    	print 'FLOW -- ************************************ '
    	print 'FLOW -- checking ' + node
    	result_list.setdefault(node, {})
    	cur_dev = getConnection(node, 'lab')
    	is_test = doTest(cur_dev, node, True)
    	if( is_test == None):
    		print 'FLOW -- error'
    		result_list.setdefault(node, {}).setdefault('status', 'error')
    		break
    	if( is_test == True):
    		print 'FLOW -- conf exist'
    		result_list.setdefault(node, {}).setdefault('status', 'nn')
    	if( is_test == False):
    		print 'FLOW -- conf not exist, doing change'
    		is_job = doJob(cur_dev, node)
    		if( is_job == None):
    			print 'FLOW -- cant do job at ' + node
    			result_list.setdefault(node, {}).setdefault('status', 'error')
    			break
    		if( is_job == False):
    			print 'FLOW -- cant do job at ' + node
    			result_list.setdefault(node, {}).setdefault('status', 'not_done')
    		if( is_job == True):
    			print 'FLOW -- done job at ' + node
    			print 'FLOW -- going sleep at ' + node
    			time.sleep(5)
    			print 'FLOW -- checking job status ' + node
    			cur_dev_confirm = getConnection(node, 'lab')
    			if ( cur_dev_confirm != None ):
    				if (doTest(cur_dev, node, False) == True):
    					print 'FLOW -- commiting the configuration at ' + node
    					if (doCommit(Config(cur_dev_confirm), node) != True):
    						print 'FLOW -- ERROR cant commit the configuration at ' + node
    						result_list.setdefault(node, {}).setdefault('status', 'not_done')
    						break
    					else:
    						print 'FLOW -- configuration commited at ' + node
    						result_list.setdefault(node, {}).setdefault('status', 'done')
    				else:
    					print 'FLOW -- ERROR cant find conf after job ' + node
    					result_list.setdefault(node, {}).setdefault('status', 'not_done')
    				close_dev(cur_dev_confirm)
    			else:
    				print 'FLOW -- ERROR cant access ' + node + ' for commiting'
    				result_list.setdefault(node, {}).setdefault('status', 'not_done')
    	close_dev(cur_dev)
    
    print result_list
    
    


    И результаты его работы по трем этапам

    Скрытый текст
    Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
    Type "copyright", "credits" or "license()" for more information.
    >>>
    ==== RESTART: C:\Users\and_andreev\Desktop\tools\lab-case2\conf_change.py ====
    FLOW -- ************************************
    FLOW -- checking 10.83.20.66
    DEBUG --- getting ssh connection to 10.83.20.66
    DEBUG --- ssh cionnection to host 10.83.20.66 established
    DEBUG --- connection 10.83.20.66 named abr1 established
    DEBUG --- doTestOSPF : at 10.83.20.66
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.66
    DEBUG --- doCompare at 10.83.20.66
    DEBUG --- starting to do config changes at 10.83.20.66
    DEBUG --- doLoad at 10.83.20.66
    DEBUG --- commit check at 10.83.20.66
    DEBUG --- doCommitCheck at 10.83.20.66
    DEBUG --- commiting changes at 10.83.20.66
    DEBUG --- doCommit at 10.83.20.66
    FLOW -- done job at 10.83.20.66
    FLOW -- going sleep at 10.83.20.66
    FLOW -- checking job status 10.83.20.66
    DEBUG --- getting ssh connection to 10.83.20.66
    DEBUG --- ssh cionnection to host 10.83.20.66 established
    DEBUG --- connection 10.83.20.66 named abr1 established
    DEBUG --- doTestOSPF : at 10.83.20.66
    FLOW -- commiting the configuration at 10.83.20.66
    DEBUG --- doCommit at 10.83.20.66
    FLOW -- configuration commited at 10.83.20.66
    FLOW -- ************************************
    FLOW -- checking 10.83.20.67
    DEBUG --- getting ssh connection to 10.83.20.67
    DEBUG --- ssh cionnection to host 10.83.20.67 established
    DEBUG --- connection 10.83.20.67 named abr2 established
    DEBUG --- doTestOSPF : at 10.83.20.67
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.67
    DEBUG --- doCompare at 10.83.20.67
    DEBUG --- starting to do config changes at 10.83.20.67
    DEBUG --- doLoad at 10.83.20.67
    DEBUG --- commit check at 10.83.20.67
    DEBUG --- doCommitCheck at 10.83.20.67
    DEBUG --- commiting changes at 10.83.20.67
    DEBUG --- doCommit at 10.83.20.67
    FLOW -- done job at 10.83.20.67
    FLOW -- going sleep at 10.83.20.67
    FLOW -- checking job status 10.83.20.67
    DEBUG --- getting ssh connection to 10.83.20.67
    DEBUG --- ssh cionnection to host 10.83.20.67 established
    DEBUG --- connection 10.83.20.67 named abr2 established
    DEBUG --- doTestOSPF : at 10.83.20.67
    FLOW -- commiting the configuration at 10.83.20.67
    DEBUG --- doCommit at 10.83.20.67
    FLOW -- configuration commited at 10.83.20.67
    FLOW -- ************************************
    FLOW -- checking 10.83.20.68
    DEBUG --- getting ssh connection to 10.83.20.68
    DEBUG --- ssh cionnection to host 10.83.20.68 established
    DEBUG --- connection 10.83.20.68 named r1 established
    DEBUG --- doTestOSPF : at 10.83.20.68
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.68
    DEBUG --- doCompare at 10.83.20.68
    DEBUG --- starting to do config changes at 10.83.20.68
    DEBUG --- doLoad at 10.83.20.68
    DEBUG --- commit check at 10.83.20.68
    DEBUG --- doCommitCheck at 10.83.20.68
    DEBUG --- commiting changes at 10.83.20.68
    DEBUG --- doCommit at 10.83.20.68
    FLOW -- done job at 10.83.20.68
    FLOW -- going sleep at 10.83.20.68
    FLOW -- checking job status 10.83.20.68
    DEBUG --- getting ssh connection to 10.83.20.68
    DEBUG --- ssh cionnection to host 10.83.20.68 established
    DEBUG --- connection 10.83.20.68 named r1 established
    DEBUG --- doTestOSPF : at 10.83.20.68
    FLOW -- commiting the configuration at 10.83.20.68
    DEBUG --- doCommit at 10.83.20.68
    FLOW -- configuration commited at 10.83.20.68
    FLOW -- ************************************
    FLOW -- checking 10.83.20.69
    DEBUG --- getting ssh connection to 10.83.20.69
    DEBUG --- ssh cionnection to host 10.83.20.69 established
    DEBUG --- connection 10.83.20.69 named r2 established
    DEBUG --- doTestOSPF : at 10.83.20.69
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/0.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/0.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/0.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.69
    DEBUG --- doCompare at 10.83.20.69
    DEBUG --- starting to do config changes at 10.83.20.69
    DEBUG --- doLoad at 10.83.20.69
    DEBUG --- commit check at 10.83.20.69
    DEBUG --- doCommitCheck at 10.83.20.69
    DEBUG --- commiting changes at 10.83.20.69
    DEBUG --- doCommit at 10.83.20.69
    FLOW -- done job at 10.83.20.69
    FLOW -- going sleep at 10.83.20.69
    FLOW -- checking job status 10.83.20.69
    DEBUG --- getting ssh connection to 10.83.20.69
    DEBUG --- ssh cionnection to host 10.83.20.69 established
    DEBUG --- connection 10.83.20.69 named r2 established
    DEBUG --- doTestOSPF : at 10.83.20.69
    FLOW -- commiting the configuration at 10.83.20.69
    DEBUG --- doCommit at 10.83.20.69
    FLOW -- configuration commited at 10.83.20.69
    FLOW -- ************************************
    FLOW -- checking 10.83.20.70
    DEBUG --- getting ssh connection to 10.83.20.70
    DEBUG --- ssh cionnection to host 10.83.20.70 established
    DEBUG --- connection 10.83.20.70 named r3 established
    DEBUG --- doTestOSPF : at 10.83.20.70
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/0.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/0.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/0.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.70
    DEBUG --- doCompare at 10.83.20.70
    DEBUG --- starting to do config changes at 10.83.20.70
    DEBUG --- doLoad at 10.83.20.70
    DEBUG --- commit check at 10.83.20.70
    DEBUG --- doCommitCheck at 10.83.20.70
    DEBUG --- commiting changes at 10.83.20.70
    DEBUG --- doCommit at 10.83.20.70
    FLOW -- done job at 10.83.20.70
    FLOW -- going sleep at 10.83.20.70
    FLOW -- checking job status 10.83.20.70
    DEBUG --- getting ssh connection to 10.83.20.70
    DEBUG --- ssh cionnection to host 10.83.20.70 established
    DEBUG --- connection 10.83.20.70 named r3 established
    DEBUG --- doTestOSPF : at 10.83.20.70
    FLOW -- commiting the configuration at 10.83.20.70
    DEBUG --- doCommit at 10.83.20.70
    FLOW -- configuration commited at 10.83.20.70
    FLOW -- ************************************
    FLOW -- checking 10.83.20.71
    DEBUG --- getting ssh connection to 10.83.20.71
    DEBUG --- ssh cionnection to host 10.83.20.71 established
    DEBUG --- connection 10.83.20.71 named r4 established
    DEBUG --- doTestOSPF : at 10.83.20.71
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/1.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/2.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface ge-0/0/3.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.71
    DEBUG --- doCompare at 10.83.20.71
    DEBUG --- starting to do config changes at 10.83.20.71
    DEBUG --- doLoad at 10.83.20.71
    DEBUG --- commit check at 10.83.20.71
    DEBUG --- doCommitCheck at 10.83.20.71
    DEBUG --- commiting changes at 10.83.20.71
    DEBUG --- doCommit at 10.83.20.71
    FLOW -- done job at 10.83.20.71
    FLOW -- going sleep at 10.83.20.71
    FLOW -- checking job status 10.83.20.71
    DEBUG --- getting ssh connection to 10.83.20.71
    DEBUG --- ssh cionnection to host 10.83.20.71 established
    DEBUG --- connection 10.83.20.71 named r4 established
    DEBUG --- doTestOSPF : at 10.83.20.71
    FLOW -- commiting the configuration at 10.83.20.71
    DEBUG --- doCommit at 10.83.20.71
    FLOW -- configuration commited at 10.83.20.71
    {'10.83.20.70': {'status': 'done'}, '10.83.20.71': {'status': 'done'}, '10.83.20.67': {'status': 'done'}, '10.83.20.66': {'status': 'done'}, '10.83.20.69': {'status': 'done'}, '10.83.20.68': {'status': 'done'}}
    >>>
    >>>
    >>>
    ==== RESTART: C:\Users\and_andreev\Desktop\tools\lab-case2\conf_change.py ====
    FLOW -- ************************************
    FLOW -- checking 10.83.20.66
    DEBUG --- getting ssh connection to 10.83.20.66
    DEBUG --- ssh cionnection to host 10.83.20.66 established
    DEBUG --- connection 10.83.20.66 named abr1 established
    DEBUG --- doTestOSPF : at 10.83.20.66
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.66
    DEBUG --- doCompare at 10.83.20.66
    DEBUG --- starting to do config changes at 10.83.20.66
    DEBUG --- doLoad at 10.83.20.66
    DEBUG --- commit check at 10.83.20.66
    DEBUG --- doCommitCheck at 10.83.20.66
    DEBUG --- commiting changes at 10.83.20.66
    DEBUG --- doCommit at 10.83.20.66
    FLOW -- done job at 10.83.20.66
    FLOW -- going sleep at 10.83.20.66
    FLOW -- checking job status 10.83.20.66
    DEBUG --- getting ssh connection to 10.83.20.66
    DEBUG --- ssh cionnection to host 10.83.20.66 established
    DEBUG --- connection 10.83.20.66 named abr1 established
    DEBUG --- doTestOSPF : at 10.83.20.66
    FLOW -- commiting the configuration at 10.83.20.66
    DEBUG --- doCommit at 10.83.20.66
    FLOW -- configuration commited at 10.83.20.66
    FLOW -- ************************************
    FLOW -- checking 10.83.20.67
    DEBUG --- getting ssh connection to 10.83.20.67
    DEBUG --- ssh cionnection to host 10.83.20.67 established
    DEBUG --- connection 10.83.20.67 named abr2 established
    DEBUG --- doTestOSPF : at 10.83.20.67
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 metric 1
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.67
    DEBUG --- doCompare at 10.83.20.67
    DEBUG --- starting to do config changes at 10.83.20.67
    DEBUG --- doLoad at 10.83.20.67
    DEBUG --- commit check at 10.83.20.67
    DEBUG --- doCommitCheck at 10.83.20.67
    DEBUG --- commiting changes at 10.83.20.67
    DEBUG --- doCommit at 10.83.20.67
    FLOW -- done job at 10.83.20.67
    FLOW -- going sleep at 10.83.20.67
    FLOW -- checking job status 10.83.20.67
    DEBUG --- getting ssh connection to 10.83.20.67
    DEBUG --- ssh cionnection to host 10.83.20.67 established
    DEBUG --- connection 10.83.20.67 named abr2 established
    DEBUG --- doTestOSPF : at 10.83.20.67
    FLOW -- commiting the configuration at 10.83.20.67
    DEBUG --- doCommit at 10.83.20.67
    FLOW -- configuration commited at 10.83.20.67
    FLOW -- ************************************
    FLOW -- checking 10.83.20.68
    DEBUG --- getting ssh connection to 10.83.20.68
    DEBUG --- ssh cionnection to host 10.83.20.68 established
    DEBUG --- connection 10.83.20.68 named r1 established
    DEBUG --- doTestOSPF : at 10.83.20.68
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/2.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/2.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface lo0.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface lo0.0 secondary
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.68
    DEBUG --- doCompare at 10.83.20.68
    DEBUG --- starting to do config changes at 10.83.20.68
    DEBUG --- doLoad at 10.83.20.68
    DEBUG --- commit check at 10.83.20.68
    DEBUG --- doCommitCheck at 10.83.20.68
    DEBUG --- commiting changes at 10.83.20.68
    DEBUG --- doCommit at 10.83.20.68
    FLOW -- done job at 10.83.20.68
    FLOW -- going sleep at 10.83.20.68
    FLOW -- checking job status 10.83.20.68
    DEBUG --- getting ssh connection to 10.83.20.68
    DEBUG --- ssh cionnection to host 10.83.20.68 established
    DEBUG --- connection 10.83.20.68 named r1 established
    DEBUG --- doTestOSPF : at 10.83.20.68
    FLOW -- commiting the configuration at 10.83.20.68
    DEBUG --- doCommit at 10.83.20.68
    FLOW -- configuration commited at 10.83.20.68
    FLOW -- ************************************
    FLOW -- checking 10.83.20.69
    DEBUG --- getting ssh connection to 10.83.20.69
    DEBUG --- ssh cionnection to host 10.83.20.69 established
    DEBUG --- connection 10.83.20.69 named r2 established
    DEBUG --- doTestOSPF : at 10.83.20.69
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/0.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/0.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface lo0.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface lo0.0 secondary
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.69
    DEBUG --- doCompare at 10.83.20.69
    DEBUG --- starting to do config changes at 10.83.20.69
    DEBUG --- doLoad at 10.83.20.69
    DEBUG --- commit check at 10.83.20.69
    DEBUG --- doCommitCheck at 10.83.20.69
    DEBUG --- commiting changes at 10.83.20.69
    DEBUG --- doCommit at 10.83.20.69
    FLOW -- done job at 10.83.20.69
    FLOW -- going sleep at 10.83.20.69
    FLOW -- checking job status 10.83.20.69
    DEBUG --- getting ssh connection to 10.83.20.69
    DEBUG --- ssh cionnection to host 10.83.20.69 established
    DEBUG --- connection 10.83.20.69 named r2 established
    DEBUG --- doTestOSPF : at 10.83.20.69
    FLOW -- commiting the configuration at 10.83.20.69
    DEBUG --- doCommit at 10.83.20.69
    FLOW -- configuration commited at 10.83.20.69
    FLOW -- ************************************
    FLOW -- checking 10.83.20.70
    DEBUG --- getting ssh connection to 10.83.20.70
    DEBUG --- ssh cionnection to host 10.83.20.70 established
    DEBUG --- connection 10.83.20.70 named r3 established
    DEBUG --- doTestOSPF : at 10.83.20.70
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/0.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/0.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface lo0.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface lo0.0 secondary
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.70
    DEBUG --- doCompare at 10.83.20.70
    DEBUG --- starting to do config changes at 10.83.20.70
    DEBUG --- doLoad at 10.83.20.70
    DEBUG --- commit check at 10.83.20.70
    DEBUG --- doCommitCheck at 10.83.20.70
    DEBUG --- commiting changes at 10.83.20.70
    DEBUG --- doCommit at 10.83.20.70
    FLOW -- done job at 10.83.20.70
    FLOW -- going sleep at 10.83.20.70
    FLOW -- checking job status 10.83.20.70
    DEBUG --- getting ssh connection to 10.83.20.70
    DEBUG --- ssh cionnection to host 10.83.20.70 established
    DEBUG --- connection 10.83.20.70 named r3 established
    DEBUG --- doTestOSPF : at 10.83.20.70
    FLOW -- commiting the configuration at 10.83.20.70
    DEBUG --- doCommit at 10.83.20.70
    FLOW -- configuration commited at 10.83.20.70
    FLOW -- ************************************
    FLOW -- checking 10.83.20.71
    DEBUG --- getting ssh connection to 10.83.20.71
    DEBUG --- ssh cionnection to host 10.83.20.71 established
    DEBUG --- connection 10.83.20.71 named r4 established
    DEBUG --- doTestOSPF : at 10.83.20.71
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/1.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/2.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/2.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 secondary
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface ge-0/0/3.0 metric 1
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.250 interface lo0.0 interface-type p2p
    DEBUG --- doTestOSPF found missing line set protocols ospf area 0.0.0.200 interface lo0.0 secondary
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.71
    DEBUG --- doCompare at 10.83.20.71
    DEBUG --- starting to do config changes at 10.83.20.71
    DEBUG --- doLoad at 10.83.20.71
    DEBUG --- commit check at 10.83.20.71
    DEBUG --- doCommitCheck at 10.83.20.71
    DEBUG --- commiting changes at 10.83.20.71
    DEBUG --- doCommit at 10.83.20.71
    FLOW -- done job at 10.83.20.71
    FLOW -- going sleep at 10.83.20.71
    FLOW -- checking job status 10.83.20.71
    DEBUG --- getting ssh connection to 10.83.20.71
    DEBUG --- ssh cionnection to host 10.83.20.71 established
    DEBUG --- connection 10.83.20.71 named r4 established
    DEBUG --- doTestOSPF : at 10.83.20.71
    FLOW -- commiting the configuration at 10.83.20.71
    DEBUG --- doCommit at 10.83.20.71
    FLOW -- configuration commited at 10.83.20.71
    {'10.83.20.70': {'status': 'done'}, '10.83.20.71': {'status': 'done'}, '10.83.20.67': {'status': 'done'}, '10.83.20.66': {'status': 'done'}, '10.83.20.69': {'status': 'done'}, '10.83.20.68': {'status': 'done'}}
    >>>
    ==== RESTART: C:\Users\and_andreev\Desktop\tools\lab-case2\conf_change.py ====
    FLOW -- ************************************
    FLOW -- checking 10.83.20.66
    DEBUG --- getting ssh connection to 10.83.20.66
    DEBUG --- ssh cionnection to host 10.83.20.66 established
    DEBUG --- connection 10.83.20.66 named abr1 established
    DEBUG --- doTestOSPF : at 10.83.20.66
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.66
    DEBUG --- doCompare at 10.83.20.66
    DEBUG --- starting to do config changes at 10.83.20.66
    DEBUG --- doLoad at 10.83.20.66
    DEBUG --- commit check at 10.83.20.66
    DEBUG --- doCommitCheck at 10.83.20.66
    DEBUG --- commiting changes at 10.83.20.66
    DEBUG --- doCommit at 10.83.20.66
    FLOW -- done job at 10.83.20.66
    FLOW -- going sleep at 10.83.20.66
    FLOW -- checking job status 10.83.20.66
    DEBUG --- getting ssh connection to 10.83.20.66
    DEBUG --- ssh cionnection to host 10.83.20.66 established
    DEBUG --- connection 10.83.20.66 named abr1 established
    DEBUG --- doTestOSPF : at 10.83.20.66
    FLOW -- commiting the configuration at 10.83.20.66
    DEBUG --- doCommit at 10.83.20.66
    FLOW -- configuration commited at 10.83.20.66
    FLOW -- ************************************
    FLOW -- checking 10.83.20.67
    DEBUG --- getting ssh connection to 10.83.20.67
    DEBUG --- ssh cionnection to host 10.83.20.67 established
    DEBUG --- connection 10.83.20.67 named abr2 established
    DEBUG --- doTestOSPF : at 10.83.20.67
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.67
    DEBUG --- doCompare at 10.83.20.67
    DEBUG --- starting to do config changes at 10.83.20.67
    DEBUG --- doLoad at 10.83.20.67
    DEBUG --- commit check at 10.83.20.67
    DEBUG --- doCommitCheck at 10.83.20.67
    DEBUG --- commiting changes at 10.83.20.67
    DEBUG --- doCommit at 10.83.20.67
    FLOW -- done job at 10.83.20.67
    FLOW -- going sleep at 10.83.20.67
    FLOW -- checking job status 10.83.20.67
    DEBUG --- getting ssh connection to 10.83.20.67
    DEBUG --- ssh cionnection to host 10.83.20.67 established
    DEBUG --- connection 10.83.20.67 named abr2 established
    DEBUG --- doTestOSPF : at 10.83.20.67
    FLOW -- commiting the configuration at 10.83.20.67
    DEBUG --- doCommit at 10.83.20.67
    FLOW -- configuration commited at 10.83.20.67
    FLOW -- ************************************
    FLOW -- checking 10.83.20.68
    DEBUG --- getting ssh connection to 10.83.20.68
    DEBUG --- ssh cionnection to host 10.83.20.68 established
    DEBUG --- connection 10.83.20.68 named r1 established
    DEBUG --- doTestOSPF : at 10.83.20.68
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.68
    DEBUG --- doCompare at 10.83.20.68
    DEBUG --- starting to do config changes at 10.83.20.68
    DEBUG --- doLoad at 10.83.20.68
    DEBUG --- commit check at 10.83.20.68
    DEBUG --- doCommitCheck at 10.83.20.68
    DEBUG --- commiting changes at 10.83.20.68
    DEBUG --- doCommit at 10.83.20.68
    FLOW -- done job at 10.83.20.68
    FLOW -- going sleep at 10.83.20.68
    FLOW -- checking job status 10.83.20.68
    DEBUG --- getting ssh connection to 10.83.20.68
    DEBUG --- ssh cionnection to host 10.83.20.68 established
    DEBUG --- connection 10.83.20.68 named r1 established
    DEBUG --- doTestOSPF : at 10.83.20.68
    FLOW -- commiting the configuration at 10.83.20.68
    DEBUG --- doCommit at 10.83.20.68
    FLOW -- configuration commited at 10.83.20.68
    FLOW -- ************************************
    FLOW -- checking 10.83.20.69
    DEBUG --- getting ssh connection to 10.83.20.69
    DEBUG --- ssh cionnection to host 10.83.20.69 established
    DEBUG --- connection 10.83.20.69 named r2 established
    DEBUG --- doTestOSPF : at 10.83.20.69
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.69
    DEBUG --- doCompare at 10.83.20.69
    DEBUG --- starting to do config changes at 10.83.20.69
    DEBUG --- doLoad at 10.83.20.69
    DEBUG --- commit check at 10.83.20.69
    DEBUG --- doCommitCheck at 10.83.20.69
    DEBUG --- commiting changes at 10.83.20.69
    DEBUG --- doCommit at 10.83.20.69
    FLOW -- done job at 10.83.20.69
    FLOW -- going sleep at 10.83.20.69
    FLOW -- checking job status 10.83.20.69
    DEBUG --- getting ssh connection to 10.83.20.69
    DEBUG --- ssh cionnection to host 10.83.20.69 established
    DEBUG --- connection 10.83.20.69 named r2 established
    DEBUG --- doTestOSPF : at 10.83.20.69
    FLOW -- commiting the configuration at 10.83.20.69
    DEBUG --- doCommit at 10.83.20.69
    FLOW -- configuration commited at 10.83.20.69
    FLOW -- ************************************
    FLOW -- checking 10.83.20.70
    DEBUG --- getting ssh connection to 10.83.20.70
    DEBUG --- ssh cionnection to host 10.83.20.70 established
    DEBUG --- connection 10.83.20.70 named r3 established
    DEBUG --- doTestOSPF : at 10.83.20.70
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.70
    DEBUG --- doCompare at 10.83.20.70
    DEBUG --- starting to do config changes at 10.83.20.70
    DEBUG --- doLoad at 10.83.20.70
    DEBUG --- commit check at 10.83.20.70
    DEBUG --- doCommitCheck at 10.83.20.70
    DEBUG --- commiting changes at 10.83.20.70
    DEBUG --- doCommit at 10.83.20.70
    FLOW -- done job at 10.83.20.70
    FLOW -- going sleep at 10.83.20.70
    FLOW -- checking job status 10.83.20.70
    DEBUG --- getting ssh connection to 10.83.20.70
    DEBUG --- ssh cionnection to host 10.83.20.70 established
    DEBUG --- connection 10.83.20.70 named r3 established
    DEBUG --- doTestOSPF : at 10.83.20.70
    FLOW -- commiting the configuration at 10.83.20.70
    DEBUG --- doCommit at 10.83.20.70
    FLOW -- configuration commited at 10.83.20.70
    FLOW -- ************************************
    FLOW -- checking 10.83.20.71
    DEBUG --- getting ssh connection to 10.83.20.71
    DEBUG --- ssh cionnection to host 10.83.20.71 established
    DEBUG --- connection 10.83.20.71 named r4 established
    DEBUG --- doTestOSPF : at 10.83.20.71
    FLOW -- conf not exist, doing change
    DEBUG --- doJob at 10.83.20.71
    DEBUG --- doCompare at 10.83.20.71
    DEBUG --- starting to do config changes at 10.83.20.71
    DEBUG --- doLoad at 10.83.20.71
    DEBUG --- commit check at 10.83.20.71
    DEBUG --- doCommitCheck at 10.83.20.71
    DEBUG --- commiting changes at 10.83.20.71
    DEBUG --- doCommit at 10.83.20.71
    FLOW -- done job at 10.83.20.71
    FLOW -- going sleep at 10.83.20.71
    FLOW -- checking job status 10.83.20.71
    DEBUG --- getting ssh connection to 10.83.20.71
    DEBUG --- ssh cionnection to host 10.83.20.71 established
    DEBUG --- connection 10.83.20.71 named r4 established
    DEBUG --- doTestOSPF : at 10.83.20.71
    FLOW -- commiting the configuration at 10.83.20.71
    DEBUG --- doCommit at 10.83.20.71
    FLOW -- configuration commited at 10.83.20.71
    {'10.83.20.70': {'status': 'done'}, '10.83.20.71': {'status': 'done'}, '10.83.20.67': {'status': 'done'}, '10.83.20.66': {'status': 'done'}, '10.83.20.69': {'status': 'done'}, '10.83.20.68': {'status': 'done'}}
    >>>


    1. The Complete IS-IS Routing Protocol — Hannes Gredler, Walter Goralski
    2. OSPF; Anatomy of an Internet Routing Protocol — John T. Moy
    3. Network Mergers and Migrations: Junos Design and Implementation — Gonzalo Gomez Herrero, Jan Anton Bernal Van Der Ven
    4. OSPF Multi-Area Adjacency — tools.ietf.org/html/rfc5185

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 1

    Only users with full accounts can post comments. Log in, please.