Exemplo n.º 1
0
    def unpack(self, container_dir, root_dir, app, app_cgroups, data):

        root_dir = fs.norm_safe(root_dir)

        emptydirs, stickydirs, mounts = configure()
        for plugin in image_fs.plugins(app):
            _LOGGER.info('Processing plugin: %r', plugin)
            extra = plugin(self.tm_env).configure(container_dir, app)
            if extra is not None:
                emptydirs.update(extra[0])
                stickydirs.update(extra[1])
                mounts.update(extra[2])

        make_fsroot(root_dir, emptydirs, stickydirs, mounts)
        make_osroot(root_dir, app, data)

        # FIXME: Lots of things are still reading this file.
        #        Copy updated state manifest as app.json in the
        #        container_dir so it is visible in chrooted env.
        shutil.copy(os.path.join(container_dir, runtime.STATE_JSON),
                    os.path.join(root_dir, appcfg.APP_JSON))

        cgrp = os.path.join(app_cgroups['memory'], 'services')

        create_environ_dir(container_dir, root_dir, app)

        create_supervision_tree(
            self.tm_env, container_dir, root_dir, app,
            cgroups_path=cgroups.makepath(
                'freezer', cgrp
            ),
        )
        create_overlay(self.tm_env, container_dir, root_dir, app)
Exemplo n.º 2
0
def kill_apps_in_cgroup(subsystem, cgrp, delete_cgrp=False):
    """Kill all apps found in a cgroup"""
    path = cgroups.makepath(subsystem, cgrp, 'tasks')
    tasks_files = glob.glob(path)
    for tasks_file in tasks_files:
        cgrp_path = os.path.dirname(tasks_file)
        try:
            with io.open(tasks_file) as tasks:
                for pid in tasks:
                    _LOGGER.info('killing process from %r: %s',
                                 tasks_file, pid)
                    try:
                        os.kill(int(pid), signal.SIGKILL)
                    except OSError as err:
                        # it is OK to fail to find the PID
                        if err.errno == errno.ESRCH:
                            continue
                        _LOGGER.exception('Unable to kill processes in %r: %s',
                                          cgrp_path, err)

        except IOError as err:
            # it is OK to fail if the tasks file is already gone
            if err.errno == errno.ENOENT:
                _LOGGER.debug('Skipping nonexistent cgroup %r', cgrp_path)
                continue
            raise

        if delete_cgrp:
            cgrp = cgroups.extractpath(cgrp_path, subsystem)
            delete(subsystem, cgrp)
Exemplo n.º 3
0
def pids_in_cgroup(subsystem, cgrp):
    """Returns the list of pids in the cgroup."""
    path = cgroups.makepath(subsystem, cgrp, 'tasks')
    with io.open(path) as tasks:
        return [
            int(line.strip()) for line
            in tasks.readlines() if line
        ]
Exemplo n.º 4
0
def is_oom():
    """Checks memory failcount and return oom state of the container."""

    # NOTE(boysson): This code runs in the container's namespace so the memory
    #                cgroup is "masked".
    mem_failcnt = cgroups.makepath('memory', '/', 'memory.failcnt')
    memsw_failcnt = cgroups.makepath('memory', '/', 'memory.memsw.failcnt')

    try:
        with open(mem_failcnt) as f:
            mem_failcnt = int(f.read().strip())
        with open(memsw_failcnt) as f:
            memsw_failcnt = int(f.read().strip())
        return mem_failcnt != 0 or memsw_failcnt != 0
    except:  # pylint: disable=W0702
        _LOGGER.info('Cannot access memory failcnt.', exc_info=True)
        return False
Exemplo n.º 5
0
def apps():
    """Returns list of apps in apps cgroup."""
    basepath = cgroups.makepath('cpu', 'treadmill/apps')
    files = os.listdir(basepath)
    return [
        appname for appname in files
        if os.path.isdir(os.path.join(basepath, appname))
    ]
Exemplo n.º 6
0
def apps(cgroup_prefix):
    """Returns list of apps in apps cgroup."""
    apps_group = apps_group_name(cgroup_prefix)
    basepath = cgroups.makepath('cpu', apps_group)
    files = os.listdir(basepath)
    return [
        appname for appname in files
        if os.path.isdir(os.path.join(basepath, appname))
    ]
Exemplo n.º 7
0
def app_cgrp_count():
    """Get the number of apps in treadmill/apps"""
    appcount = 0
    basepath = cgroups.makepath('memory', 'treadmill/apps')
    files = os.listdir(basepath)
    for appname in files:
        fullpath = os.path.join(basepath, appname)
        if os.path.isdir(fullpath):
            appcount += 1

    return appcount
Exemplo n.º 8
0
def share_cgroup_info(app, root_dir):
    """Shares subset of cgroup tree with the container."""
    # Bind /cgroup/memory inside chrooted environment to /cgroup/.../memory
    # of the container.
    unique_name = appcfg.app_unique_name(app)
    cgrp = os.path.join('treadmill', 'apps', unique_name)

    # FIXME: This should be removed and proper cgroups should be
    #        exposed (readonly). This is so that tools that
    #        (correctly) read /proc/self/cgroups can access cgroup
    #        data.
    shared_subsystems = ['memory']
    for subsystem in shared_subsystems:
        fs.mkdir_safe(os.path.join(root_dir, 'cgroup', subsystem))
        fs.mount_bind(root_dir, os.path.join('/cgroup', subsystem),
                      cgroups.makepath(subsystem, cgrp))
