Плагины SOWA#

Плагин SOWA — это отдельное jar приложение, которое позволяет создавать отдельные сервисы в рамках профиля SOWA и управляемое конфигуратором Platform V SOWA, но при этом не входящее в ее дистрибутив и разрабатываемое прикладными командами.

d49

Требования к взаимодействию плагина и Platform V SOWA#

Для взаимодействия плагина и Platform V SOWA предъявляются следующие требования:

  • плагин должен являться отдельным сервисом, он может стоять перед и/или за сервисами Platform V SOWA в рамках профиля, но не может использоваться без сервисов SOWA;

  • взаимодействие между сервисом плагина и сервисом SOWA происходит по usock;

  • формат взаимодействия — http.

Ограничения плагина#

  • ресурсы плагина находятся отдельно от ресурсов SOWA;

  • сервисы плагина запускаются под пользователем sowactl.

Требования к реализации плагина#

  • плагин должен поддерживать возможность использования сквозного (с SOWA) id запроса, под которым осуществляется логирование:

    • заголовок, в котором передается id, должен быть настраиваемым;

    • имя заголовка должно определяться в схеме сервиса параметром rqUidHeader;

    • заголовок должен передаваться при каждом запросе на SOWA (при взаимодействии SOWA → Plugin хедер также должен быть сгенерирован плагином);

    • формат значения заголовка должен соответствовать маске maxLength=32 и pattern=(-|[0-9]|[a-f]|[A-F]){32});

  • плагин должен реализовывать возможность access и error логов.

Структура плагина и расположение его артефактов#

Каталог с плагином должен иметь префикс «plugin_» и располагаться в директории /sowa/plugins/, например /sowa/plugins/plugin_<plugin_name>/.

В каталоге plugin_<plugin_name> необходимо расположить:

  • директорию lib, которая будет содержать jar-файлы: непосредственно сам плагин и необходимые для его работы библиотеки;

  • schema.yml — YAML схема с описанием сервиса, реализуемого плагином (в схеме при описании экземпляра сервиса обязательно указание поля «id» уникального идентификатора экземпляра сервиса в рамках профиля);

  • _init _.py — класс реализации интерфейса PluginInterface. Реализуемые методы будут вызываться конфигуратором для выполнения стандартных команд;

  • *.j2 — шаблон(ы) преобразования YAML-конфигурации плагина в конфигурационные файлы (например: файлы характеристик приложения, environment-файлы, а также настройки logger).

Одни плагин реализует один тип сервиса.

В качестве примера плагина приведен plugin_example.

plugin_example

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

Для корректной работоспособности плагина из примера необходимо самостоятельно установить следующие библиотеки: junixsocket-common, junixsocket-core, junixsocket-native-common, junixsocket-server, log4j-api, log4j-core, log4j-slf4j-impl, rawhttp-core, slf4j-api.

При конфигурировании профиля создается каталог /sowa/<profile_name>/, где располагается конфигурация всего профиля.

Плагин должен располагать свои артефакты, полученные в результате обработки шаблонов *.j2, в каталоге /sowa/<profile_name>/services/<service_name>_<profile_service_id>.

Внутри каждой директории (для каждого из экземпляров сервиса) должны располагаться:

  • файл service.properties — конфигурационный файл java приложения;

  • файл logger.properties — настройки logger приложения;

  • другие необходимые файлы для настройки экземпляра сервиса.

Логи всего профиля располагаются в /sowalogs/<profile_name>. Подробнее о логировании описано в разделе Системный журнал Руководства администратора.

Плагин должен располагать свои логи в /sowalogs/<profile_name>/services/<service_name>/<profile_service_id>.

Внутри каждой директории всегда есть:

  • <profile_service_id>_access.log — здесь в одной строке данные об одном запросе;

  • <profile_service_id>_error.log — подробные логи по всем запросам, например, app.log;

  • необязательная папка <profile_service_id> для логов evh , в ней:

    • 4 необязательные дочерние папки: client_request, client_response, upstream_request, upstream_response, в каждой из которой файлы <request_id>.log. Подробнее о evh логах описано в разделе Транзакционные логи профиля Руководства по системному администрированию.

