﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	resolution	keywords	cc
803	Реализовать новую систему ключей агента Zabbix	alx	alx	"В существующей системе именования ключей агента Zabbix вторым элементом является, как правило, наименование платы. Это создает целый ряд неудобств, в том числе не позволяет в полной мере воспользоваться возможностями современных версий сервера Zabbix.

Например, у нас имеется несколько типов плат (SM-01, SM-02, SM-03), у которых практически полностью совпадает MIB. Кроме этого, запланирована разработка плат SM-11 и SM-12, у которых, как я подозреваю, MIB будет таким же. Однако невозможно создать в Zabbix один шаблон для всех этих плат сразу, так как существующая схема требует указания наименования платы в основной части ключа (`MC04.SM-01.snmp.7.5.2.0[...]`), а сервер Zabbix не позволяет использовать макросы в основной части (то есть нельзя написать так: `MC04.{#BOARDNAME}.snmp.7.5.2.0[...]`). Zabbix может использовать макросы только в параметрах ключа (`MC04.SM-02.snmp.7.5.2.0[{#MACRO}, ....]`). Как результат, для каждой из пяти перечисленных плат приходится создавать свой отдельный шаблон, отличающийся только наименованием платы.

=== Основная часть ключа ===

Для преодоления этой проблемы предлагается реализовать новую систему именования ключей агента (существующую систему предлагается оставить для совместимости). Новый формат ключа предлагается сделать таким:

 `MCv2.<function>[<parameters>]`

- ""MCv2"" - префикс, позволяющий отличить новые ключи от старых;
- <function> - наименование функции (как и в старой системе, только набор будет сокращен).

Таким образом, все существенные части ключа (кроме функции) переносятся в параметры, в основной части остается только наименование выполняемой функции. Например:

 Было: `MC04.SM-01.snmp.7.5.2.0[12]`, стало: `MCv2.getvar[12, .7.5.2.0, name=SM-01]`.

=== Формат параметров ===

Также предлагается кроме позиционных параметров, которые уже были раньше, ввести опциональные именные параметры, имеющие формат `<имя>=<значение>` (см. пример выше). Это позволит легче и проще преобразовывать существующие шаблоны к новому формату ключей, в идеале, одной заменой в текстовом редакторе. Именные параметры предлагается сделать не зависящими от позиции и не влияющими на позиционные аргументы. То есть следующие параметры будут эквивалентны: `[.7.5.2.0, 12, name=SM-01]`, `[.7.5.2.0, name=SM-01, 12]`, `[name=SM-01, .7.5.2.0, 12]`.

=== Набор функций ===

Предлагается следующий набор функций ключей:

- getvar;
- substr;
- boardlist.

==== getvar ====

Предлагается следующий формат параметров: `[<slot>, <oid>]`. Агент возвращает значение переменной с OID <oid> платы в слоте <slot>.

//Именные параметры://

