From c10ee70739ab76f68b0dd58a1fd684062b937b66 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Wed, 24 Mar 2021 10:37:34 +0000 Subject: [PATCH] Drop Python cgroups module How sad. It was quite lovely code, but I need it to be handled in C. Signed-off-by: Michael Tremer --- Makefile.am | 2 - po/POTFILES.in | 1 - src/pakfire/builder.py | 27 ------ src/pakfire/cgroups.py | 207 ---------------------------------------- tests/python/cgroups.py | 44 --------- 5 files changed, 281 deletions(-) delete mode 100644 src/pakfire/cgroups.py delete mode 100755 tests/python/cgroups.py diff --git a/Makefile.am b/Makefile.am index 538ffc372..0d049ba55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -116,7 +116,6 @@ pakfire_PYTHON = \ src/pakfire/__version__.py \ src/pakfire/base.py \ src/pakfire/builder.py \ - src/pakfire/cgroups.py \ src/pakfire/client.py \ src/pakfire/cli.py \ src/pakfire/config.py \ @@ -688,7 +687,6 @@ TESTS_ENVIRONMENT = \ topdir="$(shell pwd)" dist_check_SCRIPTS = \ - tests/python/cgroups.py \ tests/python/execute.py \ tests/python/parser.py \ tests/python/test.py diff --git a/po/POTFILES.in b/po/POTFILES.in index 91963b542..b50b87795 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -46,7 +46,6 @@ src/pakfire/__version__.py src/pakfire/__version__.py.in src/pakfire/base.py src/pakfire/builder.py -src/pakfire/cgroups.py src/pakfire/cli.py src/pakfire/client.py src/pakfire/compress.py diff --git a/src/pakfire/builder.py b/src/pakfire/builder.py index e90988c8d..15b40fca1 100644 --- a/src/pakfire/builder.py +++ b/src/pakfire/builder.py @@ -24,7 +24,6 @@ import uuid from . import _pakfire from . import base -from . import cgroups from . import config from . import logger from . import util @@ -100,9 +99,6 @@ class Builder(object): if not _pakfire.arch_supported_by_host(self.arch): raise BuildError(_("Cannot build for %s on this host") % self.arch) - # Initialize cgroups - self.cgroup = self._make_cgroup() - def __enter__(self): self.log.debug("Entering %s" % self) @@ -126,13 +122,6 @@ class Builder(object): def __exit__(self, type, value, traceback): self.log.debug("Leaving %s" % self) - # Kill all remaining processes in the build environment - self.cgroup.killall() - - # Destroy the cgroup - self.cgroup.destroy() - self.cgroup = None - def setup_logging(self, logfile): l = log.getChild(self.build_id) l.setLevel(logging.DEBUG) @@ -155,22 +144,6 @@ class Builder(object): return l - def _make_cgroup(self): - """ - Initialises a cgroup so that we can enforce resource limits - and can identify processes belonging to this build environment. - """ - # Find our current group - parent = cgroups.get_own_group() - - # Create a sub-group - cgroup = parent.create_subgroup("pakfire-%s" % self.build_id) - - # Make this process join the new group - cgroup.attach_self() - - return cgroup - class BuilderContext(object): def __init__(self, pakfire, builder): diff --git a/src/pakfire/cgroups.py b/src/pakfire/cgroups.py deleted file mode 100644 index e0ad2e7a6..000000000 --- a/src/pakfire/cgroups.py +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/python3 -############################################################################### -# # -# Pakfire - The IPFire package management system # -# Copyright (C) 2021 Pakfire development team # -# # -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation, either version 3 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see . # -# # -############################################################################### - -import logging -import os -import signal -import time - -log = logging.getLogger("pakfire.cgroups") - -def find_group_by_pid(pid): - """ - Returns the cgroup of the process currently running with pid - """ - with open("/proc/%s/cgroup" % pid) as f: - for line in f: - if not line.startswith("0::"): - continue - - # Clean up path - path = line[3:].rstrip() - - return CGroup(path) - -def get_own_group(): - """ - Returns the cgroup of the process we are currently in - """ - pid = os.getpid() - - return find_group_by_pid(pid) - -class CGroup(object): - """ - cgroup controller - """ - root = "/sys/fs/cgroup/unified" - - def __init__(self, path): - if not path.startswith("/"): - raise ValueError("Invalid cgroup path") - - # Store path - self.path = path - - # Make absolute path - self.abspath = "%s%s" % (self.root, self.path) - - if not os.path.isdir(self.abspath): - raise ValueError("Non-existant cgroup") - - def __repr__(self): - return "<%s path=%s>" % (self.__class__.__name__, self.path) - - def _open(self, path, mode="r"): - """ - Opens a file in this cgroup for reading of writing - """ - # Make full path - path = os.path.join(self.abspath, path) - - return open(path, mode) - - @property - def parent(self): - """ - Returns the parent group - """ - return self.__class__(os.path.dirname(self.path)) - - def create_subgroup(self, name): - path = os.path.join(self.path, name) - - # Create directory - try: - os.mkdir("%s%s" % (self.root, path)) - - log.debug("New cgroup '%s' created" % path) - - # Silently continue if groups already exists - except FileExistsError: - pass - - # Return new instance - return self.__class__(path) - - def destroy(self): - """ - Destroys this cgroup - """ - log.debug("Destroying cgroup %s" % self.path) - - # Move whatever is left to the parent group - self.migrate(self.parent) - - # Remove the file tree - try: - os.rmdir(self.abspath) - except OSError as e: - # Ignore "Device or resource busy". - if e.errno == 16: - return - - raise - - @property - def pids(self): - """ - Returns the PIDs of all currently in this group running processes - """ - pids = [] - - with self._open("cgroup.procs") as f: - for line in f: - try: - pid = int(line) - except (TypeError, ValueError): - pass - - pids.append(pid) - - return pids - - def attach_process(self, pid): - """ - Attaches the process PID to this group - """ - log.debug("Attaching process %s to group %s" % (pid, self.path)) - - with self._open("cgroup.procs", "w") as f: - f.write("%s\n" % pid) - - def attach_self(self): - """ - Attaches this process to the group - """ - return self.attach_process(os.getpid()) - - def detach_self(self): - pid = os.getpid() - - # Move process to parent - if pid in self.pids: - self.parent.attach_process(pid) - - def migrate(self, group): - """ - Migrates all processes to the given group - """ - for pid in self.pids: - group.attach_process(pid) - - def _kill(self, signal=signal.SIGTERM): - """ - Sends signal to all processes in this cgroup - """ - for pid in self.pids: - log.debug("Sending signal %s to process %s" % (signal, pid)) - - try: - os.kill(pid, signal) - except OSError as e: - # Skip "No such process" error - if e.errno == 3: - pass - else: - raise - - # Return True if there are any processes left - return not self.pids - - def killall(self, timeout=10): - """ - Kills all processes - """ - self.detach_self() - - for i in range(timeout * 10): - if i >= 10: - s = signal.SIGKILL - else: - s = signal.SIGTERM - - # Send signal and end loop when no processes are left - if self._kill(signal=s): - break - - # Sleep for 100ms - time.sleep(0.1) diff --git a/tests/python/cgroups.py b/tests/python/cgroups.py deleted file mode 100755 index 1a1865246..000000000 --- a/tests/python/cgroups.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python3 - -import os -import unittest - -import pakfire.cgroups as cgroups - -class Test(unittest.TestCase): - def setUp(self): - # Find our own cgroup - self.cgroup = cgroups.get_own_group() - - def test_find_own_group(self): - """ - Check if we found our own cgroup - """ - self.assertIsInstance(self.cgroup, cgroups.CGroup) - - def test_subgroup(self): - # Create a new sub group - subgroup = self.cgroup.create_subgroup("test-1") - self.assertIsInstance(subgroup, cgroups.CGroup) - - # Attach the test process to it - subgroup.attach_self() - - # Fetch pids - pids = subgroup.pids - - # There must be one pid in this list - self.assertTrue(len(pids) == 1) - - # The pid must be the one of this process - self.assertTrue(pids[0] == os.getpid()) - - # Can't really test killing ourselves here - #subgroup.killall() - - # Destroy it - subgroup.destroy() - - -if __name__ == "__main__": - unittest.main() -- 2.47.2