ceph-devstack 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ceph_devstack/host.py +27 -4
- ceph_devstack/requirements.py +67 -35
- {ceph_devstack-0.1.0.dist-info → ceph_devstack-0.2.1.dist-info}/METADATA +1 -1
- {ceph_devstack-0.1.0.dist-info → ceph_devstack-0.2.1.dist-info}/RECORD +10 -10
- tests/resources/ceph/test_requirements_ceph.py +10 -18
- tests/test_requirements_core.py +137 -143
- {ceph_devstack-0.1.0.dist-info → ceph_devstack-0.2.1.dist-info}/WHEEL +0 -0
- {ceph_devstack-0.1.0.dist-info → ceph_devstack-0.2.1.dist-info}/entry_points.txt +0 -0
- {ceph_devstack-0.1.0.dist-info → ceph_devstack-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {ceph_devstack-0.1.0.dist-info → ceph_devstack-0.2.1.dist-info}/top_level.txt +0 -0
ceph_devstack/host.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import json
|
|
2
3
|
import logging
|
|
3
4
|
import os
|
|
4
5
|
import pathlib
|
|
@@ -72,14 +73,29 @@ class Host:
|
|
|
72
73
|
self._kernel_version = parse_version(raw_version.split("-")[0])
|
|
73
74
|
return self._kernel_version
|
|
74
75
|
|
|
76
|
+
@property
|
|
75
77
|
def os_type(self) -> str:
|
|
76
78
|
if not hasattr(self, "_os_type"):
|
|
77
|
-
proc = self.run(["
|
|
78
|
-
assert proc.
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
proc = self.run(["uname"])
|
|
80
|
+
assert proc.wait() == 0, "uname doesn't work?!"
|
|
81
|
+
if (uname_str := proc.stdout.read().decode().strip().lower()) == "linux":
|
|
82
|
+
proc = self.run(["bash", "-c", ". /etc/os-release && echo $ID"])
|
|
83
|
+
assert proc.stdout is not None
|
|
84
|
+
assert proc.wait() == 0, "is /etc/os-release missing?"
|
|
85
|
+
self._os_type = proc.stdout.read().decode().strip().lower()
|
|
86
|
+
else:
|
|
87
|
+
self._os_type = uname_str
|
|
81
88
|
return self._os_type
|
|
82
89
|
|
|
90
|
+
def package_manager(self) -> str | None:
|
|
91
|
+
if self.os_type in ["centos", "rhel", "alma", "rocky", "fedora"]:
|
|
92
|
+
return "dnf"
|
|
93
|
+
elif self.os_type in ["debian", "ubuntu"]:
|
|
94
|
+
return "apt"
|
|
95
|
+
elif self.os_type == "darwin":
|
|
96
|
+
return "brew"
|
|
97
|
+
raise RuntimeError("Can't determine package manager")
|
|
98
|
+
|
|
83
99
|
async def podman_info(self, force: bool = False) -> Dict:
|
|
84
100
|
if force or not hasattr(self, "_podman_info"):
|
|
85
101
|
proc = await self.arun(["podman", "info"])
|
|
@@ -89,6 +105,13 @@ class Host:
|
|
|
89
105
|
self._podman_info = yaml.safe_load(stdout.decode().strip())
|
|
90
106
|
return self._podman_info
|
|
91
107
|
|
|
108
|
+
async def podman_machine_info(self) -> List[Dict]:
|
|
109
|
+
proc = await self.arun(["podman", "machine", "list", "--format", "json"])
|
|
110
|
+
assert proc.stdout is not None
|
|
111
|
+
await proc.wait()
|
|
112
|
+
stdout = await proc.stdout.read()
|
|
113
|
+
return json.loads(stdout)
|
|
114
|
+
|
|
92
115
|
async def selinux_enforcing(self) -> bool:
|
|
93
116
|
proc = await host.arun(["cat", "/sys/fs/selinux/enforce"])
|
|
94
117
|
assert proc.stdout is not None
|
ceph_devstack/requirements.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import shlex
|
|
2
|
-
import sys
|
|
3
2
|
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from packaging.version import parse as parse_version, Version
|
|
@@ -40,7 +39,7 @@ class FixableRequirement(Requirement):
|
|
|
40
39
|
|
|
41
40
|
async def fix(self) -> bool:
|
|
42
41
|
assert self.fix_cmd, "Attempted to fix without a fix command"
|
|
43
|
-
proc = await self.host.arun(self.fix_cmd)
|
|
42
|
+
proc = await self.host.arun(self.fix_cmd, stream_output=True)
|
|
44
43
|
return await proc.wait() == 0
|
|
45
44
|
|
|
46
45
|
|
|
@@ -48,36 +47,49 @@ class LocalRequirement(Requirement):
|
|
|
48
47
|
host = local_host
|
|
49
48
|
|
|
50
49
|
|
|
51
|
-
class
|
|
50
|
+
class LocalFixableRequirement(FixableRequirement):
|
|
51
|
+
host = local_host
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class PodmanPlatform(LocalFixableRequirement):
|
|
55
|
+
suggest_msg = "podman not found"
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def fix_cmd(self):
|
|
59
|
+
host_os = self.host.os_type
|
|
60
|
+
if host_os == "darwin":
|
|
61
|
+
return ["brew", "install", "podman"]
|
|
62
|
+
return ["sudo", host.package_manager(), "install", "-y", "podman"]
|
|
63
|
+
|
|
52
64
|
async def check(self):
|
|
53
|
-
result = False
|
|
54
65
|
try:
|
|
55
|
-
|
|
66
|
+
await self.host.podman_info()
|
|
67
|
+
return True
|
|
56
68
|
except FileNotFoundError:
|
|
57
69
|
logger.error("podman not found. Try: dnf install podman")
|
|
58
70
|
return False
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if
|
|
79
|
-
|
|
80
|
-
return
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class PodmanMachinePresent(FixableRequirement):
|
|
74
|
+
suggest_msg = "podman machine (VM) not present"
|
|
75
|
+
fix_cmd = ["podman", "machine", "init", "--now"]
|
|
76
|
+
|
|
77
|
+
async def check(self):
|
|
78
|
+
machine_infos = await host.podman_machine_info()
|
|
79
|
+
if machine_infos and (machine_info := machine_infos[-1]):
|
|
80
|
+
return machine_info.get("Created") is not None
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class PodmanMachineRunning(LocalFixableRequirement):
|
|
85
|
+
suggest_msg = "podman machine (VM) not running"
|
|
86
|
+
fix_cmd = ["podman", "machine", "start"]
|
|
87
|
+
|
|
88
|
+
async def check(self):
|
|
89
|
+
machine_infos = await host.podman_machine_info()
|
|
90
|
+
if machine_infos and (machine_info := machine_infos[-1]):
|
|
91
|
+
return machine_info.get("Running", False)
|
|
92
|
+
return False
|
|
81
93
|
|
|
82
94
|
|
|
83
95
|
class PodmanGraphDriver(Requirement):
|
|
@@ -150,6 +162,12 @@ class PodmanVersion(Requirement):
|
|
|
150
162
|
|
|
151
163
|
|
|
152
164
|
class PodmanRuntime(Requirement):
|
|
165
|
+
@property
|
|
166
|
+
def fix_cmd(self):
|
|
167
|
+
if self.host.os_type != "darwin":
|
|
168
|
+
return ["sudo", self.host.package_manager(), "install", "-y", "crun"]
|
|
169
|
+
return []
|
|
170
|
+
|
|
153
171
|
async def check(self):
|
|
154
172
|
podman_info = await self.host.podman_info()
|
|
155
173
|
storage_conf_path = podman_info["store"]["configFile"]
|
|
@@ -194,22 +212,31 @@ class SysctlValue(FixableRequirement):
|
|
|
194
212
|
class PodmanDNSPlugin(FixableRequirement):
|
|
195
213
|
suggest_msg = "Could not find the podman DNS plugin"
|
|
196
214
|
|
|
197
|
-
|
|
198
|
-
|
|
215
|
+
@property
|
|
216
|
+
def dns_plugin_path(self):
|
|
217
|
+
os_type = self.host.os_type
|
|
218
|
+
if os_type in ["ubuntu", "debian"]:
|
|
219
|
+
return "/usr/lib/cni/dnsname"
|
|
220
|
+
return "/usr/libexec/cni/dnsname"
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def check_cmd(self):
|
|
224
|
+
return ["test", "-x", self.dns_plugin_path]
|
|
225
|
+
|
|
226
|
+
@property
|
|
227
|
+
def fix_cmd(self):
|
|
228
|
+
os_type = self.host.os_type
|
|
199
229
|
if os_type == "centos":
|
|
200
|
-
|
|
201
|
-
self.check_cmd = ["test", "-x", dns_plugin_path]
|
|
202
|
-
self.fix_cmd = ["sudo", "dnf", "install", "-y", dns_plugin_path]
|
|
230
|
+
return ["sudo", "dnf", "install", "-y", self.dns_plugin_path]
|
|
203
231
|
elif os_type in ["ubuntu", "debian"]:
|
|
204
|
-
|
|
205
|
-
self.check_cmd = ["test", "-x", dns_plugin_path]
|
|
206
|
-
self.fix_cmd = [
|
|
232
|
+
return [
|
|
207
233
|
"sudo",
|
|
208
234
|
"apt",
|
|
209
235
|
"install",
|
|
210
236
|
"-y",
|
|
211
237
|
"golang-github-containernetworking-plugin-dnsname",
|
|
212
238
|
]
|
|
239
|
+
return []
|
|
213
240
|
|
|
214
241
|
|
|
215
242
|
class FuseOverlayfsPresence(FixableRequirement):
|
|
@@ -234,6 +261,11 @@ class AppArmorProfile(FixableRequirement):
|
|
|
234
261
|
async def check_requirements():
|
|
235
262
|
if not await PodmanPlatform().evaluate():
|
|
236
263
|
return False
|
|
264
|
+
if local_host.os_type == "darwin":
|
|
265
|
+
if not await PodmanMachinePresent().evaluate():
|
|
266
|
+
return False
|
|
267
|
+
if not await PodmanMachineRunning().evaluate():
|
|
268
|
+
return False
|
|
237
269
|
|
|
238
270
|
result = True
|
|
239
271
|
# kernel and podman versions for native overlay filesystem
|
|
@@ -5,10 +5,10 @@ ceph_devstack/ceph_devstack.te,sha256=68i9sBb1TAEnCJn2JtyM-ECzPSuZck4vKoymcTbptX
|
|
|
5
5
|
ceph_devstack/cli.py,sha256=lSYwXrwfP8D-k60XuwSqhwZSZNKJFFQfvRM-av1rePM,2057
|
|
6
6
|
ceph_devstack/config.toml,sha256=HsxO3FhwZkHomde69QfElztuN8U1bxk7cQk1_iWB4w0,562
|
|
7
7
|
ceph_devstack/exec.py,sha256=gn95GEQttB6xgdWXXvTsxUxcQsx9TUu6PC8QVQ0_Y7w,2674
|
|
8
|
-
ceph_devstack/host.py,sha256=
|
|
8
|
+
ceph_devstack/host.py,sha256=w_Hx912y1g62yXkTuPJsw_UdUwxJr_Pbxrj8iZtEP7Y,5470
|
|
9
9
|
ceph_devstack/logging.conf,sha256=bGlswYcL_fz522y9EoKZOLInrSss8D44glNq0FievFY,521
|
|
10
10
|
ceph_devstack/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
ceph_devstack/requirements.py,sha256=
|
|
11
|
+
ceph_devstack/requirements.py,sha256=tQIk4TVl-1s5vOBgt5oML6Zk9-ZRtPLzAQ3foBdQpMk,9970
|
|
12
12
|
ceph_devstack/resources/__init__.py,sha256=D0vhJBU9Pqslq7hg2qreW_ZhndcRIOHZVVUA0zAIeDM,3386
|
|
13
13
|
ceph_devstack/resources/container.py,sha256=suJNOQ9fMRfCnXQwvEZOcg4jnPtrxb-d17a3Y1s1xG0,5388
|
|
14
14
|
ceph_devstack/resources/misc.py,sha256=iGD_3Xsqako-dOZrHJFEJbMWoQIzy7Q_KkEnkdBb8m0,552
|
|
@@ -17,13 +17,13 @@ ceph_devstack/resources/ceph/containers.py,sha256=3QEwkh3I7f3r47SnlnMB-_mU8fYGR0
|
|
|
17
17
|
ceph_devstack/resources/ceph/exceptions.py,sha256=C4ldyEA7Cukp-QUOwL-MnQ8kpgMDIQ6r_JQe0E9q4eM,101
|
|
18
18
|
ceph_devstack/resources/ceph/requirements.py,sha256=ZJt7Eeb5y2bOc7dJN3-15ftAyySi80phD7erBsGdqSU,2691
|
|
19
19
|
ceph_devstack/resources/ceph/utils.py,sha256=6-1sageEiLMcx53KHo_GKlIjaGw3swoZk8cQ-e-tDP0,1276
|
|
20
|
-
ceph_devstack-0.1.
|
|
20
|
+
ceph_devstack-0.2.1.dist-info/licenses/LICENSE,sha256=bFeYufyeS1qw0W8pkW1Wj09F2itqX7TAGTnA2NIpApU,1067
|
|
21
21
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
tests/conftest.py,sha256=qulfsMZz3PyAFMdWQ_VWpOFT9L_BiavRax_yQF2Ne24,128
|
|
23
23
|
tests/test_config.py,sha256=RLAjt9DAcAo8GQXgv9dc3Ka3hhtongMs6ioz5YQwKhY,4394
|
|
24
24
|
tests/test_deep_merge.py,sha256=IP9zzCThmhVghl9XjAAiSrKsPdouH3KbEUaKq8n3Soc,2178
|
|
25
25
|
tests/test_parse_args.py,sha256=2JDAT4Id88Ywl5QmiUHqq5IDGm_j5Yl3Kk7pbl3sOEk,7550
|
|
26
|
-
tests/test_requirements_core.py,sha256=
|
|
26
|
+
tests/test_requirements_core.py,sha256=MnhENRBFQkhIYD9sI1HBYBEocqiDBChRw7bOuSI-kPk,20089
|
|
27
27
|
tests/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
tests/resources/test_container.py,sha256=Xc4IGLf0PViSBIhUQXZHZQtRc-uI2R3PyNjU8lpX6BE,9081
|
|
29
29
|
tests/resources/test_misc.py,sha256=dtOAPngMCTE9bYuYjNuxBiRaxvEibXuBq5VwVsWBdnY,1560
|
|
@@ -32,13 +32,13 @@ tests/resources/ceph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
32
32
|
tests/resources/ceph/test_cephdevstack_core.py,sha256=2Zopu-3TkXyj1amQbMG1KpsVXyRDJts73e6TLYNyz3Y,18340
|
|
33
33
|
tests/resources/ceph/test_devstack.py,sha256=PRsEyYy9EKFIiZKkHYZh6vGffIzlZuW9jA9XEt7xz5M,6201
|
|
34
34
|
tests/resources/ceph/test_env_vars.py,sha256=bLTcEJQJSQp0iiJBunPdGHtVQ94KRWSNEkK8HtXZQn0,2741
|
|
35
|
-
tests/resources/ceph/test_requirements_ceph.py,sha256=
|
|
35
|
+
tests/resources/ceph/test_requirements_ceph.py,sha256=VLPHrzt1dLk3RnzjqRY3wyPUQbMspUuW6S_9cAWtpYU,9134
|
|
36
36
|
tests/resources/ceph/test_ssh_keypair.py,sha256=M8Tc1CY9zb_1WaccMSfnSN35tyjR-CblNtTP0s4OsYU,4019
|
|
37
37
|
tests/resources/ceph/test_testnode.py,sha256=wiftdOU058z9IKp5LeUNlv81U9XjojRUI0fYt8mrbgg,1253
|
|
38
38
|
tests/resources/ceph/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
39
|
tests/resources/ceph/fixtures/testnode-config.toml,sha256=XaI4VACYHeshb7LLxN3viKBNxOBLOUpPuwlcQJyQO-U,44
|
|
40
|
-
ceph_devstack-0.1.
|
|
41
|
-
ceph_devstack-0.1.
|
|
42
|
-
ceph_devstack-0.1.
|
|
43
|
-
ceph_devstack-0.1.
|
|
44
|
-
ceph_devstack-0.1.
|
|
40
|
+
ceph_devstack-0.2.1.dist-info/METADATA,sha256=0sxnNB5VBwU61eY7AlPi14s0LrsR6qUWGzblLEus7uA,6877
|
|
41
|
+
ceph_devstack-0.2.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
42
|
+
ceph_devstack-0.2.1.dist-info/entry_points.txt,sha256=3cXOGOSb23ATcOZVQFBTY_imM4VFgFddXlYi-m8PA10,57
|
|
43
|
+
ceph_devstack-0.2.1.dist-info/top_level.txt,sha256=NzTr-vAk2OWL08T8PsmfqkJZNEuezF5oaiHCMJBhHPM,20
|
|
44
|
+
ceph_devstack-0.2.1.dist-info/RECORD,,
|
|
@@ -216,15 +216,11 @@ class TestCephDevStackCheckRequirements:
|
|
|
216
216
|
) as MockLoopCtrlWrite,
|
|
217
217
|
patch("ceph_devstack.host.host.selinux_enforcing") as mock_selinux,
|
|
218
218
|
):
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
MockLoopCtrl.return_value = mock_loop_ctrl
|
|
225
|
-
mock_loop_ctrl_write = AsyncMock()
|
|
226
|
-
mock_loop_ctrl_write.evaluate = AsyncMock(return_value=True)
|
|
227
|
-
MockLoopCtrlWrite.return_value = mock_loop_ctrl_write
|
|
219
|
+
MockHasSudo.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
220
|
+
MockLoopCtrl.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
221
|
+
MockLoopCtrlWrite.return_value = AsyncMock(
|
|
222
|
+
evaluate=AsyncMock(return_value=True)
|
|
223
|
+
)
|
|
228
224
|
mock_selinux.return_value = False
|
|
229
225
|
result = await devstack.check_requirements()
|
|
230
226
|
assert result is True
|
|
@@ -247,15 +243,11 @@ class TestCephDevStackCheckRequirements:
|
|
|
247
243
|
patch("ceph_devstack.host.host.selinux_enforcing") as mock_selinux,
|
|
248
244
|
patch("ceph_devstack.host.host.path_exists") as mock_path_exists,
|
|
249
245
|
):
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
MockLoopCtrl.return_value = mock_loop_ctrl
|
|
256
|
-
mock_loop_ctrl_write = AsyncMock()
|
|
257
|
-
mock_loop_ctrl_write.evaluate = AsyncMock(return_value=True)
|
|
258
|
-
MockLoopCtrlWrite.return_value = mock_loop_ctrl_write
|
|
246
|
+
MockHasSudo.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
247
|
+
MockLoopCtrl.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
248
|
+
MockLoopCtrlWrite.return_value = AsyncMock(
|
|
249
|
+
evaluate=AsyncMock(return_value=True)
|
|
250
|
+
)
|
|
259
251
|
mock_selinux.return_value = False
|
|
260
252
|
mock_path_exists.return_value = False
|
|
261
253
|
result = await devstack.check_requirements()
|
tests/test_requirements_core.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import pytest
|
|
3
3
|
from packaging.version import parse as parse_version
|
|
4
|
-
from unittest.mock import AsyncMock, patch
|
|
4
|
+
from unittest.mock import AsyncMock, MagicMock, patch, PropertyMock
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
from ceph_devstack import config, requirements
|
|
@@ -17,6 +17,11 @@ def req(cls):
|
|
|
17
17
|
return cls()
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
@pytest.fixture(scope="class", params=["centos", "ubuntu", "debian"])
|
|
21
|
+
def os_type(request):
|
|
22
|
+
return request.param
|
|
23
|
+
|
|
24
|
+
|
|
20
25
|
class TestRequirement:
|
|
21
26
|
@pytest.fixture(scope="class")
|
|
22
27
|
def cls(self):
|
|
@@ -113,6 +118,73 @@ class TestLocalRequirement:
|
|
|
113
118
|
assert req.host == requirements.local_host
|
|
114
119
|
|
|
115
120
|
|
|
121
|
+
class TestPodmanPlatform:
|
|
122
|
+
@pytest.fixture(scope="class")
|
|
123
|
+
def cls(self):
|
|
124
|
+
return requirements.PodmanPlatform
|
|
125
|
+
|
|
126
|
+
async def test_podman_present(self, cls):
|
|
127
|
+
with (
|
|
128
|
+
patch(
|
|
129
|
+
"ceph_devstack.requirements.PodmanPlatform.host.podman_info"
|
|
130
|
+
) as MockPodmanInfo,
|
|
131
|
+
patch("ceph_devstack.requirements.local_host") as MockLocalHost,
|
|
132
|
+
):
|
|
133
|
+
MockLocalHost.os_type = MagicMock(return_value="darwin")
|
|
134
|
+
MockPodmanInfo.return_value = {}
|
|
135
|
+
req = cls()
|
|
136
|
+
assert await req.check() is True
|
|
137
|
+
|
|
138
|
+
async def test_podman_missing(self, cls):
|
|
139
|
+
with (
|
|
140
|
+
patch(
|
|
141
|
+
"ceph_devstack.requirements.PodmanPlatform.host.podman_info"
|
|
142
|
+
) as MockPodmanInfo,
|
|
143
|
+
patch("ceph_devstack.requirements.local_host") as MockLocalHost,
|
|
144
|
+
):
|
|
145
|
+
MockLocalHost.os_type = MagicMock(return_value="darwin")
|
|
146
|
+
MockPodmanInfo.side_effect = FileNotFoundError
|
|
147
|
+
req = cls()
|
|
148
|
+
assert await req.check() is False
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class TestPodmanMachinePresent:
|
|
152
|
+
@pytest.fixture(scope="class")
|
|
153
|
+
def cls(self):
|
|
154
|
+
return requirements.PodmanMachinePresent
|
|
155
|
+
|
|
156
|
+
@pytest.mark.parametrize(
|
|
157
|
+
"info,success", [[{}, False], [{"Created": "some_timestamp"}, True]]
|
|
158
|
+
)
|
|
159
|
+
async def test_podman_machine_present(self, cls, info, success):
|
|
160
|
+
with patch("ceph_devstack.requirements.host", AsyncMock()) as MockHost:
|
|
161
|
+
MockHost.podman_machine_info = AsyncMock(return_value=[info])
|
|
162
|
+
req = cls()
|
|
163
|
+
assert await req.check() is success
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class TestPodmanMachineRunning:
|
|
167
|
+
@pytest.fixture(scope="class")
|
|
168
|
+
def cls(self):
|
|
169
|
+
return requirements.PodmanMachineRunning
|
|
170
|
+
|
|
171
|
+
@pytest.mark.parametrize(
|
|
172
|
+
"info,success",
|
|
173
|
+
[[{}, False], [{"Running": False}, False], [{"Running": True}, True]],
|
|
174
|
+
)
|
|
175
|
+
async def test_podman_machine_running(self, cls, info, success):
|
|
176
|
+
with patch("ceph_devstack.requirements.host", AsyncMock()) as MockHost:
|
|
177
|
+
MockHost.podman_machine_info = AsyncMock(return_value=[info])
|
|
178
|
+
req = cls()
|
|
179
|
+
assert await req.check() is success
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class TestPodmanRuntime:
|
|
183
|
+
@pytest.fixture(scope="class")
|
|
184
|
+
def cls(self):
|
|
185
|
+
return requirements.PodmanRuntime
|
|
186
|
+
|
|
187
|
+
|
|
116
188
|
class TestPodmanVersionInit:
|
|
117
189
|
@pytest.fixture(scope="class")
|
|
118
190
|
def cls(self):
|
|
@@ -223,10 +295,6 @@ class TestPodmanDNSPluginInit:
|
|
|
223
295
|
def cls(self):
|
|
224
296
|
return requirements.PodmanDNSPlugin
|
|
225
297
|
|
|
226
|
-
@pytest.fixture(scope="class", params=["centos", "ubuntu", "debian"])
|
|
227
|
-
def os_type(self, request):
|
|
228
|
-
return request.param
|
|
229
|
-
|
|
230
298
|
@pytest.fixture(scope="class")
|
|
231
299
|
def dns_plugin_path(self, os_type):
|
|
232
300
|
if os_type == "centos":
|
|
@@ -235,7 +303,10 @@ class TestPodmanDNSPluginInit:
|
|
|
235
303
|
return "/usr/lib/cni/dnsname"
|
|
236
304
|
|
|
237
305
|
def test_podman_dns_plugin_config(self, cls, os_type, dns_plugin_path):
|
|
238
|
-
with patch
|
|
306
|
+
with patch(
|
|
307
|
+
"ceph_devstack.host.Host.os_type", new_callable=PropertyMock
|
|
308
|
+
) as MockHost:
|
|
309
|
+
MockHost.return_value = os_type
|
|
239
310
|
req = cls()
|
|
240
311
|
assert req.check_cmd == ["test", "-x", dns_plugin_path]
|
|
241
312
|
|
|
@@ -281,22 +352,25 @@ class TestCheckRequirements:
|
|
|
281
352
|
|
|
282
353
|
async def test_check_requirements_returns_false_on_overlay_failure(self):
|
|
283
354
|
with (
|
|
355
|
+
patch("ceph_devstack.requirements.local_host") as MockLocalHost,
|
|
284
356
|
patch("ceph_devstack.requirements.PodmanPlatform") as MockPlatform,
|
|
285
357
|
patch("ceph_devstack.requirements.PodmanGraphDriver") as MockGraph,
|
|
358
|
+
patch("ceph_devstack.requirements.PodmanVersion") as MockVersion,
|
|
359
|
+
patch("ceph_devstack.requirements.KernelVersionForOverlay") as MockKernel,
|
|
360
|
+
patch("ceph_devstack.requirements.CgroupV2") as MockCgroup,
|
|
286
361
|
):
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
MockGraph.return_value = mock_graph
|
|
294
|
-
|
|
362
|
+
MockLocalHost.os_type = MagicMock(return_value="centos")
|
|
363
|
+
MockPlatform.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
364
|
+
MockGraph.return_value = AsyncMock(evaluate=AsyncMock(return_value=False))
|
|
365
|
+
MockVersion.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
366
|
+
MockKernel.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
367
|
+
MockCgroup.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
295
368
|
result = await requirements.check_requirements()
|
|
296
369
|
assert result is False
|
|
297
370
|
|
|
298
371
|
async def test_check_requirements_returns_true_when_all_pass(self):
|
|
299
372
|
with (
|
|
373
|
+
patch("ceph_devstack.requirements.local_host") as MockLocalHost,
|
|
300
374
|
patch("ceph_devstack.requirements.PodmanPlatform") as MockPlatform,
|
|
301
375
|
patch("ceph_devstack.requirements.PodmanGraphDriver") as MockGraph,
|
|
302
376
|
patch("ceph_devstack.requirements.PodmanVersion") as MockVersion,
|
|
@@ -309,45 +383,24 @@ class TestCheckRequirements:
|
|
|
309
383
|
patch("ceph_devstack.requirements.host.selinux_enforcing") as mock_selinux,
|
|
310
384
|
patch("ceph_devstack.requirements.SysctlValue") as MockSysctl,
|
|
311
385
|
):
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
MockVersion.return_value = mock_version
|
|
323
|
-
|
|
324
|
-
mock_kernel = AsyncMock()
|
|
325
|
-
mock_kernel.evaluate = AsyncMock(return_value=True)
|
|
326
|
-
MockKernel.return_value = mock_kernel
|
|
327
|
-
|
|
328
|
-
mock_cgroup = AsyncMock()
|
|
329
|
-
mock_cgroup.evaluate = AsyncMock(return_value=True)
|
|
330
|
-
MockCgroup.return_value = mock_cgroup
|
|
331
|
-
|
|
332
|
-
mock_kernel_cgroup = AsyncMock()
|
|
333
|
-
mock_kernel_cgroup.evaluate = AsyncMock(return_value=True)
|
|
334
|
-
MockKernelCgroup.return_value = mock_kernel_cgroup
|
|
335
|
-
|
|
336
|
-
mock_runtime = AsyncMock()
|
|
337
|
-
mock_runtime.evaluate = AsyncMock(return_value=True)
|
|
338
|
-
MockRuntime.return_value = mock_runtime
|
|
339
|
-
|
|
386
|
+
MockLocalHost.os_type = MagicMock(return_value="centos")
|
|
387
|
+
MockPlatform.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
388
|
+
MockGraph.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
389
|
+
MockVersion.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
390
|
+
MockKernel.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
391
|
+
MockCgroup.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
392
|
+
MockKernelCgroup.return_value = AsyncMock(
|
|
393
|
+
evaluate=AsyncMock(return_value=True)
|
|
394
|
+
)
|
|
395
|
+
MockRuntime.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
340
396
|
mock_selinux.return_value = False
|
|
341
|
-
|
|
342
|
-
mock_sysctl = AsyncMock()
|
|
343
|
-
mock_sysctl.evaluate = AsyncMock(return_value=True)
|
|
344
|
-
MockSysctl.return_value = mock_sysctl
|
|
345
|
-
|
|
397
|
+
MockSysctl.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
346
398
|
result = await requirements.check_requirements()
|
|
347
399
|
assert result is True
|
|
348
400
|
|
|
349
401
|
async def test_check_requirements_returns_false_on_runtime_failure(self):
|
|
350
402
|
with (
|
|
403
|
+
patch("ceph_devstack.requirements.local_host") as MockLocalHost,
|
|
351
404
|
patch("ceph_devstack.requirements.PodmanPlatform") as MockPlatform,
|
|
352
405
|
patch("ceph_devstack.requirements.PodmanGraphDriver") as MockGraph,
|
|
353
406
|
patch("ceph_devstack.requirements.PodmanVersion") as MockVersion,
|
|
@@ -359,43 +412,26 @@ class TestCheckRequirements:
|
|
|
359
412
|
patch("ceph_devstack.requirements.PodmanRuntime") as MockRuntime,
|
|
360
413
|
patch("ceph_devstack.requirements.host.selinux_enforcing") as mock_selinux,
|
|
361
414
|
):
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
MockGraph.return_value = mock_graph
|
|
369
|
-
|
|
370
|
-
mock_version = AsyncMock()
|
|
371
|
-
mock_version.evaluate = AsyncMock(return_value=True)
|
|
372
|
-
MockVersion.return_value = mock_version
|
|
373
|
-
|
|
374
|
-
mock_kernel = AsyncMock()
|
|
375
|
-
mock_kernel.evaluate = AsyncMock(return_value=True)
|
|
376
|
-
MockKernel.return_value = mock_kernel
|
|
377
|
-
|
|
378
|
-
mock_cgroup = AsyncMock()
|
|
379
|
-
mock_cgroup.evaluate = AsyncMock(return_value=True)
|
|
380
|
-
MockCgroup.return_value = mock_cgroup
|
|
381
|
-
|
|
415
|
+
MockLocalHost.os_type = MagicMock(return_value="centos")
|
|
416
|
+
MockPlatform.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
417
|
+
MockGraph.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
418
|
+
MockVersion.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
419
|
+
MockKernel.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
420
|
+
MockCgroup.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
382
421
|
mock_kernel_cgroup = AsyncMock()
|
|
383
422
|
mock_kernel_cgroup.evaluate = AsyncMock(return_value=True)
|
|
384
423
|
MockKernelCgroup.return_value = mock_kernel_cgroup
|
|
385
|
-
|
|
386
|
-
mock_runtime = AsyncMock()
|
|
387
|
-
mock_runtime.evaluate = AsyncMock(return_value=False)
|
|
388
|
-
MockRuntime.return_value = mock_runtime
|
|
389
|
-
|
|
424
|
+
MockRuntime.return_value = AsyncMock(evaluate=AsyncMock(return_value=False))
|
|
390
425
|
mock_selinux.return_value = False
|
|
391
|
-
|
|
392
426
|
result = await requirements.check_requirements()
|
|
393
427
|
assert result is False
|
|
394
428
|
|
|
395
429
|
async def test_check_requirements_returns_false_on_selinux_bool_failure(self):
|
|
396
430
|
with (
|
|
431
|
+
patch("ceph_devstack.requirements.local_host") as MockLocalHost,
|
|
397
432
|
patch("ceph_devstack.requirements.PodmanPlatform") as MockPlatform,
|
|
398
433
|
patch("ceph_devstack.requirements.PodmanGraphDriver") as MockGraph,
|
|
434
|
+
patch("ceph_devstack.requirements.PodmanVersion") as MockVersion,
|
|
399
435
|
patch("ceph_devstack.requirements.KernelVersionForOverlay") as MockKernel,
|
|
400
436
|
patch("ceph_devstack.requirements.CgroupV2") as MockCgroup,
|
|
401
437
|
patch(
|
|
@@ -405,46 +441,26 @@ class TestCheckRequirements:
|
|
|
405
441
|
patch("ceph_devstack.requirements.host.selinux_enforcing") as mock_selinux,
|
|
406
442
|
patch("ceph_devstack.requirements.SELinuxBoolean") as MockSELinuxBoolean,
|
|
407
443
|
):
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
mock_cgroup = AsyncMock()
|
|
426
|
-
mock_cgroup.evaluate = AsyncMock(return_value=True)
|
|
427
|
-
MockCgroup.return_value = mock_cgroup
|
|
428
|
-
|
|
429
|
-
mock_kernel_cgroup = AsyncMock()
|
|
430
|
-
mock_kernel_cgroup.evaluate = AsyncMock(return_value=True)
|
|
431
|
-
MockKernelCgroup.return_value = mock_kernel_cgroup
|
|
432
|
-
|
|
433
|
-
mock_runtime = AsyncMock()
|
|
434
|
-
mock_runtime.evaluate = AsyncMock(return_value=True)
|
|
435
|
-
MockRuntime.return_value = mock_runtime
|
|
436
|
-
|
|
437
|
-
mock_selinux.return_value = True
|
|
438
|
-
|
|
439
|
-
mock_sel = AsyncMock()
|
|
440
|
-
mock_sel.evaluate = AsyncMock(return_value=False)
|
|
441
|
-
MockSELinuxBoolean.return_value = mock_sel
|
|
442
|
-
|
|
443
|
-
result = await requirements.check_requirements()
|
|
444
|
-
assert result is False
|
|
444
|
+
MockLocalHost.os_type = MagicMock(return_value="centos")
|
|
445
|
+
MockPlatform.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
446
|
+
MockGraph.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
447
|
+
MockVersion.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
448
|
+
MockKernel.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
449
|
+
MockCgroup.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
450
|
+
MockKernelCgroup.return_value = AsyncMock(
|
|
451
|
+
evaluate=AsyncMock(return_value=True)
|
|
452
|
+
)
|
|
453
|
+
MockRuntime.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
454
|
+
mock_selinux.return_value = True
|
|
455
|
+
MockSELinuxBoolean.return_value = AsyncMock(
|
|
456
|
+
evaluate=AsyncMock(return_value=False)
|
|
457
|
+
)
|
|
458
|
+
result = await requirements.check_requirements()
|
|
459
|
+
assert result is False
|
|
445
460
|
|
|
446
461
|
async def test_check_requirements_returns_false_on_sysctl_failure(self):
|
|
447
462
|
with (
|
|
463
|
+
patch("ceph_devstack.requirements.local_host") as MockLocalHost,
|
|
448
464
|
patch("ceph_devstack.requirements.PodmanPlatform") as MockPlatform,
|
|
449
465
|
patch("ceph_devstack.requirements.PodmanGraphDriver") as MockGraph,
|
|
450
466
|
patch("ceph_devstack.requirements.PodmanVersion") as MockVersion,
|
|
@@ -457,39 +473,17 @@ class TestCheckRequirements:
|
|
|
457
473
|
patch("ceph_devstack.requirements.host.selinux_enforcing") as mock_selinux,
|
|
458
474
|
patch("ceph_devstack.requirements.SysctlValue") as MockSysctl,
|
|
459
475
|
):
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
MockVersion.return_value = mock_version
|
|
471
|
-
|
|
472
|
-
mock_kernel = AsyncMock()
|
|
473
|
-
mock_kernel.evaluate = AsyncMock(return_value=True)
|
|
474
|
-
MockKernel.return_value = mock_kernel
|
|
475
|
-
|
|
476
|
-
mock_cgroup = AsyncMock()
|
|
477
|
-
mock_cgroup.evaluate = AsyncMock(return_value=True)
|
|
478
|
-
MockCgroup.return_value = mock_cgroup
|
|
479
|
-
|
|
480
|
-
mock_kernel_cgroup = AsyncMock()
|
|
481
|
-
mock_kernel_cgroup.evaluate = AsyncMock(return_value=True)
|
|
482
|
-
MockKernelCgroup.return_value = mock_kernel_cgroup
|
|
483
|
-
|
|
484
|
-
mock_runtime = AsyncMock()
|
|
485
|
-
mock_runtime.evaluate = AsyncMock(return_value=True)
|
|
486
|
-
MockRuntime.return_value = mock_runtime
|
|
487
|
-
|
|
476
|
+
MockLocalHost.os_type = MagicMock(return_value="centos")
|
|
477
|
+
MockPlatform.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
478
|
+
MockGraph.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
479
|
+
MockVersion.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
480
|
+
MockKernel.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
481
|
+
MockCgroup.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
482
|
+
MockKernelCgroup.return_value = AsyncMock(
|
|
483
|
+
evaluate=AsyncMock(return_value=True)
|
|
484
|
+
)
|
|
485
|
+
MockRuntime.return_value = AsyncMock(evaluate=AsyncMock(return_value=True))
|
|
488
486
|
mock_selinux.return_value = False
|
|
489
|
-
|
|
490
|
-
mock_sysctl = AsyncMock()
|
|
491
|
-
mock_sysctl.evaluate = AsyncMock(return_value=False)
|
|
492
|
-
MockSysctl.return_value = mock_sysctl
|
|
493
|
-
|
|
487
|
+
MockSysctl.return_value = AsyncMock(evaluate=AsyncMock(return_value=False))
|
|
494
488
|
result = await requirements.check_requirements()
|
|
495
489
|
assert result is False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|