mirror of
https://github.com/systemd/systemd.git
synced 2024-11-24 18:53:33 +08:00
wait-online: Add maximum operational state option
This commit is contained in:
parent
8ac7339648
commit
75cd4a5d92
@ -47,16 +47,16 @@
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<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>
|
||||
<term><option>-i</option> <replaceable>INTERFACE</replaceable><optional>:<replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></optional></term>
|
||||
<term><option>--interface=</option><replaceable>INTERFACE</replaceable><optional>:<replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></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. 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. Optionally, required minimum operational state can be
|
||||
specified after a colon <literal>:</literal>. Please see
|
||||
for all specified interfaces to be online. Optionally, required minimum and maximum operational
|
||||
states 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
|
||||
the value from <varname>RequiredForOnline=</varname> in the corresponding
|
||||
@ -74,11 +74,11 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-o</option> <replaceable>OPERSTATE</replaceable></term>
|
||||
<term><option>--operational-state=</option><replaceable>OPERSTATE</replaceable></term>
|
||||
<term><option>-o</option> <replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></term>
|
||||
<term><option>--operational-state=</option><replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></term>
|
||||
|
||||
<listitem><para>Takes an operational state. Please see
|
||||
<citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
<listitem><para>Takes a minimum operational state and an optional maximum operational state.
|
||||
Please see <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.
|
||||
|
@ -206,13 +206,14 @@
|
||||
<varlistentry>
|
||||
<term><varname>RequiredForOnline=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean or operational state. Please see
|
||||
<citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
<para>Takes a boolean or a minimum operational state and an optional maximum operational state.
|
||||
Please see <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
for possible operational states. When <literal>yes</literal>, the network is deemed required when
|
||||
determining whether the system is online when running
|
||||
<command>systemd-networkd-wait-online</command>. When <literal>no</literal>, the network is ignored
|
||||
when checking for online state. When an operational state is set, <literal>yes</literal> is implied,
|
||||
and this controls the operational state required for the network interface to be considered online.
|
||||
when checking for online state. When a minimum operational state and an optional maximum operational
|
||||
state are set, <literal>yes</literal> is implied, and this controls the minimum and maximum
|
||||
operational state required for the network interface to be considered online.
|
||||
Defaults to <literal>yes</literal>.</para>
|
||||
|
||||
<para>The network will be brought up normally in all cases, but in
|
||||
|
@ -56,3 +56,49 @@ static const char* const link_address_state_table[_LINK_ADDRESS_STATE_MAX] = {
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(link_address_state, LinkAddressState);
|
||||
|
||||
int parse_operational_state_range(const char *str, LinkOperationalStateRange *out) {
|
||||
LinkOperationalStateRange range = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
|
||||
_cleanup_free_ const char *min = NULL;
|
||||
const char *p;
|
||||
|
||||
assert(str);
|
||||
assert(out);
|
||||
|
||||
p = strchr(str, ':');
|
||||
if (p) {
|
||||
min = strndup(str, p - str);
|
||||
|
||||
if (!isempty(p + 1)) {
|
||||
range.max = link_operstate_from_string(p + 1);
|
||||
if (range.max < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
} else
|
||||
min = strdup(str);
|
||||
|
||||
if (!min)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!isempty(min)) {
|
||||
range.min = link_operstate_from_string(min);
|
||||
if (range.min < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Fail on empty strings. */
|
||||
if (range.min == _LINK_OPERSTATE_INVALID && range.max == _LINK_OPERSTATE_INVALID)
|
||||
return -EINVAL;
|
||||
|
||||
if (range.min == _LINK_OPERSTATE_INVALID)
|
||||
range.min = LINK_OPERSTATE_OFF;
|
||||
if (range.max == _LINK_OPERSTATE_INVALID)
|
||||
range.max = LINK_OPERSTATE_ROUTABLE;
|
||||
|
||||
if (range.min > range.max)
|
||||
return -EINVAL;
|
||||
|
||||
*out = range;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -47,3 +47,13 @@ LinkCarrierState link_carrier_state_from_string(const char *s) _pure_;
|
||||
|
||||
const char* link_address_state_to_string(LinkAddressState s) _const_;
|
||||
LinkAddressState link_address_state_from_string(const char *s) _pure_;
|
||||
|
||||
typedef struct LinkOperationalStateRange {
|
||||
LinkOperationalState min;
|
||||
LinkOperationalState max;
|
||||
} LinkOperationalStateRange;
|
||||
|
||||
#define LINK_OPERSTATE_RANGE_DEFAULT (LinkOperationalStateRange) { LINK_OPERSTATE_DEGRADED, \
|
||||
LINK_OPERSTATE_ROUTABLE }
|
||||
|
||||
int parse_operational_state_range(const char *str, LinkOperationalStateRange *out);
|
||||
|
@ -3879,8 +3879,14 @@ int link_save(Link *link) {
|
||||
fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
|
||||
yes_no(link->network->required_for_online));
|
||||
|
||||
fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s\n",
|
||||
strempty(link_operstate_to_string(link->network->required_operstate_for_online)));
|
||||
fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s",
|
||||
strempty(link_operstate_to_string(link->network->required_operstate_for_online.min)));
|
||||
|
||||
if (link->network->required_operstate_for_online.max != LINK_OPERSTATE_RANGE_DEFAULT.max)
|
||||
fprintf(f, ":%s",
|
||||
strempty(link_operstate_to_string(link->network->required_operstate_for_online.max)));
|
||||
|
||||
fprintf(f, "\n");
|
||||
|
||||
if (link->dhcp6_client) {
|
||||
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
|
||||
|
@ -375,7 +375,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
.n_ref = 1,
|
||||
|
||||
.required_for_online = true,
|
||||
.required_operstate_for_online = LINK_OPERSTATE_DEGRADED,
|
||||
.required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
|
||||
.dhcp = ADDRESS_FAMILY_NO,
|
||||
.dhcp_critical = -1,
|
||||
.dhcp_use_ntp = true,
|
||||
@ -1300,18 +1300,18 @@ int config_parse_required_for_online(
|
||||
void *userdata) {
|
||||
|
||||
Network *network = data;
|
||||
LinkOperationalState s;
|
||||
LinkOperationalStateRange range;
|
||||
bool required = true;
|
||||
int r;
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
network->required_for_online = true;
|
||||
network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
|
||||
network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = link_operstate_from_string(rvalue);
|
||||
if (s < 0) {
|
||||
r = parse_operational_state_range(rvalue, &range);
|
||||
if (r < 0) {
|
||||
r = parse_boolean(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
@ -1321,11 +1321,11 @@ int config_parse_required_for_online(
|
||||
}
|
||||
|
||||
required = r;
|
||||
s = LINK_OPERSTATE_DEGRADED;
|
||||
range = LINK_OPERSTATE_RANGE_DEFAULT;
|
||||
}
|
||||
|
||||
network->required_for_online = required;
|
||||
network->required_operstate_for_online = s;
|
||||
network->required_operstate_for_online = range;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ struct Network {
|
||||
bool iaid_set;
|
||||
|
||||
bool required_for_online; /* Is this network required to be considered online? */
|
||||
LinkOperationalState required_operstate_for_online;
|
||||
LinkOperationalStateRange required_operstate_for_online;
|
||||
|
||||
LLDPMode lldp_mode; /* LLDP reception */
|
||||
LLDPEmit lldp_emit; /* LLDP transmission */
|
||||
|
@ -36,7 +36,7 @@ int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) {
|
||||
.manager = m,
|
||||
.ifname = TAKE_PTR(n),
|
||||
.ifindex = ifindex,
|
||||
.required_operstate = LINK_OPERSTATE_DEGRADED,
|
||||
.required_operstate = LINK_OPERSTATE_RANGE_DEFAULT,
|
||||
};
|
||||
|
||||
r = hashmap_put(m->links_by_name, l->ifname, l);
|
||||
@ -105,7 +105,6 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
|
||||
|
||||
int link_update_monitor(Link *l) {
|
||||
_cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL;
|
||||
LinkOperationalState s;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(l);
|
||||
@ -121,19 +120,21 @@ int link_update_monitor(Link *l) {
|
||||
r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate);
|
||||
if (r < 0)
|
||||
ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m");
|
||||
else if (isempty(required_operstate))
|
||||
l->required_operstate = LINK_OPERSTATE_RANGE_DEFAULT;
|
||||
else {
|
||||
s = link_operstate_from_string(required_operstate);
|
||||
if (s < 0)
|
||||
r = parse_operational_state_range(required_operstate, &l->required_operstate);
|
||||
if (r < 0)
|
||||
ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to parse required operational state, ignoring: %m");
|
||||
else
|
||||
l->required_operstate = s;
|
||||
}
|
||||
|
||||
r = sd_network_link_get_operational_state(l->ifindex, &operstate);
|
||||
if (r < 0)
|
||||
ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m");
|
||||
else {
|
||||
LinkOperationalState s;
|
||||
|
||||
s = link_operstate_from_string(operstate);
|
||||
if (s < 0)
|
||||
ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),
|
||||
|
@ -17,7 +17,7 @@ struct Link {
|
||||
unsigned flags;
|
||||
|
||||
bool required_for_online;
|
||||
LinkOperationalState required_operstate;
|
||||
LinkOperationalStateRange required_operstate;
|
||||
LinkOperationalState operational_state;
|
||||
char *state;
|
||||
};
|
||||
|
@ -32,7 +32,7 @@ static bool manager_ignore_link(Manager *m, Link *link) {
|
||||
return strv_fnmatch(m->ignore, link->ifname, 0);
|
||||
}
|
||||
|
||||
static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) {
|
||||
static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange s) {
|
||||
/* This returns the following:
|
||||
* -EAGAIN: not processed by udev or networkd
|
||||
* 0: operstate is not enough
|
||||
@ -46,13 +46,18 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) {
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN),
|
||||
"link is being processed by networkd");
|
||||
|
||||
if (s < 0)
|
||||
s = m->required_operstate >= 0 ? m->required_operstate : l->required_operstate;
|
||||
if (s.min < 0)
|
||||
s.min = m->required_operstate.min >= 0 ? m->required_operstate.min
|
||||
: l->required_operstate.min;
|
||||
|
||||
if (l->operational_state < s) {
|
||||
log_link_debug(l, "Operational state '%s' is below '%s'",
|
||||
if (s.max < 0)
|
||||
s.max = m->required_operstate.max >= 0 ? m->required_operstate.max
|
||||
: l->required_operstate.max;
|
||||
|
||||
if (l->operational_state < s.min || l->operational_state > s.max) {
|
||||
log_link_debug(l, "Operational state '%s' is not in range ['%s':'%s']",
|
||||
link_operstate_to_string(l->operational_state),
|
||||
link_operstate_to_string(s));
|
||||
link_operstate_to_string(s.min), link_operstate_to_string(s.max));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -70,7 +75,7 @@ bool manager_configured(Manager *m) {
|
||||
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);
|
||||
LinkOperationalStateRange *range = p;
|
||||
|
||||
l = hashmap_get(m->links_by_name, ifname);
|
||||
if (!l) {
|
||||
@ -80,7 +85,7 @@ bool manager_configured(Manager *m) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (manager_link_is_online(m, l, s) <= 0) {
|
||||
if (manager_link_is_online(m, l, *range) <= 0) {
|
||||
if (!m->any)
|
||||
return false;
|
||||
continue;
|
||||
@ -102,7 +107,9 @@ bool manager_configured(Manager *m) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r = manager_link_is_online(m, l, _LINK_OPERSTATE_INVALID);
|
||||
r = manager_link_is_online(m, l,
|
||||
(LinkOperationalStateRange) { _LINK_OPERSTATE_INVALID,
|
||||
_LINK_OPERSTATE_INVALID });
|
||||
if (r < 0 && !m->any)
|
||||
return false;
|
||||
if (r > 0)
|
||||
@ -289,7 +296,7 @@ static int manager_network_monitor_listen(Manager *m) {
|
||||
}
|
||||
|
||||
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
|
||||
LinkOperationalState required_operstate,
|
||||
LinkOperationalStateRange required_operstate,
|
||||
bool any, usec_t timeout) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
int r;
|
||||
|
@ -20,7 +20,7 @@ struct Manager {
|
||||
Hashmap *interfaces;
|
||||
char **ignore;
|
||||
|
||||
LinkOperationalState required_operstate;
|
||||
LinkOperationalStateRange required_operstate;
|
||||
bool any;
|
||||
|
||||
sd_netlink *rtnl;
|
||||
@ -34,7 +34,7 @@ struct Manager {
|
||||
|
||||
void manager_free(Manager *m);
|
||||
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
|
||||
LinkOperationalState required_operstate,
|
||||
LinkOperationalStateRange required_operstate,
|
||||
bool any, usec_t timeout);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||
|
@ -18,10 +18,10 @@ static bool arg_quiet = false;
|
||||
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 LinkOperationalStateRange arg_required_operstate = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
|
||||
static bool arg_any = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_keyp);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep);
|
||||
|
||||
static int help(void) {
|
||||
@ -37,10 +37,10 @@ static int help(void) {
|
||||
" -h --help Show this help\n"
|
||||
" --version Print version string\n"
|
||||
" -q --quiet Do not show status information\n"
|
||||
" -i --interface=INTERFACE[:OPERSTATE]\n"
|
||||
" -i --interface=INTERFACE[:MIN_OPERSTATE[:MAX_OPERSTATE]]\n"
|
||||
" Block until at least these interfaces have appeared\n"
|
||||
" --ignore=INTERFACE Don't take these interfaces into account\n"
|
||||
" -o --operational-state=OPERSTATE\n"
|
||||
" -o --operational-state=MIN_OPERSTATE[:MAX_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"
|
||||
@ -52,28 +52,28 @@ static int help(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_interface_with_operstate(const char *str) {
|
||||
static int parse_interface_with_operstate_range(const char *str) {
|
||||
_cleanup_free_ char *ifname = NULL;
|
||||
LinkOperationalState s;
|
||||
_cleanup_free_ LinkOperationalStateRange *range;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(str);
|
||||
|
||||
range = new(LinkOperationalStateRange, 1);
|
||||
if (!range)
|
||||
return log_oom();
|
||||
|
||||
p = strchr(str, ':');
|
||||
if (p) {
|
||||
if (isempty(p + 1))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Operational state is empty.");
|
||||
|
||||
s = link_operstate_from_string(p + 1);
|
||||
if (s < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid operational state '%s'", p + 1);
|
||||
r = parse_operational_state_range(p + 1, range);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Invalid operational state range '%s'", p + 1);
|
||||
|
||||
ifname = strndup(optarg, p - optarg);
|
||||
} else {
|
||||
s = _LINK_OPERSTATE_INVALID;
|
||||
range->min = _LINK_OPERSTATE_INVALID;
|
||||
range->max = _LINK_OPERSTATE_INVALID;
|
||||
ifname = strdup(str);
|
||||
}
|
||||
if (!ifname)
|
||||
@ -87,7 +87,7 @@ static int parse_interface_with_operstate(const char *str) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = hashmap_put(arg_interfaces, ifname, INT_TO_PTR(s));
|
||||
r = hashmap_put(arg_interfaces, ifname, TAKE_PTR(range));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to store interface name: %m");
|
||||
if (r == 0)
|
||||
@ -140,7 +140,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return version();
|
||||
|
||||
case 'i':
|
||||
r = parse_interface_with_operstate(optarg);
|
||||
r = parse_interface_with_operstate_range(optarg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
@ -152,14 +152,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'o': {
|
||||
LinkOperationalState s;
|
||||
LinkOperationalStateRange range;
|
||||
|
||||
s = link_operstate_from_string(optarg);
|
||||
if (s < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid operational state '%s'", optarg);
|
||||
r = parse_operational_state_range(optarg, &range);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Invalid operational state range '%s'", optarg);
|
||||
|
||||
arg_required_operstate = range;
|
||||
|
||||
arg_required_operstate = s;
|
||||
break;
|
||||
}
|
||||
case ARG_ANY:
|
||||
|
Loading…
Reference in New Issue
Block a user