И снова автоматизация: Python «дополз» до маршрутизаторов

в 8:30, , рубрики: cli, huawei, ops, python, Блог компании Huawei, Программирование

image

Скорость развития технологий в наши дни поражает. Скачок научно-технического прогресса в последние годы можно сравнить разве что с темпами развития космической отрасли в период с конца 50-х по середину 70-х годов ХХ века. Как тогда присутствие человека в космосе стало реальностью, так же и сейчас повсеместная замена людей машинами уже не кажется чем-то заоблачным.

Автоматизация процессов стала полноценным «трендом» нашего времени и продолжает расширять свое влияние практически во всех сферах деятельности: начиная с сельского хозяйства и заканчивая «умными домами» или искусственным интеллектом.

Данная тенденция диктует свои правила игры и в сфере бизнеса. Игроки рынка, недостаточно инвестирующие в оптимизацию своих бизнес- и производственных процессов, в их удешевление и ускорение путем автоматизации, совсем скоро окажутся «за бортом».

Автоматизация производства – это, если хотите, уже гигиена. И речь здесь идет как о производстве автомобилей (с заменой ручной сборки конвейером), так и о производстве программного обеспечения (с заменой ручного тестирования автотестами) или предоставлении услуг связи (с заменой ручного труда телефонисток сначала на коммутационное оборудование, а затем и вовсе на новые технологии связи).

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

В «первой серии» пойдет речь о средствах управления событиями, реализованных в оборудовании Huawei.

Управление событиями

Любой сетевой протокол содержит в себе описание реакции на определенные события. Например, при падении интерфейса, включенного в процесс OSPF или RIP, маршрутизатор, обнаруживший это событие, рассылает уведомления своим соседям. Но множество реакций на события, реализованное в любом стандартном протоколе, не исчерпывает всего многообразия задач, с которыми может столкнуться специалист, обслуживающий систему. Рассмотрим пример:
image
В данном случае, как мы видим, по каждому внешнему каналу передаются как данные, так и голос: настроен QoS, выделяющий по 50% пропускной способности каждого канала для голосового трафика. Но при падении одного из каналов необходимо изменить настройки оставшегося таким образом, чтобы приоритетная очередь для голосового трафика занимала не 50%, а 70%.

Эту задачу, безусловно, можно решить с использованием NMS- или SDN-контроллера (т.е. внешней управляющей системы). Также, вероятно, можно решить ее и стандартными средствами на маршрутизаторе, но данное решение весьма неочевидно.

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

image
Вот здесь-то и приходит «звездный час» системы управления событиями, которая была внедрена нашей компанией в сетевую OS Huawei.

Система управления событиями OPS (Open Programming System) позволяет автоматически выполнять определенный набор действий (изменять конфигурацию, сохранять файл или что-либо еще) при возникновении некоторых событий.

Перейдем к деталям.

Оборудование, поддерживающее OPS

Система OPS в настоящий момент поддерживается на коммутаторах серии CE и на маршрутизаторах серий NE40 и AR. У каждой из этих моделей есть свои особенности поддержки OPS, которых мы обязательно коснемся.

Программирование

Правила реакции на события в общем случае можно создавать с использованием CLI (командной строки) или же писать на Python (языке программирования). Для описания самих правил можно также использовать как CLI, так и Python. При этом на коммутаторах CE можно использовать оба инструмента, на маршрутизаторах AR – только Python, а на маршрутизаторах NE40 – только командную строку.

Давайте взглянем на пример описания события и реакции на него при помощи CLI.

Пример #1:

[~CE]ops
[~CE-ops]assistant test1
[*CE-ops-assistant-test1]condition syslog pattern “.*Loopback[3-9].*own”
[*CE-ops-assistant-test1]execute 1.1 command sys
[*CE-ops-assistant-test1]execute 1.2 command int gi0/0/0
[*CE-ops-assistant-test1]execute 1.3 command undo shutdown
[*CE-ops-assistant-test1]execute 1.4 command commit
[*CE-ops-assistant-test1]commit

//Расшифруем: если какой-либо из интерфейсов Loopback3, Loopback 41 и т.д. перейдет в состояние down, то интерфейс Gigabit Ethernet 0/0/0 выйдет из состояния administratively down.

В другом примере описание события задано при помощи CLI, а реакция описана на Python (в файле backupconfig.py).

Пример #2:

[~CE-ops] assistant Name /* create assistant */
[*CE-ops-assistant-Name] condition event feature configuration name cfg_file_change
[*SwitchA-ops-assistant-backup_config] execute 1 python backupconfig.py
[*SwitchA-ops-assistant-backup_config] commit

//Расшифруем: при изменении файла конфигурации запускается скрипт backupconfig.

Типы событий

