5efb123ede
hld [#1296](https://github.com/sonic-net/SONiC/pull/1296) closes [#1254](https://github.com/sonic-net/SONiC/issues/1254) depends-on [#60](https://github.com/sonic-net/sonic-host-services/pull/60), [#781](https://github.com/sonic-net/sonic-swss-common/pull/781), [#2835](https://github.com/sonic-net/sonic-utilities/pull/2835), [#10749](https://github.com/sonic-net/sonic-mgmt/pull/10749) #### Why I did it To cover the next AIs: * Configure NTP global parameters * Add/remove new NTP servers * Change the configuration for NTP servers * Show NTP status * Show NTP configuration ### How I did it * Add YANG model for a new configuration * Extend configuration templates to support new knobs ### Description for the changelog * Add ability to configure NTP global parameters such as authentication, dhcp, admin state * Change the configuration for NTP servers * Add an ability to show NTP configuration #### Link to config_db schema for YANG module changes [NTP configuration](https://github.com/sonic-net/sonic-buildimage/blob/master/src/sonic-yang-models/doc/Configuration.md#ntp-and-syslog-servers)
158 lines
5.7 KiB
Django/Jinja
158 lines
5.7 KiB
Django/Jinja
###############################################################################
|
|
# This file was AUTOMATICALLY GENERATED. DO NOT MODIFY.
|
|
# Controlled by ntp-config.service
|
|
###############################################################################
|
|
|
|
# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help
|
|
|
|
# To avoid ntpd from panic and exit if the drift between new time and
|
|
# current system time is large.
|
|
tinker panic 0
|
|
|
|
driftfile /var/lib/ntpsec/ntp.drift
|
|
leapfile /usr/share/zoneinfo/leap-seconds.list
|
|
|
|
{# Getting NTP global configuration -#}
|
|
{% set global = (NTP | d({})).get('global', {}) -%}
|
|
|
|
{# Adding NTP servers. We need to know if we have some pools, to set proper
|
|
config -#}
|
|
{% set ns = namespace(is_pools=false) %}
|
|
{% for server in NTP_SERVER if NTP_SERVER[server].admin_state != 'disabled' and
|
|
NTP_SERVER[server].resolve_as and
|
|
NTP_SERVER[server].association_type -%}
|
|
{% set config = NTP_SERVER[server] -%}
|
|
{# Server options -#}
|
|
{% set soptions = '' -%}
|
|
{# Server access control options -#}
|
|
{% set aoptions = '' -%}
|
|
|
|
{# Authentication key -#}
|
|
{% if global.authentication == 'enabled' -%}
|
|
{% if config.key -%}
|
|
{% set soptions = soptions ~ ' key ' ~ config.key -%}
|
|
{% endif -%}
|
|
{% endif -%}
|
|
|
|
{# Aggressive polling -#}
|
|
{% if config.iburst -%}
|
|
{% set soptions = soptions ~ ' iburst' -%}
|
|
{% endif -%}
|
|
|
|
{# Protocol version -#}
|
|
{% if config.version -%}
|
|
{% set soptions = soptions ~ ' version ' ~ config.version -%}
|
|
{% endif -%}
|
|
|
|
{# Check if there are any pool configured. BTW it doesn't matter what was
|
|
configured as "resolve_as" for pools. If they were configured with FQDN they
|
|
must remain like that -#}
|
|
{% set config_as = config.resolve_as -%}
|
|
{% if config.association_type == 'pool' -%}
|
|
{% set ns.is_pools = true -%}
|
|
{% set config_as = server -%}
|
|
{% else -%}
|
|
{% set aoptions = aoptions ~ ' nopeer' -%}
|
|
{% endif -%}
|
|
|
|
{{ config.association_type }} {{ config_as }}{{ soptions }}
|
|
{% if global.server_role == 'disabled' %}
|
|
restrict {{ config_as }} kod limited nomodify notrap noquery{{ aoptions }}
|
|
{% endif %}
|
|
|
|
{% endfor -%}
|
|
|
|
{% set trusted_keys_arr = [] -%}
|
|
{% for key in NTP_KEY -%}
|
|
{% set keydata = NTP_KEY[key] -%}
|
|
{% if keydata.trusted == 'yes' -%}
|
|
{% set trusted_keys_arr = trusted_keys_arr.append(key) -%}
|
|
{% endif -%}
|
|
{% endfor %}
|
|
|
|
{% if global.authentication == 'enabled' %}
|
|
keys /etc/ntpsec/ntp.keys
|
|
{% if trusted_keys_arr != [] %}
|
|
trustedkey {{ trusted_keys_arr|join(' ') }}
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
{# listen on source interface if configured, else only listen on MGMT_INTERFACE,
|
|
LOOPBACK_INTERFACE ip when MGMT_INTERFACE is not defined, or eth0 if we don't
|
|
have both of them (default is to listen on all ip addresses) -#}
|
|
interface ignore wildcard
|
|
|
|
{# Set interface to listen on:
|
|
* Set global variable for configured source interface name.
|
|
* Set global boolean to indicate if the ip of the configured source
|
|
interface is configured.
|
|
* If the source interface is configured but no ip on that
|
|
interface, then listen on another interface based on existing logic. -#}
|
|
{%- macro check_ip_on_interface(interface_name, table_name) %}
|
|
{%- set ns = namespace(valid_intf = 'false') %}
|
|
{%- if table_name %}
|
|
{%- for (name, source_prefix) in table_name|pfx_filter %}
|
|
{%- if source_prefix and name == interface_name %}
|
|
{%- set ns.valid_intf = 'true' %}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
{%- endif %}
|
|
{{ ns.valid_intf }}
|
|
{%- endmacro %}
|
|
|
|
{% set ns = namespace(source_intf = "") %}
|
|
{%- set ns = namespace(source_intf_ip = 'false') %}
|
|
{%- if global.src_intf %}
|
|
{%- set ns.source_intf = global.src_intf %}
|
|
{%- if ns.source_intf != "" %}
|
|
{%- if ns.source_intf == "eth0" %}
|
|
{%- set ns.source_intf_ip = 'true' %}
|
|
{%- elif ns.source_intf.startswith('Vlan') %}
|
|
{%- set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, VLAN_INTERFACE) %}
|
|
{%- elif ns.source_intf.startswith('Ethernet') %}
|
|
{%- set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, INTERFACE) %}
|
|
{%- elif ns.source_intf.startswith('PortChannel') %}
|
|
{%- set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, PORTCHANNEL_INTERFACE) %}
|
|
{%- elif ns.source_intf.startswith('Loopback') %}
|
|
{%- set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, LOOPBACK_INTERFACE) %}
|
|
{%- endif %}
|
|
{%- endif %}
|
|
{% endif %}
|
|
|
|
{% if ns.source_intf_ip == 'true' %}
|
|
interface listen {{ns.source_intf}}
|
|
{% elif (NTP) and NTP['global']['vrf'] == 'mgmt' %}
|
|
interface listen eth0
|
|
{% elif MGMT_INTERFACE %}
|
|
{% for (mgmt_intf, mgmt_prefix) in MGMT_INTERFACE|pfx_filter %}
|
|
interface listen {{ mgmt_prefix | ip }}
|
|
{% endfor %}
|
|
{% elif LOOPBACK_INTERFACE %}
|
|
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
|
|
{% if prefix | ipv4 and name == 'Loopback0' %}
|
|
interface listen {{ prefix | ip }}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% else %}
|
|
interface listen eth0
|
|
{% endif %}
|
|
interface listen 127.0.0.1
|
|
|
|
{# Access control options -#}
|
|
{% set options = '' -%}
|
|
|
|
{# Disable NTP server functionality. Should stay on when dhcp is enabled -#}
|
|
{# {% if global.server_role == 'disabled' and global.dhcp == 'disabled' -%}
|
|
{% set options = options ~ ' ignore' -%}
|
|
{% endif -%} #}
|
|
|
|
# Access control configuration
|
|
# By default, exchange time with everybody, but don't allow configuration.
|
|
# NTPsec doesn't establish peer associations, and so nopeer has no effect, and
|
|
# has been removed from here
|
|
restrict default kod nomodify noquery limited{{ options }}
|
|
|
|
# Local users may interrogate the ntp server more closely.
|
|
restrict 127.0.0.1
|
|
restrict ::1
|