OpenConfig driver multivendor & ACLs

Device component - OpenConfig Driver:

  • Multivendor functionality
  • Dynamic templates with pyangbind

Service component:

  • Updated L2NM/L3NM - emulated service handlers to support ACL config rules
Edited by Lluis Gifre Renom

Merge request reports

Loading
+288 −0
Changes for src/device/service/drivers/openconfig/templates/ACL/ACL_multivendor.py: 288 added lines, 0 removed lines.
Original line number Diff line number Diff line
# 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.

from yattag import Doc, indent

def acl_set_mng(data, DEL):
    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_desc    = Acl_data['description']
    Acl_entries = Acl_data['entries']
    with tag('acl', xmlns="http://openconfig.net/yang/acl"):
        if DEL == True:
            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)
                    with tag('type'):text(Acl_type)
                    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)
        else:
            with tag('acl-sets'):
                with tag('acl-set'):
                    with tag('name'):text(Acl_name)
                    with tag('type'):text(Acl_type)
                    with tag('config'):
                        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'):
                                            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'):
                                            for key, value in match.items():
                                                if   "src_address"       in key and len(value) != 0:
                                                    with tag('source-address'):text(value)
                                                elif "dst_address"       in key and len(value) != 0:
                                                    with tag('destination-address'):text(value)
                                                elif "protocol"          in key                    :
                                                    with tag('protocol'):text(value)
                                                elif "hop_limit"         in key                    : 
                                                    with tag('hop-limit'):text(value)
                                                elif "dscp"              in key                    : 
                                                    with tag('dscp'):text(value)
                                        with tag('transport'):
                                            for key, value in match.items():
                                                if   "src_port"     in key : 
                                                    with tag('source-port'):text(value)
                                                elif "dst_port"     in key : 
                                                    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'):
                                            for key, value in match.items():
                                                if   "src_address"       in key and len(value) != 0:
                                                    with tag('source-address'):text(value)
                                                elif "dst_address"       in key and len(value) != 0:
                                                    with tag('destination-address'):text(value)
                                                elif "protocol"          in key                    :
                                                    with tag('protocol'):text(value)
                                                elif "hop_limit"         in key                    : 
                                                    with tag('hop-limit'):text(value)
                                                elif "dscp"              in key                    : 
                                                    with tag('dscp'):text(value)
                                    with tag('actions'):
                                        for key, value in action.items():
                                            if "forward_action" in key : 
                                                with tag('forward-action'):text(l_action[value])
                                            elif "log_action"     in key :
                                                with tag('log-action'):text(f_action[value])
    result = indent(
        doc.getvalue(),
        indentation = ' '*2,
        newline = '\r\n'
    )
    return result

def acl_interface(data,vendor, DEL):
    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']]

    with tag('acl', xmlns="http://openconfig.net/yang/acl"):
            with tag('interfaces'):
                with tag('interface'):
                    with tag('id'):text(ID)
                    with tag('config'):
                        with tag('id'):text(ID)
                    with tag('interface-ref'):
                        with tag('config'):
                            with tag('interface'):text(ID)
                            if vendor == 'ADVA': 
                                with tag('subinterface'): text(0)
                            else:
                                with tag('subinterface'): text('subinterface')
                    with tag('ingress-acl-sets'):
                        with tag('ingress-acl-set'):
                            with tag('set-name'):text(Acl_name)
                            with tag('type'):text(Acl_type)
    result = indent(
        doc.getvalue(),
        indentation = ' '*2,
        newline = '\r\n'
    )
    return result

