switch to sourcedir directive for loading servers from DHCP

Drop the chrony-helper script in favor of the new sourcedir directive.

Modify the dhclient script to save NTP servers from DHCP to
/run/chrony-dhcp/$interface.sources and configure chronyd to (re)load
the sources from files in that directory on start and the "reload
sources" command.

Other functionality of the helper script is dropped with no
replacemement.
This commit is contained in:
Miroslav Lichvar 2020-08-25 15:10:11 +02:00
parent 304dad1ba3
commit 0ecc1e4fe9
4 changed files with 19 additions and 292 deletions

View File

@ -1,11 +0,0 @@
diff -up chrony-3.5/examples/chronyd.service.service-helper chrony-3.5/examples/chronyd.service
--- chrony-3.5/examples/chronyd.service.service-helper 2019-05-10 12:22:57.000000000 +0200
+++ chrony-3.5/examples/chronyd.service 2019-05-14 13:42:38.069516800 +0200
@@ -10,6 +10,7 @@ Type=forking
PIDFile=/run/chrony/chronyd.pid
EnvironmentFile=-/etc/sysconfig/chronyd
ExecStart=/usr/sbin/chronyd $OPTIONS
+ExecStartPost=/usr/libexec/chrony-helper update-daemon
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=full

View File

@ -1,20 +1,22 @@
#!/bin/bash
SERVERFILE=$SAVEDIR/chrony.servers.$interface
CHRONY_SOURCEDIR=/run/chrony-dhcp
SERVERFILE=$CHRONY_SOURCEDIR/$interface.sources
chrony_config() {
rm -f "$SERVERFILE"
if [ "$PEERNTP" != "no" ]; then
mkdir -p $CHRONY_SOURCEDIR
for server in $new_ntp_servers; do
echo "$server ${NTPSERVERARGS:-iburst}" >> "$SERVERFILE"
echo "server $server ${NTPSERVERARGS:-iburst}" >> "$SERVERFILE"
done
/usr/libexec/chrony-helper update-daemon || :
/usr/bin/chronyc reload sources > /dev/null 2>&1 || :
fi
}
chrony_restore() {
if [ -f "$SERVERFILE" ]; then
rm -f "$SERVERFILE"
/usr/libexec/chrony-helper update-daemon || :
/usr/bin/chronyc reload sources > /dev/null 2>&1 || :
fi
}

View File

