# Channel/Trail data model v3
## Resource
Структура - умный указатель на ресурс в inventory. Не хранится сам по себе, но входит в состав других моделей.
Состоит из полей:
* model - имя модели (inv.Object, sa.Interface)
* id - Id - динамическое поле с типами int или ObjectId
* path - опциональный путь внутри ресурса
Поля oid и id взаимоисключающие и зависят от модели:
* id используется для типа int и данных в postgres
* oid используется для ObjectId и данных в mongo
**Пример1:** Точка присутсвия
``` json
{
"model": "inv.Object",
"id": `id объекта`
}
```
**Пример2:** Порт 4 на линейной карте
``` json
{
"model": "inv.Object",
"id": `id линейной карты`,
"path": "4"
}
```
**Пример3:** Интерфейс
@todo: Уточнить
``` json
{
"model": "inv.Interface",
"id": `id интерфейса`
}
```
## TechDomain
Технологический домен, представляет собой технологию для организации связи и тесно связан с контроллером - технической реализацией процесса автоматизации.
Модель данных:
* id
* name
* uuid
* description
* controller_handler
Вопросы:
* Прочая аттрибутика
## Channel
Канал обеспечивает связность между специальными ресурсами, называемыми Channel Endpoint (точки подключения). Каналы могут образовывать иерархию. В случае иерархической схемы каналы-листья организовывают связность в пределах одного технологического домена, в то время как каналы-узлы их просто группируют. В таком случае у каналов-узлов технологический домен всегда равен `group`.
Каждый канал строится в рамках отдельной задачи, так что дробление может быть вызвано не только технологическими, но и организационными причинами.
Модель данных:
* id
* name
* parent - родитель (если есть)
* description
* state
* labels
* effective_labels
* project
* subscriber
* supplier
* remote_system
* remote_id
* bi_id
* context - контекст контроллера
* constraints - клиентские настройки, ограничивающие возможные варианты построения. Список:
* type - тип ограничения:
* `i` - include
* `e` - exclude
* strict - boolean. Если `True`, то ограничение всегда должно соблюдаться, если `False`, то соблюдение условия желательно, но невозможность соблюдения не является фатальной.
* resource - Resource, который задействован в ограничении.
* path - просчитанный граф ресурсов, необходимый для организации канала. Список:
* x - Resource
* y - Resource
## ChannelEndpoint
Точки подключения являются ресурсами, обозначающие места входа в канал и могут использоваться для одного или нескольких подключений других каналов.
Модель:
* id
* trail - указатель на канал, связывающий точки подключения
* tech_domain - ссылка на tech_domain
* resource - Resource
* is_root - корневой узел дерева для топологии p2mp
* used_by - коналы, использующие связность.
* channel - указатель на channel
* discriminator - опциональный дискриминатор, в случае, если точка подключения используется не монопольно.
## Пример
OTN:
``` mermaid
flowchart LR
subgraph ADM1
ADM1::Client1[[Client1]]
ADM1::Line1[[Line1]]
ADM1::Client1 -.- ADM1::Line1
end
subgraph Och
subgraph Patch1
Patch1::1[[1]]
end
subgraph Patch2
Patch2::7[[7]]
end
Patch1::1 --- Patch2::7
end
subgraph ADM2
ADM2::Client5[[Client5]]
ADM2::Line4[[Line4]]
ADM2::Client5 -.- ADM2::Line4
end
ADM1::Line1 --- Patch1::1
ADM2::Line4 --- Patch2::7
```
Для реализации схемы необходимо:
1. Реализовать оптическую связность (Och) между патч-панелямии
2. Реализовать OTU Trail между Line портами ADM-карт
3. Реализовать ODU Trail между Client портами ADM-карт
**Och Trail:**
Начнем с реализации Och trail.
После реализации топологической связности в inventory создаем канал.
Channel:
``` json
{
"id": `och_trail`,
"tech_domain": `optical`,
"topology": "p2p",
"path": [
{
"x": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
},
"y": {
"model": "inv.Object",
"id": `Patch2`,
"path": "7"
}
}
]
}
```
Так как оптический канал предоставляет связность между двумя ресурсами мы создаем 2 endpoint.
ChannelEndpoints:
``` json
[
{
"trail": `och_trail`,
"tech_domain": `optical`,
"resource": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
}
},
{
"trail": `och_trail`,
"tech_domain": `optical`,
"resource": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
}
}
]
```
Далее мы используем оптический канал для реализации OTU trail.
Channel:
``` json
{
"id": `otu_trail`,
"tech_domain": `otn_otu`,
"topology": "p2p",
"path": [
{
"x": {
"model": "inv.Object",
"id": `ADM1`,
"path": "Line1"
},
"y": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
}
},
{
"x": {
"model": "inv.Object",
"id": `ADM2`,
"path": "Line4"
},
"y": {
"model": "inv.Object",
"id": `Patch2`,
"path": "7"
}
},
]
}
```
Так как у нас появилось два связных ресурса по технологии OTU мы добавляем два endpoint:
ChannelEndpoint
``` json
[
{
"trail": `otu_trail`,
"tech_domain": `otn_otu`,
"resource": {
"model": "inv.Object",
"id": `ADM1`,
"path": "Line1"
}
},
{
"trail": `otu_trail`,
"tech_domain": `otn_otu`,
"resource": {
"model": "inv.Object",
"id": `ADM2`,
"path": "Line4"
}
}
]
```
Так как наш OTU монопольно использует Och, мы добавляем OTU в точки подключения OCh в поля used_by и они становятся:
``` json
[
{
"trail": `och_trail`,
"tech_domain": `optical`,
"resource": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
},
"used_by": [
{
"channel": `otu_trail`
}
]
},
{
"trail": `och_trail`,
"tech_domain": `optical`,
"resource": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
},
"used_by": [
{
"channel": `otu_trail`
}
]
}
]
```
Теперь мы видим, что порты патч-панели уже заняты.
Далее мы создаем ODU Trail, используя OTU.
Channel:
``` json
{
"id": `odu_trail`,
"tech_domain": `otn_odu`,
"topology": "p2p",
"path": [
{
"x": {
"model": "inv.Object",
"id": `ADM1`,
"path": "Client1"
},
"y": {
"model": "inv.Object",
"id": `ADM1`,
"path": `Line1"
}
},
{
"x": {
"model": "inv.Object",
"id": `ADM2`,
"path": "Client4"
},
"y": {
"model": "inv.Object",
"id": `ADM2`,
"path": `Client5"
}
},
]
}
```
У нас снова возникает два endpoint, на этот раз - клиентские порты:
``` json
[
{
"trail": `odu_trail`,
"tech_domain": `otn_odu`,
"resource": {
"model": "inv.Object",
"id": `ADM1`,
"path": "Client1"
}
},
{
"trail": `odu_trail`,
"tech_domain": `otn_odu`,
"resource": {
"model": "inv.Object",
"id": `ADM2`,
"path": "Client5"
}
}
]
```
Так как мы задействовали endpoint'ы OTU, мы должны на них прописать наш новый канал:
``` json
[
{
"trail": `otu_trail`,
"tech_domain": `otn_otu`,
"resource": {
"model": "inv.Object",
"id": `ADM1`,
"path": "Line1"
},
"used_by": [
{
"channel": `odu_trail`,
"discriminator": "odu::ODU2::ODU1-1"
}
]
},
{
"trail": `otu_trail`,
"tech_domain": `otn_otu`,
"resource": {
"model": "inv.Object",
"id": `ADM2`,
"path": "Line4"
},
"used_by": [
{
"channel": `odu_trail`,
"discriminator": "odu::ODU2::ODU1-1"
}
]
}
]
```
Мы также должны добавить задания на кроссировки:
ADM1:
``` json
{
"input": "Client1",
"output": "Line1",
"output_discriminator": "odu::ODU2::ODU1-1"
}
```
ADM2:
``` json
{
"input": "Client5",
"output": "Line4",
"output_discriminator": "odu::ODU2::ODU1-1"
}
```
Теперь решаем задачи:
**Найти канал, начинающийся с ADM1::Client1**
```
channelendpoints.find(
{
"resource": {
"$elemMatch": {
"model": "inv.Object",
"id": `ADM1`,
"path": "Client1"
}
}
}, {'channel': 1})
```
**Найти каналы, проходящий через Patch1::1**
```
channels.find(
{
"$or": [
"path.x": {
"$elemMatch": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
}
},
"path.y": {
"$elemMatch": {
"model": "inv.Object",
"id": `Patch1`,
"path": "1"
}
}
]
}, {"_id": 1, "used_by": 1}
)
```
Запоминаем id, и все id из used_by
```
channels.find(
{
id: {
"$in": <список id из used by>
}
}, {"used_by": 1}
)
```
Далее дополняем наш список id и смотримы новые used by. Повторяем рекурсивно с новыми used by пока не остановимся.
**Найти свободные ODU на ADM1::Line1**
```
channelendpoints.find(
{
"resource": {
"$elemMatch": {
"model": "inv.Object",
"id": `ADM1`,
"path": "Line1"
}
}
}, {"used_by": 1}
)
```
Анализируем поля `discriminator`
@todo: Где взять настроенный тип OTU?
## Старый хлам
## Создание ODU Trail
1. Пользователь выбирает домен OTU
2. Пользователь выбирает группу в inventory (город, PoP, стойку, шасси, карту)
3. Контроллер находит все вложенные объекты
4. Контроллер выбирает все модели из списка объектов
5. Итератор выдает возможные точки подключения в виде (model=inv.Object, resource_id=<id>, path=<имя слота>, hints=<список поддерживаемых ODU>) для всех connections, которые поддерживают протоколы ODU*
6. Из полученного списка отфильтровываются все записи, которые уже присутсвуют в termination points (поля tech_domain, model, resource_id, path)
7. Пользователю предлагается список портов с доступными типами ODU
8. Пользователь выбирает порт и тип ODU
9. Контроллер проверяет все исходящие OTU Trail с данной карты и возвращает список: (OTU Trail, *список свободных портов, поддерживающих данный ODU*). Поиск осуществляется по termination point, домену==OTN OTU, model =inv.Object, resource_id=(текущая карта)
10. Если нет подходящего OTU, пользователь переходит к созданию OTU Trail
11. Пользователь выбирает ответный порт и место OTU в ODU
12. Контроллер создает запись в channel
13. Контроллер создает 2 trail с типом OTU (левый и правый) и привязывает их к каналу
14. Контлоллер создает 2 termination point для клиентских портов и привязывает их к левому и правому trail
15. Контроллер находит termination point'ы для выбранного OTU и прописывает им в endpoint ODU trail'ы и дискриминатор
16. Контроллер запускает группу из двух заданий на настройку кроссировки на ADM
## Создание OTU Trail
1. Пользователь выбирает домен OTU
2. Пользователь выбирает группу в inventory (город, PoP, стойку, шасси, карту)
3. Контроллер находит все вложенные объекты
4. Контроллер выбирает все модели из списка объектов
5. Итератор выдает возможные точки подключения в виде (model=inv.Object, resource_id=<id>, path=<имя слота>, hints=<список поддерживаемых OTU>) для всех connections, которые поддерживают протоколы OTU*
6. Из полученного списка отфильтровываются все записи, которые уже присутсвуют в termination points (поля tech_domain, model, resource_id, path)
7. Пользователю предлагается список портов с доступными типами OTU
Далее необходимо выбрать ответную часть.
Если существующая топология позволяет построить путь от выделенного порта к другому порту, поддерживающему выбранный тип OTU, то предлагаем соответсвующий порт.
В противном случае переходим к процедуре создания оптического канала Och
## Создание оптического канала
Без ROADM:
1. Выбираем стартовую точку (как в предыдущих шагах)
2. Проходим по кроссировке и показываем конечную точку
по необходимости руками меняем линки и кроссировки
3. Если нет ROADM пользователь фиксирует конечные точки
4. Если попался ROADM выбираем выходной порт и повторяем с пп. 2
5. Создается trail с доменом Optical
6. Создается 2 termination point с дискриминаторами lambda (может быть как фильтр)
7. Создаются задания на настройку ROADM