From 612e39d3af2ddbf15dc06342f8814b6b094ee1cc Mon Sep 17 00:00:00 2001 From: gAmitFrenkel Date: Thu, 22 Aug 2024 16:30:26 +0300 Subject: [PATCH 1/2] K8s container annotations (#260) * create a k8s container class to add container annotations that are k8s specific --------- Co-authored-by: Oren de Lame --- granulate_utils/containers/cri.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/granulate_utils/containers/cri.py b/granulate_utils/containers/cri.py index 995aa2b4..88861573 100644 --- a/granulate_utils/containers/cri.py +++ b/granulate_utils/containers/cri.py @@ -17,8 +17,9 @@ import json from contextlib import contextmanager, suppress +from dataclasses import dataclass, field from datetime import datetime, timezone -from typing import Any, List, Optional, Type, TypeVar +from typing import Any, Dict, List, Optional, Type, TypeVar import grpc # type: ignore # no types-grpc sadly import psutil @@ -122,7 +123,7 @@ def _create_container( with suppress(psutil.NoSuchProcess): process = psutil.Process(pid) - return Container( + return K8sContainer( runtime=self.runtime_name, name=self._reconstruct_name(container), id=container.id, @@ -130,6 +131,7 @@ def _create_container( running=container.state == self.api.api_pb2.CONTAINER_RUNNING, process=process, time_info=time_info, + annotations=container.annotations, ) @@ -182,3 +184,8 @@ def get_container(self, container_id: str, all_info: bool) -> Container: def get_runtimes(self) -> List[str]: return [client.runtime_name for client in self._clients] + + +@dataclass +class K8sContainer(Container): + annotations: Dict[str, str] = field(default_factory=dict) From 8f8b3d6546db35556b683bbaaba0a077a256f2e2 Mon Sep 17 00:00:00 2001 From: Amit Frenkel Date: Sun, 25 Aug 2024 16:09:58 +0300 Subject: [PATCH 2/2] Enter process ns utility (#259) --- granulate_utils/linux/ns.py | 43 ++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/granulate_utils/linux/ns.py b/granulate_utils/linux/ns.py index 1be5a970..8d29e93b 100644 --- a/granulate_utils/linux/ns.py +++ b/granulate_utils/linux/ns.py @@ -246,27 +246,13 @@ def run_in_ns( for ns in nstypes: assert_ns_str(ns) - # make sure "mnt" is last, once we change it our /proc is gone - nstypes = sorted(nstypes, key=lambda ns: 1 if ns == "mnt" else 0) ret: Union[T, _Sentinel] = _SENTINEL exc: Optional[BaseException] = None def _switch_and_run(): try: - global libc - if libc is None: - libc = ctypes.CDLL("libc.so.6") - - for nstype in nstypes: - if not is_same_ns(target_pid, nstype): - flag = NsType[nstype].value - if libc.unshare(flag) != 0: - raise ValueError(f"Failed to unshare({nstype})") - - with open(f"/proc/{target_pid}/ns/{nstype}", "r") as nsf: - if libc.setns(nsf.fileno(), flag) != 0: - raise ValueError(f"Failed to setns({nstype}) (to pid {target_pid})") + enter_process_ns(nstypes, target_pid) nonlocal ret ret = callback() @@ -363,3 +349,30 @@ def get_host_pid(nspid: int, container_id: str) -> Optional[int]: continue return None + + +def enter_process_ns( + nstypes: List[str], + target_pid: int = 1, +) -> None: + """ + Swaps to a set of the namespaces of a target process. + """ + for ns in nstypes: + assert_ns_str(ns) + # make sure "mnt" is last, once we change it our /proc is gone + nstypes = sorted(nstypes, key=lambda ns: 1 if ns == "mnt" else 0) + + global libc + if libc is None: + libc = ctypes.CDLL("libc.so.6") + + for nstype in nstypes: + if not is_same_ns(target_pid, nstype): + flag = NsType[nstype].value + if libc.unshare(flag) != 0: + raise ValueError(f"Failed to unshare({nstype})") + + with open(f"/proc/{target_pid}/ns/{nstype}", "r") as nsf: + if libc.setns(nsf.fileno(), flag) != 0: + raise ValueError(f"Failed to setns({nstype}) (to pid {target_pid})")