Пример #1
0
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)
Пример #2
0
    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),
        )
Пример #3
0
    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()
Пример #4
0
 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
Пример #5
0
    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()
Пример #6
0
    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),
    )
Пример #8
0
    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
        )
Пример #9
0
    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
Пример #10
0
 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)
Пример #11
0
 def setUp(self):
     self.runexecutor = RunExecutor()
Пример #12
0
 def setUp(self, *args, **kwargs):
     self.runexecutor = RunExecutor(*args, **kwargs)
Пример #13
0
 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)
Пример #14
0
 def test_require_cgroup_invalid(self):
     self.assertRaisesRegex(SystemExit, '.*invalid.*',
                            lambda: RunExecutor(additional_cgroup_subsystems=['invalid']))
Пример #15
0
 def __init__(self):
     self.executor = RunExecutor()
     signal.signal(signal.SIGINT, self.stop_run)