@ -1,265 +0,0 @@
#!/bin/bash
# This script configures running chronyd to use NTP servers obtained from
# DHCP and _ntp._udp DNS SRV records. Files with servers from DHCP are managed
# externally (e.g. by a dhclient script). Files with servers from DNS SRV
# records are updated here using the dig utility. The script can also list
# and set static sources in the chronyd configuration file.
chronyc=/usr/bin/chronyc
chrony_conf=/etc/chrony.conf
chrony_service=chronyd.service
helper_dir=/var/run/chrony-helper
added_servers_file=$helper_dir/added_servers
network_sysconfig_file=/etc/sysconfig/network
dhclient_servers_files="/var/lib/dhclient/chrony.servers.*"
dnssrv_servers_files="$helper_dir/dnssrv@*"
dnssrv_timer_prefix=chrony-dnssrv@
. $network_sysconfig_file &> /dev/null
chrony_command() {
$chronyc -a -n -m "$1"
}
is_running() {
chrony_command "tracking" &> /dev/null
}
get_servers_files() {
[ "$PEERNTP" != "no" ] && echo "$dhclient_servers_files"
echo "$dnssrv_servers_files"
}
is_update_needed() {
for file in $(get_servers_files) $added_servers_file; do
[ -e "$file" ] && return 0
done
return 1
}
update_daemon() {
local all_servers_with_args all_servers added_servers
if ! is_running; then
rm -f $added_servers_file
return 0
fi
all_servers_with_args=$(cat $(get_servers_files) 2> /dev/null)
all_servers=$(
echo "$all_servers_with_args" |
while read -r server serverargs; do
echo "$server"
done | sort -u)
added_servers=$( (
cat $added_servers_file 2> /dev/null
echo "$all_servers_with_args" |
while read -r server serverargs; do
[ -z "$server" ] && continue
chrony_command "add server $server $serverargs" &> /dev/null &&
echo "$server"
done) | sort -u)
comm -23 <(echo -n "$added_servers") <(echo -n "$all_servers") |
while read -r server; do
chrony_command "delete $server" &> /dev/null
done
added_servers=$(comm -12 <(echo -n "$added_servers") <(echo -n "$all_servers"))
if [ -n "$added_servers" ]; then
echo "$added_servers" > $added_servers_file
else
rm -f $added_servers_file
fi
}
get_dnssrv_servers() {
local name=$1 output
if ! command -v dig &> /dev/null; then
echo "Missing dig (DNS lookup utility)" >&2
return 1
fi
output=$(dig "$name" srv +short +ndots=2 +search 2> /dev/null) || return 0
echo "$output" | while read -r _ _ port target; do
server=${target%.}
[ -z "$server" ] && continue
echo "$server port $port ${NTPSERVERARGS:-iburst}"
done
}
check_dnssrv_name() {
local name=$1
if [ -z "$name" ]; then
echo "No DNS SRV name specified" >&2
return 1
fi
if [ "${name:0:9}" != _ntp._udp ]; then
echo "DNS SRV name $name doesn't start with _ntp._udp" >&2
return 1
fi
}
update_dnssrv_servers() {
local name=$1
local srv_file=$helper_dir/dnssrv@$name servers
check_dnssrv_name "$name" || return 1
servers=$(get_dnssrv_servers "$name")
if [ -n "$servers" ]; then
echo "$servers" > "$srv_file"
else
rm -f "$srv_file"
fi
}
set_dnssrv_timer() {
local state=$1 name=$2
local srv_file=$helper_dir/dnssrv@$name servers
local timer
timer=$dnssrv_timer_prefix$(systemd-escape "$name").timer || return 1
check_dnssrv_name "$name" || return 1
if [ "$state" = enable ]; then
systemctl enable "$timer"
systemctl start "$timer"
elif [ "$state" = disable ]; then
systemctl stop "$timer"
systemctl disable "$timer"
rm -f "$srv_file"
fi
}
list_dnssrv_timers() {
systemctl --all --full -t timer list-units | grep "^$dnssrv_timer_prefix" | \
sed "s|^$dnssrv_timer_prefix\(.*\)\.timer.*|\1|" |
while read -r name; do
systemd-escape --unescape "$name"
done
}
prepare_helper_dir() {
mkdir -p $helper_dir
exec 100> $helper_dir/lock
if ! flock -w 20 100; then
echo "Failed to lock $helper_dir" >&2
return 1
fi
}
is_source_line() {
local pattern="^[ \t]*(server|pool|peer|refclock)[ \t]+[^ \t]+"
[[ "$1" =~ $pattern ]]
}
list_static_sources() {
while read -r line; do
if is_source_line "$line"; then
echo "$line"
fi
done < $chrony_conf
}
set_static_sources() {
local new_config tmp_conf
new_config=$(
sources=$(
while read -r line; do
is_source_line "$line" && echo "$line"
done)
while read -r line; do
if ! is_source_line "$line"; then
echo "$line"
continue
fi
tmp_sources=$(
local removed=0
echo "$sources" | while read -r line2; do
if [ "$removed" -ne 0 ] || [ "$line" != "$line2" ]; then
echo "$line2"
else
removed=1
fi
done)
[ "$sources" == "$tmp_sources" ] && continue
sources=$tmp_sources
echo "$line"
done < $chrony_conf
echo "$sources"
)
tmp_conf=${chrony_conf}.tmp
cp -a $chrony_conf $tmp_conf &&
echo "$new_config" > $tmp_conf &&
mv $tmp_conf $chrony_conf || return 1
systemctl try-restart $chrony_service
}
print_help() {
echo "Usage: $0 COMMAND"
echo
echo "Commands:"
echo " update-daemon"
echo " update-dnssrv-servers NAME"
echo " enable-dnssrv NAME"
echo " disable-dnssrv NAME"
echo " list-dnssrv"
echo " list-static-sources"
echo " set-static-sources < sources.list"
echo " is-running"
echo " command CHRONYC-COMMAND"
}
case "$1" in
update-daemon|add-dhclient-servers|remove-dhclient-servers)
is_update_needed || exit 0
prepare_helper_dir && update_daemon
;;
update-dnssrv-servers)
prepare_helper_dir && update_dnssrv_servers "$2" && update_daemon
;;
enable-dnssrv)
set_dnssrv_timer enable "$2"
;;
disable-dnssrv)
set_dnssrv_timer disable "$2" && prepare_helper_dir && update_daemon
;;
list-dnssrv)
list_dnssrv_timers
;;
list-static-sources)
list_static_sources
;;
set-static-sources)
set_static_sources
;;
is-running)
is_running
;;
command|forced-command)
chrony_command "$2"
;;
*)
print_help
exit 2
esac
exit $?

View File

