# Привязка интерфейсов к физическим портам inventory ## Задача Установить соответсвие между физическими портами, полученными через asset discovery и из моделей устройств с логическими интерфейсами, полученными через interface discovery. ## ConnectionType В ConnectionType необходимо добавить дополнительный признак: * is_physical_interface Признак показывает, что в данном слоте находится физический интерфейс. Такие слоты могут быть привязаны к логическим интерфейсам. ## iter_physical_interface ``` ManagedObject.iter_physical_interface() -> Iterable[PhysicalPath] где: PhysicalPath = Tuple[PathItem, *] PathItem - namedtuple(object, connection_type, connection_name) ``` Итератор возвращает записи с полным физическим путем для каждого интерфейса. Полный физический путь состоит из всех модулей, начиная с шасси, вплоть до конкретного порта. Порты определяются по признаку `is_physical_interface`, порты являются границей, на которой останавливается рекурсивный спуск. По умолчанию считается, что порт начинается на дырке SFP, а не на оптических разъмах. ## Collator Класс, осуществляющий привязку логических интерфейсов к физическим. Должен реализовывать интерфейс: ``` class BaseCollator(object): def __init__(self, **kwargs): ... def collate(self, physical_path, interfaces): # type: (PhysicalPath, Dict[str, Interface]) -> Optional[str] ``` Класс `Collator` должен наследоваться от `BaseCollator` и может дополнительно конфигурироваться через именнованные аргументы конструктора. Экземпляр `Collator` создается один раз на весь процесс привязки в соотвествующем Job'е discovery. Таким образом разрешается хранение внутреннего состояния на весь процесс привязки. Основным рабочим методом является `collate`, который принимает на вход полный физический путь порта (результат одного yield `iter_physical_interface`) и словарь интерфейсов, нуждающихся в привязке (нормализованное имя интерфейса -> Interface instance). Метод `collate` возвращает имя логического интерфейса соответсвующего данному физическому пути, если привязка удалась, или None, если привязка не удалась. ## Цепочки Collator'ов Collator'ы могут быть сгруппированы в цепочки. Каждый физический порт прогоняется по цепочке, пока не будет получен ответ, отличный от None. Первый успешный ответ и будет использоваться в привязке. ## Конфигурирование Сollator'ов Осуществляется аналогично аппликаторам. В класс профилей добавляются настройки: * `interface_collators` - список из: * имя handler, или * (имя handler, настройки) настройки - dict с аргументами для конструктора collator'а. Получение эффективных настроек осуществляется методом профиля: ``` @classmethod def iter_collators(cls, object) # type: (ManagedObject) -> Iterable[BaseCollator] ``` может использоваться для тонкой настройки collator'ов в зависимости от платформы. ## Процесс привязки После отработки `interface` и `asset` discovery. Осуществляется в конце `asset` discovery. * Получаем цепочку настроенных collator'ов через `iter_collators` * Если она пуста - завершаем обработку * Строим словарь логических интерфейсов `interfaces` * по всем `path` из iter_physical_interfaces` * по всем `collator` из цепочки `collator'ов` * вызываем метод `collate(path, interfaces)` * если вернулся не None * осущесвляем привязку * break ## Хранение привязки Вводится новый тип `EmbeddedDocument` - ObjectConnectionData, для хранения дополнительных данных по связям объектов. Поля: * `name` - имя `ObjectConnection` из модели * `interface_name` - имя привязанного интерфейса (если есть) * `interface_managed_object` - опциональная ссылка на ManagedObject, если интерфейсы внутри объекта могут принадлежать разным ManagedObject. По умолчанию - всегда пустой. В дальнейшем в ObjectConnectionData могут появляться другие поля. Также в структуре `Object` появляется поле: * `connections` - список `ObjectConnectionData` При заполнении привязок происходит синхронизация `ObjectConnectionData`, добавляются и редактируются необходимые записи, пустые записи удаляются. ## Доработка datastream managedobject В разделе `asset.slots` добавляется дополнительный опциональный параметр `interface`. ## Stopper'ы * Изменяется структура `ConnectionType`, целесообразно реализовывать после слияния репозитория коллекций с `master`