- `name=<наименование платы>`: дополнительно проверяется, что установленная в слоте <slot> плата имеет указанное наименование. Если это не так, агент возвращает ошибку.
- `type=<код типа платы>`: дополнительно проверяется, что установленная в слоте <slot> плата имеет указанный код типа. Если это не так, агент возвращает ошибку.
- `format=<string|hex|array|auto>`: позволяет устранить неоднозначность формата возвращаемого значения. Так как во внутреннем протоколе обмена с платами отсутствует специальный тип ""двоичные данные"", для передачи двоичных данных используется тип ""строка"". Но, во-первых, произвольные двоичные данные не всегда представляют собой валидный код UTF-8, а во-вторых, даже если представляют, работать с таким представлением не очень удобно, т.к. трудно найти среди символов нужный двоичный байт. В запросе API можно было указать параметр `strings2data`, и тогда строки возвращаются в виде массива байт. В агенте Zabbix реализован другой механизм - если в строке есть хотя бы один непечатный символ, байты преобразуются в последовательность 16-ричных кодов, разделенных пробелами (примерно так, как это делает библиотека libsnmp).[[br]][[br]] Проблема в том, что получатель строки не всегда имеет возможность знать, получил ли он преобразованные в hex данные, или данные в таком виде и были отправлены непосредственно платой. Для устранения этой неоднозначности предлагается использовать параметр `format=`, который безусловно преобразует принятую из платы строку в заданный формат (к типам данных, отличным от строки, эти параметры не применяются). Предлагается реализовать следующие значения параметра:
 - `string` - полученная от платы строка возвращаются в виде строки ""как есть"";
 - `array` - полученная от платы строка возвращается в виде массива значений байтов, например имя платы SW-01 будет возвращено как `[83,87,45,48,49]`, такой формат удобен для последующей обработки javascript'ом на стороне сервера;
 - `hex` - полученная от платы строка возвращается в виде строки, состоящей из 16-ричных представлений каждого байта, разделенных пробелами, например имя платы SW-01 будет возвращено как `53 57 2D 30 31`;
 - `auto` - формат по умолчанию, как это есть сейчас: `hex` если в строке есть хотя бы один ""непечатный"" символ (байт с кодом меньше 32) и `string` в противном случае. Возможно, стоит возвращать hex также в случае невалидного UTF-8 кода?

**TODO** еще частой проблемой является отсутствие признака ""знаковости"" возвращаемого платой значения. То есть, например, получив от платы числовое значение, представленное байтами 0xA73C97B2, агент Zabbix не знает, имеется ли в виду значение 2805766066 или -1489201230. Может быть имеет смысл добавлять в ключ дополнительный параметр, который ""подскажет"" агенту Zabbix, знаковое или беззнаковое число ожидается от платы? Можно, конечно, учитывать знак на стороне сервера (предобработкой), но указание в ключе параметра типа `format=signed` могло бы избавить от такой необхоидмости...

==== substr ====

Предлагается следующий формат параметров: `[<slot>, <oid>, <start>, <count>]`. Функция полностью аналогична функции `getvar`, только в случае если запрошенная переменная имеет тип ""строка"", агент возвращает подстроку, начинающуюся с позиции `<start>` и содержащую `<count>` байт. Все именные параметры аналогичны функции `getvar`. Эта функция полезна в случаях, когда состояние множества элементов платы (например портов) содержится в одной переменной, возвращающей один большой массив байт.

==== boardlist ====

Предлагается следующий формат параметров: `[<код типа платы>]`. Если код равен нулю или отсутствует, возвращается список всех плат. Иначе возвращается список плат с указанным кодом типа.

//Именные параметры://

- `type=<код типа платы>`: то же самое, что и один позиционный параметр; не уверен, что это необходимо, но можно добавить для удобства.
- `name=<наименование платы>`: возвращается список плат с указанным наименованием.

==== nthbyte, hwordat, hwordat-be, wordat, wordat-be ====

Функции `nthbyte`, `hwordat`, `hwordat-be`, `wordat`, `wordat-be` предлагается реализовать предобработкой в зависимых элементах данных на стороне сервера.

==== ethstat, readsfp ====

Функции `ethstat` и `readsfp` предлагается реализовать через `getvar` - то есть добавить плате SW-01 переменную, возвращающую значения счетчиков порта коммутатора (переменная, из которой читаются данные SFP, в плате уже есть). Этим заодно (кроме унификации) устраняется неоднозначность: в ключах MC04.sys.ethstat не указывался номер слота, поэтому, во-первых, можно было получить счетчики только активной платы, а во-вторых, при активации/деактивации резервной платы SW-01 источник данных просто подменялся - вместо счетчиков одного коммутатора начинали отдаваться счетчики совсем другого! Все счетчики порта будут возвращаться в одной переменной в виде JSON массива.
"	улучшение	new	средний	1 очередь	sw			san
