ETL

В мире многообразия систем, выполняющих различные задачи, часто возникает задача на основании данных одной или нескольких систем создать объекты (таблицы или сущности) в другой системе. В общем случае за это отвечает механизм ETL.

ETL (от англ. ExtractTransformLoad — дословно «извлечение, преобразование, загрузка»). Это системы корпоративного класса, которые применяются, чтобы привести к одним справочникам и загрузить одну систему данные из нескольких разных учетных систем. Т.е. решает задачу однонаправленного обмена данными между исходной и целевой системой.

Подробнее можно почитать:


NOC ETL

В NOCе реализован базовый функционал ETL - возможность извлекать данные из внешней системы (Remote System) и на них основе получать объеты в НОКе. На данный момент возможна вгрузка следующих сущностей:

Кратко механизм выглядит так:

  1. Реализуется адаптера выгрузки (extractor). Его задача - получить данные из внешней системы и отдать в виде списка полей, определённых в загрузчике. Подробнее см главу Загрузка
  2. В интерфейсе настраивается Внешняя система и выбираются реализованные загрузчики
  3. После настройки даётся команда ./noc etl extract <remote_system_name>. Происходит извлечение информации из внешней системе (при помощи адаптера, написанного на шаге 1). Всё складывается в файлы import.csv.gz в директории /var/lib/noc/import/<remote_system_name>/<loader_name>/import.csv.gz
  4. Командой ./noc etl check <remote_system_name> проверяем целостность выгрузки
  5. Командой ./noc etl diff <remote_system_name> смотрим изменения относительно предыдущего файла выгрузки. В первым раз все объекты будут показаны как новые.
  6. Командой ./noc etl load <remote_system_name> заливаем данные в НОК (при этом создаются объекты соотв. загрузчику).

После окончания файл import.csv.gz перемещается в папку /var/lib/noc/import/<remote_system_name>/<loader_name>/archive/import_date.csv.gz и файл mappings.csv дополняется связкой: ID внешней системы <-> ID НОКа

Путь /var/lib/noc/import задаётся настройкой path -> etl_import

Настройка внешней системы

Настройка начинается в пункте меню Main -> Setup -> Remote Systems. После нажатия на кнопку Add открывается форма создания внешней ситемы с пунктами:

Н-р: noc.custom.etl.extractors.zabbix.ZBRemoteSystem рассчитывает, что файлик лежит в кастоме по пути <custom_folder>/etl/extractor/zabbix.py

Также, в объектах, поддерживающих создание из механизма ETL присутствуют поля:

Поля Remote SystemRemote ID заполняются автоматически. Вносить изменения вручную не рекомендуется.

После настройки внешней системы дальнейшая работа идёт с командой ./noc etl. Для лучшего понимания мы начнём рассмотрение с последнего этапа - загрузки в НОК.

Загрузка

Загрузка заливка извлечённых данных в НОК выполняется командой ./noc etl load REMOTE_SYSTEM_NAME <loadername>. Происходит применение изменений по следующем правилам:

Важно понимать, что изменения вычисляются относительно предыдущей загрузки (предыдущего состояния) из внешней системы. По этой причине, если внести изменения по полю в НОКе - загрузка эти изменения не откатит.
Также, если потерять архивные файлы по последней выгузке, то все объекты будут пересозданы.

Адаптеры для загрузки (загрузчики), ответственные за создание расположены в директории core/etl/loader. Разберём на примере managedobject(core/etl/loader/managedobject.py):

