Commit 581c3940 authored by Shayan Hajipour's avatar Shayan Hajipour
Browse files

merge develop into feat/110-cttc-incorrect-endpoint-lookup-in-nbi-etsi-bwm-plugin

parents 4bbdf917 f10241a6
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -226,8 +226,11 @@ def edit_config(
                chk_length(str_resource_name, resource, min_length=2, max_length=2)
                resource_key,resource_value = resource
                chk_string(str_resource_name + '.key', resource_key, allow_empty=False)

                str_config_messages = compose_config(                                                                          # get template for configuration
                    resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor, message_renderer=netconf_handler.message_renderer)
                    resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor, message_renderer='pyangbind')
                # str_config_messages = compose_config(                                                                          # get template for configuration
                #     resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor, message_renderer=netconf_handler.message_renderer)
                for str_config_message in str_config_messages:                                                                 # configuration of the received templates 
                    if str_config_message is None: raise UnsupportedResourceKeyException(resource_key)
                    logger.debug('[{:s}] str_config_message[{:d}] = {:s}'.format(
+2 −1
Original line number Diff line number Diff line
@@ -61,7 +61,8 @@ def generate_templates(resource_key: str, resource_value: str, delete: bool,vend
        elif "inter_instance_policies" in resource_key:
            result_templates.append(associate_RP_to_NI(data))
        elif "protocols" in resource_key:
            if vendor == "ADVA": result_templates.append(add_protocol_NI(data, vendor, delete))
            result_templates.append(add_protocol_NI(data, vendor, delete))
            # if vendor == "ADVA": result_templates.append(add_protocol_NI(data, vendor, delete))
        elif "table_connections" in resource_key:
            result_templates.append(create_table_conns(data, delete))
        elif "interface" in resource_key:
+33 −3
Original line number Diff line number Diff line
@@ -116,6 +116,9 @@ def add_protocol_NI(parameters,vendor, DEL):
        else:
            with tag('network-instance'):
                with tag('name'):text(parameters['name'])
                with tag('config'):
                    with tag('name'): text(parameters['name'])
                    with tag('type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"'): text('oc-ni-types:DEFAULT_INSTANCE')
                with tag('protocols'):
                    with tag('protocol'):
                        with tag('identifier', 'xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):text('oc-pol-types:',parameters['identifier'])
@@ -123,14 +126,41 @@ def add_protocol_NI(parameters,vendor, DEL):
                        with tag('config'):
                            with tag('identifier', 'xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):text('oc-pol-types:',parameters['identifier'])
                            with tag('name')      :text(parameters['protocol_name'])
                            with tag('enabled'): text('true')
                        if "BGP" in parameters['identifier']:
                            with tag('bgp'):
                                with tag('global'):
                                    with tag('afi-safis'):
                                        with tag('afi-safi'):
                                            with tag('afi-safi-name', 'xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types"'): text('oc-bgp-types:IPV4_UNICAST')
                                            with tag('config'):
                                                with tag('afi-safi-name', 'xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types"'): text('oc-bgp-types:IPV4_UNICAST')
                                                with tag('enabled'): text('true')
                                    with tag('config'):
                                        with tag('as')       :text(parameters['as'])
                                        if "router-id" in parameters: 
                                            with tag('router-id'):text(parameters['router-id'])
                if vendor == "ADVA": 
                                with tag('peer-groups'):
                                    with tag('peer-group'):
                                        with tag('peer-group-name'): text('IBGP')
                                        with tag('config'):
                                            with tag('peer-group-name'): text('IBGP')
                                            with tag('peer-as'): text(parameters['protocol_name'])
                                        with tag('afi-safis'):
                                            with tag('afi-safi'):
                                                with tag('afi-safi-name', 'xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types"'): text('oc-bgp-types:IPV4_UNICAST')
                                                with tag('config'):
                                                    with tag('afi-safi-name', 'xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types"'): text('oc-bgp-types:IPV4_UNICAST')
                                                    with tag('enabled'): text('true')

                                if 'neighbors' in parameters:
                                    with tag('neighbors'):
                                      for neighbor in parameters['neighbors']:
                                          with tag('neighbor'):
                                              with tag('neighbor-address'): text(neighbor['ip_address'])
                                              with tag('config'):
                                                  with tag('neighbor-address'): text(neighbor['ip_address'])
                                                  with tag('peer-group'): text('IBGP')
                # if vendor == "ADVA": 
                if True: 
                    with tag('tables'):
                      with tag('table'):
                          with tag('protocol', 'xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):text('oc-pol-types:',parameters['identifier'])
+11 −4
Original line number Diff line number Diff line
@@ -13,7 +13,9 @@
# limitations under the License.

import copy, deepmerge, json, logging
from typing import Dict
from common.Constants import DEFAULT_CONTEXT_NAME
from werkzeug.exceptions import UnsupportedMediaType
from context.client.ContextClient import ContextClient
from flask_restful import Resource, request
from service.client.ServiceClient import ServiceClient
@@ -37,15 +39,20 @@ class BwInfo(_Resource):
        return bw_allocations

    def post(self):
        bwinfo = request.get_json()
        service = bwInfo_2_service(self.client, bwinfo)
        if not request.is_json:
            raise UnsupportedMediaType('JSON payload is required')
        request_data: Dict = request.get_json()
        service = bwInfo_2_service(self.client, request_data)
        stripped_service = copy.deepcopy(service)
        stripped_service.ClearField('service_endpoint_ids')
        stripped_service.ClearField('service_constraints')
        stripped_service.ClearField('service_config')

        try:
            response = format_grpc_to_json(self.service_client.CreateService(stripped_service))
            response = format_grpc_to_json(self.service_client.UpdateService(service))
        except Exception as e: # pylint: disable=broad-except
            return e

        return response

+106 −37
Original line number Diff line number Diff line
@@ -19,20 +19,30 @@ import time
from decimal import ROUND_HALF_EVEN, Decimal
from flask.json import jsonify
from common.proto.context_pb2 import (
    ContextId, Empty, EndPointId, ServiceId, ServiceTypeEnum, Service, Constraint, Constraint_SLA_Capacity,
    ContextId, Empty, EndPointId, ServiceId, ServiceTypeEnum, Service, ServiceStatusEnum, Constraint, Constraint_SLA_Capacity,
    ConfigRule, ConfigRule_Custom, ConfigActionEnum)
from common.tools.grpc.Tools import grpc_message_to_json
from common.tools.grpc.ConfigRules import update_config_rule_custom
from common.tools.object_factory.Context import json_context_id
from common.tools.object_factory.Service import json_service_id

LOGGER = logging.getLogger(__name__)

ENDPOINT_SETTINGS_KEY = '/device[{:s}]/endpoint[{:s}]/vlan[{:d}]/settings'
RE_CONFIG_RULE_IF_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$')
RE_CONFIG_RULE_ADDRESS_IP = re.compile(r'\\\"address_ip\\\": \\\"((?:[0-9]{1,3}\.){3}[0-9]{1,3})\\\"')
MEC_CONSIDERED_FIELDS = ['requestType', 'sessionFilter', 'fixedAllocation', 'allocationDirection']
ALLOCATION_DIRECTION_DESCRIPTIONS = {
    '00' : 'Downlink (towards the UE)',
    '01' : 'Uplink (towards the application/session)',
    '10' : 'Symmetrical'}
VLAN_TAG = 0
PREFIX_LENGTH = 24
BGP_AS = 65000
policy_AZ = 'srv_{:d}_a'.format(VLAN_TAG)
policy_ZA = 'srv_{:d}_b'.format(VLAN_TAG)

def service_2_bwInfo(service: Service) -> dict:
    response = {}
    # allocationDirection = '??' # String: 00 = Downlink (towards the UE); 01 = Uplink (towards the application/session); 10 = Symmetrical
    response['appInsId'] = service.service_id.service_uuid.uuid # String: Application instance identifier
    for constraint in service.service_constraints:
        if constraint.WhichOneof('constraint') == 'sla_capacity':
@@ -58,50 +68,109 @@ def service_2_bwInfo(service: Service) -> dict:

    return response

def bwInfo_2_service(client, bwInfo: dict) -> Service:
def bwInfo_2_service(client, bw_info: dict) -> Service:
    # add description to allocationDirection code
    if ad_code := bw_info.get('allocationDirection'):
        bw_info['allocationDirection'] = {'code': ad_code, 'description': ALLOCATION_DIRECTION_DESCRIPTIONS[ad_code]}
    if 'sessionFilter' in bw_info:
        bw_info['sessionFilter'] = bw_info['sessionFilter'][0] # Discard other items in sessionFilter field

    service = Service()
    for key in ['allocationDirection', 'fixedBWPriority', 'requestType', 'timeStamp', 'sessionFilter']:
        if key not in bwInfo:
            continue
    
    service_config_rules = service.service_config.config_rules

    route_distinguisher = '{:5d}:{:03d}'.format(BGP_AS, VLAN_TAG)
    settings_cr_key = '/settings'
    settings_cr_value = {'bgp_as':(BGP_AS, True), 'route_distinguisher': (route_distinguisher, True)}
    update_config_rule_custom(service_config_rules, settings_cr_key, settings_cr_value)

    request_cr_key = '/request'
    request_cr_value = {k:bw_info[k] for k in MEC_CONSIDERED_FIELDS}

    config_rule = ConfigRule()
    config_rule.action = ConfigActionEnum.CONFIGACTION_SET
    config_rule_custom = ConfigRule_Custom()
        config_rule_custom.resource_key  = key
        if key != 'sessionFilter':
            config_rule_custom.resource_value  = str(bwInfo[key])
        else:
            config_rule_custom.resource_value  = json.dumps(bwInfo[key])
    config_rule_custom.resource_key  = request_cr_key
    config_rule_custom.resource_value = json.dumps(request_cr_value)
    config_rule.custom.CopyFrom(config_rule_custom)
        service.service_config.config_rules.append(config_rule)
    service_config_rules.append(config_rule)

    if 'sessionFilter' in bwInfo:
        a_ip = bwInfo['sessionFilter'][0]['sourceIp']
        z_ip = bwInfo['sessionFilter'][0]['dstAddress']
    if 'sessionFilter' in bw_info:
        a_ip = bw_info['sessionFilter']['sourceIp']
        z_ip = bw_info['sessionFilter']['dstAddress']

        devices = client.ListDevices(Empty()).devices
        router_id_counter = 1
        for device in devices:
            device_endpoint_uuids = {ep.name:ep.endpoint_id.endpoint_uuid for ep in device.device_endpoints}

            device_endpoint_uuids = {ep.name:ep.endpoint_id.endpoint_uuid.uuid for ep in device.device_endpoints}
            for cr in device.device_config.config_rules:
                if cr.WhichOneof('config_rule') == 'custom':
                if cr.WhichOneof('config_rule') != 'custom':
                    continue
                match_subif = RE_CONFIG_RULE_IF_SUBIF.match(cr.custom.resource_key)
                    match_ip = RE_CONFIG_RULE_ADDRESS_IP.match(cr.custom.resource_value)
                    if match_subif and match_ip and match_ip.groups(0)[0] in [a_ip, z_ip]:
                        # `PORT-` added as prefix
                        port_name = 'PORT-' + match_subif.groups(0)[0]
                if not match_subif:
                    continue
                address_ip = json.loads(cr.custom.resource_value).get('address_ip')
                if address_ip not in [a_ip, z_ip]:
                    continue
                port_name = 'PORT-' + match_subif.groups(0)[0] # `PORT-` added as prefix
                ep_id = EndPointId()
                ep_id.endpoint_uuid.uuid = device_endpoint_uuids[port_name]
                ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid
                service.service_endpoint_ids.append(ep_id)

                # add interface config rules
                endpoint_settings_key = ENDPOINT_SETTINGS_KEY.format(device.name, port_name, VLAN_TAG)
                if address_ip == a_ip:
                    field_updates = {
                    'address_ip': (address_ip, True),
                    # 'router_id': ('.'.join([str(router_id_counter)]*4), True),
                    'router_id': ('200.1.1.1', True),
                    'neighbor_address_ip': ('192.168.150.2', True),
                    'route_distinguisher': (route_distinguisher, True),
                    'sub_interface_index': (0, True),
                    'vlan_id'            : (VLAN_TAG, True),
                    # 'bgp_as': (BGP_AS+router_id_counter, True),
                    'bgp_as': (BGP_AS, True),
                    'ip_address': (address_ip, True),
                    'prefix_length': (PREFIX_LENGTH, True),
                    'policy_AZ'           : (policy_AZ, True),
                    'policy_ZA'           : (policy_ZA, True),
                    'address_prefix'     : (PREFIX_LENGTH, True),
                        }
                elif address_ip == z_ip:
                    field_updates = {
                    'address_ip': (address_ip, True),
                    # 'router_id': ('.'.join([str(router_id_counter)]*4), True),
                    'router_id': ('200.1.1.2', True),
                    'neighbor_address_ip': ('192.168.150.1', True),
                    'route_distinguisher': (route_distinguisher, True),
                    'sub_interface_index': (0, True),
                    'vlan_id'            : (VLAN_TAG, True),
                    # 'bgp_as': (BGP_AS+router_id_counter, True),
                    'bgp_as': (BGP_AS, True),
                    'ip_address': (address_ip, True),
                    'prefix_length': (PREFIX_LENGTH, True),
                    'policy_AZ'           : (policy_ZA, True),
                    'policy_ZA'           : (policy_AZ, True),
                    'address_prefix'     : (PREFIX_LENGTH, True),
                        }
                router_id_counter += 1
                LOGGER.debug(f'BEFORE UPDATE -> device.device_config.config_rules: {service_config_rules}')
                update_config_rule_custom(service_config_rules, endpoint_settings_key, field_updates)
                LOGGER.debug(f'AFTER UPDATE -> device.device_config.config_rules: {service_config_rules}')

    service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED
    service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM

    if 'appInsId' in bwInfo:
        service.service_id.service_uuid.uuid = bwInfo['appInsId']
    if 'appInsId' in bw_info:
        service.service_id.service_uuid.uuid = bw_info['appInsId']
        service.service_id.context_id.context_uuid.uuid = 'admin'
        service.name = bwInfo['appInsId']
        service.name = bw_info['appInsId']

    if 'fixedAllocation' in bwInfo:
    if 'fixedAllocation' in bw_info:
        capacity = Constraint_SLA_Capacity()
        capacity.capacity_gbps = float(bwInfo['fixedAllocation']) / 1.e9
        capacity.capacity_gbps = float(bw_info['fixedAllocation']) / 1.e9
        constraint = Constraint()
        constraint.sla_capacity.CopyFrom(capacity)
        service.service_constraints.append(constraint)
Loading