diff options
59 files changed, 499 insertions, 387 deletions
diff --git a/data/op-mode-standardized.json b/data/op-mode-standardized.json index 2ea4d945a..7c5524675 100644 --- a/data/op-mode-standardized.json +++ b/data/op-mode-standardized.json @@ -8,6 +8,7 @@ "dhcp.py", "dns.py", "interfaces.py", +"lldp.py", "log.py", "memory.py", "nat.py", diff --git a/data/templates/chrony/chrony.conf.j2 b/data/templates/chrony/chrony.conf.j2 new file mode 100644 index 000000000..b3bfc8c0c --- /dev/null +++ b/data/templates/chrony/chrony.conf.j2 @@ -0,0 +1,58 @@ +### Autogenerated by ntp.py ### + +# This would step the system clock if the adjustment is larger than 0.1 seconds, +# but only in the first three clock updates. +makestep 1.0 3 + +# The rtcsync directive enables a mode where the system time is periodically +# copied to the RTC and chronyd does not try to track its drift. This directive +# cannot be used with the rtcfile directive. On Linux, the RTC copy is performed +# by the kernel every 11 minutes. +rtcsync + +# This directive specifies the maximum amount of memory that chronyd is allowed +# to allocate for logging of client accesses and the state that chronyd as an +# NTP server needs to support the interleaved mode for its clients. +clientloglimit 1048576 + +driftfile /run/chrony/drift +dumpdir /run/chrony +pidfile {{ config_file | replace('.conf', '.pid') }} + +# Determine when will the next leap second occur and what is the current offset +leapsectz right/UTC + +user {{ user }} + +# NTP servers to reach out to +{% if server is vyos_defined %} +{% for server, config in server.items() %} +{% set association = 'server' %} +{% if config.pool is vyos_defined %} +{% set association = 'pool' %} +{% endif %} +{{ association }} {{ server | replace('_', '-') }} iburst {{ 'noselect' if config.noselect is vyos_defined }} {{ 'prefer' if config.prefer is vyos_defined }} +{% endfor %} +{% endif %} + +# Allowed clients configuration +{% if allow_client.address is vyos_defined %} +{% for address in allow_client.address %} +allow {{ address }} +{% endfor %} +{% endif %} +deny all + +{% if listen_address is vyos_defined or interface is vyos_defined %} +# NTP should listen on configured addresses only +{% if listen_address is vyos_defined %} +{% for address in listen_address %} +bindaddress {{ address }} +{% endfor %} +{% endif %} +{% if interface is vyos_defined %} +{% for ifname in interface %} +binddevice {{ ifname }} +{% endfor %} +{% endif %} +{% endif %} diff --git a/data/templates/ntp/override.conf.j2 b/data/templates/chrony/override.conf.j2 index 6fed9d7d2..9eaea7608 100644 --- a/data/templates/ntp/override.conf.j2 +++ b/data/templates/chrony/override.conf.j2 @@ -5,10 +5,13 @@ ConditionPathExists={{ config_file }} After=vyos-router.service [Service] +EnvironmentFile= ExecStart= -ExecStart={{ vrf_command }}/usr/sbin/ntpd -g -p {{ config_file | replace('.conf', '.pid') }} -c {{ config_file }} -u ntp:ntp +ExecStart={{ vrf_command }}/usr/sbin/chronyd -F 1 -f {{ config_file }} PIDFile= PIDFile={{ config_file | replace('.conf', '.pid') }} Restart=always RestartSec=10 +# Required for VRF support +ProtectControlGroups=No diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2 index 0baff2d72..8c4a81c57 100644 --- a/data/templates/frr/ospfd.frr.j2 +++ b/data/templates/frr/ospfd.frr.j2 @@ -84,11 +84,13 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% endfor %} {% if area_config.range is vyos_defined %} {% for range, range_config in area_config.range.items() %} -{% if range_config.cost is vyos_defined %} - area {{ area_id }} range {{ range }} cost {{ range_config.cost }} -{% endif %} {% if range_config.not_advertise is vyos_defined %} area {{ area_id }} range {{ range }} not-advertise +{% else %} + area {{ area_id }} range {{ range }} +{% endif %} +{% if range_config.cost is vyos_defined %} + area {{ area_id }} range {{ range }} cost {{ range_config.cost }} {% endif %} {% if range_config.substitute is vyos_defined %} area {{ area_id }} range {{ range }} substitute {{ range_config.substitute }} diff --git a/data/templates/ipsec/swanctl/peer.j2 b/data/templates/ipsec/swanctl/peer.j2 index 837fa263c..9d95271fe 100644 --- a/data/templates/ipsec/swanctl/peer.j2 +++ b/data/templates/ipsec/swanctl/peer.j2 @@ -45,11 +45,7 @@ {% endif %} } remote { -{% if peer_conf.authentication.remote_id is vyos_defined %} id = "{{ peer_conf.authentication.remote_id }}" -{% else %} - id = "{{ peer }}" -{% endif %} auth = {{ 'psk' if peer_conf.authentication.mode == 'pre-shared-secret' else 'pubkey' }} {% if peer_conf.authentication.mode == 'rsa' %} pubkeys = {{ peer_conf.authentication.rsa.remote_key }}.pem diff --git a/data/templates/ntp/ntpd.conf.j2 b/data/templates/ntp/ntpd.conf.j2 deleted file mode 100644 index 8921826fa..000000000 --- a/data/templates/ntp/ntpd.conf.j2 +++ /dev/null @@ -1,49 +0,0 @@ -### Autogenerated by ntp.py ### - -# -# Non-configurable defaults -# -driftfile /var/lib/ntp/ntp.drift -# By default, only allow ntpd to query time sources, ignore any incoming requests -restrict default noquery nopeer notrap nomodify -# Allow pool associations -restrict source nomodify notrap noquery -# Local users have unrestricted access, allowing reconfiguration via ntpdc -restrict 127.0.0.1 -restrict -6 ::1 - -# -# Configurable section -# -{% if server is vyos_defined %} -{% for server, config in server.items() %} -{% set association = 'server' %} -{% if config.pool is vyos_defined %} -{% set association = 'pool' %} -{% endif %} -{{ association }} {{ server | replace('_', '-') }} iburst {{ 'noselect' if config.noselect is vyos_defined }} {{ 'preempt' if config.preempt is vyos_defined }} {{ 'prefer' if config.prefer is vyos_defined }} -{% endfor %} -{% endif %} - -{% if allow_clients.address is vyos_defined %} -# Allowed clients configuration -restrict default ignore -{% for address in allow_clients.address %} -restrict {{ address | address_from_cidr }} mask {{ address | netmask_from_cidr }} nomodify notrap nopeer -{% endfor %} -{% endif %} - -{% if listen_address is vyos_defined or interface is vyos_defined %} -# NTP should listen on configured addresses only -interface ignore wildcard -{% if listen_address is vyos_defined %} -{% for address in listen_address %} -interface listen {{ address }} -{% endfor %} -{% endif %} -{% if interface is vyos_defined %} -{% for ifname in interface %} -interface listen {{ ifname }} -{% endfor %} -{% endif %} -{% endif %} diff --git a/data/templates/telegraf/telegraf.j2 b/data/templates/telegraf/telegraf.j2 index 36571ce98..c9f402281 100644 --- a/data/templates/telegraf/telegraf.j2 +++ b/data/templates/telegraf/telegraf.j2 @@ -102,7 +102,7 @@ dirs = ["/proc/sys/net/ipv4/netfilter","/proc/sys/net/netfilter"] [[inputs.ethtool]] interface_include = {{ interfaces_ethernet }} -[[inputs.ntpq]] +[[inputs.chrony]] dns_lookup = true [[inputs.internal]] [[inputs.nstat]] diff --git a/debian/control b/debian/control index a477bffec..1e593d378 100644 --- a/debian/control +++ b/debian/control @@ -101,8 +101,7 @@ Depends: nfct, nftables (>= 0.9.3), nginx-light, - ntp, - ntpdate, + chrony, nvme-cli, ocserv, opennhrp, diff --git a/interface-definitions/include/version/ntp-version.xml.i b/interface-definitions/include/version/ntp-version.xml.i index cc4ff9a1c..9eafbf7f0 100644 --- a/interface-definitions/include/version/ntp-version.xml.i +++ b/interface-definitions/include/version/ntp-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/ntp-version.xml.i --> -<syntaxVersion component='ntp' version='1'></syntaxVersion> +<syntaxVersion component='ntp' version='2'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/ntp.xml.in b/interface-definitions/ntp.xml.in index 85636a50f..65e40ee32 100644 --- a/interface-definitions/ntp.xml.in +++ b/interface-definitions/ntp.xml.in @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- NTP configuration --> <interfaceDefinition> - <node name="system"> + <node name="service"> <children> <node name="ntp" owner="${vyos_conf_scripts_dir}/ntp.py"> <properties> @@ -43,12 +43,6 @@ <valueless/> </properties> </leafNode> - <leafNode name="preempt"> - <properties> - <help>Specifies the association as preemptable rather than the default persistent</help> - <valueless/> - </properties> - </leafNode> <leafNode name="prefer"> <properties> <help>Marks the server as preferred</help> @@ -57,24 +51,33 @@ </leafNode> </children> </tagNode> - <node name="allow-clients"> + <node name="allow-client"> <properties> - <help>Network Time Protocol (NTP) server options</help> + <help>Specify NTP clients allowed to access the server</help> </properties> <children> <leafNode name="address"> <properties> <help>IP address</help> <valueHelp> + <format>ipv4</format> + <description>Allowed IPv4 address</description> + </valueHelp> + <valueHelp> <format>ipv4net</format> - <description>IP address and prefix length</description> + <description>Allowed IPv4 prefix</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>Allowed IPv6 address</description> </valueHelp> <valueHelp> <format>ipv6net</format> - <description>IPv6 address and prefix length</description> + <description>Allowed IPv6 prefix</description> </valueHelp> <multi/> <constraint> + <validator name="ip-address"/> <validator name="ip-prefix"/> </constraint> </properties> diff --git a/interface-definitions/vpn-ipsec.xml.in b/interface-definitions/vpn-ipsec.xml.in index 64966b540..fd74a51d7 100644 --- a/interface-definitions/vpn-ipsec.xml.in +++ b/interface-definitions/vpn-ipsec.xml.in @@ -957,6 +957,7 @@ <description>ID used for peer authentication</description> </valueHelp> </properties> + <defaultValue>%any</defaultValue> </leafNode> <leafNode name="use-x509-id"> <properties> diff --git a/op-mode-definitions/date.xml.in b/op-mode-definitions/date.xml.in index 15a69dbd9..6d8586025 100644 --- a/op-mode-definitions/date.xml.in +++ b/op-mode-definitions/date.xml.in @@ -37,28 +37,6 @@ </properties> <command>/bin/date "$3"</command> </tagNode> - <node name="date"> - <properties> - <help>Set system date and time</help> - </properties> - <children> - <node name="ntp"> - <properties> - <help>Set system date and time from NTP server (default: 0.pool.ntp.org)</help> - </properties> - <command>/usr/sbin/ntpdate -u 0.pool.ntp.org</command> - </node> - <tagNode name="ntp"> - <properties> - <help>Set system date and time from NTP server</help> - <completionHelp> - <script>${vyos_completion_dir}/list_ntp_servers.sh</script> - </completionHelp> - </properties> - <command>/usr/sbin/ntpdate -u "$4"</command> - </tagNode> - </children> - </node> </children> </node> </interfaceDefinition> diff --git a/op-mode-definitions/lldp.xml.in b/op-mode-definitions/lldp.xml.in index 297ccf1f4..07cafa77f 100644 --- a/op-mode-definitions/lldp.xml.in +++ b/op-mode-definitions/lldp.xml.in @@ -11,14 +11,8 @@ <properties> <help>Show LLDP neighbors</help> </properties> - <command>${vyos_op_scripts_dir}/lldp_op.py --all</command> + <command>${vyos_op_scripts_dir}/lldp.py show_neighbors</command> <children> - <node name="detail"> - <properties> - <help>Show LLDP neighbor details</help> - </properties> - <command>${vyos_op_scripts_dir}/lldp_op.py --detail</command> - </node> <tagNode name="interface"> <properties> <help>Show LLDP for specified interface</help> @@ -26,7 +20,7 @@ <script>${vyos_completion_dir}/list_interfaces.py</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/lldp_op.py --interface $5</command> + <command>${vyos_op_scripts_dir}/lldp.py show_neighbors --interface $5</command> </tagNode> </children> </node> diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in index 8abc5f4db..d616bfc08 100644 --- a/op-mode-definitions/monitor-log.xml.in +++ b/op-mode-definitions/monitor-log.xml.in @@ -101,9 +101,15 @@ </leafNode> <leafNode name="nhrp"> <properties> - <help>Monitor last lines of NHRP log</help> + <help>Monitor last lines of Next Hop Resolution Protocol (NHRP) log</help> </properties> - <command>journalctl --no-hostname --boot --unit opennhrp.service</command> + <command>journalctl --no-hostname --boot --follow --unit opennhrp.service</command> + </leafNode> + <leafNode name="ntp"> + <properties> + <help>Monitor last lines of Network Time Protocol (NTP) log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit chrony.service</command> </leafNode> <node name="pppoe"> <properties> diff --git a/op-mode-definitions/show-interfaces-bonding.xml.in b/op-mode-definitions/show-interfaces-bonding.xml.in index 6908153dd..c41e7bd5f 100644 --- a/op-mode-definitions/show-interfaces-bonding.xml.in +++ b/op-mode-definitions/show-interfaces-bonding.xml.in @@ -11,13 +11,13 @@ <path>interfaces bonding</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=bonding</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified bonding interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=bonding</command> </leafNode> <leafNode name="detail"> <properties> @@ -38,13 +38,13 @@ <path>interfaces bonding ${COMP_WORDS[3]} vif</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=bonding</command> <children> <leafNode name="brief"> <properties> <help>Show summary of specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=bonding</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-bridge.xml.in b/op-mode-definitions/show-interfaces-bridge.xml.in index b950c3a17..22cd3ee67 100644 --- a/op-mode-definitions/show-interfaces-bridge.xml.in +++ b/op-mode-definitions/show-interfaces-bridge.xml.in @@ -11,13 +11,13 @@ <path>interfaces bridge</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=bridge</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified bridge interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=bridge</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-dummy.xml.in b/op-mode-definitions/show-interfaces-dummy.xml.in index 398e00636..958d3483d 100644 --- a/op-mode-definitions/show-interfaces-dummy.xml.in +++ b/op-mode-definitions/show-interfaces-dummy.xml.in @@ -11,13 +11,13 @@ <path>interfaces dummy</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=dummy</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified dummy interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=dummy</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-ethernet.xml.in b/op-mode-definitions/show-interfaces-ethernet.xml.in index 40d4adbb2..81759c2b6 100644 --- a/op-mode-definitions/show-interfaces-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-ethernet.xml.in @@ -11,13 +11,13 @@ <path>interfaces ethernet</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=ethernet</command> </leafNode> <leafNode name="identify"> <properties> @@ -58,13 +58,13 @@ <path>interfaces ethernet ${COMP_WORDS[3]} vif</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=ethernet</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-geneve.xml.in b/op-mode-definitions/show-interfaces-geneve.xml.in index be3084af3..3cf45878d 100644 --- a/op-mode-definitions/show-interfaces-geneve.xml.in +++ b/op-mode-definitions/show-interfaces-geneve.xml.in @@ -11,13 +11,13 @@ <path>interfaces geneve</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=geneve</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified GENEVE interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=geneve</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-input.xml.in b/op-mode-definitions/show-interfaces-input.xml.in index 1f8505160..5d93dcee6 100644 --- a/op-mode-definitions/show-interfaces-input.xml.in +++ b/op-mode-definitions/show-interfaces-input.xml.in @@ -11,13 +11,13 @@ <path>interfaces input</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=input</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified input interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=input</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-l2tpv3.xml.in b/op-mode-definitions/show-interfaces-l2tpv3.xml.in index ff08b8266..713e36dac 100644 --- a/op-mode-definitions/show-interfaces-l2tpv3.xml.in +++ b/op-mode-definitions/show-interfaces-l2tpv3.xml.in @@ -11,13 +11,13 @@ <path>interfaces l2tpv3</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=l2tpv3</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified L2TPv3 interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=l2tpv3</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-loopback.xml.in b/op-mode-definitions/show-interfaces-loopback.xml.in index 9919bf32b..a24151cc3 100644 --- a/op-mode-definitions/show-interfaces-loopback.xml.in +++ b/op-mode-definitions/show-interfaces-loopback.xml.in @@ -11,13 +11,13 @@ <path>interfaces loopback</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=loopback</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified Loopback interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=loopback</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-pppoe.xml.in b/op-mode-definitions/show-interfaces-pppoe.xml.in index 80bfd00ff..a34473148 100644 --- a/op-mode-definitions/show-interfaces-pppoe.xml.in +++ b/op-mode-definitions/show-interfaces-pppoe.xml.in @@ -11,7 +11,7 @@ <path>interfaces pppoe</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=pppoe</command> <children> <leafNode name="log"> <properties> diff --git a/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in b/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in index 0c00dbdd0..cb62639ee 100644 --- a/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in @@ -11,13 +11,13 @@ <path>interfaces pseudo-ethernet</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=pseudo-ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified pseudo-ethernet/MACvlan interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=pseudo-ethernet</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-sstpc.xml.in b/op-mode-definitions/show-interfaces-sstpc.xml.in index c473f9822..a619a9fd2 100644 --- a/op-mode-definitions/show-interfaces-sstpc.xml.in +++ b/op-mode-definitions/show-interfaces-sstpc.xml.in @@ -11,7 +11,7 @@ <path>interfaces sstpc</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=sstpc</command> <children> <leafNode name="log"> <properties> diff --git a/op-mode-definitions/show-interfaces-tunnel.xml.in b/op-mode-definitions/show-interfaces-tunnel.xml.in index 4af90b813..10e10e655 100644 --- a/op-mode-definitions/show-interfaces-tunnel.xml.in +++ b/op-mode-definitions/show-interfaces-tunnel.xml.in @@ -11,13 +11,13 @@ <path>interfaces tunnel</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=tunnel</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified tunnel interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=tunnel</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in b/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in index 2aa71c687..c743492fb 100644 --- a/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in @@ -11,13 +11,13 @@ <path>interfaces virtual-ethernet</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=virtual-ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified virtual-ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=virtual-ethernet</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-vti.xml.in b/op-mode-definitions/show-interfaces-vti.xml.in index 195e1d5da..d532894b7 100644 --- a/op-mode-definitions/show-interfaces-vti.xml.in +++ b/op-mode-definitions/show-interfaces-vti.xml.in @@ -11,13 +11,13 @@ <path>interfaces vti</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=vti</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified vti interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=vti</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-vxlan.xml.in b/op-mode-definitions/show-interfaces-vxlan.xml.in index a1d01a6af..fde832551 100644 --- a/op-mode-definitions/show-interfaces-vxlan.xml.in +++ b/op-mode-definitions/show-interfaces-vxlan.xml.in @@ -11,13 +11,13 @@ <path>interfaces vxlan</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=vxlan</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified VXLAN interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=vxlan</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-wireguard.xml.in b/op-mode-definitions/show-interfaces-wireguard.xml.in index 55879cfff..eba8de568 100644 --- a/op-mode-definitions/show-interfaces-wireguard.xml.in +++ b/op-mode-definitions/show-interfaces-wireguard.xml.in @@ -11,7 +11,7 @@ <script>${vyos_completion_dir}/list_interfaces.py --type wireguard</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireguard</command> <children> <leafNode name="allowed-ips"> <properties> diff --git a/op-mode-definitions/show-interfaces-wireless.xml.in b/op-mode-definitions/show-interfaces-wireless.xml.in index 7ae2c8ce4..b0a272225 100644 --- a/op-mode-definitions/show-interfaces-wireless.xml.in +++ b/op-mode-definitions/show-interfaces-wireless.xml.in @@ -31,13 +31,13 @@ <script>${vyos_completion_dir}/list_interfaces.py --type wireless</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireless</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified wireless interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=wireless</command> </leafNode> <node name="scan"> <properties> @@ -63,13 +63,13 @@ <properties> <help>Show specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=wireless</command> <children> <leafNode name="brief"> <properties> <help>Show summary of specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=wireless</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-wwan.xml.in b/op-mode-definitions/show-interfaces-wwan.xml.in index 8ac5933a2..17d4111a9 100644 --- a/op-mode-definitions/show-interfaces-wwan.xml.in +++ b/op-mode-definitions/show-interfaces-wwan.xml.in @@ -12,7 +12,7 @@ <script>cd /sys/class/net; ls -d wwan*</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wirelessmodem</command> <children> <leafNode name="capabilities"> <properties> diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 977ece453..6608ea0d8 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -204,7 +204,7 @@ </leafNode> <leafNode name="lldp"> <properties> - <help>Show log for LLDP</help> + <help>Show log for Link Layer Discovery Protocol (LLDP)</help> </properties> <command>journalctl --no-hostname --boot --unit lldpd.service</command> </leafNode> @@ -216,10 +216,16 @@ </leafNode> <leafNode name="nhrp"> <properties> - <help>Show log for NHRP</help> + <help>Show log for Next Hop Resolution Protocol (NHRP)</help> </properties> <command>journalctl --no-hostname --boot --unit opennhrp.service</command> </leafNode> + <leafNode name="ntp"> + <properties> + <help>Show log for Network Time Protocol (NTP)</help> + </properties> + <command>journalctl --no-hostname --boot --unit chrony.service</command> + </leafNode> <node name="macsec"> <properties> <help>Show log for MACsec</help> diff --git a/op-mode-definitions/show-ntp.xml.in b/op-mode-definitions/show-ntp.xml.in index 01f4477d8..0907722af 100644 --- a/op-mode-definitions/show-ntp.xml.in +++ b/op-mode-definitions/show-ntp.xml.in @@ -6,22 +6,13 @@ <properties> <help>Show peer status of NTP daemon</help> </properties> - <command>${vyos_op_scripts_dir}/show_ntp.sh --basic</command> + <command>${vyos_op_scripts_dir}/show_ntp.sh --sourcestats</command> <children> - <tagNode name="server"> + <node name="system"> <properties> - <help>Show date and time of specified NTP server</help> - <completionHelp> - <script>${vyos_completion_dir}/list_ntp_servers.sh</script> - </completionHelp> + <help>Show parameters about the system clock performance</help> </properties> - <command>${vyos_op_scripts_dir}/show_ntp.sh --server "$4"</command> - </tagNode> - <node name="info"> - <properties> - <help>Show NTP operational summary</help> - </properties> - <command>${vyos_op_scripts_dir}/show_ntp.sh --info</command> + <command>${vyos_op_scripts_dir}/show_ntp.sh --tracking</command> </node> </children> </node> diff --git a/python/vyos/configsession.py b/python/vyos/configsession.py index 9864aa5c5..df44fd8d6 100644 --- a/python/vyos/configsession.py +++ b/python/vyos/configsession.py @@ -34,8 +34,8 @@ REMOVE_IMAGE = ['/opt/vyatta/bin/vyatta-boot-image.pl', '--del'] GENERATE = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'generate'] SHOW = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'show'] RESET = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'reset'] -ADD = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'add'] -DELETE = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'delete'] +OP_CMD_ADD = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'add'] +OP_CMD_DELETE = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'delete'] # Default "commit via" string APP = "vyos-http-api" @@ -208,11 +208,11 @@ class ConfigSession(object): return out def add_container_image(self, name): - out = self.__run_command(ADD + ['container', 'image'] + [name]) + out = self.__run_command(OP_CMD_ADD + ['container', 'image'] + [name]) return out def delete_container_image(self, name): - out = self.__run_command(DELETE + ['container', 'image'] + [name]) + out = self.__run_command(OP_CMD_DELETE + ['container', 'image'] + [name]) return out def show_container_image(self): diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 519cfc58c..5080144ff 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -239,7 +239,7 @@ class EthernetIf(Interface): if not isinstance(state, bool): raise ValueError('Value out of range') - rps_cpus = '0' + rps_cpus = 0 queues = len(glob(f'/sys/class/net/{self.ifname}/queues/rx-*')) if state: # Enable RPS on all available CPUs except CPU0 which we will not @@ -248,10 +248,16 @@ class EthernetIf(Interface): # representation of the CPUs which should participate on RPS, we # can enable more CPUs that are physically present on the system, # Linux will clip that internally! - rps_cpus = 'ffffffff,ffffffff,ffffffff,fffffffe' + rps_cpus = (1 << os.cpu_count()) -1 + + # XXX: we should probably reserve one core when the system is under + # high preasure so we can still have a core left for housekeeping. + # This is done by masking out the lowst bit so CPU0 is spared from + # receive packet steering. + rps_cpus &= ~1 for i in range(0, queues): - self._write_sysfs(f'/sys/class/net/{self.ifname}/queues/rx-{i}/rps_cpus', rps_cpus) + self._write_sysfs(f'/sys/class/net/{self.ifname}/queues/rx-{i}/rps_cpus', f'{rps_cpus:x}') # send bitmask representation as hex string without leading '0x' return True diff --git a/python/vyos/opmode.py b/python/vyos/opmode.py index 19c476b1c..30e893d74 100644 --- a/python/vyos/opmode.py +++ b/python/vyos/opmode.py @@ -70,13 +70,13 @@ class InternalError(Error): def _is_op_mode_function_name(name): - if re.match(r"^(show|clear|reset|restart|add|delete)", name): + if re.match(r"^(show|clear|reset|restart|add|delete|generate)", name): return True else: return False -def _is_show(name): - if re.match(r"^show", name): +def _capture_output(name): + if re.match(r"^(show|generate)", name): return True else: return False @@ -203,14 +203,14 @@ def run(module): # it would cause an extra argument error when we pass the dict to a function del args["subcommand"] - # Show commands must always get the "raw" argument, - # but other commands (clear/reset/restart) should not, + # Show and generate commands must always get the "raw" argument, + # but other commands (clear/reset/restart/add/delete) should not, # because they produce no output and it makes no sense for them. - if ("raw" not in args) and _is_show(function_name): + if ("raw" not in args) and _capture_output(function_name): args["raw"] = False - if re.match(r"^show", function_name): - # Show commands are slightly special: + if _capture_output(function_name): + # Show and generate commands are slightly special: # they may return human-formatted output # or a raw dict that we need to serialize in JSON for printing res = func(**args) diff --git a/python/vyos/util.py b/python/vyos/util.py index 6a828c0ac..110da3be5 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -348,9 +348,11 @@ def colon_separated_to_dict(data_string, uniquekeys=False): l = l.strip() if l: match = re.match(key_value_re, l) - if match: + if match and (len(match.groups()) == 2): key = match.groups()[0].strip() value = match.groups()[1].strip() + else: + raise ValueError(f"""Line "{l}" could not be parsed a colon-separated pair """, l) if key in data.keys(): if uniquekeys: raise ValueError("Data string has duplicate keys: {0}".format(key)) diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index ed611062a..e53413f0d 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -160,7 +160,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): self.assertFalse(is_intf_addr_assigned(intf, addr['addr'])) def test_offloading_rps(self): - # enable RPS on all available CPUs, RPS works woth a CPU bitmask, + # enable RPS on all available CPUs, RPS works with a CPU bitmask, # where each bit represents a CPU (core/thread). The formula below # expands to rps_cpus = 255 for a 8 core system rps_cpus = (1 << os.cpu_count()) -1 diff --git a/smoketest/scripts/cli/test_load_balancning_wan.py b/smoketest/scripts/cli/test_load_balancing_wan.py index 23020b9b1..33c69c595 100755 --- a/smoketest/scripts/cli/test_load_balancning_wan.py +++ b/smoketest/scripts/cli/test_load_balancing_wan.py @@ -46,7 +46,6 @@ def cmd_in_netns(netns, cmd): def delete_netns(name): return call(f'sudo ip netns del {name}') - class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): @@ -61,7 +60,6 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): self.cli_commit() def test_table_routes(self): - ns1 = 'ns201' ns2 = 'ns202' ns3 = 'ns203' @@ -79,6 +77,7 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): create_veth_pair(iface1, container_iface1) create_veth_pair(iface2, container_iface2) create_veth_pair(iface3, container_iface3) + move_interface_to_netns(container_iface1, ns1) move_interface_to_netns(container_iface2, ns2) move_interface_to_netns(container_iface3, ns3) @@ -125,7 +124,7 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): self.assertEqual(tmp, original) # Delete veth interfaces and netns - for iface in [iface1, iface2]: + for iface in [iface1, iface2, iface3, container_iface1, container_iface2, container_iface3]: call(f'sudo ip link del dev {iface}') delete_netns(ns1) @@ -196,9 +195,10 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): call(f'sudo ip address add 203.0.113.10/24 dev {iface1}') call(f'sudo ip address add 192.0.2.10/24 dev {iface2}') call(f'sudo ip address add 198.51.100.10/24 dev {iface3}') - call(f'sudo ip link set dev {iface1} up') - call(f'sudo ip link set dev {iface2} up') - call(f'sudo ip link set dev {iface3} up') + + for iface in [iface1, iface2, iface3]: + call(f'sudo ip link set dev {iface} up') + cmd_in_netns(ns1, f'ip link set {container_iface1} name eth0') cmd_in_netns(ns2, f'ip link set {container_iface2} name eth0') cmd_in_netns(ns3, f'ip link set {container_iface3} name eth0') @@ -247,12 +247,11 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): self.assertEqual(tmp, nat_vyos_pre_snat_hook) # Delete veth interfaces and netns - for iface in [iface1, iface2]: + for iface in [iface1, iface2, iface3, container_iface1, container_iface2, container_iface3]: call(f'sudo ip link del dev {iface}') delete_netns(ns1) delete_netns(ns2) - if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index 8dd0160d3..581959b15 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -75,6 +75,10 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['log-adjacency-changes', 'detail']) self.cli_set(base_path + ['default-metric', metric]) self.cli_set(base_path + ['passive-interface', 'default']) + self.cli_set(base_path + ['area', '10', 'area-type', 'stub']) + self.cli_set(base_path + ['area', '10', 'network', '10.0.0.0/16']) + self.cli_set(base_path + ['area', '10', 'range', '10.0.1.0/24']) + self.cli_set(base_path + ['area', '10', 'range', '10.0.2.0/24', 'not-advertise']) # commit changes self.cli_commit() @@ -90,6 +94,11 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' capability opaque', frrconfig) self.assertIn(f' default-metric {metric}', frrconfig) self.assertIn(f' passive-interface default', frrconfig) + self.assertIn(f' area 10 stub', frrconfig) + self.assertIn(f' network 10.0.0.0/16 area 10', frrconfig) + self.assertIn(f' area 10 range 10.0.1.0/24', frrconfig) + self.assertNotIn(f' area 10 range 10.0.1.0/24 not-advertise', frrconfig) + self.assertIn(f' area 10 range 10.0.2.0/24 not-advertise', frrconfig) def test_ospf_03_access_list(self): diff --git a/smoketest/scripts/cli/test_service_dhcpv6-relay.py b/smoketest/scripts/cli/test_service_dhcpv6-relay.py index fc206435b..8bb58d296 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-relay.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-relay.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -34,22 +34,30 @@ listen_addr = '2001:db8:ffff::1/64' interfaces = [] class TestServiceDHCPv6Relay(VyOSUnitTestSHIM.TestCase): - def setUp(self): - for tmp in interfaces: + @classmethod + def setUpClass(cls): + super(TestServiceDHCPv6Relay, cls).setUpClass() + + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, base_path) + + for tmp in Section.interfaces('ethernet', vlan=False): + interfaces.append(tmp) listen = listen_addr if tmp == upstream_if: listen = upstream_if_addr - self.cli_set(['interfaces', 'ethernet', tmp, 'address', listen]) + cls.cli_set(cls, ['interfaces', 'ethernet', tmp, 'address', listen]) - def tearDown(self): - self.cli_delete(base_path) + @classmethod + def tearDownClass(cls): for tmp in interfaces: listen = listen_addr if tmp == upstream_if: listen = upstream_if_addr - self.cli_delete(['interfaces', 'ethernet', tmp, 'address', listen]) + cls.cli_delete(cls, ['interfaces', 'ethernet', tmp, 'address', listen]) - self.cli_commit() + super(TestServiceDHCPv6Relay, cls).tearDownClass() def test_relay_default(self): dhcpv6_server = '2001:db8::ffff' @@ -100,9 +108,5 @@ class TestServiceDHCPv6Relay(VyOSUnitTestSHIM.TestCase): self.assertTrue(process_named_running(PROCESS_NAME)) if __name__ == '__main__': - for tmp in Section.interfaces('ethernet'): - if '.' not in tmp: - interfaces.append(tmp) - unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ntp.py b/smoketest/scripts/cli/test_service_ntp.py index a0806acf0..d4793adb6 100755 --- a/smoketest/scripts/cli/test_system_ntp.py +++ b/smoketest/scripts/cli/test_service_ntp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -19,14 +19,12 @@ import unittest from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError -from vyos.template import address_from_cidr -from vyos.template import netmask_from_cidr -from vyos.util import read_file +from vyos.util import cmd from vyos.util import process_named_running -PROCESS_NAME = 'ntpd' -NTP_CONF = '/run/ntpd/ntpd.conf' -base_path = ['system', 'ntp'] +PROCESS_NAME = 'chronyd' +NTP_CONF = '/run/chrony/chrony.conf' +base_path = ['service', 'ntp'] class TestSystemNTP(VyOSUnitTestSHIM.TestCase): @classmethod @@ -38,6 +36,8 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): cls.cli_delete(cls, base_path) def tearDown(self): + self.assertTrue(process_named_running(PROCESS_NAME)) + self.cli_delete(base_path) self.cli_commit() @@ -46,7 +46,7 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): def test_01_ntp_options(self): # Test basic NTP support with multiple servers and their options servers = ['192.0.2.1', '192.0.2.2'] - options = ['noselect', 'preempt', 'prefer'] + options = ['noselect', 'prefer'] pools = ['pool.vyos.io'] for server in servers: @@ -61,12 +61,14 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Check generated configuration - config = read_file(NTP_CONF) - self.assertIn('driftfile /var/lib/ntp/ntp.drift', config) - self.assertIn('restrict default noquery nopeer notrap nomodify', config) - self.assertIn('restrict source nomodify notrap noquery', config) - self.assertIn('restrict 127.0.0.1', config) - self.assertIn('restrict -6 ::1', config) + # this file must be read with higher permissions + config = cmd(f'sudo cat {NTP_CONF}') + self.assertIn('driftfile /run/chrony/drift', config) + self.assertIn('dumpdir /run/chrony', config) + self.assertIn('clientloglimit 1048576', config) + self.assertIn('rtcsync', config) + self.assertIn('makestep 1.0 3', config) + self.assertIn('leapsectz right/UTC', config) for server in servers: self.assertIn(f'server {server} iburst ' + ' '.join(options), config) @@ -80,9 +82,9 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): for listen in listen_address: self.cli_set(base_path + ['listen-address', listen]) - networks = ['192.0.2.0/24', '2001:db8:1000::/64'] + networks = ['192.0.2.0/24', '2001:db8:1000::/64', '100.64.0.0', '2001:db8::ffff'] for network in networks: - self.cli_set(base_path + ['allow-clients', 'address', network]) + self.cli_set(base_path + ['allow-client', 'address', network]) # Verify "NTP server not configured" verify() statement with self.assertRaises(ConfigSessionError): @@ -95,18 +97,14 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Check generated client address configuration - config = read_file(NTP_CONF) - self.assertIn('restrict default ignore', config) - + # this file must be read with higher permissions + config = cmd(f'sudo cat {NTP_CONF}') for network in networks: - network_address = address_from_cidr(network) - network_netmask = netmask_from_cidr(network) - self.assertIn(f'restrict {network_address} mask {network_netmask} nomodify notrap nopeer', config) + self.assertIn(f'allow {network}', config) # Check listen address - self.assertIn('interface ignore wildcard', config) for listen in listen_address: - self.assertIn(f'interface listen {listen}', config) + self.assertIn(f'bindaddress {listen}', config) def test_03_ntp_interface(self): interfaces = ['eth0', 'eth1'] @@ -120,10 +118,24 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Check generated client address configuration - config = read_file(NTP_CONF) - self.assertIn('interface ignore wildcard', config) + # this file must be read with higher permissions + config = cmd(f'sudo cat {NTP_CONF}') for interface in interfaces: - self.assertIn(f'interface listen {interface}', config) + self.assertIn(f'binddevice {interface}', config) + + def test_04_ntp_vrf(self): + vrf_name = 'vyos-mgmt' + + self.cli_set(['vrf', 'name', vrf_name, 'table', '12345']) + self.cli_set(base_path + ['vrf', vrf_name]) + + servers = ['time1.vyos.net', 'time2.vyos.net'] + for server in servers: + self.cli_set(base_path + ['server', server]) + + self.cli_commit() + + self.cli_delete(['vrf', 'name', vrf_name]) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py index 7e16235c1..f67f1710e 100755 --- a/src/conf_mode/flow_accounting_conf.py +++ b/src/conf_mode/flow_accounting_conf.py @@ -38,7 +38,7 @@ airbag.enable() uacctd_conf_path = '/run/pmacct/uacctd.conf' systemd_service = 'uacctd.service' -systemd_override = f'/etc/systemd/system/{systemd_service}.d/override.conf' +systemd_override = f'/run/systemd/system/{systemd_service}.d/override.conf' nftables_nflog_table = 'raw' nftables_nflog_chain = 'VYOS_CT_PREROUTING_HOOK' egress_nftables_nflog_table = 'inet mangle' @@ -192,7 +192,7 @@ def verify(flow_config): raise ConfigError("All sFlow servers must use the same IP protocol") else: sflow_collector_ipver = ip_address(server).version - + # check if vrf is defined for Sflow sflow_vrf = None if 'vrf' in flow_config: diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py index 7cd7ea42e..ce5e63928 100755 --- a/src/conf_mode/https.py +++ b/src/conf_mode/https.py @@ -37,7 +37,7 @@ from vyos import airbag airbag.enable() config_file = '/etc/nginx/sites-available/default' -systemd_override = r'/etc/systemd/system/nginx.service.d/override.conf' +systemd_override = r'/run/systemd/system/nginx.service.d/override.conf' cert_dir = '/etc/ssl/certs' key_dir = '/etc/ssl/private' certbot_dir = vyos.defaults.directories['certbot'] diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py index 0ecb4d736..92cb73aab 100755 --- a/src/conf_mode/ntp.py +++ b/src/conf_mode/ntp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2022 VyOS maintainers and contributors +# Copyright (C) 2018-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -21,26 +21,29 @@ from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_interface_exists from vyos.util import call +from vyos.util import chmod_750 from vyos.util import get_interface_config from vyos.template import render from vyos import ConfigError from vyos import airbag airbag.enable() -config_file = r'/run/ntpd/ntpd.conf' -systemd_override = r'/etc/systemd/system/ntp.service.d/override.conf' +config_file = r'/run/chrony/chrony.conf' +systemd_override = r'/run/systemd/system/chrony.service.d/override.conf' +user_group = '_chrony' def get_config(config=None): if config: conf = config else: conf = Config() - base = ['system', 'ntp'] + base = ['service', 'ntp'] if not conf.exists(base): return None ntp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) ntp['config_file'] = config_file + ntp['user'] = user_group tmp = is_node_changed(conf, base + ['vrf']) if tmp: ntp.update({'restart_required': {}}) @@ -52,7 +55,7 @@ def verify(ntp): if not ntp: return None - if 'allow_clients' in ntp and 'server' not in ntp: + if 'server' not in ntp: raise ConfigError('NTP server not configured') verify_vrf(ntp) @@ -77,13 +80,17 @@ def generate(ntp): if not ntp: return None - render(config_file, 'ntp/ntpd.conf.j2', ntp) - render(systemd_override, 'ntp/override.conf.j2', ntp) + render(config_file, 'chrony/chrony.conf.j2', ntp, user=user_group, group=user_group) + render(systemd_override, 'chrony/override.conf.j2', ntp, user=user_group, group=user_group) + + # Ensure proper permission for chrony command socket + config_dir = os.path.dirname(config_file) + chmod_750(config_dir) return None def apply(ntp): - systemd_service = 'ntp.service' + systemd_service = 'chrony.service' # Reload systemd manager configuration call('systemctl daemon-reload') diff --git a/src/conf_mode/protocols_failover.py b/src/conf_mode/protocols_failover.py index 048ba7a89..85e984afe 100755 --- a/src/conf_mode/protocols_failover.py +++ b/src/conf_mode/protocols_failover.py @@ -31,7 +31,7 @@ airbag.enable() service_name = 'vyos-failover' service_conf = Path(f'/run/{service_name}.conf') -systemd_service = '/etc/systemd/system/vyos-failover.service' +systemd_service = '/run/systemd/system/vyos-failover.service' rt_proto_failover = '/etc/iproute2/rt_protos.d/failover.conf' diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py index ee4eaf59d..ed0a8fba2 100755 --- a/src/conf_mode/protocols_ospfv3.py +++ b/src/conf_mode/protocols_ospfv3.py @@ -117,6 +117,10 @@ def verify(ospfv3): if 'area_type' in area_config: if len(area_config['area_type']) > 1: raise ConfigError(f'Can only configure one area-type for OSPFv3 area "{area}"!') + if 'range' in area_config: + for range, range_config in area_config['range'].items(): + if {'not_advertise', 'advertise'} <= range_config.keys(): + raise ConfigError(f'"not-advertise" and "advertise" for "range {range}" cannot be both configured at the same time!') if 'interface' in ospfv3: for interface, interface_config in ospfv3['interface'].items(): diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py index ee4fe42ab..60eff6543 100755 --- a/src/conf_mode/service_console-server.py +++ b/src/conf_mode/service_console-server.py @@ -27,7 +27,7 @@ from vyos.xml import defaults from vyos import ConfigError config_file = '/run/conserver/conserver.cf' -dropbear_systemd_file = '/etc/systemd/system/dropbear@{port}.service.d/override.conf' +dropbear_systemd_file = '/run/systemd/system/dropbear@{port}.service.d/override.conf' def get_config(config=None): if config: diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py index aafece47a..363408679 100755 --- a/src/conf_mode/service_monitoring_telegraf.py +++ b/src/conf_mode/service_monitoring_telegraf.py @@ -38,7 +38,7 @@ cache_dir = f'/etc/telegraf/.cache' config_telegraf = f'/run/telegraf/telegraf.conf' custom_scripts_dir = '/etc/telegraf/custom_scripts' syslog_telegraf = '/etc/rsyslog.d/50-telegraf.conf' -systemd_override = '/etc/systemd/system/telegraf.service.d/10-override.conf' +systemd_override = '/run/systemd/system/telegraf.service.d/10-override.conf' def get_nft_filter_chains(): """ Get nft chains for table filter """ diff --git a/src/conf_mode/service_sla.py b/src/conf_mode/service_sla.py index e7c3ca59c..b1e22f37b 100755 --- a/src/conf_mode/service_sla.py +++ b/src/conf_mode/service_sla.py @@ -27,15 +27,13 @@ from vyos import ConfigError from vyos import airbag airbag.enable() - owamp_config_dir = '/etc/owamp-server' owamp_config_file = f'{owamp_config_dir}/owamp-server.conf' -systemd_override_owamp = r'/etc/systemd/system/owamp-server.d/20-override.conf' +systemd_override_owamp = r'/run/systemd/system/owamp-server.d/20-override.conf' twamp_config_dir = '/etc/twamp-server' twamp_config_file = f'{twamp_config_dir}/twamp-server.conf' -systemd_override_twamp = r'/etc/systemd/system/twamp-server.d/20-override.conf' - +systemd_override_twamp = r'/run/systemd/system/twamp-server.d/20-override.conf' def get_config(config=None): if config: diff --git a/src/conf_mode/service_webproxy.py b/src/conf_mode/service_webproxy.py index 41a1deaa3..658e496a6 100755 --- a/src/conf_mode/service_webproxy.py +++ b/src/conf_mode/service_webproxy.py @@ -246,7 +246,7 @@ def apply(proxy): if os.path.exists(squidguard_db_dir): chmod_755(squidguard_db_dir) - call('systemctl restart squid.service') + call('systemctl reload-or-restart squid.service') return None diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index 5cd24db32..914ec245c 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -40,7 +40,7 @@ config_file_client = r'/etc/snmp/snmp.conf' config_file_daemon = r'/etc/snmp/snmpd.conf' config_file_access = r'/usr/share/snmp/snmpd.conf' config_file_user = r'/var/lib/snmp/snmpd.conf' -systemd_override = r'/etc/systemd/system/snmpd.service.d/override.conf' +systemd_override = r'/run/systemd/system/snmpd.service.d/override.conf' systemd_service = 'snmpd.service' def get_config(config=None): diff --git a/src/conf_mode/ssh.py b/src/conf_mode/ssh.py index 8746cc701..8de0617af 100755 --- a/src/conf_mode/ssh.py +++ b/src/conf_mode/ssh.py @@ -32,7 +32,7 @@ from vyos import airbag airbag.enable() config_file = r'/run/sshd/sshd_config' -systemd_override = r'/etc/systemd/system/ssh.service.d/override.conf' +systemd_override = r'/run/systemd/system/ssh.service.d/override.conf' sshguard_config_file = '/etc/sshguard/sshguard.conf' sshguard_whitelist = '/etc/sshguard/whitelist' diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index b79e9847a..3af2af4d9 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -95,6 +95,7 @@ def get_config(config=None): del default_values['esp_group'] del default_values['ike_group'] del default_values['remote_access'] + del default_values['site_to_site'] ipsec = dict_merge(default_values, ipsec) if 'esp_group' in ipsec: @@ -143,6 +144,14 @@ def get_config(config=None): ipsec['remote_access']['radius']['server'][server] = dict_merge(default_values, ipsec['remote_access']['radius']['server'][server]) + # XXX: T2665: we can not safely rely on the defaults() when there are + # tagNodes in place, it is better to blend in the defaults manually. + if dict_search('site_to_site.peer', ipsec): + default_values = defaults(base + ['site-to-site', 'peer']) + for peer in ipsec['site_to_site']['peer']: + ipsec['site_to_site']['peer'][peer] = dict_merge(default_values, + ipsec['site_to_site']['peer'][peer]) + ipsec['dhcp_no_address'] = {} ipsec['install_routes'] = 'no' if conf.exists(base + ["options", "disable-route-autoinstall"]) else default_install_routes ipsec['interface_change'] = leaf_node_changed(conf, base + ['interface']) diff --git a/src/migration-scripts/ntp/1-to-2 b/src/migration-scripts/ntp/1-to-2 new file mode 100755 index 000000000..4a701e7e5 --- /dev/null +++ b/src/migration-scripts/ntp/1-to-2 @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2023 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# 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/>. + +# T3008: move from ntpd to chrony and migrate "system ntp" to "service ntp" + +import sys + +from vyos.configtree import ConfigTree + +if (len(sys.argv) < 1): + print("Must specify file name!") + sys.exit(1) + +file_name = sys.argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +base_path = ['system', 'ntp'] +new_base_path = ['service', 'ntp'] +if not config.exists(base_path): + # Nothing to do + sys.exit(0) + +# copy "system ntp" to "service ntp" +config.copy(base_path, new_base_path) +config.delete(base_path) + +# chrony does not support the preempt option, drop it +for server in config.list_nodes(new_base_path + ['server']): + server_base = new_base_path + ['server', server] + if config.exists(server_base + ['preempt']): + config.delete(server_base + ['preempt']) + +# Rename "allow-clients" -> "allow-client" +if config.exists(new_base_path + ['allow-clients']): + config.rename(new_base_path + ['allow-clients'], 'allow-client') + +# By default VyOS 1.3 allowed NTP queries for all networks - in chrony we +# explicitly disable this behavior and clients need to be specified using the +# allow-client CLI option. In order to be fully backwards compatible, we specify +# 0.0.0.0/0 and ::/0 as allow networks if not specified otherwise explicitly. +if not config.exists(new_base_path + ['allow-client']): + config.set(new_base_path + ['allow-client', 'address'], value='0.0.0.0/0', replace=False) + config.set(new_base_path + ['allow-client', 'address'], value='::/0', replace=False) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print("Failed to save the modified config: {}".format(e)) + sys.exit(1) diff --git a/src/op_mode/lldp.py b/src/op_mode/lldp.py new file mode 100755 index 000000000..dc2b1e0b5 --- /dev/null +++ b/src/op_mode/lldp.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# 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/>. + +import jmespath +import json +import sys +import typing + +from tabulate import tabulate + +from vyos.configquery import ConfigTreeQuery +from vyos.util import cmd +from vyos.util import dict_search + +import vyos.opmode +unconf_message = 'LLDP is not configured' +capability_codes = """Capability Codes: R - Router, B - Bridge, W - Wlan r - Repeater, S - Station + D - Docsis, T - Telephone, O - Other + +""" + +def _verify(func): + """Decorator checks if LLDP config exists""" + from functools import wraps + + @wraps(func) + def _wrapper(*args, **kwargs): + config = ConfigTreeQuery() + if not config.exists(['service', 'lldp']): + raise vyos.opmode.UnconfiguredSubsystem(unconf_message) + return func(*args, **kwargs) + return _wrapper + +def _get_raw_data(interface=None, detail=False): + """ + If interface name is not set - get all interfaces + """ + tmp = 'lldpcli -f json show neighbors' + if detail: + tmp += f' details' + if interface: + tmp += f' ports {interface}' + output = cmd(tmp) + data = json.loads(output) + if not data: + return [] + return data + +def _get_formatted_output(raw_data): + data_entries = [] + for neighbor in dict_search('lldp.interface', raw_data): + for local_if, values in neighbor.items(): + tmp = [] + + # Device field + if 'chassis' in values: + tmp.append(next(iter(values['chassis']))) + else: + tmp.append('') + + # Local Port field + tmp.append(local_if) + + # Protocol field + tmp.append(values['via']) + + # Capabilities + cap = '' + capabilities = jmespath.search('chassis.[*][0][0].capability', values) + if capabilities: + for capability in capabilities: + if capability['enabled']: + if capability['type'] == 'Router': + cap += 'R' + if capability['type'] == 'Bridge': + cap += 'B' + if capability['type'] == 'Wlan': + cap += 'W' + if capability['type'] == 'Station': + cap += 'S' + if capability['type'] == 'Repeater': + cap += 'r' + if capability['type'] == 'Telephone': + cap += 'T' + if capability['type'] == 'Docsis': + cap += 'D' + if capability['type'] == 'Other': + cap += 'O' + tmp.append(cap) + + # Remote software platform + platform = jmespath.search('chassis.[*][0][0].descr', values) + tmp.append(platform[:37]) + + # Remote interface + interface = jmespath.search('port.descr', values) + if not interface: + interface = jmespath.search('port.id.value', values) + if not interface: + interface = 'Unknown' + tmp.append(interface) + + # Add individual neighbor to output list + data_entries.append(tmp) + + headers = ["Device", "Local Port", "Protocol", "Capability", "Platform", "Remote Port"] + output = tabulate(data_entries, headers, numalign="left") + return capability_codes + output + +@_verify +def show_neighbors(raw: bool, interface: typing.Optional[str], detail: typing.Optional[bool]): + lldp_data = _get_raw_data(interface=interface, detail=detail) + if raw: + return lldp_data + else: + return _get_formatted_output(lldp_data) + +if __name__ == "__main__": + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) diff --git a/src/op_mode/lldp_op.py b/src/op_mode/lldp_op.py deleted file mode 100755 index 17f6bf552..000000000 --- a/src/op_mode/lldp_op.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2019-2020 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/>. - -import argparse -import jinja2 -import json - -from sys import exit -from tabulate import tabulate - -from vyos.util import cmd -from vyos.config import Config - -parser = argparse.ArgumentParser() -parser.add_argument("-a", "--all", action="store_true", help="Show LLDP neighbors on all interfaces") -parser.add_argument("-d", "--detail", action="store_true", help="Show detailes LLDP neighbor information on all interfaces") -parser.add_argument("-i", "--interface", action="store", help="Show LLDP neighbors on specific interface") - -# Please be careful if you edit the template. -lldp_out = """Capability Codes: R - Router, B - Bridge, W - Wlan r - Repeater, S - Station - D - Docsis, T - Telephone, O - Other - -Device ID Local Proto Cap Platform Port ID ---------- ----- ----- --- -------- ------- -{% for neighbor in neighbors %} -{% for local_if, info in neighbor.items() %} -{{ "%-25s" | format(info.chassis) }} {{ "%-9s" | format(local_if) }} {{ "%-6s" | format(info.proto) }} {{ "%-5s" | format(info.capabilities) }} {{ "%-20s" | format(info.platform[:18]) }} {{ info.remote_if }} -{% endfor %} -{% endfor %} -""" - -def get_neighbors(): - return cmd('/usr/sbin/lldpcli -f json show neighbors') - -def parse_data(data, interface): - output = [] - if not isinstance(data, list): - data = [data] - - for neighbor in data: - for local_if, values in neighbor.items(): - if interface is not None and local_if != interface: - continue - cap = '' - for chassis, c_value in values.get('chassis', {}).items(): - # bail out early if no capabilities found - if 'capability' not in c_value: - continue - capabilities = c_value['capability'] - if isinstance(capabilities, dict): - capabilities = [capabilities] - - for capability in capabilities: - if capability['enabled']: - if capability['type'] == 'Router': - cap += 'R' - if capability['type'] == 'Bridge': - cap += 'B' - if capability['type'] == 'Wlan': - cap += 'W' - if capability['type'] == 'Station': - cap += 'S' - if capability['type'] == 'Repeater': - cap += 'r' - if capability['type'] == 'Telephone': - cap += 'T' - if capability['type'] == 'Docsis': - cap += 'D' - if capability['type'] == 'Other': - cap += 'O' - - remote_if = 'Unknown' - if 'descr' in values.get('port', {}): - remote_if = values.get('port', {}).get('descr') - elif 'id' in values.get('port', {}): - remote_if = values.get('port', {}).get('id').get('value', 'Unknown') - - output.append({local_if: {'chassis': chassis, - 'remote_if': remote_if, - 'proto': values.get('via','Unknown'), - 'platform': c_value.get('descr', 'Unknown'), - 'capabilities': cap}}) - - output = {'neighbors': output} - return output - -if __name__ == '__main__': - args = parser.parse_args() - tmp = { 'neighbors' : [] } - - c = Config() - if not c.exists_effective(['service', 'lldp']): - print('Service LLDP is not configured') - exit(0) - - if args.detail: - print(cmd('/usr/sbin/lldpctl -f plain')) - exit(0) - elif args.all or args.interface: - tmp = json.loads(get_neighbors()) - neighbors = dict() - - if 'interface' in tmp.get('lldp'): - neighbors = tmp['lldp']['interface'] - - else: - parser.print_help() - exit(1) - - tmpl = jinja2.Template(lldp_out, trim_blocks=True) - config_text = tmpl.render(parse_data(neighbors, interface=args.interface)) - print(config_text) - - exit(0) diff --git a/src/op_mode/show_ntp.sh b/src/op_mode/show_ntp.sh index e9dd6c5c9..85f8eda15 100755 --- a/src/op_mode/show_ntp.sh +++ b/src/op_mode/show_ntp.sh @@ -1,39 +1,34 @@ #!/bin/sh -basic=0 -info=0 +sourcestats=0 +tracking=0 while [[ "$#" -gt 0 ]]; do case $1 in - --info) info=1 ;; - --basic) basic=1 ;; - --server) server=$2; shift ;; + --sourcestats) sourcestats=1 ;; + --tracking) tracking=1 ;; *) echo "Unknown parameter passed: $1" ;; esac shift done -if ! ps -C ntpd &>/dev/null; then +if ! ps -C chronyd &>/dev/null; then echo NTP daemon disabled exit 1 fi -PID=$(pgrep ntpd) -VRF_NAME=$(ip vrf identify ${PID}) +PID=$(pgrep chronyd | head -n1) +VRF_NAME=$(ip vrf identify ) if [ ! -z ${VRF_NAME} ]; then VRF_CMD="sudo ip vrf exec ${VRF_NAME}" fi -if [ $basic -eq 1 ]; then - $VRF_CMD ntpq -n -c peers -elif [ $info -eq 1 ]; then - echo "=== sysingo ===" - $VRF_CMD ntpq -n -c sysinfo - echo - echo "=== kerninfo ===" - $VRF_CMD ntpq -n -c kerninfo -elif [ ! -z $server ]; then - $VRF_CMD /usr/sbin/ntpdate -q $server +if [ $sourcestats -eq 1 ]; then + $VRF_CMD chronyc sourcestats -v +elif [ $tracking -eq 1 ]; then + $VRF_CMD chronyc tracking -v +else + echo "Unknown option" fi |