Exemplo n.º 9
0
def delete(system, group):
    """ safely delete cgroup path """
    fullpath = cgroups.makepath(system, group)

    for (dirname, _subdirs, _files) in os.walk(fullpath, topdown=False):
        cgrp = cgroups.extractpath(dirname, system)

        # free empty memory before the cgroups is destroyed
        if system == 'memory':
            memory_force_empty(cgrp)

        try:
            cgroups.delete(system, cgrp)
        except OSError as err:
            _LOGGER.exception('Unable remove cgroup %s %s, %r',
                              system, cgrp, err)
            raise err
Exemplo n.º 10
0
def share_cgroup_info(root_dir, cgrp):
    """Shares subset of cgroup tree with the container."""
    # Bind /cgroup/memory inside chrooted environment to /cgroup/.../memory
    # of the container.

    # FIXME: This should be removed and proper cgroups should be
    #        exposed (readonly). This is so that tools that
    #        (correctly) read /proc/self/cgroups can access cgroup
    #        data.
    shared_subsystems = ['memory']
    for subsystem in shared_subsystems:
        fs.mkdir_safe(os.path.join(root_dir, 'cgroup', subsystem))
        fs_linux.mount_bind(root_dir,
                            os.path.join(os.sep, 'cgroup', subsystem),
                            source=cgroups.makepath(subsystem, cgrp),
                            recursive=True,
                            read_only=False)
Exemplo n.º 11
0
def reset_memory_limit_in_bytes(cgroup_prefix):
    """Recalculate the hard memory limits.

    If any app uses more than the value we are trying to resize to, it will be
    expunged.

    :returns:
        List of unique application names to expunge from the system.
    """
    total_soft_mem = float(total_soft_memory_limits(cgroup_prefix))
    apps_group = apps_group_name(cgroup_prefix)
    total_hard_mem = cgroups.get_value('memory', apps_group,
                                       'memory.limit_in_bytes')
    basepath = cgroups.makepath('memory', apps_group)

    _LOGGER.info('total_soft_mem: %r, total_hard_mem: %r', total_soft_mem,
                 total_hard_mem)

    expunged = []
    for f in os.listdir(basepath):
        if not os.path.isdir(os.path.join(basepath, f)):
            continue

        cgrp = os.path.join(apps_group, f)
        soft_limit = float(
            cgroups.get_value('memory', cgrp, 'memory.soft_limit_in_bytes'))

        percentage_of_allocated = soft_limit / total_soft_mem
        hard_limit = int(percentage_of_allocated * total_hard_mem)

        _LOGGER.info('%s: soft_limit %r, pcnt: %r, hard_limit: %r', cgrp,
                     soft_limit, percentage_of_allocated, hard_limit)

        if hard_limit < soft_limit:
            hard_limit = int(soft_limit)

        _LOGGER.debug('Setting cgroup %r hardlimit to %r', cgrp, hard_limit)
        try:
            set_memory_hardlimit(cgrp, hard_limit)

        except TreadmillCgroupError:
            # Unable to resize group, add it to the expunged groups.
            expunged.append(f)

    return expunged
Exemplo n.º 12
0
def total_soft_memory_limits():
    """Add up soft memory limits."""
    total_mem = 0
    path = cgroups.makepath('memory', 'treadmill/apps/*',
                            'memory.soft_limit_in_bytes')
    mem_files = glob.glob(path)
    for mem_file in mem_files:
        try:
            with io.open(mem_file) as mem:
                total_mem += int(mem.read().strip())
        except IOError as err:
            # it is ok to fail if the memfile is already gone
            if err.errno == errno.ENOENT:
                continue
            _LOGGER.exception('Unable to read soft-limit %r: %s',
                              mem_file, err)
            raise

    return total_mem
Exemplo n.º 13
0
    def unpack(self, container_dir, root_dir, app):
        make_fsroot(root_dir)

        image_fs.configure_plugins(self.tm_env, container_dir, app)

        # FIXME: Lots of things are still reading this file.
        #        Copy updated state manifest as app.json in the
        #        container_dir so it is visible in chrooted env.
        shutil.copy(os.path.join(container_dir, runtime.STATE_JSON),
                    os.path.join(root_dir, appcfg.APP_JSON))

        cgrp = get_cgroup_path(app)

        create_environ_dir(container_dir, root_dir, app)
        create_supervision_tree(self.tm_env,
                                container_dir,
                                root_dir,
                                app,
                                cgroups_path=cgroups.makepath('memory', cgrp))
        create_overlay(self.tm_env, container_dir, root_dir, app)
Exemplo n.º 14
0
def get_memory_oom_eventfd(cgrp):
    """Create, register and return a eventfd for a cgroup OOM notification.

    Args:
        cgrp ``str``: path to a cgroup root directory.

    Returns:
        ``int``: eventfd(2) filedescriptor.
    """
    # 1/ create an eventfd
    efd = eventfd.eventfd(0, eventfd.EFD_CLOEXEC)
    # 2/ open memory.oom_control
    oom_control_file = cgroups.makepath('memory', cgrp, 'memory.oom_control')
    with io.open(oom_control_file) as oom_control:
        # 3/ write '<eventfd_fd> <oom_control_fd> to cgroup.event_control
        cgroups.set_value(
            'memory', cgrp, 'cgroup.event_control',
            '{eventfd_fd} {oom_control_fd}'.format(
                eventfd_fd=efd,
                oom_control_fd=oom_control.fileno(),
            ))

    return efd
Exemplo n.º 15
0
def stat(subsystem, cgrp, pseudofile):
    """Calls stat the cgrp file"""
    path = cgroups.makepath(subsystem, cgrp, pseudofile)
    return os.stat(path)
Exemplo n.º 16
0
def reset_cpu_usage(cgrp):
    """Set the cpu usage to 0"""
    with io.open(cgroups.makepath('cpuacct', cgrp, 'cpuacct.usage'), 'w') as f:
        f.write('0')