Структура логов сервисов плагина и параметры настройки должны соответствовать структуре логов и их настройки совы.

Плагин должен создавать .pid файл после полного запуска java-приложения#

После полного запуска java-процесса ожидается создание .pid файла по пути /sowarun/<profile_name> и соответствующего формату <service_name>_<profile_service_id>.pid, содержащего pid java-процесса.

Плагин должен предоставлять http endpoint, возвращающий статистику сервиса#

Плагин должен иметь http-endpoint с возможностью обращения к нему с использованием UNIX-сокетов. В шаблоне конфигурации сервисов, данный endpoint должен определяться путем объявления параметра statusEndpoint.

statusEndpoint: url

Например,

service_sowa_ipa:
 - id: async_usock_kafka
   statusEndpoint: http://unix:/sowarun/testProfile/async_usock_kafka/statusEndpoint.sock/status

URL endpoint должен формироваться динамически в момент конфигурирования профиля.

При обращении к данному endpoint должен возвращаться json-объект, содержащий статистику данного сервиса и соответствующий JSON-схеме:

{
    "$schema": "https://json-schema.org/draft/2019-09/schema",
    "type": "object",
    "properties": {
        "status": {
            "type": "string",
            "enum": [
                "active",
                "inactive"
            ],
            "description": "Return a current service specific status"
        },
        "overallStats": {
            "$ref": "#/$defs/stats",
            "description": "An object contains current service statistic"
        },
        "backends": {
            "type": "array",
            "description": "An object contains information about service backends",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Name of backend such configuration specified"
                    },
                    "address": {
                        "type": "string",
                        "description": "Address of backend such configuration specified"
                    },
                    "status": {
                        "type": "string",
                        "description": "A current status of specific backend",
                        "oneof": [
                            "active",
                            "inactive",
                            "drain"
                        ]
                    },
                    "stats": {
                        "$ref": "#/$defs/stats"
                    }
                },
                "required": [
                    "name",
                    "address",
                    "status",
                    "stats"
                ]
            }
        }
    },
    "$defs": {
        "stats": {
            "type": "object",
            "properties": {
                "reqPrcCount": {
                    "type": "number",
                    "description": "Total count of processed request"
                },
                "errorCount": {
                    "type": "number",
                    "description": "Total error count of processed request"
                },
                "latencyWamMs": {
                    "type": "number",
                    "description": "A weighted average mean latency request processing throw this point (in milliseconds)"
                },
                "internalLatencyWamMs": {
                    "type": "number",
                    "description": "A weighted average mean latency request processing in this point (in milliseconds), without external communication"
                },
                "throughputWam": {
                    "type": "number",
                    "description": "A weighted average mean throughput request processing throw this point (in request/sec)"
                },
                "inBytes": {
                    "type": "number",
                    "description": "A total income count bytes received by this point"
                },
                "outBytes": {
                    "type": "number",
                    "description": "A total income count bytes returned from  this point"
                },
                "inSpeedWam": {
                    "type": "number",
                    "description": "A weighted average mean receiving speed at this point (bytes/sec)"
                },
                "outSpeed": {
                    "type": "number",
                    "description": "A weighted average mean sent speed from this point (bytes/sec)"
                },
                "errorDistribution": {
                    "type": "array",
                    "description": "An error status distribution",
                    "items": {
                        "type": "object",
                        "properties": {
                            "status": {
                                "type": "string",
                                "description": "Status name",
                                "maxLength": 100
                            },
                            "count": {
                                "type": "number"
                            }
                        },
                        "required": [
                            "status",
                            "count"
                        ]
                    }
                }
            },
            "required": [
                "reqPrcCount",
                "errorCount",
                "latencyWamMs",
                "internalLatencyWamMs",
                "throughputWam",
                "inBytes",
                "outBytes",
                "inSpeedWam",
                "outSpeed"
            ]
        }
    },
    "required": [
        "status",
        "overallStats"
    ],
    "additionalProperties": false
}

