diff options
-rw-r--r-- | data/templates/frr/rip.frr.tmpl | 224 | ||||
-rw-r--r-- | interface-definitions/protocols-rip.xml.in | 15 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_protocols_rip.py | 4 | ||||
-rwxr-xr-x | src/conf_mode/protocols_rip.py | 323 |
4 files changed, 159 insertions, 407 deletions
diff --git a/data/templates/frr/rip.frr.tmpl b/data/templates/frr/rip.frr.tmpl index 83df4e203..eeaee7199 100644 --- a/data/templates/frr/rip.frr.tmpl +++ b/data/templates/frr/rip.frr.tmpl @@ -1,143 +1,89 @@ ! -{% if rip_conf %} router rip -{% if old_default_distance %} -no distance {{old_default_distance}} +{% if default_information is defined and default_information.originate is defined %} + default-information originate +{% endif %} +{% if default_metric is defined and default_metric is not none %} + default-metric {{ default_metric }} +{% endif %} +{% if default_distance is defined and default_distance is not none %} + distance {{ default_distance }} +{% endif %} +{% if network_distance is defined and network_distance is not none %} +{% for network, network_config in network_distance.items() %} +{% if network_config.distance is defined and network_config.distance is not none %} + distance {{ network_config.distance }} {{ network }} +{% endif %} +{% endfor %} +{% endif %} +{% if neighbor is defined and neighbor is not none %} +{% for address in neighbor %} + neighbor {{ address }} +{% endfor %} +{% endif %} +{% if network is defined and network is not none %} +{% for prefix in network %} + network {{ prefix }} +{% endfor %} +{% endif %} +{% if interface is defined and interface is not none %} +{% for ifname in interface %} + network {{ ifname }} +{% endfor %} +{% endif %} +{% if passive_interface is defined and passive_interface is not none %} +{% for ifname in passive_interface %} + passive-interface {{ ifname }} +{% endfor %} +{% endif %} +{% if redistribute is defined and redistribute is not none %} +{% for protocol, protocol_config in redistribute.items() %} + redistribute {{ protocol }} {{ 'metric ' + protocol_config.metric if protocol_config.metric is defined }} {{ 'route-map ' + protocol_config.route_map if protocol_config.route_map is defined }} +{% endfor %} +{% endif %} +{% if route is defined and route is not none %} +{% for prefix in route %} + route {{ prefix }} +{% endfor %} +{% endif %} +{# timers have default values #} + timers basic {{ timers['update'] }} {{ timers.timeout }} {{ timers.garbage_collection }} +{% if distribute_list is defined and distribute_list is not none %} +{% if distribute_list.access_list is defined and distribute_list.access_list is not none %} +{% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} + distribute-list {{ distribute_list.access_list.in }} in +{% endif %} +{% if distribute_list.access_list.out is defined and distribute_list.access_list.out is not none %} + distribute-list {{ distribute_list.access_list.out }} out +{% endif %} +{% endif %} +{% if distribute_list.interface is defined and distribute_list.interface is not none %} +{% for interface, interface_config in distribute_list.interface.items() %} +{% if interface_config.access_list is defined and interface_config.access_list is not none %} +{% if interface_config.access_list.in is defined and interface_config.access_list.in is not none %} + distribute-list {{ interface_config.access_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.access_list.out is defined and interface_config.access_list.out is not none %} + distribute-list {{ interface_config.access_list.out }} out {{ interface }} +{% endif %} +{% endif %} +{% if interface_config.prefix_list is defined and interface_config.prefix_list is not none %} +{% if interface_config.prefix_list.in is defined and interface_config.prefix_list.in is not none %} + distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.prefix_list.out is defined and interface_config.prefix_list.out is not none %} + distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% if distribute_list.prefix_list is defined and distribute_list.prefix_list is not none %} +{% if distribute_list.prefix_list.in is defined and distribute_list.prefix_list.in is not none %} +distribute-list prefix {{ distribute_list.prefix_list.in }} in +{% endif %} +{% if distribute_list.prefix_list.out is defined and distribute_list.prefix_list.out is not none %} +distribute-list prefix {{ distribute_list.prefix_list.out }} out +{% endif %} +{% endif %} {% endif %} -{% if default_distance %} -distance {{default_distance}} -{% endif %} -{% if old_default_originate %} -no default-information originate -{% endif %} -{% if default_originate %} -default-information originate -{% endif %} -{% if old_rip.default_metric %} -no default-metric {{old_rip.default_metric}} -{% endif %} -{% if rip.default_metric %} -default-metric {{rip.default_metric}} -{% endif %} -{% for protocol in old_rip.redist %} -{% if old_rip.redist[protocol]['metric'] and old_rip.redist[protocol]['route_map'] %} -no redistribute {{protocol}} metric {{rip.redist[protocol]['metric']}} route-map {{rip.redist[protocol]['route_map']}} -{% elif old_rip.redist[protocol]['metric'] %} -no redistribute {{protocol}} metric {{old_rip.redist[protocol]['metric']}} -{% elif old_rip.redist[protocol]['route_map'] %} -no redistribute {{protocol}} route-map {{old_rip.redist[protocol]['route_map']}} -{% else %} -no redistribute {{protocol}} -{% endif %} -{% endfor %} -{% for protocol in rip.redist %} -{% if rip.redist[protocol]['metric'] and rip.redist[protocol]['route_map'] %} -redistribute {{protocol}} metric {{rip.redist[protocol]['metric']}} route-map {{rip.redist[protocol]['route_map']}} -{% elif rip.redist[protocol]['metric'] %} -redistribute {{protocol}} metric {{rip.redist[protocol]['metric']}} -{% elif rip.redist[protocol]['route_map'] %} -redistribute {{protocol}} route-map {{rip.redist[protocol]['route_map']}} -{% else %} -redistribute {{protocol}} -{% endif %} -{% endfor %} -{% for iface in old_rip.distribute %} -{% if old_rip.distribute[iface].iface_access_list_in %} -no distribute-list {{old_rip.distribute[iface].iface_access_list_in}} in {{iface}} -{% endif %} -{% if old_rip.distribute[iface].iface_access_list_out %} -no distribute-list {{old_rip.distribute[iface].iface_access_list_out}} out {{iface}} -{% endif %} -{% if old_rip.distribute[iface].iface_prefix_list_in %} -no distribute-list prefix {{old_rip.distribute[iface].iface_prefix_list_in}} in {{iface}} -{% endif %} -{% if old_rip.distribute[iface].iface_prefix_list_out %} -no distribute-list prefix {{old_rip.distribute[iface].iface_prefix_list_out}} out {{iface}} -{% endif %} -{% endfor %} -{% for iface in rip.distribute %} -{% if rip.distribute[iface].iface_access_list_in %} -distribute-list {{rip.distribute[iface].iface_access_list_in}} in {{iface}} -{% endif %} -{% if rip.distribute[iface].iface_access_list_out %} -distribute-list {{rip.distribute[iface].iface_access_list_out}} out {{iface}} -{% endif %} -{% if rip.distribute[iface].iface_prefix_list_in %} -distribute-list prefix {{rip.distribute[iface].iface_prefix_list_in}} in {{iface}} -{% endif %} -{% if rip.distribute[iface].iface_prefix_list_out %} -distribute-list prefix {{rip.distribute[iface].iface_prefix_list_out}} out {{iface}} -{% endif %} -{% endfor %} -{% if old_rip.dist_acl_in %} -no distribute-list {{old_rip.dist_acl_in}} in -{% endif %} -{% if rip.dist_acl_in %} -distribute-list {{rip.dist_acl_in}} in -{% endif %} -{% if old_rip.dist_acl_out %} -no distribute-list {{old_rip.dist_acl_out}} out -{% endif %} -{% if rip.dist_acl_out %} -distribute-list {{rip.dist_acl_out}} out -{% endif %} -{% if old_rip.dist_prfx_in %} -no distribute-list prefix {{old_rip.dist_prfx_in}} in -{% endif %} -{% if rip.dist_prfx_in %} -distribute-list prefix {{rip.dist_prfx_in}} in -{% endif %} -{% if old_rip.dist_prfx_out %} -no distribute-list prefix {{old_rip.dist_prfx_out}} out -{% endif %} -{% if rip.dist_prfx_out %} -distribute-list prefix {{rip.dist_prfx_out}} out -{% endif %} -{% for network in old_rip.networks %} -no network {{network}} -{% endfor %} -{% for network in rip.networks %} -network {{network}} -{% endfor %} -{% for iface in old_rip.ifaces %} -no network {{iface}} -{% endfor %} -{% for iface in rip.ifaces %} -network {{iface}} -{% endfor %} -{% for neighbor in old_rip.neighbors %} -no neighbor {{neighbor}} -{% endfor %} -{% for neighbor in rip.neighbors %} -neighbor {{neighbor}} -{% endfor %} -{% for net in rip.net_distance %} -{% if rip.net_distance[net].access_list and rip.net_distance[net].distance %} -distance {{rip.net_distance[net].distance}} {{net}} {{rip.net_distance[net].access_list}} -{% else %} -distance {{rip.net_distance[net].distance}} {{net}} -{% endif %} -{% endfor %} -{% for passive_iface in old_rip.passive_iface %} -no passive-interface {{passive_iface}} -{% endfor %} -{% for passive_iface in rip.passive_iface %} -passive-interface {{passive_iface}} -{% endfor %} -{% for route in old_rip.route %} -no route {{route}} -{% endfor %} -{% for route in rip.route %} -route {{route}} -{% endfor %} -{% if old_rip.timer_update or old_rip.timer_timeout or old_rip.timer_garbage %} -no timers basic -{% endif %} -{% if rip.timer_update or rip.timer_timeout or rip.timer_garbage %} -timers basic {{rip.timer_update}} {{rip.timer_timeout}} {{rip.timer_garbage}} -{% endif %} -! -{% else %} -no router rip ! -{% endif %} diff --git a/interface-definitions/protocols-rip.xml.in b/interface-definitions/protocols-rip.xml.in index c91d2c66b..2587e94c3 100644 --- a/interface-definitions/protocols-rip.xml.in +++ b/interface-definitions/protocols-rip.xml.in @@ -203,39 +203,42 @@ <children> <leafNode name="garbage-collection"> <properties> - <help>Garbage collection timer</help> + <help>Garbage collection timer (default: 120)</help> <valueHelp> <format>u32:5-2147483647</format> - <description>Garbage colletion time (default 120)</description> + <description>Garbage colletion time</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-2147483647"/> </constraint> </properties> + <defaultValue>120</defaultValue> </leafNode> <leafNode name="timeout"> <properties> - <help>Routing information timeout timer</help> + <help>Routing information timeout timer (default: 180)</help> <valueHelp> <format>u32:5-2147483647</format> - <description>Routing information timeout timer (default 180)</description> + <description>Routing information timeout timer</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-2147483647"/> </constraint> </properties> + <defaultValue>180</defaultValue> </leafNode> <leafNode name="update"> <properties> - <help>Routing table update timer</help> + <help>Routing table update timer (default: 30)</help> <valueHelp> <format>u32:5-2147483647</format> - <description>Routing table update timer in seconds (default 30)</description> + <description>Routing table update timer in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-2147483647"/> </constraint> </properties> + <defaultValue>30</defaultValue> </leafNode> </children> </node> diff --git a/smoketest/scripts/cli/test_protocols_rip.py b/smoketest/scripts/cli/test_protocols_rip.py index 56c975d7a..1bd069638 100755 --- a/smoketest/scripts/cli/test_protocols_rip.py +++ b/smoketest/scripts/cli/test_protocols_rip.py @@ -91,6 +91,8 @@ class TestProtocolsRIP(unittest.TestCase): self.session.set(base_path + ['interface', interface]) self.session.set(base_path + ['distribute-list', 'interface', interface, 'access-list', 'in', acl_in]) self.session.set(base_path + ['distribute-list', 'interface', interface, 'access-list', 'out', acl_out]) + self.session.set(base_path + ['distribute-list', 'interface', interface, 'prefix-list', 'in', prefix_list_in]) + self.session.set(base_path + ['distribute-list', 'interface', interface, 'prefix-list', 'out', prefix_list_out]) for neighbor in neighbors: self.session.set(base_path + ['neighbor', neighbor]) for network in networks: @@ -121,6 +123,8 @@ class TestProtocolsRIP(unittest.TestCase): self.assertIn(f' network {interface}', frrconfig) self.assertIn(f' distribute-list {acl_in} in {interface}', frrconfig) self.assertIn(f' distribute-list {acl_out} out {interface}', frrconfig) + self.assertIn(f' distribute-list prefix {prefix_list_in} in {interface}', frrconfig) + self.assertIn(f' distribute-list prefix {prefix_list_out} out {interface}', frrconfig) for neighbor in neighbors: self.assertIn(f' neighbor {neighbor}', frrconfig) for network in networks: diff --git a/src/conf_mode/protocols_rip.py b/src/conf_mode/protocols_rip.py index 8ddd705f2..978781d78 100755 --- a/src/conf_mode/protocols_rip.py +++ b/src/conf_mode/protocols_rip.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2021 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -18,15 +18,27 @@ import os from sys import exit -from vyos import ConfigError from vyos.config import Config +from vyos.configdict import dict_merge from vyos.util import call +from vyos.xml import defaults from vyos.template import render - +from vyos.template import render_to_string +from vyos import ConfigError +from vyos import frr from vyos import airbag airbag.enable() -config_file = r'/tmp/ripd.frr' +config_file = r'/tmp/rip.frr' +frr_daemon = 'ripd' + +DEBUG = os.path.exists('/tmp/rip.debug') +if DEBUG: + import logging + lg = logging.getLogger("vyos.frr") + lg.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + lg.addHandler(ch) def get_config(config=None): if config: @@ -34,277 +46,65 @@ def get_config(config=None): else: conf = Config() base = ['protocols', 'rip'] - rip_conf = { - 'rip_conf' : False, - 'default_distance' : [], - 'default_originate' : False, - 'old_rip' : { - 'default_metric' : [], - 'distribute' : {}, - 'neighbors' : {}, - 'networks' : {}, - 'net_distance' : {}, - 'passive_iface' : {}, - 'redist' : {}, - 'route' : {}, - 'ifaces' : {}, - 'timer_garbage' : 120, - 'timer_timeout' : 180, - 'timer_update' : 30 - }, - 'rip' : { - 'default_metric' : None, - 'distribute' : {}, - 'neighbors' : {}, - 'networks' : {}, - 'net_distance' : {}, - 'passive_iface' : {}, - 'redist' : {}, - 'route' : {}, - 'ifaces' : {}, - 'timer_garbage' : 120, - 'timer_timeout' : 180, - 'timer_update' : 30 - } - } - - if not (conf.exists(base) or conf.exists_effective(base)): - return None - - if conf.exists(base): - rip_conf['rip_conf'] = True - - conf.set_level(base) - - # Get default distance - if conf.exists_effective('default-distance'): - rip_conf['old_default_distance'] = conf.return_effective_value('default-distance') - - if conf.exists('default-distance'): - rip_conf['default_distance'] = conf.return_value('default-distance') - - # Get default information originate (originate default route) - if conf.exists_effective('default-information originate'): - rip_conf['old_default_originate'] = True - - if conf.exists('default-information originate'): - rip_conf['default_originate'] = True - - # Get default-metric - if conf.exists_effective('default-metric'): - rip_conf['old_rip']['default_metric'] = conf.return_effective_value('default-metric') - - if conf.exists('default-metric'): - rip_conf['rip']['default_metric'] = conf.return_value('default-metric') - - # Get distribute list interface old_rip - for dist_iface in conf.list_effective_nodes('distribute-list interface'): - # Set level 'distribute-list interface ethX' - conf.set_level(base + ['distribute-list', 'interface', dist_iface]) - rip_conf['rip']['distribute'].update({ - dist_iface : { - 'iface_access_list_in': conf.return_effective_value('access-list in'.format(dist_iface)), - 'iface_access_list_out': conf.return_effective_value('access-list out'.format(dist_iface)), - 'iface_prefix_list_in': conf.return_effective_value('prefix-list in'.format(dist_iface)), - 'iface_prefix_list_out': conf.return_effective_value('prefix-list out'.format(dist_iface)) - } - }) - - # Access-list in old_rip - if conf.exists_effective('access-list in'.format(dist_iface)): - rip_conf['old_rip']['iface_access_list_in'] = conf.return_effective_value('access-list in'.format(dist_iface)) - # Access-list out old_rip - if conf.exists_effective('access-list out'.format(dist_iface)): - rip_conf['old_rip']['iface_access_list_out'] = conf.return_effective_value('access-list out'.format(dist_iface)) - # Prefix-list in old_rip - if conf.exists_effective('prefix-list in'.format(dist_iface)): - rip_conf['old_rip']['iface_prefix_list_in'] = conf.return_effective_value('prefix-list in'.format(dist_iface)) - # Prefix-list out old_rip - if conf.exists_effective('prefix-list out'.format(dist_iface)): - rip_conf['old_rip']['iface_prefix_list_out'] = conf.return_effective_value('prefix-list out'.format(dist_iface)) - - conf.set_level(base) - - # Get distribute list interface - for dist_iface in conf.list_nodes('distribute-list interface'): - # Set level 'distribute-list interface ethX' - conf.set_level(base + ['distribute-list', 'interface', dist_iface]) - rip_conf['rip']['distribute'].update({ - dist_iface : { - 'iface_access_list_in': conf.return_value('access-list in'.format(dist_iface)), - 'iface_access_list_out': conf.return_value('access-list out'.format(dist_iface)), - 'iface_prefix_list_in': conf.return_value('prefix-list in'.format(dist_iface)), - 'iface_prefix_list_out': conf.return_value('prefix-list out'.format(dist_iface)) - } - }) - - # Access-list in - if conf.exists('access-list in'.format(dist_iface)): - rip_conf['rip']['iface_access_list_in'] = conf.return_value('access-list in'.format(dist_iface)) - # Access-list out - if conf.exists('access-list out'.format(dist_iface)): - rip_conf['rip']['iface_access_list_out'] = conf.return_value('access-list out'.format(dist_iface)) - # Prefix-list in - if conf.exists('prefix-list in'.format(dist_iface)): - rip_conf['rip']['iface_prefix_list_in'] = conf.return_value('prefix-list in'.format(dist_iface)) - # Prefix-list out - if conf.exists('prefix-list out'.format(dist_iface)): - rip_conf['rip']['iface_prefix_list_out'] = conf.return_value('prefix-list out'.format(dist_iface)) - - conf.set_level(base + ['distribute-list']) - - # Get distribute list, access-list in - if conf.exists_effective('access-list in'): - rip_conf['old_rip']['dist_acl_in'] = conf.return_effective_value('access-list in') - - if conf.exists('access-list in'): - rip_conf['rip']['dist_acl_in'] = conf.return_value('access-list in') - - # Get distribute list, access-list out - if conf.exists_effective('access-list out'): - rip_conf['old_rip']['dist_acl_out'] = conf.return_effective_value('access-list out') - - if conf.exists('access-list out'): - rip_conf['rip']['dist_acl_out'] = conf.return_value('access-list out') - - # Get ditstribute list, prefix-list in - if conf.exists_effective('prefix-list in'): - rip_conf['old_rip']['dist_prfx_in'] = conf.return_effective_value('prefix-list in') - - if conf.exists('prefix-list in'): - rip_conf['rip']['dist_prfx_in'] = conf.return_value('prefix-list in') - - # Get distribute list, prefix-list out - if conf.exists_effective('prefix-list out'): - rip_conf['old_rip']['dist_prfx_out'] = conf.return_effective_value('prefix-list out') - - if conf.exists('prefix-list out'): - rip_conf['rip']['dist_prfx_out'] = conf.return_value('prefix-list out') + rip = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) - conf.set_level(base) + # Bail out early if configuration tree does not exist + if not conf.exists(base): + return rip - # Get network Interfaces - if conf.exists_effective('interface'): - rip_conf['old_rip']['ifaces'] = conf.return_effective_values('interface') - - if conf.exists('interface'): - rip_conf['rip']['ifaces'] = conf.return_values('interface') - - # Get neighbors - if conf.exists_effective('neighbor'): - rip_conf['old_rip']['neighbors'] = conf.return_effective_values('neighbor') - - if conf.exists('neighbor'): - rip_conf['rip']['neighbors'] = conf.return_values('neighbor') - - # Get networks - if conf.exists_effective('network'): - rip_conf['old_rip']['networks'] = conf.return_effective_values('network') - - if conf.exists('network'): - rip_conf['rip']['networks'] = conf.return_values('network') - - # Get network-distance old_rip - for net_dist in conf.list_effective_nodes('network-distance'): - rip_conf['old_rip']['net_distance'].update({ - net_dist : { - 'access_list' : conf.return_effective_value('network-distance {0} access-list'.format(net_dist)), - 'distance' : conf.return_effective_value('network-distance {0} distance'.format(net_dist)), - } - }) - - # Get network-distance - for net_dist in conf.list_nodes('network-distance'): - rip_conf['rip']['net_distance'].update({ - net_dist : { - 'access_list' : conf.return_value('network-distance {0} access-list'.format(net_dist)), - 'distance' : conf.return_value('network-distance {0} distance'.format(net_dist)), - } - }) - - # Get passive-interface - if conf.exists_effective('passive-interface'): - rip_conf['old_rip']['passive_iface'] = conf.return_effective_values('passive-interface') - - if conf.exists('passive-interface'): - rip_conf['rip']['passive_iface'] = conf.return_values('passive-interface') - - # Get redistribute for old_rip - for protocol in conf.list_effective_nodes('redistribute'): - rip_conf['old_rip']['redist'].update({ - protocol : { - 'metric' : conf.return_effective_value('redistribute {0} metric'.format(protocol)), - 'route_map' : conf.return_effective_value('redistribute {0} route-map'.format(protocol)), - } - }) - - # Get redistribute - for protocol in conf.list_nodes('redistribute'): - rip_conf['rip']['redist'].update({ - protocol : { - 'metric' : conf.return_value('redistribute {0} metric'.format(protocol)), - 'route_map' : conf.return_value('redistribute {0} route-map'.format(protocol)), - } - }) - - conf.set_level(base) - - # Get route - if conf.exists_effective('route'): - rip_conf['old_rip']['route'] = conf.return_effective_values('route') - - if conf.exists('route'): - rip_conf['rip']['route'] = conf.return_values('route') - - # Get timers garbage - if conf.exists_effective('timers garbage-collection'): - rip_conf['old_rip']['timer_garbage'] = conf.return_effective_value('timers garbage-collection') - - if conf.exists('timers garbage-collection'): - rip_conf['rip']['timer_garbage'] = conf.return_value('timers garbage-collection') - - # Get timers timeout - if conf.exists_effective('timers timeout'): - rip_conf['old_rip']['timer_timeout'] = conf.return_effective_value('timers timeout') - - if conf.exists('timers timeout'): - rip_conf['rip']['timer_timeout'] = conf.return_value('timers timeout') - - # Get timers update - if conf.exists_effective('timers update'): - rip_conf['old_rip']['timer_update'] = conf.return_effective_value('timers update') - - if conf.exists('timers update'): - rip_conf['rip']['timer_update'] = conf.return_value('timers update') - - return rip_conf + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base) + # merge in remaining default values + rip = dict_merge(default_values, rip) + return rip def verify(rip): - if rip is None: + if not rip: return None - # Check for network. If network-distance acl is set and distance not set - for net in rip['rip']['net_distance']: - if not rip['rip']['net_distance'][net]['distance']: - raise ConfigError(f"Must specify distance for network {net}") + # check ACL and route-maps, prefix-lists def generate(rip): - if rip is None: + if not rip: + rip['new_frr_config'] = '' return None + # render(config) not needed, its only for debug render(config_file, 'frr/rip.frr.tmpl', rip) + rip['new_frr_config'] = render_to_string('frr/rip.frr.tmpl', rip) + return None def apply(rip): - if rip is None: - return None - - if os.path.exists(config_file): - call(f'vtysh -d ripd -f {config_file}') - os.remove(config_file) - else: - print("File {0} not found".format(config_file)) - + # Save original configuration prior to starting any commit actions + frr_cfg = frr.FRRConfig() + frr_cfg.load_configuration(frr_daemon) + frr_cfg.modify_section(r'interface \S+', '') + frr_cfg.modify_section('router rip', '') + frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', rip['new_frr_config']) + + # Debugging + if DEBUG: + from pprint import pprint + print('') + print('--------- DEBUGGING ----------') + pprint(dir(frr_cfg)) + print('Existing config:\n') + for line in frr_cfg.original_config: + print(line) + print(f'Replacement config:\n') + print(f'{rip["new_frr_config"]}') + print(f'Modified config:\n') + print(f'{frr_cfg}') + + frr_cfg.commit_configuration(frr_daemon) + + # If FRR config is blank, rerun the blank commit x times due to frr-reload + # behavior/bug not properly clearing out on one commit. + if rip['new_frr_config'] == '': + for a in range(5): + frr_cfg.commit_configuration(frr_daemon) return None @@ -317,4 +117,3 @@ if __name__ == '__main__': except ConfigError as e: print(e) exit(1) - |