summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Watkins <oddbloke@ubuntu.com>2020-10-20 17:13:37 -0400
committerGitHub <noreply@github.com>2020-10-20 15:13:37 -0600
commit5f8a2bbc5f26c7abafbc9bd3d1b1b655ffdcc1ae (patch)
treedd1f2283049c257cae78f7fcb8d68276a77442b7
parent468aede1384a5ba25c11a27db4e3e4b3f7b8e8b2 (diff)
downloadcloud-init-git-5f8a2bbc5f26c7abafbc9bd3d1b1b655ffdcc1ae.tar.gz
cc_mounts: correctly fallback to dd if fallocate fails (#585)
`create_swap()` was previously catching and not re-raising the ProcessExecutionError that indicated swap creation failure; this meant that the fallback logic could never be triggered. This commit adds the required re-raise (as well as removing a duplicated log message). LP: #1897099
-rw-r--r--cloudinit/config/cc_mounts.py8
-rw-r--r--cloudinit/config/tests/test_mounts.py33
2 files changed, 37 insertions, 4 deletions
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
index 54f2f878..c22d1698 100644
--- a/cloudinit/config/cc_mounts.py
+++ b/cloudinit/config/cc_mounts.py
@@ -255,8 +255,9 @@ def create_swapfile(fname: str, size: str) -> None:
try:
subp.subp(cmd, capture=True)
except subp.ProcessExecutionError as e:
- LOG.warning(errmsg, fname, size, method, e)
+ LOG.info(errmsg, fname, size, method, e)
util.del_file(fname)
+ raise
swap_dir = os.path.dirname(fname)
util.ensure_dir(swap_dir)
@@ -269,9 +270,8 @@ def create_swapfile(fname: str, size: str) -> None:
else:
try:
create_swap(fname, size, "fallocate")
- except subp.ProcessExecutionError as e:
- LOG.warning(errmsg, fname, size, "dd", e)
- LOG.warning("Will attempt with dd.")
+ except subp.ProcessExecutionError:
+ LOG.info("fallocate swap creation failed, will attempt with dd")
create_swap(fname, size, "dd")
if os.path.exists(fname):
diff --git a/cloudinit/config/tests/test_mounts.py b/cloudinit/config/tests/test_mounts.py
index 764a33e3..56510fd6 100644
--- a/cloudinit/config/tests/test_mounts.py
+++ b/cloudinit/config/tests/test_mounts.py
@@ -4,6 +4,7 @@ from unittest import mock
import pytest
from cloudinit.config.cc_mounts import create_swapfile
+from cloudinit.subp import ProcessExecutionError
M_PATH = 'cloudinit.config.cc_mounts.'
@@ -26,3 +27,35 @@ class TestCreateSwapfile:
create_swapfile(fname, '')
assert mock.call(['mkswap', fname]) in m_subp.call_args_list
+
+ @mock.patch(M_PATH + "util.get_mount_info")
+ @mock.patch(M_PATH + "subp.subp")
+ def test_fallback_from_fallocate_to_dd(
+ self, m_subp, m_get_mount_info, caplog, tmpdir
+ ):
+ swap_file = tmpdir.join("swap-file")
+ fname = str(swap_file)
+
+ def subp_side_effect(cmd, *args, **kwargs):
+ # Mock fallocate failing, to initiate fallback
+ if cmd[0] == "fallocate":
+ raise ProcessExecutionError()
+
+ m_subp.side_effect = subp_side_effect
+ # Use ext4 so both fallocate and dd are valid swap creation methods
+ m_get_mount_info.return_value = (mock.ANY, "ext4")
+
+ create_swapfile(fname, "")
+
+ cmds = [args[0][0] for args, _kwargs in m_subp.call_args_list]
+ assert "fallocate" in cmds, "fallocate was not called"
+ assert "dd" in cmds, "fallocate failure did not fallback to dd"
+
+ assert cmds.index("dd") > cmds.index(
+ "fallocate"
+ ), "dd ran before fallocate"
+
+ assert mock.call(["mkswap", fname]) in m_subp.call_args_list
+
+ msg = "fallocate swap creation failed, will attempt with dd"
+ assert msg in caplog.text