Esempio n. 1
0
def test_clean_tasksless_resctrl_groups(rmdir_mock):
    with patch('wca.resctrl.open', create_open_mock({
        '/sys/fs/resctrl/mon_groups/c1/tasks': '',  # empty
        '/sys/fs/resctrl/mon_groups/c2/tasks': '1234',
        '/sys/fs/resctrl/empty/mon_groups/c3/tasks': '',
        '/sys/fs/resctrl/half_empty/mon_groups/c5/tasks': '1234',
        '/sys/fs/resctrl/half_empty/mon_groups/c6/tasks': '',
    })):
        mon_groups_relation = {'': ['c1', 'c2'],
                               'empty': ['c3'],
                               'half_empty': ['c5', 'c6'],
                               }
        clean_taskless_groups(mon_groups_relation)

    rmdir_mock.assert_has_calls([
        call('/sys/fs/resctrl/mon_groups/c1'),
        call('/sys/fs/resctrl/empty'),
        call('/sys/fs/resctrl/half_empty/mon_groups/c6')
    ])
Esempio n. 2
0
    def sync_containers_state(self, tasks: List[Task]) -> Dict[Task, ContainerInterface]:
        """Syncs state of ContainerManager with a system by removing orphaned containers,
        and creating containers for newly arrived tasks, and synchronizing containers' state.

        Function is responsible for cleaning and initializing stateful subsystems such as:
        - perf counters: opens file descriptors for counters,
        - resctrl (ResGroups): creates and manages directories in resctrl filesystem and scarce
            "closid" hardware identifiers

        Can throw OutOfClosidsException.
        """

        # Find difference between discovered tasks and already watched containers.
        new_tasks, containers_to_cleanup = _find_new_and_dead_tasks(
            tasks, list(self.containers.values()))

        if containers_to_cleanup:
            log.debug('sync_containers_state: cleaning up %d containers',
                      len(containers_to_cleanup))
            log.log(logger.TRACE, 'sync_containers_state: containers_to_cleanup=%r',
                    containers_to_cleanup)

            # Clean up and remove orphaned containers.
            for container_to_cleanup in containers_to_cleanup:
                container_to_cleanup.cleanup()

        # Recreate self.containers.
        # mutated state e.g. labels for Kubernetes
        containers = {}
        for task in tasks:
            for known_task, container in self.containers.items():
                if task.cgroup_path == known_task.cgroup_path:
                    containers[task] = container
                    continue
        self.containers = containers

        if new_tasks:
            log.debug('Found %d new tasks', len(new_tasks))
            log.log(logger.TRACE, 'sync_containers_state: new_tasks=%r', new_tasks)

        # Prepare state of currently assigned resgroups
        # and remove some orphaned resgroups.
        container_name_to_ctrl_group = {}
        if self._rdt_information:
            assert self._rdt_information.is_monitoring_enabled(), \
                "rdt_enabled requires RDT monitoring for keeping groups relation."
            mon_groups_relation = resctrl.read_mon_groups_relation()
            log.log(TRACE, 'mon_groups_relation (before cleanup): %s',
                    pprint.pformat(mon_groups_relation))
            resctrl.clean_taskless_groups(mon_groups_relation)

            mon_groups_relation = resctrl.read_mon_groups_relation()
            log.log(TRACE, 'mon_groups_relation (after cleanup): %s',
                    pprint.pformat(mon_groups_relation))

            # Calculate inverse relation of container_name
            # to res_group name based on mon_groups_relations.
            for ctrl_group, container_names in mon_groups_relation.items():
                for container_name in container_names:
                    container_name_to_ctrl_group[container_name] = ctrl_group
            log.log(TRACE, 'container_name_to_ctrl_group: %s',
                    pprint.pformat(container_name_to_ctrl_group))

        # Create new containers and store them.
        for new_task in new_tasks:
            self.containers[new_task] = self._create_container(new_task)

        # Sync "state" of individual containers.
        # Note: only pids are synchronized, not allocations.
        for container in self.containers.values():
            if self._rdt_information:
                if container.get_name() in container_name_to_ctrl_group:
                    resgroup_name = container_name_to_ctrl_group[container.get_name()]
                    container.set_resgroup(ResGroup(name=resgroup_name))
                else:
                    # Every newly detected container is first assigned to the root group.
                    container.set_resgroup(ResGroup(name=''))
            container.sync()

        log.log(logger.TRACE, 'sync_containers_state: containers=%r', self.containers)

        return self.containers