mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-06 13:17:44 +03:00
Merge pull request #25830 from yuwata/wait-online-unmanaged
wait-online: exit with success when all interfaces are ready or unmanaged
This commit is contained in:
commit
d7301331e8
@ -61,9 +61,11 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
|
||||
assert(l);
|
||||
|
||||
/* This returns the following:
|
||||
* -EAGAIN: not processed by udev or networkd
|
||||
* 0: operstate is not enough
|
||||
* 1: online */
|
||||
* -EAGAIN : not processed by udev
|
||||
* -EBUSY : being processed by networkd
|
||||
* -EADDRNOTAVAIL: requested conditions (operstate and/or addresses) are not satisfied
|
||||
* false : unmanaged
|
||||
* true : online */
|
||||
|
||||
if (!l->state || streq(l->state, "pending"))
|
||||
/* If no state string exists, networkd (and possibly also udevd) has not detected the
|
||||
@ -79,13 +81,13 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
|
||||
/* If the link is in unmanaged state, then ignore the interface unless the interface is
|
||||
* specified in '--interface/-i' option. */
|
||||
if (!link_in_command_line_interfaces(l, m)) {
|
||||
log_link_debug(l, "link is not managed by networkd (yet?).");
|
||||
return 0;
|
||||
log_link_debug(l, "link is not managed by networkd.");
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (!streq(l->state, "configured"))
|
||||
/* If the link is in non-configured state, return negative value here. */
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN),
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EBUSY),
|
||||
"link is being processed by networkd: setup state is %s.",
|
||||
l->state);
|
||||
|
||||
@ -97,84 +99,75 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
|
||||
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.min), link_operstate_to_string(s.max));
|
||||
return 0;
|
||||
}
|
||||
if (l->operational_state < s.min || l->operational_state > s.max)
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
|
||||
"Operational state '%s' is not in range ['%s':'%s']",
|
||||
link_operstate_to_string(l->operational_state),
|
||||
link_operstate_to_string(s.min), link_operstate_to_string(s.max));
|
||||
|
||||
required_family = m->required_family > 0 ? m->required_family : l->required_family;
|
||||
needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
|
||||
needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
|
||||
|
||||
if (s.min < LINK_OPERSTATE_ROUTABLE) {
|
||||
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED) {
|
||||
log_link_debug(l, "No routable or link-local IPv4 address is configured.");
|
||||
return 0;
|
||||
}
|
||||
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED)
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
|
||||
"No routable or link-local IPv4 address is configured.");
|
||||
|
||||
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED) {
|
||||
log_link_debug(l, "No routable or link-local IPv6 address is configured.");
|
||||
return 0;
|
||||
}
|
||||
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED)
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
|
||||
"No routable or link-local IPv6 address is configured.");
|
||||
} else {
|
||||
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE) {
|
||||
log_link_debug(l, "No routable IPv4 address is configured.");
|
||||
return 0;
|
||||
}
|
||||
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE)
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
|
||||
"No routable IPv4 address is configured.");
|
||||
|
||||
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE) {
|
||||
log_link_debug(l, "No routable IPv6 address is configured.");
|
||||
return 0;
|
||||
}
|
||||
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE)
|
||||
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
|
||||
"No routable IPv6 address is configured.");
|
||||
}
|
||||
|
||||
log_link_debug(l, "link is configured by networkd and online.");
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool manager_configured(Manager *m) {
|
||||
bool one_ready = false;
|
||||
const char *ifname;
|
||||
Link *l;
|
||||
int r;
|
||||
|
||||
if (!hashmap_isempty(m->command_line_interfaces_by_name)) {
|
||||
LinkOperationalStateRange *range;
|
||||
const char *ifname;
|
||||
|
||||
/* wait for all the links given on the command line to appear */
|
||||
HASHMAP_FOREACH_KEY(range, ifname, m->command_line_interfaces_by_name) {
|
||||
|
||||
l = hashmap_get(m->links_by_name, ifname);
|
||||
if (!l && range->min == LINK_OPERSTATE_MISSING) {
|
||||
one_ready = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!l) {
|
||||
log_debug("still waiting for %s", ifname);
|
||||
if (!m->any)
|
||||
return false;
|
||||
if (range->min == LINK_OPERSTATE_MISSING) {
|
||||
if (m->any)
|
||||
return true;
|
||||
} else {
|
||||
log_debug("still waiting for %s", ifname);
|
||||
if (!m->any)
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (manager_link_is_online(m, l, *range) <= 0) {
|
||||
if (!m->any)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
one_ready = true;
|
||||
r = manager_link_is_online(m, l, *range);
|
||||
if (r <= 0 && !m->any)
|
||||
return false;
|
||||
if (r > 0 && m->any)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* all interfaces given by the command line are online, or
|
||||
* one of the specified interfaces is online. */
|
||||
return one_ready;
|
||||
/* With '--any' : no interface is ready
|
||||
* Without '--any': all interfaces are ready */
|
||||
return !m->any;
|
||||
}
|
||||
|
||||
/* wait for all links networkd manages to be in admin state 'configured'
|
||||
* and at least one link to gain a carrier */
|
||||
/* wait for all links networkd manages */
|
||||
HASHMAP_FOREACH(l, m->links_by_index) {
|
||||
if (manager_ignore_link(m, l)) {
|
||||
log_link_debug(l, "link is ignored");
|
||||
@ -184,15 +177,15 @@ bool manager_configured(Manager *m) {
|
||||
r = manager_link_is_online(m, l,
|
||||
(LinkOperationalStateRange) { _LINK_OPERSTATE_INVALID,
|
||||
_LINK_OPERSTATE_INVALID });
|
||||
if (r < 0 && !m->any)
|
||||
if (r < 0 && !m->any) /* Unlike the above loop, unmanaged interfaces are ignored here. */
|
||||
return false;
|
||||
if (r > 0)
|
||||
/* we wait for at least one link to be ready,
|
||||
* regardless of who manages it */
|
||||
one_ready = true;
|
||||
if (r > 0 && m->any)
|
||||
return true;
|
||||
}
|
||||
|
||||
return one_ready;
|
||||
/* With '--any' : no interface is ready
|
||||
* Without '--any': all interfaces are ready or unmanaged */
|
||||
return !m->any;
|
||||
}
|
||||
|
||||
static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
|
||||
|
@ -854,7 +854,7 @@ class Utilities():
|
||||
This returns if the links reached the requested operstate/setup_state; otherwise it
|
||||
raises CalledProcessError or fails test assertion.
|
||||
"""
|
||||
args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
|
||||
args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate] + [f'--ignore={link}' for link in protected_links]
|
||||
if bool_any:
|
||||
args += ['--any']
|
||||
if ipv4:
|
||||
@ -1136,6 +1136,36 @@ class NetworkdMatchTests(unittest.TestCase, Utilities):
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98-2', env=env)
|
||||
self.assertIn('Network File: /run/systemd/network/12-dummy-match-altname.network', output)
|
||||
|
||||
def test_match_udev_property(self):
|
||||
copy_network_unit('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
|
||||
start_networkd()
|
||||
self.wait_online(['dummy98:routable'])
|
||||
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
|
||||
|
||||
class WaitOnlineTests(unittest.TestCase, Utilities):
|
||||
|
||||
def setUp(self):
|
||||
setup_common()
|
||||
|
||||
def tearDown(self):
|
||||
tear_down_common()
|
||||
|
||||
def test_wait_online_all_unmanaged(self):
|
||||
start_networkd()
|
||||
self.wait_online([])
|
||||
|
||||
def test_wait_online_any(self):
|
||||
copy_network_unit('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
|
||||
start_networkd()
|
||||
|
||||
self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
|
||||
|
||||
self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
|
||||
self.wait_operstate('test1', 'degraded')
|
||||
|
||||
class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
|
||||
def setUp(self):
|
||||
@ -1154,24 +1184,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertRegex(output, '00:50:56:c0:00:28')
|
||||
|
||||
def test_match_udev_property(self):
|
||||
copy_network_unit('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
|
||||
start_networkd()
|
||||
self.wait_online(['dummy98:routable'])
|
||||
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
|
||||
|
||||
def test_wait_online_any(self):
|
||||
copy_network_unit('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
|
||||
start_networkd()
|
||||
|
||||
self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
|
||||
|
||||
self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
|
||||
self.wait_operstate('test1', 'degraded')
|
||||
|
||||
@expectedFailureIfModuleIsNotAvailable('bareudp')
|
||||
def test_bareudp(self):
|
||||
copy_network_unit('25-bareudp.netdev', '26-netdev-link-local-addressing-yes.network')
|
||||
|
Loading…
Reference in New Issue
Block a user