]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
wait-online: add --any option
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 31 Mar 2019 21:43:48 +0000 (06:43 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 1 Apr 2019 18:37:50 +0000 (03:37 +0900)
When this option is specified, wait-online exits with success even
when several interfaces are in configuring state.

Closes #9714.

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

index 3fac8ab9d3893cb52e0be99b803110d5ba99d718..7c82f68fb3203d44ff3cab8ebd6841ad491acef5 100644 (file)
@@ -35,8 +35,9 @@
     configured. By default, it will wait for all links it is aware of
     and which are managed by
     <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-    to be fully configured or failed, and for at least one link to
-    gain a carrier.</para>
+    to be fully configured or failed, and for at least one link to be online. Here, online means that
+    the link's operational state is equal or higher than <literal>degraded</literal>. The threshold
+    can be configured by <option>--operational-state=</option> option.</para>
   </refsect1>
 
   <refsect1>
         <term><option>-i</option> <replaceable>INTERFACE</replaceable><optional>:<replaceable>OPERSTATE</replaceable></optional></term>
         <term><option>--interface=</option><replaceable>INTERFACE</replaceable><optional>:<replaceable>OPERSTATE</replaceable></optional></term>
 
-        <listitem><para>Network interface to wait for before deciding
-        if the system is online. This is useful when a system has
-        several interfaces which will be configured, but a particular
-        one is necessary to access some network resources. This option
-        may be used more than once to wait for multiple network
-        interfaces. When used, all other interfaces are ignored.
-        Optinally, required minimum operational state can be
+        <listitem><para>Network interface to wait for before deciding if the system is online. This
+        is useful when a system has several interfaces which will be configured, but a particular
+        one is necessary to access some network resources. When used, all other interfaces are ignored.
+        This option may be used more than once to wait for multiple network interfaces. When this
+        option is specified multiple times, then <command>systemd-networkd-wait-online</command> waits
+        for all specified interfaces to be online. Optinally, required minimum operational state can be
         specified after a colon <literal>:</literal>. Please see
         <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
         for possible operational states. If the operational state is not specified here, then
         <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
         for possible operational states. If set, the specified value overrides
         <varname>RequiredForOnline=</varname> settings in <filename>.network</filename> files.
-        But this does not override operational states specified in <option>--interface</option> option.
+        But this does not override operational states specified in <option>--interface=</option> option.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--any</option></term>
+
+        <listitem><para>Even if several interfaces are in configuring state,
+        <command>systemd-networkd-wait-online</command> exits with success when at least one interface
+        becomes online. When this option is specified with <option>--interface=</option>, then
+        <command>systemd-networkd-wait-online</command> waits for one of the specified interfaces to be
+        online. This option is useful when some interfaces may not have carrier on boot.
         </para></listitem>
       </varlistentry>
 
index eb551f116aedac50144a062987a45fa1d1633d7b..e1f9a812fbb8c863ffb0f2c3aab44e1bcf4d3f48 100644 (file)
@@ -59,7 +59,7 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) {
         return 1;
 }
 
