blob: 720e4230d2f412d82864e2c4d91d3c629ec23c76 [file] [log] [blame]
# -*- 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)