# TESTING
'''
data = {'endpoint_id':{'device_id': {'device_uuid': {'uuid': 'R155'}},'endpoint_uuid':{'uuid':'eth-1/0/21.999'}},
        'rule_set':{'name':"ACL_L4",'type':1,'description':'acl ipv4','entries':[{'sequence_id': 1, 'description': 'IPv4_ACL', 'match': {'dst_address': '172.16.4.4', 'dscp': 0, 'protocol': 6, 'src_address': '172.16.5.5', 'src_port': 0, 'dst_port': 0, 'start_mpls_label': 0, 'end_mpls_label': 0}, 'action': {'forward_action': 1, 'log_action': 1}},
                                                                                 {'sequence_id': 2, 'description': 'L2_ACL', 'match': {'dst_address': '', 'dscp': 0, 'protocol': 0, 'src_address': '', 'src_port': 52, 'dst_port': 950, 'start_mpls_label': 0, 'end_mpls_label': 0}, 'action': {'forward_action': 1, 'log_action': 1}}]}}

print('\t\tACL')
print(acl_set_mng(data, False))
print('\t\tACL')
print(acl_set_mng(data, True))

print('\n\n\t\tInterfaz')
print(acl_interface(data,'ADVA', False))
print('\n\n\t\tInterfaz')
print(acl_interface(data,'ADVA', True))

'''
'''
OLD - VERSION

from .openconfig_acl import openconfig_acl
from pyangbind.lib.serialise import pybindIETFXMLEncoder
from common.tools.grpc.Tools import grpc_message_to_json
import logging
def acl_mgmt(parameters,vendor):                                                                                       # acl templates management
    acl   = []    
    data = grpc_message_to_json(parameters,use_integers_for_enums=True)                                         # acl rule parameters management
    acl.append(acl_set_mgmt(data,vendor))                                                                              # acl_set template
    acl.append(acl_interface(data,vendor))                                                                             # acl interface template
    return acl
    
def acl_set_mgmt(parameters,vendor):
    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    = parameters["rule_set"]
    Acl_name    = Acl_data['name']
    Acl_type    = type[Acl_data['type']]
    Acl_desc    = Acl_data['description']
    Acl_entries = Acl_data['entries']

    # Create an instance of the YANG model
    acl_instance = openconfig_acl()

    # Access the entry container
    acl_set                    = acl_instance.acl.acl_sets.acl_set.add(name = Acl_name, type=Acl_type)
    acl_set.config.name        = Acl_name
    acl_set.config.type        = Acl_type
    acl_set.config.description = Acl_desc
    LOGGER = logging.getLogger(__name__)

    LOGGER.warning("VALORES DE ENTRIES",Acl_entries)

    for entry in Acl_entries:
        ID     = entry['sequence_id']
        desc   = entry['description']
        match  = entry['match']
        action = entry['action']

        acl_entrie = acl_set.acl_entries.acl_entry.add(ID)
        acl_entrie.config.sequence_id = ID
        acl_entrie.config.description= desc
        
        # Configuration per type
        if "L2" in Acl_type:
            for key, value in match.items():
                if   "src_address"     in key and len(value) != 0: acl_entrie.l2.config.source_mac = value
                elif "dst_address"     in key and len(value) != 0: acl_entrie.l2.config.destination_mac = value
                
        elif "IPV4" in Acl_type:
            for key, value in match.items():
                if   "src_address"       in key and len(value) != 0: acl_entrie.ipv4.config.source_address = value
                elif "dst_address"       in key and len(value) != 0: acl_entrie.ipv4.config.destination_address = value
                elif "protocol"          in key                    : acl_entrie.ipv4.config.protocol = value
                elif "hop_limit"         in key                    : acl_entrie.ipv4.config.hop_limit = value
                elif "dscp"              in key                    : acl_entrie.ipv4.config.dscp = value
                    
            for key, value in match.items():
                if   "src_port"     in key : acl_entrie.transport.config.source_port = value
                elif "dst_port"     in key : acl_entrie.transport.config.destination_port = value
                elif "tcp_flags"    in key : acl_entrie.transport.config.tcp_flags = value
                
        elif "IPV6" in Acl_type:
            for key, value in match.items():
                if   "src_address"       in key and len(value) != 0: acl_entrie.ipv6.config.source_address = value
                elif "dst_address"       in key and len(value) != 0: acl_entrie.ipv6.config.destination_address = value
                elif "protocol"          in key                    : acl_entrie.ipv6.config.protocol = value
                elif "hop_limit"         in key                    : acl_entrie.ipv6.config.hop_limit = value
                elif "dscp"              in key                    : acl_entrie.ipv6.config.dscp = value
        
        for key, value in action.items():
            if   "forward_action"        in key : acl_entrie.actions.config.forwarding_action = f_action[value]
            elif "log_action"            in key : acl_entrie.actions.config.log_action = l_action[value]
            
    # Dump the entire instance as RFC 7950 XML
    acl_set = pybindIETFXMLEncoder.serialise(acl_instance)
    acl_set = acl_set.replace('<openconfig-acl xmlns="http://openconfig.net/yang/acl">',"")
    acl_set = acl_set.replace('<acl>','<acl xmlns="http://openconfig.net/yang/acl">')
    acl_set = acl_set.replace('</openconfig-acl>','')

    return(acl_set)

def acl_interface(parameters,vendor):
    type      = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"]
    ID        = parameters['endpoint_id']['endpoint_uuid']['uuid']
    Acl_data  = parameters["rule_set"]
    Acl_name  = Acl_data['name']
    Acl_type  = type[Acl_data['type']]

    # Create an instance of the YANG model
    acl_instance = openconfig_acl()

    # Access the entry container
    interface = acl_instance.acl.interfaces.interface.add(id = ID)

    #Config - Interface
    interface.config.id = ID
    
    #If the Interface parameter is defined [OPTIONAL-PARAMETER]
    interface.interface_ref.config.interface = ID        # Interface parameter 
    
    #TODO: add subinterface management
    if   vendor == "ADVA"   : interface.interface_ref.config.subinterface = '0'    # Subinterface parameter
    elif vendor == "Juniper": interface.interface_ref.config.subinterface = '0'
    else:                     interface.interface_ref.config.subinterface = Acl_data['subinterface']
    # Configuration ingress type
    ingress= interface.ingress_acl_sets.ingress_acl_set.add(set_name = Acl_name, type = Acl_type)
    ingress.config.set_name = Acl_name
    ingress.config.type     = Acl_type

    # Dump the entire instance as RFC 7950 XML
    acl_set = pybindIETFXMLEncoder.serialise(acl_instance)                                      
    acl_set = acl_set.replace('<openconfig-acl xmlns="http://openconfig.net/yang/acl">',"")     
    acl_set = acl_set.replace('<acl>','<acl xmlns="http://openconfig.net/yang/acl">')           
    acl_set = acl_set.replace('</openconfig-acl>','')                                           
    return(acl_set)
'''
 No newline at end of file