Описание свойств объекта приведено в таблице ниже:

Свойство

Тип

Возможные значения

Обязательность

Назначение

status

строка

active/incative

да

Определяет текущее состояния - активный (может принимать запросы), неактивный - не может принимать запросы.

overallStats

объект

-

да

Объект со статистической информацией.

backends

массив объектов

-

нет

Массив элементов backend, содержащий информацию о внешних сервисах, с которыми взаимодействует данный интеграционный сервис.

Объект overallStats имеет следующую структуру:

Свойство

Тип

Возможные значения

Обязательность

Назначение

reqPrcCount

number

число большее или равное 0

да

Содержит общее количество запросов, принятых и обработанных данным сервисом нарастающим итогом. Сброс значения в 0 происходит только в результате перезапуска сервиса.

errorCount

number

число большее или равное 0

да

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

latencyWam

number

число большее или равное 0

да

Средневзвешенное значение времени обработки запроса от момента установления соединения до момента отправки ответа. В качестве веса используется количество запросов на единицу времени с дискретизацией 100 мс, длина очереди запросов - 10.
Пример расчета:
1 запрос: 56 мс;
2 запрос: 100 мс;
3 запрос: 25 мс;
4 запрос: 120 мс;
5 запрос: 180 мс;
6 запрос: 700 мс;
8 запрос: 810 мс;
9 запрос: 900 мс;
10 запрос: 220 мс;
расчет: ((56+25)*2 + (100+120+180)*3 + (700)1 + (220)1 +9001 + 8101)/10 = 200 мс.

Методы, которые необходимо реализовать в init.py:

Метод

Описание параметров

Есть реализация по умолчанию

Необходимо реализовать

Комментарий

init

init

Args: configurator: object: Объект класса configurator для доступа к публичным утилитарным функциям

да, но только для вызова из потомка

да

name

-

да

не обязательно, см. init

Возвращает название плагина

service

-

да

не обязательно, см. init

Возвращает название сервиса, реализуемого плагином

version

-

да

не обязательно, см. init

Возвращает версию плагина

config

Args:
profile_name (str): имя профиля
configuration (dict): yml-конфигурация профиля целиком

нет

да

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

start_before

Args:
profile (str): имя профиля

нет

да

Запуск сервисов плагина при запуске профиля до старта основных сервисов совы

start_after

Args:
profile (str): имя профиля

нет

да

Запуск сервисов плагина при запуске профиля после старта основных сервисов совы

stop_before

Args:
profile (str): имя профиля

нет

да

Остановка сервисов плагина при остановке профиля до остановки сервиса совы

stop_after

Args:
profile (str): имя профиля

нет

да

Остановка сервисов плагина при остановке профиля после остановки сервиса совы

restart_before

Args:
profile (str): имя профиля

нет

да

Рестарт сервисов плагина при рестарте профиля до рестарта сервиса совы

restart_after

Args:
profile (str): имя профиля

нет

да

Рестарт сервисов плагина при рестарте профиля после рестарта сервиса совы

reload_before

Args:
profile (str): имя профиля

нет

да

Релоад сервисов плагина при релоаде профиля до релоада сервиса совы

reload_after

Args:
profile (str): имя профиля

нет

да

Релоад сервисов плагина при релоаде профиля после релоада сервиса совы

status

Args:
profile (str): имя профиля

нет

да

Выполняется при просмотре статуса профиля. Отображение необходимой информации о работе плагина (pid, status, execution time)

backup

Args:
profile (str): имя профиля

нет

да, можно pass

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

restore

Args:
profile (str): имя профиля

нет да, можно pass

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

status_endponit

Args:
profile (str): имя профиля

нет

да

Возвращает endpoint сервиса, на котором располагается Health check + статистика сервиса

cleanup

Args:
profile (str): имя профиля

нет

да

Очистка артефактов сервиса

getDestConfigDir

Args:
service_id (str): идентификатор экземпляра сервиса

да

нет

