[PATCH 1/2] examples: upstream chrony.helper script |
[ Thread Index |
Date Index
| More chrony.tuxfamily.org/chrony-dev Archives
]
- Subject: [PATCH 1/2] examples: upstream chrony.helper script
- From: Robert Fairley <rfairley@xxxxxxxxxx>
- Date: Sat, 23 May 2020 02:10:38 -0400
Add an example chrony.helper file, which was initially copied from
the downstream Fedora downstream package, with distro-specific parts
taken out. Overall the following changes are made from the downstream
version:
* Remove use of `/etc/sysconfig`, which is specific to
Fedora/RHEL.
* Make the paths in variables such as chrony_conf and
helper_dir configurable through markers @CHRONY_CONF@ and
@CHRONY_HELPER_DIR@. Values used here may vary across
distributions, and should be set by downstream packages.
* Introduce the server_dir variable, where `chrony.servers.*` files
are placed, so that a common marker @CHRONY_SERVER_DIR@ between the
helper script and the NetworkManager dispatch script can be used.
* Remove dhclient identifiers and commands.
---
examples/chrony.helper.in | 263 ++++++++++++++++++++++++++++++++++++++
1 file changed, 263 insertions(+)
create mode 100644 examples/chrony.helper.in
diff --git a/examples/chrony.helper.in b/examples/chrony.helper.in
new file mode 100644
index 0000000..b743a08
--- /dev/null
+++ b/examples/chrony.helper.in
@@ -0,0 +1,263 @@
+#!/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=@CHRONYC@
+chrony_conf=@CHRONY_CONF@
+chrony_service=@CHRONY_SERVICE@
+helper_dir=@CHRONY_HELPER_DIR@
+server_dir=@CHRONY_SERVER_DIR@
+
+dhcp_servers_files="${server_dir}/chrony.servers.*"
+added_servers_file=$helper_dir/added_servers
+dnssrv_servers_files="$helper_dir/dnssrv@*"
+dnssrv_timer_prefix=chrony-dnssrv@
+
+chrony_command() {
+ $chronyc -a -n -m "$1"
+}
+
+is_running() {
+ chrony_command "tracking" &> /dev/null
+}
+
+get_servers_files() {
+ echo "$dhcp_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 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)
+ 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 $?
--
2.26.2