+9903 −0

File added.

Preview size limit exceeded, changes collapsed.

+246 −0
Changes for src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py: 246 added lines, 0 removed lines.
Original line number Diff line number Diff line
# 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.

from yattag import Doc, indent
"""
# Method Name: create_If_SubIf
  
# Parameters:
  - Interface_name:     [str]  Variable to set the name of the Interface that will be configured. [Mandatory parameter in all cases].
  - DEL:                [bool] Variable that determines if the template will be for creating (DEL = False) or for deleting (DEL = True) a configuration [Mandatory parameter in all cases].
  - Interface_type:     [str]  Variable that specifies the type of interface, can take the value "l2vlan" or "l3ipvlan" [Only mandatory if DEL = False].
  - SubInterface_Index: [int]  Variable to set the index of the subinterface.[Only mandatory if DEL = False].
  - Description:        [str]  Variable for adding a description to the Interface   [Only mandatory if DEL = False].

# Functionality:
  This method generates the template of an Interface with subinterface, used both for L2 and L3 VPNs.
  This template will be generated for configuring a device, making use of pyangbind. 
  To generate the template the following steps are performed:
  1) Checks if the DEL variable is true (Template for deleting a existent Interface or) or false (Template for creating a new Interface with Subinterface).
  2) Create the template correspondent in each case, assigning the correspondent parameters with their value.
  3) Make the correspondent replaces for the unssuported configurations by pyangbind.
  
# Return:
  [str] The newly generated template according to the specified parameters.
"""
def create_If_SubIf(data,vendor, DEL):
    doc, tag, text = Doc().tagtext()

    with tag('interfaces', xmlns="http://openconfig.net/yang/interfaces"):
        if DEL == True: 
            with tag('interface' ,'xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"'):
                with tag('name'):text(data['name'])
        else:
            with tag('interface'):
                with tag('name'):text(data['name'])
                with tag('config'):
                    with tag('name'):text(data['name'])
                    with tag('type', 'xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type"'):text('ianaift:',data['type'])
                    if 'description' in data:
                        with tag('description'):text(data['description'])
                    if 'mtu' in data:
                        with tag('mtu'):text(data['mtu'])
                    with tag('enabled'):text('true')    
                with tag('subinterfaces'):
                    with tag('subinterface'):
                        if vendor == 'ADVA':
                            with tag('index'): text('0')
                        with tag('config'):
                            with tag('index'): text('0')
                            if vendor == 'ADVA' and len(data['vlan_id'] == 0): 
                                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'):
                                with tag('single-tagged'):
                                    with tag('config'):
                                        with tag('vlan-id'):text(data['vlan_id'])
                        if "l3ipvlan" in data['type']: 
                            with tag('ipv4',  xmlns="http://openconfig.net/yang/interfaces/ip"):
                                with tag('addresses'):
                                    with tag('address'):
                                        with tag('ip'):text(data['address_ip'])
                                        with tag('config'):
                                            with tag('ip'):text(data['address_ip'])
                                            with tag('prefix-length'):text(data['address_prefix'])
    result = indent(
        doc.getvalue(),
        indentation = ' '*2,
        newline = '\r\n'
    )
    return result

