summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordermotbradley <dermot_bradley@yahoo.com>2022-11-08 01:34:06 +0000
committerGitHub <noreply@github.com>2022-11-07 19:34:06 -0600
commit56f2d751f226e19cb26d56bed7c524fdb9557713 (patch)
treef68087a9830b491c17fef71c892185a37cf03fe9
parent699b6a05e20253b3666eb51eb77654741aa7c37d (diff)
downloadcloud-init-git-56f2d751f226e19cb26d56bed7c524fdb9557713.tar.gz
udevadm settle should handle non-udev system gracefully (#1806)
Not all Linux systems use udev (and therefore udevadm). Specifically an Alpine Linux system may have either udev (via "eudev" package) or mdev, or mdevd installed. Change the udev_settle function to check for the presence of the udevadm binary before calling it - if it is not present then silently exit the function. This change will enable cloud-init to run on Alpine systems using mdev/mdevd rather than udev.
-rw-r--r--cloudinit/util.py4
-rw-r--r--tests/unittests/test_util.py35
2 files changed, 29 insertions, 10 deletions
diff --git a/cloudinit/util.py b/cloudinit/util.py
index 1fd2c81b..078ce1c2 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -2934,6 +2934,10 @@ def mount_is_read_write(mount_point):
def udevadm_settle(exists=None, timeout=None):
"""Invoke udevadm settle with optional exists and timeout parameters"""
+ if not subp.which("udevadm"):
+ # a distro, such as Alpine, may not have udev installed if
+ # it relies on a udev alternative such as mdev/mdevd.
+ return
settle_cmd = ["udevadm", "settle"]
if exists:
# skip the settle if the requested path already exists
diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py
index 6dc827c1..0c2735ae 100644
--- a/tests/unittests/test_util.py
+++ b/tests/unittests/test_util.py
@@ -822,46 +822,60 @@ class TestBlkid(CiTestCase):
)
+@mock.patch("cloudinit.subp.which")
@mock.patch("cloudinit.subp.subp")
class TestUdevadmSettle(CiTestCase):
- def test_with_no_params(self, m_subp):
+ def test_with_no_params(self, m_which, m_subp):
"""called with no parameters."""
+ m_which.side_effect = lambda m: m in ("udevadm",)
util.udevadm_settle()
m_subp.called_once_with(mock.call(["udevadm", "settle"]))
- def test_with_exists_and_not_exists(self, m_subp):
+ def test_udevadm_not_present(self, m_which, m_subp):
+ """where udevadm program does not exist should not invoke subp."""
+ m_which.side_effect = lambda m: m in ("",)
+ util.udevadm_settle()
+ m_subp.called_once_with(["which", "udevadm"])
+
+ def test_with_exists_and_not_exists(self, m_which, m_subp):
"""with exists=file where file does not exist should invoke subp."""
+ m_which.side_effect = lambda m: m in ("udevadm",)
mydev = self.tmp_path("mydev")
util.udevadm_settle(exists=mydev)
m_subp.called_once_with(
["udevadm", "settle", "--exit-if-exists=%s" % mydev]
)
- def test_with_exists_and_file_exists(self, m_subp):
- """with exists=file where file does exist should not invoke subp."""
+ def test_with_exists_and_file_exists(self, m_which, m_subp):
+ """with exists=file where file does exist should only invoke subp
+ once for 'which' call."""
+ m_which.side_effect = lambda m: m in ("udevadm",)
mydev = self.tmp_path("mydev")
util.write_file(mydev, "foo\n")
util.udevadm_settle(exists=mydev)
- self.assertIsNone(m_subp.call_args)
+ m_subp.called_once_with(["which", "udevadm"])
- def test_with_timeout_int(self, m_subp):
+ def test_with_timeout_int(self, m_which, m_subp):
"""timeout can be an integer."""
+ m_which.side_effect = lambda m: m in ("udevadm",)
timeout = 9
util.udevadm_settle(timeout=timeout)
m_subp.called_once_with(
["udevadm", "settle", "--timeout=%s" % timeout]
)
- def test_with_timeout_string(self, m_subp):
+ def test_with_timeout_string(self, m_which, m_subp):
"""timeout can be a string."""
+ m_which.side_effect = lambda m: m in ("udevadm",)
timeout = "555"
util.udevadm_settle(timeout=timeout)
- m_subp.assert_called_once_with(
+ m_subp.called_once_with(
["udevadm", "settle", "--timeout=%s" % timeout]
)
- def test_with_exists_and_timeout(self, m_subp):
+ def test_with_exists_and_timeout(self, m_which, m_subp):
"""test call with both exists and timeout."""
+ m_which.side_effect = lambda m: m in ("udevadm",)
mydev = self.tmp_path("mydev")
timeout = "3"
util.udevadm_settle(exists=mydev)
@@ -874,7 +888,8 @@ class TestUdevadmSettle(CiTestCase):
]
)
- def test_subp_exception_raises_to_caller(self, m_subp):
+ def test_subp_exception_raises_to_caller(self, m_which, m_subp):
+ m_which.side_effect = lambda m: m in ("udevadm",)
m_subp.side_effect = subp.ProcessExecutionError("BOOM")
self.assertRaises(subp.ProcessExecutionError, util.udevadm_settle)