С помощью CLI можно настраивать реакцию на следующие типы событий:

  • запись в syslog;
  • запись в trapbuffer;
  • посылку или прием SNMP;
  • возникновение аварии (alarm);
  • значение таймера.

Благодаря Python можно дополнительно отследить:

  • ввод команды;
  • изменение маршрута;
  • изменение состояния интерфейса;
  • результат работы NQA (SLA).

Реакция на события

Наиболее часто используемым является изменение конфигурации устройства. В самом простом случае при помощи CLI задается последовательность команд (как показано в примере #1), второй параметр определяет последовательность исполнения (в алфавитно-цифровом порядке).

В первом примере последовательно вводятся команды:

  1. Вход в режим конфигурирования (system-view);
  2. Вход в подрежим конфигурирования интерфейса Gigabit 0/0/0;
  3. Поднятие интерфейса;
  4. Сохранение изменений.

OPS позволяет указать до 10 последовательных команд. Если же необходимо выполнить больше 10 команд, можно воспользоваться bat-файлом и запустить его при помощи команды execute 1 batch-file myfile.bat

Очевидно, с использованием Python можно применять более сложные конструкции, чем линейное выполнение последовательных команд конфигурирования.

Помимо простого выполнения команд, OPS позволяет:

  • сохранять и анализировать сохраненные переменные;
  • высылать уведомления на syslog-сервер;
  • уведомлять пользователя, принимать от него и анализировать ввод с терминала;
  • выполнять вход на удаленные устройства по протоколам telnet, ssh и др. и выполнять там какие-либо действия.

Немного магии на «Питоне» :)

Рассмотрим пример простой оболочки (shell).

  1. Напишем на Python простейшую оболочку, которая будет считывать ввод пользователя и выполнять команды Python. На этом примере рассмотрим функции ввода/вывода на терминал, исполнение команд и анализ результата исполнения.
    import os,sys
    def run(c):  
        b=c.split()
        if b[0]== «ls»:
            if b.__len__() == 1:
                b.append(«/»);
            res = os.listdir(b[1])
            print
            print(res)
        else:
            try:
                exec(c)
                return 1
            except:
                print(«Something wrong»)
                return 0
    
    def get_command(ops,VTY):
        a, b = ops.terminal.write(«>>>«,vty = VTY)
        a, b = ops.terminal.read(maxLen = 200,timeout = 60,vty=VTY)
        if a==None:
            a='q';
        return a
    
    #Ставим ловушку на ввод команды sh
    def ops_condition (ops):
            value, err_str = ops.cli.subscribe(«cli1», «^sh$», enter=True, sync=True, sync_wait=500)
            return 0
    # Собственно, сам shell
    def ops_execute (ops):
        key, value = ops.environment.get(«_cli_vty»)
        while 2<3:
            command=get_command(ops,key)
            if command == «q»:
                break;
            if  command <> '':
                run(command)
                continue
        print
        print(«exitn»)
        return 0

    В данном случае мы видим четыре функции:

    • run(command) – выполняет команду command, возвращаемое значение не анализируется;
    • get_command(OPS,VTY) – на вход подается встроенный объект OPS и номер терминала, возвращает введенную команду;
    • «ловушку» ops_condition(OPS);
    • исполнение ops_execute(OPS) – в случае срабатывания «ловушки».

    Функции ops_condition(OPS) и ops_execute(OPS) являются обязательными.

    run(command)
    Функция исполняет команду Python. Если введена команда ls, которой в Python нет, то она заменяется на имеющуюся в Python команду os.listdir(path).

    Если рath не указан, делается подстановка path=”/”. Таким образом можно создавать различные alias, т.е. аббревиатуры, которые будут заменяться на развернутые выражения.

    get_command(OPS,VTY)
    Считывает и возвращает пользовательский ввод. Если ввода не было в течение 60 секунд, возвращает значение окончания “q” – quit.

    ops_condition(OPS)
    «Ловушка». В нашем случае ставим триггер на ввод команды sh:
    ops.cli.subscribe(«cli1», «^sh$», enter=True, sync=True, sync_wait=500)
    cli1” – имя «ловушки», нужно для обрабатывания комплексного события, состоящего из нескольких «ловушек»;
    ^sh$ – regexp, описывающий строку, состоящую только из двух символов, а именно
    sh. Например, под regexp ^sh попала бы и команда shutdown, а под sh – traffic-shaping.

    ops_execute(OPS)
    Сначала считывает имя терминала в переменную key, а затем в бесконечном цикле (с помощью незамысловатого while 2<3) считывает ввод пользователя в переменную command и исполняет его (run(command)) или прекращает исполнение if command==”q”.

  2. Собственно, посмотрим, что получилось. Ввод пользователя будет обозначен болдом, а ответ от маршрутизатора – синим цветом.

    Скрипт должен быть скопирован на flash маршрутизатора, а затем его необходимо скомпилировать:

    <AR2>ops install file <scriptname.py>
    Затем необходимо создать assistant:
    <AR2>system-view
    Enter system view, return user view with Ctrl+Z.
    [AR2]ops
    [AR2-ops]script-assistant python <scriptname.py>

    Проверяем:

    <AR2>sh
    >>>
    Получили приглашение ввода. Тут нужно заметить, что контекст исполнения в Python сохраняется только внутри exec(). Мы не использовали форму exec(code,global,local), поэтому присвоение значения переменной и его печать задаем в одной строке, то есть внутри одного и того же exec.

    >>>a=2+3; print(«nr»);print a
    5

    Конечно, можно было воспользоваться следующей формой:

    >>>global a
    >>>globals()[«a»]=2+3
    >>>print a

    Результат был бы тот же, и на самом деле это не имеет значения, поскольку в реальных программах мы не будем использовать exec почти никогда, а этот простенький shell написан лишь для изучения возможностей Python на маршрутизаторах Huawei.

