summaryrefslogtreecommitdiff
path: root/python/vyos
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos')
-rw-r--r--python/vyos/component_version.py25
-rw-r--r--python/vyos/config_mgmt.py29
-rw-r--r--python/vyos/defaults.py1
-rw-r--r--python/vyos/ifconfig/bond.py13
-rw-r--r--python/vyos/ifconfig/ethernet.py34
-rw-r--r--python/vyos/utils/dict.py59
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)
+