diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-11-13 21:50:51 +0100 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2020-11-13 21:50:51 +0100 |
commit | 82193bbcf4a6ae8b661dd30eb627cf1a27593fe9 (patch) | |
tree | 8b94d527966191f25bd8395639d62db9c491b3e6 /src | |
parent | 9ca2b7b2223be826a8278e0f29dfbca6ae65f671 (diff) | |
download | vyos-1x-82193bbcf4a6ae8b661dd30eb627cf1a27593fe9.tar.gz vyos-1x-82193bbcf4a6ae8b661dd30eb627cf1a27593fe9.zip |
isis: T1316: refactor config retrieval and Jinja2 template
Make the entire template code more human readable by denesting it, as there can
only be one ISIS daemon instance in FRR.
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/protocols_isis.py | 91 |
1 files changed, 53 insertions, 38 deletions
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py index 4ee6b31f6..d5e5b64fb 100755 --- a/src/conf_mode/protocols_isis.py +++ b/src/conf_mode/protocols_isis.py @@ -19,29 +19,33 @@ import os from sys import exit from vyos.config import Config +from vyos.configdict import node_changed from vyos import ConfigError from vyos.util import call from vyos.template import render from vyos.template import render_to_string from vyos import frr from vyos import airbag -from pprint import pprint airbag.enable() config_file = r'/tmp/isis.frr' -default_config_data = { - 'interface': '' -} - -def get_config(): - conf = Config() +def get_config(config=None): + if config: + conf = config + else: + conf = Config() base = ['protocols', 'isis'] - isis = conf.get_config_dict(base, key_mangling=('-', '_')) - if not conf.exists(base): - isis = {} - pprint(isis) + isis = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + + # determine which members have been removed + for instance in isis: + conf.set_level(base + [instance]) + tmp = node_changed(conf, ['interface']) + if tmp: + isis[instance].update({'interface_remove': tmp}) + return isis def verify(isis): @@ -49,32 +53,31 @@ def verify(isis): if not isis: return None - for proc_id, foo_config in isis['isis'].items(): - + for process, isis_config in isis.items(): # If more then one isis process is defined (Frr only supports one) # http://docs.frrouting.org/en/latest/isisd.html#isis-router - if len(isis['isis']) > 1: + if len(isis) > 1: raise ConfigError('Only one isis process can be definded') # If network entity title (net) not defined - if not "net" in foo_config: - raise ConfigError('Define net format iso is mandatory in \"isis {} net"!'.format(proc_id)) + if 'net' not in isis_config: + raise ConfigError('ISIS net format iso is mandatory!') # If interface not set - if not "interface" in foo_config: - raise ConfigError('Define interface is mandatory in \"isis {} interface"!'.format(proc_id)) + if 'interface' not in isis_config: + raise ConfigError('ISIS interface is mandatory!') # If md5 and plaintext-password set at the same time - if 'area_password' in foo_config: - if "md5" in foo_config['area_password'] and "plaintext_password" in foo_config['area_password']: - raise ConfigError('Only one password type should be used in \"isis {} area-password"!'.format(proc_id)) + if 'area_password' in isis_config: + if {'md5', 'plaintext_password'} <= set(isis_config['encryption']): + raise ConfigError('Can not use both md5 and plaintext-password for ISIS area-password!') # If one param from deley set, but not set others - if 'spf_delay_ietf' in foo_config: + if 'spf_delay_ietf' in isis_config: required_timers = ['holddown', 'init_delay', 'long_delay', 'short_delay', 'time_to_learn'] exist_timers = [] for elm_timer in required_timers: - if elm_timer in foo_config['spf_delay_ietf']: + if elm_timer in isis_config['spf_delay_ietf']: exist_timers.append(elm_timer) exist_timers = set(required_timers).difference(set(exist_timers)) @@ -82,14 +85,14 @@ def verify(isis): raise ConfigError('All types of delay must be specified: ' + ', '.join(exist_timers).replace('_', '-')) # If Redistribute set, but level don't set - if 'redistribute' in foo_config: - proc_level = foo_config.get('level','').replace('-','_') - for proto, proto_config in foo_config.get('redistribute', {}).get('ipv4', {}).items(): + if 'redistribute' in isis_config: + proc_level = isis_config.get('level','').replace('-','_') + for proto, proto_config in isis_config.get('redistribute', {}).get('ipv4', {}).items(): if 'level_1' not in proto_config and 'level_2' not in proto_config: - raise ConfigError('Redistribute level-1 or level-2 should be specified in \"protocols isis {} redistribute ipv4 {}\"'.format(proc_id, proto)) + raise ConfigError('Redistribute level-1 or level-2 should be specified in \"protocols isis {} redistribute ipv4 {}\"'.format(process, proto)) for redistribute_level in proto_config.keys(): if proc_level and proc_level != 'level_1_2' and proc_level != redistribute_level: - raise ConfigError('\"protocols isis {0} redistribute ipv4 {2} {3}\" cannot be used with \"protocols isis {0} level {1}\"'.format(proc_id, proc_level, proto, redistribute_level)) + raise ConfigError('\"protocols isis {0} redistribute ipv4 {2} {3}\" cannot be used with \"protocols isis {0} level {1}\"'.format(process, proc_level, proto, redistribute_level)) return None @@ -98,31 +101,43 @@ def generate(isis): isis['new_frr_config'] = '' return None + # only one ISIS process is supported, so we can directly send the first key + # of the config dict + process = list(isis.keys())[0] + isis[process]['process'] = process + + import pprint + pprint.pprint(isis[process]) + # render(config) not needed, its only for debug - render(config_file, 'frr/isis.frr.tmpl', isis) + render(config_file, 'frr/isis.frr.tmpl', isis[process], trim_blocks=True) - isis['new_frr_config'] = render_to_string('frr/isis.frr.tmpl', isis) + isis['new_frr_config'] = render_to_string('frr/isis.frr.tmpl', + isis[process], trim_blocks=True) return None def apply(isis): # Save original configration prior to starting any commit actions - isis['original_config'] = frr.get_configuration(daemon='isisd') - isis['modified_config'] = frr.replace_section(isis['original_config'], isis['new_frr_config'], from_re='router isis .*') + frr_cfg = {} + frr_cfg['original_config'] = frr.get_configuration(daemon='isisd') + frr_cfg['modified_config'] = frr.replace_section(frr_cfg['original_config'], isis['new_frr_config'], from_re='router isis .*') # Debugging print('') print('--------- DEBUGGING ----------') - print(f'Existing config:\n{isis["original_config"]}\n\n') + print(f'Existing config:\n{frr_cfg["original_config"]}\n\n') print(f'Replacement config:\n{isis["new_frr_config"]}\n\n') - print(f'Modified config:\n{isis["modified_config"]}\n\n') + print(f'Modified config:\n{frr_cfg["modified_config"]}\n\n') - # Frr Mark configuration will test for syntax errors and exception out if any syntax errors are detected - frr.mark_configuration(isis['modified_config']) + # FRR mark configuration will test for syntax errors and throws an + # exception if any syntax errors is detected + frr.mark_configuration(frr_cfg['modified_config']) - # Commit the resulting new configuration to frr, this will render an frr.CommitError() Exception on fail - frr.reload_configuration(isis['modified_config'], daemon='isisd') + # Commit resulting configuration to FRR, this will throw CommitError + # on failure + frr.reload_configuration(frr_cfg['modified_config'], daemon='isisd') return None |