@ -15,16 +15,12 @@ Source0: https://download.tuxfamily.org/chrony/chrony-%{version}%{?prerel
Source1: https://download.tuxfamily.org/chrony/chrony-%{version}%{?prerelease}-tar-gz-asc.txt
Source2: https://chrony.tuxfamily.org/gpgkey-8B1F4A9ADA73D401E3085A0B5FF06F29BA1E013B.asc
Source3: chrony.dhclient
Source4: chrony.helper
Source5: chrony-dnssrv@.service
Source6: chrony-dnssrv@.timer
# simulator for test suite
Source10: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
%{?gitpatch:Patch0: chrony-%{version}%{?prerelease}-%{gitpatch}.patch.gz}
# add NTP servers from DHCP when starting service
Patch2: chrony-service-helper.patch
BuildRequires: libcap-devel libedit-devel nettle-devel pps-tools-devel
%ifarch %{ix86} x86_64 %{arm} aarch64 mipsel mips64el ppc64 ppc64le s390 s390x
BuildRequires: libseccomp-devel
@ -35,9 +31,6 @@ BuildRequires: gcc gcc-c++ bison systemd gnupg2 net-tools
Requires(pre): shadow-utils
%{?systemd_requires}
# required by chrony-helper
Requires: coreutils
# Old NetworkManager expects the dispatcher scripts in a different place
Conflicts: NetworkManager < 1.20
@ -59,7 +52,6 @@ service to other computers in the network.
%{gpgverify} --keyring=%{SOURCE2} --signature=%{SOURCE1} --data=%{SOURCE0}
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
%{?gitpatch:%patch0 -p1}
%patch2 -p1 -b .service-helper
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
@ -70,7 +62,7 @@ md5sum -c <<-EOF | (! grep -v 'OK$')
96999221eeef476bd49fe97b97503126 examples/chrony.keys.example
6a3178c4670de7de393d9365e2793740 examples/chrony.logrotate
8f5a98fcb400a482d355b929d04b5518 examples/chrony.nm-dispatcher.onoffline
b23bcc3bd78e195ca2849459e459f3ed examples/chronyd.service
32c34c995c59fd1c3ad1616d063ae4a0 examples/chronyd.service
EOF
# don't allow packaging without vendor zone
@ -80,9 +72,11 @@ test -n "%{vendorzone}"
# - use our vendor zone (2.*pool.ntp.org names include IPv6 addresses)
# - enable leapsectz to get TAI-UTC offset and leap seconds from tzdata
# - enable keyfile
# - use NTP servers from DHCP
sed -e 's|^\(pool \)\(pool.ntp.org\)|\12.%{vendorzone}\2|' \
-e 's|#\(leapsectz\)|\1|' \
-e 's|#\(keyfile\)|\1|' \
-e 's|^pool.*pool.ntp.org.*|&\n\n# Use NTP servers from DHCP.\nsourcedir /run/chrony-dhcp|' \
< examples/chrony.conf.example2 > chrony.conf
touch -r examples/chrony.conf.example2 chrony.conf
@ -140,8 +134,6 @@ install -m 644 -p examples/chrony-wait.service \
install -m 644 -p %{SOURCE5} $RPM_BUILD_ROOT%{_unitdir}/chrony-dnssrv@.service
install -m 644 -p %{SOURCE6} $RPM_BUILD_ROOT%{_unitdir}/chrony-dnssrv@.timer
install -m 755 -p %{SOURCE4} $RPM_BUILD_ROOT%{_libexecdir}/chrony-helper
cat > $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/chronyd <<EOF
# Command-line options for chronyd
OPTIONS=""
@ -175,6 +167,16 @@ then
fi
# workaround for late reload of unit file (#1614751)
%{_bindir}/systemctl daemon-reload
# migrate from chrony-helper to sourcedir directive
if test -a %{_libexecdir}/chrony-helper; then
grep -qi 'sourcedir /run/chrony-dhcp$' %{_sysconfdir}/chrony.conf 2> /dev/null || \
echo -e '\n# Use NTP servers from DHCP.\nsourcedir /run/chrony-dhcp' >> \
%{_sysconfdir}/chrony.conf
mkdir -p /run/chrony-dhcp
for f in %{_localstatedir}/lib/dhclient/chrony.servers.*; do
sed 's|.*|server &|' < $f > /run/chrony-dhcp/"${f##*servers.}.sources"
done 2> /dev/null
fi
%systemd_post chronyd.service chrony-wait.service
%preun
@ -194,7 +196,6 @@ fi
%{_sysconfdir}/dhcp/dhclient.d/chrony.sh
%{_bindir}/chronyc
%{_sbindir}/chronyd
%{_libexecdir}/chrony-helper
%{_prefix}/lib/NetworkManager
%{_prefix}/lib/systemd/ntp-units.d/*.list
%{_unitdir}/chrony*.service