diff options
46 files changed, 973 insertions, 302 deletions
diff --git a/data/templates/container/systemd-unit.j2 b/data/templates/container/systemd-unit.j2 index fa48384ab..d379f0a07 100644 --- a/data/templates/container/systemd-unit.j2 +++ b/data/templates/container/systemd-unit.j2 @@ -13,5 +13,5 @@ ExecStop=/usr/bin/podman stop --ignore --cidfile %t/%n.cid -t 5 ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/%n.cid ExecStopPost=/bin/rm -f %t/%n.cid PIDFile=%t/%n.pid -KillMode=none +KillMode=control-group Type=forking diff --git a/data/templates/dhcp-server/kea-dhcp6.conf.j2 b/data/templates/dhcp-server/kea-dhcp6.conf.j2 index 3ce4e6370..3ab21551b 100644 --- a/data/templates/dhcp-server/kea-dhcp6.conf.j2 +++ b/data/templates/dhcp-server/kea-dhcp6.conf.j2 @@ -1,7 +1,11 @@ { "Dhcp6": { "interfaces-config": { +{% if listen_interface is vyos_defined %} + "interfaces": {{ listen_interface | tojson }}, +{% else %} "interfaces": [ "*" ], +{% endif %} "service-sockets-max-retries": 5, "service-sockets-retry-wait-time": 5000 }, diff --git a/data/templates/firewall/nftables-zone.j2 b/data/templates/firewall/nftables-zone.j2 index 5e55099ca..e78725079 100644 --- a/data/templates/firewall/nftables-zone.j2 +++ b/data/templates/firewall/nftables-zone.j2 @@ -1,13 +1,6 @@ - -{% macro zone_chains(zone, family, state_policy=False) %} -{% if family == 'ipv6' %} -{% set fw_name = 'ipv6_name' %} -{% set suffix = '6' %} -{% else %} -{% set fw_name = 'name' %} -{% set suffix = '' %} -{% endif %} - +{% macro zone_chains(zone, ipv6=False, state_policy=False) %} +{% set fw_name = 'ipv6_name' if ipv6 else 'name' %} +{% set suffix = '6' if ipv6 else '' %} chain VYOS_ZONE_FORWARD { type filter hook forward priority 1; policy accept; {% if state_policy %} diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2 index e0ad0e00a..833df3a67 100644 --- a/data/templates/firewall/nftables.j2 +++ b/data/templates/firewall/nftables.j2 @@ -163,7 +163,7 @@ table ip vyos_filter { {{ group_tmpl.groups(group, False, True) }} {% if zone is vyos_defined %} -{{ zone_tmpl.zone_chains(zone, 'ipv4', global_options.state_policy is vyos_defined) }} +{{ zone_tmpl.zone_chains(zone, False, global_options.state_policy is vyos_defined) }} {% endif %} {% if global_options.state_policy is vyos_defined %} chain VYOS_STATE_POLICY { @@ -298,7 +298,7 @@ table ip6 vyos_filter { {% endif %} {{ group_tmpl.groups(group, True, True) }} {% if zone is vyos_defined %} -{{ zone_tmpl.zone_chains(zone, 'ipv6', global_options.state_policy is vyos_defined) }} +{{ zone_tmpl.zone_chains(zone, True, global_options.state_policy is vyos_defined) }} {% endif %} {% if global_options.state_policy is vyos_defined %} chain VYOS_STATE_POLICY6 { diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2 index 679ba8b04..e02fdd1bb 100644 --- a/data/templates/frr/bgpd.frr.j2 +++ b/data/templates/frr/bgpd.frr.j2 @@ -402,6 +402,9 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% if afi_config.flooding.head_end_replication is vyos_defined %} flooding head-end-replication {% endif %} +{% if afi_config.nexthop.vpn.export is vyos_defined %} + nexthop vpn export {{ afi_config.nexthop.vpn.export }} +{% endif %} {% if afi_config.rd.vpn.export is vyos_defined %} rd vpn export {{ afi_config.rd.vpn.export }} {% endif %} @@ -436,6 +439,9 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% if afi_config.route_map.vpn.import is vyos_defined %} route-map vpn import {{ afi_config.route_map.vpn.import }} {% endif %} +{% if afi_config.sid.vpn.export is vyos_defined %} + sid vpn export {{ afi_config.sid.vpn.export }} +{% endif %} {% if afi_config.vni is vyos_defined %} {% for vni, vni_config in afi_config.vni.items() %} vni {{ vni }} diff --git a/data/templates/grub/grub_common.j2 b/data/templates/grub/grub_common.j2 index 278ffbf2c..5e9b95cc0 100644 --- a/data/templates/grub/grub_common.j2 +++ b/data/templates/grub/grub_common.j2 @@ -8,9 +8,13 @@ fi function setup_serial { # initialize the first serial port by default if [ "${console_type}" == "ttyS" ]; then - serial --unit=${console_num} + if [ "${console_num}" == "0" ]; then + serial --unit=0 --speed=${console_speed} + else + serial --unit=${console_num} --speed=115200 + fi else - serial --unit=0 + serial --unit=0 --speed=${console_speed} fi terminal_output --append serial console terminal_input --append serial console diff --git a/data/templates/grub/grub_compat.j2 b/data/templates/grub/grub_compat.j2 index 887d5d0bd..d1085eec8 100644 --- a/data/templates/grub/grub_compat.j2 +++ b/data/templates/grub/grub_compat.j2 @@ -22,13 +22,13 @@ {%- endmacro %} {% macro console_opts(type) -%} {% if type == 'tty' -%} - console=ttyS0,115200 console=tty0 + console=ttyS0,{{ console_speed }} console=tty0 {%- elif type == 'ttyS' -%} - console=tty0 console=ttyS0,115200 + console=tty0 console=ttyS0,{{ console_speed }} {%- elif type == 'ttyUSB' -%} console=tty0 console=ttyUSB0,115200 {%- else -%} - console=tty0 console=ttyS0,115200 + console=tty0 console=ttyS0,{{ console_speed }} {%- endif %} {%- endmacro %} {% macro passwd_opts(mode) -%} @@ -39,9 +39,13 @@ set default={{ default }} set timeout={{ timeout }} {% if console_type == 'ttyS' %} +{% if console_num == '0' %} +serial --unit=0 --speed={{ console_speed }} +{% else %} serial --unit={{ console_num }} --speed=115200 +{% endif %} {% else %} -serial --unit=0 --speed=115200 +serial --unit=0 --speed={{ console_speed }} {% endif %} terminal_output --append serial terminal_input serial console diff --git a/data/templates/grub/grub_vyos_version.j2 b/data/templates/grub/grub_vyos_version.j2 index 97fbe8473..62688e68b 100644 --- a/data/templates/grub/grub_vyos_version.j2 +++ b/data/templates/grub/grub_vyos_version.j2 @@ -6,16 +6,21 @@ {% endif %} menuentry "{{ version_name }}" --id {{ version_uuid }} { set boot_opts="{{ boot_opts_rendered }}" + if [ "${console_type}" == "ttyS" ]; then + set console_opts="console=${console_type}${console_num},${console_speed}" + else + set console_opts="console=${console_type}${console_num}" + fi # load rootfs to RAM if [ "${boot_toram}" == "yes" ]; then set boot_opts="${boot_opts} toram" fi if [ "${bootmode}" == "pw_reset" ]; then - set boot_opts="${boot_opts} console=${console_type}${console_num} init=/usr/libexec/vyos/system/standalone_root_pw_reset" + set boot_opts="${boot_opts} ${console_opts} init=/usr/libexec/vyos/system/standalone_root_pw_reset" elif [ "${bootmode}" == "recovery" ]; then - set boot_opts="${boot_opts} console=${console_type}${console_num} init=/usr/bin/busybox init" + set boot_opts="${boot_opts} ${console_opts} init=/usr/bin/busybox init" else - set boot_opts="${boot_opts} console=${console_type}${console_num}" + set boot_opts="${boot_opts} ${console_opts}" fi linux "/boot/{{ version_name }}/vmlinuz" ${boot_opts} initrd "/boot/{{ version_name }}/initrd.img" diff --git a/data/templates/ipsec/swanctl/peer.j2 b/data/templates/ipsec/swanctl/peer.j2 index 9d95271fe..86a44a0ff 100644 --- a/data/templates/ipsec/swanctl/peer.j2 +++ b/data/templates/ipsec/swanctl/peer.j2 @@ -83,8 +83,7 @@ start_action = none {% endif %} {% if ike.dead_peer_detection is vyos_defined %} -{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %} - dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} + dpd_action = {{ ike.dead_peer_detection.action }} {% endif %} close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }} } @@ -134,8 +133,7 @@ start_action = none {% endif %} {% if ike.dead_peer_detection is vyos_defined %} -{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %} - dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} + dpd_action = {{ ike.dead_peer_detection.action }} {% endif %} close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }} {% if peer_conf.vti.bind is vyos_defined %} diff --git a/data/templates/rsyslog/rsyslog.conf.j2 b/data/templates/rsyslog/rsyslog.conf.j2 index 96f91def1..97e0ee0b7 100644 --- a/data/templates/rsyslog/rsyslog.conf.j2 +++ b/data/templates/rsyslog/rsyslog.conf.j2 @@ -1,9 +1,5 @@ ### Autogenerated by system_syslog.py ### -# Load journald logs to rsyslog -module(load="imjournal") -module(load="mmjsonparse") - {% if global.marker is vyos_defined %} $ModLoad immark {% if global.marker.interval is vyos_defined %} diff --git a/interface-definitions/include/bgp/afi-nexthop-vpn-export.xml.i b/interface-definitions/include/bgp/afi-nexthop-vpn-export.xml.i new file mode 100644 index 000000000..d90597f37 --- /dev/null +++ b/interface-definitions/include/bgp/afi-nexthop-vpn-export.xml.i @@ -0,0 +1,32 @@ +<!-- include start from bgp/afi-nexthop-vpn-export.xml.i --> +<node name="nexthop"> + <properties> + <help>Specify next hop to use for VRF advertised prefixes</help> + </properties> + <children> + <node name="vpn"> + <properties> + <help>Between current address-family and vpn</help> + </properties> + <children> + <leafNode name="export"> + <properties> + <help>For routes leaked from current address-family to vpn</help> + <valueHelp> + <format>ipv4</format> + <description>BGP neighbor IP address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>BGP neighbor IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ip-address"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + </children> +</node> + <!-- include end --> diff --git a/interface-definitions/include/bgp/afi-sid.xml.i b/interface-definitions/include/bgp/afi-sid.xml.i new file mode 100644 index 000000000..38a3dcf9b --- /dev/null +++ b/interface-definitions/include/bgp/afi-sid.xml.i @@ -0,0 +1,36 @@ +<!-- include start from bgp/sid.xml.i --> +<node name="sid"> + <properties> + <help>SID value for VRF</help> + </properties> + <children> + <node name="vpn"> + <properties> + <help>Between current VRF and VPN</help> + </properties> + <children> + <leafNode name="export"> + <properties> + <help>For routes leaked from current VRF to VPN</help> + <completionHelp> + <list>auto</list> + </completionHelp> + <valueHelp> + <format>u32:1-1048575</format> + <description>SID allocation index</description> + </valueHelp> + <valueHelp> + <format>auto</format> + <description>Automatically assign a label</description> + </valueHelp> + <constraint> + <regex>auto</regex> + <validator name="numeric" argument="--range 1-1048575"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + </children> + </node> + <!-- include end --> diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index bb35efe94..9895b025c 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -120,6 +120,7 @@ #include <include/bgp/afi-rd.xml.i> #include <include/bgp/afi-route-map-vpn.xml.i> #include <include/bgp/afi-route-target-vpn.xml.i> + #include <include/bgp/afi-nexthop-vpn-export.xml.i> <node name="redistribute"> <properties> <help>Redistribute routes from other protocols into BGP</help> @@ -188,6 +189,7 @@ </leafNode> </children> </node> + #include <include/bgp/afi-sid.xml.i> </children> </node> <node name="ipv4-multicast"> @@ -495,6 +497,7 @@ #include <include/bgp/afi-rd.xml.i> #include <include/bgp/afi-route-map-vpn.xml.i> #include <include/bgp/afi-route-target-vpn.xml.i> + #include <include/bgp/afi-nexthop-vpn-export.xml.i> <node name="redistribute"> <properties> <help>Redistribute routes from other protocols into BGP</help> @@ -555,6 +558,7 @@ </leafNode> </children> </node> + #include <include/bgp/afi-sid.xml.i> </children> </node> <node name="ipv6-multicast"> diff --git a/interface-definitions/include/dhcp/option-v6.xml.i b/interface-definitions/include/dhcp/option-v6.xml.i new file mode 100644 index 000000000..1df0c3934 --- /dev/null +++ b/interface-definitions/include/dhcp/option-v6.xml.i @@ -0,0 +1,110 @@ +<!-- include start from dhcp/option-v6.xml.i --> +<node name="option"> + <properties> + <help>DHCPv6 option</help> + </properties> + <children> + #include <include/dhcp/captive-portal.xml.i> + #include <include/dhcp/domain-search.xml.i> + #include <include/name-server-ipv6.xml.i> + <leafNode name="nis-domain"> + <properties> + <help>NIS domain name for client to use</help> + <constraint> + #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> + </constraint> + <constraintErrorMessage>Invalid NIS domain name</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="nis-server"> + <properties> + <help>IPv6 address of a NIS Server</help> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address of NIS server</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + </constraint> + <multi/> + </properties> + </leafNode> + <leafNode name="nisplus-domain"> + <properties> + <help>NIS+ domain name for client to use</help> + <constraint> + #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> + </constraint> + <constraintErrorMessage>Invalid NIS+ domain name. May only contain letters, numbers and .-_</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="nisplus-server"> + <properties> + <help>IPv6 address of a NIS+ Server</help> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address of NIS+ server</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + </constraint> + <multi/> + </properties> + </leafNode> + <leafNode name="sip-server"> + <properties> + <help>IPv6 address of SIP server</help> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address of SIP server</description> + </valueHelp> + <valueHelp> + <format>hostname</format> + <description>FQDN of SIP server</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + <validator name="fqdn"/> + </constraint> + <multi/> + </properties> + </leafNode> + <leafNode name="sntp-server"> + <properties> + <help>IPv6 address of an SNTP server for client to use</help> + <constraint> + <validator name="ipv6-address"/> + </constraint> + <multi/> + </properties> + </leafNode> + <node name="vendor-option"> + <properties> + <help>Vendor Specific Options</help> + </properties> + <children> + <node name="cisco"> + <properties> + <help>Cisco specific parameters</help> + </properties> + <children> + <leafNode name="tftp-server"> + <properties> + <help>TFTP server name</help> + <valueHelp> + <format>ipv6</format> + <description>TFTP server IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + </constraint> + <multi/> + </properties> + </leafNode> + </children> + </node> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/version/ipsec-version.xml.i b/interface-definitions/include/version/ipsec-version.xml.i index de7a9c088..a4d556cfc 100644 --- a/interface-definitions/include/version/ipsec-version.xml.i +++ b/interface-definitions/include/version/ipsec-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/ipsec-version.xml.i --> -<syntaxVersion component='ipsec' version='12'></syntaxVersion> +<syntaxVersion component='ipsec' version='13'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/service_dhcpv6-server.xml.in b/interface-definitions/service_dhcpv6-server.xml.in index 6934ceeec..07cbfc85d 100644 --- a/interface-definitions/service_dhcpv6-server.xml.in +++ b/interface-definitions/service_dhcpv6-server.xml.in @@ -9,6 +9,7 @@ </properties> <children> #include <include/generic-disable-node.xml.i> + #include <include/listen-interface-multi-broadcast.xml.i> <node name="global-parameters"> <properties> <help>Additional global parameters for DHCPv6 server</help> @@ -89,11 +90,17 @@ </constraint> </properties> <children> - <node name="address-range"> + #include <include/dhcp/option-v6.xml.i> + <tagNode name="range"> <properties> <help>Parameters setting ranges for assigning IPv6 addresses</help> + <constraint> + #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> + </constraint> + <constraintErrorMessage>Invalid range name, may only be alphanumeric, dot and hyphen</constraintErrorMessage> </properties> <children> + #include <include/dhcp/option-v6.xml.i> <leafNode name="prefix"> <properties> <help>IPv6 prefix defining range of addresses to assign</help> @@ -104,10 +111,9 @@ <constraint> <validator name="ipv6-prefix"/> </constraint> - <multi/> </properties> </leafNode> - <tagNode name="start"> + <leafNode name="start"> <properties> <help>First in range of consecutive IPv6 addresses to assign</help> <valueHelp> @@ -118,25 +124,21 @@ <validator name="ipv6-address"/> </constraint> </properties> - <children> - <leafNode name="stop"> - <properties> - <help>Last in range of consecutive IPv6 addresses</help> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address</description> - </valueHelp> - <constraint> - <validator name="ipv6-address"/> - </constraint> - </properties> - </leafNode> - </children> - </tagNode> + </leafNode> + <leafNode name="stop"> + <properties> + <help>Last in range of consecutive IPv6 addresses</help> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + </constraint> + </properties> + </leafNode> </children> - </node> - #include <include/dhcp/captive-portal.xml.i> - #include <include/dhcp/domain-search.xml.i> + </tagNode> <node name="lease-time"> <properties> <help>Parameters relating to the lease time</help> @@ -180,51 +182,6 @@ </leafNode> </children> </node> - #include <include/name-server-ipv6.xml.i> - <leafNode name="nis-domain"> - <properties> - <help>NIS domain name for client to use</help> - <constraint> - #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> - </constraint> - <constraintErrorMessage>Invalid NIS domain name</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="nis-server"> - <properties> - <help>IPv6 address of a NIS Server</help> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address of NIS server</description> - </valueHelp> - <constraint> - <validator name="ipv6-address"/> - </constraint> - <multi/> - </properties> - </leafNode> - <leafNode name="nisplus-domain"> - <properties> - <help>NIS+ domain name for client to use</help> - <constraint> - #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> - </constraint> - <constraintErrorMessage>Invalid NIS+ domain name. May only contain letters, numbers and .-_</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="nisplus-server"> - <properties> - <help>IPv6 address of a NIS+ Server</help> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address of NIS+ server</description> - </valueHelp> - <constraint> - <validator name="ipv6-address"/> - </constraint> - <multi/> - </properties> - </leafNode> <node name="prefix-delegation"> <properties> <help>Parameters relating to IPv6 prefix delegation</help> @@ -272,33 +229,6 @@ </tagNode> </children> </node> - <leafNode name="sip-server"> - <properties> - <help>IPv6 address of SIP server</help> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address of SIP server</description> - </valueHelp> - <valueHelp> - <format>hostname</format> - <description>FQDN of SIP server</description> - </valueHelp> - <constraint> - <validator name="ipv6-address"/> - <validator name="fqdn"/> - </constraint> - <multi/> - </properties> - </leafNode> - <leafNode name="sntp-server"> - <properties> - <help>IPv6 address of an SNTP server for client to use</help> - <constraint> - <validator name="ipv6-address"/> - </constraint> - <multi/> - </properties> - </leafNode> <tagNode name="static-mapping"> <properties> <help>Hostname for static mapping reservation</help> @@ -308,6 +238,7 @@ <constraintErrorMessage>Invalid static mapping hostname</constraintErrorMessage> </properties> <children> + #include <include/dhcp/option-v6.xml.i> #include <include/generic-disable-node.xml.i> #include <include/interface/mac.xml.i> #include <include/interface/duid.xml.i> @@ -349,33 +280,6 @@ </constraint> </properties> </leafNode> - <node name="vendor-option"> - <properties> - <help>Vendor Specific Options</help> - </properties> - <children> - <node name="cisco"> - <properties> - <help>Cisco specific parameters</help> - </properties> - <children> - <leafNode name="tftp-server"> - <properties> - <help>TFTP server name</help> - <valueHelp> - <format>ipv6</format> - <description>TFTP server IPv6 address</description> - </valueHelp> - <constraint> - <validator name="ipv6-address"/> - </constraint> - <multi/> - </properties> - </leafNode> - </children> - </node> - </children> - </node> </children> </tagNode> </children> diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index 1847401b5..76c71949f 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -280,10 +280,10 @@ <properties> <help>Keep-alive failure action</help> <completionHelp> - <list>hold clear restart</list> + <list>trap clear restart</list> </completionHelp> <valueHelp> - <format>hold</format> + <format>trap</format> <description>Attempt to re-negotiate the connection when matching traffic is seen</description> </valueHelp> <valueHelp> @@ -295,7 +295,7 @@ <description>Attempt to re-negotiate the connection immediately</description> </valueHelp> <constraint> - <regex>(hold|clear|restart)</regex> + <regex>(trap|clear|restart)</regex> </constraint> </properties> <defaultValue>clear</defaultValue> diff --git a/python/vyos/kea.py b/python/vyos/kea.py index aa4fb7ae5..fb5afc2ce 100644 --- a/python/vyos/kea.py +++ b/python/vyos/kea.py @@ -175,16 +175,6 @@ def kea_parse_subnet(subnet, config): def kea6_parse_options(config): options = [] - if 'common_options' in config: - common_opt = config['common_options'] - - for node, option_name in kea6_options.items(): - if node not in common_opt: - continue - - value = ", ".join(common_opt[node]) if isinstance(common_opt[node], list) else common_opt[node] - options.append({'name': option_name, 'data': value}) - for node, option_name in kea6_options.items(): if node not in config: continue @@ -218,20 +208,27 @@ def kea6_parse_options(config): def kea6_parse_subnet(subnet, config): out = {'subnet': subnet, 'id': int(config['subnet_id'])} - options = kea6_parse_options(config) - if 'address_range' in config: - addr_range = config['address_range'] + if 'option' in config: + out['option-data'] = kea6_parse_options(config['option']) + + if 'range' in config: pools = [] + for num, range_config in config['range'].items(): + pool = {} - if 'prefix' in addr_range: - for prefix in addr_range['prefix']: - pools.append({'pool': prefix}) + if 'prefix' in range_config: + pool['pool'] = range_config['prefix'] - if 'start' in addr_range: - for start, range_conf in addr_range['start'].items(): - stop = range_conf['stop'] - pools.append({'pool': f'{start} - {stop}'}) + if 'start' in range_config: + start = range_config['start'] + stop = range_config['stop'] + pool['pool'] = f'{start} - {stop}' + + if 'option' in range_config: + pool['option-data'] = kea6_parse_options(range_config['option']) + + pools.append(pool) out['pools'] = pools @@ -278,13 +275,13 @@ def kea6_parse_subnet(subnet, config): if 'ipv6_prefix' in host_config: reservation['prefixes'] = [ host_config['ipv6_prefix'] ] + if 'option' in host_config: + reservation['option-data'] = kea6_parse_options(host_config['option']) + reservations.append(reservation) out['reservations'] = reservations - if options: - out['option-data'] = options - return out def kea_parse_leases(lease_path): diff --git a/python/vyos/system/compat.py b/python/vyos/system/compat.py index 319c3dabf..436da14e8 100644 --- a/python/vyos/system/compat.py +++ b/python/vyos/system/compat.py @@ -27,7 +27,7 @@ TMPL_GRUB_COMPAT: str = 'grub/grub_compat.j2' # define regexes and variables REGEX_VERSION = r'^menuentry "[^\n]*{\n[^}]*\s+linux /boot/(?P<version>\S+)/[^}]*}' REGEX_MENUENTRY = r'^menuentry "[^\n]*{\n[^}]*\s+linux /boot/(?P<version>\S+)/vmlinuz (?P<options>[^\n]+)\n[^}]*}' -REGEX_CONSOLE = r'^.*console=(?P<console_type>[^\s\d]+)(?P<console_num>[\d]+).*$' +REGEX_CONSOLE = r'^.*console=(?P<console_type>[^\s\d]+)(?P<console_num>[\d]+)(,(?P<console_speed>[\d]+))?.*$' REGEX_SANIT_CONSOLE = r'\ ?console=[^\s\d]+[\d]+(,\d+)?\ ?' REGEX_SANIT_INIT = r'\ ?init=\S*\ ?' REGEX_SANIT_QUIET = r'\ ?quiet\ ?' @@ -131,6 +131,8 @@ def parse_entry(entry: tuple) -> dict: # find console type and number regex_filter = compile(REGEX_CONSOLE) entry_dict.update(regex_filter.match(entry[1]).groupdict()) + speed = entry_dict.get('console_speed', None) + entry_dict['console_speed'] = speed if speed is not None else '115200' entry_dict['boot_opts'] = sanitize_boot_opts(entry[1]) return entry_dict @@ -271,9 +273,11 @@ def grub_cfg_fields(root_dir: str = '') -> dict: root_dir = disk.find_persistence() grub_cfg_main = f'{root_dir}/{grub.GRUB_CFG_MAIN}' + grub_vars = f'{root_dir}/{grub.CFG_VYOS_VARS}' - fields = {'default': 0, 'timeout': 5} - # 'default' and 'timeout' from legacy grub.cfg + fields = grub.vars_read(grub_vars) + # 'default' and 'timeout' from legacy grub.cfg resets 'default' to + # index, rather than uuid fields |= grub.vars_read(grub_cfg_main) fields['tools_version'] = SYSTEM_CFG_VER diff --git a/python/vyos/system/grub.py b/python/vyos/system/grub.py index a94729964..781962dd0 100644 --- a/python/vyos/system/grub.py +++ b/python/vyos/system/grub.py @@ -354,5 +354,18 @@ def set_console_type(console_type: str, root_dir: str = '') -> None: vars_current['console_type'] = str(console_type) vars_write(vars_file, vars_current) -def set_raid(root_dir: str = '') -> None: - pass +def set_console_speed(console_speed: str, root_dir: str = '') -> None: + """Write default console speed to GRUB configuration + + Args: + console_speed (str): default console speed + root_dir (str, optional): an optional path to the root directory. + Defaults to empty. + """ + if not root_dir: + root_dir = disk.find_persistence() + + vars_file: str = f'{root_dir}/{CFG_VYOS_VARS}' + vars_current: dict[str, str] = vars_read(vars_file) + vars_current['console_speed'] = str(console_speed) + vars_write(vars_file, vars_current) diff --git a/python/vyos/system/grub_util.py b/python/vyos/system/grub_util.py new file mode 100644 index 000000000..9e79d41d4 --- /dev/null +++ b/python/vyos/system/grub_util.py @@ -0,0 +1,42 @@ +# Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +from vyos.system import disk, grub, compat + +@compat.grub_cfg_update +def set_console_speed(console_speed: str, root_dir: str = '') -> None: + """Write default console speed to GRUB configuration + + Args: + console_speed (str): default console speed + root_dir (str, optional): an optional path to the root directory. + Defaults to empty. + """ + if not root_dir: + root_dir = disk.find_persistence() + + grub.set_console_speed(console_speed, root_dir) + +def update_console_speed(console_speed: str, root_dir: str = '') -> None: + """Update console_speed if different from current value""" + + if not root_dir: + root_dir = disk.find_persistence() + + vars_file: str = f'{root_dir}/{grub.CFG_VYOS_VARS}' + vars_current: dict[str, str] = grub.vars_read(vars_file) + console_speed_current = vars_current.get('console_speed', None) + if console_speed != console_speed_current: + set_console_speed(console_speed, root_dir) diff --git a/python/vyos/template.py b/python/vyos/template.py index 1368f1f61..456239568 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -894,7 +894,9 @@ def kea6_shared_network_json(shared_networks): 'name': name, 'subnet6': [] } - options = kea6_parse_options(config) + + if 'common_options' in config: + network['option-data'] = kea6_parse_options(config['common_options']) if 'interface' in config: network['interface'] = config['interface'] @@ -903,9 +905,6 @@ def kea6_shared_network_json(shared_networks): for subnet, subnet_config in config['subnet'].items(): network['subnet6'].append(kea6_parse_subnet(subnet, subnet_config)) - if options: - network['option-data'] = options - out.append(network) return dumps(out, indent=4) diff --git a/smoketest/config-tests/bgp-medium-confederation b/smoketest/config-tests/bgp-medium-confederation new file mode 100644 index 000000000..ea3c2d144 --- /dev/null +++ b/smoketest/config-tests/bgp-medium-confederation @@ -0,0 +1,73 @@ +set interfaces dummy dum0 address '1.1.1.1/32' +set interfaces dummy dum0 address '2001:db8::1/128' +set interfaces ethernet eth0 address 'fd52:100:200:fffe::1/64' +set interfaces ethernet eth0 address '192.168.253.1/24' +set interfaces ethernet eth1 +set interfaces ethernet eth2 +set policy route-map BGP-IN rule 10 action 'permit' +set policy route-map BGP-OUT rule 10 action 'permit' +set policy route-map BGP-REDISTRIBUTE rule 10 action 'deny' +set policy route-map DEFAULT-ZEBRA-IN rule 10 action 'deny' +set protocols bgp address-family ipv4-unicast redistribute connected route-map 'BGP-REDISTRIBUTE' +set protocols bgp address-family ipv4-unicast redistribute static route-map 'BGP-REDISTRIBUTE' +set protocols bgp address-family ipv6-unicast redistribute connected route-map 'BGP-REDISTRIBUTE' +set protocols bgp neighbor 192.168.253.14 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.16 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.17 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.18 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.19 peer-group 'WDC07' +set protocols bgp neighbor eth1 interface v6only peer-group 'BACKBONE' +set protocols bgp neighbor eth1 interface v6only remote-as '666' +set protocols bgp neighbor eth2 interface v6only peer-group 'BACKBONE' +set protocols bgp neighbor eth2 interface v6only remote-as '666' +set protocols bgp neighbor fd52:100:200:fffe::14 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::14 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::16 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::16 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::17 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::17 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::18 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::18 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::19 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::19 peer-group 'WDC07v6' +set protocols bgp parameters bestpath as-path confed +set protocols bgp parameters bestpath as-path multipath-relax +set protocols bgp parameters confederation identifier '696' +set protocols bgp parameters confederation peers '668' +set protocols bgp parameters confederation peers '669' +set protocols bgp parameters confederation peers '666' +set protocols bgp parameters graceful-restart +set protocols bgp parameters router-id '192.168.253.15' +set protocols bgp peer-group BACKBONE address-family ipv4-unicast nexthop-self +set protocols bgp peer-group BACKBONE address-family ipv4-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group BACKBONE address-family ipv4-unicast route-map import 'BGP-IN' +set protocols bgp peer-group BACKBONE address-family ipv4-unicast soft-reconfiguration inbound +set protocols bgp peer-group BACKBONE address-family ipv6-unicast nexthop-self +set protocols bgp peer-group BACKBONE address-family ipv6-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group BACKBONE address-family ipv6-unicast route-map import 'BGP-IN' +set protocols bgp peer-group BACKBONE address-family ipv6-unicast soft-reconfiguration inbound +set protocols bgp peer-group BACKBONE capability extended-nexthop +set protocols bgp peer-group WDC07 address-family ipv4-unicast default-originate +set protocols bgp peer-group WDC07 address-family ipv4-unicast nexthop-self +set protocols bgp peer-group WDC07 address-family ipv4-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group WDC07 address-family ipv4-unicast route-map import 'BGP-IN' +set protocols bgp peer-group WDC07 address-family ipv4-unicast soft-reconfiguration inbound +set protocols bgp peer-group WDC07 remote-as '670' +set protocols bgp peer-group WDC07 update-source 'dum0' +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast default-originate +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast nexthop-self +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast route-map import 'BGP-IN' +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast soft-reconfiguration inbound +set protocols bgp peer-group WDC07v6 remote-as '670' +set protocols bgp peer-group WDC07v6 update-source 'dum0' +set protocols bgp system-as '670' +set system config-management commit-revisions '200' +set system console device ttyS0 speed '115200' +set system domain-name 'vyos.net' +set system host-name 'vyos' +set system ip protocol bgp route-map 'DEFAULT-ZEBRA-IN' +set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0' +set system login user vyos authentication plaintext-password '' +set system syslog global facility all level 'notice' +set system syslog global facility local7 level 'debug' diff --git a/smoketest/configs/basic-vyos b/smoketest/configs/basic-vyos index fca4964bf..c42f14841 100644 --- a/smoketest/configs/basic-vyos +++ b/smoketest/configs/basic-vyos @@ -95,10 +95,15 @@ service { shared-network-name LAN6 { subnet fe88::/56 { address-range { - prefix fe88::/56 { + prefix fe88::/60 { temporary } + start fe88:0000:0000:fe:: { + stop fe88:0000:0000:ff:: + } } + domain-search vyos.net + name-server fe88::1 prefix-delegation { start fe88:0000:0000:0001:: { prefix-length 64 diff --git a/smoketest/configs/bgp-azure-ipsec-gateway b/smoketest/configs/bgp-azure-ipsec-gateway index ddcd459ae..5803e8ce9 100644 --- a/smoketest/configs/bgp-azure-ipsec-gateway +++ b/smoketest/configs/bgp-azure-ipsec-gateway @@ -226,6 +226,31 @@ protocols { } } service { + snmp { + v3 { + engineid 0xff42 + group default { + mode ro + seclevel priv + view default + } + user VyOS { + auth { + encrypted-key 0x1ad73f4620b8c0dd2de066622f875b161a14adad + type sha + } + group default + privacy { + encrypted-key 0x1ad73f4620b8c0dd2de066622f875b16 + type aes + } + } + view default { + oid 1 { + } + } + } + } ssh { disable-host-validation port 22 diff --git a/smoketest/configs/bgp-medium-confederation b/smoketest/configs/bgp-medium-confederation new file mode 100644 index 000000000..dfb944d09 --- /dev/null +++ b/smoketest/configs/bgp-medium-confederation @@ -0,0 +1,247 @@ +interfaces { + dummy dum0 { + address 1.1.1.1/32 + address 2001:db8::1/128 + } + ethernet eth0 { + address 192.168.253.1/24 + address fd52:100:200:fffe::1/64 + } + ethernet eth1 { + } + ethernet eth2 { + } +} +policy { + route-map BGP-IN { + rule 10 { + action permit + } + } + route-map BGP-OUT { + rule 10 { + action permit + } + } + route-map BGP-REDISTRIBUTE { + rule 10 { + action deny + } + } + route-map DEFAULT-ZEBRA-IN { + rule 10 { + action deny + } + } +} +protocols { + bgp 670 { + address-family { + ipv4-unicast { + redistribute { + connected { + route-map BGP-REDISTRIBUTE + } + static { + route-map BGP-REDISTRIBUTE + } + } + } + ipv6-unicast { + redistribute { + connected { + route-map BGP-REDISTRIBUTE + } + } + } + } + neighbor 192.168.253.14 { + peer-group WDC07 + } + neighbor 192.168.253.16 { + peer-group WDC07 + } + neighbor 192.168.253.17 { + peer-group WDC07 + } + neighbor 192.168.253.18 { + peer-group WDC07 + } + neighbor 192.168.253.19 { + peer-group WDC07 + } + neighbor eth1 { + interface { + v6only { + peer-group BACKBONE + remote-as 666 + } + } + } + neighbor eth2 { + interface { + v6only { + peer-group BACKBONE + remote-as 666 + } + } + } + neighbor fd52:100:200:fffe::14 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::16 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::17 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::18 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::19 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + parameters { + bestpath { + as-path { + confed + multipath-relax + } + } + confederation { + identifier 696 + peers 668 + peers 669 + peers 666 + } + default { + no-ipv4-unicast + } + graceful-restart { + } + router-id 192.168.253.15 + } + peer-group BACKBONE { + address-family { + ipv4-unicast { + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + ipv6-unicast { + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + } + capability { + extended-nexthop + } + } + peer-group WDC07 { + address-family { + ipv4-unicast { + default-originate { + } + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + } + remote-as 670 + update-source dum0 + } + peer-group WDC07v6 { + address-family { + ipv6-unicast { + default-originate { + } + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + } + remote-as 670 + update-source dum0 + } + route-map DEFAULT-ZEBRA-IN + } +} +system { + config-management { + commit-revisions 200 + } + console { + device ttyS0 { + speed 115200 + } + } + domain-name vyos.net + host-name vyos + login { + user vyos { + authentication { + encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0 + plaintext-password "" + } + } + } + syslog { + global { + facility all { + level notice + } + facility protocols { + level debug + } + } + } +} + +// Warning: Do not remove the following line. +// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:container@1:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1" +// Release version: 1.3.5 diff --git a/smoketest/configs/ospf-small b/smoketest/configs/ospf-small index b3002b1af..c55627b77 100644 --- a/smoketest/configs/ospf-small +++ b/smoketest/configs/ospf-small @@ -1,13 +1,63 @@ interfaces { dummy dum0 { - address 172.18.254.201/32 + address 172.18.254.200/32 } ethernet eth0 { duplex auto smp-affinity auto speed auto vif 201 { - address 172.18.201.10/24 + address 172.18.201.9/24 + ip { + ospf { + authentication { + md5 { + key-id 10 { + md5-key OSPFVyOSNET + } + } + } + dead-interval 40 + hello-interval 10 + priority 1 + retransmit-interval 5 + transmit-delay 1 + } + } + ipv6 { + ospfv3 { + bfd + cost 40 + } + } + } + vif 202 { + address 172.18.202.9/24 + ip { + ospf { + authentication { + md5 { + key-id 10 { + md5-key OSPFVyOSNET + } + } + } + dead-interval 40 + hello-interval 10 + priority 1 + retransmit-interval 5 + transmit-delay 1 + } + } + ipv6 { + ospfv3 { + bfd + cost 40 + } + } + } + vif 203 { + address 172.18.203.9/24 ip { ospf { authentication { @@ -51,48 +101,31 @@ protocols { ospf { area 0 { network 172.18.201.0/24 - network 172.18.254.201/32 + network 172.18.202.0/24 + network 172.18.203.0/24 + network 172.18.254.200/32 } log-adjacency-changes { } parameters { abr-type cisco - router-id 172.18.254.201 + router-id 172.18.254.200 } passive-interface default passive-interface-exclude eth0.201 + passive-interface-exclude eth0.202 + passive-interface-exclude eth0.203 } ospfv3 { area 0.0.0.0 { - interface eth0 + interface eth0.201 + interface eth0.202 + interface eth0.203 interface eth1 - interface eth2 - } - } - static { - route 0.0.0.0/0 { - next-hop 172.18.201.254 { - distance 10 - } } } } service { - lldp { - interface all { - } - snmp { - enable - } - } - snmp { - community public { - authorization ro - network 172.16.100.0/24 - } - contact "VyOS maintainers and contributors <maintainers@vyos.io>" - location "Jenkins" - } ssh { disable-host-validation port 22 @@ -120,11 +153,9 @@ system { } name-server 172.16.254.30 ntp { - server 0.pool.ntp.org { - } - server 1.pool.ntp.org { + server time1.vyos.net { } - server 2.pool.ntp.org { + server time2.vyos.net { } } sysctl { diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 2be616da1..72fbdb37d 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -671,8 +671,10 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): ### Zone def test_zone_basic(self): self.cli_set(['firewall', 'ipv4', 'name', 'smoketest', 'default-action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'name', 'smoketestv6', 'default-action', 'drop']) self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'interface', 'eth0']) self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'from', 'smoketest-local', 'firewall', 'name', 'smoketest']) + self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'intra-zone-filtering', 'firewall', 'ipv6-name', 'smoketestv6']) self.cli_set(['firewall', 'zone', 'smoketest-local', 'local-zone']) self.cli_set(['firewall', 'zone', 'smoketest-local', 'from', 'smoketest-eth0', 'firewall', 'name', 'smoketest']) self.cli_set(['firewall', 'global-options', 'state-policy', 'established', 'action', 'accept']) @@ -704,16 +706,30 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): ['ct state related', 'accept'] ] - nftables_output = cmd('sudo nft list table ip vyos_filter') - - for search in nftables_search: - matched = False - for line in nftables_output.split("\n"): - if all(item in line for item in search): - matched = True - break - self.assertTrue(matched) + nftables_search_v6 = [ + ['chain VYOS_ZONE_FORWARD'], + ['type filter hook forward priority filter + 1'], + ['chain VYOS_ZONE_OUTPUT'], + ['type filter hook output priority filter + 1'], + ['chain VYOS_ZONE_LOCAL'], + ['type filter hook input priority filter + 1'], + ['chain VZONE_smoketest-eth0'], + ['chain VZONE_smoketest-local_IN'], + ['chain VZONE_smoketest-local_OUT'], + ['oifname "eth0"', 'jump VZONE_smoketest-eth0'], + ['jump VZONE_smoketest-local_IN'], + ['jump VZONE_smoketest-local_OUT'], + ['iifname "eth0"', 'jump NAME6_smoketestv6'], + ['jump VYOS_STATE_POLICY6'], + ['chain VYOS_STATE_POLICY6'], + ['ct state established', 'log prefix "[STATE-POLICY-EST-A]"', 'accept'], + ['ct state invalid', 'drop'], + ['ct state related', 'accept'] + ] + nftables_output = cmd('sudo nft list table ip vyos_filter') + self.verify_nftables(nftables_search, 'ip vyos_filter') + self.verify_nftables(nftables_search_v6, 'ip6 vyos_filter') def test_flow_offload(self): self.cli_set(['firewall', 'flowtable', 'smoketest', 'interface', 'eth0']) diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index d5efae12c..2dbc30a41 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -1139,10 +1139,16 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): def test_bgp_24_srv6_sid(self): locator_name = 'VyOS_foo' sid = 'auto' + nexthop_ipv4 = '192.0.0.1' + nexthop_ipv6 = '2001:db8:100:200::2' self.cli_set(base_path + ['srv6', 'locator', locator_name]) self.cli_set(base_path + ['sid', 'vpn', 'per-vrf', 'export', sid]) - + self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'sid', 'vpn', 'export', sid]) + # verify() - SID per VRF and SID per address-family are mutually exclusive! + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(base_path + ['address-family', 'ipv4-unicast', 'sid']) self.cli_commit() frrconfig = self.getFRRconfig(f'router bgp {ASN}') @@ -1151,6 +1157,27 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' locator {locator_name}', frrconfig) self.assertIn(f' sid vpn per-vrf export {sid}', frrconfig) + # Now test AFI SID + self.cli_delete(base_path + ['sid']) + self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'sid', 'vpn', 'export', sid]) + self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'nexthop', 'vpn', 'export', nexthop_ipv4]) + self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'sid', 'vpn', 'export', sid]) + self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'nexthop', 'vpn', 'export', nexthop_ipv6]) + + self.cli_commit() + + frrconfig = self.getFRRconfig(f'router bgp {ASN}') + self.assertIn(f'router bgp {ASN}', frrconfig) + self.assertIn(f' segment-routing srv6', frrconfig) + self.assertIn(f' locator {locator_name}', frrconfig) + + afiv4_config = self.getFRRconfig(' address-family ipv4 unicast') + self.assertIn(f' sid vpn export {sid}', afiv4_config) + self.assertIn(f' nexthop vpn export {nexthop_ipv4}', afiv4_config) + afiv6_config = self.getFRRconfig(' address-family ipv6 unicast') + self.assertIn(f' sid vpn export {sid}', afiv6_config) + self.assertIn(f' nexthop vpn export {nexthop_ipv6}', afiv4_config) + def test_bgp_25_ipv4_ipv6_labeled_unicast_peer_group(self): pg_ipv4 = 'foo4' pg_ipv6 = 'foo6' diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py index fcbfeb7be..dcce30f55 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-server.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py @@ -104,24 +104,25 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['preference', preference]) self.cli_set(pool + ['subnet-id', '1']) # we use the first subnet IP address as default gateway - self.cli_set(pool + ['name-server', dns_1]) - self.cli_set(pool + ['name-server', dns_2]) - self.cli_set(pool + ['name-server', dns_2]) self.cli_set(pool + ['lease-time', 'default', lease_time]) self.cli_set(pool + ['lease-time', 'maximum', max_lease_time]) self.cli_set(pool + ['lease-time', 'minimum', min_lease_time]) - self.cli_set(pool + ['nis-domain', domain]) - self.cli_set(pool + ['nisplus-domain', domain]) - self.cli_set(pool + ['sip-server', sip_server]) - self.cli_set(pool + ['sntp-server', sntp_server]) - self.cli_set(pool + ['address-range', 'start', range_start, 'stop', range_stop]) + self.cli_set(pool + ['option', 'name-server', dns_1]) + self.cli_set(pool + ['option', 'name-server', dns_2]) + self.cli_set(pool + ['option', 'name-server', dns_2]) + self.cli_set(pool + ['option', 'nis-domain', domain]) + self.cli_set(pool + ['option', 'nisplus-domain', domain]) + self.cli_set(pool + ['option', 'sip-server', sip_server]) + self.cli_set(pool + ['option', 'sntp-server', sntp_server]) + self.cli_set(pool + ['range', '1', 'start', range_start]) + self.cli_set(pool + ['range', '1', 'stop', range_stop]) for server in nis_servers: - self.cli_set(pool + ['nis-server', server]) - self.cli_set(pool + ['nisplus-server', server]) + self.cli_set(pool + ['option', 'nis-server', server]) + self.cli_set(pool + ['option', 'nisplus-server', server]) for search in search_domains: - self.cli_set(pool + ['domain-search', search]) + self.cli_set(pool + ['option', 'domain-search', search]) client_base = 1 for client in ['client1', 'client2', 'client3']: @@ -217,7 +218,8 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase): pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet] self.cli_set(pool + ['subnet-id', '1']) - self.cli_set(pool + ['address-range', 'start', range_start, 'stop', range_stop]) + self.cli_set(pool + ['range', '1', 'start', range_start]) + self.cli_set(pool + ['range', '1', 'stop', range_stop]) self.cli_set(pool + ['prefix-delegation', 'prefix', delegate_start, 'delegated-length', delegate_len]) self.cli_set(pool + ['prefix-delegation', 'prefix', delegate_start, 'prefix-length', prefix_len]) diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index bf807fa5f..f6f3370c3 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -206,6 +206,10 @@ def verify_remote_as(peer_config, bgp_config): if 'v6only' in peer_config['interface']: if 'remote_as' in peer_config['interface']['v6only']: return peer_config['interface']['v6only']['remote_as'] + if 'peer_group' in peer_config['interface']['v6only']: + peer_group_name = peer_config['interface']['v6only']['peer_group'] + tmp = dict_search(f'peer_group.{peer_group_name}.remote_as', bgp_config) + if tmp: return tmp return None @@ -216,9 +220,12 @@ def verify_afi(peer_config, bgp_config): # If address_family configured under peer-group # if neighbor interface configured - peer_group_name = '' + peer_group_name = None if dict_search('interface.peer_group', peer_config): peer_group_name = peer_config['interface']['peer_group'] + elif dict_search('interface.v6only.peer_group', peer_config): + peer_group_name = peer_config['interface']['v6only']['peer_group'] + # if neighbor IP configured. if 'peer_group' in peer_config: peer_group_name = peer_config['peer_group'] @@ -538,6 +545,10 @@ def verify(bgp): tmp = dict_search(f'route_map.vpn.{export_import}', afi_config) if tmp: verify_route_map(tmp, bgp) + # per-vrf sid and per-af sid are mutually exclusive + if 'sid' in afi_config and 'sid' in bgp: + raise ConfigError('SID per VRF and SID per address-family are mutually exclusive!') + # Checks only required for L2VPN EVPN if afi in ['l2vpn_evpn']: if 'vni' in afi_config: diff --git a/src/conf_mode/service_dhcpv6-server.py b/src/conf_mode/service_dhcpv6-server.py index 7cd801cdd..214531904 100755 --- a/src/conf_mode/service_dhcpv6-server.py +++ b/src/conf_mode/service_dhcpv6-server.py @@ -81,26 +81,29 @@ def verify(dhcpv6): subnet_ids.append(subnet_config['subnet_id']) - if 'address_range' in subnet_config: - if 'start' in subnet_config['address_range']: - range6_start = [] - range6_stop = [] - for start, start_config in subnet_config['address_range']['start'].items(): - if 'stop' not in start_config: - raise ConfigError(f'address-range stop address for start "{start}" is not defined!') - stop = start_config['stop'] + if 'range' in subnet_config: + range6_start = [] + range6_stop = [] + + for num, range_config in subnet_config['range'].items(): + if 'start' in range_config: + start = range_config['start'] + + if 'stop' not in range_config: + raise ConfigError(f'Range stop address for start "{start}" is not defined!') + stop = range_config['stop'] # Start address must be inside network if not ip_address(start) in ip_network(subnet): - raise ConfigError(f'address-range start address "{start}" is not in subnet "{subnet}"!') + raise ConfigError(f'Range start address "{start}" is not in subnet "{subnet}"!') # Stop address must be inside network if not ip_address(stop) in ip_network(subnet): - raise ConfigError(f'address-range stop address "{stop}" is not in subnet "{subnet}"!') + raise ConfigError(f'Range stop address "{stop}" is not in subnet "{subnet}"!') # Stop address must be greater or equal to start address if not ip_address(stop) >= ip_address(start): - raise ConfigError(f'address-range stop address "{stop}" must be greater then or equal ' \ + raise ConfigError(f'Range stop address "{stop}" must be greater then or equal ' \ f'to the range start address "{start}"!') # DHCPv6 range start address must be unique - two ranges can't @@ -108,6 +111,7 @@ def verify(dhcpv6): if start in range6_start: raise ConfigError(f'Conflicting DHCPv6 lease range: '\ f'Pool start address "{start}" defined multipe times!') + range6_start.append(start) # DHCPv6 range stop address must be unique - two ranges can't @@ -115,12 +119,14 @@ def verify(dhcpv6): if stop in range6_stop: raise ConfigError(f'Conflicting DHCPv6 lease range: '\ f'Pool stop address "{stop}" defined multipe times!') + range6_stop.append(stop) - if 'prefix' in subnet_config: - for prefix in subnet_config['prefix']: - if ip_network(prefix) not in ip_network(subnet): - raise ConfigError(f'address-range prefix "{prefix}" is not in subnet "{subnet}""') + if 'prefix' in range_config: + prefix = range_config['prefix'] + + if not ip_network(prefix).subnet_of(ip_network(subnet)): + raise ConfigError(f'Range prefix "{prefix}" is not in subnet "{subnet}"') # Prefix delegation sanity checks if 'prefix_delegation' in subnet_config: @@ -151,13 +157,15 @@ def verify(dhcpv6): raise ConfigError(f'Either MAC address or Client identifier (DUID) is required for ' f'static mapping "{mapping}" within shared-network "{network}, {subnet}"!') - if 'vendor_option' in subnet_config: - if len(dict_search('vendor_option.cisco.tftp_server', subnet_config)) > 2: - raise ConfigError(f'No more then two Cisco tftp-servers should be defined for subnet "{subnet}"!') + if 'option' in subnet_config: + if 'vendor_option' in subnet_config['option']: + if len(dict_search('option.vendor_option.cisco.tftp_server', subnet_config)) > 2: + raise ConfigError(f'No more then two Cisco tftp-servers should be defined for subnet "{subnet}"!') # Subnets must be unique if subnet in subnets: raise ConfigError(f'DHCPv6 subnets must be unique! Subnet {subnet} defined multiple times!') + subnets.append(subnet) # DHCPv6 requires at least one configured address range or one static mapping diff --git a/src/conf_mode/system_console.py b/src/conf_mode/system_console.py index ebf9a113b..a888b125e 100755 --- a/src/conf_mode/system_console.py +++ b/src/conf_mode/system_console.py @@ -22,6 +22,7 @@ from vyos.config import Config from vyos.utils.process import call from vyos.utils.file import read_file from vyos.utils.file import write_file +from vyos.system import grub_util from vyos.template import render from vyos import ConfigError from vyos import airbag @@ -114,30 +115,7 @@ def generate(console): return None speed = console['device']['ttyS0']['speed'] - grub_config = '/boot/grub/grub.cfg' - if not os.path.isfile(grub_config): - return None - - lines = read_file(grub_config).split('\n') - p = re.compile(r'^(.* console=ttyS0),[0-9]+(.*)$') - write = False - newlines = [] - for line in lines: - if line.startswith('serial --unit'): - newline = f'serial --unit=0 --speed={speed}' - elif p.match(line): - newline = '{},{}{}'.format(p.search(line)[1], speed, p.search(line)[2]) - else: - newline = line - - if newline != line: - write = True - - newlines.append(newline) - newlines.append('') - - if write: - write_file(grub_config, '\n'.join(newlines)) + grub_util.update_console_speed(speed) return None diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook index 35721d009..d5e6462ba 100644 --- a/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook +++ b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook @@ -29,6 +29,7 @@ fi if [ "$RUN" = "yes" ]; then BASE_PATH=$(python3 -c "from vyos.defaults import directories; print(directories['isc_dhclient_dir'])") + mkdir -p ${BASE_PATH} LOG=${BASE_PATH}/dhclient_"$interface"."$proto"lease echo `date` > $LOG diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook index c7a92fe26..e6edc1ac3 100755 --- a/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook +++ b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook @@ -71,10 +71,6 @@ if __name__ == '__main__': conf_lines[i] = line.replace(old_ip, new_ip) found = True - for i, line in enumerate(secrets_lines): - if line.find(to_match) > 0: - secrets_lines[i] = line.replace(old_ip, new_ip) - if found: write_file(SWANCTL_CONF, conf_lines) ipsec_down(old_ip) diff --git a/src/migration-scripts/bgp/0-to-1 b/src/migration-scripts/bgp/0-to-1 index 03c45107b..5b8e8a163 100755 --- a/src/migration-scripts/bgp/0-to-1 +++ b/src/migration-scripts/bgp/0-to-1 @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# T3417: migrate IS-IS tagNode to node as we can only have one IS-IS process +# T3417: migrate BGP tagNode to node as we can only have one BGP process from sys import argv from sys import exit diff --git a/src/migration-scripts/bgp/1-to-2 b/src/migration-scripts/bgp/1-to-2 index 96b939b47..a40d86e67 100755 --- a/src/migration-scripts/bgp/1-to-2 +++ b/src/migration-scripts/bgp/1-to-2 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2022 VyOS maintainers and contributors +# Copyright (C) 2021-2024 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 @@ -15,6 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # T3741: no-ipv4-unicast is now enabled by default +# T5937: Migrate IPv6 BGP Neighbor Peer Groups from sys import argv from sys import exit @@ -66,6 +67,15 @@ else: if not config.exists(afi_ipv4): config.set(afi_ipv4) +# Migrate IPv6 AFI peer-group +if config.exists(base + ['neighbor']): + for neighbor in config.list_nodes(base + ['neighbor']): + tmp_path = base + ['neighbor', neighbor, 'address-family', 'ipv6-unicast', 'peer-group'] + if config.exists(tmp_path): + peer_group = config.return_value(tmp_path) + config.set(base + ['neighbor', neighbor, 'peer-group'], value=peer_group) + config.delete(tmp_path) + try: with open(file_name, 'w') as f: f.write(config.to_string()) diff --git a/src/migration-scripts/dhcpv6-server/3-to-4 b/src/migration-scripts/dhcpv6-server/3-to-4 index c065e3d43..4747ebd60 100755 --- a/src/migration-scripts/dhcpv6-server/3-to-4 +++ b/src/migration-scripts/dhcpv6-server/3-to-4 @@ -16,6 +16,8 @@ # T3316: # - Add subnet IDs to existing subnets +# - Move options to option node +# - Migrate address-range to range tagNode import sys import re @@ -37,6 +39,10 @@ if not config.exists(base): # Nothing to do sys.exit(0) +option_nodes = ['captive-portal', 'domain-search', 'name-server', + 'nis-domain', 'nis-server', 'nisplus-domain', 'nisplus-server', + 'sip-server', 'sntp-server', 'vendor-option'] + subnet_id = 1 for network in config.list_nodes(base): @@ -44,6 +50,35 @@ for network in config.list_nodes(base): for subnet in config.list_nodes(base + [network, 'subnet']): base_subnet = base + [network, 'subnet', subnet] + if config.exists(base_subnet + ['address-range']): + config.set(base_subnet + ['range']) + config.set_tag(base_subnet + ['range']) + + range_id = 1 + + if config.exists(base_subnet + ['address-range', 'prefix']): + for prefix in config.return_values(base_subnet + ['address-range', 'prefix']): + config.set(base_subnet + ['range', range_id, 'prefix'], value=prefix) + + range_id += 1 + + if config.exists(base_subnet + ['address-range', 'start']): + for start in config.list_nodes(base_subnet + ['address-range', 'start']): + stop = config.return_value(base_subnet + ['address-range', 'start', start, 'stop']) + + config.set(base_subnet + ['range', range_id, 'start'], value=start) + config.set(base_subnet + ['range', range_id, 'stop'], value=stop) + + range_id += 1 + + config.delete(base_subnet + ['address-range']) + + for option in option_nodes: + if config.exists(base_subnet + [option]): + config.set(base_subnet + ['option']) + config.copy(base_subnet + [option], base_subnet + ['option', option]) + config.delete(base_subnet + [option]) + config.set(base_subnet + ['subnet-id'], value=subnet_id) subnet_id += 1 diff --git a/src/migration-scripts/ipsec/12-to-13 b/src/migration-scripts/ipsec/12-to-13 new file mode 100755 index 000000000..504a2e9c7 --- /dev/null +++ b/src/migration-scripts/ipsec/12-to-13 @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 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 +# 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/>. + +# Changed value of dead-peer-detection.action from hold to trap + +import re + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if len(argv) < 2: + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['vpn', 'ipsec', 'ike-group'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) +else: + for ike_group in config.list_nodes(base): + base_dpd_action = base + [ike_group, 'dead-peer-detection', 'action'] + if config.exists(base_dpd_action) and config.return_value(base_dpd_action) == 'hold': + config.set(base_dpd_action, 'trap', replace=True) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/nat/5-to-6 b/src/migration-scripts/nat/5-to-6 index de3830582..c83b93d84 100755 --- a/src/migration-scripts/nat/5-to-6 +++ b/src/migration-scripts/nat/5-to-6 @@ -51,8 +51,9 @@ for direction in ['source', 'destination']: for iface in ['inbound-interface','outbound-interface']: if config.exists(base + [iface]): tmp = config.return_value(base + [iface]) - config.delete(base + [iface]) - config.set(base + [iface, 'interface-name'], value=tmp) + if tmp: + config.delete(base + [iface]) + config.set(base + [iface, 'interface-name'], value=tmp) try: with open(file_name, 'w') as f: diff --git a/src/migration-scripts/ospf/0-to-1 b/src/migration-scripts/ospf/0-to-1 index 8f02acada..a6cb9feb8 100755 --- a/src/migration-scripts/ospf/0-to-1 +++ b/src/migration-scripts/ospf/0-to-1 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2024 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 @@ -28,6 +28,7 @@ def ospf_passive_migration(config, ospf_base): default = True continue config.set(ospf_base + ['interface', interface, 'passive']) + config.set_tag(ospf_base + ['interface']) config.delete(ospf_base + ['passive-interface']) config.set(ospf_base + ['passive-interface'], value='default') @@ -35,6 +36,7 @@ def ospf_passive_migration(config, ospf_base): if config.exists(ospf_base + ['passive-interface-exclude']): for interface in config.return_values(ospf_base + ['passive-interface-exclude']): config.set(ospf_base + ['interface', interface, 'passive', 'disable']) + config.set_tag(ospf_base + ['interface']) config.delete(ospf_base + ['passive-interface-exclude']) if len(argv) < 2: diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py index 02f4d5bbb..a64acec31 100755 --- a/src/op_mode/dhcp.py +++ b/src/op_mode/dhcp.py @@ -194,14 +194,11 @@ def _get_pool_size(pool, family='inet'): size = 0 subnets = config.list_nodes(f'{base} subnet') for subnet in subnets: - if family == 'inet6': - ranges = config.list_nodes(f'{base} subnet {subnet} address-range start') - else: - ranges = config.list_nodes(f'{base} subnet {subnet} range') + ranges = config.list_nodes(f'{base} subnet {subnet} range') for range in ranges: if family == 'inet6': - start = config.list_nodes(f'{base} subnet {subnet} address-range start')[0] - stop = config.value(f'{base} subnet {subnet} address-range start {start} stop') + start = config.value(f'{base} subnet {subnet} range {range} start') + stop = config.value(f'{base} subnet {subnet} range {range} stop') else: start = config.value(f'{base} subnet {subnet} range {range} start') stop = config.value(f'{base} subnet {subnet} range {range} stop') diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index 791d76718..fad6face7 100755 --- a/src/op_mode/image_installer.py +++ b/src/op_mode/image_installer.py @@ -93,6 +93,7 @@ DEFAULT_BOOT_VARS: dict[str, str] = { 'timeout': '5', 'console_type': 'tty', 'console_num': '0', + 'console_speed': '115200', 'bootmode': 'normal' } diff --git a/src/op_mode/interfaces_wireless.py b/src/op_mode/interfaces_wireless.py index dfe50e2cb..259fd3900 100755 --- a/src/op_mode/interfaces_wireless.py +++ b/src/op_mode/interfaces_wireless.py @@ -32,6 +32,7 @@ def _verify(func): def _wrapper(*args, **kwargs): config = ConfigTreeQuery() if not config.exists(['interfaces', 'wireless']): + unconf_message = 'No Wireless interfaces configured' raise vyos.opmode.UnconfiguredSubsystem(unconf_message) return func(*args, **kwargs) return _wrapper diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py index 3ac5991b4..c07d0c4bd 100755 --- a/src/op_mode/powerctrl.py +++ b/src/op_mode/powerctrl.py @@ -191,7 +191,7 @@ def main(): nargs="*", metavar="HH:MM") - action.add_argument("--reboot_in", "-i", + action.add_argument("--reboot-in", "-i", help="Reboot the system", nargs="*", metavar="Minutes") @@ -214,7 +214,7 @@ def main(): if args.reboot is not None: for r in args.reboot: if ':' not in r and '/' not in r and '.' not in r: - print("Incorrect format! Use HH:MM") + print("Incorrect format! Use HH:MM") exit(1) execute_shutdown(args.reboot, reboot=True, ask=args.yes) if args.reboot_in is not None: diff --git a/src/system/grub_update.py b/src/system/grub_update.py index 3c851f0e0..5a7d8eb72 100644 --- a/src/system/grub_update.py +++ b/src/system/grub_update.py @@ -68,7 +68,8 @@ if __name__ == '__main__': 'default': grub.gen_version_uuid(default_entry['version']), 'bootmode': default_entry['bootmode'], 'console_type': default_entry['console_type'], - 'console_num': default_entry['console_num'] + 'console_num': default_entry['console_num'], + 'console_speed': default_entry['console_speed'] } vars.update(default_settings) |