def create_user_cgroups(user, script=True): logger.info('Creating cgroups sub-directories for user %s' % user) # Get hierarchies and create cgroups sub-directories try: hierarchies = os.listdir(BASE_CGROUPS) except OSError as e: if e.errno == 2: raise CgroupsException( "cgroups filesystem is not mounted on %s" % BASE_CGROUPS) else: raise OSError(e) logger.debug('Hierarchies availables: %s' % hierarchies) for hierarchy in hierarchies: user_cgroup = os.path.join(BASE_CGROUPS, hierarchy, user) if not os.path.exists(user_cgroup): try: os.mkdir(user_cgroup) except OSError as e: if e.errno == 13: if script: raise CgroupsException( "Permission denied, you don't have root privileges") else: raise CgroupsException( "Permission denied. If you want to use cgroups " + "without root priviliges, please execute first " + "the 'user_cgroups' command (as root or sudo).") elif e.errno == 17: pass else: raise OSError(e) else: uid, gid = get_user_info(user) os.chown(user_cgroup, uid, gid) logger.warn('cgroups sub-directories created for user %s' % user)
def set_freezer_state(self, state): if state not in ('THAWED', 'FROZEN'): raise CgroupsException( "there is two values of freezer.state paramener available - THAWED|FROZEN." ) if 'freezer' in self.cgroups: freezer_state_file = self._get_cgroup_file('freezer', 'freezer.state') with open(freezer_state_file, 'w+') as f: f.write("%s\n" % state) else: raise CgroupsException( 'FREEZER hierarchy not available in this cgroup')
def set_swappiness(self, swappiness=SWAPPINESS_DEFAULT): if 'memory' in self.cgroups: swappiness = int(swappiness) if swappiness < 0 and swappiness > 100: raise CgroupsException( "swappiness value must be in range 1..100") value = swappiness swappiness_file = self._get_cgroup_file('memory', 'memory.swappiness') with open(swappiness_file, 'w+') as f: f.write('%s\n' % value) else: raise CgroupsException( 'MEMORY hierarchy not available in this cgroup')
def _format_cpu_value(self, limit=None): if limit is None: value = CPU_DEFAULT else: try: limit = float(limit) except ValueError: raise CgroupsException('Limit must be convertible to a float') else: if limit <= float(0) or limit > float(100): raise CgroupsException('Limit must be between 0 and 100') else: limit = limit / 100 value = int(round(CPU_DEFAULT * limit)) return value
def _format_cpu_share_value(self, share=None): if share is None: value = CPU_DEFAULT else: try: share = float(share) except ValueError: raise CgroupsException('Share must be convertible to a float') else: if share <= float(0) or share > float(100): raise CgroupsException('Share must be between 0 and 100') else: share = share / 100 value = int(round(CPU_DEFAULT * share)) return value
def __init__(self, name, hierarchies='all', user='******'): self.name = name # Get user self.user = user if self.user == 'current': self.user = getpass.getuser() # Get hierarchies if hierarchies == 'all': hierarchies = HIERARCHIES self.hierarchies = [h for h in hierarchies if h in HIERARCHIES] # Get user cgroups self.user_cgroups = {} system_hierarchies = os.listdir(BASE_CGROUPS) for hierarchy in self.hierarchies: if hierarchy not in system_hierarchies: raise CgroupsException("Hierarchy %s is not mounted" % hierarchy) user_cgroup = os.path.join(BASE_CGROUPS, hierarchy, self.user) self.user_cgroups[hierarchy] = user_cgroup create_user_cgroups(self.user, script=False) # Create name cgroups self.cgroups = {} for hierarchy, user_cgroup in self.user_cgroups.items(): cgroup = os.path.join(user_cgroup, self.name) if not os.path.exists(cgroup): os.mkdir(cgroup) self.cgroups[hierarchy] = cgroup
def get_user_info(user): try: user_system = getpwnam(user) except KeyError: raise CgroupsException("User %s doesn't exists" % user) else: uid = user_system.pw_uid gid = user_system.pw_gid return uid, gid
def set_cpu_limit(self, limit=None): if 'cpu' in self.cgroups: value = self._format_cpu_value(limit) cpu_shares_file = self._get_cgroup_file('cpu', 'cpu.shares') with open(cpu_shares_file, 'w+') as f: f.write('%s\n' % value) else: raise CgroupsException( 'CPU hierarchy not available in this cgroup')
def _format_cfs(self, value=None): if value is None: value = CFS_DEFAULT else: try: value = int(value) except ValueError: raise CgroupsException('value must be convertible to an int') else: if (value >= int(1000) and value <= int(1000000)) or value == int(-1): value = int(value) else: raise CgroupsException( 'value must be between 1000us and 1000000us or -1 for no restriction' ) return value
def set_memory_limit(self, limit=None, unit='megabytes'): if 'memory' in self.cgroups: value = self._format_memory_value(unit, limit) memory_limit_file = self._get_cgroup_file('memory', 'memory.limit_in_bytes') with open(memory_limit_file, 'w+') as f: f.write('%s\n' % value) else: raise CgroupsException( 'MEMORY hierarchy not available in this cgroup')
def set_cfs_period_us(self, period=100000): '''specifies a period of time in microseconds µs for how regularly a cgroup's access to CPU resources should be reallocated''' if 'cpu' in self.cgroups: value = self._format_cfs(period) cfs_period_file = self._get_cgroup_file('cpu', 'cpu.cfs_period_us') with open(cfs_period_file, 'w+') as f: f.write('%s\n' % value) else: raise CgroupsException( 'CPU hierarchy not available in this cgroup')
def set_cfs_quota_us(self, quota=-1): '''cpu.cfs_quota_us = [1000us - 1000000us]''' if 'cpu' in self.cgroups: value = self._format_cfs(quota) cfs_quota_file = self._get_cgroup_file('cpu', 'cpu.cfs_quota_us') with open(cfs_quota_file, 'w+') as f: print(type(value)) f.write('%s\n' % value) else: raise CgroupsException( 'CPU hierarchy not available in this cgroup')
def add(self, pid): try: os.kill(pid, 0) except OSError: raise CgroupsException('Pid %s does not exists' % pid) for hierarchy, cgroup in self.cgroups.items(): tasks_file = self._get_cgroup_file(hierarchy, 'tasks') with open(tasks_file, 'r+') as f: cgroups_pids = f.read().split('\n') if not str(pid) in cgroups_pids: with open(tasks_file, 'a+') as f: f.write('%s\n' % pid)
def _format_memory_value(self, unit, limit=None): units = ('bytes', 'kilobytes', 'megabytes', 'gigabytes') if unit not in units: raise CgroupsException('Unit must be in %s' % units) if limit is None: value = MEMORY_DEFAULT else: try: limit = int(limit) except ValueError: raise CgroupsException('Limit must be convertible to an int') else: if unit == 'bytes': value = limit elif unit == 'kilobytes': value = limit * 1024 elif unit == 'megabytes': value = limit * 1024 * 1024 elif unit == 'gigabytes': value = limit * 1024 * 1024 * 1024 return value
def set_omm_kill(self, allow=True): if 'memory' in self.cgroups: oom_control_file = self._get_cgroup_file('memory', 'memory.oom_control') oom_kill_disable = 0 if allow else 1 under_oom = 1 if self.is_under_oom else 0 with open(oom_control_file, 'w+') as f: f.write("oom_kill_disable %s\nunder_oom %s\n" % (oom_kill_disable, under_oom)) else: raise CgroupsException( 'MEMORY hierarchy not available in this cgroup')
def _quota_set_cpu_limit(self, limit=None): if 'cpu' in self.cgroups: value = int(CPU_PER_PERIOD * CPU_COUNT * (limit / 100)) # cgroup 限制最小值为 1000 quota = 1000 if value < 1000 else value cpu_cfs_peroid_file = self._get_cgroup_file('cpu', 'cpu.cfs_period_us') cpu_cfs_quota_file = self._get_cgroup_file('cpu', 'cpu.cfs_quota_us') with open(cpu_cfs_peroid_file, 'w+') as f: f.write('{}\n'.format(CPU_PER_PERIOD)) with open(cpu_cfs_quota_file, 'w+') as f: f.write('{}\n'.format(quota)) else: raise CgroupsException('CPU hierarchy not available in this cgroup')