# GUFO Data Model ## Preface Все инвентарные данные в GUFO, имеющие бизнес-ценность являются сервисами и встроены в общую сервисную модель. ## База данных Структура БД рассчитана на PostgreSQL с расширениями Citus. Для удобства управления правами доступа и резервного копирования база данных состоит из схем: * `main` - основная инвентарная схема * `fm` - fault management: events/alarms * `pm` - performance management: метрики и телеметрия * `mon` - самомониторинг * `bi` - схема с аналитическими view ## Модели Pydantic Модели [pydantic](https://pydantic-docs.helpmanual.io) определяют структуру данных при взаимодействии с внешними процессами: * Формат REST запросов (FastAPI) * Структура JSON-полей в БД * Форматы выгрузок ETL Модели хранятся в каталоге `models` и разбиты по категориям: * `models/api/` - модели API * `models/traits/` - модели БД * `models/etl/` - модели ETL * `models/config/` - конфигурация системы Модели могут быть адресованы в виде строки `<модуль>.<класс>`. Например, в контексте БД модель `address.Address` модель расположена в модуле `models/db/address` в классе `Address`. Для загрузки моделей используется Loader API (По аналогии с NOC). Модели могут быть кастомизированы и находиться в `custom`. ## ServiceTraits Сервисы разных типов могут иметь разный набор атрибутов. Аттрибуты редко сущесвуют сами по себе. Обычно, они объединяются в группы и описывают один из аспектов взаимодействия с внешним миром. В ООП используется понятиие `Trait`. Trait определяет набор методов, имеющих определенную семантику использования и может использоваться для параметризации других Trait. Таблица БД: `main.service_trait` | Поле | Тип | Constraints | Описание | | --- | --- | --- | --- | | id | INTEGER | NOT NULL PRIMARY KEY | Первичный ключ | | name | VARCHAR | NOT NULL UNIQUE | Название Trait | | description | TEXT | NULL | Описание | | title | VARCHAR | NULL | Заголовок | | model | VARCHAR | NOT NULL | Модель Pydantic | ### Trait name Именнованные сервисы ```python class NameTrait(BaseModel): name: str description: Optional[str] ``` ## ServiceType Тип сервиса определяет поведение системы при работе с сервисом и его модель данных. Введение нового типа сервисов, обычно, требует соответсвующих моделей, которые могут быть расположены как в базовой системе, так и в custom. В любом случае - доработка системы в той или иной мере. Предполагается, что ServiceType будет заполняться из коллекций через механизм ETL. Таблица БД: `main.service_type` | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | id | INTEGER | NOT NULL PRIMARY KEY | Первичный ключ | | name | VARCHAR | NOT NULL | UNIQUE | Название типа сервисов | | description | TEXT | NULL | Описание | | policy_traits | Array[TraitItem] | NULL | Trait'ы, задаваемые на уровне политики | | service_traits | Array[TraitItem] | NULL | Trait'ы, задаваемые на уровне сервиса | Тип TraitItem: | Поле | Тип | Описание | | --- | --- | --- | | trait_id | INTEGER | Ссылка на trait | | is_required | BOOLEAN | Признак обязательности | NB: Модели адресуются в контексте `traits` @todo: Relationship restrictions. @todo: Процедуры проверки PL/PGSQL. ## ServicePolicy Групповые настройки сервисов. Аналог ***Profile в NOC, но единый для всех видов сущностей. Предполагается, что для каждого ServiceType будет автоматически создаваться ServicePolicy с именем `<service_type> default` Таблица БД: `main.service_category` | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | id | INTEGER | NOT NULL PRIMARY KEY | Первичный ключ | | name | VARCHAR | NOT NULL | UNIQUE | Название типа сервисов | | description | TEXT | NULL | Описание | | service_type_id | INTEGER | NOT NULL REFERENCES service_type | ссылка на тип сервиса | | workflow_id | INTEGER | NOT NULL REFERENCES workflow | Рабочий процесс | | data | JSONB | NULL | Групповые настройки, модель описана в service_type.category_model | | labels | ARRAY[TEXT] | NULL | Метки | | effective_labels | ARRAY[TEXT] | NULL | Эффективный набор меток | | mappings | JSONB | NULL | Отображения ID из внешних систем. Массив | | > remote_system_id | INTEGER | | id RemoteSystem | | > remote_id | TEXT | | id во внешней системе | Все используемые labels должны иметь `permit` `service_policy` @todo: Caps? ## Service Сервисы. Вездесущая сущность, модель данных определяется настройками ServiceType | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | id | INTEGER | NOT NULL PRIMARY KEY | Первичный ключ | | name | VARCHAR | NOT NULL | UNIQUE | Название типа сервисов | | description | TEXT | NULL | Описание | | service_category_id | INTEGER | NOT NULL REFERENCES service_category | Категория сервисов | | data | JSONB | | Настройки сервисов, модель описана в service_type.service_model | | labels | ARRAY[TEXT] | NULL | Метки | | effective_labels | ARRAY[TEXT] | NULL | Эффективный набор меток | | mappings | JSONB | NULL | Отображения ID из внешних систем. Массив | | > remote_system_id | INTEGER | | id RemoteSystem | | > remote_id | TEXT | | id во внешней системе | Все используемые labels должны иметь `permit` `service` NB: Организация иерархий определяется на уровне связей сервисов. NB: data и category доступны из ORM через модели pydantic (lazy get) как поля .data и .category NB: Для удобства работы и отчетов в системе создается набор view (`v_*`) и поля из `data` могут вытягиваться как отдельные аттрибуты view. @todo: Caps? ## ServiceTopology Связи между сервисами служат для выполнения различных задач и могут быть сгруппированы по назначению. При разделении ребер графа на несколько групп мы получаем разбиение общего графа на несколько независимых графов с разными свойствами. Каждый полученный граф называется "Топологией" и обладает отдельными свойствами и накладывает отдельные ограничения. Предполагается, что ServiceTopology будет заполняться из коллекций через механизм ETL. | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | id | INTEGER | NOT NULL PRIMARY KEY | Первичный ключ | | name | VARCHAR | NOT NULL | UNIQUE | Название типа сервисов | | description | TEXT | NULL | Описание | | is_acyclic | BOOLEAN | NOT NULL | Требование ацикличности | Предопределенные топологии: | Имя | is_acyclic | Описаниие | | --- | --- | --- | | `inventry` | Да | Иерархия inventory | | `service_fault` | Да | распространение аварии по зависимостям | | `l2_uplink` | Нет | корреляция аварий на основе топологии L2 | ## ServiceLinkType Тип связей между сервисами (ребер графа). Предполагается, что ServiceLinkType будет заполняться из коллекций через механизм ETL. | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | id | INTEGER | NOT NULL PRIMARY KEY | Первичный ключ | | name | VARCHAR | NOT NULL | UNIQUE | Название типа сервисов | | description | TEXT | NULL | Описание | | topology_id | INTEGER | NOT NULL | Ссылка на ServiceTopology | | from_type_id | INTEGER | NOT NULL | Тип узла для начала ребра | | to_type_id | INTEGER | NOT NULL | Тип узла для окончания ребра | ## ServiceLink Связь между сервисами (ребро графа). | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | id | INTEGER | NOT NULL PRIMARY KEY | Первичный ключ | | name | VARCHAR | NOT NULL | UNIQUE | Название типа сервисов | | link_type_id | INTEGER | NOT NULL | Тип связи | | from_service_id | INTEGER | NOT NULL | Сервис начала ребра | | to_service_id | INTEGER | NOT NULL | Сервис окончания ребра | | mappings | JSONB | NULL | Отображения ID из внешних систем. Массив | | > remote_system_id | INTEGER | | id RemoteSystem | | > remote_id | TEXT | | id во внешней системе | ## ServiceStatus Текущее состояние сервиса. Вынесено в отдельную таблицу, так как часто обновляется и из-за MVCC Postgres будет приводить к распуханию и деградациии таблицы с сервисами. | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | service_id | INTEGER | NOT NULL UNIQUE PRIMARY | Ссылка на сервис | | admin_status | INTEGER | NOT NULL | Административное состояние (бизнес). Назначается по state workflow | | dep_status | INTEGER | NOT NULL | Вычисляемый статус по зависимостям | | probe_status | INTEGER | NOT NULL | Результат работы пробы | | op_status | INTEGER | NOT NULL | Операционное состояние. Результат композиции dep_status и op_status | | admin_last_change | TIMESTAMP | NOT NULL | Время изменения admin_status | | dep_last_change | TIMESTAMP | NOT NULL | Время изменения dep_status | | probe_last_change | TIMESTAMP | NOT NULL | Время изменения probe_status | | op_last_change | TIMESTAMP | NOT NULL | Время изменения op_status | AdminState может принимать значения: 1. UNKNOWN - Не определено 2. PROVISIONING - В процессе настройке 3. FAIL - Ошибка при развертывании 4. READY - Готов 5. SUSPEND - Приостановлен 6. MAINTENANCE - Отключен на РНР 7. CLOSED - Закрыт, больше не используется OpState может принимать значения: 1. NA - Не применимо 2. UNKNOWN - Не определено 3. DISABLED - Отключен 4. FAIL - Не работает 5. DEGRADED - Деградация. Еще один отказ, и будет авария. 6. SOFT DEGRADED - Есть отказ зависимости, но остается резерв. 7. OK - Работает, все зависимости - OK. ## Labels Метки. Таблица БД: `main.labels` | Поле | Тип | Constraits | Описание | | --- | --- | --- | --- | | label | VARCHAR | NOT NULL | PRIMARY KEY | Название метки | | description | TEXT | NULL | Описание | | permit | ARRAY[TEXT] | NULL | Допустимые применения | | expose | ARRAY[TEXT] | NULL | Фильтры перетекания | Допустимые значения для permit и expose: * `remote_system` * `service_category` * `service` * `workflow` * `state` ```mermaid graph LR RemoteSystem --> ServiceCategory ServiceCategory --> Service Workflow --> ServiceCategory State --> Service ``` ## @todo: Worflow ## @todo: State ## @todo: Agent ## @todo: RemoteSystem ## @todo: Project ## @todo: ServiceEvent Схема: fm ## @todo: ServiceAlarm Схема: fm +root +root_type ## @todo: ServiceMaintenanceCategory ## @todo: ServiceMaintenance @todo: Workflow ## Вычисление effective_labels Производится на уровне триггеров по диаграмме перетекания меток. Для того, чтобы метка перетекла по стрелке необходимо выполнение двух условий: наличие разрешений `expose` (право передать метку в направлении стрелки) и `permit` (право принять метку). ## Корреляция аварий по зависимостям Осуществляется по топологии service_fault. Топология является ацикличной, @todo: Резерв @todo: РНР ## Корреляция по топологии L2 Корреляция проводится по топологии l2_uplink. Топология может содержать циклы и строится между Managed Object'ами с использованием связей типа "L2 Uplink" ```mermaid graph LR MO1 --> MO3 MO2 --> MO3 MO1 --> MO2 MO2 --> MO1 ``` Авария считается последствием, если все ее зависимости накрыты аварией. В таком случае, она коррелируется с наиболее старой аварией. @todo: Нужен ли виртуальный сервис L2? ## @todo: Корреляция по топологии L3 ## Cases ### Happy Customer Если сервисная модель ориентирована на обслуживание живых клиентов, заказывающих одновременно несколько услуг, то можно использовать виртуальные сервисы типа Happy Customer. Клиент счастлив, когда у него все работает. ```mermaid graph LR Customer[Happy Customer] Internet --> Customer IPTV --> Customer VoIP --> Customer ``` Сервисы типа Happy Customer могут строиться автоматически, группируя сервисы по признаку Customer. ## Открытые вопросы Заполняйте свои вопросы здесь *