| # -*- coding: utf-8 -*- |
| |
| ####################################################################################### |
| # This file is part of OSM RO module |
| # |
| # Copyright ETSI Contributors and Others. |
| # |
| # 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. |
| ####################################################################################### |
| # This work has been performed in the context of the TeraFlow Project - |
| # funded by the European Commission under Grant number 101015857 through the |
| # Horizon 2020 program. |
| # Contributors: |
| # - Lluis Gifre <lluis.gifre@cttc.es> |
| # - Ricard Vilalta <ricard.vilalta@cttc.es> |
| ####################################################################################### |
| |
| """This file contains the ServiceComposer class used by the Transport API (TAPI) WIM |
| connector to compose the services based on the service_endpoint_ids and their |
| directionality.""" |
| |
| from .exceptions import ( |
| WimTapiIncongruentDirectionality, |
| WimTapiIncongruentEndPoints, |
| WimTapiMissingMappingField, |
| WimTapiSipNotFound, |
| ) |
| from .message_composers import ( |
| compose_endpoint, |
| compose_requested_capacity, |
| # compose_vlan_constraint, |
| ) |
| |
| |
| class ServicesComposer: |
| def __init__(self, service_interface_points) -> None: |
| self.sips = service_interface_points |
| |
| # if unidirectional |
| # - a single service_endpoint item is created |
| # - the service_endpoint item contains with the 2 bidirectional SIPs |
| # if bidirectional |
| # - two service_endpoint items are created |
| # - each service_endpoint item containing a list of 2 unidirectional SIPs (in, out) |
| self.services = list() |
| |
| # TODO: populate dynamically capacity of the connection |
| self.requested_capacity = compose_requested_capacity(1, unit="GBPS") |
| |
| self.vlan_constraint = None |
| # TODO: VLAN needs to be processed by connection point; by now deactivated |
| # if connection_point.get("service_endpoint_encapsulation_type") == "dot1q": |
| # encap_info = connection_point.get("service_endpoint_encapsulation_info", {}) |
| # vlan_id = encap_info.get("vlan") |
| # if vlan_id is not None: |
| # vlan_constraint = compose_vlan_constraint(vlan_id) |
| |
| def add_bidirectional(self, service_endpoint_id): |
| if len(self.services) == 0: |
| # assume bidirectional, SIP is service_endpoint_id |
| service_interface_point = self.sips[service_endpoint_id] |
| self.services.append([compose_endpoint(service_interface_point)]) |
| elif len(self.services) == 1: |
| # is bidirectional, SIP is service_endpoint_id |
| if len(self.services[0]) > 1: |
| # too much endpoints per service |
| raise WimTapiIncongruentEndPoints(self.services, service_endpoint_id) |
| self.services[0].append(compose_endpoint(self.sips[service_endpoint_id])) |
| else: |
| raise WimTapiIncongruentDirectionality(self.services, service_endpoint_id) |
| |
| def add_unidirectional(self, service_endpoint_id, sip_input, sip_output): |
| if len(self.services) == 0: |
| # assume unidirectional |
| self.services.append([compose_endpoint(self.sips[sip_output])]) # AZ |
| self.services.append([compose_endpoint(self.sips[sip_input])]) # ZA |
| elif len(self.services) == 2: |
| # is unidirectional |
| |
| if len(self.services[0]) > 1: |
| # too much endpoints per service |
| raise WimTapiIncongruentEndPoints(self.services[0], service_endpoint_id) |
| self.services[0].append(compose_endpoint(self.sips[sip_input])) # AZ |
| |
| if len(self.services[1]) > 1: |
| # too much endpoints per service |
| raise WimTapiIncongruentEndPoints(self.services[1], service_endpoint_id) |
| self.services[1].insert(0, compose_endpoint(self.sips[sip_output])) # ZA |
| else: |
| raise WimTapiIncongruentDirectionality(self.services, service_endpoint_id) |
| |
| def add_service_endpoint(self, service_endpoint_id, mapping): |
| service_mapping_info = mapping.get("service_mapping_info", {}) |
| |
| if ( |
| len(service_mapping_info) == 0 |
| or "sip_input" not in service_mapping_info |
| or "sip_output" not in service_mapping_info |
| ): |
| # bidirectional (no mapping or no sip_input or no sip_output) |
| if service_endpoint_id not in self.sips: |
| raise WimTapiSipNotFound(service_endpoint_id, self.sips) |
| self.add_bidirectional(service_endpoint_id) |
| |
| else: |
| # unidirectional, sip_input and sip_output provided in mapping |
| |
| sip_input = service_mapping_info.get("sip_input") |
| if sip_input is None: |
| raise WimTapiMissingMappingField( |
| mapping, "service_mapping_info.sip_input" |
| ) |
| |
| if sip_input not in self.sips: |
| raise WimTapiSipNotFound(sip_input, self.sips) |
| |
| sip_output = service_mapping_info.get("sip_output") |
| if sip_output is None: |
| raise WimTapiMissingMappingField( |
| mapping, "service_mapping_info.sip_output" |
| ) |
| |
| if sip_output not in self.sips: |
| raise WimTapiSipNotFound(sip_output, self.sips) |
| |
| self.add_unidirectional(service_endpoint_id, sip_input, sip_output) |
| |
| def is_bidirectional(self): |
| return len(self.services) == 1 |
| |
| def dump(self, logger): |
| str_data = "\n".join( |
| [ |
| "services_composer {", |
| " services={:s}".format(str(self.services)), |
| " requested_capacity={:s}".format(str(self.requested_capacity)), |
| " vlan_constraint={:s}".format(str(self.vlan_constraint)), |
| "}", |
| ] |
| ) |
| logger.debug(str_data) |