def _calc_free_traits(limits, allocs, old_id): """Calculate free capacity in partition by trait. Note: allocation with old_id is not counted. """ free = {} for limit in limits: free[limit['trait']] = { 'cpu': utils.cpu_units(limit['cpu']), 'disk': utils.size_to_bytes(limit['disk']), 'memory': utils.size_to_bytes(limit['memory']), } for alloc in allocs: # skip allocation with old_id if alloc['_id'] == old_id: continue for trait in alloc['traits']: if trait in free: free[trait]['cpu'] -= utils.cpu_units(alloc['cpu']) free[trait]['disk'] -= utils.size_to_bytes(alloc['cpu']) free[trait]['memory'] -= utils.size_to_bytes(alloc['cpu']) return free
def _check_capacity(cell, allocation, rsrc): """Check that there is enough free space for the allocation. """ try: old = _admin_cell_alloc().get([cell, allocation]) if old['partition'] != rsrc['partition']: old = {'cpu': '0%', 'memory': '0G', 'disk': '0G'} except ldap_exceptions.LDAPNoSuchObjectResult: old = {'cpu': '0%', 'memory': '0G', 'disk': '0G'} free = _partition_free(rsrc['partition'], cell) if (free['cpu'] + utils.cpu_units(old['cpu']) < utils.cpu_units( rsrc['cpu'])): raise exc.InvalidInputError(__name__, 'Not enough cpu capacity in partition.') if (free['memory'] + utils.size_to_bytes(old['memory']) < utils.size_to_bytes(rsrc['memory'])): raise exc.InvalidInputError( __name__, 'Not enough memory capacity in partition.') if (free['disk'] + utils.size_to_bytes(old['disk']) < utils.size_to_bytes( rsrc['disk'])): raise exc.InvalidInputError(__name__, 'Not enough disk capacity in partition.')
def cginit(mem, mem_core, cpu, cpu_cores): """Initialize core and system cgroups.""" if cpu_cores > 0: tm_cpu_shares = sysinfo.bogomips_linux(range(0, cpu_cores)) tm_core_cpu_shares = int(tm_cpu_shares * 0.01) tm_apps_cpu_shares = tm_cpu_shares - tm_core_cpu_shares total_cores = sysinfo.cpu_count() system_cores = range(cpu_cores, total_cores) system_cpu_shares = sysinfo.bogomips_linux(system_cores) _LOGGER.info( 'Configuring CPU limits: ' 'treadmill cores: %d, ' 'treadmill: %d, ' 'treadmill core: %d, ' 'treadmill apps: %d', cpu_cores, tm_cpu_shares, tm_core_cpu_shares, tm_apps_cpu_shares) else: total_cores = sysinfo.cpu_count() total_cpu_shares = sysinfo.bogomips_linux(range(0, total_cores)) tm_cpu_shares = int(total_cpu_shares * utils.cpu_units(cpu) / 100.0) system_cpu_shares = int(total_cpu_shares - tm_cpu_shares) tm_core_cpu_shares = int(tm_cpu_shares * 0.01) tm_apps_cpu_shares = tm_cpu_shares - tm_core_cpu_shares _LOGGER.info( 'Configuring CPU limits: ' 'total: %d, ' 'treadmill: %d, ' 'system: %d, ' 'treadmill core: %d, ' 'treadmill apps: %d', total_cpu_shares, tm_cpu_shares, system_cpu_shares, tm_core_cpu_shares, tm_apps_cpu_shares) tm_mem = utils.size_to_bytes(mem) tm_core_mem = utils.size_to_bytes(mem_core) total_physical_mem = sysinfo.mem_info().total * 1024 if tm_mem <= 0: # For readability, instead of + tm_mem (negative). real_tm_mem = total_physical_mem - abs(tm_mem) else: real_tm_mem = tm_mem _LOGGER.info( 'Configuring memory limits: ' 'total: %s, ' 'treadmill total: %s, ' 'treadmill core: %s', utils.bytes_to_readable(total_physical_mem, 'B'), utils.bytes_to_readable(real_tm_mem, 'B'), utils.bytes_to_readable(tm_core_mem, 'B')) cgutils.create_treadmill_cgroups(system_cpu_shares, tm_cpu_shares, tm_core_cpu_shares, tm_apps_cpu_shares, cpu_cores, real_tm_mem, tm_core_mem)
def on_create_request(self, rsrc_id, rsrc_data): instance_id = rsrc_id memory_limit = rsrc_data['memory'] cpu_limit = rsrc_data['cpu'] cgrp = os.path.join('treadmill', 'apps', instance_id) with lc.LogContext(_LOGGER, rsrc_id, adapter_cls=lc.ContainerAdapter) as log: log.info('Creating cgroups: %s:%s', self.SUBSYSTEMS, cgrp) for subsystem in self.SUBSYSTEMS: cgutils.create(subsystem, cgrp) # blkio settings # cgroups.set_value('blkio', cgrp, 'blkio.weight', 100) # memory settings # self._register_oom_handler(cgrp, instance_id) cgroups.set_value('memory', cgrp, 'memory.soft_limit_in_bytes', memory_limit) # TODO: set hardlimit to app.memory and comment the # reset_memory block until proper solution for # cgroup race condition is implemented. cgutils.set_memory_hardlimit(cgrp, memory_limit) # expunged = cgutils.reset_memory_limit_in_bytes() # for expunged_uniq_name in expunged: # exp_app_dir = os.path.join(tm_env.apps_dir, # expunged_uniq_name) # with open(os.path.join(exp_app_dir, # 'services', 'finished'), 'w') as f: # f.write('oom') # exp_cgrp = os.path.join('treadmill', 'apps', # expunged_uniq_name) # cgutils.kill_apps_in_cgroup('memory', exp_cgrp, # delete_cgrp=False) # cpu settings # # Calculate the value of cpu shares for the app. # # [treadmill/apps/cpu.shares] = <total bogomips allocated to TM> # # [treadmill/apps/<app>/cpu.shares] = app.cpu * BMIPS_PER_CPU # app_cpu_pcnt = utils.cpu_units(cpu_limit) / 100. app_bogomips = app_cpu_pcnt * sysinfo.BMIPS_PER_CPU app_cpu_shares = int(app_bogomips) log.info('created in cpu:%s with %s shares', cgrp, app_cpu_shares) cgroups.set_cpu_shares(cgrp, app_cpu_shares) return {subsystem: cgrp for subsystem in self.SUBSYSTEMS}
def _partition_free(partition, cell): """Calculate free capacity for given partition.""" try: part_obj = _admin_partition().get([partition, cell]) except ldap3.LDAPNoSuchObjectResult: # pretend partition has zero capacity part_obj = {'cpu': '0%', 'memory': '0G', 'disk': '0G'} allocs = _admin_cell_alloc().list({'cell': cell, 'partition': partition}) cpu = utils.cpu_units(part_obj['cpu']) memory = utils.size_to_bytes(part_obj['memory']) disk = utils.size_to_bytes(part_obj['disk']) for alloc in allocs: cpu -= utils.cpu_units(alloc['cpu']) memory -= utils.size_to_bytes(alloc['memory']) disk -= utils.size_to_bytes(alloc['disk']) return {'cpu': cpu, 'memory': memory, 'disk': disk}
def _calc_free(limit, allocs, old_id): """Calculate free capacity in partition. Note: allocation with old_id is not counted. """ free = { 'cpu': utils.cpu_units(limit['cpu']), 'disk': utils.size_to_bytes(limit['disk']), 'memory': utils.size_to_bytes(limit['memory']), } for alloc in allocs: # skip allocation with old_id if alloc['_id'] == old_id: continue free['cpu'] -= utils.cpu_units(alloc['cpu']) free['disk'] -= utils.size_to_bytes(alloc['disk']) free['memory'] -= utils.size_to_bytes(alloc['memory']) return free
def _check_limit(limit, request, extra_info=''): """Check capacity limit for reqested allocation. """ if utils.cpu_units(request['cpu']) > limit['cpu']: raise exc.InvalidInputError( __name__, 'Not enough cpu capacity in partition.' + extra_info) if utils.size_to_bytes(request['disk']) > limit['disk']: raise exc.InvalidInputError( __name__, 'Not enough disk capacity in partition.' + extra_info) if utils.size_to_bytes(request['memory']) > limit['memory']: raise exc.InvalidInputError( __name__, 'Not enough memory capacity in partition.' + extra_info)
def _get_cgroup_cpu_shares(treadmill_core_cpu_shares, treadmill_apps_cpuset_cpus): """get cgroup cpu shares parameter for treadmill core/apps group """ # TODO: Refactor this whole function: # * There is no need to read bogomips for relative weight core/apps. total_app_cpus = _total_cpu_cores(treadmill_apps_cpuset_cpus) apps_cpu_shares = sysinfo.bogomips(total_app_cpus) if treadmill_core_cpu_shares is not None: # in worst case, treadmill/core runs x% percent of treadmill/apps time core_cpu_shares = int(apps_cpu_shares * utils.cpu_units(treadmill_core_cpu_shares) / 100.0) else: core_cpu_shares = None _LOGGER.info( 'Configuring CPU shares: ' 'treadmill core: %r, ' 'treadmill apps: %r', core_cpu_shares, apps_cpu_shares) return (core_cpu_shares, apps_cpu_shares)
def test_cpuunits(self): """Test conversion of cpu string to bmips.""" self.assertEquals(10, utils.cpu_units('10%')) self.assertEquals(10, utils.cpu_units('10'))
def _cgroup_init(treadmill_core_cpu_shares, treadmill_core_cpuset_cpus, treadmill_apps_cpuset_cpus, treadmill_core_memory_limit): # calculate CPU shares allocation total_cores = sysinfo.cpu_count() total_cpu_shares = sysinfo.bogomips(six.moves.range(total_cores)) core_cpu_shares = int( total_cpu_shares * utils.cpu_units(treadmill_core_cpu_shares) / 100.0 ) apps_cpu_shares = total_cpu_shares - core_cpu_shares _LOGGER.info( 'Configuring CPU shares: ' 'total: %d, ' 'treadmill core: %d, ' 'treadmill apps: %d', total_cpu_shares, core_cpu_shares, apps_cpu_shares ) # calculate memory allocation core_memory = utils.size_to_bytes(treadmill_core_memory_limit) total_physical_mem = sysinfo.mem_info().total * 1024 # XXX: tm_mem = utils.size_to_bytes(treadmill_mem) # XXX: if tm_mem <= 0: # XXX: real_tm_mem = total_physical_mem - abs(tm_mem) # XXX: else: # XXX: real_tm_mem = tm_mem treadmill_memory = total_physical_mem apps_memory = treadmill_memory - core_memory _LOGGER.info( 'Configuring memory limits: ' 'total: %s, ' 'treadmill core: %s, ' 'treadmill apps: %s', utils.bytes_to_readable(total_physical_mem, 'B'), utils.bytes_to_readable(core_memory, 'B'), utils.bytes_to_readable(apps_memory, 'B') ) # calculate cpuset cores allocation core_cpuset_cpus = _parse_cpuset_cpus( treadmill_core_cpuset_cpus ) apps_cpuset_cpus = _parse_cpuset_cpus( treadmill_apps_cpuset_cpus ) _LOGGER.info( 'Configuring cpuset cores: ' 'treadmill core cpuset: %s, ' 'treadmill app cpuset: %s', core_cpuset_cpus, apps_cpuset_cpus ) cgutils.create_treadmill_cgroups( core_cpu_shares, apps_cpu_shares, core_cpuset_cpus, apps_cpuset_cpus, core_memory, apps_memory )
def _cgroup_init(treadmill_core_cpu_shares, treadmill_core_cpuset_cpus, treadmill_apps_cpuset_cpus, treadmill_core_memory_limit): # TODO: Refactor this whole function: # * It should be mostly folded into cgutils # * There is no need to read sysinfo for CPUs, use cpuset cgroup. # * There is no need to read bogomips for relative weight core/apps. # * There is no need to read physical memory here, use cgroups. # calculate CPU shares allocation total_cores = sysinfo.cpu_count() total_cpu_shares = sysinfo.bogomips(six.moves.range(total_cores)) if treadmill_core_cpu_shares is not None: core_cpu_shares = int( total_cpu_shares * utils.cpu_units(treadmill_core_cpu_shares) / 100.0 ) apps_cpu_shares = total_cpu_shares - core_cpu_shares else: core_cpu_shares = apps_cpu_shares = None _LOGGER.info( 'Configuring CPU shares: ' 'total: %d, ' 'treadmill core: %r, ' 'treadmill apps: %r', total_cpu_shares, core_cpu_shares, apps_cpu_shares ) # calculate memory allocation total_physical_mem = sysinfo.mem_info().total * 1024 if treadmill_core_memory_limit is not None: core_memory = utils.size_to_bytes(treadmill_core_memory_limit) # XXX: tm_mem = utils.size_to_bytes(treadmill_mem) # XXX: if tm_mem <= 0: # XXX: real_tm_mem = total_physical_mem - abs(tm_mem) # XXX: else: # XXX: real_tm_mem = tm_mem treadmill_memory = total_physical_mem apps_memory = treadmill_memory - core_memory else: core_memory = apps_memory = None _LOGGER.info( 'Configuring memory limits: ' 'total: %s, ' 'treadmill core: %r, ' 'treadmill apps: %r', utils.bytes_to_readable(total_physical_mem, 'B'), utils.bytes_to_readable(core_memory, 'B'), utils.bytes_to_readable(apps_memory, 'B') ) # calculate cpuset cores allocation if treadmill_core_cpuset_cpus is not None: core_cpuset_cpus = _parse_cpuset_cpus( treadmill_core_cpuset_cpus ) # TODO: Calculate from apps as treadmill - core apps_cpuset_cpus = _parse_cpuset_cpus( treadmill_apps_cpuset_cpus ) else: core_cpuset_cpus = apps_cpuset_cpus = None _LOGGER.info( 'Configuring cpuset cores: ' 'treadmill cpuset: %r, ' 'treadmill core cpuset: %r, ' 'treadmill app cpuset: %r', 'TBD', core_cpuset_cpus, apps_cpuset_cpus ) cgutils.create_treadmill_cgroups( core_cpu_shares, apps_cpu_shares, core_cpuset_cpus, apps_cpuset_cpus, core_memory, apps_memory )