#TESTING
'''
data = {'name'          : 'eth-1/0/22.222',
        'type'          : 'l3ipvlan',
        'mtu'           : '3000',
        'index'         : '0',
        'description'   : 'Interfaz con subinterfaz', 
        'vlan_id'       : '222',
        'address_ip'    : '172.16.55.55', 
        'address_prefix': '24'}

print('\n\t\tINTERFAZ - Create')
print(create_If_SubIf(data,'ADVA', False))
print('\n\t\tINTERFAZ - Delete')
print(create_If_SubIf(data,'ADVA', True))
'''


'''
from .openconfig_interfaces import openconfig_interfaces
from pyangbind.lib.serialise import pybindIETFXMLEncoder

"""
# Method Name: set_vlan
  
# Parameters:
  - vendor:     [str]  Variable to set the name of the vendor of the device to be configured. Depending on the vendor, the generated template may vary.
  - vlan_id:    [int]  Variable to set the value of the parameter "vlan id". 
# Functionality:
  This is an auxiliary method that helps in the creation of the Interface template. This method generates the correspondent configuration of the vlan for the interface.
  The method first checks if the parameters vendor and vlan_id are defined. If the vendor is ADVA and vlan_id = 0, an special configuration line is created. 
  Based on the values of the given parameters, the method generates the vlan configuration string.
  
# Return:
  [str] The method returns the generated vlan configuration string, that can be later used in the generation of the Interface template.
"""
def set_vlan(OptionalParams):                                   #[L2/L3] Sets a VLANID and a VENDOR that will be requested for executing the following methods
    verify = str(OptionalParams)                                #Verify transforms the received parameters into a string format for later making verifications and modifications
    
    #If the Vendor parameter is defined [OPTIONAL-PARAMETER]
    if verify.find('vendor')>0:
        Vendor = OptionalParams['vendor']  

    #If the VlanID parameter is defined [OPTIONAL-PARAMETER]
    if verify.find('vlan_id')>0:
        VlanID = OptionalParams['vlan_id'] 
        if VlanID == 0 and "ADVA" in Vendor: vlan = '  <untagged-allowed xmlns="http://www.advaoptical.com/cim/adva-dnos-oc-interfaces">true</untagged-allowed></config> \n          </config>\n        </subinterface>'
        elif VlanID != 0:                    vlan = '</config>\n          <vlan xmlns="http://openconfig.net/yang/vlan"> \n\t    <match> \n\t      <single-tagged> \n \t\t<config>\n \t\t  <vlan-id>'+str(VlanID)+'</vlan-id> \n \t\t</config> \n \t      </single-tagged> \n \t    </match> \n \t  </vlan> \n         </subinterface>'
        else:                                vlan = '</subinterface>\n          </config>'
    else:                                    vlan = '</subinterface>\n          </config>'   
    return vlan

"""
# Method Name: set_ip
  
# Parameters:
  - address_ip:     [str]  Variable that sets the value of the ip address.
  - address_prefix: [int]  Variable that specifies the prefix of the given ip address. 
# Functionality:
  This is an auxiliary method that helps in the creation of the Interface template. This method generates the correspondent configuration of the ip address for the interface.
  The method first checks if the parameter address_ip is defined. If it is defined, then it creates the configuration string that will be used later in the Interface template.
  
# Return:
  [str] The method returns the generated ip configuration string, that can be later used in the generation of the Interface template.
"""
def set_ip(OptionalParams):                                         #[L3] Sets a IPAddress that will be requested for executing the following L3VPN methods
    verify = str(OptionalParams)                                    # Verify transforms the received parameters into a string format for later making verifications and modifications
    
    #If the Address_ip parameter is defined [OPTIONAL-PARAMETER]
    if verify.find('address_ip')>0:
        IP      = OptionalParams['address_ip']  
        Prefix  = OptionalParams['address_prefix']
        address = '  <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip"> \n\t    <addresses> \n\t      <address> \n \t\t<ip>'+IP+'</ip> \n \t\t<config>\n \t\t  <ip>'+IP+'</ip> \n \t\t  <prefix-length>'+str(Prefix)+'</prefix-length> \n \t\t</config> \n \t      </address> \n \t    </addresses> \n \t  </ipv4>  \n \t</subinterface>'
    else:
        address ='</subinterface>'
    return address

"""
# Method Name: create_If_SubIf
  
# Parameters:
  - Interface_name:     [str]  Variable to set the name of the Interface that will be configured. [Mandatory parameter in all cases].
  - DEL:                [bool] Variable that determines if the template will be for creating (DEL = False) or for deleting (DEL = True) a configuration [Mandatory parameter in all cases].
  - Interface_type:     [str]  Variable that specifies the type of interface, can take the value "l2vlan" or "l3ipvlan" [Only mandatory if DEL = False].
  - SubInterface_Index: [int]  Variable to set the index of the subinterface.[Only mandatory if DEL = False].
  - Description:        [str]  Variable for adding a description to the Interface   [Only mandatory if DEL = False].

# Functionality:
  This method generates the template of an Interface with subinterface, used both for L2 and L3 VPNs.
  This template will be generated for configuring a device, making use of pyangbind. 
  To generate the template the following steps are performed:
  1) Checks if the DEL variable is true (Template for deleting a existent Interface or) or false (Template for creating a new Interface with Subinterface).
  2) Create the template correspondent in each case, assigning the correspondent parameters with their value.
  3) Make the correspondent replaces for the unssuported configurations by pyangbind.
  
# Return:
  [str] The newly generated template according to the specified parameters.
"""
def create_If_SubIf(parameters):                                #[L2/L3] Creates a Interface with a Subinterface as described in /interface[{:s}]/subinterface[{:d}]
    Interface_name     = parameters['name']
    DEL                = parameters['DEL']                      # If the parameters DEL is set to "TRUE" that will mean that is for making a DELETE, ELSE is for creating
    verify             = str(parameters)                        # Verify transforms the received parameters into a string format for later making verifications and modifications

    #Create an instance of the YANG model
    InterfaceInstance = openconfig_interfaces()

    if DEL==True:                                               #DELETE OPERATION
        # Access the entry container
        InterfaceInstance_set = InterfaceInstance.interfaces.interface.add(name = Interface_name)
        
        # Dump the entire instance as RFC 7950 XML
        InterfaceInstance_set = pybindIETFXMLEncoder.serialise(InterfaceInstance)

        #Replace for setting the "Delete" Operation
        InterfaceInstance_set = InterfaceInstance_set.replace('<interface>','<interface xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete">')

        #Generic Replaces
        InterfaceInstance_set = InterfaceInstance_set.replace('<openconfig-interfaces xmlns="http://openconfig.net/yang/interfaces">',"")
        InterfaceInstance_set = InterfaceInstance_set.replace('<interfaces>','<interfaces xmlns="http://openconfig.net/yang/interfaces">')
        InterfaceInstance_set = InterfaceInstance_set.replace('</openconfig-interfaces>','')

    else:                                                       #MERGE OPERATION
        Interface_type     = parameters['type']
        SubInterface_Index = parameters["index"]

        #Access the entry container
        InterfaceInstance_set = InterfaceInstance.interfaces.interface.add(name = Interface_name)
        InterfaceInstance_set.config.name = Interface_name
        InterfaceInstance_set.config.enabled = True

        #SubIntefaces-Config
        SubInterfaceInstance              = InterfaceInstance_set.subinterfaces.subinterface.add(index = SubInterface_Index)
        SubInterfaceInstance.config.index = SubInterface_Index

        #If the description parameter is defined [OPTIONAL-PARAMETER]
        if verify.find('description')>0:
            Description = parameters['description']   
            if  len(Description) != 0: SubInterfaceInstance.config.description = Description   #If description parameter has a value

        #If the MTU parameter is defined [OPTIONAL-PARAMETER]
        if verify.find('mtu')>0:
            MTU = parameters['mtu']    
            if  MTU != 0: InterfaceInstance_set.config.mtu = MTU                       #If MTU parameter has a value

        #Dump the entire instance as RFC 750 XML
        InterfaceInstance_set = pybindIETFXMLEncoder.serialise(InterfaceInstance)

        #Replaces for adding the Interface Type
        InterfaceInstance_set = InterfaceInstance_set.replace('</config>\n      <subinterfaces>','  <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:'+Interface_type+'</type>\n      </config>\n      <subinterfaces>')
        vlan = set_vlan(parameters)
        InterfaceInstance_set = InterfaceInstance_set.replace('</config>\n        </subinterface>',vlan)
        
        if "l3ipvlan" in Interface_type: 
            ip = set_ip(parameters)
            InterfaceInstance_set = InterfaceInstance_set.replace('</subinterface>',ip)

        #Generic Replaces
        InterfaceInstance_set = InterfaceInstance_set.replace('<openconfig-interfaces xmlns="http://openconfig.net/yang/interfaces">',"")
        InterfaceInstance_set = InterfaceInstance_set.replace('<interfaces>','<interfaces xmlns="http://openconfig.net/yang/interfaces">')
        InterfaceInstance_set = InterfaceInstance_set.replace('</openconfig-interfaces>','')

    return (InterfaceInstance_set) 
  
'''
+839 −0

