blob: ff930fa56f54d725f02610a21adcb8a3bd6b8a55 [file] [log] [blame]
Sergei Trofimov4e6afe92015-10-09 09:30:04 +01001# Copyright 2014-2015 ARM Limited
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15# pylint: disable=attribute-defined-outside-init
16import logging
17from collections import namedtuple
18
19from devlib.module import Module
20from devlib.exception import TargetError
21from devlib.utils.misc import list_to_ranges, isiterable
22from devlib.utils.types import boolean
23
24
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000025class Controller(object):
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010026
Patrick Bellasib569a562016-11-29 10:39:28 +000027 def __init__(self, kind, hid, clist):
28 """
29 Initialize a controller given the hierarchy it belongs to.
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010030
Patrick Bellasib569a562016-11-29 10:39:28 +000031 :param kind: the name of the controller
32 :type kind: str
33
34 :param hid: the Hierarchy ID this controller is mounted on
35 :type hid: int
36
37 :param clist: the list of controller mounted in the same hierarchy
38 :type clist: list(str)
39 """
40 self.mount_name = 'devlib_cgh{}'.format(hid)
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000041 self.kind = kind
Patrick Bellasib569a562016-11-29 10:39:28 +000042 self.hid = hid
43 self.clist = clist
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000044 self.target = None
Patrick Bellasi15f9c032016-04-26 15:23:56 +010045 self._noprefix = False
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000046
Patrick Bellasib569a562016-11-29 10:39:28 +000047 self.logger = logging.getLogger('CGroup.'+self.kind)
48 self.logger.debug('Initialized [%s, %d, %s]',
49 self.kind, self.hid, self.clist)
50
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010051 self.mount_point = None
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000052 self._cgroups = {}
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010053
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000054 def mount(self, target, mount_root):
55
56 mounted = target.list_file_systems()
57 if self.mount_name in [e.device for e in mounted]:
58 # Identify mount point if controller is already in use
59 self.mount_point = [
60 fs.mount_point
61 for fs in mounted
62 if fs.device == self.mount_name
63 ][0]
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010064 else:
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000065 # Mount the controller if not already in use
66 self.mount_point = target.path.join(mount_root, self.mount_name)
67 target.execute('mkdir -p {} 2>/dev/null'\
68 .format(self.mount_point), as_root=True)
69 target.execute('mount -t cgroup -o {} {} {}'\
Patrick Bellasib569a562016-11-29 10:39:28 +000070 .format(','.join(self.clist),
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000071 self.mount_name,
72 self.mount_point),
73 as_root=True)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010074
Patrick Bellasi15f9c032016-04-26 15:23:56 +010075 # Check if this controller uses "noprefix" option
76 output = target.execute('mount | grep "{} "'.format(self.mount_name))
77 if 'noprefix' in output:
78 self._noprefix = True
79 # self.logger.debug('Controller %s using "noprefix" option',
80 # self.kind)
81
82 self.logger.debug('Controller %s mounted under: %s (noprefix=%s)',
83 self.kind, self.mount_point, self._noprefix)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010084
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000085 # Mark this contoller as available
86 self.target = target
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010087
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000088 # Create root control group
89 self.cgroup('/')
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010090
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000091 def cgroup(self, name):
92 if not self.target:
93 raise RuntimeError('CGroup creation failed: {} controller not mounted'\
94 .format(self.kind))
95 if name not in self._cgroups:
96 self._cgroups[name] = CGroup(self, name)
97 return self._cgroups[name]
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010098
Patrick Bellasi9c9a7482015-11-03 11:49:31 +000099 def exists(self, name):
100 if not self.target:
101 raise RuntimeError('CGroup creation failed: {} controller not mounted'\
102 .format(self.kind))
103 if name not in self._cgroups:
104 self._cgroups[name] = CGroup(self, name, create=False)
105 return self._cgroups[name].existe()
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100106
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000107 def list_all(self):
108 self.logger.debug('Listing groups for %s controller', self.kind)
109 output = self.target.execute('{} find {} -type d'\
Patrick Bellasi3acf5d52016-04-26 15:31:05 +0100110 .format(self.target.busybox, self.mount_point),
111 as_root=True)
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000112 cgroups = []
Patrick Bellasie2e5e682016-02-23 12:12:28 +0000113 for cg in output.splitlines():
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000114 cg = cg.replace(self.mount_point + '/', '/')
115 cg = cg.replace(self.mount_point, '/')
116 cg = cg.strip()
117 if cg == '':
118 continue
119 self.logger.debug('Populate %s cgroup: %s', self.kind, cg)
120 cgroups.append(cg)
121 return cgroups
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100122
Patrick Bellasi3cab7862016-08-26 16:27:23 +0100123 def move_tasks(self, source, dest, exclude=[]):
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100124 try:
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000125 srcg = self._cgroups[source]
126 dstg = self._cgroups[dest]
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100127 except KeyError as e:
128 raise ValueError('Unkown group: {}'.format(e))
Patrick Bellasi3cab7862016-08-26 16:27:23 +0100129 output = self.target._execute_util(
130 'cgroups_tasks_move {} {} \'{}\''.format(
131 srcg.directory, dstg.directory, exclude),
132 as_root=True)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100133
Patrick Bellasi21d18f82016-08-26 18:13:47 +0100134 def move_all_tasks_to(self, dest, exclude=[]):
135 """
136 Move all the tasks to the specified CGroup
137
138 Tasks are moved from all their original CGroup the the specified on.
139 The tasks which name matches one of the string in exclude are moved
140 instead in the root CGroup for the controller.
141 The name of a tasks to exclude must be a substring of the task named as
142 reported by the "ps" command. Indeed, this list will be translated into
143 a: "ps | grep -e name1 -e name2..." in order to obtain the PID of these
144 tasks.
145
146 :param exclude: list of commands to keep in the root CGroup
147 :type exlude: list(str)
148 """
149
150 if isinstance(exclude, str):
151 exclude = [exclude]
152 if not isinstance(exclude, list):
153 raise ValueError('wrong type for "exclude" parameter, '
154 'it must be a str or a list')
155
Patrick Bellasic8f118d2016-08-31 11:39:33 +0100156 logging.debug('Moving all tasks into %s', dest)
Patrick Bellasi21d18f82016-08-26 18:13:47 +0100157
158 # Build list of tasks to exclude
159 grep_filters = ''
160 for comm in exclude:
Brendan Jackman3dd4ea62016-11-25 16:04:34 +0000161 grep_filters += '-e {} '.format(comm)
Patrick Bellasic8f118d2016-08-31 11:39:33 +0100162 logging.debug(' using grep filter: %s', grep_filters)
Patrick Bellasi21d18f82016-08-26 18:13:47 +0100163 if grep_filters != '':
Patrick Bellasic8f118d2016-08-31 11:39:33 +0100164 logging.debug(' excluding tasks which name matches:')
165 logging.debug(' %s', ', '.join(exclude))
Patrick Bellasi21d18f82016-08-26 18:13:47 +0100166
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000167 for cgroup in self._cgroups:
168 if cgroup != dest:
Patrick Bellasi21d18f82016-08-26 18:13:47 +0100169 self.move_tasks(cgroup, dest, grep_filters)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100170
Patrick Bellasi42efd0a2016-08-26 16:25:43 +0100171 def tasks(self, cgroup):
172 try:
173 cg = self._cgroups[cgroup]
174 except KeyError as e:
175 raise ValueError('Unkown group: {}'.format(e))
176 output = self.target._execute_util(
177 'cgroups_tasks_in {}'.format(cg.directory),
178 as_root=True)
179 entries = output.splitlines()
180 tasks = {}
181 for task in entries:
182 tid = task.split(',')[0]
183 try:
184 tname = task.split(',')[1]
185 except: continue
186 try:
187 tcmdline = task.split(',')[2]
188 except:
189 tcmdline = ''
190 tasks[int(tid)] = (tname, tcmdline)
191 return tasks
192
Patrick Bellasid8ae3ab2016-08-26 16:28:45 +0100193 def tasks_count(self, cgroup):
194 try:
195 cg = self._cgroups[cgroup]
196 except KeyError as e:
197 raise ValueError('Unkown group: {}'.format(e))
198 output = self.target.execute(
199 '{} wc -l {}/tasks'.format(
200 self.target.busybox, cg.directory),
201 as_root=True)
202 return int(output.split()[0])
203
204 def tasks_per_group(self):
205 tasks = {}
206 for cg in self.list_all():
207 tasks[cg] = self.tasks_count(cg)
208 return tasks
209
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000210class CGroup(object):
211
212 def __init__(self, controller, name, create=True):
213 self.logger = logging.getLogger('cgroups.' + controller.kind)
214 self.target = controller.target
215 self.controller = controller
216 self.name = name
217
218 # Control cgroup path
219 self.directory = controller.mount_point
220 if name != '/':
221 self.directory = self.target.path.join(controller.mount_point, name[1:])
222
223 # Setup path for tasks file
224 self.tasks_file = self.target.path.join(self.directory, 'tasks')
225 self.procs_file = self.target.path.join(self.directory, 'cgroup.procs')
226
227 if not create:
228 return
229
Patrick Bellasi7112cfe2016-02-25 16:54:16 +0000230 self.logger.debug('Creating cgroup %s', self.directory)
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000231 self.target.execute('[ -d {0} ] || mkdir -p {0}'\
232 .format(self.directory), as_root=True)
233
234 def exists(self):
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100235 try:
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000236 self.target.execute('[ -d {0} ]'\
Patrick Bellasi3acf5d52016-04-26 15:31:05 +0100237 .format(self.directory), as_root=True)
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000238 return True
239 except TargetError:
240 return False
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100241
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000242 def get(self):
243 conf = {}
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100244
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000245 logging.debug('Reading %s attributes from:',
246 self.controller.kind)
247 logging.debug(' %s',
248 self.directory)
Patrick Bellasia65ff132016-02-23 12:11:06 +0000249 output = self.target._execute_util(
250 'cgroups_get_attributes {} {}'.format(
Patrick Bellasi3acf5d52016-04-26 15:31:05 +0100251 self.directory, self.controller.kind),
252 as_root=True)
Patrick Bellasia65ff132016-02-23 12:11:06 +0000253 for res in output.splitlines():
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000254 attr = res.split(':')[0]
255 value = res.split(':')[1]
256 conf[attr] = value
257
258 return conf
259
260 def set(self, **attrs):
261 for idx in attrs:
262 if isiterable(attrs[idx]):
263 attrs[idx] = list_to_ranges(attrs[idx])
264 # Build attribute path
Patrick Bellasi658005a2016-04-26 15:26:44 +0100265 if self.controller._noprefix:
266 attr_name = '{}'.format(idx)
267 else:
268 attr_name = '{}.{}'.format(self.controller.kind, idx)
269 path = self.target.path.join(self.directory, attr_name)
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000270
271 self.logger.debug('Set attribute [%s] to: %s"',
272 path, attrs[idx])
273
274 # Set the attribute value
Patrick Bellasi658005a2016-04-26 15:26:44 +0100275 try:
276 self.target.write_value(path, attrs[idx])
277 except TargetError:
278 # Check if the error is due to a non-existing attribute
279 attrs = self.get()
280 if idx not in attrs:
281 raise ValueError('Controller [{}] does not provide attribute [{}]'\
282 .format(self.controller.kind, attr_name))
283 raise
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000284
285 def get_tasks(self):
286 task_ids = self.target.read_value(self.tasks_file).split()
287 logging.debug('Tasks: %s', task_ids)
288 return map(int, task_ids)
289
Joel Fernandes53375252017-06-20 15:55:26 -0700290 # Used to insert fake cgroup attach events to know existing cgroup assignments
291 def trace_cgroup_tasks(self):
292 exec_cmd = "cgroup_trace_attach_task {} {} {}".format(self.controller.hid, self.directory, self.tasks_file)
293 self.target._execute_util(exec_cmd)
294
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000295 def add_task(self, tid):
296 self.target.write_value(self.tasks_file, tid, verify=False)
297
298 def add_tasks(self, tasks):
299 for tid in tasks:
300 self.add_task(tid)
301
302 def add_proc(self, pid):
303 self.target.write_value(self.procs_file, pid, verify=False)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100304
305CgroupSubsystemEntry = namedtuple('CgroupSubsystemEntry', 'name hierarchy num_cgroups enabled')
306
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100307class CgroupsModule(Module):
308
309 name = 'cgroups'
Patrick Bellasi616f2292016-05-13 18:17:22 +0100310 stage = 'setup'
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100311
312 @staticmethod
313 def probe(target):
Patrick Bellasi4b58c572016-04-26 15:33:23 +0100314 if not target.is_rooted:
315 return False
316 if target.file_exists('/proc/cgroups'):
317 return True
318 return target.config.has('cgroups')
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100319
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100320 def __init__(self, target):
321 super(CgroupsModule, self).__init__(target)
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000322
323 self.logger = logging.getLogger('CGroups')
324
Patrick Bellasib2ec9572016-11-29 10:02:57 +0000325 # Set Devlib's CGroups mount point
326 self.cgroup_root = target.path.join(
327 target.working_directory, 'cgroups')
328
Patrick Bellasi103f7922016-11-29 10:13:01 +0000329 # Get the list of the available controllers
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000330 subsys = self.list_subsystems()
Patrick Bellasi103f7922016-11-29 10:13:01 +0000331 if len(subsys) == 0:
332 self.logger.warning('No CGroups controller available')
333 return
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000334
Patrick Bellasib569a562016-11-29 10:39:28 +0000335 # Map hierarchy IDs into a list of controllers
336 hierarchy = {}
337 for ss in subsys:
338 try:
339 hierarchy[ss.hierarchy].append(ss.name)
340 except KeyError:
341 hierarchy[ss.hierarchy] = [ss.name]
342 self.logger.debug('Available hierarchies: %s', hierarchy)
343
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000344 # Initialize controllers
Patrick Bellasi103f7922016-11-29 10:13:01 +0000345 self.logger.info('Available controllers:')
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000346 self.controllers = {}
Patrick Bellasi103f7922016-11-29 10:13:01 +0000347 for ss in subsys:
Patrick Bellasib569a562016-11-29 10:39:28 +0000348 hid = ss.hierarchy
349 controller = Controller(ss.name, hid, hierarchy[hid])
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000350 try:
Patrick Bellasib2ec9572016-11-29 10:02:57 +0000351 controller.mount(self.target, self.cgroup_root)
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000352 except TargetError:
Patrick Bellasib569a562016-11-29 10:39:28 +0000353 message = 'Failed to mount "{}" controller'
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000354 raise TargetError(message.format(controller.kind))
Patrick Bellasib569a562016-11-29 10:39:28 +0000355 self.logger.info(' %-12s : %s', controller.kind,
356 controller.mount_point)
Patrick Bellasi103f7922016-11-29 10:13:01 +0000357 self.controllers[ss.name] = controller
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100358
359 def list_subsystems(self):
360 subsystems = []
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000361 for line in self.target.execute('{} cat /proc/cgroups'\
Patrick Bellasie2e5e682016-02-23 12:12:28 +0000362 .format(self.target.busybox)).splitlines()[1:]:
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100363 line = line.strip()
364 if not line or line.startswith('#'):
365 continue
366 name, hierarchy, num_cgroups, enabled = line.split()
367 subsystems.append(CgroupSubsystemEntry(name,
368 int(hierarchy),
369 int(num_cgroups),
370 boolean(enabled)))
371 return subsystems
372
373
Patrick Bellasi9c9a7482015-11-03 11:49:31 +0000374 def controller(self, kind):
375 if kind not in self.controllers:
376 self.logger.warning('Controller %s not available', kind)
377 return None
378 return self.controllers[kind]
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100379
Patrick Bellasib2ec9572016-11-29 10:02:57 +0000380 def run_into_cmd(self, cgroup, cmdline):
Brendan Jackmandbd12992017-01-12 16:34:34 +0000381 """
382 Get the command to run a command into a given cgroup
383
384 :param cmdline: Commdand to be run into cgroup
385 :param cgroup: Name of cgroup to run command into
386 :returns: A command to run `cmdline` into `cgroup`
387 """
Patrick Bellasib2ec9572016-11-29 10:02:57 +0000388 return 'CGMOUNT={} {} cgroups_run_into {} {}'\
389 .format(self.cgroup_root, self.target.shutils,
390 cgroup, cmdline)
391
Patrick Bellasi28739392016-04-22 11:43:49 +0100392 def run_into(self, cgroup, cmdline):
393 """
394 Run the specified command into the specified CGroup
Brendan Jackmandbd12992017-01-12 16:34:34 +0000395
396 :param cmdline: Command to be run into cgroup
397 :param cgroup: Name of cgroup to run command into
398 :returns: Output of command.
Patrick Bellasi28739392016-04-22 11:43:49 +0100399 """
Brendan Jackmand0e28f02017-01-12 16:38:12 +0000400 cmd = self.run_into_cmd(cgroup, cmdline)
Brendan Jackmande619372017-01-12 16:45:54 +0000401 raw_output = self.target.execute(cmd)
402
403 # First line of output comes from shutils; strip it out.
404 return raw_output.split('\n', 1)[1]
Patrick Bellasi28739392016-04-22 11:43:49 +0100405
406 def cgroups_tasks_move(self, srcg, dstg, exclude=''):
407 """
408 Move all the tasks from the srcg CGroup to the dstg one.
409 A regexps of tasks names can be used to defined tasks which should not
410 be moved.
411 """
412 return self.target._execute_util(
413 'cgroups_tasks_move {} {} {}'.format(srcg, dstg, exclude),
414 as_root=True)
415
Patrick Bellasi75a086d2016-08-26 16:29:43 +0100416 def isolate(self, cpus, exclude=[]):
417 """
418 Remove all userspace tasks from specified CPUs.
419
420 A list of CPUs can be specified where we do not want userspace tasks
421 running. This functions creates a sandbox cpuset CGroup where all
422 user-space tasks and not-pinned kernel-space tasks are moved into.
423 This should allows to isolate the specified CPUs which will not get
424 tasks running unless explicitely moved into the isolated group.
425
426 :param cpus: the list of CPUs to isolate
427 :type cpus: list(int)
428
429 :return: the (sandbox, isolated) tuple, where:
430 sandbox is the CGroup of sandboxed CPUs
431 isolated is the CGroup of isolated CPUs
432 """
433 all_cpus = set(range(self.target.number_of_cpus))
434 sbox_cpus = list(all_cpus - set(cpus))
435 isol_cpus = list(all_cpus - set(sbox_cpus))
436
437 # Create Sandbox and Isolated cpuset CGroups
438 cpuset = self.controller('cpuset')
439 sbox_cg = cpuset.cgroup('/DEVLIB_SBOX')
440 isol_cg = cpuset.cgroup('/DEVLIB_ISOL')
441
442 # Set CPUs for Sandbox and Isolated CGroups
443 sbox_cg.set(cpus=sbox_cpus, mems=0)
444 isol_cg.set(cpus=isol_cpus, mems=0)
445
446 # Move all currently running tasks to the Sandbox CGroup
447 cpuset.move_all_tasks_to('/DEVLIB_SBOX', exclude)
448
449 return sbox_cg, isol_cg
450
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100451 def freeze(self, exclude=[], thaw=False):
452 """
Patrick Bellasi730bb602016-08-31 11:40:10 +0100453 Freeze all user-space tasks but the specified ones
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100454
455 A freezer cgroup is used to stop all the tasks in the target system but
456 the ones which name match one of the path specified by the exclude
457 paramater. The name of a tasks to exclude must be a substring of the
458 task named as reported by the "ps" command. Indeed, this list will be
459 translated into a: "ps | grep -e name1 -e name2..." in order to obtain
460 the PID of these tasks.
461
462 :param exclude: list of commands paths to exclude from freezer
Patrick Bellasi730bb602016-08-31 11:40:10 +0100463 :type exclude: list(str)
464
465 :param thaw: if true thaw tasks instead
466 :type thaw: bool
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100467 """
468
469 # Create Freezer CGroup
470 freezer = self.controller('freezer')
Brendan Jackmanc89f7122016-11-25 11:56:42 +0000471 if freezer is None:
472 raise RuntimeError('freezer cgroup controller not present')
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100473 freezer_cg = freezer.cgroup('/DEVLIB_FREEZER')
Quentin Perret4b364392017-08-21 18:16:10 +0100474 cmd = 'cgroups_freezer_set_state {{}} {}'.format(freezer_cg.directory)
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100475
476 if thaw:
477 # Restart froozen tasks
Quentin Perret4b364392017-08-21 18:16:10 +0100478 freezer.target._execute_util(cmd.format('THAWED'), as_root=True)
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100479 # Remove all tasks from freezer
480 freezer.move_all_tasks_to('/')
481 return
482
483 # Move all tasks into the freezer group
484 freezer.move_all_tasks_to('/DEVLIB_FREEZER', exclude)
485
Patrick Bellasic8f118d2016-08-31 11:39:33 +0100486 # Get list of not frozen tasks, which is reported as output
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100487 tasks = freezer.tasks('/')
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100488
489 # Freeze all tasks
Quentin Perret4b364392017-08-21 18:16:10 +0100490 freezer.target._execute_util(cmd.format('FROZEN'), as_root=True)
Patrick Bellasi23ad61f2016-08-26 18:14:37 +0100491
Patrick Bellasic8f118d2016-08-31 11:39:33 +0100492 return tasks
493