diff options
Diffstat (limited to 'python/vyos')
-rw-r--r-- | python/vyos/config.py | 15 | ||||
-rw-r--r-- | python/vyos/configdict.py | 5 | ||||
-rw-r--r-- | python/vyos/configtree.py | 62 | ||||
-rw-r--r-- | python/vyos/ifconfig/control.py | 12 | ||||
-rw-r--r-- | python/vyos/ifconfig/dhcp.py | 4 | ||||
-rw-r--r-- | python/vyos/ifconfig/interface.py | 10 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireguard.py | 56 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireless.py | 2 | ||||
-rw-r--r-- | python/vyos/ifconfig_vlan.py | 2 | ||||
-rw-r--r-- | python/vyos/interfaces.py | 65 | ||||
-rw-r--r-- | python/vyos/migrator.py | 11 | ||||
-rw-r--r-- | python/vyos/util.py | 2 |
12 files changed, 104 insertions, 142 deletions
diff --git a/python/vyos/config.py b/python/vyos/config.py index 2342f7021..75055a603 100644 --- a/python/vyos/config.py +++ b/python/vyos/config.py @@ -238,6 +238,19 @@ class Config(object): str: working configuration """ + # show_config should be independent of CLI edit level. + # Set the CLI edit environment to the top level, and + # restore original on exit. + save_env = self.__session_env + + env_str = self._run(self._make_command('getEditResetEnv', '')) + env_list = re.findall(r'([A-Z_]+)=\'([^;\s]+)\'', env_str) + root_env = os.environ + for k, v in env_list: + root_env[k] = v + + self.__session_env = root_env + # FIXUP: by default, showConfig will give you a diff # if there are uncommitted changes. # The config parser obviously cannot work with diffs, @@ -253,8 +266,10 @@ class Config(object): path = " ".join(path) try: out = self._run(self._make_command('showConfig', path)) + self.__session_env = save_env return out except VyOSError: + self.__session_env = save_env return(default) def get_config_dict(self, path=[], effective=False): diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index 66da52ff3..24fe174d2 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -123,6 +123,7 @@ def vlan_to_dict(conf): 'ip_enable_arp_accept': 0, 'ip_enable_arp_announce': 0, 'ip_enable_arp_ignore': 0, + 'ip_proxy_arp': 0, 'ipv6_autoconf': 0, 'ipv6_forwarding': 1, 'ipv6_dup_addr_detect': 1, @@ -190,6 +191,10 @@ def vlan_to_dict(conf): if conf.exists('ip enable-arp-ignore'): vlan['ip_enable_arp_ignore'] = 1 + # Enable Proxy ARP + if conf.exists('ip enable-proxy-arp'): + vlan['ip_proxy_arp'] = 1 + # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC) if conf.exists('ipv6 address autoconf'): vlan['ipv6_autoconf'] = 1 diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index 0274f3573..a0b0eb3c1 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -24,58 +24,10 @@ def escape_backslash(string: str) -> str: result = p.sub(r'\\\\', string) return result -def strip_comments(s): - """ Split a config string into the config section and the trailing comments """ - INITIAL = 0 - IN_COMMENT = 1 - - i = len(s) - 1 - - state = INITIAL - - config_end = 0 - - # Find the first character of the comments section at the end, - # if it exists - while (i >= 0): - c = s[i] - - if (state == INITIAL) and re.match(r'\s', c): - # Ignore whitespace - if (i != 0): - i -= 1 - else: - config_end = 0 - break - elif (state == INITIAL) and not re.match(r'(\s|\/)', c): - # Assume there are no (more) trailing comments, - # this is an end of a node: either a brace of the last character - # of a leaf node value - config_end = i + 1 - break - elif (state == INITIAL) and (c == '/'): - # A comment begins, or it's a stray slash - if (s[i-1] == '*'): - state = IN_COMMENT - i -= 2 - else: - raise ValueError("Invalid syntax: stray slash at character {0}".format(i + 1)) - elif (state == IN_COMMENT) and (c == '*'): - # A comment ends here - try: - if (s[i-1] == '/'): - state = INITIAL - i -= 2 - except: - raise ValueError("Invalid syntax: malformed commend end at character {0}".format(i + 1)) - elif (state == IN_COMMENT) and (c != '*'): - # Ignore everything inside comments, including braces - i -= 1 - else: - # Shouldn't happen - raise ValueError("Invalid syntax at character {0}: invalid character {1}".format(i + 1, c)) - - return (s[0:config_end], s[config_end+1:]) +def extract_version(s): + """ Extract the version string from the config string """ + t = re.split('(^//)', s, maxsplit=1, flags=re.MULTILINE) + return (s, ''.join(t[1:])) def check_path(path): # Necessary type checking @@ -174,7 +126,7 @@ class ConfigTree(object): self.__destroy = self.__lib.destroy self.__destroy.argtypes = [c_void_p] - config_section, comments_section = strip_comments(config_string) + 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: @@ -182,7 +134,7 @@ class ConfigTree(object): raise ValueError("Failed to parse config: {0}".format(msg)) else: self.__config = config - self.__comments = comments_section + self.__version = version_section def __del__(self): if self.__config is not None: @@ -193,7 +145,7 @@ class ConfigTree(object): def to_string(self): config_string = self.__to_string(self.__config).decode() - config_string = "{0}\n{1}".format(config_string, self.__comments) + config_string = "{0}\n{1}".format(config_string, self.__version) return config_string def to_commands(self): diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py index 1c9f7e284..c1a073aef 100644 --- a/python/vyos/ifconfig/control.py +++ b/python/vyos/ifconfig/control.py @@ -24,8 +24,18 @@ class Control(Register): _command_get = {} _command_set = {} + def __init__(self, **kargs): + # some commands (such as operation comands - show interfaces, etc.) + # need to query the interface statistics. If the interface + # code is used and the debugging is enabled, the screen output + # will include both the command but also the debugging for that command + # to prevent this, debugging can be explicitely disabled + + # if debug is not explicitely disabled the the config, enable it + self.debug = kargs.get('debug', True) + def _debug_msg(self, msg): - if os.path.isfile('/tmp/vyos.ifconfig.debug'): + if os.path.isfile('/tmp/vyos.ifconfig.debug') and self.debug: print('DEBUG/{:<6} {}'.format(self.config['ifname'], msg)) def _popen(self, command): diff --git a/python/vyos/ifconfig/dhcp.py b/python/vyos/ifconfig/dhcp.py index 8d3653433..8ec8263b5 100644 --- a/python/vyos/ifconfig/dhcp.py +++ b/python/vyos/ifconfig/dhcp.py @@ -50,7 +50,9 @@ interface "{{ intf }}" { class DHCP (Control): client_base = r'/var/lib/dhcp/dhclient_' - def __init__ (self, ifname): + def __init__ (self, ifname, **kargs): + super().__init__(**kargs) + # per interface DHCP config files self._dhcp = { 4: { diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 8b41d6158..4a34f96d6 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -162,15 +162,17 @@ class Interface(DHCP): >>> i = Interface('eth0') """ - DHCP.__init__(self, ifname) - self.config = deepcopy(self.default) - self.config['ifname'] = ifname - for k in self.options: if k in kargs: self.config[k] = kargs[k] + # make sure the ifname is the first argument and not from the dict + self.config['ifname'] = ifname + + # we must have updated config before initialising the Interface + super().__init__(ifname, **kargs) + if not os.path.exists('/sys/class/net/{}'.format(self.config['ifname'])): if not self.config['type']: raise Exception('interface "{}" not found'.format(self.config['ifname'])) diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index 7f123f9b4..def5ab7c5 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.py @@ -15,14 +15,15 @@ import os +import time +import subprocess +from datetime import timedelta -import vyos +from vyos.config import Config from vyos.ifconfig.interface import Interface -from vyos.interfaces import wireguard_dump -from datetime import timedelta -import time from hurry.filesize import size,alternative + @Interface.register class WireGuardIf(Interface): default = { @@ -108,10 +109,10 @@ class WireGuardIf(Interface): return self._cmd(cmd) def op_show_interface(self): - wgdump = wireguard_dump().get( + wgdump = self._dump().get( self.config['ifname'], None) - c = vyos.config.Config() + c = Config() c.set_level(["interfaces", "wireguard", self.config['ifname']]) description = c.return_effective_value(["description"]) ips = c.return_effective_values(["address"]) @@ -177,3 +178,46 @@ class WireGuardIf(Interface): wgpeer['persistent_keepalive'])) print() super().op_show_interface_stats() + + def _dump(self): + """Dump wireguard data in a python friendly way.""" + last_device = None + output = {} + + # Dump wireguard connection data + _f = self._cmd('wg show all dump') + for line in _f.split('\n'): + if not line: + # Skip empty lines and last line + continue + items = line.split('\t') + + if last_device != items[0]: + # We are currently entering a new node + device, private_key, public_key, listen_port, fw_mark = items + last_device = device + + output[device] = { + 'private_key': None if private_key == '(none)' else private_key, + 'public_key': None if public_key == '(none)' else public_key, + 'listen_port': int(listen_port), + 'fw_mark': None if fw_mark == 'off' else int(fw_mark), + 'peers': {}, + } + else: + # We are entering a peer + device, public_key, preshared_key, endpoint, allowed_ips, latest_handshake, transfer_rx, transfer_tx, persistent_keepalive = items + if allowed_ips == '(none)': + allowed_ips = [] + else: + allowed_ips = allowed_ips.split('\t') + output[device]['peers'][public_key] = { + 'preshared_key': None if preshared_key == '(none)' else preshared_key, + 'endpoint': None if endpoint == '(none)' else endpoint, + 'allowed_ips': allowed_ips, + 'latest_handshake': None if latest_handshake == '0' else int(latest_handshake), + 'transfer_rx': int(transfer_rx), + 'transfer_tx': int(transfer_tx), + 'persistent_keepalive': None if persistent_keepalive == 'off' else int(persistent_keepalive), + } + return output diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py index 932d07d01..946ae1642 100644 --- a/python/vyos/ifconfig/wireless.py +++ b/python/vyos/ifconfig/wireless.py @@ -47,7 +47,7 @@ class WiFiIf(Interface): self._cmd(cmd) # wireless interface is administratively down by default - self.set_state('down') + self.set_admin_state('down') def _delete(self): cmd = 'iw dev {ifname} del' \ diff --git a/python/vyos/ifconfig_vlan.py b/python/vyos/ifconfig_vlan.py index 00270cf58..ed22646c1 100644 --- a/python/vyos/ifconfig_vlan.py +++ b/python/vyos/ifconfig_vlan.py @@ -64,6 +64,8 @@ def apply_vlan_config(vlan, config): vlan.set_arp_announce(config['ip_enable_arp_announce']) # configure ARP ignore vlan.set_arp_ignore(config['ip_enable_arp_ignore']) + # configure Proxy ARP + vlan.set_proxy_arp(config['ip_proxy_arp']) # IPv6 address autoconfiguration vlan.set_ipv6_autoconf(config['ipv6_autoconf']) # IPv6 forwarding diff --git a/python/vyos/interfaces.py b/python/vyos/interfaces.py deleted file mode 100644 index 4697c0acc..000000000 --- a/python/vyos/interfaces.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - -import re -import json - -from vyos.ifconfig import Interface -import subprocess -import netifaces - - -def wireguard_dump(): - """Dump wireguard data in a python friendly way.""" - last_device=None - output = {} - - # Dump wireguard connection data - _f = subprocess.check_output(["wg", "show", "all", "dump"]).decode() - for line in _f.split('\n'): - if not line: - # Skip empty lines and last line - continue - items = line.split('\t') - - if last_device != items[0]: - # We are currently entering a new node - device, private_key, public_key, listen_port, fw_mark = items - last_device = device - - output[device] = { - 'private_key': None if private_key == '(none)' else private_key, - 'public_key': None if public_key == '(none)' else public_key, - 'listen_port': int(listen_port), - 'fw_mark': None if fw_mark == 'off' else int(fw_mark), - 'peers': {}, - } - else: - # We are entering a peer - device, public_key, preshared_key, endpoint, allowed_ips, latest_handshake, transfer_rx, transfer_tx, persistent_keepalive = items - if allowed_ips == '(none)': - allowed_ips = [] - else: - allowed_ips = allowed_ips.split('\t') - output[device]['peers'][public_key] = { - 'preshared_key': None if preshared_key == '(none)' else preshared_key, - 'endpoint': None if endpoint == '(none)' else endpoint, - 'allowed_ips': allowed_ips, - 'latest_handshake': None if latest_handshake == '0' else int(latest_handshake), - 'transfer_rx': int(transfer_rx), - 'transfer_tx': int(transfer_tx), - 'persistent_keepalive': None if persistent_keepalive == 'off' else int(persistent_keepalive), - } - return output diff --git a/python/vyos/migrator.py b/python/vyos/migrator.py index f05228041..9a5fdef2f 100644 --- a/python/vyos/migrator.py +++ b/python/vyos/migrator.py @@ -25,7 +25,7 @@ class MigratorError(Exception): pass class Migrator(object): - def __init__(self, config_file, force=False, set_vintage=None): + def __init__(self, config_file, force=False, set_vintage='vyos'): self._config_file = config_file self._force = force self._set_vintage = set_vintage @@ -61,9 +61,6 @@ class Migrator(object): if self._set_vintage: self._config_file_vintage = self._set_vintage - if not self._config_file_vintage: - self._config_file_vintage = vyos.defaults.cfg_vintage - if self._config_file_vintage not in ['vyatta', 'vyos']: raise MigratorError("Unknown vintage.") @@ -204,16 +201,12 @@ class Migrator(object): return self._changed class VirtualMigrator(Migrator): - def __init__(self, config_file, vintage='vyos'): - super().__init__(config_file, set_vintage = vintage) - def run(self): cfg_file = self._config_file cfg_versions = self.read_config_file_versions() if not cfg_versions: - raise MigratorError("Config file has no version information;" - " virtual migration not possible.") + return if self.update_vintage(): self._changed = True diff --git a/python/vyos/util.py b/python/vyos/util.py index 635b11ee5..67aa87a3a 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -84,6 +84,8 @@ def colon_separated_to_dict(data_string, uniquekeys=False): def process_running(pid_file): """ Checks if a process with PID in pid_file is running """ + if not os.path.isfile(pid_file): + return False with open(pid_file, 'r') as f: pid = f.read().strip() return psutil.pid_exists(int(pid)) |