File added.

Preview size limit exceeded, changes collapsed.

+274 −0
Changes for src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py: 274 added lines, 0 removed lines.
Original line number Diff line number Diff line
# 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.

from yattag import Doc, indent
"""
# Method Name: create_rp_statement
  
# Parameters:
  - Policy_Name:        [str]  Variable that determines the name of the Routing Policy [Mandatory parameter in all cases].
  - DEL:                [bool] Variable that determines if the template will be for creating (DEL = False) or for deleting (DEL = True) a configuration [Mandatory parameter in all cases].
  - Statement_Name:     [str]  Variable that determines the name of the Routing Policy Statement, which is a unique statement within the policy [Only mandatory if DEL = False].
  - Policy_Result:      [str]  Variable to set if the policy is for accepting (ACCEPT ROUTE) or rejecting (REJECT ROUTE). [Only mandatory if DEL = False].
  - ExtCommSetName:     [str]  Variable to set the name of the extended community set in the context of BGP policy conditions. [Only mandatory if DEL = False].
  
# Functionality:
  This method generates the template of a routing policy statement to configure in a device, making use of pyangbind. 
  To generate the template the following steps are performed:
  1) Checks if the DEL variable is true (Template for deleting a policy statement) or false (Template for creating a policy statement).
  2) Create the template correspondent in each case, assigning the correspondent parameters with their value.
  3) Make the correspondent replaces for the unssuported configurations by pyangbind.
  
# Return:
  [str] The newly generated template according to the specified parameters.
"""
def create_rp_statement(data, DEL):
    doc, tag, text = Doc().tagtext()

    RP_policy_name          = data['policy_name']
    RP_statement_name       = data['statement_name']
    RP_policy_result        = data['policy_result']
    RP_ext_comm_set_name    = data['ext_community_set_name']
    

    with tag('routing-policy', xmlns="http://openconfig.net/yang/routing-policy"):
        if DEL == True: 
            with tag('policy-definitions'):
                with tag('policy-definition' ,'xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"'):
                    with tag('name'):text(RP_policy_name)
        else:
            with tag('policy-definitions'):
                with tag('policy-definition'):
                    with tag('name'):text(RP_policy_name)
                    with tag('config'):
                        with tag('name'):text(RP_policy_name)
                    with tag('statements'):
                        with tag('statement'):
                            with tag('name'):text(RP_statement_name)
                            with tag('config'):
                                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')
                                with tag('bgp-conditions', xmlns="http://openconfig.net/yang/bgp-policy"):
                                    with tag('config'):
                                        with tag('ext-community-set'):text(RP_ext_comm_set_name)
                            with tag('actions'):
                                with tag('config'):
                                    with tag('policy-result'):text(RP_policy_result)
    result = indent(
        doc.getvalue(),
        indentation = ' '*2,
        newline = '\r\n'
    )
    return result