Работа с файлами

>>>a=dir(os);print a['EX_CANTCREAT', …'O_APPEND', 'O_ASYNC', 'O_CREAT', …, 'O_RDWR', …]

Как видите, здесь присутствуют константы для создания файлов, и теперь можно попробовать создать файл.

Работать будем с каталогом sd1: или /mnt/sd1 – это одно и то же.

>>>ls /mnt/sd1
['AR2220-V200R003C01SPC900.cc',…, 'V600R008C10SPC300_RM.mod', 'AR2220-V200R007C00SPC600.cc', 'shelldir', 'python', …]– видим, что в выводе присутствуют файлы из sd1:. Сравним:
<AR2> dir

Directory of sd1:/
  Idx  Attr     Size(Byte)  Date        Time(LMT)  FileName
    0  -rw-     94,689,536  Apr 23 2014 17:38:30   AR2220-V200R003C01SPC900.cc
…
   22  -rw-      1,113,612  Dec 16 2015 14:38:44   V600R008C10SPC300_RM.mod
   23  -rw-    123,975,040  Mar 15 2016 13:18:56   AR2220-V200R007C00SPC600.cc
   24  drw-              -  Apr 01 2016 10:16:28   shelldir
   25  drw-              -  Apr 06 2016 14:45:26   python 

Самый простой способ создать файл:

>>>os.system('echo qqq > /mnt/sd1/s.s')
<AR2> dir s*

Directory of sd1:/
  Idx  Attr     Size(Byte)  Date        Time(LMT)  FileName
    9  -rw-              4  Oct 09 2016 17:24:15   s.s
1,961,192 KB total available (1,402,760 KB free)

<AR2>more s.s

Qqq

Собственно, вот и наш файл. Теперь возникает вопрос: как читать из него? В данном случае мы воспользуемся теми средствами, которые предоставляет модуль os.

>>>f=os.open('/mnt/sd1/s.s',os.O_CREAT|os.O_RDWR);print f
47
>>>
str=’222';os.write(47,str)
>>>str='nr111';os.write(47,str)
>>>os.close(47)
<AR2>more s.s
222
111

К слову, аналогичного результата можно добиться, используя os.system:

>>>os.system('echo 222 > /mnt/sd1/d.d')
>>>os.system('echo 111 >> /mnt/sd1/d.d')
<AR2>more d.d
222
111

Теперь прочитаем из файла:

>>>f=os.open('/mnt/sd1/s.s',os.O_RDONLY);print f
49
>>>s=os.read(49,8);print s
222
111

Как видите, работать с файлами в оболочке OPS достаточно просто, при этом можно писать довольно сложные обработчики событий, используя описанный функционал.

Функционал, который обеспечивает OPS, позволяет решать те же задачи, которые решает аналогичная система управления событиями EEM (Embedded Event Management) от Cisco Systems, за исключением отправки e-mail-сообщений.

Но, во-первых, это лишь первая реализация Python, и в следующих версиях ожидается дополнительный функционал. Во-вторых, e-mail все-таки можно оправить через open relay, используя telnet на порт 25. Функции для остальных обработчиков и выполнения действий полностью идентичны Cisco EEM.

Конец первой серии

Мы попытались продемонстрировать некоторые возможности применения CLI и Python для управления событиями на маршрутизаторах Huawei. Насколько это оказалось полезным, судить вам. Будем рады увидеть ваши комментарии, вопросы и отзывы.

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

А пока завершим первую серию словами юного Сережи Сыроежкина, героя фильма «Приключения Электроника»:

До чего дошел прогресс: труд физический исчез,
Да и умственный заменит механический процесс.

Музыка, титры, to be continued…

Автор: Huawei

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js