From 6958674bf5af23810e1e318981c979450683069c Mon Sep 17 00:00:00 2001 From: hajipour Date: Fri, 26 Jan 2024 14:49:05 +0100 Subject: [PATCH 01/29] bug fix: port & device uuids extracted from device protobuf message instead of custom feature which is dedicated for emulated devices. --- .../rest_server/nbi_plugins/etsi_bwm/Tools.py | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index a78d28193..c80591992 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -14,6 +14,7 @@ import json import logging +import re import time from decimal import ROUND_HALF_EVEN, Decimal from flask.json import jsonify @@ -26,6 +27,9 @@ from common.tools.object_factory.Service import json_service_id LOGGER = logging.getLogger(__name__) +RE_PORT_AND_IP_MATCH = r'resource_key: \"\/interface\[(.*)\]\/subinterface\[.*\]\"[.|\n]*.*\\\"address_ip\\\": \\\"{}\\\"' +RE_ENDPOINT_UUID_PORT_MATCH = r'\s*\n?\s*endpoint_uuid .\s*\n?\s*uuid: \"(.*)\"\n?\s*.\n?\s*.\n?\s*name: \"{}\"' +RE_DEVICE_UUID_MATCH = r'\n?\s*device_uuid \{\s*\n?\s*uuid: \"(.*)\"\n?\s*\}\n?\s*\}' def service_2_bwInfo(service: Service) -> dict: response = {} @@ -75,17 +79,20 @@ def bwInfo_2_service(client, bwInfo: dict) -> Service: a_ip = bwInfo['sessionFilter'][0]['sourceIp'] z_ip = bwInfo['sessionFilter'][0]['dstAddress'] - devices = client.ListDevices(Empty()).devices + devices = (str(device) for device in client.ListDevices(Empty()).devices) for device in devices: - for cr in device.device_config.config_rules: - if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == '_connect/settings': - for ep in json.loads(cr.custom.resource_value)['endpoints']: - if 'ip' in ep and (ep['ip'] == a_ip or ep['ip'] == z_ip): - ep_id = EndPointId() - ep_id.endpoint_uuid.uuid = ep['uuid'] - ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid - service.service_endpoint_ids.append(ep_id) - + for ep_id in (a_ip, z_ip): + if look_up := re.search(RE_PORT_AND_IP_MATCH.format(ep_id), device): + physical_port = look_up.groups(0)[0] + # 'PORT-' is added as a prefix + port = 'PORT-' + physical_port + port_uuid = re.search(RE_ENDPOINT_UUID_PORT_MATCH.format(port), device).group(0)[0] + device_uuid = re.search(RE_DEVICE_UUID_MATCH, device).group(0)[0] + ep_id = EndPointId() + ep_id.endpoint_uuid.uuid = port_uuid + ep_id.device_id.device_uuid.uuid = device_uuid + service.service_endpoint_ids.append(ep_id) + service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM if 'appInsId' in bwInfo: -- GitLab From 27b2104dd4fb4615db630ec424ee20258acbeec0 Mon Sep 17 00:00:00 2001 From: hajipour Date: Fri, 26 Jan 2024 23:16:03 +0100 Subject: [PATCH 02/29] refactoring: port lookup done sequentially in device protobuf instead of global regex search --- .../rest_server/nbi_plugins/etsi_bwm/Tools.py | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index c80591992..17199315d 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -27,9 +27,8 @@ from common.tools.object_factory.Service import json_service_id LOGGER = logging.getLogger(__name__) -RE_PORT_AND_IP_MATCH = r'resource_key: \"\/interface\[(.*)\]\/subinterface\[.*\]\"[.|\n]*.*\\\"address_ip\\\": \\\"{}\\\"' -RE_ENDPOINT_UUID_PORT_MATCH = r'\s*\n?\s*endpoint_uuid .\s*\n?\s*uuid: \"(.*)\"\n?\s*.\n?\s*.\n?\s*name: \"{}\"' -RE_DEVICE_UUID_MATCH = r'\n?\s*device_uuid \{\s*\n?\s*uuid: \"(.*)\"\n?\s*\}\n?\s*\}' +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})\\\"') def service_2_bwInfo(service: Service) -> dict: response = {} @@ -79,20 +78,20 @@ def bwInfo_2_service(client, bwInfo: dict) -> Service: a_ip = bwInfo['sessionFilter'][0]['sourceIp'] z_ip = bwInfo['sessionFilter'][0]['dstAddress'] - devices = (str(device) for device in client.ListDevices(Empty()).devices) + devices = client.ListDevices(Empty()).devices for device in devices: - for ep_id in (a_ip, z_ip): - if look_up := re.search(RE_PORT_AND_IP_MATCH.format(ep_id), device): - physical_port = look_up.groups(0)[0] - # 'PORT-' is added as a prefix - port = 'PORT-' + physical_port - port_uuid = re.search(RE_ENDPOINT_UUID_PORT_MATCH.format(port), device).group(0)[0] - device_uuid = re.search(RE_DEVICE_UUID_MATCH, device).group(0)[0] - ep_id = EndPointId() - ep_id.endpoint_uuid.uuid = port_uuid - ep_id.device_id.device_uuid.uuid = device_uuid - service.service_endpoint_ids.append(ep_id) - + device_endpoint_uuids = {ep.name:ep.endpoint_id.endpoint_uuid for ep in device.device_endpoints} + for cr in device.device_config.config_rules: + if cr.WhichOneof('config_rule') == 'custom': + 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] + 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 + service.service_endpoint_ids.append(ep_id) service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM if 'appInsId' in bwInfo: -- GitLab From c2179dd845b717806fb0acc522f80e70581e0a37 Mon Sep 17 00:00:00 2001 From: hajipour Date: Fri, 26 Jan 2024 23:44:16 +0100 Subject: [PATCH 03/29] bug fix: Showing service info error in webui when service is created by BWM resolved. --- src/webui/service/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py index 05b2eeaf0..5211ad935 100644 --- a/src/webui/service/__init__.py +++ b/src/webui/service/__init__.py @@ -48,7 +48,7 @@ def json_to_list(json_str : str) -> List[Union[str, Tuple[str, str]]]: if isinstance(data, dict): return [('kv', (key, value)) for key, value in data.items()] - elif isinstance(data, list): + elif isinstance(data, list) and not isinstance(data[0], dict): return [('item', ', '.join(data))] else: return [('item', str(data))] -- GitLab From ccdf13d912422c550f141a4f6ca81533ff749aad Mon Sep 17 00:00:00 2001 From: hajipour Date: Sun, 28 Jan 2024 11:18:15 +0100 Subject: [PATCH 04/29] bug fix:device's uuid assigned to EndpointId.device_id.device_uuid.uuid in bwm service creation. --- src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index 17199315d..b9ed73850 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -90,7 +90,7 @@ def bwInfo_2_service(client, bwInfo: dict) -> Service: port_name = 'PORT-' + match_subif.groups(0)[0] 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 + ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid service.service_endpoint_ids.append(ep_id) service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM -- GitLab From 4bbdf917ca1ea8a6a19a2ea9e5bfbe4b3ddf60dd Mon Sep 17 00:00:00 2001 From: hajipour Date: Sun, 28 Jan 2024 17:26:48 +0100 Subject: [PATCH 05/29] bug fix: json_to_list function bug when json_str is empty list resolved. --- src/webui/service/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py index 5211ad935..7146f321b 100644 --- a/src/webui/service/__init__.py +++ b/src/webui/service/__init__.py @@ -45,10 +45,12 @@ def json_to_list(json_str : str) -> List[Union[str, Tuple[str, str]]]: data = json.loads(json_str) except: # pylint: disable=bare-except return [('item', str(json_str))] - + if isinstance(data, dict): return [('kv', (key, value)) for key, value in data.items()] - elif isinstance(data, list) and not isinstance(data[0], dict): + elif isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict): # BWM use-case + return [('kv', (key, value)) for key, value in data[0].items()] + elif isinstance(data, list) and all(isinstance(d, str) for d in data): return [('item', ', '.join(data))] else: return [('item', str(data))] -- GitLab From f10241a6c1228d1100750f5e79bdff1e88fbce02 Mon Sep 17 00:00:00 2001 From: hajipour Date: Mon, 12 Feb 2024 12:24:01 +0000 Subject: [PATCH 06/29] bug fix: temporary fix for MEC PoC demo. Config rules and OpenConfig driver for L3VPN should change based on telefonica recipe. --- .../drivers/openconfig/OpenConfigDriver.py | 5 +- .../drivers/openconfig/templates/Tools.py | 3 +- .../VPN/Network_instance_multivendor.py | 36 ++++- .../nbi_plugins/etsi_bwm/Resources.py | 15 +- .../rest_server/nbi_plugins/etsi_bwm/Tools.py | 140 +++++++++++++----- .../algorithms/tools/ComposeConfigRules.py | 18 +++ .../l3nm_openconfig/ConfigRules.py | 66 +++++++-- 7 files changed, 229 insertions(+), 54 deletions(-) diff --git a/src/device/service/drivers/openconfig/OpenConfigDriver.py b/src/device/service/drivers/openconfig/OpenConfigDriver.py index 8c6e07b3f..99ae1c8db 100644 --- a/src/device/service/drivers/openconfig/OpenConfigDriver.py +++ b/src/device/service/drivers/openconfig/OpenConfigDriver.py @@ -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( diff --git a/src/device/service/drivers/openconfig/templates/Tools.py b/src/device/service/drivers/openconfig/templates/Tools.py index 79bebef51..3e8043680 100644 --- a/src/device/service/drivers/openconfig/templates/Tools.py +++ b/src/device/service/drivers/openconfig/templates/Tools.py @@ -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: diff --git a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py index c4d494ea6..e36955a0d 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py @@ -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']) diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py index 3fccbbb55..394b50de8 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py @@ -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') - response = format_grpc_to_json(self.service_client.CreateService(stripped_service)) - response = format_grpc_to_json(self.service_client.UpdateService(service)) + 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 diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index a78d28193..d3be769c9 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -14,22 +14,35 @@ import json import logging +import re 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\[([^\]]+)\]$') +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': @@ -55,47 +68,108 @@ 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 - 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.CopyFrom(config_rule_custom) - service.service_config.config_rules.append(config_rule) - - if 'sessionFilter' in bwInfo: - a_ip = bwInfo['sessionFilter'][0]['sourceIp'] - z_ip = bwInfo['sessionFilter'][0]['dstAddress'] + + 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 = request_cr_key + config_rule_custom.resource_value = json.dumps(request_cr_value) + config_rule.custom.CopyFrom(config_rule_custom) + service_config_rules.append(config_rule) + + 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.uuid for ep in device.device_endpoints} for cr in device.device_config.config_rules: - if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == '_connect/settings': - for ep in json.loads(cr.custom.resource_value)['endpoints']: - if 'ip' in ep and (ep['ip'] == a_ip or ep['ip'] == z_ip): - ep_id = EndPointId() - ep_id.endpoint_uuid.uuid = ep['uuid'] - ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid - service.service_endpoint_ids.append(ep_id) - + if cr.WhichOneof('config_rule') != 'custom': + continue + match_subif = RE_CONFIG_RULE_IF_SUBIF.match(cr.custom.resource_key) + 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) diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py index 329552a91..498db7dcd 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py @@ -24,6 +24,7 @@ SETTINGS_RULE_NAME = '/settings' DEVICE_SETTINGS = re.compile(r'\/device\[([^\]]+)\]\/settings') ENDPOINT_SETTINGS = re.compile(r'\/device\[([^\]]+)\]\/endpoint\[([^\]]+)\]\/settings') +RE_ENDPOINT_VLAN_SETTINGS = re.compile(r'\/device\[([^\]]+)\]\/endpoint\[([^\]]+)\]\/vlan\[([^\]]+)\]\/settings') L2NM_SETTINGS_FIELD_DEFAULTS = { 'encapsulation_type': 'dot1q', @@ -150,6 +151,23 @@ def compose_device_config_rules( device_endpoint_keys = set(itertools.product(device_keys, endpoint_keys)) if len(device_endpoint_keys.intersection(endpoints_traversed)) == 0: continue subservice_config_rules.append(config_rule) + + match = RE_ENDPOINT_VLAN_SETTINGS.match(config_rule.custom.resource_key) + if match is not None: + device_uuid_or_name = match.group(1) + device_name_or_uuid = device_name_mapping[device_uuid_or_name] + device_keys = {device_uuid_or_name, device_name_or_uuid} + + endpoint_uuid_or_name = match.group(2) + endpoint_name_or_uuid_1 = endpoint_name_mapping[(device_uuid_or_name, endpoint_uuid_or_name)] + endpoint_name_or_uuid_2 = endpoint_name_mapping[(device_name_or_uuid, endpoint_uuid_or_name)] + endpoint_keys = {endpoint_uuid_or_name, endpoint_name_or_uuid_1, endpoint_name_or_uuid_2} + + device_endpoint_keys = set(itertools.product(device_keys, endpoint_keys)) + if len(device_endpoint_keys.intersection(endpoints_traversed)) == 0: continue + # ! check later: vlan removed from config_rule + config_rule.custom.resource_key = re.sub('\/vlan\[[^\]]+\]', '', config_rule.custom.resource_key) + subservice_config_rules.append(config_rule) else: continue diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 1e4425cdb..0369d6207 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -37,6 +37,7 @@ def setup_config_rules( vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 + neighbor_address_ip = json_endpoint_settings.get('neighbor_address_ip', '0.0.0.0') # '2.2.2.1' policy_import = json_endpoint_settings.get('policy_AZ', '2' ) # 2 policy_export = json_endpoint_settings.get('policy_ZA', '7' ) # 30 @@ -46,18 +47,21 @@ def setup_config_rules( network_subinterface_desc = json_endpoint_settings.get('subif_description','') #service_short_uuid = service_uuid.split('-')[-1] #network_instance_name = '{:s}-NetInst'.format(service_short_uuid) - network_instance_name = json_endpoint_settings.get('ni_name', service_uuid.split('-')[-1]) #ELAN-AC:1 + # network_instance_name = json_endpoint_settings.get('ni_name', service_uuid.split('-')[-1]) #ELAN-AC:1 + network_instance_name = 'default' - if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) + ''' + # if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) + if_subif_name = '{:s}'.format(endpoint_name[5:]) json_config_rules = [ - # Configure Interface (not used) - #json_config_rule_set( + # # Configure Interface (not used) + # json_config_rule_set( # '/interface[{:s}]'.format(endpoint_name), { # 'name': endpoint_name, # 'description': network_interface_desc, # 'mtu': mtu, - #}), + # }), #Create network instance json_config_rule_set( @@ -74,8 +78,10 @@ def setup_config_rules( json_config_rule_set( '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { 'name': network_instance_name, - 'protocol_name': 'BGP', + # 'protocol_name': 'BGP', + 'protocol_name': bgp_as, 'identifier': 'BGP', + # 'identifier': bgp_as, 'as': bgp_as, 'router_id': router_id, }), @@ -101,7 +107,8 @@ def setup_config_rules( json_config_rule_set( '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { 'name' : if_subif_name, - 'type' :'l3ipvlan', + # 'type' :'l3ipvlan', + 'type' :'ethernetCsmacd', 'mtu' : mtu, 'index' : sub_interface_index, 'description' : network_subinterface_desc, @@ -183,6 +190,40 @@ def setup_config_rules( }), ] + ''' + if_subif_name = '{:s}'.format(endpoint_name[5:]) + + json_config_rules = [ + + #Add DIRECTLY CONNECTED protocol to network instance + json_config_rule_set( + '/network_instance[{:s}]/protocols[DIRECTLY_CONNECTED]'.format(network_instance_name), { + 'name': network_instance_name, + 'identifier': 'DIRECTLY_CONNECTED', + 'protocol_name': 'DIRECTLY_CONNECTED', + }), + + # Add BGP neighbors + json_config_rule_set( + '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { + 'name': network_instance_name, + 'protocol_name': bgp_as, + 'identifier': 'BGP', + 'as': bgp_as, + 'router_id': router_id, + 'neighbors': [{'ip_address': neighbor_address_ip, 'remote_as': bgp_as}] + }), + json_config_rule_set( + '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format(network_instance_name), { + 'name' : network_instance_name, + 'src_protocol' : 'DIRECTLY_CONNECTED', + 'dst_protocol' : 'BGP', + 'address_family' : 'IPV4', + 'default_import_policy': 'ACCEPT_ROUTE', + }), + + ] + for res_key, res_value in endpoint_acls: json_config_rules.append( {'action': 1, 'acl': res_value} @@ -201,7 +242,8 @@ def teardown_config_rules( json_endpoint_settings : Dict = endpoint_settings.value service_short_uuid = service_uuid.split('-')[-1] - network_instance_name = '{:s}-NetInst'.format(service_short_uuid) + # network_instance_name = '{:s}-NetInst'.format(service_short_uuid) + network_instance_name = json_endpoint_settings.get('ni_name', service_short_uuid) #ELAN-AC:1 #network_interface_desc = '{:s}-NetIf'.format(service_uuid) #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) @@ -262,10 +304,10 @@ def teardown_config_rules( #Delete interface; automatically deletes: # - /interface[]/subinterface[] - json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name), - { - 'name': if_subif_name, - }), + # json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name), + # { + # 'name': if_subif_name, + # }), #Delete network instance; automatically deletes: # - /network_instance[]/interface[] -- GitLab From 85ba5e458329734fe377eb7110151eccf9d4d966 Mon Sep 17 00:00:00 2001 From: hajipour Date: Tue, 27 Feb 2024 08:23:26 +0000 Subject: [PATCH 07/29] bgp configuration with VRF support added --- .../templates/VPN/Interfaces_multivendor.py | 3 +- .../VPN/Network_instance_multivendor.py | 73 +++++++++++-------- .../templates/VPN/Routing_policy.py | 13 ++-- .../rest_server/nbi_plugins/etsi_bwm/Tools.py | 29 ++++---- .../l3nm_openconfig/ConfigRules.py | 65 ++++++----------- 5 files changed, 91 insertions(+), 92 deletions(-) diff --git a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py index d6f72ee65..12411bd8a 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py @@ -54,7 +54,8 @@ def create_If_SubIf(data,vendor, DEL): with tag('enabled'):text('true') with tag('subinterfaces'): with tag('subinterface'): - if vendor == 'ADVA': + # if vendor == 'ADVA': + if True: with tag('index'): text('0') with tag('config'): with tag('index'): text('0') diff --git a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py index e36955a0d..a8fc97cf9 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py @@ -64,10 +64,14 @@ def create_NI(parameters,vendor,DEL): elif "L3VRF" in parameters['type']: with tag('config'): with tag('name'):text(parameters['name']) - if vendor == "ADVA": + if "router_id" in parameters: + with tag('router-id'):text(parameters['router_id']) + # if vendor == "ADVA": + if True: with tag('type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"'):text('oc-ni-types:',parameters['type']) with tag('route-distinguisher'):text(parameters['route_distinguisher']) - if vendor == "ADVA": + # if vendor == "ADVA": + if True: with tag('encapsulation'): with tag('config'): with tag('encapsulation-type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"') :text('oc-ni-types:MPLS') @@ -116,9 +120,6 @@ 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']) @@ -129,36 +130,25 @@ def add_protocol_NI(parameters,vendor, DEL): with tag('enabled'): text('true') if "BGP" in parameters['identifier']: with tag('bgp'): + with tag('name'): text(parameters['as']) 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']) - 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 "router_id" in parameters: + with tag('router-id'):text(parameters['router_id']) 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') + for neighbor in parameters['neighbors']: + with tag('neighbor'): + with tag('neighbor-address'): text(neighbor['ip_address']) + with tag('afi-safis'): + with tag('afi-safi', 'xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types"'): + with tag('afi-safi-name'): text('oc-bgp-types:IPV4_UNICAST') + with tag('enabled'): text('true') + with tag('config'): + with tag('neighbor-address'): text(neighbor['ip_address']) + with tag('enabled'): text('true') + with tag('peer-as'): text(parameters['as']) # if vendor == "ADVA": if True: with tag('tables'): @@ -207,6 +197,9 @@ def associate_If_to_NI(parameters, 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:L3VRF') with tag('interfaces'): with tag('interface'): with tag('id'):text(parameters['id']) @@ -214,6 +207,25 @@ def associate_If_to_NI(parameters, DEL): with tag('id') :text(parameters['id']) with tag('interface') :text(parameters['interface']) with tag('subinterface'):text(parameters['subinterface']) + with tag('interfaces', 'xmlns="http://openconfig.net/yang/interfaces"'): + with tag('interface'): + with tag('name'):text(parameters['interface']) + with tag('config'): + with tag('name'):text(parameters['interface']) + with tag('subinterfaces'): + with tag('subinterface'): + with tag('index'): text(parameters['subinterface']) + with tag('config'): + with tag('index'): text(parameters['subinterface']) + with tag('ipv4', 'xmlns="http://openconfig.net/yang/interfaces/ip"'): + with tag('config'): + with tag('mtu'): text('1500') + with tag('addresses'): + with tag('address'): + with tag('ip'):text(parameters['address_ip']) + with tag('config'): + with tag('ip'):text(parameters['address_ip']) + with tag('prefix-length'):text(parameters['address_prefix']) result = indent( doc.getvalue(), @@ -356,6 +368,7 @@ def create_table_conns(parameters,DEL): with tag('src-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'): text('oc-pol-types:',parameters['src_protocol']) with tag('dst-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'): text('oc-pol-types:',parameters['dst_protocol']) with tag('address-family', 'xmlns:oc-types="http://openconfig.net/yang/openconfig-types"'):text('oc-types:',parameters['address_family']) + with tag('dst-instance', 'xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-oc-ni-augments"'):text('65000') if len(parameters['default_import_policy']) != 0: with tag('default-import-policy'):text(parameters['default_import_policy']) result = indent( diff --git a/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py b/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py index 54e6c1c01..e1287f9f8 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py @@ -40,6 +40,7 @@ def create_rp_statement(data, DEL): RP_statement_name = data['statement_name'] RP_policy_result = data['policy_result'] RP_ext_comm_set_name = data['ext_community_set_name'] + RP_sequence_id = data['sequence_id'] with tag('routing-policy', xmlns="http://openconfig.net/yang/routing-policy"): @@ -55,9 +56,9 @@ def create_rp_statement(data, DEL): with tag('name'):text(RP_policy_name) with tag('statements'): with tag('statement'): - with tag('name'):text(RP_statement_name) + with tag('name'):text(RP_sequence_id) with tag('config'): - with tag('name'):text(RP_statement_name) + with tag('name'):text(RP_sequence_id) with tag('conditions'): with tag('config'): with tag('install-protocol-eq', **{'xmlns:openconfig-policy-types': 'http://openconfig.net/yang/policy-types'}):text('openconfig-policy-types:DIRECTLY_CONNECTED') @@ -133,14 +134,14 @@ data_2 = {'ext_community_member' : '65001:101', 'ext_community_set_name' : 'set_srv_101_a'} print('\nRouting Policy Statement - CREATE\n') -print(rp_statement(data_1, False)) +print(create_rp_statement(data_1, False)) print('\nRouting Policy Statement - DELETE\n') -print(rp_statement(data_1, True)) +print(create_rp_statement(data_1, True)) print('\nRouting Policy Defined Set - CREATE\n') -print(rp_defined_set(data_2, False)) +print(create_rp_def(data_2, False)) print('\nRouting Policy Defined Set - DELETE\n') -print(rp_defined_set(data_2, True)) +print(create_rp_def(data_2, True)) ''' ''' diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index 3c5d4b5e6..4b7ee7b39 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -38,8 +38,9 @@ ALLOCATION_DIRECTION_DESCRIPTIONS = { 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) +POLICY_AZ = 'srv_{:d}_a'.format(VLAN_TAG) +POLICY_ZA = 'srv_{:d}_b'.format(VLAN_TAG) +BGP_NETWORK_CIDR = '192.168.150.0/24' def service_2_bwInfo(service: Service) -> dict: response = {} @@ -102,7 +103,6 @@ def bwInfo_2_service(client, bw_info: dict) -> Service: devices = client.ListDevices(Empty()).devices router_id_counter = 1 for device in devices: - 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': @@ -118,41 +118,42 @@ def bwInfo_2_service(client, bw_info: dict) -> Service: 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), + 'self_bgp_interface_name': ('xe5', True), + 'self_bgp_interface_address_ip': ('192.168.150.1', True), + 'self_bgp_interface_address_prefix': (PREFIX_LENGTH, True), + 'self_bgp_sub_interface_index': (0, 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), + '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), + 'self_bgp_interface_name': ('xe5', True), + 'self_bgp_interface_address_ip': ('192.168.150.2', True), + 'self_bgp_interface_address_prefix': (PREFIX_LENGTH, True), + 'self_bgp_sub_interface_index': (0, 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), + 'policy_AZ' : (POLICY_ZA, True), + 'policy_ZA' : (POLICY_AZ, True), 'address_prefix' : (PREFIX_LENGTH, True), } router_id_counter += 1 diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 0369d6207..2f518d56a 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -47,11 +47,14 @@ def setup_config_rules( network_subinterface_desc = json_endpoint_settings.get('subif_description','') #service_short_uuid = service_uuid.split('-')[-1] #network_instance_name = '{:s}-NetInst'.format(service_short_uuid) - # network_instance_name = json_endpoint_settings.get('ni_name', service_uuid.split('-')[-1]) #ELAN-AC:1 - network_instance_name = 'default' + network_instance_name = json_endpoint_settings.get('ni_name', service_uuid.split('-')[-1]) #ELAN-AC:1 - ''' - # if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) + bgp_if_name = json_endpoint_settings.get('self_bgp_interface_name','') + bgp_address_ip = json_endpoint_settings.get('self_bgp_interface_address_ip','') + bgp_address_prefix = json_endpoint_settings.get('self_bgp_interface_address_prefix','') + bgp_sub_interface_index = json_endpoint_settings.get('self_bgp_sub_interface_index', 0 ) + + # if_subif_name = '{:s}.{:d}'.format(endpoint_name, 0) if_subif_name = '{:s}'.format(endpoint_name[5:]) json_config_rules = [ @@ -70,7 +73,7 @@ def setup_config_rules( 'description': network_interface_desc, 'type': 'L3VRF', 'route_distinguisher': route_distinguisher, - #'router_id': router_id, + 'router_id': router_id, #'address_families': address_families, }), @@ -78,12 +81,12 @@ def setup_config_rules( json_config_rule_set( '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { 'name': network_instance_name, - # 'protocol_name': 'BGP', 'protocol_name': bgp_as, 'identifier': 'BGP', - # 'identifier': bgp_as, + 'type': 'L3VRF', 'as': bgp_as, 'router_id': router_id, + 'neighbors': [{'ip_address': neighbor_address_ip, 'remote_as': bgp_as}] }), #Add DIRECTLY CONNECTED protocol to network instance @@ -107,7 +110,6 @@ def setup_config_rules( json_config_rule_set( '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { 'name' : if_subif_name, - # 'type' :'l3ipvlan', 'type' :'ethernetCsmacd', 'mtu' : mtu, 'index' : sub_interface_index, @@ -124,6 +126,18 @@ def setup_config_rules( 'id' : if_subif_name, 'interface' : if_subif_name, 'subinterface': sub_interface_index, + 'address_ip' : address_ip, + 'address_prefix': address_prefix, + }), + + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, bgp_if_name), { + 'name' : network_instance_name, + 'id' : bgp_if_name, + 'interface' : bgp_if_name, + 'subinterface': bgp_sub_interface_index, + 'address_ip' : bgp_address_ip, + 'address_prefix': bgp_address_prefix, }), #Create routing policy @@ -139,6 +153,7 @@ def setup_config_rules( 'statement_name' : 'stm_{:s}'.format(policy_import), 'ext_community_set_name': 'set_{:s}'.format(policy_import), 'policy_result' : 'ACCEPT_ROUTE', + 'sequence_id' : '10' }), #Associate routing policy to network instance @@ -161,6 +176,7 @@ def setup_config_rules( 'statement_name' : 'stm_{:s}'.format(policy_export), 'ext_community_set_name': 'set_{:s}'.format(policy_export), 'policy_result' : 'ACCEPT_ROUTE', + 'sequence_id' : '10' }), #Associate routing policy to network instance @@ -189,39 +205,6 @@ def setup_config_rules( 'default_import_policy': 'ACCEPT_ROUTE', }), - ] - ''' - if_subif_name = '{:s}'.format(endpoint_name[5:]) - - json_config_rules = [ - - #Add DIRECTLY CONNECTED protocol to network instance - json_config_rule_set( - '/network_instance[{:s}]/protocols[DIRECTLY_CONNECTED]'.format(network_instance_name), { - 'name': network_instance_name, - 'identifier': 'DIRECTLY_CONNECTED', - 'protocol_name': 'DIRECTLY_CONNECTED', - }), - - # Add BGP neighbors - json_config_rule_set( - '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { - 'name': network_instance_name, - 'protocol_name': bgp_as, - 'identifier': 'BGP', - 'as': bgp_as, - 'router_id': router_id, - 'neighbors': [{'ip_address': neighbor_address_ip, 'remote_as': bgp_as}] - }), - json_config_rule_set( - '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format(network_instance_name), { - 'name' : network_instance_name, - 'src_protocol' : 'DIRECTLY_CONNECTED', - 'dst_protocol' : 'BGP', - 'address_family' : 'IPV4', - 'default_import_policy': 'ACCEPT_ROUTE', - }), - ] for res_key, res_value in endpoint_acls: -- GitLab From 8f65918fa23fbe19796917affff3f18bec4c62ff Mon Sep 17 00:00:00 2001 From: hajipour Date: Wed, 28 Feb 2024 12:29:12 +0000 Subject: [PATCH 08/29] service creation and deletion with webui added to pyangbind mode and tested --- .../drivers/openconfig/OpenConfigDriver.py | 3 + .../VPN/Network_instance_multivendor.py | 2 +- .../rest_server/nbi_plugins/etsi_bwm/Tools.py | 88 ++++++------ .../l3nm_openconfig/ConfigRules.py | 132 ++++++++++-------- .../L3NMOpenConfigServiceHandler.py | 6 +- 5 files changed, 131 insertions(+), 100 deletions(-) diff --git a/src/device/service/drivers/openconfig/OpenConfigDriver.py b/src/device/service/drivers/openconfig/OpenConfigDriver.py index 99ae1c8db..452f2f7c8 100644 --- a/src/device/service/drivers/openconfig/OpenConfigDriver.py +++ b/src/device/service/drivers/openconfig/OpenConfigDriver.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import time import json import anytree, copy, logging, pytz, queue, re, threading #import lxml.etree as ET @@ -240,6 +241,8 @@ def edit_config( test_option=test_option, error_option=error_option, format=format) if commit_per_rule: netconf_handler.commit() # configuration commit + if 'table_connections' in resource_key: + time.sleep(5) # CPU usage might exceed critical level after route redistribution, BGP daemon needs time to reload #results[i] = True results.append(True) diff --git a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py index a8fc97cf9..13612b607 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py @@ -357,7 +357,7 @@ def create_table_conns(parameters,DEL): with tag('table-connection','xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"'): with tag('src-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'): text('oc-pol-types:',parameters['src_protocol']) with tag('dst-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'): text('oc-pol-types:',parameters['dst_protocol']) - with tag('address-family', 'xmlns:oc-types="http://openconfig.net/yang/openconfig-types"'):text('oc-types:',parameters['dst_protocol']) + with tag('address-family', 'xmlns:oc-types="http://openconfig.net/yang/openconfig-types"'):text('oc-types:',parameters['address_family']) else: with tag('table-connections'): with tag('table-connection'): diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index 4b7ee7b39..f32fe5699 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -29,6 +29,7 @@ from common.tools.object_factory.Service import json_service_id LOGGER = logging.getLogger(__name__) ENDPOINT_SETTINGS_KEY = '/device[{:s}]/endpoint[{:s}]/vlan[{:d}]/settings' +DEVICE_SETTINGS_KEY = '/device[{:s}]/settings' RE_CONFIG_RULE_IF_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$') MEC_CONSIDERED_FIELDS = ['requestType', 'sessionFilter', 'fixedAllocation', 'allocationDirection'] ALLOCATION_DIRECTION_DESCRIPTIONS = { @@ -40,7 +41,11 @@ PREFIX_LENGTH = 24 BGP_AS = 65000 POLICY_AZ = 'srv_{:d}_a'.format(VLAN_TAG) POLICY_ZA = 'srv_{:d}_b'.format(VLAN_TAG) -BGP_NETWORK_CIDR = '192.168.150.0/24' +BGP_NEIGHBOR_IP_A = '192.168.150.1' +BGP_NEIGHBOR_IP_Z = '192.168.150.2' +ROUTER_ID_A = '200.1.1.1' +ROUTER_ID_Z = '200.1.1.2' +ROUTE_DISTINGUISHER = '{:5d}:{:03d}'.format(BGP_AS, VLAN_TAG) def service_2_bwInfo(service: Service) -> dict: response = {} @@ -80,10 +85,6 @@ def bwInfo_2_service(client, bw_info: dict) -> Service: 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} @@ -101,9 +102,10 @@ def bwInfo_2_service(client, bw_info: dict) -> Service: z_ip = bw_info['sessionFilter']['dstAddress'] devices = client.ListDevices(Empty()).devices - router_id_counter = 1 + ip_interface_name_dict = {} for device in devices: device_endpoint_uuids = {ep.name:ep.endpoint_id.endpoint_uuid.uuid for ep in device.device_endpoints} + skip_device = True for cr in device.device_config.config_rules: if cr.WhichOneof('config_rule') != 'custom': continue @@ -111,55 +113,59 @@ def bwInfo_2_service(client, bw_info: dict) -> Service: if not match_subif: continue address_ip = json.loads(cr.custom.resource_value).get('address_ip') + short_port_name = match_subif.groups(0)[0] + ip_interface_name_dict[address_ip] = short_port_name if address_ip not in [a_ip, z_ip]: continue - port_name = 'PORT-' + match_subif.groups(0)[0] # `PORT-` added as prefix + port_name = 'PORT-' + short_port_name # `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 = { + if address_ip in a_ip: + router_id = ROUTER_ID_A + policy_az = POLICY_AZ + policy_za = POLICY_ZA + neighbor_bgp_interface_address_ip = BGP_NEIGHBOR_IP_Z + self_bgp_interface_address_ip = BGP_NEIGHBOR_IP_A + else: + router_id = ROUTER_ID_Z + policy_az = POLICY_ZA + policy_za = POLICY_AZ + neighbor_bgp_interface_address_ip= BGP_NEIGHBOR_IP_A + self_bgp_interface_address_ip = BGP_NEIGHBOR_IP_Z + endpoint_field_updates = { 'address_ip': (address_ip, True), - 'router_id': ('200.1.1.1', True), - 'neighbor_address_ip': ('192.168.150.2', True), - 'self_bgp_interface_name': ('xe5', True), - 'self_bgp_interface_address_ip': ('192.168.150.1', True), - 'self_bgp_interface_address_prefix': (PREFIX_LENGTH, True), - 'self_bgp_sub_interface_index': (0, True), - 'route_distinguisher': (route_distinguisher, True), - 'sub_interface_index': (0, 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': ('200.1.1.2', True), - 'neighbor_address_ip': ('192.168.150.1', True), - 'self_bgp_interface_name': ('xe5', True), - 'self_bgp_interface_address_ip': ('192.168.150.2', True), - 'self_bgp_interface_address_prefix': (PREFIX_LENGTH, True), - 'self_bgp_sub_interface_index': (0, True), - 'route_distinguisher': (route_distinguisher, True), 'sub_interface_index': (0, 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) + update_config_rule_custom(service_config_rules, endpoint_settings_key, endpoint_field_updates) LOGGER.debug(f'AFTER UPDATE -> device.device_config.config_rules: {service_config_rules}') + skip_device = False + if skip_device: + continue + device_field_updates = { + 'bgp_as':(BGP_AS, True), + 'route_distinguisher': (ROUTE_DISTINGUISHER, True), + 'router_id': (router_id, True), + 'policy_AZ': (policy_az, True), + 'policy_ZA': (policy_za, True), + 'neighbor_bgp_interface_address_ip': (neighbor_bgp_interface_address_ip, True), + 'self_bgp_interface_name': (ip_interface_name_dict[self_bgp_interface_address_ip], True), + 'self_bgp_interface_address_ip': (self_bgp_interface_address_ip, True), + 'bgp_interface_address_prefix': (PREFIX_LENGTH, True) + } + device_settings_key = DEVICE_SETTINGS_KEY.format(device.name) + LOGGER.debug(f'BEFORE UPDATE -> device.device_config.config_rules: {service_config_rules}') + update_config_rule_custom(service_config_rules, device_settings_key, device_field_updates) + LOGGER.debug(f'AFTER UPDATE -> device.device_config.config_rules: {service_config_rules}') + + settings_cr_key = '/settings' + settings_cr_value = {} + update_config_rule_custom(service_config_rules, settings_cr_key, settings_cr_value) service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 2f518d56a..cee44641a 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -18,29 +18,30 @@ from service.service.service_handler_api.AnyTreeTools import TreeNode def setup_config_rules( service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, - service_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple] + service_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple], device_settings: TreeNode ) -> List[Dict]: if service_settings is None: return [] if endpoint_settings is None: return [] + if device_settings is None: return [] json_settings : Dict = service_settings.value json_endpoint_settings : Dict = endpoint_settings.value + json_device_settings : Dict = device_settings.value mtu = json_settings.get('mtu', 1450 ) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - bgp_as = json_settings.get('bgp_as', 65000 ) # 65000 + bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 - router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' - route_distinguisher = json_settings.get('route_distinguisher', '65000:101' ) # '60001:801' + router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + route_distinguisher = json_device_settings.get('route_distinguisher', '65000:101' ) # '60001:801' sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 - neighbor_address_ip = json_endpoint_settings.get('neighbor_address_ip', '0.0.0.0') # '2.2.2.1' - policy_import = json_endpoint_settings.get('policy_AZ', '2' ) # 2 - policy_export = json_endpoint_settings.get('policy_ZA', '7' ) # 30 + policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 + policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 #network_interface_desc = '{:s}-NetIf'.format(service_uuid) network_interface_desc = json_endpoint_settings.get('ni_description','') #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) @@ -49,10 +50,11 @@ def setup_config_rules( #network_instance_name = '{:s}-NetInst'.format(service_short_uuid) network_instance_name = json_endpoint_settings.get('ni_name', service_uuid.split('-')[-1]) #ELAN-AC:1 - bgp_if_name = json_endpoint_settings.get('self_bgp_interface_name','') - bgp_address_ip = json_endpoint_settings.get('self_bgp_interface_address_ip','') - bgp_address_prefix = json_endpoint_settings.get('self_bgp_interface_address_prefix','') - bgp_sub_interface_index = json_endpoint_settings.get('self_bgp_sub_interface_index', 0 ) + self_bgp_if_name = json_device_settings.get('self_bgp_interface_name', '') + self_bgp_address_ip = json_device_settings.get('self_bgp_interface_address_ip', '') + bgp_address_prefix = json_device_settings.get('bgp_interface_address_prefix', '') + bgp_sub_interface_index = json_device_settings.get('self_bgp_sub_interface_index', 0) + neighbor_bgp_if_address_ip= json_device_settings.get('neighbor_bgp_interface_address_ip', '0.0.0.0') # '2.2.2.1' # if_subif_name = '{:s}.{:d}'.format(endpoint_name, 0) if_subif_name = '{:s}'.format(endpoint_name[5:]) @@ -86,7 +88,7 @@ def setup_config_rules( 'type': 'L3VRF', 'as': bgp_as, 'router_id': router_id, - 'neighbors': [{'ip_address': neighbor_address_ip, 'remote_as': bgp_as}] + 'neighbors': [{'ip_address': neighbor_bgp_if_address_ip, 'remote_as': bgp_as}] }), #Add DIRECTLY CONNECTED protocol to network instance @@ -96,7 +98,6 @@ def setup_config_rules( 'identifier': 'DIRECTLY_CONNECTED', 'protocol_name': 'DIRECTLY_CONNECTED', }), - #Add STATIC protocol to network instance json_config_rule_set( @@ -131,12 +132,12 @@ def setup_config_rules( }), json_config_rule_set( - '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, bgp_if_name), { + '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, self_bgp_if_name), { 'name' : network_instance_name, - 'id' : bgp_if_name, - 'interface' : bgp_if_name, + 'id' : self_bgp_if_name, + 'interface' : self_bgp_if_name, 'subinterface': bgp_sub_interface_index, - 'address_ip' : bgp_address_ip, + 'address_ip' : self_bgp_address_ip, 'address_prefix': bgp_address_prefix, }), @@ -215,76 +216,75 @@ def setup_config_rules( def teardown_config_rules( service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, - service_settings : TreeNode, endpoint_settings : TreeNode + service_settings : TreeNode, endpoint_settings : TreeNode, device_settings: TreeNode ) -> List[Dict]: if service_settings is None: return [] if endpoint_settings is None: return [] + if device_settings is None: return [] json_settings : Dict = service_settings.value json_endpoint_settings : Dict = endpoint_settings.value + json_device_settings : Dict = device_settings.value service_short_uuid = service_uuid.split('-')[-1] # network_instance_name = '{:s}-NetInst'.format(service_short_uuid) network_instance_name = json_endpoint_settings.get('ni_name', service_short_uuid) #ELAN-AC:1 #network_interface_desc = '{:s}-NetIf'.format(service_uuid) - #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) + # network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) + network_subinterface_desc = '' - #mtu = json_settings.get('mtu', 1450 ) # 1512 + mtu = json_settings.get('mtu', 1450 ) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - #bgp_as = json_settings.get('bgp_as', 65000 ) # 65000 - route_distinguisher = json_settings.get('route_distinguisher', '0:0' ) # '60001:801' - #sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 - #router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' - vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 - #address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' - #address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 - policy_import = json_endpoint_settings.get('policy_AZ', '2' ) # 2 - policy_export = json_endpoint_settings.get('policy_ZA', '7' ) # 30 - - if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) + bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 + route_distinguisher = json_device_settings.get('route_distinguisher', '0:0' ) # '60001:801' + sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 + router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 + address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' + address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 + policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 + policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 - json_config_rules = [ - #Delete table connections - json_config_rule_delete( - '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format(network_instance_name),{ - 'name' : network_instance_name, - 'src_protocol' : 'DIRECTLY_CONNECTED', - 'dst_protocol' : 'BGP', - 'address_family': 'IPV4', - }), + self_bgp_if_name = json_device_settings.get('self_bgp_interface_name', '') + self_bgp_address_ip = json_device_settings.get('self_bgp_interface_address_ip', '') + bgp_address_prefix = json_device_settings.get('bgp_interface_address_prefix', '') + bgp_sub_interface_index = json_device_settings.get('self_bgp_sub_interface_index', 0) - - json_config_rule_delete( - '/network_instance[{:s}]/table_connections[STATIC][BGP][IPV4]'.format(network_instance_name), { - 'name' : network_instance_name, - 'src_protocol' : 'STATIC', - 'dst_protocol' : 'BGP', - 'address_family': 'IPV4', - }), + # if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) + if_subif_name = '{:s}'.format(endpoint_name[5:]) + json_config_rules = [ #Delete export routing policy - json_config_rule_delete( - '/routing_policy/policy_definition[{:s}_export]'.format(network_instance_name), { - 'policy_name': '{:s}_export'.format(network_instance_name), + # pylint: disable=duplicate-string-formatting-argument + '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { + 'policy_name' : policy_export, + 'statement_name' : 'stm_{:s}'.format(policy_export), + 'ext_community_set_name': 'set_{:s}'.format(policy_export), + 'policy_result' : 'ACCEPT_ROUTE', + 'sequence_id' : '10' }), json_config_rule_delete( '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]'.format(policy_export, route_distinguisher), { 'ext_community_set_name': 'set_{:s}'.format(policy_export), + 'ext_community_member' : route_distinguisher, }), - #Delete import routing policy - json_config_rule_delete( - '/routing_policy/policy_definition[{:s}_import]'.format(network_instance_name), { - 'policy_name': '{:s}_import'.format(network_instance_name), + # pylint: disable=duplicate-string-formatting-argument + '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { + 'policy_name' : policy_import, + 'statement_name' : 'stm_{:s}'.format(policy_import), + 'ext_community_set_name': 'set_{:s}'.format(policy_import), + 'policy_result' : 'ACCEPT_ROUTE', + 'sequence_id' : '10' }), json_config_rule_delete( '/routing_policy/bgp_defined_set[{:s}_rt_import][{:s}]'.format(policy_import, route_distinguisher), { 'ext_community_set_name': 'set_{:s}'.format(policy_import), + 'ext_community_member' : route_distinguisher, }), - #Delete interface; automatically deletes: # - /interface[]/subinterface[] # json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name), @@ -296,6 +296,26 @@ def teardown_config_rules( # - /network_instance[]/interface[] # - /network_instance[]/protocols[] # - /network_instance[]/inter_instance_policies[] + + #Associate interface to network instance + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format('default', if_subif_name), { + 'name' : 'default', + 'id' : if_subif_name, + 'interface' : if_subif_name, + 'subinterface': sub_interface_index, + 'address_ip' : address_ip, + 'address_prefix': address_prefix, + }), + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format('default', self_bgp_if_name), { + 'name' : 'default', + 'id' : self_bgp_if_name, + 'interface' : self_bgp_if_name, + 'subinterface': bgp_sub_interface_index, + 'address_ip' : self_bgp_address_ip, + 'address_prefix': bgp_address_prefix, + }), json_config_rule_delete('/network_instance[{:s}]'.format(network_instance_name), { 'name': network_instance_name diff --git a/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py b/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py index 3f8a6d9dd..d061573db 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py +++ b/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py @@ -52,6 +52,7 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler): device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint) device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) + device_settings = self.__settings_handler.get_device_settings(device_obj) endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid) endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj) endpoint_acls = self.__settings_handler.get_endpoint_acls(device_obj, endpoint_obj) @@ -59,7 +60,7 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler): json_config_rules = setup_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name, - settings, endpoint_settings, endpoint_acls) + settings, endpoint_settings, endpoint_acls, device_settings) if len(json_config_rules) > 0: del device_obj.device_config.config_rules[:] @@ -90,13 +91,14 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler): device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint) device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) + device_settings = self.__settings_handler.get_device_settings(device_obj) endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid) endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj) endpoint_name = endpoint_obj.name json_config_rules = teardown_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name, - settings, endpoint_settings) + settings, endpoint_settings, device_settings) if len(json_config_rules) > 0: del device_obj.device_config.config_rules[:] -- GitLab From f6afa0c7cebe50e35ad3abe59b1dbe15e06c8294 Mon Sep 17 00:00:00 2001 From: hajipour Date: Wed, 28 Feb 2024 16:28:34 +0000 Subject: [PATCH 09/29] service creation and deletion with webui added to jinja mode --- .../drivers/openconfig/OpenConfigDriver.py | 5 +-- .../drivers/openconfig/templates/__init__.py | 2 +- .../interface/subinterface/edit_config.xml | 13 ------- .../network_instance/edit_config.xml | 2 +- .../interface/edit_config.xml | 34 +++++++++++++++++++ .../protocols/edit_config.xml | 22 ++++++++++++ .../table_connections/edit_config.xml | 1 + .../statement/edit_config.xml | 4 +-- .../l3nm_openconfig/ConfigRules.py | 2 ++ 9 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/device/service/drivers/openconfig/OpenConfigDriver.py b/src/device/service/drivers/openconfig/OpenConfigDriver.py index 452f2f7c8..476c2f0cc 100644 --- a/src/device/service/drivers/openconfig/OpenConfigDriver.py +++ b/src/device/service/drivers/openconfig/OpenConfigDriver.py @@ -227,11 +227,8 @@ 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='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) + 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( diff --git a/src/device/service/drivers/openconfig/templates/__init__.py b/src/device/service/drivers/openconfig/templates/__init__.py index 87eea1f0b..b1d8de511 100644 --- a/src/device/service/drivers/openconfig/templates/__init__.py +++ b/src/device/service/drivers/openconfig/templates/__init__.py @@ -121,7 +121,7 @@ def compose_config( # template generation templates.append(JINJA_ENV.get_template('acl/acl-set/acl-entry/edit_config.xml')) templates.append(JINJA_ENV.get_template('acl/interfaces/ingress/edit_config.xml')) data : Dict[str, Any] = json.loads(resource_value) - operation = 'delete' if delete else 'merge' + operation = 'delete' if delete else '' return [ '{:s}'.format( diff --git a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml index e44100400..9cff1afd3 100644 --- a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml @@ -30,19 +30,6 @@ {% endif %} - {% if address_ip is defined %} - - - - {{address_ip}} - - {{address_ip}} - {{address_prefix}} - - - - - {% endif %} {% endif %} diff --git a/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml index 6b6b733da..891881867 100644 --- a/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml @@ -1,5 +1,5 @@ - + {{name}} {% if operation is not defined or operation != 'delete' %} diff --git a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml index 855f321b4..96e13cc37 100644 --- a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml @@ -1,6 +1,10 @@ {{name}} + + {{name}} + oc-ni-types:L3VRF + {{id}} @@ -13,3 +17,33 @@ + + + {{interface}} + + {{interface}} + + + + {{subinterface}} + + {{subinterface}} + + + + 1500 + + +
+ {{address_ip}} + + {{address_ip}} + {{address_prefix}} + +
+
+
+
+
+
+
diff --git a/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml index c9c068e48..da66d97f0 100644 --- a/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml @@ -9,15 +9,37 @@ oc-pol-types:{{identifier}} {{protocol_name}} + true {% if identifier=='BGP' %} + {{as}} {{as}} {{router_id}} + {% if neighbors is defined %} + + {% for neighbor in neighbors %} + + {{neighbor['ip_address']}} + + + oc-bgp-types:IPV4_UNICAST + true + + + + {{neighbor['ip_address']}} + true + {{as}} + + + {% endfor %} + + {% endif %} {% endif %} {% endif %} diff --git a/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml index 46bf5e387..bd1dac1b3 100644 --- a/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml @@ -11,6 +11,7 @@ oc-pol-types:{{src_protocol}} oc-pol-types:{{dst_protocol}} oc-types:{{address_family}} + {{as}} {% if default_import_policy is defined %}{{default_import_policy}}{% endif %}
{% endif %} diff --git a/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml b/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml index eda2d99c9..1bf1cf322 100644 --- a/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml @@ -8,9 +8,9 @@ - {{statement_name}} + {{sequence_id}} - {{statement_name}} + {{sequence_id}} diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index cee44641a..87556c36b 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -195,6 +195,7 @@ def setup_config_rules( 'dst_protocol' : 'BGP', 'address_family' : 'IPV4', 'default_import_policy': 'ACCEPT_ROUTE', + 'as' : bgp_as, }), json_config_rule_set( @@ -204,6 +205,7 @@ def setup_config_rules( 'dst_protocol' : 'BGP', 'address_family' : 'IPV4', 'default_import_policy': 'ACCEPT_ROUTE', + 'as' : bgp_as, }), ] -- GitLab From 5f64f0ea74e6a69b63b177a2fd2adceca33f030a Mon Sep 17 00:00:00 2001 From: hajipour Date: Thu, 29 Feb 2024 21:38:18 +0000 Subject: [PATCH 10/29] service_2_bwInfo function bug resolved: change in config rules applied in the function --- .../rest_server/nbi_plugins/etsi_bwm/Tools.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index f32fe5699..c39a380dc 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -31,7 +31,7 @@ LOGGER = logging.getLogger(__name__) ENDPOINT_SETTINGS_KEY = '/device[{:s}]/endpoint[{:s}]/vlan[{:d}]/settings' DEVICE_SETTINGS_KEY = '/device[{:s}]/settings' RE_CONFIG_RULE_IF_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$') -MEC_CONSIDERED_FIELDS = ['requestType', 'sessionFilter', 'fixedAllocation', 'allocationDirection'] +MEC_CONSIDERED_FIELDS = ['requestType', 'sessionFilter', 'fixedAllocation', 'allocationDirection', 'fixedBWPriority'] ALLOCATION_DIRECTION_DESCRIPTIONS = { '00' : 'Downlink (towards the UE)', '01' : 'Uplink (towards the application/session)', @@ -59,12 +59,19 @@ def service_2_bwInfo(service: Service) -> dict: break for config_rule in service.service_config.config_rules: + resource_value_json = json.loads(config_rule.custom.resource_value) + if config_rule.custom.resource_key != '/request': + continue for key in ['allocationDirection', 'fixedBWPriority', 'requestType', 'sourceIp', 'sourcePort', 'dstPort', 'protocol', 'sessionFilter']: - if config_rule.custom.resource_key == key: - if key != 'sessionFilter': - response[key] = config_rule.custom.resource_value - else: - response[key] = json.loads(config_rule.custom.resource_value) + if key not in resource_value_json: + continue + + if key == 'sessionFilter': + response[key] = [resource_value_json[key]] + elif key == 'requestType': + response[key] = str(resource_value_json[key]) + else: + response[key] = resource_value_json[key] unixtime = time.time() response['timeStamp'] = { # Time stamp to indicate when the corresponding information elements are sent @@ -76,8 +83,6 @@ def service_2_bwInfo(service: Service) -> dict: 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 -- GitLab From 4580bbff8b079ccb088de2c0e2fe695414ca725c Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 09:41:32 +0000 Subject: [PATCH 11/29] Device component - OpenConfig driver: - Fixes in per-vendor specificities - Renamed sequence_id to statement_name --- .../openconfig/templates/VPN/Interfaces_multivendor.py | 3 +-- .../templates/VPN/Network_instance_multivendor.py | 9 +++------ .../drivers/openconfig/templates/VPN/Routing_policy.py | 5 ++--- .../policy_definition/statement/edit_config.xml | 4 ++-- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py index 453096e19..0efa2e8f2 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py @@ -54,8 +54,7 @@ def create_If_SubIf(data,vendor, DEL): with tag('enabled'):text('true') with tag('subinterfaces'): with tag('subinterface'): - # if vendor == 'ADVA': - if True: + if vendor is None or vendor == 'ADVA': with tag('index'): text('0') with tag('config'): with tag('index'): text('0') diff --git a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py index 8e6a9144e..1f7015694 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py @@ -66,12 +66,10 @@ def create_NI(parameters,vendor,DEL): with tag('name'):text(parameters['name']) if "router_id" in parameters: with tag('router-id'):text(parameters['router_id']) - # if vendor == "ADVA": - if True: + if vendor is None or vendor == 'ADVA': with tag('type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"'):text('oc-ni-types:',parameters['type']) with tag('route-distinguisher'):text(parameters['route_distinguisher']) - # if vendor == "ADVA": - if True: + if vendor is None or vendor == 'ADVA': with tag('encapsulation'): with tag('config'): with tag('encapsulation-type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"') :text('oc-ni-types:MPLS') @@ -149,8 +147,7 @@ def add_protocol_NI(parameters,vendor, DEL): with tag('neighbor-address'): text(neighbor['ip_address']) with tag('enabled'): text('true') with tag('peer-as'): text(parameters['as']) - # if vendor == "ADVA": - if True: + if vendor is None or vendor == 'ADVA': 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']) diff --git a/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py b/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py index b144eb5ba..69fdd2cc5 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py @@ -40,7 +40,6 @@ def create_rp_statement(data, DEL): RP_statement_name = data['statement_name'] RP_policy_result = data['policy_result'] RP_ext_comm_set_name = data['ext_community_set_name'] - RP_sequence_id = data['sequence_id'] with tag('routing-policy', xmlns="http://openconfig.net/yang/routing-policy"): @@ -56,9 +55,9 @@ def create_rp_statement(data, DEL): with tag('name'):text(RP_policy_name) with tag('statements'): with tag('statement'): - with tag('name'):text(RP_sequence_id) + with tag('name'):text(RP_statement_name) with tag('config'): - with tag('name'):text(RP_sequence_id) + with tag('name'):text(RP_statement_name) with tag('conditions'): with tag('config'): with tag('install-protocol-eq', **{'xmlns:openconfig-policy-types': 'http://openconfig.net/yang/policy-types'}):text('openconfig-policy-types:DIRECTLY_CONNECTED') diff --git a/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml b/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml index 1bf1cf322..eda2d99c9 100644 --- a/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/routing_policy/policy_definition/statement/edit_config.xml @@ -8,9 +8,9 @@ - {{sequence_id}} + {{statement_name}} - {{sequence_id}} + {{statement_name}} -- GitLab From db0c5aad39824e05b2e7deb212abc23d8da7acae Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 09:53:33 +0000 Subject: [PATCH 12/29] Device component - OpenConfig driver: - Fixes in per-vendor specificities - Cosmetic improvements --- src/device/service/drivers/openconfig/templates/Tools.py | 4 ++-- src/device/service/drivers/openconfig/templates/__init__.py | 3 ++- .../openconfig/templates/network_instance/edit_config.xml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/device/service/drivers/openconfig/templates/Tools.py b/src/device/service/drivers/openconfig/templates/Tools.py index d49d66c7a..c4ef22b1e 100644 --- a/src/device/service/drivers/openconfig/templates/Tools.py +++ b/src/device/service/drivers/openconfig/templates/Tools.py @@ -61,8 +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: - result_templates.append(add_protocol_NI(data, vendor, delete)) - # if vendor == "ADVA": result_templates.append(add_protocol_NI(data, vendor, delete)) + if vendor is None or 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: diff --git a/src/device/service/drivers/openconfig/templates/__init__.py b/src/device/service/drivers/openconfig/templates/__init__.py index 5c5424d28..969ca9f60 100644 --- a/src/device/service/drivers/openconfig/templates/__init__.py +++ b/src/device/service/drivers/openconfig/templates/__init__.py @@ -121,7 +121,8 @@ def compose_config( # template generation templates.append(JINJA_ENV.get_template('acl/acl-set/acl-entry/edit_config.xml')) templates.append(JINJA_ENV.get_template('acl/interfaces/ingress/edit_config.xml')) data : Dict[str, Any] = json.loads(resource_value) - operation = 'delete' if delete else '' + operation = 'delete' if delete else 'merge' # others + #operation = 'delete' if delete else '' # ipinfusion? return [ '{:s}'.format( diff --git a/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml index 891881867..6b6b733da 100644 --- a/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/network_instance/edit_config.xml @@ -1,5 +1,5 @@ - + {{name}} {% if operation is not defined or operation != 'delete' %} -- GitLab From 137f5bedff9523f436bb0946da09e0c80a58cad4 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 10:30:09 +0000 Subject: [PATCH 13/29] Device component - OpenConfig driver: - Recovered removed blocks - Adapted IP address assignment to interfaces being part of a network instance --- .../interface/subinterface/edit_config.xml | 16 ++++++++++ .../interface/edit_config.xml | 32 +------------------ 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml index 9cff1afd3..eb7f49d76 100644 --- a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml @@ -30,6 +30,22 @@ {% endif %} + {% if address_ip is defined %} + + + 1500 + + + + {{address_ip}} + + {{address_ip}} + {{address_prefix}} + + + + + {% endif %} {% endif %} diff --git a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml index 96e13cc37..e926796d0 100644 --- a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml @@ -3,7 +3,7 @@ {{name}} {{name}} - oc-ni-types:L3VRF + oc-ni-types:{{type}} @@ -17,33 +17,3 @@ - - - {{interface}} - - {{interface}} - - - - {{subinterface}} - - {{subinterface}} - - - - 1500 - - -
- {{address_ip}} - - {{address_ip}} - {{address_prefix}} - -
-
-
-
-
-
-
-- GitLab From 4f61e94182bb48e71a55088bd7ba90459b27a35b Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 10:30:40 +0000 Subject: [PATCH 14/29] Service component - L3NM OpenConfig: - Correct order of config rules - Correct attribute names --- .../l3nm_openconfig/ConfigRules.py | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 596126d1e..3f31f1ddf 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -107,7 +107,30 @@ def setup_config_rules( 'protocol_name': 'STATIC', }), - #Create interface with subinterface + #Create interface with subinterface (without IP address) + json_config_rule_set( + '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { + 'name' : if_subif_name, + 'type' :'ethernetCsmacd', + 'mtu' : mtu, + 'index' : sub_interface_index, + 'description': network_subinterface_desc, + 'vlan_id' : vlan_id, + }), + + #Associate interface to network instance + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { + 'name' : network_instance_name, + 'type' : 'L3VRF', + 'id' : if_subif_name, + 'interface' : if_subif_name, + 'subinterface' : sub_interface_index, + 'address_ip' : address_ip, + 'address_prefix': address_prefix, + }), + + #Create interface with subinterface (with IP address) json_config_rule_set( '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { 'name' : if_subif_name, @@ -120,20 +143,10 @@ def setup_config_rules( 'address_prefix': address_prefix, }), - #Associate interface to network instance - json_config_rule_set( - '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { - 'name' : network_instance_name, - 'id' : if_subif_name, - 'interface' : if_subif_name, - 'subinterface': sub_interface_index, - 'address_ip' : address_ip, - 'address_prefix': address_prefix, - }), - json_config_rule_set( '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, self_bgp_if_name), { 'name' : network_instance_name, + 'type' : 'L3VRF', 'id' : self_bgp_if_name, 'interface' : self_bgp_if_name, 'subinterface': bgp_sub_interface_index, @@ -151,10 +164,9 @@ def setup_config_rules( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { 'policy_name' : policy_import, - 'statement_name' : 'stm_{:s}'.format(policy_import), + 'statement_name' : 'stm_{:s}'.format(policy_import), # OCNOS: '10', 'ext_community_set_name': 'set_{:s}'.format(policy_import), 'policy_result' : 'ACCEPT_ROUTE', - 'sequence_id' : '10' }), #Associate routing policy to network instance @@ -174,10 +186,9 @@ def setup_config_rules( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { 'policy_name' : policy_export, - 'statement_name' : 'stm_{:s}'.format(policy_export), + 'statement_name' : 'stm_{:s}'.format(policy_export), # OCNOS: '10', 'ext_community_set_name': 'set_{:s}'.format(policy_export), 'policy_result' : 'ACCEPT_ROUTE', - 'sequence_id' : '10' }), #Associate routing policy to network instance @@ -262,10 +273,9 @@ def teardown_config_rules( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { 'policy_name' : policy_export, - 'statement_name' : 'stm_{:s}'.format(policy_export), + 'statement_name' : 'stm_{:s}'.format(policy_export), # OCNOS: '10', 'ext_community_set_name': 'set_{:s}'.format(policy_export), 'policy_result' : 'ACCEPT_ROUTE', - 'sequence_id' : '10' }), json_config_rule_delete( '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]'.format(policy_export, route_distinguisher), { @@ -277,10 +287,9 @@ def teardown_config_rules( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { 'policy_name' : policy_import, - 'statement_name' : 'stm_{:s}'.format(policy_import), + 'statement_name' : 'stm_{:s}'.format(policy_import), # OCNOS: '10', 'ext_community_set_name': 'set_{:s}'.format(policy_import), 'policy_result' : 'ACCEPT_ROUTE', - 'sequence_id' : '10' }), json_config_rule_delete( '/routing_policy/bgp_defined_set[{:s}_rt_import][{:s}]'.format(policy_import, route_distinguisher), { -- GitLab From 5643f06bfc723355fab65df7d5583a81b2b6cb48 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 10:41:48 +0000 Subject: [PATCH 15/29] Device component - OpenConfig driver: - Disabled IPInfusion custom fields in table connections - Corrected interface handling messages --- .../templates/VPN/Interfaces_multivendor.py | 4 ++- .../VPN/Network_instance_multivendor.py | 25 +++---------------- .../table_connections/edit_config.xml | 4 ++- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py index 0efa2e8f2..ab57ce3bd 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py @@ -65,8 +65,10 @@ def create_If_SubIf(data,vendor, DEL): with tag('single-tagged'): with tag('config'): with tag('vlan-id'):text(data['vlan_id']) - if "l3ipvlan" in data['type']: + if "l3ipvlan" in data['type'] and 'address_ip' in data: with tag('ipv4', xmlns="http://openconfig.net/yang/interfaces/ip"): + if 'mtu' in data: + with tag('mtu'):text(data['mtu']) with tag('addresses'): with tag('address'): with tag('ip'):text(data['address_ip']) diff --git a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py index 1f7015694..8d59cf5ac 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py @@ -196,7 +196,7 @@ def associate_If_to_NI(parameters, DEL): 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:L3VRF') + with tag('type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"'):text('oc-ni-types:',parameters['type']) with tag('interfaces'): with tag('interface'): with tag('id'):text(parameters['id']) @@ -204,25 +204,7 @@ def associate_If_to_NI(parameters, DEL): with tag('id') :text(parameters['id']) with tag('interface') :text(parameters['interface']) with tag('subinterface'):text(parameters['subinterface']) - with tag('interfaces', 'xmlns="http://openconfig.net/yang/interfaces"'): - with tag('interface'): - with tag('name'):text(parameters['interface']) - with tag('config'): - with tag('name'):text(parameters['interface']) - with tag('subinterfaces'): - with tag('subinterface'): - with tag('index'): text(parameters['subinterface']) - with tag('config'): - with tag('index'): text(parameters['subinterface']) - with tag('ipv4', 'xmlns="http://openconfig.net/yang/interfaces/ip"'): - with tag('config'): - with tag('mtu'): text('1500') - with tag('addresses'): - with tag('address'): - with tag('ip'):text(parameters['address_ip']) - with tag('config'): - with tag('ip'):text(parameters['address_ip']) - with tag('prefix-length'):text(parameters['address_prefix']) + result = indent( doc.getvalue(), @@ -365,7 +347,8 @@ def create_table_conns(parameters,DEL): with tag('src-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'): text('oc-pol-types:',parameters['src_protocol']) with tag('dst-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'): text('oc-pol-types:',parameters['dst_protocol']) with tag('address-family', 'xmlns:oc-types="http://openconfig.net/yang/openconfig-types"'):text('oc-types:',parameters['address_family']) - with tag('dst-instance', 'xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-oc-ni-augments"'):text('65000') + # for OCNOS: check if needed + #with tag('dst-instance', 'xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-oc-ni-augments"'):text('65000') if len(parameters['default_import_policy']) != 0: with tag('default-import-policy'):text(parameters['default_import_policy']) result = indent( diff --git a/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml index bd1dac1b3..35c535c6b 100644 --- a/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml @@ -11,7 +11,9 @@ oc-pol-types:{{src_protocol}} oc-pol-types:{{dst_protocol}} oc-types:{{address_family}} - {{as}} + {% if False %} + {{as}} + {% endif %} {% if default_import_policy is defined %}{{default_import_policy}}{% endif %}
{% endif %} -- GitLab From d2bc0964a009fca64000cbfe2740ddf19555919c Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 11:07:43 +0000 Subject: [PATCH 16/29] Device component - OpenConfig driver: - Add MTU to subinterfaces - Cosmetic improvements --- .../openconfig/templates/VPN/Network_instance_multivendor.py | 1 - .../openconfig/templates/interface/subinterface/edit_config.xml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py index 8d59cf5ac..157dd0ab8 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py @@ -204,7 +204,6 @@ def associate_If_to_NI(parameters, DEL): with tag('id') :text(parameters['id']) with tag('interface') :text(parameters['interface']) with tag('subinterface'):text(parameters['subinterface']) - result = indent( doc.getvalue(), diff --git a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml index eb7f49d76..20aecb90b 100644 --- a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml @@ -33,7 +33,7 @@ {% if address_ip is defined %} - 1500 + {% if mtu is defined %}{{mtu}}{% endif%} -- GitLab From e5a05ea8f0d06353f6f506da57eb117d342c17a4 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 11:08:13 +0000 Subject: [PATCH 17/29] PathComp component- Frontend: - Merged logics to manage composition of config rules --- .../algorithms/tools/ComposeConfigRules.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py index d5d5ad286..f92f9b2ff 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py @@ -184,23 +184,10 @@ def compose_device_config_rules( device_endpoint_keys = set(itertools.product(device_keys, endpoint_keys)) if len(device_endpoint_keys.intersection(endpoints_traversed)) == 0: continue - subservice_config_rules.append(config_rule) - match = RE_ENDPOINT_VLAN_SETTINGS.match(config_rule.custom.resource_key) - if match is not None: - device_uuid_or_name = match.group(1) - device_name_or_uuid = device_name_mapping[device_uuid_or_name] - device_keys = {device_uuid_or_name, device_name_or_uuid} + # TODO: check if vlan needs to be removed from config_rule + #config_rule.custom.resource_key = re.sub('\/vlan\[[^\]]+\]', '', config_rule.custom.resource_key) - endpoint_uuid_or_name = match.group(2) - endpoint_name_or_uuid_1 = endpoint_name_mapping[(device_uuid_or_name, endpoint_uuid_or_name)] - endpoint_name_or_uuid_2 = endpoint_name_mapping[(device_name_or_uuid, endpoint_uuid_or_name)] - endpoint_keys = {endpoint_uuid_or_name, endpoint_name_or_uuid_1, endpoint_name_or_uuid_2} - - device_endpoint_keys = set(itertools.product(device_keys, endpoint_keys)) - if len(device_endpoint_keys.intersection(endpoints_traversed)) == 0: continue - # ! check later: vlan removed from config_rule - config_rule.custom.resource_key = re.sub('\/vlan\[[^\]]+\]', '', config_rule.custom.resource_key) subservice_config_rules.append(config_rule) else: continue -- GitLab From 8a29bd6a8581c77457e1fe88dd2a890ac4b8127e Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 14:40:55 +0000 Subject: [PATCH 18/29] Service component - L3NM OpenConfig: - Cosmetic changes --- .../l3nm_openconfig/ConfigRules.py | 36 ++++++++++--------- .../L3NMOpenConfigServiceHandler.py | 4 +-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 3f31f1ddf..1f2593b0d 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -18,7 +18,7 @@ from service.service.service_handler_api.AnyTreeTools import TreeNode def setup_config_rules( service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, - service_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple], device_settings: TreeNode + service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple] ) -> List[Dict]: if service_settings is None: return [] @@ -60,13 +60,13 @@ def setup_config_rules( if_subif_name = '{:s}'.format(endpoint_name[5:]) json_config_rules = [ - # # Configure Interface (not used) - # json_config_rule_set( + # Configure Interface (not used) + #json_config_rule_set( # '/interface[{:s}]'.format(endpoint_name), { # 'name': endpoint_name, # 'description': network_interface_desc, # 'mtu': mtu, - # }), + #}), #Create network instance json_config_rule_set( @@ -98,7 +98,7 @@ def setup_config_rules( 'identifier': 'DIRECTLY_CONNECTED', 'protocol_name': 'DIRECTLY_CONNECTED', }), - + #Add STATIC protocol to network instance json_config_rule_set( '/network_instance[{:s}]/protocols[STATIC]'.format(network_instance_name), { @@ -229,7 +229,7 @@ def setup_config_rules( def teardown_config_rules( service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, - service_settings : TreeNode, endpoint_settings : TreeNode, device_settings: TreeNode + service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode ) -> List[Dict]: if service_settings is None: return [] @@ -247,17 +247,17 @@ def teardown_config_rules( # network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) network_subinterface_desc = '' - mtu = json_settings.get('mtu', 1450 ) # 1512 - #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 - route_distinguisher = json_device_settings.get('route_distinguisher', '0:0' ) # '60001:801' - sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 - router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' - vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 - address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' - address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 - policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 - policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 + mtu = json_settings.get('mtu', 1450 ) # 1512 + #address_families = json_settings.get('address_families', [] ) # ['IPV4'] + #bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 + route_distinguisher = json_device_settings.get('route_distinguisher', '0:0' ) # '60001:801' + sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 + #router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 + address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' + address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 + policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 + policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 self_bgp_if_name = json_device_settings.get('self_bgp_interface_name', '') self_bgp_address_ip = json_device_settings.get('self_bgp_interface_address_ip', '') @@ -282,6 +282,7 @@ def teardown_config_rules( 'ext_community_set_name': 'set_{:s}'.format(policy_export), 'ext_community_member' : route_distinguisher, }), + #Delete import routing policy json_config_rule_delete( # pylint: disable=duplicate-string-formatting-argument @@ -296,6 +297,7 @@ def teardown_config_rules( 'ext_community_set_name': 'set_{:s}'.format(policy_import), 'ext_community_member' : route_distinguisher, }), + #Delete interface; automatically deletes: # - /interface[]/subinterface[] # json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name), diff --git a/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py b/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py index 00a5406d7..2c944bfe4 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py +++ b/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py @@ -60,7 +60,7 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler): json_config_rules = setup_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name, - settings, endpoint_settings, endpoint_acls, device_settings) + settings, device_settings, endpoint_settings, endpoint_acls) if len(json_config_rules) > 0: del device_obj.device_config.config_rules[:] @@ -98,7 +98,7 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler): json_config_rules = teardown_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name, - settings, endpoint_settings, device_settings) + settings, device_settings, endpoint_settings) if len(json_config_rules) > 0: del device_obj.device_config.config_rules[:] -- GitLab From a3abb6d44de5cebadd6b6044aa4f117affbcea03 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 14:51:18 +0000 Subject: [PATCH 19/29] WebUI component: - Minor style fixing --- src/webui/service/__init__.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py index dc653126e..b864d3549 100644 --- a/src/webui/service/__init__.py +++ b/src/webui/service/__init__.py @@ -45,13 +45,14 @@ def json_to_list(json_str : str) -> List[Union[str, Tuple[str, str]]]: data = json.loads(json_str) except: # pylint: disable=bare-except return [('item', str(json_str))] - + if isinstance(data, dict): return [('kv', (key, value)) for key, value in data.items()] - elif isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict): # BWM use-case - return [('kv', (key, value)) for key, value in data[0].items()] - elif isinstance(data, list) and all(isinstance(d, str) for d in data): - return [('item', ', '.join(data))] + elif isinstance(data, list): + if len(data) == 1 and isinstance(data[0], dict): + return [('kv', (key, value)) for key, value in data[0].items()] + else: + return [('item', ', '.join([str(d) for d in data]))] else: return [('item', str(data))] -- GitLab From 8842d9b786bf2f5a721dc59445d4c365aa71fb1d Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 15:18:43 +0000 Subject: [PATCH 20/29] Service component - L3NM OpenConfig: - Rolling back malformed config rules, left backup for future integration --- .../l3nm_openconfig/ConfigRules.py | 88 ++--- .../l3nm_openconfig/ConfigRules_test_ocnos.py | 337 ++++++++++++++++++ 2 files changed, 357 insertions(+), 68 deletions(-) create mode 100644 src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 1f2593b0d..724f38298 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -31,17 +31,17 @@ def setup_config_rules( mtu = json_settings.get('mtu', 1450 ) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 + bgp_as = json_settings.get('bgp_as', 65000 ) # 65000 - router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' - route_distinguisher = json_device_settings.get('route_distinguisher', '65000:101' ) # '60001:801' + router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + route_distinguisher = json_settings.get('route_distinguisher', '65000:101' ) # '60001:801' sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 - policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 - policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 + policy_import = json_endpoint_settings.get('policy_AZ', '2' ) # 2 + policy_export = json_endpoint_settings.get('policy_ZA', '7' ) # 30 #network_interface_desc = '{:s}-NetIf'.format(service_uuid) network_interface_desc = json_endpoint_settings.get('ni_description','') #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) @@ -50,14 +50,7 @@ def setup_config_rules( #network_instance_name = '{:s}-NetInst'.format(service_short_uuid) network_instance_name = json_endpoint_settings.get('ni_name', service_uuid.split('-')[-1]) #ELAN-AC:1 - self_bgp_if_name = json_device_settings.get('self_bgp_interface_name', '') - self_bgp_address_ip = json_device_settings.get('self_bgp_interface_address_ip', '') - bgp_address_prefix = json_device_settings.get('bgp_interface_address_prefix', '') - bgp_sub_interface_index = json_device_settings.get('self_bgp_sub_interface_index', 0) - neighbor_bgp_if_address_ip= json_device_settings.get('neighbor_bgp_interface_address_ip', '0.0.0.0') # '2.2.2.1' - - # if_subif_name = '{:s}.{:d}'.format(endpoint_name, 0) - if_subif_name = '{:s}'.format(endpoint_name[5:]) + if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) json_config_rules = [ # Configure Interface (not used) @@ -75,7 +68,7 @@ def setup_config_rules( 'description': network_interface_desc, 'type': 'L3VRF', 'route_distinguisher': route_distinguisher, - 'router_id': router_id, + #'router_id': router_id, #'address_families': address_families, }), @@ -83,12 +76,11 @@ def setup_config_rules( json_config_rule_set( '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { 'name': network_instance_name, - 'protocol_name': bgp_as, + 'protocol_name': 'BGP', 'identifier': 'BGP', 'type': 'L3VRF', 'as': bgp_as, 'router_id': router_id, - 'neighbors': [{'ip_address': neighbor_bgp_if_address_ip, 'remote_as': bgp_as}] }), #Add DIRECTLY CONNECTED protocol to network instance @@ -107,17 +99,6 @@ def setup_config_rules( 'protocol_name': 'STATIC', }), - #Create interface with subinterface (without IP address) - json_config_rule_set( - '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { - 'name' : if_subif_name, - 'type' :'ethernetCsmacd', - 'mtu' : mtu, - 'index' : sub_interface_index, - 'description': network_subinterface_desc, - 'vlan_id' : vlan_id, - }), - #Associate interface to network instance json_config_rule_set( '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { @@ -130,11 +111,11 @@ def setup_config_rules( 'address_prefix': address_prefix, }), - #Create interface with subinterface (with IP address) + #Create interface with subinterface json_config_rule_set( '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { 'name' : if_subif_name, - 'type' :'ethernetCsmacd', + 'type' :'l3ipvlan', 'mtu' : mtu, 'index' : sub_interface_index, 'description' : network_subinterface_desc, @@ -164,7 +145,7 @@ def setup_config_rules( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { 'policy_name' : policy_import, - 'statement_name' : 'stm_{:s}'.format(policy_import), # OCNOS: '10', + 'statement_name' : 'stm_{:s}'.format(policy_import), 'ext_community_set_name': 'set_{:s}'.format(policy_import), 'policy_result' : 'ACCEPT_ROUTE', }), @@ -186,7 +167,7 @@ def setup_config_rules( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { 'policy_name' : policy_export, - 'statement_name' : 'stm_{:s}'.format(policy_export), # OCNOS: '10', + 'statement_name' : 'stm_{:s}'.format(policy_export), 'ext_community_set_name': 'set_{:s}'.format(policy_export), 'policy_result' : 'ACCEPT_ROUTE', }), @@ -206,7 +187,6 @@ def setup_config_rules( 'dst_protocol' : 'BGP', 'address_family' : 'IPV4', 'default_import_policy': 'ACCEPT_ROUTE', - 'as' : bgp_as, }), json_config_rule_set( @@ -216,7 +196,6 @@ def setup_config_rules( 'dst_protocol' : 'BGP', 'address_family' : 'IPV4', 'default_import_policy': 'ACCEPT_ROUTE', - 'as' : bgp_as, }), ] @@ -241,8 +220,7 @@ def teardown_config_rules( json_device_settings : Dict = device_settings.value service_short_uuid = service_uuid.split('-')[-1] - # network_instance_name = '{:s}-NetInst'.format(service_short_uuid) - network_instance_name = json_endpoint_settings.get('ni_name', service_short_uuid) #ELAN-AC:1 + network_instance_name = '{:s}-NetInst'.format(service_short_uuid) #network_interface_desc = '{:s}-NetIf'.format(service_uuid) # network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) network_subinterface_desc = '' @@ -259,21 +237,13 @@ def teardown_config_rules( policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 - self_bgp_if_name = json_device_settings.get('self_bgp_interface_name', '') - self_bgp_address_ip = json_device_settings.get('self_bgp_interface_address_ip', '') - bgp_address_prefix = json_device_settings.get('bgp_interface_address_prefix', '') - bgp_sub_interface_index = json_device_settings.get('self_bgp_sub_interface_index', 0) - - # if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) - if_subif_name = '{:s}'.format(endpoint_name[5:]) - json_config_rules = [ #Delete export routing policy json_config_rule_delete( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { 'policy_name' : policy_export, - 'statement_name' : 'stm_{:s}'.format(policy_export), # OCNOS: '10', + 'statement_name' : 'stm_{:s}'.format(policy_export), 'ext_community_set_name': 'set_{:s}'.format(policy_export), 'policy_result' : 'ACCEPT_ROUTE', }), @@ -284,11 +254,12 @@ def teardown_config_rules( }), #Delete import routing policy + json_config_rule_delete( # pylint: disable=duplicate-string-formatting-argument '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { 'policy_name' : policy_import, - 'statement_name' : 'stm_{:s}'.format(policy_import), # OCNOS: '10', + 'statement_name' : 'stm_{:s}'.format(policy_import), 'ext_community_set_name': 'set_{:s}'.format(policy_import), 'policy_result' : 'ACCEPT_ROUTE', }), @@ -300,35 +271,16 @@ def teardown_config_rules( #Delete interface; automatically deletes: # - /interface[]/subinterface[] - # json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name), - # { - # 'name': if_subif_name, - # }), + json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name), + { + 'name': if_subif_name, + }), #Delete network instance; automatically deletes: # - /network_instance[]/interface[] # - /network_instance[]/protocols[] # - /network_instance[]/inter_instance_policies[] - #Associate interface to network instance - json_config_rule_set( - '/network_instance[{:s}]/interface[{:s}]'.format('default', if_subif_name), { - 'name' : 'default', - 'id' : if_subif_name, - 'interface' : if_subif_name, - 'subinterface': sub_interface_index, - 'address_ip' : address_ip, - 'address_prefix': address_prefix, - }), - json_config_rule_set( - '/network_instance[{:s}]/interface[{:s}]'.format('default', self_bgp_if_name), { - 'name' : 'default', - 'id' : self_bgp_if_name, - 'interface' : self_bgp_if_name, - 'subinterface': bgp_sub_interface_index, - 'address_ip' : self_bgp_address_ip, - 'address_prefix': bgp_address_prefix, - }), json_config_rule_delete('/network_instance[{:s}]'.format(network_instance_name), { 'name': network_instance_name diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py new file mode 100644 index 000000000..1f2593b0d --- /dev/null +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py @@ -0,0 +1,337 @@ +# 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. + +from typing import Dict, List, Tuple +from common.tools.object_factory.ConfigRule import json_config_rule_delete, json_config_rule_set +from service.service.service_handler_api.AnyTreeTools import TreeNode + +def setup_config_rules( + service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, + service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple] +) -> List[Dict]: + + if service_settings is None: return [] + if endpoint_settings is None: return [] + if device_settings is None: return [] + + json_settings : Dict = service_settings.value + json_endpoint_settings : Dict = endpoint_settings.value + json_device_settings : Dict = device_settings.value + + mtu = json_settings.get('mtu', 1450 ) # 1512 + #address_families = json_settings.get('address_families', [] ) # ['IPV4'] + bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 + + router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + route_distinguisher = json_device_settings.get('route_distinguisher', '65000:101' ) # '60001:801' + sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 + vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 + address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' + address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 + + policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 + policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 + #network_interface_desc = '{:s}-NetIf'.format(service_uuid) + network_interface_desc = json_endpoint_settings.get('ni_description','') + #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) + network_subinterface_desc = json_endpoint_settings.get('subif_description','') + #service_short_uuid = service_uuid.split('-')[-1] + #network_instance_name = '{:s}-NetInst'.format(service_short_uuid) + network_instance_name = json_endpoint_settings.get('ni_name', service_uuid.split('-')[-1]) #ELAN-AC:1 + + self_bgp_if_name = json_device_settings.get('self_bgp_interface_name', '') + self_bgp_address_ip = json_device_settings.get('self_bgp_interface_address_ip', '') + bgp_address_prefix = json_device_settings.get('bgp_interface_address_prefix', '') + bgp_sub_interface_index = json_device_settings.get('self_bgp_sub_interface_index', 0) + neighbor_bgp_if_address_ip= json_device_settings.get('neighbor_bgp_interface_address_ip', '0.0.0.0') # '2.2.2.1' + + # if_subif_name = '{:s}.{:d}'.format(endpoint_name, 0) + if_subif_name = '{:s}'.format(endpoint_name[5:]) + + json_config_rules = [ + # Configure Interface (not used) + #json_config_rule_set( + # '/interface[{:s}]'.format(endpoint_name), { + # 'name': endpoint_name, + # 'description': network_interface_desc, + # 'mtu': mtu, + #}), + + #Create network instance + json_config_rule_set( + '/network_instance[{:s}]'.format(network_instance_name), { + 'name': network_instance_name, + 'description': network_interface_desc, + 'type': 'L3VRF', + 'route_distinguisher': route_distinguisher, + 'router_id': router_id, + #'address_families': address_families, + }), + + #Add BGP protocol to network instance + json_config_rule_set( + '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { + 'name': network_instance_name, + 'protocol_name': bgp_as, + 'identifier': 'BGP', + 'type': 'L3VRF', + 'as': bgp_as, + 'router_id': router_id, + 'neighbors': [{'ip_address': neighbor_bgp_if_address_ip, 'remote_as': bgp_as}] + }), + + #Add DIRECTLY CONNECTED protocol to network instance + json_config_rule_set( + '/network_instance[{:s}]/protocols[DIRECTLY_CONNECTED]'.format(network_instance_name), { + 'name': network_instance_name, + 'identifier': 'DIRECTLY_CONNECTED', + 'protocol_name': 'DIRECTLY_CONNECTED', + }), + + #Add STATIC protocol to network instance + json_config_rule_set( + '/network_instance[{:s}]/protocols[STATIC]'.format(network_instance_name), { + 'name': network_instance_name, + 'identifier': 'STATIC', + 'protocol_name': 'STATIC', + }), + + #Create interface with subinterface (without IP address) + json_config_rule_set( + '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { + 'name' : if_subif_name, + 'type' :'ethernetCsmacd', + 'mtu' : mtu, + 'index' : sub_interface_index, + 'description': network_subinterface_desc, + 'vlan_id' : vlan_id, + }), + + #Associate interface to network instance + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { + 'name' : network_instance_name, + 'type' : 'L3VRF', + 'id' : if_subif_name, + 'interface' : if_subif_name, + 'subinterface' : sub_interface_index, + 'address_ip' : address_ip, + 'address_prefix': address_prefix, + }), + + #Create interface with subinterface (with IP address) + json_config_rule_set( + '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { + 'name' : if_subif_name, + 'type' :'ethernetCsmacd', + 'mtu' : mtu, + 'index' : sub_interface_index, + 'description' : network_subinterface_desc, + 'vlan_id' : vlan_id, + 'address_ip' : address_ip, + 'address_prefix': address_prefix, + }), + + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, self_bgp_if_name), { + 'name' : network_instance_name, + 'type' : 'L3VRF', + 'id' : self_bgp_if_name, + 'interface' : self_bgp_if_name, + 'subinterface': bgp_sub_interface_index, + 'address_ip' : self_bgp_address_ip, + 'address_prefix': bgp_address_prefix, + }), + + #Create routing policy + json_config_rule_set( + '/routing_policy/bgp_defined_set[{:s}_rt_import][{:s}]'.format(policy_import,route_distinguisher), { + 'ext_community_set_name': 'set_{:s}'.format(policy_import), + 'ext_community_member' : route_distinguisher, + }), + json_config_rule_set( + # pylint: disable=duplicate-string-formatting-argument + '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { + 'policy_name' : policy_import, + 'statement_name' : 'stm_{:s}'.format(policy_import), # OCNOS: '10', + 'ext_community_set_name': 'set_{:s}'.format(policy_import), + 'policy_result' : 'ACCEPT_ROUTE', + }), + + #Associate routing policy to network instance + json_config_rule_set( + '/network_instance[{:s}]/inter_instance_policies[{:s}]'.format(network_instance_name, policy_import), { + 'name' : network_instance_name, + 'import_policy': policy_import, + }), + + #Create routing policy + json_config_rule_set( + '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]'.format(policy_export, route_distinguisher), { + 'ext_community_set_name': 'set_{:s}'.format(policy_export), + 'ext_community_member' : route_distinguisher, + }), + json_config_rule_set( + # pylint: disable=duplicate-string-formatting-argument + '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { + 'policy_name' : policy_export, + 'statement_name' : 'stm_{:s}'.format(policy_export), # OCNOS: '10', + 'ext_community_set_name': 'set_{:s}'.format(policy_export), + 'policy_result' : 'ACCEPT_ROUTE', + }), + + #Associate routing policy to network instance + json_config_rule_set( + '/network_instance[{:s}]/inter_instance_policies[{:s}]'.format(network_instance_name, policy_export),{ + 'name' : network_instance_name, + 'export_policy': policy_export, + }), + + #Create table connections + json_config_rule_set( + '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format(network_instance_name), { + 'name' : network_instance_name, + 'src_protocol' : 'DIRECTLY_CONNECTED', + 'dst_protocol' : 'BGP', + 'address_family' : 'IPV4', + 'default_import_policy': 'ACCEPT_ROUTE', + 'as' : bgp_as, + }), + + json_config_rule_set( + '/network_instance[{:s}]/table_connections[STATIC][BGP][IPV4]'.format(network_instance_name), { + 'name' : network_instance_name, + 'src_protocol' : 'STATIC', + 'dst_protocol' : 'BGP', + 'address_family' : 'IPV4', + 'default_import_policy': 'ACCEPT_ROUTE', + 'as' : bgp_as, + }), + + ] + + for res_key, res_value in endpoint_acls: + json_config_rules.append( + {'action': 1, 'acl': res_value} + ) + return json_config_rules + +def teardown_config_rules( + service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, + service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode +) -> List[Dict]: + + if service_settings is None: return [] + if endpoint_settings is None: return [] + if device_settings is None: return [] + + json_settings : Dict = service_settings.value + json_endpoint_settings : Dict = endpoint_settings.value + json_device_settings : Dict = device_settings.value + + service_short_uuid = service_uuid.split('-')[-1] + # network_instance_name = '{:s}-NetInst'.format(service_short_uuid) + network_instance_name = json_endpoint_settings.get('ni_name', service_short_uuid) #ELAN-AC:1 + #network_interface_desc = '{:s}-NetIf'.format(service_uuid) + # network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) + network_subinterface_desc = '' + + mtu = json_settings.get('mtu', 1450 ) # 1512 + #address_families = json_settings.get('address_families', [] ) # ['IPV4'] + #bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 + route_distinguisher = json_device_settings.get('route_distinguisher', '0:0' ) # '60001:801' + sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 + #router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 + address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' + address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 + policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 + policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 + + self_bgp_if_name = json_device_settings.get('self_bgp_interface_name', '') + self_bgp_address_ip = json_device_settings.get('self_bgp_interface_address_ip', '') + bgp_address_prefix = json_device_settings.get('bgp_interface_address_prefix', '') + bgp_sub_interface_index = json_device_settings.get('self_bgp_sub_interface_index', 0) + + # if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) + if_subif_name = '{:s}'.format(endpoint_name[5:]) + + json_config_rules = [ + #Delete export routing policy + json_config_rule_delete( + # pylint: disable=duplicate-string-formatting-argument + '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { + 'policy_name' : policy_export, + 'statement_name' : 'stm_{:s}'.format(policy_export), # OCNOS: '10', + 'ext_community_set_name': 'set_{:s}'.format(policy_export), + 'policy_result' : 'ACCEPT_ROUTE', + }), + json_config_rule_delete( + '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]'.format(policy_export, route_distinguisher), { + 'ext_community_set_name': 'set_{:s}'.format(policy_export), + 'ext_community_member' : route_distinguisher, + }), + + #Delete import routing policy + json_config_rule_delete( + # pylint: disable=duplicate-string-formatting-argument + '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { + 'policy_name' : policy_import, + 'statement_name' : 'stm_{:s}'.format(policy_import), # OCNOS: '10', + 'ext_community_set_name': 'set_{:s}'.format(policy_import), + 'policy_result' : 'ACCEPT_ROUTE', + }), + json_config_rule_delete( + '/routing_policy/bgp_defined_set[{:s}_rt_import][{:s}]'.format(policy_import, route_distinguisher), { + 'ext_community_set_name': 'set_{:s}'.format(policy_import), + 'ext_community_member' : route_distinguisher, + }), + + #Delete interface; automatically deletes: + # - /interface[]/subinterface[] + # json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name), + # { + # 'name': if_subif_name, + # }), + + #Delete network instance; automatically deletes: + # - /network_instance[]/interface[] + # - /network_instance[]/protocols[] + # - /network_instance[]/inter_instance_policies[] + + #Associate interface to network instance + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format('default', if_subif_name), { + 'name' : 'default', + 'id' : if_subif_name, + 'interface' : if_subif_name, + 'subinterface': sub_interface_index, + 'address_ip' : address_ip, + 'address_prefix': address_prefix, + }), + json_config_rule_set( + '/network_instance[{:s}]/interface[{:s}]'.format('default', self_bgp_if_name), { + 'name' : 'default', + 'id' : self_bgp_if_name, + 'interface' : self_bgp_if_name, + 'subinterface': bgp_sub_interface_index, + 'address_ip' : self_bgp_address_ip, + 'address_prefix': bgp_address_prefix, + }), + json_config_rule_delete('/network_instance[{:s}]'.format(network_instance_name), + { + 'name': network_instance_name + }), + ] + return json_config_rules -- GitLab From da5aa154c4b7a218adbf032cb2fba3da54cfc0a5 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 15:23:39 +0000 Subject: [PATCH 21/29] Service component - L3NM OpenConfig: - Rolling back malformed config rules, left backup for future integration --- .../l3nm_openconfig/ConfigRules.py | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 724f38298..504a3ff6a 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -222,51 +222,58 @@ def teardown_config_rules( service_short_uuid = service_uuid.split('-')[-1] network_instance_name = '{:s}-NetInst'.format(service_short_uuid) #network_interface_desc = '{:s}-NetIf'.format(service_uuid) - # network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) - network_subinterface_desc = '' + #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) - mtu = json_settings.get('mtu', 1450 ) # 1512 - #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - #bgp_as = json_device_settings.get('bgp_as', 65000 ) # 65000 + #mtu = json_settings.get('mtu', 1450 ) # 1512 + #address_families = json_settings.get('address_families', [] ) # ['IPV4'] + #bgp_as = json_settings.get('bgp_as', 65000 ) # 65000 route_distinguisher = json_device_settings.get('route_distinguisher', '0:0' ) # '60001:801' - sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 - #router_id = json_device_settings.get('router_id', '0.0.0.0') # '10.95.0.10' - vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 - address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' - address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 + #sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 + #router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + #address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' + #address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 json_config_rules = [ + #Delete table connections + json_config_rule_delete( + '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format(network_instance_name),{ + 'name' : network_instance_name, + 'src_protocol' : 'DIRECTLY_CONNECTED', + 'dst_protocol' : 'BGP', + 'address_family': 'IPV4', + }), + + + json_config_rule_delete( + '/network_instance[{:s}]/table_connections[STATIC][BGP][IPV4]'.format(network_instance_name), { + 'name' : network_instance_name, + 'src_protocol' : 'STATIC', + 'dst_protocol' : 'BGP', + 'address_family': 'IPV4', + }), + #Delete export routing policy + json_config_rule_delete( - # pylint: disable=duplicate-string-formatting-argument - '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), { - 'policy_name' : policy_export, - 'statement_name' : 'stm_{:s}'.format(policy_export), - 'ext_community_set_name': 'set_{:s}'.format(policy_export), - 'policy_result' : 'ACCEPT_ROUTE', + '/routing_policy/policy_definition[{:s}_export]'.format(network_instance_name), { + 'policy_name': '{:s}_export'.format(network_instance_name), }), json_config_rule_delete( '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]'.format(policy_export, route_distinguisher), { 'ext_community_set_name': 'set_{:s}'.format(policy_export), - 'ext_community_member' : route_distinguisher, }), #Delete import routing policy json_config_rule_delete( - # pylint: disable=duplicate-string-formatting-argument - '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), { - 'policy_name' : policy_import, - 'statement_name' : 'stm_{:s}'.format(policy_import), - 'ext_community_set_name': 'set_{:s}'.format(policy_import), - 'policy_result' : 'ACCEPT_ROUTE', + '/routing_policy/policy_definition[{:s}_import]'.format(network_instance_name), { + 'policy_name': '{:s}_import'.format(network_instance_name), }), json_config_rule_delete( '/routing_policy/bgp_defined_set[{:s}_rt_import][{:s}]'.format(policy_import, route_distinguisher), { 'ext_community_set_name': 'set_{:s}'.format(policy_import), - 'ext_community_member' : route_distinguisher, }), #Delete interface; automatically deletes: @@ -280,7 +287,6 @@ def teardown_config_rules( # - /network_instance[]/interface[] # - /network_instance[]/protocols[] # - /network_instance[]/inter_instance_policies[] - json_config_rule_delete('/network_instance[{:s}]'.format(network_instance_name), { 'name': network_instance_name -- GitLab From 097eb53c60b413358ba2972db27b20f33da6cf47 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 15:25:57 +0000 Subject: [PATCH 22/29] Service component - L3NM OpenConfig: - Rolling back malformed config rules, left backup for future integration --- .../l3nm_openconfig/ConfigRules.py | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 504a3ff6a..098776970 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -99,18 +99,6 @@ def setup_config_rules( 'protocol_name': 'STATIC', }), - #Associate interface to network instance - json_config_rule_set( - '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { - 'name' : network_instance_name, - 'type' : 'L3VRF', - 'id' : if_subif_name, - 'interface' : if_subif_name, - 'subinterface' : sub_interface_index, - 'address_ip' : address_ip, - 'address_prefix': address_prefix, - }), - #Create interface with subinterface json_config_rule_set( '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), { @@ -124,15 +112,16 @@ def setup_config_rules( 'address_prefix': address_prefix, }), + #Associate interface to network instance json_config_rule_set( - '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, self_bgp_if_name), { - 'name' : network_instance_name, - 'type' : 'L3VRF', - 'id' : self_bgp_if_name, - 'interface' : self_bgp_if_name, - 'subinterface': bgp_sub_interface_index, - 'address_ip' : self_bgp_address_ip, - 'address_prefix': bgp_address_prefix, + '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { + 'name' : network_instance_name, + 'type' : 'L3VRF', + 'id' : if_subif_name, + 'interface' : if_subif_name, + 'subinterface' : sub_interface_index, + 'address_ip' : address_ip, + 'address_prefix': address_prefix, }), #Create routing policy -- GitLab From 214ffd0ec89b28466b0217a93fca8d05416c9c07 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 15:29:42 +0000 Subject: [PATCH 23/29] Service component - L3NM OpenConfig: - Rolling back malformed config rules, left backup for future integration --- .../l3nm_openconfig/ConfigRules.py | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 098776970..f440a3c92 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -115,13 +115,11 @@ def setup_config_rules( #Associate interface to network instance json_config_rule_set( '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { - 'name' : network_instance_name, - 'type' : 'L3VRF', - 'id' : if_subif_name, - 'interface' : if_subif_name, - 'subinterface' : sub_interface_index, - 'address_ip' : address_ip, - 'address_prefix': address_prefix, + 'name' : network_instance_name, + 'type' : 'L3VRF', + 'id' : if_subif_name, + 'interface' : if_subif_name, + 'subinterface': sub_interface_index, }), #Create routing policy @@ -216,13 +214,16 @@ def teardown_config_rules( #mtu = json_settings.get('mtu', 1450 ) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] #bgp_as = json_settings.get('bgp_as', 65000 ) # 65000 - route_distinguisher = json_device_settings.get('route_distinguisher', '0:0' ) # '60001:801' + route_distinguisher = json_settings.get('route_distinguisher', '0:0' ) # '60001:801' #sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 #router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' + vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 #address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' #address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 - policy_import = json_device_settings.get('policy_AZ', '2' ) # 2 - policy_export = json_device_settings.get('policy_ZA', '7' ) # 30 + policy_import = json_endpoint_settings.get('policy_AZ', '2' ) # 2 + policy_export = json_endpoint_settings.get('policy_ZA', '7' ) # 30 + + if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) json_config_rules = [ #Delete table connections -- GitLab From a27a8eb0ea44d77e65c186f57e7583aa7a9e065a Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 23 Apr 2024 15:30:59 +0000 Subject: [PATCH 24/29] Service component - L3NM OpenConfig: - Rolling back malformed config rules, left backup for future integration --- .../service_handlers/l3nm_openconfig/ConfigRules.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index f440a3c92..716d0413a 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -22,12 +22,12 @@ def setup_config_rules( ) -> List[Dict]: if service_settings is None: return [] + if device_settings is None: return [] if endpoint_settings is None: return [] - if device_settings is None: return [] json_settings : Dict = service_settings.value - json_endpoint_settings : Dict = endpoint_settings.value json_device_settings : Dict = device_settings.value + json_endpoint_settings : Dict = endpoint_settings.value mtu = json_settings.get('mtu', 1450 ) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] @@ -199,12 +199,12 @@ def teardown_config_rules( ) -> List[Dict]: if service_settings is None: return [] - if endpoint_settings is None: return [] if device_settings is None: return [] + if endpoint_settings is None: return [] json_settings : Dict = service_settings.value - json_endpoint_settings : Dict = endpoint_settings.value json_device_settings : Dict = device_settings.value + json_endpoint_settings : Dict = endpoint_settings.value service_short_uuid = service_uuid.split('-')[-1] network_instance_name = '{:s}-NetInst'.format(service_short_uuid) -- GitLab From dc32fbb82671af64b0d78d93ee4a59371a9bef92 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 7 May 2024 16:32:35 +0000 Subject: [PATCH 25/29] Device - OpenConfig SBI driver: - Corrected Jinja template for edit-config interface/subinterface --- .../interface/subinterface/edit_config.xml | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml index 20aecb90b..2d8d3ee07 100644 --- a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml +++ b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml @@ -1,5 +1,4 @@ - + {{name}} {% if operation is defined and operation != 'delete' %} @@ -31,20 +30,20 @@ {% endif %} {% if address_ip is defined %} - - + + {% if mtu is defined %}{{mtu}}{% endif%} - - - - {{address_ip}} - - {{address_ip}} - {{address_prefix}} - - - - + + +
+ {{address_ip}} + + {{address_ip}} + {{address_prefix}} + +
+
+ {% endif %} -- GitLab From 658b71b00cbc29adcd34fc3e73b138ee75c1b4c3 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 7 May 2024 16:52:40 +0000 Subject: [PATCH 26/29] Device - OpenConfig SBI driver: - Added test for IPInfusion OcNOS --- ...n_tests_locally-device-openconfig-ocnos.sh | 25 +++ .../tests/test_unitary_openconfig_ocnos.py | 210 ++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100755 scripts/run_tests_locally-device-openconfig-ocnos.sh create mode 100644 src/device/tests/test_unitary_openconfig_ocnos.py diff --git a/scripts/run_tests_locally-device-openconfig-ocnos.sh b/scripts/run_tests_locally-device-openconfig-ocnos.sh new file mode 100755 index 000000000..413691b85 --- /dev/null +++ b/scripts/run_tests_locally-device-openconfig-ocnos.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# 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. + + +PROJECTDIR=`pwd` + +cd $PROJECTDIR/src +RCFILE=$PROJECTDIR/coverage/.coveragerc + +# Run unitary tests and analyze coverage of code at same time +# helpful pytest flags: --log-level=INFO -o log_cli=true --verbose --maxfail=1 --durations=0 +coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO -o log_cli=true --verbose \ + device/tests/test_unitary_openconfig_ocnos.py diff --git a/src/device/tests/test_unitary_openconfig_ocnos.py b/src/device/tests/test_unitary_openconfig_ocnos.py new file mode 100644 index 000000000..5e02accdd --- /dev/null +++ b/src/device/tests/test_unitary_openconfig_ocnos.py @@ -0,0 +1,210 @@ +# 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, logging, os, pytest, time +from typing import Dict, Tuple +os.environ['DEVICE_EMULATED_ONLY'] = 'YES' + +# pylint: disable=wrong-import-position +from device.service.drivers.openconfig.OpenConfigDriver import OpenConfigDriver +#from device.service.driver_api._Driver import ( +# RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES, RESOURCE_ROUTING_POLICIES, RESOURCE_SERVICES +#) + +logging.basicConfig(level=logging.DEBUG) +#logging.getLogger('ncclient.operations.rpc').setLevel(logging.INFO) +#logging.getLogger('ncclient.transport.parser').setLevel(logging.INFO) + +LOGGER = logging.getLogger(__name__) + + +##### DRIVERS FIXTURE ################################################################################################## + +DEVICES = { + 'CSGW1': {'address': '10.1.1.86', 'port': 830, 'settings': { + 'username': 'ocnos', 'password': 'ocnos', + 'vendor': None, 'force_running': False, 'hostkey_verify': False, 'look_for_keys': False, 'allow_agent': False, + 'commit_per_rule': True, 'device_params': {'name': 'default'}, 'manager_params': {'timeout' : 120} + }}, + 'CSGW2': {'address': '10.1.1.87', 'port': 830, 'settings': { + 'username': 'ocnos', 'password': 'ocnos', + 'vendor': None, 'force_running': False, 'hostkey_verify': False, 'look_for_keys': False, 'allow_agent': False, + 'commit_per_rule': True, 'device_params': {'name': 'default'}, 'manager_params': {'timeout' : 120} + }}, +} + +@pytest.fixture(scope='session') +def drivers() -> Dict[str, OpenConfigDriver]: + _drivers : Dict[str, OpenConfigDriver] = dict() + for device_name, driver_params in DEVICES.items(): + driver = OpenConfigDriver(driver_params['address'], driver_params['port'], **(driver_params['settings'])) + driver.Connect() + _drivers[device_name] = driver + yield _drivers + time.sleep(1) + for _,driver in _drivers.items(): + driver.Disconnect() + + +def network_instance(ni_name, ni_type, ni_router_id=None, ni_route_distinguisher=None) -> Tuple[str, Dict]: + path = '/network_instance[{:s}]'.format(ni_name) + data = {'name': ni_name, 'type': ni_type} + if ni_router_id is not None: data['router_id'] = ni_router_id + if ni_route_distinguisher is not None: data['route_distinguisher'] = ni_route_distinguisher + return path, json.dumps(data) + +def network_instance_add_protocol_bgp(ni_name, ni_type, ni_router_id, ni_bgp_as, neighbors=[]) -> Tuple[str, Dict]: + path = '/network_instance[{:s}]/protocols[BGP]'.format(ni_name) + data = { + 'name': ni_name, 'type': ni_type, 'router_id': ni_router_id, 'identifier': 'BGP', + 'protocol_name': ni_bgp_as, 'as': ni_bgp_as + } + if len(neighbors) > 0: + data['neighbors'] = [ + {'ip_address': neighbor_ip_address, 'remote_as': neighbor_remote_as} + for neighbor_ip_address, neighbor_remote_as in neighbors + ] + return path, json.dumps(data) + +def network_instance_add_protocol_direct(ni_name, ni_type) -> Tuple[str, Dict]: + path = '/network_instance[{:s}]/protocols[DIRECTLY_CONNECTED]'.format(ni_name) + data = { + 'name': ni_name, 'type': ni_type, 'identifier': 'DIRECTLY_CONNECTED', + 'protocol_name': 'DIRECTLY_CONNECTED' + } + return path, json.dumps(data) + +def network_instance_add_protocol_static(ni_name, ni_type) -> Tuple[str, Dict]: + path = '/network_instance[{:s}]/protocols[STATIC]'.format(ni_name) + data = { + 'name': ni_name, 'type': ni_type, 'identifier': 'STATIC', + 'protocol_name': 'STATIC' + } + return path, json.dumps(data) + +#def network_instance_static_route(ni_name, prefix, next_hop, next_hop_index=0) -> Tuple[str, Dict]: +# path = '/network_instance[{:s}]/static_route[{:s}]'.format(ni_name, prefix) +# data = {'name': ni_name, 'prefix': prefix, 'next_hop': next_hop, 'next_hop_index': next_hop_index} +# return path, json.dumps(data) + +def network_instance_add_table_connection( + ni_name, src_protocol, dst_protocol, address_family, default_import_policy, bgp_as=None +) -> Tuple[str, Dict]: + path = '/network_instance[{:s}]/table_connections[{:s}][{:s}][{:s}]'.format( + ni_name, src_protocol, dst_protocol, address_family + ) + data = { + 'name': ni_name, 'src_protocol': src_protocol, 'dst_protocol': dst_protocol, + 'address_family': address_family, 'default_import_policy': default_import_policy, + } + if bgp_as is not None: data['as'] = bgp_as + return path, json.dumps(data) + +def interface( + name, index, description=None, if_type=None, vlan_id=None, mtu=None, ipv4_address_prefix=None, enabled=None +) -> Tuple[str, Dict]: + path = '/interface[{:s}]/subinterface[{:d}]'.format(name, index) + data = {'name': name, 'index': index} + if description is not None: data['description'] = description + if if_type is not None: data['type' ] = if_type + if vlan_id is not None: data['vlan_id' ] = vlan_id + if mtu is not None: data['mtu' ] = mtu + if enabled is not None: data['enabled' ] = enabled + if ipv4_address_prefix is not None: + ipv4_address, ipv4_prefix = ipv4_address_prefix + data['address_ip' ] = ipv4_address + data['address_prefix'] = ipv4_prefix + return path, json.dumps(data) + +def network_instance_interface(ni_name, ni_type, if_name, if_index) -> Tuple[str, Dict]: + path = '/network_instance[{:s}]/interface[{:s}.{:d}]'.format(ni_name, if_name, if_index) + data = {'name': ni_name, 'type': ni_type, 'id': if_name, 'interface': if_name, 'subinterface': if_index} + return path, json.dumps(data) + +def test_configure(drivers : Dict[str, OpenConfigDriver]): + #resources_to_get = [] + #resources_to_get = [RESOURCE_ENDPOINTS] + #resources_to_get = [RESOURCE_INTERFACES] + #resources_to_get = [RESOURCE_NETWORK_INSTANCES] + #resources_to_get = [RESOURCE_ROUTING_POLICIES] + #resources_to_get = [RESOURCE_SERVICES] + #LOGGER.info('resources_to_get = {:s}'.format(str(resources_to_get))) + #results_getconfig = driver.GetConfig(resources_to_get) + #LOGGER.info('results_getconfig = {:s}'.format(str(results_getconfig))) + + #csgw1_resources_to_set = [ + # network_instance('ecoc24', 'L3VRF', '192.168.150.1', '65001:1'), + # network_instance_add_protocol_direct('ecoc24', 'L3VRF'), + # network_instance_add_protocol_static('ecoc24', 'L3VRF'), + # network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.1', '65001', neighbors=[ + # ('192.168.150.2', '65001') + # ]), + # network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + # network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + # + # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500), + # network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), + # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.10.1', 24), enabled=True), + # + # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500), + # network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), + # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.1', 24), enabled=True), + #] + #LOGGER.info('CSGW1 resources_to_set = {:s}'.format(str(csgw1_resources_to_set))) + #results_setconfig = drivers['CSGW1'].SetConfig(csgw1_resources_to_set) + #LOGGER.info('CSGW1 results_setconfig = {:s}'.format(str(results_setconfig))) + + #csgw2_resources_to_set = [ + # network_instance('ecoc24', 'L3VRF', '192.168.150.2', '65001:1'), + # network_instance_add_protocol_direct('ecoc24', 'L3VRF'), + # network_instance_add_protocol_static('ecoc24', 'L3VRF'), + # network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.2', '65001', neighbors=[ + # ('192.168.150.1', '65001') + # ]), + # network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + # network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + # + # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500), + # network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), + # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.20.1', 24), enabled=True), + # + # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500), + # network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), + # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.2', 24), enabled=True), + #] + #LOGGER.info('CSGW2 resources_to_set = {:s}'.format(str(csgw2_resources_to_set))) + #results_setconfig = drivers['CSGW2'].SetConfig(csgw2_resources_to_set) + #LOGGER.info('CSGW2 results_setconfig = {:s}'.format(str(results_setconfig))) + + csgw1_resources_to_delete = [ + network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), + network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), + #interface('ce1', 0), + #interface('xe5', 0), + network_instance('ecoc24', 'L3VRF'), + ] + LOGGER.info('CSGW1 resources_to_delete = {:s}'.format(str(csgw1_resources_to_delete))) + results_deleteconfig = drivers['CSGW1'].DeleteConfig(csgw1_resources_to_delete) + LOGGER.info('CSGW1 results_deleteconfig = {:s}'.format(str(results_deleteconfig))) + + #csgw2_resources_to_delete = [ + # network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), + # network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), + # #interface('ce1', 0), + # #interface('xe5', 0), + # network_instance('ecoc24', 'L3VRF'), + #] + #LOGGER.info('CSGW2 resources_to_delete = {:s}'.format(str(csgw2_resources_to_delete))) + #results_deleteconfig = drivers['CSGW2'].DeleteConfig(csgw2_resources_to_delete) + #LOGGER.info('CSGW2 results_deleteconfig = {:s}'.format(str(results_deleteconfig))) -- GitLab From 89e73d9b83c6b018512334613f5cfc0476918ffa Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Thu, 9 May 2024 12:52:57 +0000 Subject: [PATCH 27/29] Service component - L3NM OpenConfig Service Handler: - intermediate step towards supporting configuration of OcNOS devices --- .../l3nm_openconfig/ConfigRules.py | 23 ++++++++++++++----- .../l3nm_openconfig/ConfigRules_test_ocnos.py | 8 +++---- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py index 716d0413a..752793287 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py @@ -12,10 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, List, Tuple +from typing import Any, Dict, List, Optional, Tuple from common.tools.object_factory.ConfigRule import json_config_rule_delete, json_config_rule_set from service.service.service_handler_api.AnyTreeTools import TreeNode +def get_value(field_name : str, *containers, default=None) -> Optional[Any]: + if len(containers) == 0: raise Exception('No containers specified') + for container in containers: + if field_name not in container: continue + return container[field_name] + return default + def setup_config_rules( service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple] @@ -29,9 +36,11 @@ def setup_config_rules( json_device_settings : Dict = device_settings.value json_endpoint_settings : Dict = endpoint_settings.value - mtu = json_settings.get('mtu', 1450 ) # 1512 + settings = (json_settings, json_endpoint_settings, json_device_settings) + + mtu = get_value('mtu', *settings, default=1450) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - bgp_as = json_settings.get('bgp_as', 65000 ) # 65000 + bgp_as = get_value('bgp_as', *settings, default=65000) # 65000 router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' route_distinguisher = json_settings.get('route_distinguisher', '65000:101' ) # '60001:801' @@ -199,21 +208,23 @@ def teardown_config_rules( ) -> List[Dict]: if service_settings is None: return [] - if device_settings is None: return [] + if device_settings is None: return [] if endpoint_settings is None: return [] json_settings : Dict = service_settings.value json_device_settings : Dict = device_settings.value json_endpoint_settings : Dict = endpoint_settings.value + settings = (json_settings, json_endpoint_settings, json_device_settings) + service_short_uuid = service_uuid.split('-')[-1] network_instance_name = '{:s}-NetInst'.format(service_short_uuid) #network_interface_desc = '{:s}-NetIf'.format(service_uuid) #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) - #mtu = json_settings.get('mtu', 1450 ) # 1512 + #mtu = get_value('mtu', *settings, default=1450) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - #bgp_as = json_settings.get('bgp_as', 65000 ) # 65000 + #bgp_as = get_value('bgp_as', *settings, default=65000) # 65000 route_distinguisher = json_settings.get('route_distinguisher', '0:0' ) # '60001:801' #sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 #router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py index 1f2593b0d..5fa1d0b5b 100644 --- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py +++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py @@ -22,12 +22,12 @@ def setup_config_rules( ) -> List[Dict]: if service_settings is None: return [] + if device_settings is None: return [] if endpoint_settings is None: return [] - if device_settings is None: return [] json_settings : Dict = service_settings.value - json_endpoint_settings : Dict = endpoint_settings.value json_device_settings : Dict = device_settings.value + json_endpoint_settings : Dict = endpoint_settings.value mtu = json_settings.get('mtu', 1450 ) # 1512 #address_families = json_settings.get('address_families', [] ) # ['IPV4'] @@ -233,12 +233,12 @@ def teardown_config_rules( ) -> List[Dict]: if service_settings is None: return [] + if device_settings is None: return [] if endpoint_settings is None: return [] - if device_settings is None: return [] json_settings : Dict = service_settings.value - json_endpoint_settings : Dict = endpoint_settings.value json_device_settings : Dict = device_settings.value + json_endpoint_settings : Dict = endpoint_settings.value service_short_uuid = service_uuid.split('-')[-1] # network_instance_name = '{:s}-NetInst'.format(service_short_uuid) -- GitLab From 6ebc4d54fb504c79fa7e0217e7f3b7630555536b Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Thu, 9 May 2024 12:53:35 +0000 Subject: [PATCH 28/29] Device - OpenConfig SBI driver: - Updated test for IPInfusion OcNOS --- .../tests/test_unitary_openconfig_ocnos.py | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/device/tests/test_unitary_openconfig_ocnos.py b/src/device/tests/test_unitary_openconfig_ocnos.py index 5e02accdd..87d951581 100644 --- a/src/device/tests/test_unitary_openconfig_ocnos.py +++ b/src/device/tests/test_unitary_openconfig_ocnos.py @@ -143,49 +143,49 @@ def test_configure(drivers : Dict[str, OpenConfigDriver]): #results_getconfig = driver.GetConfig(resources_to_get) #LOGGER.info('results_getconfig = {:s}'.format(str(results_getconfig))) - #csgw1_resources_to_set = [ - # network_instance('ecoc24', 'L3VRF', '192.168.150.1', '65001:1'), - # network_instance_add_protocol_direct('ecoc24', 'L3VRF'), - # network_instance_add_protocol_static('ecoc24', 'L3VRF'), - # network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.1', '65001', neighbors=[ - # ('192.168.150.2', '65001') - # ]), - # network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), - # network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), - # - # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500), - # network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), - # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.10.1', 24), enabled=True), - # - # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500), - # network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), - # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.1', 24), enabled=True), - #] - #LOGGER.info('CSGW1 resources_to_set = {:s}'.format(str(csgw1_resources_to_set))) - #results_setconfig = drivers['CSGW1'].SetConfig(csgw1_resources_to_set) - #LOGGER.info('CSGW1 results_setconfig = {:s}'.format(str(results_setconfig))) - - #csgw2_resources_to_set = [ - # network_instance('ecoc24', 'L3VRF', '192.168.150.2', '65001:1'), - # network_instance_add_protocol_direct('ecoc24', 'L3VRF'), - # network_instance_add_protocol_static('ecoc24', 'L3VRF'), - # network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.2', '65001', neighbors=[ - # ('192.168.150.1', '65001') - # ]), - # network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), - # network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), - # - # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500), - # network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), - # interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.20.1', 24), enabled=True), - # - # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500), - # network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), - # interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.2', 24), enabled=True), - #] - #LOGGER.info('CSGW2 resources_to_set = {:s}'.format(str(csgw2_resources_to_set))) - #results_setconfig = drivers['CSGW2'].SetConfig(csgw2_resources_to_set) - #LOGGER.info('CSGW2 results_setconfig = {:s}'.format(str(results_setconfig))) + csgw1_resources_to_set = [ + network_instance('ecoc24', 'L3VRF', '192.168.150.1', '65001:1'), + network_instance_add_protocol_direct('ecoc24', 'L3VRF'), + network_instance_add_protocol_static('ecoc24', 'L3VRF'), + network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.1', '65001', neighbors=[ + ('192.168.150.2', '65001') + ]), + network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + + interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500), + network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), + interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.10.1', 24), enabled=True), + + interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500), + network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), + interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.1', 24), enabled=True), + ] + LOGGER.info('CSGW1 resources_to_set = {:s}'.format(str(csgw1_resources_to_set))) + results_setconfig = drivers['CSGW1'].SetConfig(csgw1_resources_to_set) + LOGGER.info('CSGW1 results_setconfig = {:s}'.format(str(results_setconfig))) + + csgw2_resources_to_set = [ + network_instance('ecoc24', 'L3VRF', '192.168.150.2', '65001:1'), + network_instance_add_protocol_direct('ecoc24', 'L3VRF'), + network_instance_add_protocol_static('ecoc24', 'L3VRF'), + network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.2', '65001', neighbors=[ + ('192.168.150.1', '65001') + ]), + network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'), + + interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500), + network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), + interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.20.1', 24), enabled=True), + + interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500), + network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), + interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.2', 24), enabled=True), + ] + LOGGER.info('CSGW2 resources_to_set = {:s}'.format(str(csgw2_resources_to_set))) + results_setconfig = drivers['CSGW2'].SetConfig(csgw2_resources_to_set) + LOGGER.info('CSGW2 results_setconfig = {:s}'.format(str(results_setconfig))) csgw1_resources_to_delete = [ network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), @@ -198,13 +198,13 @@ def test_configure(drivers : Dict[str, OpenConfigDriver]): results_deleteconfig = drivers['CSGW1'].DeleteConfig(csgw1_resources_to_delete) LOGGER.info('CSGW1 results_deleteconfig = {:s}'.format(str(results_deleteconfig))) - #csgw2_resources_to_delete = [ - # network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), - # network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), - # #interface('ce1', 0), - # #interface('xe5', 0), - # network_instance('ecoc24', 'L3VRF'), - #] - #LOGGER.info('CSGW2 resources_to_delete = {:s}'.format(str(csgw2_resources_to_delete))) - #results_deleteconfig = drivers['CSGW2'].DeleteConfig(csgw2_resources_to_delete) - #LOGGER.info('CSGW2 results_deleteconfig = {:s}'.format(str(results_deleteconfig))) + csgw2_resources_to_delete = [ + network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0), + network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0), + #interface('ce1', 0), + #interface('xe5', 0), + network_instance('ecoc24', 'L3VRF'), + ] + LOGGER.info('CSGW2 resources_to_delete = {:s}'.format(str(csgw2_resources_to_delete))) + results_deleteconfig = drivers['CSGW2'].DeleteConfig(csgw2_resources_to_delete) + LOGGER.info('CSGW2 results_deleteconfig = {:s}'.format(str(results_deleteconfig))) -- GitLab From 02aade12c4800deaa80e81c6ab3eb8ebf736f3af Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Thu, 9 May 2024 12:57:16 +0000 Subject: [PATCH 29/29] Scripts: - Updated header of test launcher for IPInfusion OcNOS SBI driver --- scripts/run_tests_locally-device-openconfig-ocnos.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run_tests_locally-device-openconfig-ocnos.sh b/scripts/run_tests_locally-device-openconfig-ocnos.sh index 413691b85..60af6768d 100755 --- a/scripts/run_tests_locally-device-openconfig-ocnos.sh +++ b/scripts/run_tests_locally-device-openconfig-ocnos.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# 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. -- GitLab