"""
# Method Name: create_rp_def
  
# Parameters:
  - ExtCommSetName:     [str]  Variable to set the name of the extended community set in the context of BGP policy conditions. [Mandatory parameter in all cases].
  - DEL:                [bool] Variable that determines if the template will be for creating (DEL = False) or for deleting (DEL = True) a configuration [Mandatory parameter in all cases].
  - ExtCommMember:      [str]  Variable that represents an individual member or value within an Extended Community [Only mandatory if DEL = False].
   
# Functionality:
  This method generates the template of a routing policy defined sets, which are objects defined and used within a routing policy statement.
  This template will be generated for being configured in a device, making use of pyangbind. 
  To generate the template the following steps are performed:
  1) Checks if the DEL variable is true (Template for deleting a routing policy defined set) or false (Template for creating a routing policy defined set).
  2) Create the template correspondent in each case, assigning the correspondent parameters with their value.
  3) Make the correspondent replaces for the unssuported configurations by pyangbind.
  
# Return:
  [str] The newly generated template according to the specified parameters.
"""
def create_rp_def(data, DEL):
    doc, tag, text = Doc().tagtext()
   
    RP_ext_comm_set_name    = data['ext_community_set_name']
    RP_ext_comm_member      = data['ext_community_member']
    
    with tag('routing-policy', xmlns="http://openconfig.net/yang/routing-policy"):
        if DEL == True: 
            with tag('defined-sets'):
                with tag('bgp-defined-sets', xmlns="http://openconfig.net/yang/bgp-policy"):
                    with tag('ext-community-sets'):
                        with tag('ext-community-set' ,'xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"'):
                            with tag('ext-community-set-name'):text(RP_ext_comm_set_name)
        else:
            with tag('defined-sets'):
                with tag('bgp-defined-sets', xmlns="http://openconfig.net/yang/bgp-policy"):
                    with tag('ext-community-sets'):
                        with tag('ext-community-set'):
                            with tag('ext-community-set-name'):text(RP_ext_comm_set_name)
                            with tag('config'):
                                with tag('ext-community-set-name'):text(RP_ext_comm_set_name)
                                with tag('ext-community-member'):text(RP_ext_comm_member)
    result = indent(
        doc.getvalue(),
        indentation = ' '*2,
        newline = '\r\n'
    )
    return result