-bool manager_all_configured(Manager *m) {
+bool manager_configured(Manager *m) {
         bool one_ready = false;
         Iterator i;
         const char *ifname;
@@ -67,24 +67,33 @@ bool manager_all_configured(Manager *m) {
         Link *l;
         int r;
 
-        /* wait for all the links given on the command line to appear */
-        HASHMAP_FOREACH_KEY(p, ifname, m->interfaces, i) {
-                LinkOperationalState s = PTR_TO_INT(p);
+        if (!hashmap_isempty(m->interfaces)) {
+                /* wait for all the links given on the command line to appear */
+                HASHMAP_FOREACH_KEY(p, ifname, m->interfaces, i) {
+                        LinkOperationalState s = PTR_TO_INT(p);
+
+                        l = hashmap_get(m->links_by_name, ifname);
+                        if (!l) {
+                                log_debug("still waiting for %s", ifname);
+                                if (!m->any)
+                                        return false;
+                                continue;
+                        }
+
+                        if (manager_link_is_online(m, l, s) <= 0) {
+                                if (!m->any)
+                                        return false;
+                                continue;
+                        }
 
-                l = hashmap_get(m->links_by_name, ifname);
-                if (!l) {
-                        log_debug("still waiting for %s", ifname);
-                        return false;
+                        one_ready = true;
                 }
 
-                if (manager_link_is_online(m, l, s) <= 0)
-                        return false;
+                /* all interfaces given by the command line are online, or
+                 * one of the specified interfaces is online. */
+                return one_ready;
         }
 
-        if (!hashmap_isempty(m->interfaces))
-                /* all interfaces given by the command line are online. */
-                return true;
-
         /* wait for all links networkd manages to be in admin state 'configured'
          * and at least one link to gain a carrier */
         HASHMAP_FOREACH(l, m->links, i) {
@@ -94,7 +103,7 @@ bool manager_all_configured(Manager *m) {
                 }
 
                 r = manager_link_is_online(m, l, _LINK_OPERSTATE_INVALID);
-                if (r < 0)
+                if (r < 0 && !m->any)
                         return false;
                 if (r > 0)
                         /* we wait for at least one link to be ready,
@@ -180,7 +189,7 @@ static int on_rtnl_event(sd_netlink *rtnl, sd_netlink_message *mm, void *userdat
         if (r < 0)
                 return r;
 
-        if (manager_all_configured(m))
+        if (manager_configured(m))
                 sd_event_exit(m->event, 0);
 
         return 1;
@@ -248,7 +257,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
                         log_link_warning_errno(l, r, "Failed to update monitor information: %m");
         }
 
-        if (manager_all_configured(m))
+        if (manager_configured(m))
                 sd_event_exit(m->event, 0);
 
         return 0;
@@ -280,7 +289,8 @@ static int manager_network_monitor_listen(Manager *m) {
 }
 
 int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
-                LinkOperationalState required_operstate, usec_t timeout) {
+                LinkOperationalState required_operstate,
+                bool any, usec_t timeout) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
 
@@ -294,6 +304,7 @@ int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
                 .interfaces = interfaces,
                 .ignore = ignore,
                 .required_operstate = required_operstate,
+                .any = any,
         };
 
         r = sd_event_default(&m->event);
index e559dd168de4529bc8d4cd8f054d49f7b7af3f43..dd7d847dd385636e4929c46dfe07091c21041fe0 100644 (file)
@@ -21,6 +21,7 @@ struct Manager {
         char **ignore;
 
         LinkOperationalState required_operstate;
+        bool any;
 
         sd_netlink *rtnl;
         sd_event_source *rtnl_event_source;
@@ -33,8 +34,9 @@ struct Manager {
 
 void manager_free(Manager *m);
 int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
-                LinkOperationalState required_operstate, usec_t timeout);
+                LinkOperationalState required_operstate,
+                bool any, usec_t timeout);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 
-bool manager_all_configured(Manager *m);
+bool manager_configured(Manager *m);
index fd7a48d81dc7e37ada56a233e47d3ac3641fa1d0..4ce2ac31b2d60ae6f2506d27dc58645e66cd633b 100644 (file)
@@ -19,6 +19,7 @@ static usec_t arg_timeout = 120 * USEC_PER_SEC;
 static Hashmap *arg_interfaces = NULL;
 static char **arg_ignore = NULL;
 static LinkOperationalState arg_required_operstate = _LINK_OPERSTATE_INVALID;
+static bool arg_any = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_keyp);
 STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep);
@@ -41,6 +42,7 @@ static int help(void) {
                "     --ignore=INTERFACE     Don't take these interfaces into account\n"
                "  -o --operational-state=OPERSTATE\n"
                "                            Required operational state\n"
+               "     --any                  Wait until at least one of the interfaces is online\n"
                "     --timeout=SECS         Maximum time to wait for network connectivity\n"
                "\nSee the %s for details.\n"
                , program_invocation_short_name
@@ -101,6 +103,7 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_IGNORE,
+                ARG_ANY,
                 ARG_TIMEOUT,
         };
 
@@ -111,6 +114,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "interface",         required_argument, NULL, 'i'         },
                 { "ignore",            required_argument, NULL, ARG_IGNORE  },
                 { "operational-state", required_argument, NULL, 'o'         },
+                { "any",               no_argument,       NULL, ARG_ANY     },
                 { "timeout",           required_argument, NULL, ARG_TIMEOUT },
                 {}
         };
@@ -158,6 +162,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_required_operstate = s;
                         break;
                 }
+                case ARG_ANY:
+                        arg_any = true;
+                        break;
+
                 case ARG_TIMEOUT:
                         r = parse_sec(optarg, &arg_timeout);
                         if (r < 0)
@@ -192,11 +200,11 @@ static int run(int argc, char *argv[]) {
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
 
-        r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_timeout);
+        r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_any, arg_timeout);
         if (r < 0)
                 return log_error_errno(r, "Could not create manager: %m");
 
-        if (manager_all_configured(m))
+        if (manager_configured(m))
                 goto success;
 
         notify_message = notify_start("READY=1\n"