mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
module/cgroups2: Added utilisation of the 'LinuxTarget' interface.
Replaced all references to devlib.Target with devlib.LinuxTarget to correctly utilise appropriate interface. Also added relevant functionality to corectly create the root directories of the CGroup hierarchies, handling any error that occurs in that case.
This commit is contained in:
parent
5ea63490a9
commit
e012b175c6
@ -26,17 +26,17 @@ It also handles the cgroup delegation API of systemd.
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# Necessary Imports
|
# Necessary Imports
|
||||||
from devlib import Target
|
from devlib import LinuxTarget
|
||||||
from devlib.module.cgroups2 import RequestTree
|
from devlib.module.cgroups2 import RequestTree
|
||||||
|
|
||||||
# Connecting to target device. Configure appropriately.
|
# Connecting to target device. Configure appropriately.
|
||||||
|
|
||||||
my_target = Target(name="target",
|
my_target = LinuxTarget(connection_settings={
|
||||||
host="127.0.0.1",
|
"host":"127.0.0.1",
|
||||||
port="0000",
|
"port":"0000",
|
||||||
username="root",
|
"username":"root",
|
||||||
password="root",
|
"password":"root"
|
||||||
kind="linux")
|
})
|
||||||
|
|
||||||
# Instantiating the RequestTree object,
|
# Instantiating the RequestTree object,
|
||||||
# representing a hierarchical CGroup structure consisting
|
# representing a hierarchical CGroup structure consisting
|
||||||
@ -104,7 +104,7 @@ from shlex import quote
|
|||||||
from typing import Dict, Set, List, Union, Any
|
from typing import Dict, Set, List, Union, Any
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from devlib import Target
|
from devlib import LinuxTarget
|
||||||
from devlib.exception import (
|
from devlib.exception import (
|
||||||
TargetStableCalledProcessError,
|
TargetStableCalledProcessError,
|
||||||
TargetStableError,
|
TargetStableError,
|
||||||
@ -113,7 +113,7 @@ from devlib.target import FstabEntry
|
|||||||
from devlib.utils.misc import memoized
|
from devlib.utils.misc import memoized
|
||||||
|
|
||||||
|
|
||||||
def _is_systemd_online(target: Target):
|
def _is_systemd_online(target: LinuxTarget):
|
||||||
"""
|
"""
|
||||||
Determines if systemd is activated on the target system.
|
Determines if systemd is activated on the target system.
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ def _is_systemd_online(target: Target):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _read_lines(target: Target, path: str):
|
def _read_lines(target: LinuxTarget, path: str):
|
||||||
"""
|
"""
|
||||||
Reads the lines of a file stored on the target device.
|
Reads the lines of a file stored on the target device.
|
||||||
|
|
||||||
@ -228,13 +228,17 @@ def _add_controller_mounts(
|
|||||||
return {
|
return {
|
||||||
controller: {**config, "mount_point": path if path is not None else config}
|
controller: {**config, "mount_point": path if path is not None else config}
|
||||||
for (controller, config, path) in (
|
for (controller, config, path) in (
|
||||||
(controller, config, _infer_mount(controller=controller,configuration=config))
|
(
|
||||||
|
controller,
|
||||||
|
config,
|
||||||
|
_infer_mount(controller=controller, configuration=config),
|
||||||
|
)
|
||||||
for (controller, config) in controllers.items()
|
for (controller, config) in controllers.items()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _get_cgroup_controllers(target: Target):
|
def _get_cgroup_controllers(target: LinuxTarget):
|
||||||
"""
|
"""
|
||||||
Returns the CGroup controllers that are currently enabled on the target device, alongside their appropriate configurations.
|
Returns the CGroup controllers that are currently enabled on the target device, alongside their appropriate configurations.
|
||||||
|
|
||||||
@ -287,7 +291,7 @@ def _get_cgroup_controllers(target: Target):
|
|||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _request_delegation(target: Target):
|
def _request_delegation(target: LinuxTarget):
|
||||||
"""
|
"""
|
||||||
Requests systemd to delegate a subtree CGroup hierarchy to our transient service unit.
|
Requests systemd to delegate a subtree CGroup hierarchy to our transient service unit.
|
||||||
|
|
||||||
@ -322,7 +326,7 @@ def _request_delegation(target: Target):
|
|||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _mount_v2_controllers(target: Target):
|
def _mount_v2_controllers(target: LinuxTarget):
|
||||||
"""
|
"""
|
||||||
Mounts the V2 unified CGroup controller hierarchy.
|
Mounts the V2 unified CGroup controller hierarchy.
|
||||||
|
|
||||||
@ -331,22 +335,27 @@ def _mount_v2_controllers(target: Target):
|
|||||||
|
|
||||||
:yield: The path to the root of the mounted V2 controller hierarchy.
|
:yield: The path to the root of the mounted V2 controller hierarchy.
|
||||||
:rtype: str
|
:rtype: str
|
||||||
|
|
||||||
|
:raises TargetStableError: Occurs in the case where the root directory of the requested CGroup V2 Controller hierarchy
|
||||||
|
is unable to be created up on the target system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
path = target.tempfile()
|
||||||
|
|
||||||
|
try:
|
||||||
|
target.makedirs(path, as_root=True)
|
||||||
|
except TargetStableCalledProcessError:
|
||||||
|
raise TargetStableError("Un-able to create the root directory of the requested CGroup V2 hierarchy")
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
path = target.execute(
|
|
||||||
"{busybox} mktemp -d".format(busybox=quote(target.busybox)), as_root=True
|
|
||||||
).strip()
|
|
||||||
|
|
||||||
target.execute(
|
target.execute(
|
||||||
"{busybox} mount -t cgroup2 none {path}".format(
|
"{busybox} mount -t cgroup2 none {path}".format(
|
||||||
busybox=quote(target.busybox), path=quote(path)
|
busybox=quote(target.busybox), path=quote(path)
|
||||||
),
|
),
|
||||||
as_root=True,
|
as_root=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
yield path
|
yield path
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
target.execute(
|
target.execute(
|
||||||
"{busybox} umount {path} && {busybox} rmdir -- {path}".format(
|
"{busybox} umount {path} && {busybox} rmdir -- {path}".format(
|
||||||
@ -358,7 +367,7 @@ def _mount_v2_controllers(target: Target):
|
|||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _mount_v1_controllers(target: Target, controllers: Set[str]):
|
def _mount_v1_controllers(target: LinuxTarget, controllers: Set[str]):
|
||||||
"""
|
"""
|
||||||
Mounts the V1 split CGroup controller hierarchies.
|
Mounts the V1 split CGroup controller hierarchies.
|
||||||
|
|
||||||
@ -370,18 +379,24 @@ def _mount_v1_controllers(target: Target, controllers: Set[str]):
|
|||||||
|
|
||||||
:yield: A dictionary mapping CGroup controller names to the paths that they're currently mounted at.
|
:yield: A dictionary mapping CGroup controller names to the paths that they're currently mounted at.
|
||||||
:rtype: Dict[str,str]
|
:rtype: Dict[str,str]
|
||||||
|
|
||||||
|
:raises TargetStableError: Occurs in the case where the root directory of a requested CGroup V1 Controller hierarchy
|
||||||
|
is unable to be created up on the target system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Internal helper function which mounts a single V1 controller hierarchy and returns
|
# Internal helper function which mounts a single V1 controller hierarchy and returns
|
||||||
# its mount path.
|
# its mount path.
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _mount_controller(controller):
|
def _mount_controller(controller):
|
||||||
try:
|
|
||||||
path = target.execute(
|
|
||||||
"{busybox} mktemp -d".format(busybox=quote(target.busybox)),
|
|
||||||
as_root=True,
|
|
||||||
).strip()
|
|
||||||
|
|
||||||
|
path = target.tempfile()
|
||||||
|
|
||||||
|
try:
|
||||||
|
target.makedirs(path, as_root=True)
|
||||||
|
except TargetStableCalledProcessError as err:
|
||||||
|
raise TargetStableError("Un-able to create the root directory of the {controller} CGroup V1 hierarchy".format(controller = controller))
|
||||||
|
|
||||||
|
try:
|
||||||
target.execute(
|
target.execute(
|
||||||
"{busybox} mount -t cgroup -o {controller} none {path}".format(
|
"{busybox} mount -t cgroup -o {controller} none {path}".format(
|
||||||
busybox=quote(target.busybox),
|
busybox=quote(target.busybox),
|
||||||
@ -389,6 +404,7 @@ def _mount_v1_controllers(target: Target, controllers: Set[str]):
|
|||||||
path=quote(path),
|
path=quote(path),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
yield path
|
yield path
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
@ -459,7 +475,7 @@ class _CGroupBase(ABC):
|
|||||||
name: str,
|
name: str,
|
||||||
parent_path: str,
|
parent_path: str,
|
||||||
active_controllers: Dict[str, Dict[str, str]],
|
active_controllers: Dict[str, Dict[str, str]],
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.active_controllers = active_controllers
|
self.active_controllers = active_controllers
|
||||||
@ -551,8 +567,9 @@ class _CGroupBase(ABC):
|
|||||||
path=self.target.path.join(self.group_path, "cgroup.procs"),
|
path=self.target.path.join(self.group_path, "cgroup.procs"),
|
||||||
target=self.target,
|
target=self.target,
|
||||||
)
|
)
|
||||||
except TargetStableCalledProcessError:
|
except TargetStableError:
|
||||||
self._set_controller_attribute("cgroup", "procs", pid)
|
self._set_controller_attribute("cgroup", "procs", pid)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if str(pid) not in member_processes:
|
if str(pid) not in member_processes:
|
||||||
self._set_controller_attribute("cgroup", "procs", pid)
|
self._set_controller_attribute("cgroup", "procs", pid)
|
||||||
@ -648,7 +665,7 @@ class _CGroupV2(_CGroupBase):
|
|||||||
active_controllers: Dict[str, Dict[str, str]],
|
active_controllers: Dict[str, Dict[str, str]],
|
||||||
subtree_controllers: set,
|
subtree_controllers: set,
|
||||||
is_threaded: bool,
|
is_threaded: bool,
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
):
|
):
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -705,7 +722,7 @@ class _CGroupV2(_CGroupBase):
|
|||||||
self._set_controller_attribute(
|
self._set_controller_attribute(
|
||||||
"cgroup", "type", "threaded", verify=True
|
"cgroup", "type", "threaded", verify=True
|
||||||
)
|
)
|
||||||
except TargetStableCalledProcessError:
|
except TargetStableError:
|
||||||
raise TargetStableError(
|
raise TargetStableError(
|
||||||
"Domain CGroup controllers are enabled within a threaded CGroup subtree. Ensure only threaded controllers are enabled in threaded CGroups."
|
"Domain CGroup controllers are enabled within a threaded CGroup subtree. Ensure only threaded controllers are enabled in threaded CGroups."
|
||||||
)
|
)
|
||||||
@ -822,7 +839,7 @@ class _CGroupV2Root(_CGroupV2):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_delegated_sub_path(cls, delegated_pid: int, target: Target):
|
def _get_delegated_sub_path(cls, delegated_pid: int, target: LinuxTarget):
|
||||||
"""
|
"""
|
||||||
Returns the relative sub-path the delegated root of the V2 hierarchy is mounted on, via the parsing
|
Returns the relative sub-path the delegated root of the V2 hierarchy is mounted on, via the parsing
|
||||||
of the /proc/<PID>/cgroup file of the delegated process associated with ``delegated_pid``.
|
of the /proc/<PID>/cgroup file of the delegated process associated with ``delegated_pid``.
|
||||||
@ -939,7 +956,7 @@ class _CGroupV2Root(_CGroupV2):
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def _systemd_offline_mount(
|
def _systemd_offline_mount(
|
||||||
cls,
|
cls,
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
all_controllers: Dict[str, Dict[str, Union[str, int]]],
|
all_controllers: Dict[str, Dict[str, Union[str, int]]],
|
||||||
requested_controllers: Set[str],
|
requested_controllers: Set[str],
|
||||||
):
|
):
|
||||||
@ -976,7 +993,7 @@ class _CGroupV2Root(_CGroupV2):
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def _systemd_online_setup(
|
def _systemd_online_setup(
|
||||||
cls,
|
cls,
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
all_controllers: Dict[str, Dict[str, int]],
|
all_controllers: Dict[str, Dict[str, int]],
|
||||||
requested_controllers: Set[str],
|
requested_controllers: Set[str],
|
||||||
):
|
):
|
||||||
@ -1031,7 +1048,7 @@ class _CGroupV2Root(_CGroupV2):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _mount_filesystem(cls, target: Target, requested_controllers: Set[str]):
|
def _mount_filesystem(cls, target: LinuxTarget, requested_controllers: Set[str]):
|
||||||
"""
|
"""
|
||||||
Mounts/Sets-up a V2 hierarchy on the target device, covering contexts where
|
Mounts/Sets-up a V2 hierarchy on the target device, covering contexts where
|
||||||
systemd is both present and absent.
|
systemd is both present and absent.
|
||||||
@ -1073,7 +1090,7 @@ class _CGroupV2Root(_CGroupV2):
|
|||||||
self,
|
self,
|
||||||
mount_point: str,
|
mount_point: str,
|
||||||
subtree_controllers: set,
|
subtree_controllers: set,
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
):
|
):
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -1250,9 +1267,9 @@ class _CGroupV1Root(_CGroupV1):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def _get_delegated_paths(
|
def _get_delegated_paths(
|
||||||
cls,
|
cls,
|
||||||
controllers: Dict[str, Dict[str,Union[str, int]]],
|
controllers: Dict[str, Dict[str, Union[str, int]]],
|
||||||
delegated_pid: int,
|
delegated_pid: int,
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Returns the relative sub-paths the delegated roots of the V1 hierarchies, via the parsing
|
Returns the relative sub-paths the delegated roots of the V1 hierarchies, via the parsing
|
||||||
@ -1322,7 +1339,7 @@ class _CGroupV1Root(_CGroupV1):
|
|||||||
cls,
|
cls,
|
||||||
requested_controllers: Set[str],
|
requested_controllers: Set[str],
|
||||||
all_controllers: Dict[str, Dict[str, Union[str, int]]],
|
all_controllers: Dict[str, Dict[str, Union[str, int]]],
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Manually mounts the V1 split hierarchy on the target device. Occurs in the absence of systemd.
|
Manually mounts the V1 split hierarchy on the target device. Occurs in the absence of systemd.
|
||||||
@ -1355,7 +1372,9 @@ class _CGroupV1Root(_CGroupV1):
|
|||||||
yield mounted
|
yield mounted
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_available_v1_controllers(cls, controllers: Dict[str, Dict[str, Union[int,str]]]):
|
def _get_available_v1_controllers(
|
||||||
|
cls, controllers: Dict[str, Dict[str, Union[int, str]]]
|
||||||
|
):
|
||||||
|
|
||||||
unused_controllers = {
|
unused_controllers = {
|
||||||
controller: configuration
|
controller: configuration
|
||||||
@ -1372,7 +1391,7 @@ class _CGroupV1Root(_CGroupV1):
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def _systemd_online_setup(
|
def _systemd_online_setup(
|
||||||
cls,
|
cls,
|
||||||
target: Target,
|
target: LinuxTarget,
|
||||||
requested_controllers: Set[str],
|
requested_controllers: Set[str],
|
||||||
all_controllers: Dict[str, Dict[str, str]],
|
all_controllers: Dict[str, Dict[str, str]],
|
||||||
):
|
):
|
||||||
@ -1409,7 +1428,7 @@ class _CGroupV1Root(_CGroupV1):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _mount_filesystem(cls, target: Target, requested_controllers: Set[str]):
|
def _mount_filesystem(cls, target: LinuxTarget, requested_controllers: Set[str]):
|
||||||
"""
|
"""
|
||||||
A context manager which Mounts/Sets-up a V1 split hierarchy on the target device, covering contexts where
|
A context manager which Mounts/Sets-up a V1 split hierarchy on the target device, covering contexts where
|
||||||
systemd is both present and absent. This context manager Mounts/Sets-up a split V1 hierarchy (if possible)
|
systemd is both present and absent. This context manager Mounts/Sets-up a split V1 hierarchy (if possible)
|
||||||
@ -1447,7 +1466,7 @@ class _CGroupV1Root(_CGroupV1):
|
|||||||
with cm as controllers:
|
with cm as controllers:
|
||||||
yield controllers
|
yield controllers
|
||||||
|
|
||||||
def __init__(self, mount_point: str, target: Target):
|
def __init__(self, mount_point: str, target: LinuxTarget):
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
# Root name is null. Isn't required.
|
# Root name is null. Isn't required.
|
||||||
@ -1479,7 +1498,7 @@ class _TreeBase(ABC):
|
|||||||
|
|
||||||
:param name: The name assigned to the tree node.
|
:param name: The name assigned to the tree node.
|
||||||
:type name: str
|
:type name: str
|
||||||
|
|
||||||
:param is_threaded: Whether the node is threaded or not.
|
:param is_threaded: Whether the node is threaded or not.
|
||||||
:type is_threaded: bool
|
:type is_threaded: bool
|
||||||
"""
|
"""
|
||||||
@ -1592,8 +1611,8 @@ class RequestTree(_TreeBase):
|
|||||||
their respective to be assigned values, , defaults to ``None``.
|
their respective to be assigned values, , defaults to ``None``.
|
||||||
:type controllers: Dict[str, Dict[str, Union[str,int]]], optional
|
:type controllers: Dict[str, Dict[str, Union[str,int]]], optional
|
||||||
|
|
||||||
:param is_threaded: defines whether the object will represent a CGroup capable of managing threads, defaults to ``False``.
|
:param threaded: defines whether the object will represent a CGroup capable of managing threads, defaults to ``False``.
|
||||||
:type is_threaded: bool, optional
|
:type threaded: bool, optional
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -1648,7 +1667,7 @@ class RequestTree(_TreeBase):
|
|||||||
return list(self.children)
|
return list(self.children)
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def setup_hierarchy(self, version: int, target: Target):
|
def setup_hierarchy(self, version: int, target: LinuxTarget):
|
||||||
"""
|
"""
|
||||||
A context manager which processes the user defined hierarchy and sets-up said hierarchy on the ``target`` device.
|
A context manager which processes the user defined hierarchy and sets-up said hierarchy on the ``target`` device.
|
||||||
Uses an internal exit stack to the handle the entering and safe exiting of the lower level
|
Uses an internal exit stack to the handle the entering and safe exiting of the lower level
|
||||||
|
Loading…
x
Reference in New Issue
Block a user