class ManagedObjectLoader(BaseLoader):
    """
    Managed Object loader
    """
    name = "managedobject"  # Имя (Loader Name)
    model = ManagedObject   # NOC object Model (модель, создаваемая адаптером)
    fields = [        # Список полей, необходимых для создания
                     # объекта
        "id",            
        "name",
        "is_managed",
        "container",
        "administrative_domain",
        "pool",
        "segment",
        "profile",
        "object_profile",
        "static_client_groups",
        "static_service_groups",
        "scheme",
        "address",
        "port",
        "user",
        "password",
        "super_password",
        "snmp_ro",
        "description",
        "auth_profile",
        "tags",
        "tt_system",
        "tt_queue",
        "tt_system_id"
    ]

    mapped_fields = {  # карта связей полей с другими вгрузчиками (loader)
        "administrative_domain": "administrativedomain",
        "object_profile": "managedobjectprofile",
        "segment": "networksegment",
        "container": "container",
        "auth_profile": "authprofile",
        "tt_system": "ttsystem",
        "static_client_groups": "resourcegroup",
        "static_service_groups": "resourcegroup"
    }


Структура загрузчика состоит из аттрибутов:

Остановимся на карте связей подробнее. Для системы нормально, когда одни сущности связываются с другими. Это позволяет не мешать всё в одну кучу, по этой причине и существуют карты связей (mappings map). В примере указано что поле object_profile необходидо связать с вгрузчиком managedobjectprofile. Сама привязка идёт по полям ID (всегда первые в списке), а сам вгрузчик ищется по имени:


Рассмотрим пример загрузчика для ManagedObject Profile

class ManagedObjectProfileLoader(BaseLoader):
    """
    Managed Object Profile loader
    """
    name = "managedobjectprofile"
    model = ManagedObjectProfile
    fields = [
        "id",
        "name",
        "level"
    ]

Как видно, для managedobjectprofile достаточно 3 полей: idимяуровень. При этом, карта связей (mapped_fields) отсутствует.

При работе с картами связей, необходимо помнить - что не все поля являются обязательными. Н-р для модели managedobject обязательными являются: administrative_domainobject_profilesegment

следовательно, для реализаци адаптера выгрузки объектов управления (ManagedObject), необходимо будет реализовать выгрузку для administrativedomainnetworksegment и managedobjectprofile. Иначе при выполнении команды ./noc etl check будет множество ошибок вида:

[noc.core.etl.loader.base] [RS|managedobject] ERROR: Field #4(administrative_domain) == 'administrativedomain' refers to non-existent record: 10106,mos-pma-pta-pta1-sw01#10106,True,,administrativedomain,default,!new,Generic.Host,zb.std.sw,,,2,192.168.3.2,,,,,,,ZB.AUTO,,
[noc.core.etl.loader.base] [RS|managedobject] ERROR: Field #4(administrative_domain) == 'administrativedomain' refers to non-existent record: 10107,mos-pma-lta-lta1-sw01#10107,True,10107,administrativedomain,default,!new,Generic.Host,zb.std.sw,,,2,192.168.3.4,,,,,,,ZB.AUTO,,

Определение и проверка изменений

Проверка выгруженных данныч выполняется командой ./noc etl check REMOTE_SYSTEM_NAME. Происходит проверка файла import.csv на правильность структуры и связей.
Возможные ошибки:

[noc.core.etl.loader.base] [RS|managedobject] ERROR: Field #4(administrative_domain) == 'administrativedomain' refers to non-existent record: 10106,mos-pma-pta-pta1-sw01#10106,True,,administrativedomain,default,!new,Generic.Host,zb.std.sw,,,2,192.168.3.2,,,,,,,ZB.AUTO,,
[noc.core.etl.loader.base] [RS|managedobject] ERROR: Field #4(administrative_domain) == 'administrativedomain' refers to non-existent record: 10107,mos-pma-lta-lta1-sw01#10107,True,,administrativedomain,default,!new,Generic.Host,zb.std.sw,,,2,192.168.3.4,,,,,,,ZB.AUTO,,

Расшифровывается, что поле administrative_domain ссылается на несуществующую запись в выгрузке с administrativedomain (на это указывает поле из mapped_fields) c ID administrativedomain

