Skip to content

Commit

Permalink
feat: IOS-XE QoS to OC - Fixes and refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
jrouliez committed Feb 9, 2024
2 parents cbe3dd1 + f9189b3 commit e666b7b
Show file tree
Hide file tree
Showing 53 changed files with 5,388 additions and 389 deletions.
18 changes: 1 addition & 17 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:

# actual configuration of semantic-release is done in .releaserc
- name: Install dependencies
run: npm install semantic-release && npm install @semantic-release/exec conventional-changelog-conventionalcommits @semantic-release/release-notes-generator semantic-release-pypi
run: npm install semantic-release && npm install @semantic-release/exec @semantic-release/git conventional-changelog-conventionalcommits @semantic-release/release-notes-generator semantic-release-pypi

- name: Set up Python
uses: actions/setup-python@v2
Expand All @@ -40,19 +40,3 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYPI_TOKEN: ${{ secrets.CISCOPS_PYPI_TOKEN }}
run: npx semantic-release

- name: Commit version change
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git commit -m "Update version" -a
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true

- name: Push changes
run: |
git push origin HEAD:main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true
19 changes: 6 additions & 13 deletions .releaserc
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,14 @@
"preset": "conventionalcommits"
}],
"@semantic-release/release-notes-generator",
[
"@semantic-release/exec",
{
"prepareCmd": "sed -i 's|<package-version>.*</package-version>|<package-version>${nextRelease.version}</package-version>|g' mdd/package-meta-data.xml"
}
],
[
"semantic-release-pypi",
{
"repoUrl": "https://upload.pypi.org/legacy/"
}
],
"@semantic-release/github",
["@semantic-release/exec", {
"publishCmd": "/bin/true"
"prepareCmd": "sed -i 's|<package-version>.*</package-version>|<package-version>${nextRelease.version}</package-version>|' mdd/package-meta-data.xml",
"publishCmd": "/bin/true"
}],
["@semantic-release/git", {
"assets": "mdd/package-meta-data.xml",
"message": "chore(release): Update NSO package version to ${nextRelease.version} [skip ci]"
}]
]
}
2 changes: 1 addition & 1 deletion mdd/package-meta-data.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<ncs-package xmlns="http://tail-f.com/ns/ncs-packages">
<name>mdd</name>
<package-version>2.80.0</package-version>
<package-version>2.82.0</package-version>
<description>Translates OpenConfig models to NSO devices and augments OpenConfig models with custom configurations.</description>
<ncs-min-version>5.5</ncs-min-version>
<component>
Expand Down
3 changes: 2 additions & 1 deletion mdd/python/translation/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def get_interface_type_and_number(interface: str) -> Tuple[str, str]:
interface_name = rt.group(0)
rn = re.search(r'[0-9]+(\/[0-9]+)*', interface)
interface_number = rn.group(0)
interface_number = interface_number.replace("{", "").replace("}", "")
interface_name = interface_name.replace('-', '_')

