diff options
Diffstat (limited to 'python/vyos')
-rw-r--r-- | python/vyos/component_version.py | 25 | ||||
-rw-r--r-- | python/vyos/config_mgmt.py | 29 | ||||
-rw-r--r-- | python/vyos/defaults.py | 1 | ||||
-rw-r--r-- | python/vyos/ifconfig/bond.py | 13 | ||||
-rw-r--r-- | python/vyos/ifconfig/ethernet.py | 34 | ||||
-rw-r--r-- | python/vyos/utils/dict.py | 59 |
6 files changed, 131 insertions, 30 deletions
diff --git a/python/vyos/component_version.py b/python/vyos/component_version.py index 84e0ae51a..9662ebfcf 100644 --- a/python/vyos/component_version.py +++ b/python/vyos/component_version.py @@ -90,31 +90,6 @@ def from_system(): """ return component_version() -def legacy_from_system(): - """ - Get system component version dict from legacy location. - This is for a transitional sanity check; the directory will eventually - be removed. - """ - system_versions = {} - legacy_dir = directories['current'] - - # To be removed: - if not os.path.isdir(legacy_dir): - return system_versions - - try: - version_info = os.listdir(legacy_dir) - except OSError as err: - sys.exit(repr(err)) - - for info in version_info: - if re.match(r'[\w,-]+@\d+', info): - pair = info.split('@') - system_versions[pair[0]] = int(pair[1]) - - return system_versions - def format_string(ver: dict) -> str: """ Version dict to string. diff --git a/python/vyos/config_mgmt.py b/python/vyos/config_mgmt.py index dbf17ade4..654a8d698 100644 --- a/python/vyos/config_mgmt.py +++ b/python/vyos/config_mgmt.py @@ -25,7 +25,7 @@ from datetime import datetime from textwrap import dedent from pathlib import Path from tabulate import tabulate -from shutil import copy +from shutil import copy, chown from vyos.config import Config from vyos.configtree import ConfigTree, ConfigTreeError, show_diff @@ -37,6 +37,7 @@ from vyos.utils.process import is_systemd_service_active from vyos.utils.process import rc_cmd SAVE_CONFIG = '/usr/libexec/vyos/vyos-save-config.py' +config_json = '/run/vyatta/config/config.json' # created by vyatta-cfg-postinst commit_post_hook_dir = '/etc/commit/post-hooks.d' @@ -64,8 +65,11 @@ formatter = logging.Formatter('%(funcName)s: %(levelname)s:%(message)s') ch.setFormatter(formatter) logger.addHandler(ch) -def save_config(target): - cmd = f'{SAVE_CONFIG} {target}' +def save_config(target, json_out=None): + if json_out is None: + cmd = f'{SAVE_CONFIG} {target}' + else: + cmd = f'{SAVE_CONFIG} {target} --write-json-file {json_out}' rc, out = rc_cmd(cmd) if rc != 0: logger.critical(f'save config failed: {out}') @@ -326,6 +330,12 @@ Proceed ?''' """ mask = os.umask(0o002) os.makedirs(archive_dir, exist_ok=True) + json_dir = os.path.dirname(config_json) + try: + os.makedirs(json_dir, exist_ok=True) + chown(json_dir, group='vyattacfg') + except OSError as e: + logger.warning(f'cannot create {json_dir}: {e}') self._add_logrotate_conf() @@ -481,10 +491,21 @@ Proceed ?''' ext = os.getpid() cmp_saved = f'/tmp/config.boot.{ext}' if save_to_tmp: - save_config(cmp_saved) + save_config(cmp_saved, json_out=config_json) else: copy(config_file, cmp_saved) + # on boot, we need to manually create the config.json file; after + # boot, it is written by save_config, above + if not os.path.exists(config_json): + ct = self._get_saved_config_tree() + try: + with open(config_json, 'w') as f: + f.write(ct.to_json()) + chown(config_json, group='vyattacfg') + except OSError as e: + logger.warning(f'cannot create {config_json}: {e}') + try: if cmp(cmp_saved, archive_config_file, shallow=False): os.unlink(cmp_saved) diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py index a5314790d..a229533bd 100644 --- a/python/vyos/defaults.py +++ b/python/vyos/defaults.py @@ -24,7 +24,6 @@ directories = { 'op_mode' : f'{base_dir}/op_mode', 'services' : f'{base_dir}/services', 'config' : '/opt/vyatta/etc/config', - 'current' : '/opt/vyatta/etc/config-migrate/current', 'migrate' : '/opt/vyatta/etc/config-migrate/migrate', 'log' : '/var/log/vyatta', 'templates' : '/usr/share/vyos/templates/', diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py index d1d7d48c4..45e6e4c16 100644 --- a/python/vyos/ifconfig/bond.py +++ b/python/vyos/ifconfig/bond.py @@ -92,6 +92,19 @@ class BondIf(Interface): } }} + @staticmethod + def get_inherit_bond_options() -> list: + """ + Returns list of option + which are inherited from bond interface to member interfaces + :return: List of interface options + :rtype: list + """ + options = [ + 'mtu' + ] + return options + def remove(self): """ Remove interface from operating system. Removing the interface diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 285542057..aa1e87744 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -75,6 +75,40 @@ class EthernetIf(Interface): }, }} + @staticmethod + def get_bond_member_allowed_options() -> list: + """ + Return list of options which are allowed for changing, + when interface is a bond member + :return: List of interface options + :rtype: list + """ + bond_allowed_sections = [ + 'description', + 'disable', + 'disable_flow_control', + 'disable_link_detect', + 'duplex', + 'eapol.ca_certificate', + 'eapol.certificate', + 'eapol.passphrase', + 'mirror.egress', + 'mirror.ingress', + 'offload.gro', + 'offload.gso', + 'offload.lro', + 'offload.rfs', + 'offload.rps', + 'offload.sg', + 'offload.tso', + 'redirect', + 'ring_buffer.rx', + 'ring_buffer.tx', + 'speed', + 'hw_id' + ] + return bond_allowed_sections + def __init__(self, ifname, **kargs): super().__init__(ifname, **kargs) self.ethtool = Ethtool(ifname) diff --git a/python/vyos/utils/dict.py b/python/vyos/utils/dict.py index 9484eacdd..d36b6fcfb 100644 --- a/python/vyos/utils/dict.py +++ b/python/vyos/utils/dict.py @@ -199,6 +199,31 @@ def dict_search_recursive(dict_object, key, path=[]): for x in dict_search_recursive(j, key, new_path): yield x + +def dict_set(key_path, value, dict_object): + """ Set value to Python dictionary (dict_object) using path to key delimited by dot (.). + The key will be added if it does not exist. + """ + path_list = key_path.split(".") + dynamic_dict = dict_object + if len(path_list) > 0: + for i in range(0, len(path_list)-1): + dynamic_dict = dynamic_dict[path_list[i]] + dynamic_dict[path_list[len(path_list)-1]] = value + +def dict_delete(key_path, dict_object): + """ Delete key in Python dictionary (dict_object) using path to key delimited by dot (.). + """ + path_dict = dict_object + path_list = key_path.split('.') + inside = path_list[:-1] + if not inside: + del dict_object[path_list] + else: + for key in path_list[:-1]: + path_dict = path_dict[key] + del path_dict[path_list[len(path_list)-1]] + def dict_to_list(d, save_key_to=None): """ Convert a dict to a list of dicts. @@ -228,6 +253,39 @@ def dict_to_list(d, save_key_to=None): return collect +def dict_to_paths_values(conf: dict) -> dict: + """ + Convert nested dictionary to simple dictionary, where key is a path is delimited by dot (.). + """ + list_of_paths = [] + dict_of_options ={} + for path in dict_to_key_paths(conf): + str_path = '.'.join(path) + list_of_paths.append(str_path) + + for path in list_of_paths: + dict_of_options[path] = dict_search(path,conf) + + return dict_of_options +def dict_to_key_paths(d: dict) -> list: + """ Generator to return list of key paths from dict of list[str]|str + """ + def func(d, path): + if isinstance(d, dict): + if not d: + yield path + for k, v in d.items(): + for r in func(v, path + [k]): + yield r + elif isinstance(d, list): + yield path + elif isinstance(d, str): + yield path + else: + raise ValueError('object is not a dict of strings/list of strings') + for r in func(d, []): + yield r + def dict_to_paths(d: dict) -> list: """ Generator to return list of paths from dict of list[str]|str """ @@ -305,3 +363,4 @@ class FixedDict(dict): if k not in self._allowed: raise ConfigError(f'Option "{k}" has no defined default') super().__setitem__(k, v) + |