Команда ./noc etl diff REMOTE_SYSTEM_NAME <ExtractorNAME> позволяет увидеть разницу между последней успешной и текущей загрузками. В построчно формате с указателями:

--- RS.admdiv
--- RS.networksegmentprofile
+ zb.default,zb.default
--- RS.networksegment
+ !new,,Новые,,zb.default
+ !rej,,Отсев,,zb.default
+ !tgfake,,tgfake,,zb.default
--- RS.container
+ 10107,ZabbixHost,PoP | Access,,0,60.646729,56.852081,Екатеринбург, ул. Мира 4
--- RS.resourcegroup
--- RS.managedobjectprofile
+ zb.core.sw,zb.core.sw,35
+ zb.std.sw,zb.std.sw,25
--- RS.administrativedomain
+ zb.root,Заббикс,
--- RS.authprofile
+ ZB.AUTO,ZB.AUTO,,S,,,,,
+ snmp.default,snmp.default,,G,,,,public,
--- RS.ttsystem
--- RS.managedobject
+ 10106,mos-pma-pta-pta1-sw01#10106,True,,zb.root,default,!new,Generic.Host,zb.std.sw,,,2,192.168.3.2,,,,,,,ZB.AUTO,
+ 10107,mos-pma-lta-lta1-sw01#10107,True,10107,zb.root,default,!new,Generic.Host,zb.std.sw,,,2,192.168.3.4,,,,,,,ZB.AUTO,
--- RS.link
--- RS.subscriber
--- RS.serviceprofile
--- RS.service

Есть дополнительный ключ - summary позволяет посмотреть суммарное число изменений:
./noc etl diff --summary REMOTE_SYSTEM_NAME <ExtractorNAME>

              Loader |      New |  Updated |  Deleted
              admdiv |        0 |        0 |        0
networksegmentprofile |        1 |        0 |        0
      networksegment |        3 |        0 |        0
           container |        1 |        0 |        0
       resourcegroup |        0 |        0 |        0
managedobjectprofile |        2 |        0 |        0

Выгрузка (Извлечение)

Выполняется командой ./noc etl extract REMOTE_SYSTEM_NAME <EXTRACTOR_NAME>, где:

При этой команде произойдёт подключение к внешней системе, забор информации с неё и формирование файлов import.csv по пути: <etl_path>/remote_system_name/loader_name/

Термины

Реализация адаптера на примере Zabbix

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

Также Zabbix поддерживает 2 варианта доступа к данным:

  1. API (при помощи WEB API)
  2. Прямой доступ к базе (есть возможность выдать прямой доступ к БД Zabbix)

Воспользуемся вариантов взаимодействия через API. Адаптер можно посмотреть: Файл адаптера выгрузки Zabbix.

Для настройки адаптера сохраним файл в одном из 2 мест:

  1. contrib/share/zabbix.py. В этом случае строчка Handlers будет выглядеть как: noc.contrib.share.zabbix.ZBRemoteSystem.
  2. <custom_path>/etl/extractors/zabbix.py - в этом случае строчка Handlers в настройках будет выглядеть: noc.custom.etl.extractors.zabbix.ZBRemoteSystem

В каждой папке пути необходимо поместить файл __init__.py:


Адаптер требует установленного пакета py-zabbix. Для этого в паке NOCа выполняем: ./bin/pip install py-zabbix

  1. В меню MainSetupRemote Systems WEB интерфейса добавляем внешнюю систему н-р ZABBIX. Отмечаем галочки на реализованных загрузчиках и прописываем в настройках URL, пользователя и пароль:
  2. В папке НОКа выдаём команду ./noc etl extract ZABBIX. Ожидаем окончания выгрузки.
  3. Командой ./noc etl check ZABBIX. Проверяем отсутствие ошибок.
  4. Командой ./noc etl diff ZABBIX смотрим выгруженные объекты.
  5. ./noc etl load ZABBIX запускает заливку объектов.