diff options
35 files changed, 318 insertions, 169 deletions
diff --git a/data/templates/frr/staticd.frr.tmpl b/data/templates/frr/staticd.frr.tmpl index db59a44c2..bfe959c1d 100644 --- a/data/templates/frr/staticd.frr.tmpl +++ b/data/templates/frr/staticd.frr.tmpl @@ -15,6 +15,15 @@ vrf {{ vrf }} {{ static_routes(ip_prefix, prefix, prefix_config) }} {%- endfor -%} {% endif %} +{# IPv4 default routes from DHCP interfaces #} +{% if dhcp is defined and dhcp is not none %} +{% for interface in dhcp %} +{% set next_hop = interface | get_dhcp_router %} +{% if next_hop is defined and next_hop is not none %} +{{ ip_prefix }} route 0.0.0.0/0 {{ next_hop }} {{ interface }} tag 210 210 +{% endif %} +{% endfor %} +{% endif %} {# IPv6 routing #} {% if route6 is defined and route6 is not none %} {% for prefix, prefix_config in route6.items() %} diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install index d332e0d36..10426260a 100644 --- a/debian/vyos-1x.install +++ b/debian/vyos-1x.install @@ -1,6 +1,7 @@ etc/cron.hourly etc/dhcp etc/ipsec.d +etc/logrotate.d etc/netplug etc/opennhrp etc/ppp diff --git a/interface-definitions/bcast-relay.xml.in b/interface-definitions/bcast-relay.xml.in index 3f781f07f..aeaa5ab37 100644 --- a/interface-definitions/bcast-relay.xml.in +++ b/interface-definitions/bcast-relay.xml.in @@ -39,15 +39,7 @@ <help>Description</help> </properties> </leafNode> - <leafNode name="interface"> - <properties> - <help>Interface to repeat UDP broadcasts to [REQUIRED]</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi.xml.i> #include <include/port-number.xml.i> </children> </tagNode> diff --git a/interface-definitions/dhcp-relay.xml.in b/interface-definitions/dhcp-relay.xml.in index 0d485ef80..483e776a7 100644 --- a/interface-definitions/dhcp-relay.xml.in +++ b/interface-definitions/dhcp-relay.xml.in @@ -9,15 +9,7 @@ <priority>910</priority> </properties> <children> - <leafNode name="interface"> - <properties> - <help>DHCP relay interface [REQUIRED]</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py -b</script> - </completionHelp> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi-broadcast.xml.i> <node name="relay-options"> <properties> <help>Relay options</help> diff --git a/interface-definitions/dhcp-server.xml.in b/interface-definitions/dhcp-server.xml.in index 47bdc4db1..45a629181 100644 --- a/interface-definitions/dhcp-server.xml.in +++ b/interface-definitions/dhcp-server.xml.in @@ -289,9 +289,9 @@ <properties> <help>Name of static mapping</help> <constraint> - <regex>[-_a-zA-Z0-9.]+</regex> + <regex>^[-_a-zA-Z0-9]+$</regex> </constraint> - <constraintErrorMessage>Invalid static mapping name. May only contain letters, numbers and .-_</constraintErrorMessage> + <constraintErrorMessage>Invalid static mapping name. May only contain letters, numbers and a hyphen (-)!</constraintErrorMessage> </properties> <children> #include <include/generic-disable-node.xml.i> diff --git a/interface-definitions/flow-accounting-conf.xml.in b/interface-definitions/flow-accounting-conf.xml.in index b0f308afd..113c1d849 100644 --- a/interface-definitions/flow-accounting-conf.xml.in +++ b/interface-definitions/flow-accounting-conf.xml.in @@ -136,15 +136,7 @@ </constraint> </properties> </leafNode> - <leafNode name="interface"> - <properties> - <help>Interface for flow-accounting [REQUIRED]</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi.xml.i> <node name="netflow"> <properties> <help>NetFlow settings</help> diff --git a/interface-definitions/include/generic-interface-broadcast.xml.i b/interface-definitions/include/generic-interface-broadcast.xml.i new file mode 100644 index 000000000..6f76dde1a --- /dev/null +++ b/interface-definitions/include/generic-interface-broadcast.xml.i @@ -0,0 +1,17 @@ +<!-- include start from generic-interface-broadcast.xml.i --> +<leafNode name="interface"> + <properties> + <help>Interface Name to use</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/generic-interface-multi-broadcast.xml.i b/interface-definitions/include/generic-interface-multi-broadcast.xml.i new file mode 100644 index 000000000..00638f3b7 --- /dev/null +++ b/interface-definitions/include/generic-interface-multi-broadcast.xml.i @@ -0,0 +1,18 @@ +<!-- include start from generic-interface-multi-broadcast.xml.i --> +<leafNode name="interface"> + <properties> + <help>Interface Name to use</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + <multi/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/generic-interface-multi.xml.i b/interface-definitions/include/generic-interface-multi.xml.i new file mode 100644 index 000000000..44e87775c --- /dev/null +++ b/interface-definitions/include/generic-interface-multi.xml.i @@ -0,0 +1,18 @@ +<!-- include start from generic-interface-multi.xml.i --> +<leafNode name="interface"> + <properties> + <help>Interface Name to use</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + <multi/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/generic-interface.xml.i b/interface-definitions/include/generic-interface.xml.i new file mode 100644 index 000000000..50af718a5 --- /dev/null +++ b/interface-definitions/include/generic-interface.xml.i @@ -0,0 +1,17 @@ +<!-- include start from generic-interface.xml.i --> +<leafNode name="interface"> + <properties> + <help>Interface Name to use</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in index 05e0d8461..17879cf1e 100644 --- a/interface-definitions/interfaces-bonding.xml.in +++ b/interface-definitions/interfaces-bonding.xml.in @@ -177,6 +177,13 @@ <completionHelp> <script>${vyos_completion_dir}/list_interfaces.py --bondable</script> </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> <multi/> </properties> </leafNode> @@ -189,6 +196,13 @@ <completionHelp> <script>${vyos_completion_dir}/list_interfaces.py --bondable</script> </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> </properties> </leafNode> #include <include/interface/vif-s.xml.i> diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in index cf65daf00..225f9a6f9 100644 --- a/interface-definitions/policy.xml.in +++ b/interface-definitions/policy.xml.in @@ -597,14 +597,7 @@ </completionHelp> </properties> </leafNode> - <leafNode name="interface"> - <properties> - <help>First hop interface of a route to match</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - </properties> - </leafNode> + #include <include/generic-interface.xml.i> <node name="ip"> <properties> <help>IP prefix parameters to match</help> diff --git a/interface-definitions/protocols-bfd.xml.in b/interface-definitions/protocols-bfd.xml.in index cc3c3bf12..7b22b8125 100644 --- a/interface-definitions/protocols-bfd.xml.in +++ b/interface-definitions/protocols-bfd.xml.in @@ -43,14 +43,7 @@ <help>Bind listener to specified interface/address, mandatory for IPv6</help> </properties> <children> - <leafNode name="interface"> - <properties> - <help>Local interface to bind our peer listener to</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - </properties> - </leafNode> + #include <include/generic-interface.xml.i> <leafNode name="address"> <properties> <help>Local address to bind our peer listener to</help> diff --git a/interface-definitions/protocols-mpls.xml.in b/interface-definitions/protocols-mpls.xml.in index e7646e625..be8e30c18 100644 --- a/interface-definitions/protocols-mpls.xml.in +++ b/interface-definitions/protocols-mpls.xml.in @@ -524,15 +524,7 @@ </node> </children> </node> - <leafNode name="interface"> - <properties> - <help>Enable LDP and neighbor discovery on interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi.xml.i> </children> </node> <node name="parameters"> @@ -560,15 +552,7 @@ </leafNode> </children> </node> - <leafNode name="interface"> - <properties> - <help>Enable MPLS packet processing on interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi.xml.i> </children> </node> </children> diff --git a/interface-definitions/protocols-ospfv3.xml.in b/interface-definitions/protocols-ospfv3.xml.in index 99cfec661..fffeeb9a5 100644 --- a/interface-definitions/protocols-ospfv3.xml.in +++ b/interface-definitions/protocols-ospfv3.xml.in @@ -61,22 +61,7 @@ </completionHelp> </properties> </leafNode> - <leafNode name="interface"> - <properties> - <help>Enable routing on an IPv6 interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <valueHelp> - <format>txt</format> - <description>Interface used for routing information exchange</description> - </valueHelp> - <constraint> - <validator name="interface-name"/> - </constraint> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi.xml.i> <tagNode name="range"> <properties> <help>Specify IPv6 prefix (border routers only)</help> diff --git a/interface-definitions/service_mdns-repeater.xml.in b/interface-definitions/service_mdns-repeater.xml.in index d02dac8a6..9a94f1488 100644 --- a/interface-definitions/service_mdns-repeater.xml.in +++ b/interface-definitions/service_mdns-repeater.xml.in @@ -14,15 +14,7 @@ </properties> <children> #include <include/generic-disable-node.xml.i> - <leafNode name="interface"> - <properties> - <help>Interface to repeat mDNS advertisements [REQUIRED]</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi.xml.i> <leafNode name="vrrp-disable"> <properties> <help>Disables mDNS repeater on VRRP interfaces not in MASTER state</help> diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index 164ba6618..cfa456e42 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -498,15 +498,7 @@ <help>Sets to include an additional secrets file for strongSwan. Use an absolute path to specify the included file.</help> </properties> </leafNode> - <leafNode name="interface"> - <properties> - <help>Onterface used for IPsec communication</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> + #include <include/generic-interface-multi.xml.i> <node name="log"> <properties> <help>IPsec logging</help> @@ -822,14 +814,7 @@ <help>DHCP pool options for remote-access</help> </properties> <children> - <leafNode name="interface"> - <properties> - <help>Interface with DHCP server to use</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - </properties> - </leafNode> + #include <include/generic-interface.xml.i> <leafNode name="server"> <properties> <help>DHCP server address</help> diff --git a/interface-definitions/vrrp.xml.in b/interface-definitions/vrrp.xml.in index 44a9a1f54..53d79caac 100644 --- a/interface-definitions/vrrp.xml.in +++ b/interface-definitions/vrrp.xml.in @@ -16,14 +16,7 @@ <help>VRRP group</help> </properties> <children> - <leafNode name="interface"> - <properties> - <help>Network interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script> - </completionHelp> - </properties> - </leafNode> + #include <include/generic-interface-broadcast.xml.i> <leafNode name="advertise-interval"> <properties> <help>Advertise interval</help> diff --git a/op-mode-definitions/force-part-resize.xml.in b/op-mode-definitions/force-part-resize.xml.in new file mode 100644 index 000000000..cb76273c7 --- /dev/null +++ b/op-mode-definitions/force-part-resize.xml.in @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="force"> + <children> + <node name="resize-partition"> + <properties> + <help>Resize the VyOS partition</help> + </properties> + <command>${vyos_op_scripts_dir}/force_part_resize.sh</command> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index afdd62a73..425a2e416 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -155,18 +155,15 @@ def get_removed_vlans(conf, dict): D.set_level(conf.get_level()) # get_child_nodes() will return dict_keys(), mangle this into a list with PEP448 keys = D.get_child_nodes_diff(['vif'], expand_nodes=Diff.DELETE)['delete'].keys() - if keys: - dict.update({'vif_remove': [*keys]}) + if keys: dict['vif_remove'] = [*keys] # get_child_nodes() will return dict_keys(), mangle this into a list with PEP448 keys = D.get_child_nodes_diff(['vif-s'], expand_nodes=Diff.DELETE)['delete'].keys() - if keys: - dict.update({'vif_s_remove': [*keys]}) + if keys: dict['vif_s_remove'] = [*keys] for vif in dict.get('vif_s', {}).keys(): keys = D.get_child_nodes_diff(['vif-s', vif, 'vif-c'], expand_nodes=Diff.DELETE)['delete'].keys() - if keys: - dict.update({'vif_s': { vif : {'vif_c_remove': [*keys]}}}) + if keys: dict['vif_s'][vif]['vif_c_remove'] = [*keys] return dict @@ -319,6 +316,40 @@ def is_source_interface(conf, interface, intftype=None): old_level = conf.set_level(old_level) return ret_val +def get_dhcp_interfaces(conf, vrf=None): + """ Common helper functions to retrieve all interfaces from current CLI + sessions that have DHCP configured. """ + dhcp_interfaces = [] + dict = conf.get_config_dict(['interfaces'], get_first_key=True) + if not dict: + return dhcp_interfaces + + def check_dhcp(config, ifname): + out = [] + if 'address' in config and 'dhcp' in config['address']: + if 'vrf' in config: + if vrf is config['vrf']: out.append(ifname) + else: out.append(ifname) + return out + + for section, interface in dict.items(): + for ifname, ifconfig in interface.items(): + tmp = check_dhcp(ifconfig, ifname) + dhcp_interfaces.extend(tmp) + # check per VLAN interfaces + for vif, vif_config in ifconfig.get('vif', {}).items(): + tmp = check_dhcp(vif_config, f'{ifname}.{vif}') + dhcp_interfaces.extend(tmp) + # check QinQ VLAN interfaces + for vif_s, vif_s_config in ifconfig.get('vif-s', {}).items(): + tmp = check_dhcp(vif_s_config, f'{ifname}.{vif_s}') + dhcp_interfaces.extend(tmp) + for vif_c, vif_c_config in vif_s_config.get('vif-c', {}).items(): + tmp = check_dhcp(vif_c_config, f'{ifname}.{vif_s}.{vif_c}') + dhcp_interfaces.extend(tmp) + + return dhcp_interfaces + def get_interface_dict(config, base, ifname=''): """ Common utility function to retrieve and mangle the interfaces configuration diff --git a/python/vyos/template.py b/python/vyos/template.py index d13915766..b32cafe74 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -349,7 +349,6 @@ def get_dhcp_router(interface): Returns False of no router is found, returns the IP address as string if a router is found. """ - interface = interface.replace('.', '_') lease_file = f'/var/lib/dhcp/dhclient_{interface}.leases' if not os.path.exists(lease_file): return None diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index 90c534796..340ec4edd 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -493,6 +493,16 @@ class BasicInterfaceTest: tmp = get_interface_config(vif) self.assertEqual(tmp['mtu'], int(self._mtu)) + # T3972: remove vif-c interfaces from vif-s + for interface in self._interfaces: + base = self._base_path + [interface] + for vif_s in self._qinq_range: + base = self._base_path + [interface, 'vif-s', vif_s, 'vif-c'] + self.cli_delete(base) + + self.cli_commit() + + def test_vif_s_protocol_change(self): # XXX: This testcase is not allowed to run as first testcase, reason # is the Wireless test will first load the wifi kernel hwsim module diff --git a/src/conf_mode/containers.py b/src/conf_mode/containers.py index cc34f9d39..ab992e415 100755 --- a/src/conf_mode/containers.py +++ b/src/conf_mode/containers.py @@ -30,8 +30,6 @@ from vyos.util import cmd from vyos.util import run from vyos.util import read_file from vyos.util import write_file -from vyos.util import is_systemd_service_active -from vyos.util import is_systemd_service_running from vyos.template import inc_ip from vyos.template import is_ipv4 from vyos.template import is_ipv6 @@ -102,7 +100,7 @@ def verify(container): # Check if the specified container network exists network_name = list(container_config['network'])[0] if network_name not in container['network']: - raise ConfigError('Container network "{network_name}" does not exist!') + raise ConfigError(f'Container network "{network_name}" does not exist!') if 'address' in container_config['network'][network_name]: if 'network' not in container_config: @@ -237,17 +235,6 @@ def apply(container): if os.path.exists(tmp): os.unlink(tmp) - service_name = 'podman.service' - if 'network' in container or 'name' in container: - # Start podman if it's required and not yet running - if not is_systemd_service_active(service_name): - _cmd(f'systemctl start {service_name}') - # Wait for podman to be running - while not is_systemd_service_running(service_name): - sleep(0.250) - else: - _cmd(f'systemctl stop {service_name}') - # Add container if 'name' in container: for name, container_config in container['name'].items(): @@ -318,7 +305,17 @@ def apply(container): if 'address' in container_config['network'][network]: address = container_config['network'][network]['address'] ipparam = f'--ip {address}' - _cmd(f'{container_base_cmd} --net {network} {ipparam} {image}') + + counter = 0 + while True: + if counter >= 10: + break + try: + _cmd(f'{container_base_cmd} --net {network} {ipparam} {image}') + break + except: + counter = counter +1 + sleep(0.5) return None diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 8f660fe1d..1e76147dd 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -82,26 +82,25 @@ def get_config(config=None): tmp_pki = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) - # We have to get the dict using 'get_config_dict' instead of 'get_interface_dict' - # as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there. - tmp_openvpn = conf.get_config_dict(base + [os.environ['VYOS_TAGNODE_VALUE']], key_mangling=('-', '_'), - get_first_key=True, no_tag_node_value_mangle=True) - openvpn = get_interface_dict(conf, base) if 'deleted' not in openvpn: openvpn['pki'] = tmp_pki + # We have to get the dict using 'get_config_dict' instead of 'get_interface_dict' + # as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there. + tmp = conf.get_config_dict(base + [openvpn['ifname']], get_first_key=True) + + # We have to cleanup the config dict, as default values could enable features + # which are not explicitly enabled on the CLI. Example: server mfa totp + # originate comes with defaults, which will enable the + # totp plugin, even when not set via CLI so we + # need to check this first and drop those keys + if dict_search('server.mfa.totp', tmp) == None: + del openvpn['server']['mfa'] + openvpn['auth_user_pass_file'] = '/run/openvpn/{ifname}.pw'.format(**openvpn) - # We have to cleanup the config dict, as default values could enable features - # which are not explicitly enabled on the CLI. Example: server mfa totp - # originate comes with defaults, which will enable the - # totp plugin, even when not set via CLI so we - # need to check this first and drop those keys - if dict_search('server.totp', tmp_openvpn) == None and dict_search('server', tmp_openvpn) != None: - del openvpn['server']['mfa']['totp'] - return openvpn def is_ec_private_key(pki, cert_name): diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 597fcc443..f010141e9 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -21,6 +21,7 @@ from sys import argv from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configdict import get_dhcp_interfaces from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_vrf from vyos.template import render_to_string @@ -56,6 +57,10 @@ def get_config(config=None): # Merge policy dict into "regular" config dict static = dict_merge(tmp, static) + # T3680 - get a list of all interfaces currently configured to use DHCP + tmp = get_dhcp_interfaces(conf, vrf) + if tmp: static['dhcp'] = tmp + return static def verify(static): diff --git a/src/conf_mode/system-login-banner.py b/src/conf_mode/system-login-banner.py index a960a4da3..e9d6a339c 100755 --- a/src/conf_mode/system-login-banner.py +++ b/src/conf_mode/system-login-banner.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2021 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 @@ -22,12 +22,13 @@ from vyos import airbag airbag.enable() motd=""" -The programs included with the Debian/VyOS GNU/Linux system are free software; -the exact distribution terms for each program are described in the -individual files in /usr/share/doc/*/copyright. +Check out project news at https://blog.vyos.io +and feel free to report bugs at https://phabricator.vyos.net -Debian/VyOS GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent -permitted by applicable law. +You can change this banner using "set system login banner post-login" command. + +VyOS is a free software distribution that includes multiple components, +you can check individual component licenses under /usr/share/doc/*/copyright """ diff --git a/src/etc/logrotate.d/vyos-atop b/src/etc/logrotate.d/vyos-atop new file mode 100644 index 000000000..0c8359c7b --- /dev/null +++ b/src/etc/logrotate.d/vyos-atop @@ -0,0 +1,20 @@ +/var/log/atop/atop.log { + daily + dateext + dateformat _%Y-%m-%d_%H-%M-%S + maxsize 10M + missingok + nocompress + nocreate + nomail + rotate 10 + prerotate + # stop the service + systemctl stop atop.service + endscript + postrotate + # start atop service again + systemctl start atop.service + endscript +} + diff --git a/src/etc/systemd/system/atop.service.d/10-override.conf b/src/etc/systemd/system/atop.service.d/10-override.conf new file mode 100644 index 000000000..10df15862 --- /dev/null +++ b/src/etc/systemd/system/atop.service.d/10-override.conf @@ -0,0 +1,6 @@ +[Service] +ExecStartPre= +ExecStart= +ExecStart=/bin/sh -c 'exec /usr/bin/atop ${LOGOPTS} -w "${LOGPATH}/atop.log" ${LOGINTERVAL}' +ExecStartPost= + diff --git a/src/etc/udev/rules.d/62-temporary-interface-rename.rules b/src/etc/udev/rules.d/62-temporary-interface-rename.rules new file mode 100644 index 000000000..4a579dcab --- /dev/null +++ b/src/etc/udev/rules.d/62-temporary-interface-rename.rules @@ -0,0 +1 @@ +SUBSYSTEM=="net", ACTION=="add", KERNEL=="eth*", DRIVERS=="?*", NAME="e$env{IFINDEX}" diff --git a/src/etc/udev/rules.d/65-vyos-net.rules b/src/etc/udev/rules.d/65-vyos-net.rules index c8d5750dd..32ae352de 100644 --- a/src/etc/udev/rules.d/65-vyos-net.rules +++ b/src/etc/udev/rules.d/65-vyos-net.rules @@ -4,11 +4,8 @@ ACTION!="add", GOTO="vyos_net_end" SUBSYSTEM!="net", GOTO="vyos_net_end" -# ignore the interface if a name has already been set -NAME=="?*", GOTO="vyos_net_end" - # Do name change for ethernet and wireless devices only -KERNEL!="eth*|wlan*", GOTO="vyos_net_end" +KERNEL!="eth*|wlan*|e*", GOTO="vyos_net_end" # ignore "secondary" monitor interfaces of mac80211 drivers KERNEL=="wlan*", ATTRS{type}=="803", GOTO="vyos_net_end" diff --git a/src/helpers/vyos_net_name b/src/helpers/vyos_net_name index 0652e98b1..5d9535cf0 100755 --- a/src/helpers/vyos_net_name +++ b/src/helpers/vyos_net_name @@ -77,10 +77,12 @@ def get_biosdevname(ifname: str) -> str: XXX: This throws an error, and likely has for a long time, unnoticed since vyatta_net_name redirected stderr to /dev/null. """ - if 'eth' not in ifname: - return ifname + intf = f"eth{re.sub(r'[^0-9]', '', ifname)}" if 'e' == ifname[0] else ifname + + if 'eth' not in intf: + return intf if os.path.isdir('/proc/xen'): - return ifname + return intf time.sleep(1) @@ -90,7 +92,7 @@ def get_biosdevname(ifname: str) -> str: logging.error(f'biosdevname error: {e}') biosname = '' - return ifname if biosname == '' else biosname + return intf if biosname == '' else biosname def leave_rescan_hint(intf_name: str, hwid: str): """Write interface information reported by udev @@ -186,9 +188,9 @@ def on_boot_event(intf_name: str, hwid: str, predefined: str = '') -> str: interfaces = get_configfile_interfaces() logging.debug(f"config file interfaces are {interfaces}") - if hwid in list(interfaces) and intf_name == interfaces[hwid]: - logging.info(f"use mapping from config file: '{hwid}' -> '{intf_name}'") - return intf_name + if hwid in list(interfaces): + logging.info(f"use mapping from config file: '{hwid}' -> '{interfaces[hwid]}'") + return interfaces[hwid] add_assigned_interfaces(interfaces) logging.debug(f"adding assigned interfaces: {interfaces}") @@ -223,6 +225,7 @@ lock.acquire() if not boot_configuration_complete(): res = on_boot_event(argv[1], argv[2], predefined=predef_name) logging.debug(f"on boot, returned name is {res}") + print(res) else: logging.debug("boot configuration complete") lock.release() diff --git a/src/op_mode/force_part_resize.sh b/src/op_mode/force_part_resize.sh new file mode 100755 index 000000000..eb0f26d8a --- /dev/null +++ b/src/op_mode/force_part_resize.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2021 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 as +# published by the Free Software Foundation. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# +# Function to get the vyos version from the commandline. +# +get_version () { +for item in `cat /proc/cmdline`; do + if [ "vyos-union" == "${item%=*}" ]; then + echo ${item#*=} + fi +done +} + +# +# VERSION is the output of the get_version output. +# DEVICEPART is the device partition where VyOS is mounted on. +# DEVICEPATH is the path to the device where VyOS is mounted on. +# DEVICE is the device of the device partition. +# PARTNR is the device partition number used for parted. +# +VERSION=$(get_version) +DEVICEPART=$(mount | grep $VERSION/grub | cut -d' ' -f1 | rev | cut -d'/' -f1 | rev) +DEVICEPATH=$(mount | grep $VERSION/grub | cut -d' ' -f1 | rev | cut -d'/' -f2- | rev) +DEVICE=$(lsblk -no pkname $DEVICEPATH/$DEVICEPART) +PARTNR=$(grep -c $DEVICEPART /proc/partitions) + +# +# Check if the device really exits. +# +fdisk -l $DEVICEPATH/$DEVICE >> /dev/null 2>&1 || (echo "could not find device $DEVICE" && exit 1) + +# +# START is the partition starting sector. +# CURSIZE is the partition start sector + the partition end sector. +# MAXSIZE is the device end sector. +# +START=$(cat /sys/block/$DEVICE/$DEVICEPART/start) +CURSIZE=$(($START+$(cat /sys/block/$DEVICE/$DEVICEPART/size))) +MAXSIZE=$(($(cat /sys/block/$DEVICE/size)-8)) + +# +# Check if the device size is larger then the partition size +# and if that is the case, resize the partition and grow the filesystem. +# +if [ $MAXSIZE -gt $CURSIZE ]; then +parted "${DEVICEPATH}/${DEVICE}" ---pretend-input-tty > /dev/null 2>&1 <<EOF +unit +s +resizepart +${PARTNR} +Yes +"$MAXSIZE" +quit +EOF + partprobe > /dev/null 2>&1 + resize2fs ${DEVICEPATH}/$DEVICEPART > /dev/null 2>&1 +fi + diff --git a/src/services/api/graphql/README.graphql b/src/services/api/graphql/README.graphql index a04138010..580c0eb7f 100644 --- a/src/services/api/graphql/README.graphql +++ b/src/services/api/graphql/README.graphql @@ -25,7 +25,7 @@ mutation { createDhcpServer(data: {sharedNetworkName: "BOB", subnet: "192.168.0.0/24", defaultRouter: "192.168.0.1", - dnsServer: "192.168.0.1", + nameServer: "192.168.0.1", domainName: "vyos.net", lease: 86400, range: 0, diff --git a/src/services/api/graphql/graphql/schema/dhcp_server.graphql b/src/services/api/graphql/graphql/schema/dhcp_server.graphql index a7ee75d40..9f741a0a5 100644 --- a/src/services/api/graphql/graphql/schema/dhcp_server.graphql +++ b/src/services/api/graphql/graphql/schema/dhcp_server.graphql @@ -2,7 +2,7 @@ input dhcpServerConfigInput { sharedNetworkName: String subnet: String defaultRouter: String - dnsServer: String + nameServer: String domainName: String lease: Int range: Int @@ -17,7 +17,7 @@ type dhcpServerConfig { sharedNetworkName: String subnet: String defaultRouter: String - dnsServer: String + nameServer: String domainName: String lease: Int range: Int diff --git a/src/services/api/graphql/recipes/templates/dhcp_server.tmpl b/src/services/api/graphql/recipes/templates/dhcp_server.tmpl index 629ce83c1..70de43183 100644 --- a/src/services/api/graphql/recipes/templates/dhcp_server.tmpl +++ b/src/services/api/graphql/recipes/templates/dhcp_server.tmpl @@ -1,5 +1,5 @@ set service dhcp-server shared-network-name {{ shared_network_name }} subnet {{ subnet }} default-router {{ default_router }} -set service dhcp-server shared-network-name {{ shared_network_name }} subnet {{ subnet }} dns-server {{ dns_server }} +set service dhcp-server shared-network-name {{ shared_network_name }} subnet {{ subnet }} name-server {{ name_server }} set service dhcp-server shared-network-name {{ shared_network_name }} subnet {{ subnet }} domain-name {{ domain_name }} set service dhcp-server shared-network-name {{ shared_network_name }} subnet {{ subnet }} lease {{ lease }} set service dhcp-server shared-network-name {{ shared_network_name }} subnet {{ subnet }} range {{ range }} start {{ start }} |