Возвращает абсолютный путь до каталога с конфигурационными артефактами экземпляра сервиса (/sowa/…)

getDestLogDir

Args:
service_id (str): идентификатор экземпляра сервиса

да

нет

Возвращает абсолютный путь до каталога с логами экземпляра сервиса (/sowalogs/…)

getDestTmpDir

Args:
service_id (str): идентификатор экземпляра сервиса

да

нет

Возвращает абсолютный путь до каталога с временными файлами экземпляра сервиса (/sowarun/…)

createDirStruct

Args:
service_id (str): идентификатор экземпляра сервиса

да

нет

Создает в профиле необходимую структуру каталогов для экземпляра сервиса

cleanPluginServices

Args:
profile (str): имя профиля

нет

да

Очищает реестр сервисов плагина в профиле. Обертка над методом cleanPluginServices из класса PluginInterface

addPluginService

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса
config (str): YAML-конфиг экземпляра сервиса, по умолчанию пусто
start_before (bool): признак старта профиля до профиля Совы (по умолчанию после, False)
stop_before (bool): признак остановки профиля до остановки совы (по умолчанию после, False)

да

нет

Добавляет в реестр сервисов профиля информацию об экземпляре сервиса.
Нужно использовать в методе config.
Обертка над методом addPluginService из класса PluginInterface

getPluginServices

Args:
profile (str): имя профиля

да

нет

Возвращает список сконфигурированных сервисов плагина. Обертка над методом getPluginServices из класса PluginInterface

getPluginServicesStartBefore

Args:
profile (str): имя профиля

да

нет

Возвращает список сконфигурированных сервисов плагина с признаком «start before». Обертка над методом getPluginServicesStartBefore из класса PluginInterface

getPluginServicesStartAfter

Args:
profile (str): имя профиля

да

нет

Возвращает список сконфигурированных сервисов плагина с признаком «start after». Обертка над методом getPluginServicesStartAfter из класса PluginInterface

getPluginServicesStopBefore

Args:
profile (str): имя профиля

да

нет

Возвращает список сконфигурированных сервисов плагина с признаком «stop after». Обертка над методом getPluginServicesStopBefore из класса PluginInterface

getPluginServicesStopAfter

Args:
profile (str): имя профиля

да

нет

Возвращает список сконфигурированных сервисов плагина с признаком «stop after». Обертка над методом getPluginServicesStopAfter из класса PluginInterface

startService

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Выполняет старт сервиса плагина. Обертка над методом unitAction из класса PluginInterface

stopService

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да нет

Выполняет остановку сервиса плагина. Обертка над методом unitAction из класса PluginInterface

restartService

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Выполняет рестарт сервиса плагина. Обертка над методами stopService и startService.

serviceStatus

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Отображает состояние процесса сервиса. Обертка над методом unitAction из класса PluginInterface

getPluginServiceID

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Возвращает порядковый номер из реестра сервисов, присвоенный при регистрации сервиса. Обертка над методом getPluginServiceID из класса PluginInterface

addPidFile

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Создает pid-файл экземпляра сервиса по стандартному пути

delPidFile

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Удаляет pid-файл экземпляра сервиса по стандартному пути

addUsock

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Создает unix socket файл экземпляра сервиса по стандартному пути

delUsock

Args:
profile_name (str): имя профиля
service_id (str): идентификатор экземпляра сервиса

да

нет

Удаляет unix socket файл экземпляра сервиса по стандартному пути

logDebug
logInfo
logWarn
logError
logCritical

message(str): сообщение в лог
source(str): источник ошибки (пусто по умолчанию)
print_to_output(bool): False - если = true, то сообщение выводится в консоль

Добавляет cообщение в лог с определенным уровнем

-

getDirStruct

-

Возвращает объект со структурой директорий профиля и конфигуратора в целом

-

renderTemplate

srcTemplate(str): путь к шаблону *.j2
destFile(str): путь к файлу, куда будет записан результат шаблонизации
encoding(str): кодировка файла (по умолчанию utf-8)
**var(dict): список дополнительных переменных для шаблонизации

