diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 99d5da01..c2392d4e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,26 +1,26 @@ exclude: 'ceph_devstack/ceph_devstack\.(te|pp)' repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 - hooks: - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace -- repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.11 - hooks: - - id: ruff-check - - id: ruff-format -- repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.0 - hooks: - - id: mypy - exclude: ^docs/conf.py - additional_dependencies: - - types-dataclasses >= 0.1.3 - - types-PyYAML - - tomli >= 0.2.6, < 2.0.0 - - types-typed-ast >= 1.4.1 - - click >= 8.1.0 - - platformdirs >= 2.1.0 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.11 + hooks: + - id: ruff-check + - id: ruff-format + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.20.1 + hooks: + - id: mypy + exclude: ^docs/conf.py + additional_dependencies: + - types-dataclasses >= 0.1.3 + - types-PyYAML + - tomli >= 0.2.6, < 2.0.0 + - types-typed-ast >= 1.4.1 + - click >= 8.1.0 + - platformdirs >= 2.1.0 diff --git a/ceph_devstack/ceph_devstack.pp b/ceph_devstack/ceph_devstack.pp index f507aede..04433ece 100644 Binary files a/ceph_devstack/ceph_devstack.pp and b/ceph_devstack/ceph_devstack.pp differ diff --git a/ceph_devstack/ceph_devstack.te b/ceph_devstack/ceph_devstack.te index 7451a521..f661669b 100644 --- a/ceph_devstack/ceph_devstack.te +++ b/ceph_devstack/ceph_devstack.te @@ -1,10 +1,13 @@ module ceph_devstack 1.0; require { + type unconfined_t; + type container_t; type container_init_t; type proc_t; type sysfs_t; type tmpfs_t; + type user_tmp_t; type devpts_t; class filesystem mount; class filesystem unmount; @@ -74,6 +77,9 @@ require { type fuse_device_t; type tun_tap_device_t; + + class sock_file write; + class unix_stream_socket connectto; } #============= container_init_t ============== @@ -116,3 +122,6 @@ allow container_init_t lvm_control_t:chr_file mounton; allow container_init_t fuse_device_t:chr_file mounton; allow container_init_t fixed_disk_device_t:blk_file mounton; allow container_init_t tun_tap_device_t:chr_file mounton; + +allow container_t user_tmp_t:sock_file write; +allow container_t unconfined_t:unix_stream_socket connectto; diff --git a/ceph_devstack/exec.py b/ceph_devstack/exec.py index 9e3bff72..bfeb9363 100644 --- a/ceph_devstack/exec.py +++ b/ceph_devstack/exec.py @@ -60,7 +60,10 @@ def run(self) -> subprocess.Popen: async def arun(self) -> asyncio.subprocess.Process: logger.log(VERBOSE, self._make_log_msg()) loop = asyncio.get_running_loop() - protocol_factory: functools.partial[SubprocessStreamProtocol] + protocol_factory: ( + functools.partial[SubprocessStreamProtocol] + | functools.partial[LoggingStreamProtocol] + ) if self.stream_output: protocol_factory = functools.partial( LoggingStreamProtocol, diff --git a/ceph_devstack/host.py b/ceph_devstack/host.py index 1fcca5f4..d4646fbb 100644 --- a/ceph_devstack/host.py +++ b/ceph_devstack/host.py @@ -99,7 +99,7 @@ async def check_selinux_bool(self, name: str): proc = await host.arun(["getsebool", name]) assert proc.stdout is not None out = await proc.stdout.read() - return out.decode().strip() != f"{name} --> on" + return out.decode().strip() == f"{name} --> on" async def get_sysctl_value(self, name: str) -> int: proc = await host.arun(["sysctl", "-b", name]) diff --git a/ceph_devstack/resources/__init__.py b/ceph_devstack/resources/__init__.py index 1c9e39d6..65051cc3 100644 --- a/ceph_devstack/resources/__init__.py +++ b/ceph_devstack/resources/__init__.py @@ -38,6 +38,7 @@ class PodmanResource: stop_cmd: List[str] = [] cmd_vars: List[str] = ["name"] log: Dict[str, Set[str]] = {} + _name: str | None = None def __init__(self, name: str = ""): if name: @@ -45,7 +46,7 @@ def __init__(self, name: str = ""): @property def name(self) -> str: - if hasattr(self, "_name"): + if self._name is not None: return self._name return self.__class__.__name__.lower() @@ -110,5 +111,5 @@ async def remove(self): await self.cmd(self.format_cmd(self.remove_cmd)) def __repr__(self): - param_str = "" if not hasattr(self, "_name") else f'name="{self._name}"' + param_str = "" if self._name is None else f'name="{self._name}"' return f"{self.__class__.__name__}({param_str})" diff --git a/ceph_devstack/resources/ceph/__init__.py b/ceph_devstack/resources/ceph/__init__.py index 289197f1..d40a15aa 100644 --- a/ceph_devstack/resources/ceph/__init__.py +++ b/ceph_devstack/resources/ceph/__init__.py @@ -1,6 +1,7 @@ import asyncio import contextlib import os +import pathlib import tempfile from subprocess import CalledProcessError @@ -67,12 +68,13 @@ async def _get_ssh_keys(self): privkey_path = os.environ.get("SSH_PRIVKEY_PATH") self.pubkey_path = "/dev/null" if not privkey_path: - privkey_path = tempfile.mktemp( + temp_dir = tempfile.mkdtemp( prefix="teuthology-ssh-key-", dir="/tmp", ) + privkey_path = pathlib.Path(temp_dir) / self.__class__.privkey_path await self.cmd( - ["ssh-keygen", "-t", "rsa", "-N", "", "-f", privkey_path], + ["ssh-keygen", "-t", "rsa", "-N", "", "-f", str(privkey_path)], check=True, force_local=True, ) @@ -229,9 +231,7 @@ async def wait(self, container_name: str): logger.error(f"Could not find container {container_name}") return 1 - async def logs( - self, run_name: str = None, job_id: str = None, locate: bool = False - ): + async def logs(self, run_name: str = "", job_id: str = "", locate: bool = False): try: log_file = self.get_log_file(run_name, job_id) except FileNotFoundError: @@ -250,7 +250,7 @@ async def logs( while chunk := f.read(buffer_size): print(chunk, end="") - def get_log_file(self, run_name: str = None, job_id: str = None): + def get_log_file(self, run_name: str, job_id: str): archive_dir = Teuthology().archive_dir.expanduser() if not run_name: diff --git a/ceph_devstack/resources/ceph/containers.py b/ceph_devstack/resources/ceph/containers.py index dab877a9..d0332fdd 100644 --- a/ceph_devstack/resources/ceph/containers.py +++ b/ceph_devstack/resources/ceph/containers.py @@ -99,7 +99,7 @@ class Paddles(Container): class Archive(Container): - cmd_vars: List[str] = ["name", "image", "archive_dir"] + cmd_vars = Container.cmd_vars + ["archive_dir"] create_cmd = [ "podman", "container", @@ -150,11 +150,12 @@ class Pulpito(Container): ] env_vars = { "PULPITO_PADDLES_ADDRESS": "http://paddles:8080", + "VITE_MACHINE_TYPE": "testnode", } class TestNode(Container): - cmd_vars: List[str] = ["name", "image"] + _image_name = "teuthology-testnode" capabilities = [ "SYS_ADMIN", "NET_ADMIN", @@ -367,7 +368,7 @@ def create_cmd(self): f"{ansible_inv}/secrets:/etc/ansible/secrets", ] ssh_auth_socket = os.environ.get("SSH_AUTH_SOCK") - if ssh_auth_socket: + if ssh_auth_socket and Path(ssh_auth_socket).exists(): cmd += [ "-v", f"{ssh_auth_socket}:{ssh_auth_socket}", diff --git a/ceph_devstack/resources/ceph/utils.py b/ceph_devstack/resources/ceph/utils.py index 6f96f5aa..43834382 100644 --- a/ceph_devstack/resources/ceph/utils.py +++ b/ceph_devstack/resources/ceph/utils.py @@ -10,6 +10,7 @@ def get_logtimestamp(dirname: str) -> datetime: match_ = RUN_DIRNAME_PATTERN.search(dirname) + assert match_ return datetime.strptime(match_.group("timestamp"), "%Y-%m-%d_%H:%M:%S") diff --git a/ceph_devstack/resources/container.py b/ceph_devstack/resources/container.py index c0c6d9ef..49662b3c 100644 --- a/ceph_devstack/resources/container.py +++ b/ceph_devstack/resources/container.py @@ -11,12 +11,12 @@ class Container(PodmanResource): network: str secret: List[str] - cmd_vars: List[str] = ["name", "image", "image_tag"] + cmd_vars: List[str] = ["name", "image", "image_name", "image_tag"] build_cmd: List[str] = [ "podman", "build", "-t", - "{name}:{image_tag}", + "{image_name}:{image_tag}", ".", ] create_cmd: List[str] = ["podman", "container", "create", "{name}"] @@ -27,6 +27,7 @@ class Container(PodmanResource): pull_cmd: List[str] = ["podman", "pull", "{image}"] wait_cmd: List[str] = ["podman", "wait", "{name}"] env_vars: Dict[str, Optional[str]] = {} + _image_name: str | None = None def __init__(self, name: str = ""): super().__init__(name) @@ -48,10 +49,16 @@ def add_env_to_args(self, args: List): def config(self): return config["containers"].get(self.__class__.__name__.lower(), {}) + @property + def image_name(self) -> str: + if self._image_name is not None: + return self._image_name + return self.__class__.__name__.lower() + @property def image(self): if self.repo: - return f"localhost/{self.name}" + return f"localhost/{self.image_name}" return self.config["image"] @property