diff options
Diffstat (limited to 'python/vyos')
-rw-r--r-- | python/vyos/configtree.py | 65 | ||||
-rw-r--r-- | python/vyos/configverify.py | 2 | ||||
-rw-r--r-- | python/vyos/ethtool.py | 2 | ||||
-rw-r--r-- | python/vyos/ifconfig/bridge.py | 12 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireless.py | 6 | ||||
-rw-r--r-- | python/vyos/migrator.py | 2 | ||||
-rw-r--r-- | python/vyos/systemversions.py | 7 | ||||
-rw-r--r-- | python/vyos/util.py | 9 | ||||
-rw-r--r-- | python/vyos/xml/__init__.py | 4 | ||||
-rw-r--r-- | python/vyos/xml/definition.py | 9 |
10 files changed, 88 insertions, 30 deletions
diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index d8ffaca99..866f24e47 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -15,8 +15,9 @@ import re import json -from ctypes import cdll, c_char_p, c_void_p, c_int +from ctypes import cdll, c_char_p, c_void_p, c_int, POINTER +LIBPATH = '/usr/lib/libvyosconfig.so.0' def escape_backslash(string: str) -> str: """Escape single backslashes in string that are not in escape sequence""" @@ -42,7 +43,9 @@ class ConfigTreeError(Exception): class ConfigTree(object): - def __init__(self, config_string, libpath='/usr/lib/libvyosconfig.so.0'): + def __init__(self, config_string=None, address=None, libpath=LIBPATH): + if config_string is None and address is None: + raise TypeError("ConfigTree() requires one of 'config_string' or 'address'") self.__config = None self.__lib = cdll.LoadLibrary(libpath) @@ -60,7 +63,7 @@ class ConfigTree(object): self.__to_string.restype = c_char_p self.__to_commands = self.__lib.to_commands - self.__to_commands.argtypes = [c_void_p] + self.__to_commands.argtypes = [c_void_p, c_char_p] self.__to_commands.restype = c_char_p self.__to_json = self.__lib.to_json @@ -126,15 +129,19 @@ class ConfigTree(object): self.__destroy = self.__lib.destroy self.__destroy.argtypes = [c_void_p] - config_section, version_section = extract_version(config_string) - config_section = escape_backslash(config_section) - config = self.__from_string(config_section.encode()) - if config is None: - msg = self.__get_error().decode() - raise ValueError("Failed to parse config: {0}".format(msg)) + if address is None: + config_section, version_section = extract_version(config_string) + config_section = escape_backslash(config_section) + config = self.__from_string(config_section.encode()) + if config is None: + msg = self.__get_error().decode() + raise ValueError("Failed to parse config: {0}".format(msg)) + else: + self.__config = config + self.__version = version_section else: - self.__config = config - self.__version = version_section + self.__config = address + self.__version = '' def __del__(self): if self.__config is not None: @@ -143,13 +150,16 @@ class ConfigTree(object): def __str__(self): return self.to_string() + def _get_config(self): + return self.__config + def to_string(self): config_string = self.__to_string(self.__config).decode() config_string = "{0}\n{1}".format(config_string, self.__version) return config_string - def to_commands(self): - return self.__to_commands(self.__config).decode() + def to_commands(self, op="set"): + return self.__to_commands(self.__config, op.encode()).decode() def to_json(self): return self.__to_json(self.__config).decode() @@ -281,3 +291,32 @@ class ConfigTree(object): else: raise ConfigTreeError("Path [{}] doesn't exist".format(path_str)) +class Diff: + def __init__(self, left, right, path=[], libpath=LIBPATH): + if not (isinstance(left, ConfigTree) and isinstance(right, ConfigTree)): + raise TypeError("Arguments must be instances of ConfigTree") + if path: + if not left.exists(path): + raise ConfigTreeError(f"Path {path} doesn't exist in lhs tree") + if not right.exists(path): + raise ConfigTreeError(f"Path {path} doesn't exist in rhs tree") + self.left = left + self.right = right + + check_path(path) + path_str = " ".join(map(str, path)).encode() + df = cdll.LoadLibrary(libpath).diffs + df.restype = POINTER(c_void_p * 3) + res = list(df(path_str, left._get_config(), right._get_config()).contents) + self._diff = {'add': ConfigTree(address=res[0]), + 'del': ConfigTree(address=res[1]), + 'int': ConfigTree(address=res[2]) } + + self.add = self._diff['add'] + self.delete = self._diff['del'] + self.inter = self._diff['int'] + + def to_commands(self): + add = self.add.to_commands() + delete = self.delete.to_commands(op="delete") + return delete + "\n" + add diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 365a28feb..18fb7f9f7 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -173,7 +173,7 @@ def verify_eapol(config): if ca_cert_name not in config['pki']['ca']: raise ConfigError('Invalid CA certificate specified for EAPoL') - ca_cert = config['pki']['ca'][cert_name] + ca_cert = config['pki']['ca'][ca_cert_name] if 'certificate' not in ca_cert: raise ConfigError('Invalid CA certificate specified for EAPoL') diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py index e45b0f041..80d44eee6 100644 --- a/python/vyos/ethtool.py +++ b/python/vyos/ethtool.py @@ -41,7 +41,7 @@ class Ethtool: # '100' : {'full': '', 'half': ''}, # '1000': {'full': ''} # } - _speed_duplex = { } + _speed_duplex = {'auto': {'auto': ''}} _ring_buffers = { } _ring_buffers_max = { } _driver_name = None diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index 27073b266..ffd9c590f 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -298,7 +298,6 @@ class BridgeIf(Interface): tmp = dict_search('member.interface', config) if tmp: - for interface, interface_config in tmp.items(): # if interface does yet not exist bail out early and # add it later @@ -316,10 +315,13 @@ class BridgeIf(Interface): # enslave interface port to bridge self.add_port(interface) - # always set private-vlan/port isolation - tmp = dict_search('isolated', interface_config) - value = 'on' if (tmp != None) else 'off' - lower.set_port_isolation(value) + if not interface.startswith('wlan'): + # always set private-vlan/port isolation - this can not be + # done when lower link is a wifi link, as it will trigger: + # RTNETLINK answers: Operation not supported + tmp = dict_search('isolated', interface_config) + value = 'on' if (tmp != None) else 'off' + lower.set_port_isolation(value) # set bridge port path cost if 'cost' in interface_config: diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py index 748b6e02d..88eaa772b 100644 --- a/python/vyos/ifconfig/wireless.py +++ b/python/vyos/ifconfig/wireless.py @@ -49,10 +49,10 @@ class WiFiIf(Interface): on any interface. """ # We can not call add_to_bridge() until wpa_supplicant is running, thus - # we will remove the key from the config dict and react to this specal - # case in thie derived class. + # we will remove the key from the config dict and react to this special + # case in this derived class. # re-add ourselves to any bridge we might have fallen out of - bridge_member = '' + bridge_member = None if 'is_bridge_member' in config: bridge_member = config['is_bridge_member'] del config['is_bridge_member'] diff --git a/python/vyos/migrator.py b/python/vyos/migrator.py index 4574bb6d1..a2e0daabd 100644 --- a/python/vyos/migrator.py +++ b/python/vyos/migrator.py @@ -195,7 +195,7 @@ class Migrator(object): # This will force calling all migration scripts: cfg_versions = {} - sys_versions = systemversions.get_system_versions() + sys_versions = systemversions.get_system_component_version() # save system component versions in json file for easy reference self.save_json_record(sys_versions) diff --git a/python/vyos/systemversions.py b/python/vyos/systemversions.py index 9b3f4f413..f2da76d4f 100644 --- a/python/vyos/systemversions.py +++ b/python/vyos/systemversions.py @@ -17,7 +17,10 @@ import os import re import sys import vyos.defaults +from vyos.xml import component_version +# legacy version, reading from the file names in +# /opt/vyatta/etc/config-migrate/current def get_system_versions(): """ Get component versions from running system; critical failure if @@ -37,3 +40,7 @@ def get_system_versions(): system_versions[pair[0]] = int(pair[1]) return system_versions + +# read from xml cache +def get_system_component_version(): + return component_version() diff --git a/python/vyos/util.py b/python/vyos/util.py index 571d43754..1767ff9d3 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -997,3 +997,12 @@ def boot_configuration_complete() -> bool: if os.path.isfile(config_status): return True return False + +def sysctl(name, value): + """ Change value via sysctl() - return True if changed, False otherwise """ + tmp = cmd(f'sysctl {name}') + # last list index contains the actual value - only write if value differs + if tmp.split()[-1] != str(value): + call(f'sysctl -wq {name}={value}') + return True + return False diff --git a/python/vyos/xml/__init__.py b/python/vyos/xml/__init__.py index e0eacb2d1..6db446a40 100644 --- a/python/vyos/xml/__init__.py +++ b/python/vyos/xml/__init__.py @@ -46,8 +46,8 @@ def is_tag(lpath): def is_leaf(lpath, flat=True): return load_configuration().is_leaf(lpath, flat) -def component_versions(): - return load_configuration().component_versions() +def component_version(): + return load_configuration().component_version() def defaults(lpath, flat=False): return load_configuration().defaults(lpath, flat) diff --git a/python/vyos/xml/definition.py b/python/vyos/xml/definition.py index 5e0d5282c..bc3892b42 100644 --- a/python/vyos/xml/definition.py +++ b/python/vyos/xml/definition.py @@ -249,10 +249,11 @@ class XML(dict): # @lru_cache(maxsize=100) # XXX: need to use cachetool instead - for later - def component_versions(self) -> dict: - sort_component = sorted(self[kw.component_version].items(), - key = lambda kv: kv[0]) - return dict(sort_component) + def component_version(self) -> dict: + d = {} + for k in sorted(self[kw.component_version]): + d[k] = int(self[kw.component_version][k]) + return d def defaults(self, lpath, flat): d = self[kw.default] |