summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Falcon <james.falcon@canonical.com>2022-08-15 16:35:13 -0500
committerGitHub <noreply@github.com>2022-08-15 16:35:13 -0500
commit7136109df5a7b3c75dfb05a853fc4485fed25b5f (patch)
tree1e70ee5f80f13805b881b9418acd6a9e689a2d80
parentb2847a105311842fb81a56afb1bc64c1ca56c7f2 (diff)
downloadcloud-init-git-7136109df5a7b3c75dfb05a853fc4485fed25b5f.tar.gz
Workaround net_setup_link race with udev (#1655)
LP: #1983516
-rw-r--r--cloudinit/net/netplan.py27
1 files changed, 21 insertions, 6 deletions
diff --git a/cloudinit/net/netplan.py b/cloudinit/net/netplan.py
index 66ad598f..d63d86d8 100644
--- a/cloudinit/net/netplan.py
+++ b/cloudinit/net/netplan.py
@@ -276,12 +276,27 @@ class Renderer(renderer.Renderer):
LOG.debug("netplan net_setup_link postcmd disabled")
return
setup_lnk = ["udevadm", "test-builtin", "net_setup_link"]
- for cmd in [
- setup_lnk + [SYS_CLASS_NET + iface]
- for iface in get_devicelist()
- if os.path.islink(SYS_CLASS_NET + iface)
- ]:
- subp.subp(cmd, capture=True)
+
+ # It's possible we can race a udev rename and attempt to run
+ # net_setup_link on a device that no longer exists. When this happens,
+ # we don't know what the device was renamed to, so re-gather the
+ # entire list of devices and try again.
+ last_exception = Exception
+ for _ in range(5):
+ try:
+ for iface in get_devicelist():
+ if os.path.islink(SYS_CLASS_NET + iface):
+ subp.subp(
+ setup_lnk + [SYS_CLASS_NET + iface], capture=True
+ )
+ break
+ except subp.ProcessExecutionError as e:
+ last_exception = e
+ else:
+ raise RuntimeError(
+ "'udevadm test-builtin net_setup_link' unable to run "
+ "successfully for all devices."
+ ) from last_exception
def _render_content(self, network_state: NetworkState):