#TESTING
'''
data_1 =    {"ext_community_set_name"   : "set_srv_101_a", 
             "policy_name"              : "srv_101_a", 
             "policy_result"            : "ACCEPT_ROUTE", 
             "statement_name"           : "stm_srv_101_a"}

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('\nRouting Policy Statement - DELETE\n')
print(rp_statement(data_1, True))

print('\nRouting Policy Defined Set - CREATE\n')
print(rp_defined_set(data_2, False))
print('\nRouting Policy Defined Set - DELETE\n')
print(rp_defined_set(data_2, True))
'''

'''
from .openconfig_routing_policy import openconfig_routing_policy
from pyangbind.lib.serialise import pybindIETFXMLEncoder

"""
# Method Name: create_rp_statement
  
# Parameters:
  - Policy_Name:        [str]  Variable that determines the name of the Routing Policy [Mandatory parameter in all cases].
  - DEL:                [bool] Variable that determines if the template will be for creating (DEL = False) or for deleting (DEL = True) a configuration [Mandatory parameter in all cases].
  - Statement_Name:     [str]  Variable that determines the name of the Routing Policy Statement, which is a unique statement within the policy [Only mandatory if DEL = False].
  - Policy_Result:      [str]  Variable to set if the policy is for accepting (ACCEPT ROUTE) or rejecting (REJECT ROUTE). [Only mandatory if DEL = False].
  - ExtCommSetName:     [str]  Variable to set the name of the extended community set in the context of BGP policy conditions. [Only mandatory if DEL = False].
  
# Functionality:
  This method generates the template of a routing policy statement to configure in a device, making use of pyangbind. 
  To generate the template the following steps are performed:
  1) Checks if the DEL variable is true (Template for deleting a policy statement) or false (Template for creating a policy statement).
  2) Create the template correspondent in each case, assigning the correspondent parameters with their value.
  3) Make the correspondent replaces for the unssuported configurations by pyangbind.
  
# Return:
  [str] The newly generated template according to the specified parameters.
"""
def create_rp_statement(parameters):                        #[L3] Creates a Routing Policy Statement
    Policy_Name      = parameters['policy_name']   
    DEL              = parameters['DEL']                            #If the parameter DEL is set to "TRUE" that will mean that is for making a DELETE, ELSE is for creating
           
    #Create an instance of the YANG model
    RoutingPolicy_Instance = openconfig_routing_policy()

    if DEL == True:
        #Set the Name of the Routing Policy
        Set_RoutingPolicy = RoutingPolicy_Instance.routing_policy.policy_definitions.policy_definition.add(name=Policy_Name)

        #Dump the entire instance as RFC 750 XML
        RoutingInstance_set = pybindIETFXMLEncoder.serialise(RoutingPolicy_Instance)

        RoutingInstance_set = RoutingInstance_set.replace('<openconfig-routing-policy xmlns="http://openconfig.net/yang/routing-policy">',"")
        RoutingInstance_set = RoutingInstance_set.replace('<routing-policy>','<routing-policy xmlns="http://openconfig.net/yang/routing-policy">')

        #Operation Delete [Replace]
        RoutingInstance_set = RoutingInstance_set.replace('<policy-definition>','<policy-definition xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete">')
        RoutingInstance_set = RoutingInstance_set.replace('</openconfig-routing-policy>','')   

    else:
        Statement_Name   = parameters['statement_name']             
        Policy_Result    = parameters['policy_result']
        ExtCommSetName   = parameters['ext_community_set_name']

        #Access the entry container

        #Set the Name of the Routing Policy
        Set_RoutingPolicy = RoutingPolicy_Instance.routing_policy.policy_definitions.policy_definition.add(name=Policy_Name)
        Set_RoutingPolicy.config.name = Policy_Name

        #Configure the Statement of the Routing Policy 
        Set_Statement_RoutingPolicy = Set_RoutingPolicy.statements.statement.add(name=Statement_Name)
        Set_Statement_RoutingPolicy.config.name = Statement_Name
        Set_Statement_RoutingPolicy.conditions.config.install_protocol_eq = "DIRECTLY_CONNECTED"
        Set_Statement_RoutingPolicy.actions.config.policy_result = Policy_Result
        
        #Dump the entire instance as RFC 750 XML
        RoutingInstance_set = pybindIETFXMLEncoder.serialise(RoutingPolicy_Instance)

        #Policy-Definition - Statements - BGP-Conditions [Replace]
        RoutingInstance_set = RoutingInstance_set.replace('</conditions>','  <bgp-conditions xmlns="http://openconfig.net/yang/bgp-policy"> \n\t\t <config> \n\t    \
        <ext-community-set>'+ ExtCommSetName +'</ext-community-set> \n\t\t </config> \n\t      </bgp-conditions>\n\t    </conditions>')

        #Generic Replaces
        RoutingInstance_set = RoutingInstance_set.replace('<openconfig-routing-policy xmlns="http://openconfig.net/yang/routing-policy">',"")
        RoutingInstance_set = RoutingInstance_set.replace('<routing-policy>','<routing-policy xmlns="http://openconfig.net/yang/routing-policy">')
        RoutingInstance_set = RoutingInstance_set.replace('</openconfig-routing-policy>','') 

    return (RoutingInstance_set)

"""
# Method Name: create_rp_def
  
# Parameters:
  - ExtCommSetName:     [str]  Variable to set the name of the extended community set in the context of BGP policy conditions. [Mandatory parameter in all cases].
  - DEL:                [bool] Variable that determines if the template will be for creating (DEL = False) or for deleting (DEL = True) a configuration [Mandatory parameter in all cases].
  - ExtCommMember:      [str]  Variable that represents an individual member or value within an Extended Community [Only mandatory if DEL = False].
   
# Functionality:
  This method generates the template of a routing policy defined sets, which are objects defined and used within a routing policy statement.
  This template will be generated for being configured in a device, making use of pyangbind. 
  To generate the template the following steps are performed:
  1) Checks if the DEL variable is true (Template for deleting a routing policy defined set) or false (Template for creating a routing policy defined set).
  2) Create the template correspondent in each case, assigning the correspondent parameters with their value.
  3) Make the correspondent replaces for the unssuported configurations by pyangbind.
  
# Return:
  [str] The newly generated template according to the specified parameters.
"""
def create_rp_def(parameters):                              #[L3] Creates a Routing Policy - Defined Sets [ '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]' ]
    ExtCommSetName   = parameters['ext_community_set_name']
    DEL              = parameters['DEL']                            #If the parameter DEL is set to "TRUE" that will mean that is for making a DELETE, ELSE is for creating             
                                                                    
    #Create an instance of the YANG model
    RoutingPolicy_Instance = openconfig_routing_policy()

    if DEL == True:                                                                                 #Delete operation
        #Dump the entire instance as RFC 750 XML
        RoutingInstance_set = pybindIETFXMLEncoder.serialise(RoutingPolicy_Instance)

        #BGP-Defined-Sets [Replace]
        RoutingInstance_set = RoutingInstance_set.replace('<openconfig-routing-policy xmlns="http://openconfig.net/yang/routing-policy"/>',
        '<routing-policy xmlns="http://openconfig.net/yang/routing-policy"> \n   <defined-sets> \n      <bgp-defined-sets xmlns="http://openconfig.net/yang/bgp-policy">\
        \n\t <ext-community-sets> \n\t   <ext-community-set xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"> \n      \
        <ext-community-set-name>'+ExtCommSetName+'</ext-community-set-name> \n\t   </ext-community-set> \n\t </ext-community-sets> \
         \n      </bgp-defined-sets> \n   </defined-sets> \n </routing-policy>')

    else:                                                                                            #Merge operation
        #Add new requested parameter - ext_community_member
        ExtCommMember    = parameters['ext_community_member'] 

        #Dump the entire instance as RFC 750 XML
        RoutingInstance_set = pybindIETFXMLEncoder.serialise(RoutingPolicy_Instance)

        #BGP-Defined-Sets [Replace]
        RoutingInstance_set = RoutingInstance_set.replace('<openconfig-routing-policy xmlns="http://openconfig.net/yang/routing-policy"/>',
        '<routing-policy xmlns="http://openconfig.net/yang/routing-policy"> \n   <defined-sets> \n     <bgp-defined-sets xmlns="http://openconfig.net/yang/bgp-policy">\
        \n\t<ext-community-sets> \n\t  <ext-community-set> \n\t   <ext-community-set-name>'+ExtCommSetName+'</ext-community-set-name> \n\t     <config>     \
        \n\t\t<ext-community-set-name>'+ ExtCommSetName +'</ext-community-set-name> \n\t\t<ext-community-member>'+ExtCommMember+'</ext-community-member> \n     \
        </config>  \n\t   </ext-community-set> \n\t </ext-community-sets> \n      </bgp-defined-sets> \n   </defined-sets> \n </routing-policy>')

    return (RoutingInstance_set)
'''
Loading
Loading