return interface_name, interface_number
Expand All @@ -49,7 +50,7 @@ def get_interface_type_number_and_subinterface(interface: str) -> Tuple[str, str
interface_name = rt.group(0)
rn = re.search(r'[0-9]+(\/[0-9]+)*(\.[0-9]+)*', interface)
interface_number = rn.group(0)

interface_number = interface_number.replace("{", "").replace("}", "")
return interface_name, interface_number

def prefix_to_network_and_mask(prefix: str) -> str:
Expand Down
4 changes: 4 additions & 0 deletions mdd/python/translation/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
from ncs.application import Application, Service

from translation.openconfig_xe.xe_main import check_xe_features
from translation.openconfig_xe.xe_main import clean_xe_cdb
from translation.openconfig_xr.xr_main import check_xr_features
from translation.openconfig_xr.xr_main import clean_xr_cdb
from translation.openconfig_nx.nx_main import check_nx_features

from translation.common import NsoProps
Expand All @@ -23,8 +25,10 @@ def cb_create(self, tctx: TransCtxRef, root: Root, service: ListElement, proplis

# Each NED may have a template and will have python processing code
if 'cisco-ios-cli' in nso_props.root.devices.device[nso_props.device_name].device_type.cli.ned_id:
clean_xe_cdb(nso_props)
check_xe_features(self, nso_props)
elif 'cisco-iosxr-cli' in nso_props.root.devices.device[nso_props.device_name].device_type.cli.ned_id:
clean_xr_cdb(nso_props)
check_xr_features(self, nso_props)
elif 'cisco-nx-cli' in nso_props.root.devices.device[nso_props.device_name].device_type.cli.ned_id:
check_nx_features(self, nso_props)
Expand Down
12 changes: 0 additions & 12 deletions mdd/python/translation/openconfig_xe/xe_acls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@
r'(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5][0-9]{4}|[0-9]{1,4})\.\.(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5][0-9]{4}|[0-9]{1,4})')


def acl_remove(device, service_acl):
# remove any instances of ACL
if device.ios__ip.access_list.extended.ext_named_acl.exists(service_acl.name):
del device.ios__ip.access_list.extended.ext_named_acl[service_acl.name]
if device.ios__ip.access_list.standard.std_named_acl.exists(service_acl.name):
del device.ios__ip.access_list.standard.std_named_acl[service_acl.name]
if service_acl.name.isdigit() and device.ios__access_list.access_list.exists(int(service_acl.name)):
del device.ios__access_list.access_list[int(service_acl.name)]


def xe_acls_program_service(self, nso_props) -> None:
"""
Program service for xe NED features
Expand Down Expand Up @@ -84,7 +74,6 @@ def xe_acls_program_service(self, nso_props) -> None:
device = nso_props.root.devices.device[nso_props.device_name].config
for service_acl in nso_props.service.oc_acl__acl.acl_sets.acl_set:
if service_acl.type == 'oc-acl:ACL_IPV4':
acl_remove(device, service_acl)
device.ios__ip.access_list.extended.ext_named_acl.create(service_acl.name)

acl = device.ios__ip.access_list.extended.ext_named_acl[service_acl.name]
Expand Down Expand Up @@ -167,7 +156,6 @@ def xe_acls_program_service(self, nso_props) -> None:
acl.ext_access_list_rule.create(i)

if service_acl.type == 'oc-acl-ext:ACL_IPV4_STANDARD':
acl_remove(device, service_acl)
device.ios__ip.access_list.standard.std_named_acl.create(service_acl.name)
acl = device.ios__ip.access_list.standard.std_named_acl[service_acl.name]
rules_oc_config = list() # {'10 permit any'}
Expand Down
11 changes: 5 additions & 6 deletions mdd/python/translation/openconfig_xe/xe_bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@ def xe_bgp_global_program_service(self, nso_props, service_protocol, network_ins
service_bgp_global = service_protocol.bgp.oc_netinst__global

if network_instance_type == 'oc-ni-types:DEFAULT_INSTANCE':
if not nso_props.root.devices.device[nso_props.device_name].config.ios__router.bgp.exists(
service_bgp_global.config.oc_netinst__as):
nso_props.root.devices.device[nso_props.device_name].config.ios__router.bgp.create(
device_bgp_cbd = nso_props.root.devices.device[nso_props.device_name].config.ios__router.bgp.create(
service_bgp_global.config.oc_netinst__as)
device_bgp_cbd = nso_props.root.devices.device[nso_props.device_name].config.ios__router.bgp[
service_bgp_global.config.oc_netinst__as]
if service_bgp_global.config.router_id:
device_bgp_cbd.bgp.router_id = service_bgp_global.config.router_id
if service_bgp_global.config.log_neighbor_changes:
Expand Down Expand Up @@ -66,7 +62,8 @@ def xe_bgp_global_program_service(self, nso_props, service_protocol, network_ins
device_bgp_cbd.bgp.default.ipv4_unicast = False # If using AFI_SAFI turn off BGP ipv4 default
for afi_safi_service in service_bgp_global.afi_safis.afi_safi:
if network_instance_type == 'oc-ni-types:DEFAULT_INSTANCE' and afi_safi_service.config.enabled:
if afi_safi_service.config.afi_safi_name == 'oc-bgp-types:IPV4_UNICAST':
if afi_safi_service.config.afi_safi_name == 'oc-bgp-types:IPV4_UNICAST' or \
afi_safi_service.config.afi_safi_name == 'oc-bgp-types:IPV4_LABELED_UNICAST':
if not device_bgp_cbd.address_family.ipv4.exists('unicast'):
device_bgp_cbd.address_family.ipv4.create('unicast')
if afi_safi_service.ipv4_unicast.config.send_default_route:
Expand Down Expand Up @@ -348,6 +345,8 @@ def xe_bgp_neighbors_program_service(self, nso_props, service_protocol, network_
apply_policy(neighbor_object_cdb, afi_safi_service)
if service_bgp_neighbor.config.send_community and service_bgp_neighbor.config.send_community != 'NONE':
send_community(neighbor_object_cdb, service_bgp_neighbor)
if afi_safi_service.config.afi_safi_name == 'oc-bgp-types:IPV4_LABELED_UNICAST':
neighbor_object_cdb.send_label.create()
elif afi_safi_service.config.afi_safi_name == 'oc-bgp-types:L3VPN_IPV4_UNICAST':
if not device_bgp_cbd.address_family.vpnv4['unicast'].neighbor.exists(
service_bgp_neighbor.neighbor_address):
Expand Down
1 change: 1 addition & 0 deletions mdd/python/translation/openconfig_xe/xe_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ def xe_configure_hsrp_v1(self, interface_cdb: ncs.maagic.ListElement, service_ip
"""
Configures ipv4 hsrp
"""
interface_cdb.standby.standby_list.delete()
for a in service_ipv4.addresses.address:
if hasattr(a, 'hsrp'):
if a.hsrp.hsrp_group:
Expand Down
41 changes: 41 additions & 0 deletions mdd/python/translation/openconfig_xe/xe_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,47 @@ def check_xe_features(oc_self, nso_props) -> None:
# OpenConfig System
xe_system_program_service(oc_self, nso_props)

<<<<<<< HEAD
# OpenConfig QoS
if nso_props.service.oc_qos__qos:
xe_qos_program_service(oc_self, nso_props)
=======

def clean_xe_cdb(nso_props) -> None:
"""
Remove CDB lists to be repopulated with OC configs.
"""
device = nso_props.root.devices.device[nso_props.device_name].config

device.ios__access_list.access_list.delete()
device.ios__ip.access_list.extended.ext_named_acl.delete()
device.ios__ip.access_list.standard.std_named_acl.delete()
device.ios__ip.arp.inspection.vlan.delete()
device.ios__ip.as_path.access_list.delete()
device.ios__ip.community_list.expanded.delete()
device.ios__ip.community_list.standard.delete()
device.ios__ip.dhcp.snooping.vlan.delete()
device.ios__ip.extcommunity_list.standard.no_mode_list.delete()
device.ios__ip.http.secure_ciphersuite.delete()
device.ios__ip.name_server.vrf.delete()
device.ios__ip.name_server.name_server_list.delete()
device.ios__ip.nat.inside.source.list_vrf.list.delete()
device.ios__ip.nat.inside.source.list.delete()
device.ios__ip.nat.pool.delete()
device.ios__ip.prefix_list.prefixes.delete()
device.ios__ip.route.ip_route_forwarding_list.delete()
device.ios__ip.route.ip_route_interface_list.delete()
device.ios__ip.route.vrf.delete()
device.ios__ip.ssh.server.algorithm.encryption.delete()
device.ios__logging.host.ipv4_vrf.delete()
device.ios__logging.host.ipv4.delete()
device.ios__logging.source_interface.delete()
device.ios__ntp.peer.peer_list.delete()
device.ios__ntp.server.peer_list.delete()
device.ios__ntp.server.vrf.delete()
device.ios__ntp.peer.vrf.delete()
device.ios__ntp.authentication_key.delete()
device.ios__ntp.trusted_key.delete()
device.ios__router.bgp.delete()
device.ios__router.ospf.delete()
>>>>>>> main
27 changes: 16 additions & 11 deletions mdd/python/translation/openconfig_xe/xe_network_instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,27 @@ def xe_configure_vrfs(self, nso_props, network_instance) -> None:
rt_export_config = set([rt for rt in network_instance.config.route_targets_export])
rt_export_config.update(export_rts_policy)

# Get import route-targets from the CDB
rt_import_cdb = set([rt for rt in nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
network_instance.name].route_target.ios__import])
# Get export route-targets from the CDB
rt_export_cdb = set([rt for rt in nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
network_instance.name].route_target.export])
# # Get import route-targets from the CDB
# rt_import_cdb = set([rt for rt in nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
# network_instance.name].route_target.ios__import])
# # Get export route-targets from the CDB
# rt_export_cdb = set([rt for rt in nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
# network_instance.name].route_target.export])

# Find route targets to create in CDB
rt_import_to_cdb = rt_import_config.difference(rt_import_cdb)
rt_export_to_cdb = rt_export_config.difference(rt_export_cdb)
# # Find route targets to create in CDB
# rt_import_to_cdb = rt_import_config.difference(rt_import_cdb)
# rt_export_to_cdb = rt_export_config.difference(rt_export_cdb)

# Add Route Targets to CDB
for rt in rt_import_to_cdb:
nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
network_instance.name].route_target.ios__import.delete()
for rt in rt_import_config:
nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
network_instance.name].route_target.ios__import.create(rt)
for rt in rt_export_to_cdb:

nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
network_instance.name].route_target.export.delete()
for rt in rt_export_config:
nso_props.root.devices.device[nso_props.device_name].config.ios__vrf.definition[
network_instance.name].route_target.export.create(rt)

Expand Down
17 changes: 8 additions & 9 deletions mdd/python/translation/openconfig_xe/xe_ospf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ def xe_ospf_program_service(self, nso_props, service_protocol, network_instance_
"""
self.log.info(f'{nso_props.device_name} OSPF')
# Process
if not nso_props.root.devices.device[nso_props.device_name].config.ios__router.ospf.exists(service_protocol.name):
nso_props.root.devices.device[nso_props.device_name].config.ios__router.ospf.create(service_protocol.name)
device_ospf_cbd = nso_props.root.devices.device[nso_props.device_name].config.ios__router.ospf[
service_protocol.name]
device_ospf_cbd = nso_props.root.devices.device[nso_props.device_name].config.ios__router.ospf.create(service_protocol.name)
# Process VRF
if network_instance_type == 'oc-ni-types:L3VRF':
device_ospf_cbd.vrf = vrf_name
Expand Down Expand Up @@ -111,6 +108,7 @@ def xe_ospf_program_service(self, nso_props, service_protocol, network_instance_
raise ValueError('XE OSPF throttle timers spf needs values for spf-start, spf-hold, and spf-max-wait')
# area
if len(service_protocol.ospfv2.areas.area) > 0:
device_ospf_cbd.network.delete()
for service_area in service_protocol.ospfv2.areas.area:
if len(service_area.interfaces.interface) > 0:
for service_interface in service_area.interfaces.interface:
Expand All @@ -126,7 +124,6 @@ def xe_ospf_program_service(self, nso_props, service_protocol, network_instance_
class_attribute = getattr(nso_props.root.devices.device[nso_props.device_name].config.ios__interface,
interface_type)
interface_cdb = class_attribute[interface_number]
# router ospf network statement
create_area_network_statement(nso_props, service_interface, device_ospf_cbd, service_area)
# interface ospf network type
if service_interface.config.network_type:
Expand Down Expand Up @@ -180,10 +177,12 @@ def xe_ospf_program_service(self, nso_props, service_protocol, network_instance_
del interface_cdb.ip.ospf.authentication
interface_cdb.ip.ospf.authentication.create()
interface_cdb.ip.ospf.authentication.message_digest.create()
for authentication_key in service_interface.oc_ospfv2_ext__authentication.md5_authentication_keys.md5_authentication_key:
interface_cdb.ip.ospf.message_digest_key.create(authentication_key.config.key_id)
interface_cdb.ip.ospf.message_digest_key[
authentication_key.config.key_id].md5.secret = authentication_key.config.key
if len(service_interface.oc_ospfv2_ext__authentication.md5_authentication_keys.md5_authentication_key) > 0:
interface_cdb.ip.ospf.message_digest_key.delete()
for authentication_key in service_interface.oc_ospfv2_ext__authentication.md5_authentication_keys.md5_authentication_key:
interface_cdb.ip.ospf.message_digest_key.create(authentication_key.config.key_id)
interface_cdb.ip.ospf.message_digest_key[
authentication_key.config.key_id].md5.secret = authentication_key.config.key
else:
raise ValueError("OSPF MD5 authentication must have at least one key configured.")
elif service_interface.oc_ospfv2_ext__authentication.config.authentication_type == "SIMPLE":
Expand Down
Loading

0 comments on commit e666b7b

Please sign in to comment.