From c468bb45ef81c2bb3b1967122e21371214ad3d70 Mon Sep 17 00:00:00 2001 From: Tomas Peterka Date: Mon, 22 May 2017 08:54:30 -0400 Subject: [PATCH 1/3] Construct slapos tree rather in ../cgroups/slapos/ --- slapos/format.py | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/slapos/format.py b/slapos/format.py index de36f4a22..31b394ffa 100644 --- a/slapos/format.py +++ b/slapos/format.py @@ -477,6 +477,64 @@ class Computer(object): command = 'ip address add dev %s fd00::1/64' % interface_name callAndRead(command.split()) + @property + def software_gid(self): + """Return GID for self.software_user. + + Has to be dynamic because __init__ happens before ``construct`` where we + effectively create the user and group.""" + return pwd.getpwnam(self.software_user)[3] + + + def _prepare_cgroups_folder(self, folder): + """If-Create folder and set group write permission.""" + if not os.path.exists(folder): + os.mkdir(folder) + os.chown(folder, -1, self.software_gid) + return folder + + + def _prepare_cgroups_cpuset(self, base_path, group): + """Create cgroups folder per-CPU with exclusive access to the CPU. + + Those folders are "``base_path``/cpuset/cpu". + """ + with open("/sys/fs/cgroup/cpuset/cpuset.cpus", "rt") as cpu_def: + # build up cpu_list of available CPU IDs + cpu_list = [] # types: list[int] + for cpu_def_split in cpu_def.read().strip().split(","): + # IDs can be in form "0-4" or "0,1,2,3,4" + if "-" in cpu_def_split: + a, b = map(int, cpu_def_split.split("-")) + cpu_list.extend(range(a, b + 1)) # because cgroups' range is inclusive + continue + cpu_list.append(int(cpu_def_split)) + + # For every CPU ID create an exclusive cgroup + for cpu in cpu_list: + cpu_path = self._prepare_cgroups_folder( + os.path.join(base_path, "cpu" + str(cpu))) + with open(cpu_path + "/cpuset.cpus", "wt") as fx: + fx.write(str(cpu)) # this cgroup manages only this cpu + with open(cpu_path + "/cpuset.cpu_exclusive", "wt") as fx: + fx.write("1") # manages it exclusively + os.chown(cpu_path + "/tasks", -1, self.software_gid) + + def _prepare_cgroups(self): + """Build CGROUPS tree exclusively for slapos. + + - Create hierarchy of CPU sets so that every partition can have exclusive + hold of one of the CPUs. + """ + base_path = self._prepare_cgroups_folder("/sys/fs/cgroup/slapos") + + # If cgroups-cpuset is present create exclusive cpusets "cpuN" per CPU + if os.path.exists("/sys/fs/cgroup/cpuset/cpuset.cpus"): + self._prepare_cgroups_cpuset( + self._prepare_cgroups_folder( + os.path.join(base_path, "cpuset"))) + + def construct(self, alter_user=True, alter_network=True, create_tap=True, use_unique_local_address_block=False): """ Construct the computer object as it is. @@ -506,6 +564,9 @@ class Computer(object): os.chown(slapsoft.path, slapsoft_pw.pw_uid, slapsoft_pw.pw_gid) os.chmod(self.software_root, 0o755) + # Build own CGROUPS tree for resource control + self._prepare_cgroups() + # get list of instance external storage if exist instance_external_list = [] if self.instance_storage_home: -- 2.30.9 From 2d942896e9be603ddc4e6e0065bd521ce08fe09a Mon Sep 17 00:00:00 2001 From: Tomas Peterka Date: Mon, 22 May 2017 09:13:26 -0400 Subject: [PATCH 2/3] cgroup-cpuset work only inside itself --- slapos/format.py | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/slapos/format.py b/slapos/format.py index 31b394ffa..2e3379bd9 100644 --- a/slapos/format.py +++ b/slapos/format.py @@ -486,7 +486,7 @@ class Computer(object): return pwd.getpwnam(self.software_user)[3] - def _prepare_cgroups_folder(self, folder): + def _prepare_cgroup_folder(self, folder): """If-Create folder and set group write permission.""" if not os.path.exists(folder): os.mkdir(folder) @@ -494,11 +494,15 @@ class Computer(object): return folder - def _prepare_cgroups_cpuset(self, base_path, group): - """Create cgroups folder per-CPU with exclusive access to the CPU. + def _prepare_cgroup_cpuset(self): + """Create cgroup folder per-CPU with exclusive access to the CPU. - Those folders are "``base_path``/cpuset/cpu". + Those folders are "/sys/fs/cgroup/cpuset/cpu". """ + if not os.path.exists("/sys/fs/cgroup/cpuset/cpuset.cpus"): + self.logger.warining("Cannot prepare CGROUP CPUSET - not supported by current OS") + return + with open("/sys/fs/cgroup/cpuset/cpuset.cpus", "rt") as cpu_def: # build up cpu_list of available CPU IDs cpu_list = [] # types: list[int] @@ -506,33 +510,28 @@ class Computer(object): # IDs can be in form "0-4" or "0,1,2,3,4" if "-" in cpu_def_split: a, b = map(int, cpu_def_split.split("-")) - cpu_list.extend(range(a, b + 1)) # because cgroups' range is inclusive + cpu_list.extend(range(a, b + 1)) # because cgroup's range is inclusive continue cpu_list.append(int(cpu_def_split)) # For every CPU ID create an exclusive cgroup for cpu in cpu_list: - cpu_path = self._prepare_cgroups_folder( - os.path.join(base_path, "cpu" + str(cpu))) + cpu_path = self._prepare_cgroup_folder( + os.path.join("/sys/fs/cgroup/cpuset/", "cpu" + str(cpu))) with open(cpu_path + "/cpuset.cpus", "wt") as fx: fx.write(str(cpu)) # this cgroup manages only this cpu with open(cpu_path + "/cpuset.cpu_exclusive", "wt") as fx: fx.write("1") # manages it exclusively os.chown(cpu_path + "/tasks", -1, self.software_gid) - def _prepare_cgroups(self): - """Build CGROUPS tree exclusively for slapos. + + def prepare_cgroup(self): + """Build CGROUP tree exclusively for slapos. - Create hierarchy of CPU sets so that every partition can have exclusive hold of one of the CPUs. """ - base_path = self._prepare_cgroups_folder("/sys/fs/cgroup/slapos") - - # If cgroups-cpuset is present create exclusive cpusets "cpuN" per CPU - if os.path.exists("/sys/fs/cgroup/cpuset/cpuset.cpus"): - self._prepare_cgroups_cpuset( - self._prepare_cgroups_folder( - os.path.join(base_path, "cpuset"))) + self._prepare_cgroup_cpuset() def construct(self, alter_user=True, alter_network=True, create_tap=True, use_unique_local_address_block=False): @@ -565,7 +564,7 @@ class Computer(object): os.chmod(self.software_root, 0o755) # Build own CGROUPS tree for resource control - self._prepare_cgroups() + self.prepare_cgroup() # get list of instance external storage if exist instance_external_list = [] -- 2.30.9 From 2c7e2a3e13439debd736a5aca8c4cbd3253dc7bc Mon Sep 17 00:00:00 2001 From: Tomas Peterka Date: Thu, 1 Jun 2017 06:08:25 -0400 Subject: [PATCH 3/3] Group writeable cgroup task file --- slapos/format.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slapos/format.py b/slapos/format.py index 2e3379bd9..d954d222c 100644 --- a/slapos/format.py +++ b/slapos/format.py @@ -523,6 +523,7 @@ class Computer(object): with open(cpu_path + "/cpuset.cpu_exclusive", "wt") as fx: fx.write("1") # manages it exclusively os.chown(cpu_path + "/tasks", -1, self.software_gid) + os.chmod(cpu_path + "/tasks", 0o664) def prepare_cgroup(self): -- 2.30.9