chiark / gitweb /
networkd-wait-online: add timeout
authorTom Gundersen <teg@jklm.no>
Sun, 1 Feb 2015 20:04:35 +0000 (21:04 +0100)
committerTom Gundersen <teg@jklm.no>
Mon, 2 Feb 2015 10:57:52 +0000 (11:57 +0100)
Default to timing out after 120 seconds without a network connection. Setting a
timeout of 0 disables the timeout.

TODO
man/systemd-networkd-wait-online.service.xml
src/network/networkd-wait-online-manager.c
src/network/networkd-wait-online.c
src/network/networkd-wait-online.h

diff --git a/TODO b/TODO
index 1d9ca394c957ec67ab98c5cae7016f9b611505b5..c7b530b25672ebe32c22e3072ef1b989c69f2252 100644 (file)
--- a/TODO
+++ b/TODO
@@ -34,8 +34,6 @@ External:
 
 Features:
 
-* network-wait-online should have a configurable timeout, maybe as --timeout-usec=
-
 * The udev blkid built-in should expose a property that reflects
   whether media was sensed in USB CF/SD card readers. This should then
   be used to control SYSTEMD_READY=1/0 so that USB card readers aren't
@@ -156,8 +154,6 @@ Features:
 
 * timesyncd + resolved: add ugly bus calls to set NTP and DNS servers per-interface, for usage by NM
 
-* networkd-wait-online really should have a timeout by default
-
 * add infrastructure to allocate dynamic/transient users and UID ranges, for use in user-namespaced containers, per-seat gdm login screens and gdm guest sessions
 
 * machined: add an API so that libvirt-lxc can inform us about network interfaces being removed or added to an existing machine
index 0cb41a3b6aae8be181b8938da213640df998bb79..4f039fedc7b18487df472ec9e7f514c9c5dcbf7f 100644 (file)
                                 more than once to ignore multiple network interfaces.
                                 </para></listitem>
                         </varlistentry>
+                        <varlistentry>
+                                <term><option>--timeout=</option></term>
+                                <listitem><para>Fail the service if the network is not
+                                online by the time the timeout elapses. A timeout of 0
+                                disables the timeout. Defaults to 120 seconds.
+                                </para></listitem>
+                        </varlistentry>
                 </variablelist>
         </refsect1>
 
index d1273725f075c835c9765d0681d6717f0eaf8b7a..cafe110e50dabdb305f8881c9c70eb4fda746ce6 100644 (file)
@@ -31,6 +31,7 @@
 #include "networkd-wait-online.h"
 
 #include "util.h"
+#include "time-util.h"
 
 bool manager_ignore_link(Manager *m, Link *link) {
         char **ignore;
@@ -262,7 +263,7 @@ static int manager_network_monitor_listen(Manager *m) {
         return 0;
 }
 
-int manager_new(Manager **ret, char **interfaces, char **ignore) {
+int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
 
@@ -282,6 +283,16 @@ int manager_new(Manager **ret, char **interfaces, char **ignore) {
         sd_event_add_signal(m->event, NULL, SIGTERM, NULL,  NULL);
         sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
 
+        if (timeout > 0) {
+                usec_t usec;
+
+                usec = now(clock_boottime_or_monotonic()) + timeout;
+
+                r = sd_event_add_time(m->event, NULL, clock_boottime_or_monotonic(), usec, 0, NULL, INT_TO_PTR(-ETIMEDOUT));
+                if (r < 0)
+                        return r;
+        }
+
         sd_event_set_watchdog(m->event, true);
 
         r = manager_network_monitor_listen(m);
index 826ab929cc5bb5af17d9ab4e9d505461e436f58d..f0ca6def874989c67608aada33373086851b3deb 100644 (file)
@@ -28,6 +28,7 @@
 #include "build.h"
 
 static bool arg_quiet = false;
+static usec_t arg_timeout = 120 * USEC_PER_SEC;
 static char **arg_interfaces = NULL;
 static char **arg_ignore = NULL;
 
@@ -39,6 +40,7 @@ static void help(void) {
                "  -q --quiet                Do not show status information\n"
                "  -i --interface=INTERFACE  Block until at least these interfaces have appeared\n"
                "     --ignore=INTERFACE     Don't take these interfaces into account\n"
+               "     --timeout=SECS         Maximum time to wait for network connectivity\n"
                , program_invocation_short_name);
 }
 
@@ -47,6 +49,7 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_IGNORE,
+                ARG_TIMEOUT,
         };
 
         static const struct option options[] = {
@@ -55,10 +58,11 @@ static int parse_argv(int argc, char *argv[]) {
                 { "quiet",           no_argument,       NULL, 'q'         },
                 { "interface",       required_argument, NULL, 'i'         },
                 { "ignore",          required_argument, NULL, ARG_IGNORE  },
+                { "timeout",         required_argument, NULL, ARG_TIMEOUT  },
                 {}
         };
 
-        int c;
+        int c, r;
 
         assert(argc >= 0);
         assert(argv);
@@ -92,6 +96,13 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_TIMEOUT:
+                        r = parse_sec(optarg, &arg_timeout);
+                        if (r < 0)
+                                return r;
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -121,7 +132,7 @@ int main(int argc, char *argv[]) {
 
         assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
 
-        r = manager_new(&m, arg_interfaces, arg_ignore);
+        r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout);
         if (r < 0) {
                 log_error_errno(r, "Could not create manager: %m");
                 goto finish;
@@ -143,10 +154,16 @@ int main(int argc, char *argv[]) {
         }
 
 finish:
-        sd_notify(false, "STATUS=All interfaces configured...");
-
         strv_free(arg_interfaces);
         strv_free(arg_ignore);
 
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        if (r >= 0) {
+                sd_notify(false, "STATUS=All interfaces configured...");
+
+                return EXIT_SUCCESS;
+        } else {
+                sd_notify(false, "STATUS=Failed waiting for network connectivity...");
+
+                return EXIT_FAILURE;
+        }
 }
index eb78647ebd567879b3536f8bb7b80a5e92f058b1..66b865cfe2bf127bf617933ec1d3f309447df332 100644 (file)
@@ -49,7 +49,7 @@ struct Manager {
 };
 
 void manager_free(Manager *m);
-int manager_new(Manager **ret, char **interfaces, char **ignore);
+int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);