From 4619287fbdd5455d94f1642296c6cfd8549d9de6 Mon Sep 17 00:00:00 2001 From: Benjamin Milan Date: Fri, 14 Aug 2026 15:33:20 +0100 Subject: [PATCH] BWDO-836 restrict docker run cpu usage --- src/sc/branching/commands/group.py | 2 +- src/sc/branching/commands/show.py | 6 +++--- src/sc/docker/docker.py | 13 +++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/sc/branching/commands/group.py b/src/sc/branching/commands/group.py index c7f2d62..ef344f6 100644 --- a/src/sc/branching/commands/group.py +++ b/src/sc/branching/commands/group.py @@ -68,7 +68,7 @@ def _show_project(self, proj: ProjectElementInterface): proj_dir = self.top_dir / proj.path logger.info(f"Project: {proj_dir}") logger.info( - f"Lock Status: [bold yellow]\[{proj.lock_status or 'NORMAL'}][/]", + rf"Lock Status: [bold yellow]\[{proj.lock_status or 'NORMAL'}][/]", extra={"markup": True} ) diff --git a/src/sc/branching/commands/show.py b/src/sc/branching/commands/show.py index 65e76ae..b864daa 100644 --- a/src/sc/branching/commands/show.py +++ b/src/sc/branching/commands/show.py @@ -49,15 +49,15 @@ def _show_project(self, proj: ProjectElementInterface): proj_dir = self.top_dir / proj.path logger.info(f"Project: {proj_dir}") logger.info( - f"Lock Status: \[[bold yellow]{proj.lock_status or 'NORMAL'}[/]]", + rf"Lock Status: \[[bold yellow]{proj.lock_status or 'NORMAL'}[/]]", extra={"markup": True} ) if proj.groups: groups = proj.groups.split(",") - group_str = " ".join([f"\[[bold yellow]{g}[/]]" for g in groups]) + group_str = " ".join([rf"\[[bold yellow]{g}[/]]" for g in groups]) else: - group_str = "\[[red bold]No Groups[/]]" + group_str = "\\[[red bold]No Groups[/]]" logger.info(f"Groups: {group_str}", extra={"markup": True}) diff --git a/src/sc/docker/docker.py b/src/sc/docker/docker.py index 0dfe16d..49dc307 100644 --- a/src/sc/docker/docker.py +++ b/src/sc/docker/docker.py @@ -583,6 +583,9 @@ def _generate_docker_run_command( else: self._warn_x11_not_forwarded(display, xauth_line) + if max_cpu := self._get_cpu_limit(): + docker_args += [f"--cpuset-cpus=0-{max_cpu}"] + coverity_dir = Path('/opt/coverity').resolve() if Path('/opt/coverity').is_symlink() and Path(coverity_dir).exists(): docker_args += ["-v", f"{coverity_dir}:{coverity_dir}"] @@ -678,3 +681,13 @@ def _warn_x11_not_forwarded(self, display: str | None, xauth_line: str | None): click.secho( "WARNING: Failed to get line from xauthority.", fg="yellow") click.secho("WARNING: X11 not forwarded into docker.", fg="yellow") + + def _get_cpu_limit(self) -> int | None: + """Get the highest CPU ID to leave at least 4 cores free.""" + cpu_count = os.cpu_count() or 1 + + if cpu_count >= 20: + # We leave 4 cores free, but CPU IDs start from zero so minus 5 + return cpu_count - 5 + else: + return None