diff --git a/src/device/service/Tools.py b/src/device/service/Tools.py index 8fc1b7a57e513aef22e8e01de3425115350ae110..b2b206471e07b654e5339f81db632699ae8b95df 100644 --- a/src/device/service/Tools.py +++ b/src/device/service/Tools.py @@ -288,7 +288,7 @@ def compute_rules_to_add_delete( acl_ruleset_name = config_rule.acl.rule_set.name # get the acl name ACL_KEY_TEMPLATE = '/device[{:s}]/endpoint[{:s}]/acl_ruleset[{:s}]' key_or_path = ACL_KEY_TEMPLATE.format(device_uuid, endpoint_uuid, acl_ruleset_name) - context_config_rules[key_or_path] = config_rule.acl # get the resource value of the acl + context_config_rules[key_or_path] = grpc_message_to_json(config_rule.acl) # get the resource value of the acl request_config_rules = [] for config_rule in request.device_config.config_rules: @@ -304,7 +304,7 @@ def compute_rules_to_add_delete( ACL_KEY_TEMPLATE = '/device[{:s}]/endpoint[{:s}]/acl_ruleset[{:s}]' key_or_path = ACL_KEY_TEMPLATE.format(device_uuid, endpoint_uuid, acl_ruleset_name) request_config_rules.append(( - config_rule.action, key_or_path, config_rule.acl + config_rule.action, key_or_path, grpc_message_to_json(config_rule.acl) )) resources_to_set : List[Tuple[str, Any]] = [] # key, value diff --git a/src/device/service/drivers/openconfig/templates/ACL/ACL_multivendor.py b/src/device/service/drivers/openconfig/templates/ACL/ACL_multivendor.py index 7b18fa24a1a42a7a5349185c93326b99f13eaedc..91d05d3d18f1b19374a38f9149dc7bd6b7c518b6 100755 --- a/src/device/service/drivers/openconfig/templates/ACL/ACL_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/ACL/ACL_multivendor.py @@ -14,20 +14,38 @@ from yattag import Doc, indent -def acl_set_mng(data, DEL): +RULE_TYPE_MAPPING = { + 'ACLRULETYPE_UNDEFINED': 'ACL_UNDEFINED', + 'ACLRULETYPE_IPV4' : 'ACL_IPV4', + 'ACLRULETYPE_IPV6' : 'ACL_IPV6', + 'ACLRULETYPE_L2' : 'ACL_L2', + 'ACLRULETYPE_MPLS' : 'ACL_MPLS', + 'ACLRULETYPE_MIXED' : 'ACL_MIXED', +} + +FORWARDING_ACTION_MAPPING = { + 'ACLFORWARDINGACTION_UNDEFINED': 'UNDEFINED', + 'ACLFORWARDINGACTION_DROP' : 'DROP', + 'ACLFORWARDINGACTION_ACCEPT' : 'ACCEPT', + 'ACLFORWARDINGACTION_REJECT' : 'REJECT', +} + +LOG_ACTION_MAPPING = { + 'ACLLOGACTION_UNDEFINED': 'UNDEFINED', + 'ACLLOGACTION_NOLOG' : 'LOG_NONE', + 'ACLLOGACTION_SYSLOG' : 'LOG_SYSLOG', +} + +def acl_set_mng(data,vendor, delete): doc, tag, text = Doc().tagtext() - type = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"] - f_action = ["UNDEFINED", "DROP","ACCEPT","REJECT"] - l_action = ["UNDEFINED", "LOG_NONE","LOG_SYSLOG"] - Acl_data = data["rule_set"] Acl_name = Acl_data['name'] - Acl_type = type[Acl_data['type']] + Acl_type = RULE_TYPE_MAPPING[Acl_data['type']] Acl_desc = Acl_data['description'] Acl_entries = Acl_data['entries'] with tag('acl', xmlns="http://openconfig.net/yang/acl"): - if DEL == True: + if delete: with tag('acl-sets' ,'xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"'): with tag('acl-set'): with tag('name'):text(Acl_name) @@ -49,27 +67,29 @@ def acl_set_mng(data, DEL): with tag('name'): text(Acl_name) with tag('type'): text(Acl_type) with tag('description'):text(Acl_desc) - with tag('acl-entries'): - for entry in Acl_entries: - ID = entry['sequence_id'] - desc = entry['description'] - match = entry['match'] - action = entry['action'] - with tag('acl-entry'): - with tag('sequence-id'):text(ID) - with tag('config'): - with tag('acl-entry'): text(ID) - with tag('description'): text(desc) - # Configuration per type - if "L2" in Acl_type: - with tag('l2'): + with tag('acl-entries'): + for entry in Acl_entries: + ID = entry['sequence_id'] + desc = entry['description'] + match = entry['match'] + action = entry['action'] + with tag('acl-entry'): + with tag('sequence-id'):text(ID) + with tag('config'): + with tag('sequence-id'): text(ID) + with tag('description'): text(desc) + # Configuration per type + if "L2" in Acl_type: + with tag('l2'): + with tag('config'): for key, value in match.items(): if "src_address" in key and len(value) != 0: with tag('source-mac'):text(value) elif "dst_address" in key and len(value) != 0: with tag('destination-mac'):text(value) - elif "IPV4" in Acl_type: - with tag('ipv4'): + elif "IPV4" in Acl_type: + with tag('ipv4'): + with tag('config'): for key, value in match.items(): if "src_address" in key and len(value) != 0: with tag('source-address'):text(value) @@ -81,7 +101,8 @@ def acl_set_mng(data, DEL): with tag('hop-limit'):text(value) elif "dscp" in key : with tag('dscp'):text(value) - with tag('transport'): + with tag('transport'): + with tag('config'): for key, value in match.items(): if "src_port" in key : with tag('source-port'):text(value) @@ -89,8 +110,9 @@ def acl_set_mng(data, DEL): with tag('destination-port'):text(value) elif "tcp_flags" in key : with tag('tcp-flags'):text(value) - elif "IPV6" in Acl_type: - with tag('ipv6'): + elif "IPV6" in Acl_type: + with tag('ipv6'): + with tag('config'): for key, value in match.items(): if "src_address" in key and len(value) != 0: with tag('source-address'):text(value) @@ -102,12 +124,13 @@ def acl_set_mng(data, DEL): with tag('hop-limit'):text(value) elif "dscp" in key : with tag('dscp'):text(value) - with tag('actions'): + with tag('actions'): + with tag('config'): for key, value in action.items(): if "forward_action" in key : - with tag('forward-action'):text(l_action[value]) + with tag('forwarding-action'):text(FORWARDING_ACTION_MAPPING[value]) elif "log_action" in key : - with tag('log-action'):text(f_action[value]) + with tag('log-action'):text(LOG_ACTION_MAPPING[value]) result = indent( doc.getvalue(), indentation = ' '*2, @@ -115,14 +138,14 @@ def acl_set_mng(data, DEL): ) return result -def acl_interface(data,vendor, DEL): + +def acl_interface(data,vendor, delete): doc, tag, text = Doc().tagtext() - type = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"] ID = data['endpoint_id']['endpoint_uuid']['uuid'] Acl_data = data["rule_set"] Acl_name = Acl_data['name'] - Acl_type = type[Acl_data['type']] + Acl_type = RULE_TYPE_MAPPING[Acl_data['type']] with tag('acl', xmlns="http://openconfig.net/yang/acl"): with tag('interfaces'): @@ -141,6 +164,9 @@ def acl_interface(data,vendor, DEL): with tag('ingress-acl-set'): with tag('set-name'):text(Acl_name) with tag('type'):text(Acl_type) + with tag('config'): + with tag('set-name'):text(Acl_name) + with tag('type'):text(Acl_type) result = indent( doc.getvalue(), indentation = ' '*2, @@ -148,6 +174,13 @@ def acl_interface(data,vendor, DEL): ) return result + +def acl_mgmt(parameters,vendor,delete): + acl = [] + acl.append(acl_set_mng( parameters,vendor,delete)) + acl.append(acl_interface(parameters,vendor,delete)) + return acl + # TESTING ''' data = {'endpoint_id':{'device_id': {'device_uuid': {'uuid': 'R155'}},'endpoint_uuid':{'uuid':'eth-1/0/21.999'}}, @@ -285,4 +318,4 @@ def acl_interface(parameters,vendor): acl_set = acl_set.replace('','') acl_set = acl_set.replace('','') return(acl_set) -''' \ No newline at end of file +''' diff --git a/src/device/service/drivers/openconfig/templates/Tools.py b/src/device/service/drivers/openconfig/templates/Tools.py index 054907aefb4fea694b68dc5976cd6ab1651278ec..79bebef5179b3464c33ce7fa0663b0cd35a51fc0 100644 --- a/src/device/service/drivers/openconfig/templates/Tools.py +++ b/src/device/service/drivers/openconfig/templates/Tools.py @@ -15,7 +15,7 @@ import json import lxml.etree as ET from typing import Collection, Dict, Any -from .ACL.ACL_multivendor import acl_set_mng +from .ACL.ACL_multivendor import acl_mgmt from .VPN.Network_instance_multivendor import create_NI, associate_virtual_circuit, associate_RP_to_NI, add_protocol_NI, create_table_conns, associate_If_to_NI from .VPN.Interfaces_multivendor import create_If_SubIf from .VPN.Routing_policy import create_rp_def, create_rp_statement @@ -84,6 +84,6 @@ def generate_templates(resource_key: str, resource_value: str, delete: bool,vend result_templates.append(create_rp_statement(data, delete)) else: if "acl_ruleset" in resource_key: # acl rules management - result_templates.extend(acl_set_mng(resource_value, delete)) + result_templates.extend(acl_mgmt(resource_value,vendor, delete)) return result_templates \ No newline at end of file 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 2327b849c3ae3208222052307c9cc2da3ced787a..d6f72ee6556fd5ca5dc08c5349a41e0db736bd4d 100644 --- a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py +++ b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py @@ -58,7 +58,7 @@ def create_If_SubIf(data,vendor, DEL): with tag('index'): text('0') with tag('config'): with tag('index'): text('0') - if vendor == 'ADVA' and len(data['vlan_id'] == 0): + if vendor == 'ADVA' and not 'vlan_id'in data: with tag('untagged-allowed', 'xmlns="http://www.advaoptical.com/cim/adva-dnos-oc-interfaces"'):text('true') with tag('vlan', xmlns="http://openconfig.net/yang/vlan"): with tag('match'): diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py index c6621773b8b45230358eebff2c60b95aacdda31f..329552a914e478f0e927bd6f04fce6725bef0b5e 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py @@ -12,11 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -import itertools, json, re +import itertools, json, logging, re from typing import Dict, List, Optional, Tuple from common.proto.context_pb2 import ConfigRule +from common.tools.grpc.Tools import grpc_message_to_json_string from common.tools.object_factory.ConfigRule import json_config_rule_set +LOGGER = logging.getLogger(__name__) + SETTINGS_RULE_NAME = '/settings' DEVICE_SETTINGS = re.compile(r'\/device\[([^\]]+)\]\/settings') @@ -76,6 +79,10 @@ def compose_device_config_rules( config_rules : List, subservice_config_rules : List, path_hops : List, device_name_mapping : Dict[str, str], endpoint_name_mapping : Dict[Tuple[str, str], str] ) -> None: + LOGGER.debug('[compose_device_config_rules] begin') + + LOGGER.debug('[compose_device_config_rules] device_name_mapping={:s}'.format(str(device_name_mapping))) + LOGGER.debug('[compose_device_config_rules] endpoint_name_mapping={:s}'.format(str(endpoint_name_mapping))) devices_traversed = set() endpoints_traversed = set() @@ -85,29 +92,65 @@ def compose_device_config_rules( endpoints_traversed.add((device_uuid_or_name, path_hop['ingress_ep'])) endpoints_traversed.add((device_uuid_or_name, path_hop['egress_ep'])) - for config_rule in config_rules: - if config_rule.WhichOneof('config_rule') != 'custom': continue + LOGGER.debug('[compose_device_config_rules] devices_traversed={:s}'.format(str(devices_traversed))) + LOGGER.debug('[compose_device_config_rules] endpoints_traversed={:s}'.format(str(endpoints_traversed))) - match = DEVICE_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] + for config_rule in config_rules: + LOGGER.debug('[compose_device_config_rules] processing config_rule: {:s}'.format( + grpc_message_to_json_string(config_rule))) + + if config_rule.WhichOneof('config_rule') == 'acl': + LOGGER.debug('[compose_device_config_rules] is acl') + endpoint_id = config_rule.acl.endpoint_id + device_uuid_or_name = endpoint_id.device_id.device_uuid.uuid + LOGGER.debug('[compose_device_config_rules] device_uuid_or_name={:s}'.format(str(device_uuid_or_name))) + device_name_or_uuid = device_name_mapping.get(device_uuid_or_name, device_uuid_or_name) + LOGGER.debug('[compose_device_config_rules] device_name_or_uuid={:s}'.format(str(device_name_or_uuid))) device_keys = {device_uuid_or_name, device_name_or_uuid} - if len(device_keys.intersection(devices_traversed)) == 0: continue - subservice_config_rules.append(config_rule) - - match = ENDPOINT_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_uuid = endpoint_id.endpoint_uuid.uuid + LOGGER.debug('[compose_device_config_rules] endpoint_uuid={:s}'.format(str(endpoint_uuid))) + # given endpoint uuids link 'eth-1/0/20.533', remove last part after the '.' + endpoint_uuid_or_name = (endpoint_uuid[::-1].split('.', maxsplit=1)[-1])[::-1] + LOGGER.debug('[compose_device_config_rules] endpoint_uuid_or_name={:s}'.format(str(endpoint_uuid_or_name))) 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 + + LOGGER.debug('[compose_device_config_rules] adding acl config rule') subservice_config_rules.append(config_rule) + + elif config_rule.WhichOneof('config_rule') == 'custom': + LOGGER.debug('[compose_device_config_rules] is custom') + + match = DEVICE_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} + + if len(device_keys.intersection(devices_traversed)) == 0: continue + subservice_config_rules.append(config_rule) + + match = ENDPOINT_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 + subservice_config_rules.append(config_rule) + else: + continue + + LOGGER.debug('[compose_device_config_rules] end') diff --git a/src/service/service/service_handlers/l2nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l2nm_openconfig/ConfigRules.py index 69daa057fbf66984cfb56d18c6d2b949e0a4bd5b..cedb39ebf151ef229d374150619ef4486c03a240 100644 --- a/src/service/service/service_handlers/l2nm_openconfig/ConfigRules.py +++ b/src/service/service/service_handlers/l2nm_openconfig/ConfigRules.py @@ -40,16 +40,17 @@ def setup_config_rules( #address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 remote_router = json_endpoint_settings.get('remote_router', '5.5.5.5') # '5.5.5.5' network_instance_name = json_endpoint_settings.get('ni_name', 'ELAN-AC:{:s}'.format(str(vlan_id))) #ELAN-AC:1 - virtual_circuit_id = json_endpoint_settings.get('vc_id', '111' ) # '111' + # virtual_circuit_id = json_endpoint_settings.get('vc_id', '111' ) # '111' connection_point = json_endpoint_settings.get('conn_point', '1' ) # '111' #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','') - if_cirid_name = '{:s}.{:s}'.format(endpoint_name, vlan_id) + if_cirid_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) connection_point_id = 'VC-{:s}'.format(str(connection_point)) #Provisionalmente comentado, en principio se deberia usar asi #connection_point_id = 'VC-1' #Uso provisional + virtual_circuit_id = vlan_id json_config_rules = [ @@ -96,14 +97,14 @@ def teardown_config_rules( #router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' #route_distinguisher = json_endpoint_settings.get('route_distinguisher', '0:0' ) # '60001:801' sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 - #vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 + 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 #remote_router = json_endpoint_settings.get('remote_router', '0.0.0.0') # '5.5.5.5' - circuit_id = json_endpoint_settings.get('circuit_id', '000' ) # '111' + #circuit_id = json_endpoint_settings.get('circuit_id', '000' ) # '111' - if_cirid_name = '{:s}.{:s}'.format(endpoint_name, str(circuit_id)) - network_instance_name = 'ELAN-AC:{:s}'.format(str(circuit_id)) + if_cirid_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) + network_instance_name = 'ELAN-AC:{:s}'.format(str(vlan_id)) connection_point_id = 'VC-1' json_config_rules = [