summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/staticd.frr.tmpl9
-rw-r--r--debian/vyos-1x.install1
-rw-r--r--interface-definitions/bcast-relay.xml.in10
-rw-r--r--interface-definitions/dhcp-relay.xml.in10
-rw-r--r--interface-definitions/dhcp-server.xml.in4
-rw-r--r--interface-definitions/flow-accounting-conf.xml.in10
-rw-r--r--interface-definitions/include/generic-interface-broadcast.xml.i17
-rw-r--r--interface-definitions/include/generic-interface-multi-broadcast.xml.i18
-rw-r--r--interface-definitions/include/generic-interface-multi.xml.i18
-rw-r--r--interface-definitions/include/generic-interface.xml.i17
-rw-r--r--interface-definitions/interfaces-bonding.xml.in14
-rw-r--r--interface-definitions/policy.xml.in9
-rw-r--r--interface-definitions/protocols-bfd.xml.in9
-rw-r--r--interface-definitions/protocols-mpls.xml.in20
-rw-r--r--interface-definitions/protocols-ospfv3.xml.in17
-rw-r--r--interface-definitions/service_mdns-repeater.xml.in10
-rw-r--r--interface-definitions/vpn_ipsec.xml.in19
-rw-r--r--interface-definitions/vrrp.xml.in9
-rw-r--r--op-mode-definitions/force-part-resize.xml.in13
-rw-r--r--python/vyos/configdict.py43
-rw-r--r--python/vyos/template.py1
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py10
-rwxr-xr-xsrc/conf_mode/containers.py27
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py25
-rwxr-xr-xsrc/conf_mode/protocols_static.py5
-rwxr-xr-xsrc/conf_mode/system-login-banner.py13
-rw-r--r--src/etc/logrotate.d/vyos-atop20
-rw-r--r--src/etc/systemd/system/atop.service.d/10-override.conf6
-rw-r--r--src/etc/udev/rules.d/62-temporary-interface-rename.rules1
-rw-r--r--src/etc/udev/rules.d/65-vyos-net.rules5
-rwxr-xr-xsrc/helpers/vyos_net_name17
-rwxr-xr-xsrc/op_mode/force_part_resize.sh72
-rw-r--r--src/services/api/graphql/README.graphql2
-rw-r--r--src/services/api/graphql/graphql/schema/dhcp_server.graphql4
-rw-r--r--src/services/api/graphql/recipes/templates/dhcp_server.tmpl2
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 }}