def check_cgroup_availability(wait=1): """ Basic utility to check the availability and permissions of cgroups. This will log some warnings for the user if necessary. On some systems, daemons such as cgrulesengd might interfere with the cgroups of a process soon after it was started. Thus this function starts a process, waits a configurable amount of time, and check whether the cgroups have been changed. @param wait: a non-negative int that is interpreted as seconds to wait during the check @raise SystemExit: if cgroups are not usable """ logging.basicConfig(format="%(levelname)s: %(message)s") runexecutor = RunExecutor(use_namespaces=False) my_cgroups = runexecutor.cgroups if not ( CPUACCT in my_cgroups and CPUSET in my_cgroups # and FREEZER in my_cgroups # For now, we do not require freezer and MEMORY in my_cgroups ): sys.exit(1) with tempfile.NamedTemporaryFile(mode="rt") as tmp: runexecutor.execute_run( ["sh", "-c", "sleep {0}; cat /proc/self/cgroup".format(wait)], tmp.name, memlimit=1024 * 1024, # set memlimit to force check for swapaccount # set cores and memory_nodes to force usage of CPUSET cores=util.parse_int_list(my_cgroups.get_value(CPUSET, "cpus")), memory_nodes=my_cgroups.read_allowed_memory_banks(), ) lines = [] for line in tmp: line = line.strip() if ( line and not line == "sh -c 'sleep {0}; cat /proc/self/cgroup'".format(wait) and not all(c == "-" for c in line) ): lines.append(line) task_cgroups = find_my_cgroups(lines) fail = False for subsystem in CPUACCT, CPUSET, MEMORY, FREEZER: if subsystem in my_cgroups: if not task_cgroups[subsystem].startswith( os.path.join(my_cgroups[subsystem], "benchmark_") ): logging.warning( "Task was in cgroup %s for subsystem %s, " "which is not the expected sub-cgroup of %s. " "Maybe some other program is interfering with cgroup management?", task_cgroups[subsystem], subsystem, my_cgroups[subsystem], ) fail = True if fail: sys.exit(1)
def test_require_cgroup_invalid(self): with self.assertLogs(level=logging.ERROR) as log: with self.assertRaises(SystemExit): RunExecutor(additional_cgroup_subsystems=["invalid"]) self.assertIn( 'Cgroup subsystem "invalid" was required but is not available', "\n".join(log.output), )
def __init__(self, benchmark, my_cpus, my_memory_nodes, my_user, output_handler): threading.Thread.__init__(self) # constuctor of superclass self.benchmark = benchmark self.my_cpus = my_cpus self.my_memory_nodes = my_memory_nodes self.output_handler = output_handler self.run_executor = RunExecutor(user=my_user) self.setDaemon(True) self.start()
def setUp(self, *args, **kwargs): try: self.runexecutor = RunExecutor(use_namespaces=False, *args, **kwargs) except SystemExit as e: if str(e).startswith( "Cannot reliably kill sub-processes without freezer cgroup" ): self.skipTest(e) else: raise e
def __init__(self, benchmark, my_cpus, my_memory_nodes, output_handler, run_finished_callback): threading.Thread.__init__(self) # constuctor of superclass self.run_finished_callback = run_finished_callback self.benchmark = benchmark self.my_cpus = my_cpus self.my_memory_nodes = my_memory_nodes self.output_handler = output_handler self.run_executor = RunExecutor(**benchmark.config.containerargs) self.setDaemon(True) self.start()
def setUp(self, *args, **kwargs): try: container.execute_in_namespace(lambda: 0) except OSError as e: self.skipTest("Namespaces not supported: {}".format(os.strerror(e.errno))) self.runexecutor = RunExecutor( use_namespaces=True, dir_modes={"/": containerexecutor.DIR_READ_ONLY, "/tmp": containerexecutor.DIR_HIDDEN}, container_system_config=False, *args, **kwargs)
def run_exec_cmd( environment: Environment, cmd: Sequence[str], env: Mapping[str, str], cwd: Path, dir_modes: Mapping[str, Any], tmp_dir: Path, time_limit: int, mem_limit: int, ) -> Tuple[Tuple[str, ...], RunexecStats, str, str]: stdout = tmp_dir / "info.log" if stdout.exists(): stdout.unlink() stderr = tmp_dir / "error.log" if stderr.exists(): stderr.unlink() combined_cmd = combine_cmd(*environment.run(cmd, env, cwd)) stderr.write_text(" \\\n ".join( shlex.quote(part) for part in combined_cmd) + "\n\n") run_executor = RunExecutor( use_namespaces=False, # dir_modes=dir_modes, # network_access=True, # Need to system config so DNS works. # container_system_config=True, ) logger = logging.getLogger("root") with runexec_catch_signals(run_executor), capture_logs( logger, logging.WARNING) as logs: run_exec_run = run_executor.execute_run( args=combined_cmd, environments={ "keepEnv": {}, }, workingDir="/", write_header=False, output_filename=stdout, error_filename=stderr, softtimelimit=time_limit, hardtimelimit=int(time_limit * 1.1), walltimelimit=int(time_limit * 1.2), memlimit=mem_limit, ) return ( combined_cmd, RunexecStats.create(run_exec_run), stdout.read_text(), stderr.read_text() + "\n".join(record.getMessage() for record in logs), )
def setUp(self, *args, **kwargs): try: container.execute_in_namespace(lambda: 0) except OSError as e: self.skipTest(f"Namespaces not supported: {os.strerror(e.errno)}") dir_modes = kwargs.pop( "dir_modes", { "/": containerexecutor.DIR_READ_ONLY, "/home": containerexecutor.DIR_HIDDEN, "/tmp": containerexecutor.DIR_HIDDEN, }, ) self.runexecutor = RunExecutor( use_namespaces=True, dir_modes=dir_modes, *args, **kwargs )
def _run_command(self, command: str, time: float, memory=None, file_count=None, stdin=None): """Runs specified command Arguments: command {str} -- command to be run time {float} -- time limit in seconds Keyword Arguments: memory {int} -- memory limit in bytes (default: {None}) file_count {int} -- maximum number of files to write (default: {None}) stdin {file} -- file used as standard input (default: {None}) Returns: OrderedDict -- dict with results """ executor = RunExecutor(use_namespaces=False) if memory is None: memory = self._limits.max_memory args = command.split(' ') try: result = executor.execute_run(args, self._output_log_file, memlimit=memory, hardtimelimit=time, walltimelimit=time, files_count_limit=file_count, stdin=stdin) if 'cputime' in result and result['cputime'] > time: result['terminationreason'] = 'cputime' except: result = {'terminationreason': 'something went very wrong'} return result
def setUp(self, *args, **kwargs): with self.skip_if_logs( "Cannot reliably kill sub-processes without freezer cgroup"): self.runexecutor = RunExecutor(use_namespaces=False, *args, **kwargs)
def setUp(self): self.runexecutor = RunExecutor()
def setUp(self, *args, **kwargs): self.runexecutor = RunExecutor(*args, **kwargs)
def setUp(self, *args, **kwargs): try: self.runexecutor = RunExecutor(user=self.user, *args, **kwargs) except SystemExit as e: # sudo seems not to be available self.skipTest(e)
def test_require_cgroup_invalid(self): self.assertRaisesRegex(SystemExit, '.*invalid.*', lambda: RunExecutor(additional_cgroup_subsystems=['invalid']))
def __init__(self): self.executor = RunExecutor() signal.signal(signal.SIGINT, self.stop_run)