Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • tfs/controller
1 result
Show changes
Commits on Source (36)
Showing
with 832 additions and 80 deletions
#!/bin/bash
# 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.
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
......@@ -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
......@@ -237,6 +238,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)
......
......@@ -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))
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:
......
......@@ -54,7 +54,7 @@ def create_If_SubIf(data,vendor, DEL):
with tag('enabled'):text('true')
with tag('subinterfaces'):
with tag('subinterface'):
if vendor == 'ADVA':
if vendor is None or vendor == 'ADVA':
with tag('index'): text('0')
with tag('config'):
with tag('index'): text('0')
......@@ -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'])
......
......@@ -64,10 +64,12 @@ 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 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 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')
......@@ -123,14 +125,29 @@ 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('name'): text(parameters['as'])
with tag('global'):
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":
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('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 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'])
......@@ -177,6 +194,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:',parameters['type'])
with tag('interfaces'):
with tag('interface'):
with tag('id'):text(parameters['id'])
......@@ -315,7 +335,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'):
......@@ -326,6 +346,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'])
# 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(
......
......@@ -133,14 +133,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))
'''
'''
......
......@@ -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 'merge'
operation = 'delete' if delete else 'merge' # others
#operation = 'delete' if delete else '' # ipinfusion?
return [
'<config>{:s}</config>'.format(
......
<interfaces xmlns="http://openconfig.net/yang/interfaces"
xmlns:oc-ip="http://openconfig.net/yang/interfaces/ip" >
<interfaces xmlns="http://openconfig.net/yang/interfaces">
<interface{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
<name>{{name}}</name>
{% if operation is defined and operation != 'delete' %}
......@@ -31,17 +30,20 @@
</vlan>
{% endif %}
{% if address_ip is defined %}
<oc-ip:ipv4>
<oc-ip:addresses>
<oc-ip:address>
<oc-ip:ip>{{address_ip}}</oc-ip:ip>
<oc-ip:config>
<oc-ip:ip>{{address_ip}}</oc-ip:ip>
<oc-ip:prefix-length>{{address_prefix}}</oc-ip:prefix-length>
</oc-ip:config>
</oc-ip:address>
</oc-ip:addresses>
</oc-ip:ipv4>
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
<config>
{% if mtu is defined %}<mtu>{{mtu}}</mtu>{% endif%}
</config>
<addresses>
<address>
<ip>{{address_ip}}</ip>
<config>
<ip>{{address_ip}}</ip>
<prefix-length>{{address_prefix}}</prefix-length>
</config>
</address>
</addresses>
</ipv4>
{% endif %}
</subinterface>
</subinterfaces>
......
<network-instances xmlns="http://openconfig.net/yang/network-instance">
<network-instance>
<name>{{name}}</name>
<config>
<name>{{name}}</name>
<type xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types">oc-ni-types:{{type}}</type>
</config>
<interfaces>
<interface{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
<id>{{id}}</id>
......
......@@ -9,15 +9,37 @@
<config>
<identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:{{identifier}}</identifier>
<name>{{protocol_name}}</name>
<enabled>true</enabled>
</config>
{% if identifier=='BGP' %}
<bgp>
<name>{{as}}</name>
<global>
<config>
<as>{{as}}</as>
<router-id>{{router_id}}</router-id>
</config>
</global>
{% if neighbors is defined %}
<neighbors>
{% for neighbor in neighbors %}
<neighbor>
<neighbor-address>{{neighbor['ip_address']}}</neighbor-address>
<afi-safis>
<afi-safi xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">
<afi-safi-name>oc-bgp-types:IPV4_UNICAST</afi-safi-name>
<enabled>true</enabled>
</afi-safi>
</afi-safis>
<config>
<neighbor-address>{{neighbor['ip_address']}}</neighbor-address>
<enabled>true</enabled>
<peer-as>{{as}}</peer-as>
</config>
</neighbor>
{% endfor %}
</neighbors>
{% endif %}
</bgp>
{% endif %}
{% endif %}
......
......@@ -11,6 +11,9 @@
<src-protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:{{src_protocol}}</src-protocol>
<dst-protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:{{dst_protocol}}</dst-protocol>
<address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:{{address_family}}</address-family>
{% if False %}
<dst-instance xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-oc-ni-augments">{{as}}</dst-instance>
{% endif %}
{% if default_import_policy is defined %}<default-import-policy>{{default_import_policy}}</default-import-policy>{% endif %}
</config>
{% endif %}
......
# 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)))
......@@ -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
......
......@@ -14,22 +14,41 @@
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'
DEVICE_SETTINGS_KEY = '/device[{:s}]/settings'
RE_CONFIG_RULE_IF_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$')
MEC_CONSIDERED_FIELDS = ['requestType', 'sessionFilter', 'fixedAllocation', 'allocationDirection', 'fixedBWPriority']
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)
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 = {}
# 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':
......@@ -40,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
......@@ -55,47 +81,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 '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
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
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' 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')
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-' + 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 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),
'address_prefix' : (PREFIX_LENGTH, True),
'sub_interface_index': (0, True),
}
LOGGER.debug(f'BEFORE UPDATE -> device.device_config.config_rules: {service_config_rules}')
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
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)
......
......@@ -184,6 +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
# TODO: check if vlan needs to be 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
......
......@@ -12,24 +12,35 @@
# 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, endpoint_settings : TreeNode, endpoint_acls : List [Tuple]
service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple]
) -> List[Dict]:
if service_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
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'
......@@ -76,6 +87,7 @@ def setup_config_rules(
'name': network_instance_name,
'protocol_name': 'BGP',
'identifier': 'BGP',
'type': 'L3VRF',
'as': bgp_as,
'router_id': router_id,
}),
......@@ -88,7 +100,6 @@ def setup_config_rules(
'protocol_name': 'DIRECTLY_CONNECTED',
}),
#Add STATIC protocol to network instance
json_config_rule_set(
'/network_instance[{:s}]/protocols[STATIC]'.format(network_instance_name), {
......@@ -114,6 +125,7 @@ def setup_config_rules(
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,
......@@ -183,6 +195,7 @@ def setup_config_rules(
}),
]
for res_key, res_value in endpoint_acls:
json_config_rules.append(
{'action': 1, 'acl': res_value}
......@@ -191,23 +204,27 @@ 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, device_settings : TreeNode, endpoint_settings : TreeNode
) -> List[Dict]:
if service_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'
......
# 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 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
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 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
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
......@@ -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, device_settings, endpoint_settings, endpoint_acls)
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, device_settings, endpoint_settings)
if len(json_config_rules) > 0:
del device_obj.device_config.config_rules[:]
......
......@@ -49,7 +49,10 @@ 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):
return [('item', ', '.join(data))]
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))]
......