diff options
35 files changed, 243 insertions, 60 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8458d3208..e74cf3d0e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,7 +42,7 @@ in your commit message, as shown below: * `ddclient: T1030: auto create runtime directories` * `Jenkins: add current Git commit ID to build description` -If there is no [Phabricator](https://phabricator.vyos.net) reference in the +If there is no [Phabricator](https://vyos.dev) reference in the commits of your pull request, we have to ask you to amend the commit message. Otherwise we will have to reject it. @@ -126,7 +126,7 @@ also contain information that is helpful for the development team. ### Reporting In order to open up a bug-report/feature request you need to create yourself -an account on [Phabricator](https://phabricator.vyos.net). On the left +an account on [Phabricator](https://vyos.dev). On the left side of the specific project (VyOS 1.2 or VyOS 1.3) you will find quick-links for opening a bug-report/feature request. @@ -141,7 +141,7 @@ for opening a bug-report/feature request. You have an idea of how to make VyOS better or you are in need of a specific feature which all users of VyOS would benefit from? To send a feature request -please search [Phabricator](https://phabricator.vyos.net) if there is already a +please search [Phabricator](https://vyos.dev) if there is already a request pending. You can enhance it or if you don't find one, create a new one by use the quick link in the left side under the specific project. diff --git a/data/templates/accel-ppp/config_ip_pool.j2 b/data/templates/accel-ppp/config_ip_pool.j2 index 3b0f68084..f61a4f148 100644 --- a/data/templates/accel-ppp/config_ip_pool.j2 +++ b/data/templates/accel-ppp/config_ip_pool.j2 @@ -11,4 +11,14 @@ gw-ip-address={{ gateway_address }} {{ subnet }} {% endfor %} {% endif %} +{% if client_ip_pool.name is defined and client_ip_pool.name is not none %} +{% for pool, pool_config in client_ip_pool.name.items() %} +{% if pool_config.subnet is defined and pool_config.subnet is not none %} +{{ pool_config.subnet }},name={{ pool }} +{% endif %} +{% if pool_config.gateway_address is defined and pool_config.gateway_address is not none %} +gw-ip-address={{ pool_config.gateway_address }} +{% endif %} +{% endfor %} +{% endif %} {% endif %} diff --git a/data/templates/accel-ppp/config_shaper_radius.j2 b/data/templates/accel-ppp/config_shaper_radius.j2 index c409c3718..b7bd9c128 100644 --- a/data/templates/accel-ppp/config_shaper_radius.j2 +++ b/data/templates/accel-ppp/config_shaper_radius.j2 @@ -1,7 +1,7 @@ -{% if authentication is defined and authentication.mode is defined and authentication.mode == 'radius' %} -{% if authentication is defined and authentication.radius is defined and authentication.radius.rate_limit is defined and authentication.radius.rate_limit.enable is defined %} +{% if authentication is defined and authentication.mode is defined and authentication.mode == 'radius' or shaper is defined %} [shaper] verbose=1 +{% if authentication is defined and authentication.radius is defined and authentication.radius.rate_limit is defined and authentication.radius.rate_limit.enable is defined %} attr={{ authentication.radius.rate_limit.attribute }} {% if authentication.radius.rate_limit.vendor is defined and authentication.radius.rate_limit.vendor is not none %} vendor={{ authentication.radius.rate_limit.vendor }} @@ -10,4 +10,10 @@ vendor={{ authentication.radius.rate_limit.vendor }} rate-multiplier={{ authentication.radius.rate_limit.multiplier }} {% endif %} {% endif %} +{% if shaper is defined %} +{% if shaper.fwmark is defined and shaper.fwmark is not none %} +fwmark={{ shaper.fwmark }} +down-limiter=htb +{% endif %} +{% endif %} {% endif %} diff --git a/data/templates/accel-ppp/pppoe.config.tmpl b/data/templates/accel-ppp/pppoe.config.tmpl index a44208e15..b37004f5b 100644 --- a/data/templates/accel-ppp/pppoe.config.tmpl +++ b/data/templates/accel-ppp/pppoe.config.tmpl @@ -65,8 +65,6 @@ ccp={{ "1" if ppp_options.ccp is defined else "0" }} unit-preallocate={{ "1" if authentication.radius.preallocate_vif is defined else "0" }} {% if ppp_options.min_mtu is defined and ppp_options.min_mtu is not none %} min-mtu={{ ppp_options.min_mtu }} -{% else %} -min-mtu={{ mtu }} {% endif %} {% if ppp_options.mru is defined and ppp_options.mru is not none %} mru={{ ppp_options.mru }} @@ -138,6 +136,21 @@ pado-delay={{ pado_delay_param.value }} called-sid={{ authentication.radius.called_sid_format }} {% endif %} +{% if authentication is defined and authentication.mode is defined and authentication.mode == 'local' %} +{% if client_ip_pool is defined and client_ip_pool is not none %} +{% if client_ip_pool.name is defined and client_ip_pool.name is not none %} +{% for pool, pool_config in client_ip_pool.name.items() %} +{% if pool_config.subnet is defined and pool_config.subnet is not none %} +ip-pool={{ pool }} +{% if pool_config.gateway_address is defined and pool_config.gateway_address is not none %} +gw-ip-address={{ pool_config.gateway_address }}/{{ pool_config.subnet.split('/')[1] }} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% endif %} +{% endif %} + {% if limits is defined %} [connlimit] {% if limits.connection_limit is defined and limits.connection_limit is not none %} diff --git a/data/templates/pppoe/ip-down.script.tmpl b/data/templates/pppoe/ip-down.script.tmpl index c1d1132b3..9db3219b3 100644 --- a/data/templates/pppoe/ip-down.script.tmpl +++ b/data/templates/pppoe/ip-down.script.tmpl @@ -11,7 +11,7 @@ DIALER_PID=$(cat /var/run/{{ ifname }}.pid) logger -t pppd[$DIALER_PID] "executing $0" {% if connect_on_demand is not defined %} -# See https://phabricator.vyos.net/T2248. Determine if we are enslaved to a +# See https://vyos.dev/T2248. Determine if we are enslaved to a # VRF, this is needed to properly insert the default route. VRF_NAME="" if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then diff --git a/data/templates/pppoe/ip-up.script.tmpl b/data/templates/pppoe/ip-up.script.tmpl index 302756960..7f0c234fe 100644 --- a/data/templates/pppoe/ip-up.script.tmpl +++ b/data/templates/pppoe/ip-up.script.tmpl @@ -12,7 +12,7 @@ DIALER_PID=$(cat /var/run/{{ ifname }}.pid) logger -t pppd[$DIALER_PID] "executing $0" {% if default_route != 'none' %} -# See https://phabricator.vyos.net/T2248 & T2220. Determine if we are enslaved +# See https://vyos.dev/T2248 & T2220. Determine if we are enslaved # to a VRF, this is needed to properly insert the default route. SED_OPT="^ip route" diff --git a/data/templates/pppoe/ipv6-up.script.tmpl b/data/templates/pppoe/ipv6-up.script.tmpl index 238f8c28e..245ef1b87 100644 --- a/data/templates/pppoe/ipv6-up.script.tmpl +++ b/data/templates/pppoe/ipv6-up.script.tmpl @@ -54,7 +54,7 @@ systemctl restart dhcp6c@{{ ifname }}.service {% endif %} {% if default_route != 'none' %} -# See https://phabricator.vyos.net/T2248 & T2220. Determine if we are enslaved +# See https://vyos.dev/T2248 & T2220. Determine if we are enslaved # to a VRF, this is needed to properly insert the default route. SED_OPT="^ipv6 route" diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install index 96c3f2008..82f3f73fc 100644 --- a/debian/vyos-1x.install +++ b/debian/vyos-1x.install @@ -1,3 +1,4 @@ +etc/commit etc/dhcp etc/netplug etc/ppp diff --git a/interface-definitions/include/accel-ppp/client-ip-pool-name.xml.i b/interface-definitions/include/accel-ppp/client-ip-pool-name.xml.i new file mode 100644 index 000000000..654b6727e --- /dev/null +++ b/interface-definitions/include/accel-ppp/client-ip-pool-name.xml.i @@ -0,0 +1,18 @@ +<!-- include start from accel-ppp/client-ip-pool-name.xml.i --> +<tagNode name="name"> + <properties> + <help>Pool name</help> + <valueHelp> + <format>txt</format> + <description>Name of IP pool</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]+</regex> + </constraint> + </properties> + <children> + #include <include/accel-ppp/gateway-address.xml.i> + #include <include/accel-ppp/client-ip-pool-subnet-single.xml.i> + </children> +</tagNode> +<!-- include end --> diff --git a/interface-definitions/include/accel-ppp/shaper.xml.i b/interface-definitions/include/accel-ppp/shaper.xml.i new file mode 100644 index 000000000..b4f9536d2 --- /dev/null +++ b/interface-definitions/include/accel-ppp/shaper.xml.i @@ -0,0 +1,21 @@ +<!-- include start from accel-ppp/shaper.xml.i --> +<node name="shaper"> + <properties> + <help>Traffic shaper bandwidth parameters</help> + </properties> + <children> + <leafNode name="fwmark"> + <properties> + <help>Firewall mark value for traffic that excludes from shaping</help> + <valueHelp> + <format>u32:1-2147483647</format> + <description>Match firewall mark value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-2147483647"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index fa54aedc1..7543df412 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -74,10 +74,10 @@ <help>Secure Connectivity Association Key Name</help> <valueHelp> <format>txt</format> - <description>32-byte (256-bit) hex-string (64 hex-digits)</description> + <description>>1..32-bytes (8..256 bit) hex-string (2..64 hex-digits)</description> </valueHelp> <constraint> - <regex>^[A-Fa-f0-9]{64}$</regex> + <regex>^[A-Fa-f0-9]{2,64}$</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/service_ipoe-server.xml.in b/interface-definitions/service_ipoe-server.xml.in index b9279793c..d81ec99f9 100644 --- a/interface-definitions/service_ipoe-server.xml.in +++ b/interface-definitions/service_ipoe-server.xml.in @@ -117,19 +117,7 @@ <help>Client IP pools and gateway setting</help> </properties> <children> - <tagNode name="name"> - <properties> - <help>Pool name</help> - <constraint> - <regex>[-_a-zA-Z0-9]+</regex> - </constraint> - <constraintErrorMessage>Client IP pool is limited to alphanumerical characters and can contain hyphen and underscores</constraintErrorMessage> - </properties> - <children> - #include <include/accel-ppp/gateway-address.xml.i> - #include <include/accel-ppp/client-ip-pool-subnet-single.xml.i> - </children> - </tagNode> + #include <include/accel-ppp/client-ip-pool-name.xml.i> </children> </node> #include <include/accel-ppp/client-ipv6-pool.xml.i> diff --git a/interface-definitions/service_pppoe-server.xml.in b/interface-definitions/service_pppoe-server.xml.in index 36bea6a7a..65868226b 100644 --- a/interface-definitions/service_pppoe-server.xml.in +++ b/interface-definitions/service_pppoe-server.xml.in @@ -56,6 +56,7 @@ <children> #include <include/accel-ppp/client-ip-pool-start-stop.xml.i> #include <include/accel-ppp/client-ip-pool-subnet.xml.i> + #include <include/accel-ppp/client-ip-pool-name.xml.i> </children> </node> #include <include/accel-ppp/client-ipv6-pool.xml.i> @@ -148,6 +149,7 @@ <validator name="numeric" argument="--range 68-65535"/> </constraint> </properties> + <defaultValue>1280</defaultValue> </leafNode> <leafNode name="mru"> <properties> @@ -324,6 +326,7 @@ </properties> <defaultValue>replace</defaultValue> </leafNode> + #include <include/accel-ppp/shaper.xml.i> <node name="snmp"> <properties> <help>Enable SNMP</help> diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index a35ea0b74..6afb1c596 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -1,4 +1,4 @@ -# Copyright 2020-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2020-2023 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 @@ -23,6 +23,7 @@ from vyos import ConfigError from vyos.util import dict_search +from vyos.util import dict_search_recursive def verify_mtu(config): """ @@ -35,8 +36,14 @@ def verify_mtu(config): mtu = int(config['mtu']) tmp = Interface(config['ifname']) - min_mtu = tmp.get_min_mtu() - max_mtu = tmp.get_max_mtu() + # Not all interfaces support min/max MTU + # https://vyos.dev/T5011 + try: + min_mtu = tmp.get_min_mtu() + max_mtu = tmp.get_max_mtu() + except: # Fallback to defaults + min_mtu = 68 + max_mtu = 9000 if mtu < min_mtu: raise ConfigError(f'Interface MTU too low, ' \ @@ -355,7 +362,18 @@ def verify_accel_ppp_base_service(config): if 'key' not in radius_config: raise ConfigError(f'Missing RADIUS secret key for server "{server}"') - if 'gateway_address' not in config: + # Check global gateway or gateway in named pool + gateway = False + if 'gateway_address' in config: + gateway = True + else: + if 'client_ip_pool' in config: + if dict_search_recursive(config, 'gateway_address', ['client_ip_pool', 'name']): + for _, v in config['client_ip_pool']['name'].items(): + if 'gateway_address' in v: + gateway = True + break + if not gateway: raise ConfigError('Server requires gateway-address to be configured!') if 'name_server_ipv4' in config: @@ -427,4 +445,3 @@ def verify_common_route_maps(config): for protocol, protocol_config in config['redistribute'].items(): if 'route_map' in protocol_config: verify_route_map(protocol_config['route_map'], config) - diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py index 30c890fdf..1b8161ce5 100644 --- a/python/vyos/ifconfig/loopback.py +++ b/python/vyos/ifconfig/loopback.py @@ -47,7 +47,7 @@ class LoopbackIf(Interface): if addr in self._persistent_addresses: # Do not allow deletion of the default loopback addresses as # this will cause weird system behavior like snmp/ssh no longer - # operating as expected, see https://phabricator.vyos.net/T2034. + # operating as expected, see https://vyos.dev/T2034. continue self.del_addr(addr) diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py index 5258a2cb1..f776240a1 100644 --- a/python/vyos/ifconfig/tunnel.py +++ b/python/vyos/ifconfig/tunnel.py @@ -162,6 +162,15 @@ class TunnelIf(Interface): """ Get a synthetic MAC address. """ return self.get_mac_synthetic() + def set_multicast(self): + """ Set multicast """ + if self.config.get('multicast', 'disable') == 'enable': + cmd = 'ip link set dev {ifname} multicast on' + else: + cmd = 'ip link set dev {ifname} multicast off' + + self._cmd(cmd.format(**self.config)) + def update(self, config): """ General helper function which works on a dictionary retrived by get_config_dict(). It's main intention is to consolidate the scattered @@ -170,5 +179,8 @@ class TunnelIf(Interface): # Adjust iproute2 tunnel parameters if necessary self._change_options() + # Add multicast + self.set_multicast() + # call base class first super().update(config) diff --git a/python/vyos/util.py b/python/vyos/util.py index 5c6409341..32a5ae116 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2020-2023 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 @@ -720,6 +720,26 @@ def dict_search(path, dict_object): c = c.get(p, {}) return c.get(parts[-1], None) +def dict_search_recursive(dict_object, key, path=[]): + """ Traverse a dictionary recurisvely and return the value of the key + we are looking for. + Thankfully copied from https://stackoverflow.com/a/19871956 + Modified to yield optional path to found keys + """ + if isinstance(dict_object, list): + for i in dict_object: + new_path = path + [i] + for x in dict_search_recursive(i, key, new_path): + yield x + elif isinstance(dict_object, dict): + if key in dict_object: + new_path = path + [key] + yield dict_object[key], new_path + for k, j in dict_object.items(): + new_path = path + [k] + for x in dict_search_recursive(j, key, new_path): + yield x + def convert_data(data): """Convert multiple types of data to types usable in CLI diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index b3492b074..856471c94 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -116,7 +116,7 @@ class BasicInterfaceTest: # Also enable DHCP (ISC DHCP always places interface in admin up # state so we check that we do not start DHCP client. - # https://phabricator.vyos.net/T2767 + # https://vyos.dev/T2767 self.cli_set(self._base_path + [interface, 'address', 'dhcp']) self.cli_commit() @@ -395,7 +395,7 @@ class BasicInterfaceTest: def test_vif_8021q_lower_up_down(self): - # Testcase for https://phabricator.vyos.net/T3349 + # Testcase for https://vyos.dev/T3349 if not self._test_vlan: self.skipTest('not supported') diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py index 21d1028ce..8514801a8 100755 --- a/smoketest/scripts/cli/test_service_pppoe-server.py +++ b/smoketest/scripts/cli/test_service_pppoe-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -147,6 +147,8 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): self.basic_config() subnet = '172.18.0.0/24' + fwmark = '223' + limiter = 'htb' self.set(['client-ip-pool', 'subnet', subnet]) start = '192.0.2.10' @@ -155,6 +157,7 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): start_stop = f'{start}-{stop_octet}' self.set(['client-ip-pool', 'start', start]) self.set(['client-ip-pool', 'stop', stop]) + self.set(['shaper', 'fwmark', fwmark]) # commit changes self.cli_commit() @@ -172,6 +175,35 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): self.assertTrue(process_named_running(self._process_name)) + def test_pppoe_server_client_ip_pool_name(self): + # Test configuration of named client pools + self.basic_config() + + subnet = '192.0.2.0/24' + gateway = '192.0.2.1' + pool = 'VYOS' + + subnet_name = f'{subnet},name' + gw_ip_prefix = f'{gateway}/24' + + self.set(['client-ip-pool', 'name', pool, 'subnet', subnet]) + self.set(['client-ip-pool', 'name', pool, 'gateway-address', gateway]) + self.cli_delete(self._base_path + ['gateway-address']) + + # commit changes + self.cli_commit() + + # Validate configuration values + conf = ConfigParser(allow_no_value=True, delimiters='=') + conf.read(self._config_file) + + # Validate configuration + self.assertEqual(conf['ip-pool'][subnet_name], pool) + self.assertEqual(conf['ip-pool']['gw-ip-address'], gateway) + self.assertEqual(conf['pppoe']['ip-pool'], pool) + self.assertEqual(conf['pppoe']['gw-ip-address'], gw_ip_prefix) + + def test_pppoe_server_client_ipv6_pool(self): # Test configuration of IPv6 client pools self.basic_config() diff --git a/smoketest/scripts/cli/test_service_tftp-server.py b/smoketest/scripts/cli/test_service_tftp-server.py index 99d81e203..642b6af88 100755 --- a/smoketest/scripts/cli/test_service_tftp-server.py +++ b/smoketest/scripts/cli/test_service_tftp-server.py @@ -18,6 +18,7 @@ import unittest from psutil import process_iter from base_vyostest_shim import VyOSUnitTestSHIM +from time import sleep from vyos.configsession import ConfigSessionError from vyos.util import cmd @@ -51,7 +52,14 @@ class TestServiceTFTPD(VyOSUnitTestSHIM.TestCase): def tearDown(self): # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) + count = 0 + while count < 10: + count += 1 + tmp = process_named_running(PROCESS_NAME) + print(tmp) + if tmp: break + sleep(1) + self.assertTrue(tmp) self.cli_delete(base_path) self.cli_commit() @@ -140,7 +148,13 @@ class TestServiceTFTPD(VyOSUnitTestSHIM.TestCase): self.assertIn('--create --umask 000', config) # Check for process in VRF - tmp = cmd(f'ip vrf pids {vrf}') + count = 0 + while count < 10: + count += 1 + tmp = cmd(f'ip vrf pids {vrf}') + print(tmp) + if tmp: break + sleep(1) self.assertIn(PROCESS_NAME, tmp) # delete VRF diff --git a/sonar-project.properties b/sonar-project.properties index 1258da817..eddfd5e1e 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -10,7 +10,7 @@ sonar.sourceEncoding=UTF-8 sonar.links.homepage=https://github.com/vyos/vyos-1x sonar.links.ci=https://ci.vyos.net/job/vyos-1x/ sonar.links.scm=https://github.com/vyos/vyos-1x -sonar.links.issue=https://phabricator.vyos.net/ +sonar.links.issue=https://vyos.dev/ sonar.host.url=https://sonarcloud.io diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 08861053d..90e5f84f2 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2022 VyOS maintainers and contributors +# Copyright (C) 2021-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -84,16 +84,16 @@ def get_config(config=None): # tagNodes in place, it is better to blend in the defaults manually. if 'port' in container['name'][name]: for port in container['name'][name]['port']: - default_values = defaults(base + ['name', 'port']) + default_values_port = defaults(base + ['name', 'port']) container['name'][name]['port'][port] = dict_merge( - default_values, container['name'][name]['port'][port]) + default_values_port, container['name'][name]['port'][port]) # XXX: T2665: we can not safely rely on the defaults() when there are # tagNodes in place, it is better to blend in the defaults manually. if 'volume' in container['name'][name]: for volume in container['name'][name]['volume']: - default_values = defaults(base + ['name', 'volume']) + default_values_volume = defaults(base + ['name', 'volume']) container['name'][name]['volume'][volume] = dict_merge( - default_values, container['name'][name]['volume'][volume]) + default_values_volume, container['name'][name]['volume'][volume]) # Delete container network, delete containers tmp = node_changed(conf, base + ['network']) diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py index d27f8d995..11ee6b60a 100755 --- a/src/conf_mode/dhcp_server.py +++ b/src/conf_mode/dhcp_server.py @@ -283,7 +283,7 @@ def generate(dhcp): if not dhcp or 'disable' in dhcp: return None - # Please see: https://phabricator.vyos.net/T1129 for quoting of the raw + # Please see: https://vyos.dev/T1129 for quoting of the raw # parameters we can pass to ISC DHCPd tmp_file = '/tmp/dhcpd.conf' render(tmp_file, 'dhcp-server/dhcpd.conf.tmpl', dhcp, diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index fe5898282..7e2e025ba 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -489,7 +489,7 @@ def generate(openvpn): user=user, group=group) # we need to support quoting of raw parameters from OpenVPN CLI - # see https://phabricator.vyos.net/T1632 + # see https://vyos.dev/T1632 render(cfg_file.format(**openvpn), 'openvpn/server.conf.tmpl', openvpn, formater=lambda _: _.replace(""", '"'), user=user, group=group) diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index 25ff9d0dd..0be0da3d1 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -145,7 +145,7 @@ def get_config(): # Always listen on localhost if an explicit address has been configured # This is a safety measure to not end up with invalid listen addresses - # that are not configured on this system. See https://phabricator.vyos.net/T850 + # that are not configured on this system. See https://vyos.dev/T850 if not '127.0.0.1' in conf.list_nodes('listen-address'): snmp['listen_address'].append(('127.0.0.1', '161')) diff --git a/src/etc/commit/post-hooks.d/00vyos-sync b/src/etc/commit/post-hooks.d/00vyos-sync new file mode 100755 index 000000000..8ec732df0 --- /dev/null +++ b/src/etc/commit/post-hooks.d/00vyos-sync @@ -0,0 +1,7 @@ +#!/bin/sh +# When power is lost right after a commit modified files, the +# system can be corrupted and e.g. login is no longer possible. +# Always sync files to the backend storage after a commit. +# https://vyos.dev/T4975 +sync + diff --git a/src/migration-scripts/interfaces/0-to-1 b/src/migration-scripts/interfaces/0-to-1 index ee4d6b82c..c7f324661 100755 --- a/src/migration-scripts/interfaces/0-to-1 +++ b/src/migration-scripts/interfaces/0-to-1 @@ -3,7 +3,7 @@ # Change syntax of bridge interface # - move interface based bridge-group to actual bridge (de-nest) # - make stp and igmp-snooping nodes valueless -# https://phabricator.vyos.net/T1556 +# https://vyos.dev/T1556 import sys from vyos.configtree import ConfigTree diff --git a/src/migration-scripts/interfaces/1-to-2 b/src/migration-scripts/interfaces/1-to-2 index 050137318..c75404d85 100755 --- a/src/migration-scripts/interfaces/1-to-2 +++ b/src/migration-scripts/interfaces/1-to-2 @@ -2,7 +2,7 @@ # Change syntax of bond interface # - move interface based bond-group to actual bond (de-nest) -# https://phabricator.vyos.net/T1614 +# https://vyos.dev/T1614 import sys from vyos.configtree import ConfigTree @@ -40,7 +40,7 @@ else: # some combinations were allowed in the past from a CLI perspective # but the kernel overwrote them - remove from CLI to not confuse the users. # In addition new consitency checks are in place so users can't repeat the - # mistake. One of those nice issues is https://phabricator.vyos.net/T532 + # mistake. One of those nice issues is https://vyos.dev/T532 for bond in config.list_nodes(base): if config.exists(base + [bond, 'arp-monitor', 'interval']) and config.exists(base + [bond, 'mode']): mode = config.return_value(base + [bond, 'mode']) diff --git a/src/migration-scripts/interfaces/16-to-17 b/src/migration-scripts/interfaces/16-to-17 index a6b4c7663..d123be06f 100755 --- a/src/migration-scripts/interfaces/16-to-17 +++ b/src/migration-scripts/interfaces/16-to-17 @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # Command line migration of port mirroring -# https://phabricator.vyos.net/T3089 +# https://vyos.dev/T3089 import sys from vyos.configtree import ConfigTree diff --git a/src/migration-scripts/interfaces/2-to-3 b/src/migration-scripts/interfaces/2-to-3 index a63a54cdf..68d41de39 100755 --- a/src/migration-scripts/interfaces/2-to-3 +++ b/src/migration-scripts/interfaces/2-to-3 @@ -2,7 +2,7 @@ # Change syntax of openvpn encryption settings # - move cipher from encryption to encryption cipher -# https://phabricator.vyos.net/T1704 +# https://vyos.dev/T1704 import sys from vyos.configtree import ConfigTree diff --git a/src/migration-scripts/interfaces/20-to-21 b/src/migration-scripts/interfaces/20-to-21 index 0bd858760..cb1c36882 100755 --- a/src/migration-scripts/interfaces/20-to-21 +++ b/src/migration-scripts/interfaces/20-to-21 @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # T3619: mirror Linux Kernel defaults for ethernet offloading options into VyOS -# CLI. See https://phabricator.vyos.net/T3619#102254 for all the details. +# CLI. See https://vyos.dev/T3619#102254 for all the details. # T3787: Remove deprecated UDP fragmentation offloading option from sys import argv diff --git a/src/migration-scripts/interfaces/4-to-5 b/src/migration-scripts/interfaces/4-to-5 index 2a42c60ff..f645c5aeb 100755 --- a/src/migration-scripts/interfaces/4-to-5 +++ b/src/migration-scripts/interfaces/4-to-5 @@ -50,7 +50,7 @@ def migrate_dialer(config, tree, intf): # Remove IPv6 router-advert nodes as this makes no sense on a # client diale rinterface to send RAs back into the network - # https://phabricator.vyos.net/T2055 + # https://vyos.dev/T2055 ipv6_ra = pppoe_base + ['ipv6', 'router-advert'] if config.exists(ipv6_ra): config.delete(ipv6_ra) diff --git a/src/migration-scripts/snmp/0-to-1 b/src/migration-scripts/snmp/0-to-1 index a836f7011..096ba779d 100755 --- a/src/migration-scripts/snmp/0-to-1 +++ b/src/migration-scripts/snmp/0-to-1 @@ -33,18 +33,18 @@ if not config.exists(config_base): # Nothing to do sys.exit(0) else: - # we no longer support a per trap target engine ID (https://phabricator.vyos.net/T818) + # we no longer support a per trap target engine ID (https://vyos.dev/T818) if config.exists(config_base + ['v3', 'trap-target']): for target in config.list_nodes(config_base + ['v3', 'trap-target']): config.delete(config_base + ['v3', 'trap-target', target, 'engineid']) - # we no longer support a per user engine ID (https://phabricator.vyos.net/T818) + # we no longer support a per user engine ID (https://vyos.dev/T818) if config.exists(config_base + ['v3', 'user']): for user in config.list_nodes(config_base + ['v3', 'user']): config.delete(config_base + ['v3', 'user', user, 'engineid']) # we drop TSM support as there seem to be no users and this code is untested - # https://phabricator.vyos.net/T1769 + # https://vyos.dev/T1769 if config.exists(config_base + ['v3', 'tsm']): config.delete(config_base + ['v3', 'tsm']) diff --git a/src/op_mode/restart_dhcp_relay.py b/src/op_mode/restart_dhcp_relay.py index af4fb2d15..23df92243 100755 --- a/src/op_mode/restart_dhcp_relay.py +++ b/src/op_mode/restart_dhcp_relay.py @@ -39,7 +39,7 @@ if __name__ == '__main__': if not c.exists_effective('service dhcp-relay'): print("DHCP relay service not configured") else: - call('systemctl restart isc-dhcp-server.service') + call('systemctl restart isc-dhcp-relay.service') sys.exit(0) elif args.ipv6: @@ -47,7 +47,7 @@ if __name__ == '__main__': if not c.exists_effective('service dhcpv6-relay'): print("DHCPv6 relay service not configured") else: - call('systemctl restart isc-dhcp-server6.service') + call('systemctl restart isc-dhcp-relay6.service') sys.exit(0) else: diff --git a/src/tests/test_dict_search.py b/src/tests/test_dict_search.py index 6a0fc74ad..deee9a657 100644 --- a/src/tests/test_dict_search.py +++ b/src/tests/test_dict_search.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -16,14 +16,28 @@ from unittest import TestCase from vyos.util import dict_search +from vyos.util import dict_search_recursive data = { 'string': 'fooo', 'nested': {'string': 'bar', 'empty': '', 'list': ['foo', 'bar']}, + 'non': {}, 'list': ['bar', 'baz'], - 'dict': {'key_1': {}, 'key_2': 'vyos'} + 'dict': {'key_1': {}, 'key_2': 'vyos'}, + 'interfaces': {'dummy': {'dum0': {'address': ['192.0.2.17/29']}}, + 'ethernet': {'eth0': {'address': ['2001:db8::1/64', '192.0.2.1/29'], + 'description': 'Test123', + 'duplex': 'auto', + 'hw_id': '00:00:00:00:00:01', + 'speed': 'auto'}, + 'eth1': {'address': ['192.0.2.9/29'], + 'description': 'Test456', + 'duplex': 'auto', + 'hw_id': '00:00:00:00:00:02', + 'speed': 'auto'}}} } + class TestDictSearch(TestCase): def setUp(self): pass @@ -55,3 +69,10 @@ class TestDictSearch(TestCase): def test_nested_list(self): # TestDictSearch: Return list items when querying nested list self.assertEqual(dict_search('nested.list', data), data['nested']['list']) + + def test_dict_search_recursive(self): + # Test nested search in dictionary + tmp = list(dict_search_recursive(data, 'hw_id')) + self.assertEqual(len(tmp), 2) + tmp = list(dict_search_recursive(data, 'address')) + self.assertEqual(len(tmp), 3) |