]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
timedated: add back support for ntp-units.d/
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 21 Jul 2019 13:06:35 +0000 (15:06 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 22 Jul 2019 13:21:20 +0000 (15:21 +0200)
We removed support for foreign services (and ntp-units.d/) in b72ddf0f4.
Support for foreign services was added back in 5d280742, but through an
environment variable.

The problem with the env var approach is that it only works as a mechanism
to select one item, and doesn't work nicely as a mechinism to create a list
of items through drop-ins (because the env var can be easily overridden, but not
extended). Having a list of "ntp providers" is important to be able to reliably disable
all of them when that is requested.

Another problem is that nobody ever bothered to care about our new "standard".
ntp-units.d/ is a nice simple format that works and is already supported by
chrony and ntpd and timedatex. If we were to introduce and ask people to follow
a new standard, there should be some good reason for this. The idea with env
vars has lower functionality, requires systemd-specific syntax. We should just
re-adopt the format that we originally introduced and that seems to work for
everyone, and more on to more interesting problems.

man/systemd-timedated.service.xml
man/timedatectl.xml
src/shared/pretty-print.c
src/timedate/timedated.c

index 3626e8bc51184f9f24d2799e5f40f56cc9be53a4..f981848cb204a3bfd09a065f2fc902a72bbc6c68 100644 (file)
@@ -31,7 +31,7 @@
 
     <para><filename>systemd-timedated</filename> is a system service
     that may be used as a mechanism to change the system clock and
-    timezone, as well as to enable/disable NTP time synchronization.
+    timezone, as well as to enable/disable network time synchronization.
     <filename>systemd-timedated</filename> is automatically activated
     on request and terminates itself when it is unused.</para>
 
   </refsect1>
 
   <refsect1>
-    <title>Environment</title>
-
-    <variablelist class='environment-variables'>
-      <varlistentry>
-        <term><varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname></term>
-
-        <listitem><para>Colon-separated list of unit names of NTP client services.
-        If not set, then
-        <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        is used. See the entries of NTP related commands of
-        <citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-        for details about this.</para>
-
-        <para>Example:
-        <programlisting>SYSTEMD_TIMEDATED_NTP_SERVICES=ntpd.service:chronyd.service:systemd-timesyncd.service</programlisting>
-        </para></listitem>
-      </varlistentry>
-    </variablelist>
+    <title>List of network time synchronization services</title>
+
+    <para><command>systemd-timesyncd</command> will look for files with a <literal>.list</literal> extension
+    in <filename>ntp-units.d/</filename> directories. Each file is parsed as a list of unit names, one per
+    line. Empty lines and lines with comments (<literal>#</literal>) are ignored.  Files are read from
+    <filename>/usr/lib/systemd/ntp-units.d/</filename> and the corresponding directories under
+    <filename>/etc/</filename>, <filename>/run/</filename>, <filename>/usr/local/lib/</filename>. Files in
+    <filename>/etc/</filename> override files with the same name in <filename>/run/</filename>,
+    <filename>/usr/local/lib/</filename>, and <filename>/usr/lib/</filename>. Files in
+    <filename>/run/</filename> override files with the same name under <filename>/usr/</filename>. Packages
+    should install their configuration files in <filename>/usr/lib/</filename> (distribution packages) or
+    <filename>/usr/local/lib/</filename> (local installs).</para>
+
+    <example>
+      <title><filename>ntp-units.d/</filename> entry for <command>systemd-timesyncd</command></title>
+      <programlisting># /usr/lib/systemd/ntp-units.d/80-systemd-timesync.list
+systemd-timesyncd.service
+</programlisting>
+    </example>
+
+    <para>If the environment variable <varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname> is set,
+    <command>systemd-timesyncd</command> will parse the contents of that variable as a colon-separated list
+    of unit names. When set, this variable overrides the file-based list described above.</para>
+
+    <example>
+      <title>An override that specifies that <command>chronyd</command> should be used if available</title>
+      <programlisting>SYSTEMD_TIMEDATED_NTP_SERVICES=chronyd.service:systemd-timesyncd.service</programlisting>
+    </example>
   </refsect1>
+
   <refsect1>
     <title>See Also</title>
     <para>
index 262b9126e7cc3269ee4dfa5fbb6cd70fbc5ca6b4..f797e0cd67c7e33d694440b7e28abbfe37f59ddb 100644 (file)
 
   <refsynopsisdiv>
     <cmdsynopsis>
-      <command>timedatectl <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">COMMAND</arg></command>
+      <command>timedatectl</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <arg choice="req">COMMAND</arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
   <refsect1>
     <title>Description</title>
 
-    <para><command>timedatectl</command> may be used to query and
-    change the system clock and its settings.</para>
+    <para><command>timedatectl</command> may be used to query and change the system clock and its settings,
+    and enable or disable time synchronization services.</para>
 
     <para>Use
     <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     to initialize the system time zone for mounted (but not booted)
     system images.</para>
 
-    <para><command>timedatectl</command> may be used to show the current status of
+    <para><command>timedatectl</command> may be used to show the current status of time synchronization
+    services, for example
     <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
     </para>
 
       <varlistentry>
         <term><command>status</command></term>
 
-        <listitem><para>Show current settings of the system clock and RTC,
-        including whether network time synchronization through
-        <filename>systemd-timesyncd.service</filename> is active. Even if it is
-        inactive, a different service might still synchronize the clock.
-        If no command is specified, this is the implied default.
+        <listitem><para>Show current settings of the system clock and RTC, including whether network time
+        synchronization is active. If no command is specified, this is the implied default.
         </para></listitem>
       </varlistentry>
 
       <varlistentry>
         <term><command>set-ntp [BOOL]</command></term>
 
-        <listitem><para>Takes a boolean argument. Controls whether network time synchronization is active
-        and enabled (if available). If the argument is true, this enables and starts the first existed
-        service listed in the environment variable <varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname>
-        of <filename>systemd-timedated.service</filename>. If the argument is false, then this disables and
-        stops the all services listed in <varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname>.</para></listitem>
+        <listitem><para>Takes a boolean argument. Controls whether network time synchronization is active and
+        enabled (if available). If the argument is true, this enables and starts the first existing network
+        synchronization service. If the argument is false, then this disables and stops the known network
+        synchronization services. The way that the list of services is built is described below.</para>
+        </listitem>
       </varlistentry>
 
     </variablelist>
   <refsect1>
     <title>Exit status</title>
 
-    <para>On success, 0 is returned, a non-zero failure
-    code otherwise.</para>
+    <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
   </refsect1>
 
   <xi:include href="less-variables.xml" />
index c602e036eb55cb3adec11647786147334391d4c9..96e74a758f09229301e42d807a9c896a25138432 100644 (file)
@@ -247,6 +247,11 @@ static int guess_type(const char **name, bool *is_usr, bool *is_collection, cons
         if (path_equal(n, "kernel/install.d"))
                 ext = ".install";
 
+        if (path_equal(n, "systemd/ntp-units.d")) {
+                coll = true;
+                ext = ".list";
+        }
+
         if (PATH_IN_SET(n, "systemd/system-preset", "systemd/user-preset")) {
                 coll = true;
                 ext = ".preset";
index 57bbefc0c10fc9c8ca3a2b03e20826acc748895f..074ba3c0792d07224a23f828c20426d1aa3e97c6 100644 (file)
@@ -15,7 +15,9 @@
 #include "bus-error.h"
 #include "bus-util.h"
 #include "clock-util.h"
+#include "conf-files.h"
 #include "def.h"
+#include "fd-util.h"
 #include "fileio-label.h"
 #include "fileio.h"
 #include "fs-util.h"
@@ -36,6 +38,8 @@
 #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
 #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
 
+#define UNIT_LIST_DIRS (const char* const*) CONF_PATHS_STRV("systemd/ntp-units.d")
+
 typedef struct UnitStatusInfo {
         char *name;
         char *load_state;
@@ -117,20 +121,17 @@ static int context_add_ntp_service(Context *c, const char *s) {
         return 0;
 }
 
-static int context_parse_ntp_services(Context *c) {
+static int context_parse_ntp_services_from_environment(Context *c) {
         const char *env, *p;
         int r;
 
         assert(c);
 
         env = getenv("SYSTEMD_TIMEDATED_NTP_SERVICES");
-        if (!env) {
-                r = context_add_ntp_service(c, "systemd-timesyncd.service");
-                if (r < 0)
-                        log_warning_errno(r, "Failed to add NTP service \"systemd-timesyncd.service\", ignoring: %m");
-
+        if (!env)
                 return 0;
-        }
+
+        log_debug("Using list of ntp services from environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES.");
 
         for (p = env;;) {
                 _cleanup_free_ char *word = NULL;
@@ -150,7 +151,62 @@ static int context_parse_ntp_services(Context *c) {
                         log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word);
         }
 
-        return 0;
+        return 1;
+}
+
+static int context_parse_ntp_services_from_disk(Context *c) {
+        _cleanup_strv_free_ char **files = NULL;
+        char **f;
+        int r;
+
+        r = conf_files_list_strv(&files, ".list", NULL, CONF_FILES_FILTER_MASKED, UNIT_LIST_DIRS);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enumerate .list files: %m");
+
+        STRV_FOREACH(f, files) {
+                _cleanup_fclose_ FILE *file = NULL;
+
+                log_debug("Reading file '%s'", *f);
+
+                r = fopen_unlocked(*f, "re", &file);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to open %s, ignoring: %m", *f);
+                        continue;
+                }
+
+                for (;;) {
+                        _cleanup_free_ char *line = NULL;
+                        const char *word;
+
+                        r = read_line(file, LINE_MAX, &line);
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to read %s, ignoring: %m", *f);
+                                continue;
+                        }
+                        if (r == 0)
+                                break;
+
+                        word = strstrip(line);
+                        if (isempty(word) || startswith("#", word))
+                                continue;
+
+                        r = context_add_ntp_service(c, word);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word);
+                }
+        }
+
+        return 1;
+}
+
+static int context_parse_ntp_services(Context *c) {
+        int r;
+
+        r = context_parse_ntp_services_from_environment(c);
+        if (r != 0)
+                return r;
+
+        return context_parse_ntp_services_from_disk(c);
 }
 
 static int context_ntp_service_is_active(Context *c) {