Problematic:
There is one obvious source of overhead during the running of conf_mode scripts, contributing to non trivial delays in commit, hence boot. Each script initializes a Config class, which consists in a call to the backend to retrieve the active and session configs; this is expensive. In addition, each conf_mode script incurs the start-up cost of the Python interpreter.
Observation:
- During the commit phase, the configuration state is fixed: active and session config are unchanging, so the initialization of each script is not fetching 'new' information.
- Other than that initial config information, the execution of conf_mode scripts does not require the session in any other manner. Thus, with the provided configs, conf_mode scripts may be run 'off-line'.
Approach (initial version complete; link below):
- a script daemon, running as a zmq server, that accepts requests to run a specific conf_mode script; the request consists of the script name and, if applicable, a VYOS_TAGNODE_VALUE.
- a shim zmq client, in C, that is called _within_ the node definition file; if 'on', it dispatches the arguments (script name, tagnode?); 'off', a no-op, and the execution of the script proceeds as normal. On initialization, it provides the active and session configs to the daemon.
- a variant of the Config class (frozen_config.py) with constructor taking arguments: active_config_string, session_config_string. This provides enough for conf_mode scripts to run outside of a config session, with reference to a single Config instance, as long as they adhere to a few requirements, detailed below.
A design goal is that this is as unobtrusive as possible; no existing code has been changed. For conf_mode scripts to participate, they will add a few lines (also below); those lines are a no-op if shim is off.
Requirements on conf_mode scripts:
In order to be dispatch-able, a conf_mode script needs
- adherence to the proper use of get_config/verify/generate/apply as outlined in the coding guidelines:
https://docs.vyos.io/en/latest/contributing/development.html#python
- not use the following functions from config.py: in_session, session_changed, show_config, is_tag, is_multi, is_leaf --- none of these should be ever needed; the one instance of 'is_tag' I find in current scripts is removable.
3) not have a hyphen in the script name, so that it may be imported as module. [No longer required]
Required lines for off-loading:
The example case is interfaces-dummy.py; diff is here:
43c43,48 < def get_config(): --- > def get_config(config=None): > if config: > conf = config > else: > conf = Config() > 45d49 < conf = Config()
To test:
One will need the vyos-1x and vyatta-cfg branch below (a few lines in vyatta-cfg signal the beginning of commit for initialization); one will need to install 'libzmq3-dev' in your docker image as a build requirement for vyos-1x.
There is one annoying manual intervention required: since the shim reference can not be added to _all_ node.def's at this point, one will need to do the following for the test case:
> /opt/vyatta/share/vyatta-cfg/templates/interfaces/dummy/node.def > > < end: sudo sh -c "VYOS_TAGNODE_VALUE='$VAR(@)' ${vyos_conf_scripts_dir}/interfaces_dummy.py" > --- >> end: sudo sh -c "${vyshim} VYOS_TAGNODE_VALUE='$VAR(@)' ${vyos_conf_scripts_dir}/interfaces_dummy.py" >
On the running system, 'sudo systemctl start vyos-configd'; in the shell from which you launch config, 'export vyshim=/usr/sbin/vyshim'; config; add, say, 100 dummy interfaces; commit.
time 100 dummy interfaces:
with daemon and shim:
real 0m7.174s
user 0m1.165s
sys 0m0.750s
without daemon and shim:
real 0m28.267s
user 0m14.436s
sys 0m5.345s
Code is here; note this includes the patch for T2568, but will be rebased when that is pushed.
https://github.com/vyos/vyos-1x/compare/current...jestabro:vyos-configd
https://github.com/vyos/vyatta-cfg/compare/current...jestabro:vyos-configd
This is the first version, and many details will evolve quickly, but the logic is well demonstrated by the current example.