Производит шаблонизацию по указанному шаблону

Обязателен вызов со стороны плагина на этапе конфигурирования профиля

__makedirs

dirName

да

нет

Функция создания произвольной директории профиля

Методы для регистрации сервиса и его параметров в профиле

Метод

Аргументы

Описание

Комментарий

addPluginService

profile_name (str): имя профиля
plugin_name (str): имя плагина
service_id (str): идентификатор экземпляра сервиса
config (str): YAML-конфиг экземпляра сервиса, по умолчанию пусто
start_before (bool): признак старта профиля до профиля Совы (по умолчанию после, False)
stop_before (bool): признак остановки профиля до остановки совы (по умолчанию после, False)
classpath(str): classpath приложения, путь к необходимым .jar файлам библиотек
app_options (str): java-аргументы, используемые при запуске приложения service_name (str): имя сервиса, возвращаемое методом service()

Регистрирует сервис в реестре для обеспечения возможности управления сервисами на последующих этапах

Обязателен вызов со стороны плагина на этапе конфигурирования профиля

cleanPluginServices

profile_name (str): имя профиля
plugin_name (str): имя плагина

Отменяет регистрацию всех сервисов плагина в реестре

Обязателен вызов со стороны плагина на этапе повторного конфигурирования профиля с последующим вызовом addPluginService. Также необходимы использовать в методе clean интерфейса.

getPluginServices

profile_name (str): имя профиля
plugin_name (str): имя плагина

Возвращает список сконфигурированных сервисов плагина

-

getPluginServicesStartBefore

profile_name (str): имя профиля
plugin_name (str): имя плагина

Возвращает список сконфигурированных сервисов плагина с признаком «start before»

-

getPluginServicesStartAfter

profile_name (str): имя профиля
plugin_name (str): имя плагина

Возвращает список сконфигурированных сервисов плагина с признаком «start after»

-

getPluginServicesStopBefore

profile_name (str): имя профиля
plugin_name (str): имя плагина

Возвращает список сконфигурированных сервисов плагина с признаком «stop before»

-

getPluginServicesStopAfter

profile_name (str): имя профиля
plugin_name (str): имя плагина

Возвращает список сконфигурированных сервисов плагина с признаком «stop after»

-

getPluginServiceID

profile_name (str): имя профиля
plugin_name (str): имя плагина
service_id (str): идентификатор экземпляра сервиса

Возвращает порядковый номер из реестра сервисов, присвоенный при регистрации сервиса

-

execCMD

args (list): список аргументов в формате [«one», «two», «etc»]
suppress_output (bool): подавлять вывод сообщений на экран (по умолчанию False),
return_code_exclusion (list): список исключений для успешных кодов выполнения команды, suppress_errors
(bool): подавлять вывод на экран сообщений об ошибках (по умолчанию False)

Выполнение команды

Требуется наличие записи в sudoers для выполнения необходимой команды. Согласовывается с КБ.

unitAction

action(str): действие systemctl (start, stop, status)
profile_name(str): имя профиля
plugin_name(str): имя сервиса плагина
service_id(str): идентификатор экземпляра сервиса

Выполняет указанное действие с systemctl

Обязателен вызов со стороны плагина как минимум на этапах запуска и остановки профиля

addPort

profile_name(str): имя профиля
portNum(int): номер регистрируемого порта
isSSL(bool): признак ssl порта (по умолчанию None)
isStatus(bool): признак того, что указанный порт является статусным (для обращений мониторинга), по умолчанию None
address(str): адрес, на котором слушает порт (по умолчанию «0.0.0.0»)

Регистрирует в реестре порт для сервиса плагина в рамках профиля. Необходим для отслеживания и валидации используемых портов.

Обязателен вызов со стороны плагина на этапе конфигурирования профиля в случае, если сервис плагина принимает входящее соединение на определенном порту

delPort

profile_name(str): имя профиля
portNum(int): номер удаляемого порта

Удаляет порт из списка зарегистрированных для профиля в реестре

Обязателен вызов со стороны плагина на этапе удаления профиля