diff --git a/src/device/service/driver_api/ImportTopologyEnum.py b/src/device/service/driver_api/ImportTopologyEnum.py new file mode 100644 index 0000000000000000000000000000000000000000..06f0ff9c2db1f1baccc4b46c5babc4458ca6ffb6 --- /dev/null +++ b/src/device/service/driver_api/ImportTopologyEnum.py @@ -0,0 +1,37 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from enum import Enum +from typing import Dict + +class ImportTopologyEnum(Enum): + # While importing underlying resources, the driver just imports endpoints and exposes them directly. + DISABLED = 'disabled' + + # While importing underlying resources, the driver just imports imports sub-devices but not links + # connecting them. The endpoints are exposed in virtual nodes representing the sub-devices. + # (a remotely-controlled transport domain might exist between nodes) + DEVICES = 'devices' + + # While importing underlying resources, the driver just imports imports sub-devices and links + # connecting them. The endpoints are exposed in virtual nodes representing the sub-devices. + # (enables to define constrained connectivity between the sub-devices) + TOPOLOGY = 'topology' + +def get_import_topology(settings : Dict, default : ImportTopologyEnum = ImportTopologyEnum.DISABLED): + str_import_topology = settings.get('import_topology') + if str_import_topology is None: return default + import_topology = ImportTopologyEnum._value2member_map_.get(str_import_topology) # pylint: disable=no-member + if import_topology is None: raise Exception('Unexpected setting value') + return import_topology diff --git a/src/device/service/drivers/xr/XrDriver.py b/src/device/service/drivers/xr/XrDriver.py index 83ffd52183a5e8f81b465aaa15c07e1478e67a8d..2b53de8e71f84aada460f444a3663238290f6ea5 100644 --- a/src/device/service/drivers/xr/XrDriver.py +++ b/src/device/service/drivers/xr/XrDriver.py @@ -22,6 +22,7 @@ from common.DeviceTypes import DeviceTypeEnum from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method from common.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum from common.type_checkers.Checkers import chk_type +from device.service.driver_api.ImportTopologyEnum import ImportTopologyEnum, get_import_topology from device.service.driver_api._Driver import _Driver from .cm.cm_connection import CmConnection, ConsistencyMode from .cm import tf @@ -48,6 +49,14 @@ class XrDriver(_Driver): username = settings.get("username", "xr-user-1") password = settings.get("password", "xr-user-1") + # Options are: + # disabled --> just import endpoints as usual + # devices --> imports sub-devices but not links connecting them. + # (a remotely-controlled transport domain might exist between them) + # topology --> imports sub-devices and links connecting them. + # (not supported by XR driver) + self.__import_topology = get_import_topology(settings, default=ImportTopologyEnum.DISABLED) + # Options are: # asynchronous --> operation considered complete when IPM responds with suitable status code, # including "accepted", that only means request is semantically good and queued. @@ -100,50 +109,56 @@ class XrDriver(_Driver): constellation = self.__cm_connection.get_constellation_by_hub_name(self.__hub_module_name) if constellation: self.__constellation = constellation - #return [(f"/endpoints/endpoint[{ifname}]", {'uuid': ifname, 'type': 'optical', 'sample_types': {}}) for ifname in constellation.ifnames()] - - devices : Set[str] = set() - pluggables : Set[str] = set() - devices_and_endpoints = [] - for ifname in constellation.ifnames(): - device_name,pluggable_name = ifname.split('|') - - if device_name not in devices: - device_url = '/devices/device[{:s}]'.format(device_name) - device_data = { - 'uuid': device_name, 'name': device_name, - 'type': DeviceTypeEnum.EMULATED_PACKET_ROUTER.value, - 'status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED, - 'drivers': [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED], - } - devices_and_endpoints.append((device_url, device_data)) - - for copper_if_index in range(4): - copper_ifname = '1/{:d}'.format(copper_if_index + 1) - endpoint_url = '/endpoints/endpoint[{:s}]'.format(copper_ifname) + if self.__import_topology == ImportTopologyEnum.DISABLED: + return [ + (f"/endpoints/endpoint[{ifname}]", {'uuid': ifname, 'type': 'optical', 'sample_types': {}}) + for ifname in constellation.ifnames() + ] + elif self.__import_topology == ImportTopologyEnum.DEVICES: + devices : Set[str] = set() + pluggables : Set[str] = set() + devices_and_endpoints = [] + for ifname in constellation.ifnames(): + device_name,pluggable_name = ifname.split('|') + + if device_name not in devices: + device_url = '/devices/device[{:s}]'.format(device_name) + device_data = { + 'uuid': device_name, 'name': device_name, + 'type': DeviceTypeEnum.EMULATED_PACKET_ROUTER.value, + 'status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED, + 'drivers': [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED], + } + devices_and_endpoints.append((device_url, device_data)) + + for copper_if_index in range(4): + copper_ifname = '1/{:d}'.format(copper_if_index + 1) + endpoint_url = '/endpoints/endpoint[{:s}]'.format(copper_ifname) + endpoint_data = { + 'device_uuid': device_name, 'uuid': copper_ifname, 'name': copper_ifname, + 'type': 'copper/internal', 'sample_types': {} + } + devices_and_endpoints.append((endpoint_url, endpoint_data)) + + devices.add(device_name) + + if ifname not in pluggables: + endpoint_url = '/endpoints/endpoint[{:s}]'.format(ifname) + if 'hub' in ifname.lower(): + endpoint_type = 'optical/xr-hub' + elif 'leaf' in ifname.lower(): + endpoint_type = 'optical/xr-leaf' + else: + endpoint_type = 'optical/xr' endpoint_data = { - 'device_uuid': device_name, 'uuid': copper_ifname, 'name': copper_ifname, - 'type': 'copper/internal', 'sample_types': {} + 'device_uuid': device_name, 'uuid': pluggable_name, 'name': pluggable_name, + 'type': endpoint_type, 'sample_types': {} } devices_and_endpoints.append((endpoint_url, endpoint_data)) - devices.add(device_name) - - if ifname not in pluggables: - endpoint_url = '/endpoints/endpoint[{:s}]'.format(ifname) - if 'hub' in ifname.lower(): - endpoint_type = 'optical/xr-hub' - elif 'leaf' in ifname.lower(): - endpoint_type = 'optical/xr-leaf' - else: - endpoint_type = 'optical/xr' - endpoint_data = { - 'device_uuid': device_name, 'uuid': pluggable_name, 'name': pluggable_name, - 'type': endpoint_type, 'sample_types': {} - } - devices_and_endpoints.append((endpoint_url, endpoint_data)) - - return devices_and_endpoints + return devices_and_endpoints + else: + raise Exception('Unsupported import_topology mode: {:s}'.format(str(self.__import_topology))) else: return []