Loading src/service/service/service_handler_api/FilterFields.py +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ DEVICE_DRIVER_VALUES = { DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN, DeviceDriverEnum.DEVICEDRIVER_OC, DeviceDriverEnum.DEVICEDRIVER_QKD, DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN, } # Map allowed filter fields to allowed values per Filter field. If no restriction (free text) None is specified Loading src/service/service/service_handlers/__init__.py +7 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ from common.proto.context_pb2 import DeviceDriverEnum, ServiceTypeEnum from ..service_handler_api.FilterFields import FilterFieldEnum from .l2nm_emulated.L2NMEmulatedServiceHandler import L2NMEmulatedServiceHandler from .l2nm_ietfl2vpn.L2NM_IETFL2VPN_ServiceHandler import L2NM_IETFL2VPN_ServiceHandler from .l3nm_ietfl3vpn.L3NM_IETFL3VPN_ServiceHandler import L3NM_IETFL3VPN_ServiceHandler from .l2nm_openconfig.L2NMOpenConfigServiceHandler import L2NMOpenConfigServiceHandler from .l3nm_emulated.L3NMEmulatedServiceHandler import L3NMEmulatedServiceHandler from .l3nm_openconfig.L3NMOpenConfigServiceHandler import L3NMOpenConfigServiceHandler Loading Loading @@ -66,6 +67,12 @@ SERVICE_HANDLERS = [ FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN, } ]), (L3NM_IETFL3VPN_ServiceHandler, [ { FilterFieldEnum.SERVICE_TYPE : ServiceTypeEnum.SERVICETYPE_L3NM, FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN, } ]), (TapiServiceHandler, [ { FilterFieldEnum.SERVICE_TYPE : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, Loading src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py 0 → 100644 +230 −0 Original line number Diff line number Diff line # Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. import json import logging from typing import Any, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method from common.proto.context_pb2 import ConfigRule, DeviceId, Service from common.tools.object_factory.ConfigRule import ( json_config_rule_delete, json_config_rule_set, ) from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_type from service.service.service_handler_api._ServiceHandler import _ServiceHandler from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.service_handler_api.Tools import ( get_device_endpoint_uuids, get_endpoint_matching, ) from service.service.task_scheduler.TaskExecutor import TaskExecutor LOGGER = logging.getLogger(__name__) METRICS_POOL = MetricsPool("Service", "Handler", labels={"handler": "l3nm_ietf_l3vpn"}) class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler): def __init__( # pylint: disable=super-init-not-called self, service: Service, task_executor: TaskExecutor, **settings ) -> None: self.__service = service self.__task_executor = task_executor self.__settings_handler = SettingsHandler(service.service_config, **settings) @metered_subclass_method(METRICS_POOL) def SetEndpoint( self, endpoints: List[Tuple[str, str, Optional[str]]], connection_uuid: Optional[str] = None, ) -> List[Union[bool, Exception]]: chk_type("endpoints", endpoints, list) if len(endpoints) < 2: return [] service_uuid = self.__service.service_id.service_uuid.uuid results = [] try: src_device_uuid, src_endpoint_uuid = get_device_endpoint_uuids(endpoints[0]) src_device_obj = self.__task_executor.get_device( DeviceId(**json_device_id(src_device_uuid)) ) src_endpoint_obj = get_endpoint_matching(src_device_obj, src_endpoint_uuid) src_endpoint_settings = self.__settings_handler.get_endpoint_settings( src_device_obj, src_endpoint_obj ).value dst_device_uuid, dst_endpoint_uuid = get_device_endpoint_uuids( endpoints[-1] ) dst_device_obj = self.__task_executor.get_device( DeviceId(**json_device_id(dst_device_uuid)) ) dst_endpoint_obj = get_endpoint_matching(dst_device_obj, dst_endpoint_uuid) dst_endpoint_settings = self.__settings_handler.get_endpoint_settings( dst_device_obj, dst_endpoint_obj ).value if dst_device_uuid != src_device_uuid: raise Exception("Different Src-Dst devices not supported by now") json_config_rule = json_config_rule_set( "/services/service[{:s}]".format(service_uuid), { "uuid": service_uuid, "src_device_name": src_device_obj.name, "src_endpoint_name": src_endpoint_obj.name, "src_site_location": src_endpoint_settings["location"], "src_ipv4_lan_prefixes": src_endpoint_settings["ipv4_lan_prefixes"], "src_ce_address": src_endpoint_settings["ce-ip"], "src_pe_address": src_endpoint_settings["address_ip"], "src_ce_pe_network_prefix": src_endpoint_settings["address_prefix"], "src_mtu": src_endpoint_settings["mtu"], "dst_device_name": dst_device_obj.name, "dst_endpoint_name": dst_endpoint_obj.name, "dst_site_location": dst_endpoint_settings["location"], "dst_ipv4_lan_prefixes": dst_endpoint_settings["ipv4_lan_prefixes"], "dst_ce_address": dst_endpoint_settings["ce-ip"], "dst_pe_address": dst_endpoint_settings["address_ip"], "dst_ce_pe_network_prefix": dst_endpoint_settings["address_prefix"], "dst_mtu": dst_endpoint_settings["mtu"], }, ) del src_device_obj.device_config.config_rules[:] src_device_obj.device_config.config_rules.append( ConfigRule(**json_config_rule) ) self.__task_executor.configure_device(src_device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception( "Unable to SetEndpoint for Service({:s})".format(str(service_uuid)) ) results.append(e) return results @metered_subclass_method(METRICS_POOL) def DeleteEndpoint( self, endpoints: List[Tuple[str, str, Optional[str]]], connection_uuid: Optional[str] = None, ) -> List[Union[bool, Exception]]: chk_type("endpoints", endpoints, list) if len(endpoints) < 2: return [] service_uuid = self.__service.service_id.service_uuid.uuid results = [] try: src_device_uuid, _ = get_device_endpoint_uuids(endpoints[0]) src_device = self.__task_executor.get_device( DeviceId(**json_device_id(src_device_uuid)) ) src_controller = self.__task_executor.get_device_controller(src_device) dst_device_uuid, _ = get_device_endpoint_uuids(endpoints[1]) dst_device = self.__task_executor.get_device( DeviceId(**json_device_id(dst_device_uuid)) ) dst_controller = self.__task_executor.get_device_controller(dst_device) if ( src_controller.device_id.device_uuid.uuid != dst_controller.device_id.device_uuid.uuid ): raise Exception("Different Src-Dst devices not supported by now") controller = src_controller json_config_rule = json_config_rule_delete( "/services/service[{:s}]".format(service_uuid), {"uuid": service_uuid} ) del controller.device_config.config_rules[:] controller.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(controller) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception( "Unable to DeleteEndpoint for Service({:s})".format(str(service_uuid)) ) results.append(e) return results @metered_subclass_method(METRICS_POOL) def SetConstraint( self, constraints: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("constraints", constraints, list) if len(constraints) == 0: return [] msg = "[SetConstraint] Method not implemented. Constraints({:s}) are being ignored." LOGGER.warning(msg.format(str(constraints))) return [True for _ in range(len(constraints))] @metered_subclass_method(METRICS_POOL) def DeleteConstraint( self, constraints: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("constraints", constraints, list) if len(constraints) == 0: return [] msg = "[DeleteConstraint] Method not implemented. Constraints({:s}) are being ignored." LOGGER.warning(msg.format(str(constraints))) return [True for _ in range(len(constraints))] @metered_subclass_method(METRICS_POOL) def SetConfig( self, resources: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("resources", resources, list) if len(resources) == 0: return [] results = [] for resource in resources: try: resource_value = json.loads(resource[1]) self.__settings_handler.set(resource[0], resource_value) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception("Unable to SetConfig({:s})".format(str(resource))) results.append(e) return results @metered_subclass_method(METRICS_POOL) def DeleteConfig( self, resources: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("resources", resources, list) if len(resources) == 0: return [] results = [] for resource in resources: try: self.__settings_handler.delete(resource[0]) except Exception as e: # pylint: disable=broad-except LOGGER.exception("Unable to DeleteConfig({:s})".format(str(resource))) results.append(e) return results src/service/service/service_handlers/l3nm_ietfl3vpn/__init__.py 0 → 100644 +14 −0 Original line number Diff line number Diff line # Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. Loading
src/service/service/service_handler_api/FilterFields.py +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ DEVICE_DRIVER_VALUES = { DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN, DeviceDriverEnum.DEVICEDRIVER_OC, DeviceDriverEnum.DEVICEDRIVER_QKD, DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN, } # Map allowed filter fields to allowed values per Filter field. If no restriction (free text) None is specified Loading
src/service/service/service_handlers/__init__.py +7 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ from common.proto.context_pb2 import DeviceDriverEnum, ServiceTypeEnum from ..service_handler_api.FilterFields import FilterFieldEnum from .l2nm_emulated.L2NMEmulatedServiceHandler import L2NMEmulatedServiceHandler from .l2nm_ietfl2vpn.L2NM_IETFL2VPN_ServiceHandler import L2NM_IETFL2VPN_ServiceHandler from .l3nm_ietfl3vpn.L3NM_IETFL3VPN_ServiceHandler import L3NM_IETFL3VPN_ServiceHandler from .l2nm_openconfig.L2NMOpenConfigServiceHandler import L2NMOpenConfigServiceHandler from .l3nm_emulated.L3NMEmulatedServiceHandler import L3NMEmulatedServiceHandler from .l3nm_openconfig.L3NMOpenConfigServiceHandler import L3NMOpenConfigServiceHandler Loading Loading @@ -66,6 +67,12 @@ SERVICE_HANDLERS = [ FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN, } ]), (L3NM_IETFL3VPN_ServiceHandler, [ { FilterFieldEnum.SERVICE_TYPE : ServiceTypeEnum.SERVICETYPE_L3NM, FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN, } ]), (TapiServiceHandler, [ { FilterFieldEnum.SERVICE_TYPE : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, Loading
src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py 0 → 100644 +230 −0 Original line number Diff line number Diff line # Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. import json import logging from typing import Any, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method from common.proto.context_pb2 import ConfigRule, DeviceId, Service from common.tools.object_factory.ConfigRule import ( json_config_rule_delete, json_config_rule_set, ) from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_type from service.service.service_handler_api._ServiceHandler import _ServiceHandler from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.service_handler_api.Tools import ( get_device_endpoint_uuids, get_endpoint_matching, ) from service.service.task_scheduler.TaskExecutor import TaskExecutor LOGGER = logging.getLogger(__name__) METRICS_POOL = MetricsPool("Service", "Handler", labels={"handler": "l3nm_ietf_l3vpn"}) class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler): def __init__( # pylint: disable=super-init-not-called self, service: Service, task_executor: TaskExecutor, **settings ) -> None: self.__service = service self.__task_executor = task_executor self.__settings_handler = SettingsHandler(service.service_config, **settings) @metered_subclass_method(METRICS_POOL) def SetEndpoint( self, endpoints: List[Tuple[str, str, Optional[str]]], connection_uuid: Optional[str] = None, ) -> List[Union[bool, Exception]]: chk_type("endpoints", endpoints, list) if len(endpoints) < 2: return [] service_uuid = self.__service.service_id.service_uuid.uuid results = [] try: src_device_uuid, src_endpoint_uuid = get_device_endpoint_uuids(endpoints[0]) src_device_obj = self.__task_executor.get_device( DeviceId(**json_device_id(src_device_uuid)) ) src_endpoint_obj = get_endpoint_matching(src_device_obj, src_endpoint_uuid) src_endpoint_settings = self.__settings_handler.get_endpoint_settings( src_device_obj, src_endpoint_obj ).value dst_device_uuid, dst_endpoint_uuid = get_device_endpoint_uuids( endpoints[-1] ) dst_device_obj = self.__task_executor.get_device( DeviceId(**json_device_id(dst_device_uuid)) ) dst_endpoint_obj = get_endpoint_matching(dst_device_obj, dst_endpoint_uuid) dst_endpoint_settings = self.__settings_handler.get_endpoint_settings( dst_device_obj, dst_endpoint_obj ).value if dst_device_uuid != src_device_uuid: raise Exception("Different Src-Dst devices not supported by now") json_config_rule = json_config_rule_set( "/services/service[{:s}]".format(service_uuid), { "uuid": service_uuid, "src_device_name": src_device_obj.name, "src_endpoint_name": src_endpoint_obj.name, "src_site_location": src_endpoint_settings["location"], "src_ipv4_lan_prefixes": src_endpoint_settings["ipv4_lan_prefixes"], "src_ce_address": src_endpoint_settings["ce-ip"], "src_pe_address": src_endpoint_settings["address_ip"], "src_ce_pe_network_prefix": src_endpoint_settings["address_prefix"], "src_mtu": src_endpoint_settings["mtu"], "dst_device_name": dst_device_obj.name, "dst_endpoint_name": dst_endpoint_obj.name, "dst_site_location": dst_endpoint_settings["location"], "dst_ipv4_lan_prefixes": dst_endpoint_settings["ipv4_lan_prefixes"], "dst_ce_address": dst_endpoint_settings["ce-ip"], "dst_pe_address": dst_endpoint_settings["address_ip"], "dst_ce_pe_network_prefix": dst_endpoint_settings["address_prefix"], "dst_mtu": dst_endpoint_settings["mtu"], }, ) del src_device_obj.device_config.config_rules[:] src_device_obj.device_config.config_rules.append( ConfigRule(**json_config_rule) ) self.__task_executor.configure_device(src_device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception( "Unable to SetEndpoint for Service({:s})".format(str(service_uuid)) ) results.append(e) return results @metered_subclass_method(METRICS_POOL) def DeleteEndpoint( self, endpoints: List[Tuple[str, str, Optional[str]]], connection_uuid: Optional[str] = None, ) -> List[Union[bool, Exception]]: chk_type("endpoints", endpoints, list) if len(endpoints) < 2: return [] service_uuid = self.__service.service_id.service_uuid.uuid results = [] try: src_device_uuid, _ = get_device_endpoint_uuids(endpoints[0]) src_device = self.__task_executor.get_device( DeviceId(**json_device_id(src_device_uuid)) ) src_controller = self.__task_executor.get_device_controller(src_device) dst_device_uuid, _ = get_device_endpoint_uuids(endpoints[1]) dst_device = self.__task_executor.get_device( DeviceId(**json_device_id(dst_device_uuid)) ) dst_controller = self.__task_executor.get_device_controller(dst_device) if ( src_controller.device_id.device_uuid.uuid != dst_controller.device_id.device_uuid.uuid ): raise Exception("Different Src-Dst devices not supported by now") controller = src_controller json_config_rule = json_config_rule_delete( "/services/service[{:s}]".format(service_uuid), {"uuid": service_uuid} ) del controller.device_config.config_rules[:] controller.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(controller) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception( "Unable to DeleteEndpoint for Service({:s})".format(str(service_uuid)) ) results.append(e) return results @metered_subclass_method(METRICS_POOL) def SetConstraint( self, constraints: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("constraints", constraints, list) if len(constraints) == 0: return [] msg = "[SetConstraint] Method not implemented. Constraints({:s}) are being ignored." LOGGER.warning(msg.format(str(constraints))) return [True for _ in range(len(constraints))] @metered_subclass_method(METRICS_POOL) def DeleteConstraint( self, constraints: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("constraints", constraints, list) if len(constraints) == 0: return [] msg = "[DeleteConstraint] Method not implemented. Constraints({:s}) are being ignored." LOGGER.warning(msg.format(str(constraints))) return [True for _ in range(len(constraints))] @metered_subclass_method(METRICS_POOL) def SetConfig( self, resources: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("resources", resources, list) if len(resources) == 0: return [] results = [] for resource in resources: try: resource_value = json.loads(resource[1]) self.__settings_handler.set(resource[0], resource_value) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception("Unable to SetConfig({:s})".format(str(resource))) results.append(e) return results @metered_subclass_method(METRICS_POOL) def DeleteConfig( self, resources: List[Tuple[str, Any]] ) -> List[Union[bool, Exception]]: chk_type("resources", resources, list) if len(resources) == 0: return [] results = [] for resource in resources: try: self.__settings_handler.delete(resource[0]) except Exception as e: # pylint: disable=broad-except LOGGER.exception("Unable to DeleteConfig({:s})".format(str(resource))) results.append(e) return results
src/service/service/service_handlers/l3nm_ietfl3vpn/__init__.py 0 → 100644 +14 −0 Original line number Diff line number Diff line # Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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.