Configuring FRR is for the time being done in multiple different ways depending on the script used.
Some scripts execute vtysh directly to configure each and every command option, and some use hard to read templates with a script template thats being applied to FRR. this is a mismatch on "set" and "no" statements to add and remove configuration options from FRR.
This makes FRR vulnerable to inconsistency on a failed command/commit as FRR will be in one state but the commit is aborted by and VyOS does not rollback the changes done prior to the issue happening.
To try to fix this i've created a mini-framework for configuring FRR from inside python that uses frr-reload.py (the official FRR configuration reload script) to load a new configuration into FRR. it is by now possible to do this:
- Collect the config of a daemon in FRR
- check FRR config syntax
- replace FRR config block (eg. replace the whole router ospf section
- apply a new configuration via frr-reload.py
As this is using frr-reload.py we do not need to take into account commands that is going to be removed, as frr-reload.py will mirror our configuration into the running configuration. this makes creating templates in FRR much simpler and we could remove much code from the configuration scripts because of this.
i've created my own branch for doing this work: https://github.com/runborg/vyos-1x/blob/frr-mod/python/vyos/frr.py
Following here is a simple example of configuring frr with this:
>>> new_ospf_config_from_template = """ router ospf router-id 1.2.3.4 area 0 network 0.0.0.0/0 """ >>> from vyos import frr # Load configuration from FRR >>> original_config = frr.get_configuration(daemon='ospfd') # Modify Configuration >>> modified_configuration = frr.replace_section(original_config, new_ospf_config_from_template, from_re='router ospf' # Test configuration, this will exception if an syntax error is detected >>> frr.mark_configuration(modified_configuration) # Apply the new configuration >>> frr.reload_configuration(modified_configuration, daemon='ospfd')
Also see the vyos.frr module for more examples.
as this uses frr-reload.py it depends on the frr-pythontools package to being installed on the system.
and as of FRR version 7.3.0 the frr-reload.py script is not functioning and needs a patch to work as expected:
https://github.com/FRRouting/frr/issues/6062
@@ -155,7 +155,7 @@ try: config_text = subprocess.check_output( bindir + "/vtysh --config_dir " + confdir + " -c 'show run " + daemon + "' | /usr/bin/tail -n +4 | " + bindir + "/vtysh --config_dir " + confdir + " -m -f -", - shell=True, stderr=subprocess.STDOUT) + shell=True) except subprocess.CalledProcessError as e: ve = VtyshMarkException(e) ve.output = e.output
As for now i've not integrated this into any existing configuration script, but as a start this could be implemented into T2547 as a proof of concept before changing other daemons
There is one limitation on using frr-reload.py, and that is that it wants to save the configuration to frr.conf, so wee need to rewrite the frr.conf on reboot to revert these changes prior to starting FRR. or less we will be out-of-sync with FRR on bootup. (it seems like this behavior changes when writing to the integrated config va a daemon config)