def test(config): result = consts.TEST_PASSED cause = None for entry in TABLE: try: Cgroup.xset(config, cgname=CGNAME, setting=entry[0], value=entry[1], version=entry[2]) except RunError as re: if re.stderr.find('Invalid argument') >= 0: # The kernel disallowed this setting, likely due to the many # complexities of exclusive cpusets continue raise re out = Cgroup.xget(config, cgname=CGNAME, setting=entry[3], version=entry[5], values_only=True, print_headers=False) if out != entry[4]: result = consts.TEST_FAILED cause = ( 'After setting {}={}, expected {}={}, but received ' '{}={}' ''.format(entry[0], entry[1], entry[3], entry[4], entry[3], out) ) return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None ret = Cgroup.configparser(config, cghelp=True) if 'Parse and load the specified cgroups' not in ret: result = consts.TEST_FAILED cause = 'Failed to print cgconfigparser help text' return result, cause try: Cgroup.configparser(config, load_file=CONFIG_FILE_NAME) except RunError as re: if 'Invalid argument' not in re.stderr: result = consts.TEST_FAILED cause = "Expected 'Invalid argument' to be in stderr" return result, cause if re.ret != 96: result = consts.TEST_FAILED cause = 'Expected return code of 96 but received {}'.format(re.ret) return result, cause else: result = consts.TEST_FAILED cause = 'Test case erroneously passed' return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None for entry in TABLE: Cgroup.xset(config, cgname=CGNAME, setting=entry[0], value=entry[1], version=entry[2]) out = Cgroup.xget(config, cgname=CGNAME, setting=entry[3], version=entry[5], values_only=True, print_headers=False) if out != entry[4]: result = consts.TEST_FAILED cause = ('After setting {}={}, expected {}={}, but received ' '{}={}'.format(entry[0], entry[1], entry[3], entry[4], entry[3], out)) return result, cause return result, cause
def test(config): Cgroup.set(config, cgname=CGNAME, setting=SETTINGS, value=VALUES) for i, setting in enumerate(SETTINGS): Cgroup.get_and_validate(config, CGNAME, setting, VALUES[i]) return consts.TEST_PASSED, None
def test(config): Cgroup.set(config, cgname=DST_CGNAME, copy_from=SRC_CGNAME) for i, setting in enumerate(SETTINGS): Cgroup.get_and_validate(config, DST_CGNAME, setting, VALUES[i]) return consts.TEST_PASSED, None
def create_process_in_cgroup(self, config, controller, cgname, cgclassify=True): if cgclassify: child_pid = self.create_process(config) Cgroup.classify(config, controller, cgname, child_pid) else: # use cgexec # To allow for multiple processes to be created, each new process # sleeps for a different amount of time. This lets us uniquely # find each process later in this function sleep_time = len(self.children) + 1 p = mp.Process(target=Process.__cgexec_infinite_loop, args=( config, controller, cgname, sleep_time, )) p.start() self.children.append(p)
def in_my_cgroup(): """ Function to add new process into the cgroup """ pid = os.getpid() cg = Cgroup('level_201') cg.add_task(pid)
def setup(config): user_name = Run.run('whoami', shell_bool=True) group_name = Run.run('groups', shell_bool=True).split(' ')[0] CgroupCli.create(config, controller_list=CONTROLLER, cgname=PARENT_NAME, user_name=user_name, group_name=group_name)
def teardown(config): pids = Cgroup.get_pids_in_cgroup(config, CGNAME, CONTROLLER) if pids: for p in pids.splitlines(): if config.args.container: config.container.run(['kill', '-9', p]) else: Run.run(['sudo', 'kill', '-9', p]) Cgroup.delete(config, CONTROLLER, CGNAME)
def setup(config): Cgroup.create(config, CONTROLLER, PARENT_CGNAME) Cgroup.create(config, CONTROLLER, os.path.join(PARENT_CGNAME, CHILD_CGNAME)) Cgroup.create(config, CONTROLLER, os.path.join(PARENT_CGNAME, CHILD_CGNAME, GRANDCHILD_CGNAME)) Cgroup.create(config, CONTROLLER, SIBLING_CGNAME) Cgroup.create(config, CONTROLLER, os.path.join(SIBLING_CGNAME, SIBLING_CHILD_CGNAME))
def __cgexec_infinite_loop(config, controller, cgname, sleep_time=1): cmd = [ "/usr/bin/perl", "-e", "'while(1){{sleep({})}};'".format(sleep_time) ] try: Cgroup.cgexec(config, controller, cgname, cmd) except RunError: # When this process is killed, it will throw a run error. # Ignore it. pass
def test(config): result = consts.TEST_PASSED cause = None expected = Cgroup.snapshot_to_dict(CGSNAPSHOT) actual = Cgroup.snapshot(config, controller=CONTROLLER) if expected[CGNAME].controllers[CONTROLLER] != \ actual[CGNAME].controllers[CONTROLLER]: result = consts.TEST_FAILED cause = 'Expected cgsnapshot result did not equal actual cgsnapshot' return result, cause
def test(config): result = consts.TEST_PASSED cause = None Cgroup.create(config, None, CGNAME) # verify the cgroup exists by reading cgroup.procs Cgroup.get( config, controller=None, cgname=CGNAME, setting='cgroup.procs', print_headers=True, values_only=False ) return result, cause
def teardown(config): os.remove(CONFIG_FILE_NAME) try: if config.args.container: config.container.run(['userdel', USER]) config.container.run(['groupdel', GROUP]) else: Run.run(['sudo', 'userdel', USER]) Run.run(['sudo', 'groupdel', GROUP]) except (ContainerError, RunError, ValueError): pass Cgroup.delete(config, CONTROLLER, CGNAME)
def test(config): Cgroup.configparser(config, load_file=CONFIG_FILE_NAME) Cgroup.get_and_validate(config, CGNAME, 'cpu.cfs_period_us', CFS_PERIOD) Cgroup.get_and_validate(config, CGNAME, 'cpu.cfs_quota_us', CFS_QUOTA) Cgroup.get_and_validate(config, CGNAME, 'cpu.shares', SHARES) return consts.TEST_PASSED, None
def test(config): result = consts.TEST_PASSED cause = None out = Cgroup.get(config, controller=None, cgname=CGNAME, setting=SETTING, print_headers=True, values_only=False) # arbitrary check to ensure we read several lines if len(out.splitlines()) < 10: result = consts.TEST_FAILED cause = ('Expected multiple lines, but only received {}' ''.format(len(out.splitlines()))) return result, cause # arbitrary check for a setting that's in both cgroup v1 and cgroup v2 # memory.stat if '\tunevictable' not in out: result = consts.TEST_FAILED cause = 'Unexpected output\n{}'.format(out) return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None out = Cgroup.get(config, cgname=CGNAME, all_controllers=True) # arbitrary check to ensure we read several lines if len(out.splitlines()) < 20: result = consts.TEST_FAILED cause = ('Expected multiple lines, but only received {}' ''.format(len(out.splitlines()))) return result, cause # arbitrary check for a setting that's in both cgroup v1 and cgroup v2 # memory.stat if '\tpgmajfault' not in out: result = consts.TEST_FAILED cause = 'Unexpected output\n{}'.format(out) return result, cause # make sure that a cpuset value was in the output: if 'cpuset.cpus' not in out: result = consts.TEST_FAILED cause = 'Failed to find cpuset settings in output\n{}'.format(out) return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None version = CgroupVersion.get_version(CONTROLLER) if version == CgroupVersion.CGROUP_V1: setting = SETTING_V1 expected_out = EXPECTED_OUT_V1 elif version == CgroupVersion.CGROUP_V2: setting = SETTING_V2 expected_out = EXPECTED_OUT_V2 out = Cgroup.get(config, controller=None, cgname=[CGNAME1, CGNAME2], setting=setting) for line_num, line in enumerate(out.splitlines()): if line.strip() != expected_out.splitlines()[line_num].strip(): result = consts.TEST_FAILED cause = ('Expected line:\n\t{}\nbut received line:\n\t{}' ''.format(expected_out.splitlines()[line_num].strip(), line.strip())) return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None cg1 = Cgroup(CGNAME, Version.CGROUP_V1) cg1.add_controller(CONTROLLER) cg1.add_setting(SETTING1, VALUE1) cg1.cgxset() value_v1 = CgroupCli.xget( config, setting=SETTING1, print_headers=False, values_only=True, version=CgroupCliVersion.CGROUP_V1, cgname=CGNAME ) if value_v1 != VALUE1: result = consts.TEST_FAILED cause = 'Expected {}, but received {}'.format(VALUE1, value_v1) return result, cause # Set the cpu.shares/cpu.weight to an arbitrary value to ensure # the following v2 cgxset works properly CgroupCli.xset(config, cgname=CGNAME, setting=SETTING1, value='1234', version=CgroupCliVersion.CGROUP_V1) cg2 = Cgroup(CGNAME, Version.CGROUP_V2) cg2.add_controller(CONTROLLER) cg2.add_setting(SETTING2, VALUE2) cg2.cgxset() value_v2 = CgroupCli.xget( config, setting=SETTING2, print_headers=False, values_only=True, version=CgroupCliVersion.CGROUP_V2, cgname=CGNAME ) if value_v2 != VALUE2: result = consts.TEST_FAILED cause = 'Expected {}, but received {}'.format(VALUE2, value_v2) return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None Cgroup.configparser(config, load_file=CONFIG_FILE_NAME, dflt_usr=USER, dflt_grp=GROUP, dperm=DPERM, fperm=FPERM) mnt_path = Cgroup.get_controller_mount_point(CONTROLLER) cpus_path = os.path.join(mnt_path, CGNAME, 'cpuset.cpus') user = utils.get_file_owner_username(config, cpus_path) group = utils.get_file_owner_group_name(config, cpus_path) if user != USER: result = consts.TEST_FAILED cause = ('Owner name failed. Expected {}, received {}\n' ''.format(USER, user)) return result, cause if group != GROUP: result = consts.TEST_FAILED cause = ('Owner group failed. Expected {}, received {}\n' ''.format(GROUP, group)) return result, cause fperm = utils.get_file_permissions(config, cpus_path) if fperm != FPERM: result = consts.TEST_FAILED cause = ('File permissions failed. Expected {}, received {}\n' ''.format(FPERM, fperm)) return result, cause dperm = utils.get_file_permissions(config, os.path.join(mnt_path, CGNAME)) if dperm != DPERM: result = consts.TEST_FAILED cause = ('Directory permissions failed. Expected {}, received {}\n' ''.format(DPERM, dperm)) return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None mount_list = Cgroup.get_cgroup_mounts(config, expand_v2_mounts=True) # cgroup v2 mounts won't show up unless '-a' is specified lssubsys_list = Cgroup.lssubsys(config, ls_all=True) for mount in mount_list: if mount.controller == 'name=systemd' or mount.controller == 'systemd': continue found = False for lsmount in lssubsys_list.splitlines(): if ',' in lsmount: for ctrl in lsmount.split(','): if ctrl == mount.controller: found = True break if lsmount == mount.controller: found = True break if lsmount == 'blkio' and mount.controller == 'io': found = True break if not found: result = consts.TEST_FAILED cause = ('Failed to find {} in lssubsys list' ''.format(mount.controller)) return result, cause ret = Cgroup.lssubsys(config, cghelp=True) if 'Usage:' not in ret: result = consts.TEST_FAILED cause = 'Failed to print help text' return result, cause return result, cause
def create_threaded_process_in_cgroup(self, config, controller, cgname, threads=2, cgclassify=True): p = mp.Process(target=self.create_threaded_process, args=( config, threads, )) p.start() if cgclassify: Cgroup.classify(config, controller, cgname, p.pid) self.children.append(p) self.children_pids.append(p.pid) return p.pid
def test(config): result = consts.TEST_PASSED cause = None try: # check if the memsw.failcnt file exists. if so, add it to the # expected snapshot Cgroup.get(config, setting='memory.memsw.failcnt', cgname=CGNAME) expected_str = CGSNAPSHOT + CGSNAPSHOT_SWAP except RunError: # memsw files don't exist. exclude them from the snapshot expected_str = CGSNAPSHOT + CGSNAPSHOT_NOSWAP expected = Cgroup.snapshot_to_dict(expected_str) actual = Cgroup.snapshot(config, controller=CONTROLLER) if expected[CGNAME] != actual[CGNAME]: result = consts.TEST_FAILED cause = 'Expected cgsnapshot result did not equal actual cgsnapshot' return result, cause
def setup(config): Cgroup.create(config, CONTROLLER, PARENT_CGNAME) Cgroup.create(config, CONTROLLER, os.path.join(PARENT_CGNAME, CHILD_CGNAME)) Cgroup.set_cgrules_conf(config, CGRULE, append=False) cg.start_cgrules(config)
def test(config): Cgroup.set(config, cgname=[CGNAME1, CGNAME2], setting=SETTING, value=VALUE) Cgroup.get_and_validate(config, CGNAME1, SETTING, VALUE) Cgroup.get_and_validate(config, CGNAME2, SETTING, VALUE) return consts.TEST_PASSED, None
def test(config): result = consts.TEST_PASSED cause = None Cgroup.configparser(config, load_file=CONFIG_FILE_NAME, tperm=TPERM, tasks_usr=USER, tasks_grp=GROUP) mnt_path = Cgroup.get_controller_mount_point(CONTROLLER) tasks_path = os.path.join(mnt_path, CGNAME, 'tasks') user = utils.get_file_owner_username(config, tasks_path) group = utils.get_file_owner_group_name(config, tasks_path) if user != USER: result = consts.TEST_FAILED cause = ( 'Owner name failed. Expected {}, received {}\n' ''.format(USER, user) ) return result, cause if group != GROUP: result = consts.TEST_FAILED cause = ( 'Owner group failed. Expected {}, received {}\n' ''.format(GROUP, group) ) return result, cause tperm = utils.get_file_permissions(config, tasks_path) if tperm != TPERM: result = consts.TEST_FAILED cause = ( 'File permissions failed. Expected {}, received {}\n' ''.format(TPERM, tperm) ) return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None try: Cgroup.delete(config, CONTROLLER2, CGNAME) except RunError as re: if 'No such file or directory' in re.stderr: cause = 'cpu and cpuacct controllers do not share mount points.' result = consts.TEST_FAILED else: raise re try: Cgroup.delete(config, CONTROLLER1, CGNAME) except RunError as re: if 'No such file or directory' in re.stderr: cause = 'Missing support to delete cgroup on shared mount points.' result = consts.TEST_FAILED else: raise re return result, cause
def test(config): config.process.create_process_in_cgroup(config, CONTROLLER, CGNAME, cgclassify=False) pids = Cgroup.get_pids_in_cgroup(config, CGNAME, CONTROLLER) if pids is None: result = consts.TEST_FAILED cause = 'No processes were found in cgroup {}'.format(CGNAME) return result, cause # run cgexec -h ret = Cgroup.cgexec(config, controller=CONTROLLER, cgname=CGNAME, cmdline=None, cghelp=True) if 'Run the task in given control group(s)' not in ret: result = consts.TEST_FAILED cause = 'Failed to print cgexec help text: {}'.format(ret) return result, cause return consts.TEST_PASSED, None
def test(config): result = consts.TEST_PASSED cause = None out = Cgroup.lscgroup(config, controller=[CONTROLLER, CONTROLLER], path=[PARENT_CGNAME, SIBLING_CGNAME]) if out != EXPECTED_OUT1: result = consts.TEST_FAILED cause = ( "Expected lscgroup output doesn't match received output\n" "Expected:\n{}\n" "Received:\n{}\n" "".format(utils.indent(EXPECTED_OUT1, 4), utils.indent(out, 4)) ) return result, cause ret = Cgroup.lscgroup(config, cghelp=True) if 'Usage:' not in ret: result = consts.TEST_FAILED cause = 'Failed to print help text' return result, cause return result, cause
def test(config): result = consts.TEST_PASSED cause = None out = Cgroup.lscgroup(config, controller=CONTROLLER, path=PARENT_CGNAME) if out != EXPECTED_OUT1: result = consts.TEST_FAILED cause = ("Expected lscgroup output doesn't match received output\n'" "Expected:\n{}\n" "Received:\n{}\n" "".format(utils.indent(EXPECTED_OUT1, 4), utils.indent(out, 4))) return result, cause return result, cause
def addCgroups(self): for cgroupName in self.configure.get("cgroup"): cgroup = Cgroup(cgroupName,self.id,self.configure) cgroup.initialize() self.cgroups[cgroupName]=cgroup