# 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