def make_kthread(state): log.debug("entering make_kthread, state=%s", state) shield_exists() if state == 'on': log.info('--> activating kthread shielding') root_tasks = cset.unique_set('/').tasks log.debug('root set has %d tasks, checking for unbound', len(root_tasks)) tasks = [] for task in root_tasks: try: if proc.is_unbound(task): tasks.append(task) except: pass if len(tasks) != 0: log.debug("total root tasks %s", len(root_tasks)) log.info("kthread shield activated, moving %s tasks into system cpuset...", len(tasks)) proc.move('root', SYS_SET, tasks, verbose) else: log.info('--> deactivating kthread shielding') usr_tasks = cset.unique_set(SYS_SET).tasks tasks = [] for task in usr_tasks: try: os.readlink('/proc/'+task+'/exe') except: tasks.append(task) if len(tasks) != 0: log.info("moving %s tasks into root cpuset...", len(tasks)) proc.move(SYS_SET, '/', tasks, verbose) log.info('done')
def rename_set(options, args): """rename cpuset as specified in options and args lists""" log.debug('entering rename_set, options=%s args=%s', options, args) # figure out target cpuset name, if --set not used, use first arg name = options.newname if options.set: tset = cset.unique_set(options.set) elif len(args) > 0: tset = cset.unique_set(args[0]) else: raise CpusetException('desired cpuset not specified') path = tset.path[0:tset.path.rfind('/')+1] log.debug('target set="%s", path="%s", name="%s"', tset.path, path, name) try: if name.find('/') == -1: chk = cset.unique_set(path+name) else: if name[0:name.rfind('/')+1] != path: raise CpusetException('desired name cannot have different path') chk = cset.unique_set(name) raise CpusetException('cpuset "'+chk.path+'" already exists') except CpusetNotFound: pass except: raise if name.rfind('/') != -1: name = name[name.rfind('/')+1:] log.info('--> renaming "%s" to "%s"', cset.CpuSet.basepath+tset.path, name) os.rename(cset.CpuSet.basepath+tset.path, cset.CpuSet.basepath+path+name) cset.rescan()
def rename_set(options, args): """rename cpuset as specified in options and args lists""" log.debug('entering rename_set, options=%s args=%s', options, args) # figure out target cpuset name, if --set not used, use first arg name = options.newname if options.set: tset = cset.unique_set(options.set) elif len(args) > 0: tset = cset.unique_set(args[0]) else: raise CpusetException('desired cpuset not specified') path = tset.path[0:tset.path.rfind('/') + 1] log.debug('target set="%s", path="%s", name="%s"', tset.path, path, name) try: if name.find('/') == -1: chk = cset.unique_set(path + name) else: if name[0:name.rfind('/') + 1] != path: raise CpusetException( 'desired name cannot have different path') chk = cset.unique_set(name) raise CpusetException('cpuset "' + chk.path + '" already exists') except CpusetNotFound: pass except: raise if name.rfind('/') != -1: name = name[name.rfind('/') + 1:] log.info('--> renaming "%s" to "%s"', cset.CpuSet.basepath + tset.path, name) os.rename(cset.CpuSet.basepath + tset.path, cset.CpuSet.basepath + path + name) cset.rescan()
def shield_exists(): try: cset.unique_set(USR_SET) cset.unique_set(SYS_SET) return True except CpusetNotFound: log.debug('can\'t find "%s" and "%s" cpusets on system...', SYS_SET, USR_SET) raise CpusetException('shielding not active on system')
def print_usr_stats(): if verbose and len(cset.unique_set(USR_SET).tasks) > 0: if verbose == 1: proc.log_detailed_task_table(cset.unique_set(USR_SET), ' ', 76) else: proc.log_detailed_task_table(cset.unique_set(USR_SET), ' ') else: if config.mread: str = USR_SET if str[0] == '/': str = str[1:] log.info('proc_list_no_tasks-' + str) else: log.info(cset.summary(cset.unique_set(USR_SET)))
def reset_shield(): log.info("--> deactivating/reseting shielding") shield_exists() tasks = cset.unique_set(USR_SET).tasks log.info('moving %s tasks from "%s" user set to root set...', len(tasks), USR_SET) proc.move(USR_SET, 'root', None, verbose) tasks = cset.unique_set(SYS_SET).tasks log.info('moving %s tasks from "%s" system set to root set...', len(tasks), SYS_SET) proc.move(SYS_SET, 'root', None, verbose) log.info('deleting "%s" and "%s" sets', USR_SET, SYS_SET) set.destroy(USR_SET) set.destroy(SYS_SET) log.info('done')
def destroy(name): """destroy one cpuset by name as cset or string""" log.debug('entering destroy, name=%s', name) if isinstance(name, str): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException( "passed name=%s, which is not a string or CpuSet" % name) else: set = name tsks = set.tasks if len(tsks) > 0: # wait for tasks, sometimes it takes a little while to # have them leave the set ii = 0 while len(tsks) > 0: log.debug( '%i tasks still running in set %s, waiting interval %s...', len(tsks), set.name, ii + 1) time.sleep(0.5) tsks = set.tasks ii += 1 if (ii) > 6: # try it for 3 seconds, bail if tasks still there raise CpusetException( "trying to destroy cpuset %s with tasks running: %s" % (set.path, set.tasks)) log.debug("tasks expired, deleting set %s" % set.path) os.rmdir(cset.CpuSet.basepath + set.path) # fixme: perhaps reparsing the all the sets is not so efficient... cset.rescan()
def test_walk_set(self): # no special checking ATM self.assertEqual(type(cset.unique_set("root")), cset.CpuSet) root_set = cset.find_sets("/") for node in root_set: for x in cset.walk_set(node): self.assertEqual(type(x), cset.CpuSet)
def destroy(name): """destroy one cpuset by name as cset or string""" log.debug('entering destroy, name=%s', name) if isinstance(name, str): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException( "passed name=%s, which is not a string or CpuSet" % name) else: set = name tsks = set.tasks if len(tsks) > 0: # wait for tasks, sometimes it takes a little while to # have them leave the set ii = 0 while len(tsks)>0: log.debug('%i tasks still running in set %s, waiting interval %s...', len(tsks), set.name, ii+1) time.sleep(0.5) tsks = set.tasks ii += 1 if (ii) > 6: # try it for 3 seconds, bail if tasks still there raise CpusetException( "trying to destroy cpuset %s with tasks running: %s" % (set.path, set.tasks)) log.debug("tasks expired, deleting set %s" % set.path) os.rmdir(cset.CpuSet.basepath+set.path) # fixme: perhaps reparsing the all the sets is not so efficient... cset.rescan()
def move(fromset, toset, plist=None, verb=None, force=None): log.debug('entering move, fromset=%s toset=%s list=%s force=%s verb=%s', fromset, toset, plist, force, verb) if isinstance(fromset, str): fset = cset.unique_set(fromset) elif not isinstance(fromset, cset.CpuSet) and plist == None: raise CpusetException( "passed fromset=%s, which is not a string or CpuSet" % fromset) else: fset = fromset if isinstance(toset, str): tset = cset.unique_set(toset) elif not isinstance(toset, cset.CpuSet): raise CpusetException( "passed toset=%s, which is not a string or CpuSet" % toset) else: tset = toset if plist == None: log.debug('moving default of all processes') if tset != fset and not force: plist = fset.tasks else: raise CpusetException( "cannot move tasks into their origination cpuset") output = 0 if verb: output = verb elif verbose: output = verbose if output: l = [] if config.mread: l.append('move_tasks_start') l.extend(task_detail_table(plist)) l.append('move_tasks_stop') else: l.append(' ') l.extend(task_detail_header(' ')) if output > 1: l.extend(task_detail_table(plist, ' ')) else: l.extend(task_detail_table(plist, ' ', 76)) log.info("\n".join(l)) # do the move... tset.tasks = plist
def create(name, cpuspec, memspec, cx, mx): """create one cpuset by name, cpuspec, memspec, cpu and mem exclusive flags""" log.debug('entering create, name=%s cpuspec=%s memspec=%s cx=%s mx=%s', name, cpuspec, memspec, cx, mx) try: cset.unique_set(name) except CpusetNotFound: pass except: raise CpusetException('cpuset "%s" not unique, please specify by path' % name) else: raise CpusetExists('attempt to create already existing set: "%s"' % name) # FIXME: check if name is a path here os.mkdir(cset.CpuSet.basepath+'/'+name) # fixme: perhaps reparsing the all the sets is not so efficient... cset.rescan() log.debug('created new cpuset "%s"', name) modify(name, cpuspec, memspec, cx, mx)
def set_details(name, indent=None, width=None, usehex=False): """return string of cpuset details""" if width == None: width = 0 if isinstance(name, str): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException("passing bogus set=%s" % name) else: set = name l = [] l.append(set.name.rjust(12)) cs = set.cpus if cs == '': cs = '*****' elif usehex: cs = cset.cpuspec_to_hex(cs) l.append(cs.rjust(10)) if set.cpu_exclusive: l.append('y') else: l.append('n') cs = set.mems if cs == '': cs = '*****' elif usehex: cs = cset.cpuspec_to_hex(cs) l.append(cs.rjust(7)) if set.mem_exclusive: l.append('y') else: l.append('n') l.append(str(len(set.tasks)).rjust(5)) l.append(str(len(set.subsets)).rjust(4)) if config.mread: l.append(set.path) l2 = [] for line in l: l2.append(line.strip()) return ';'.join(l2) out = ' '.join(l) + ' ' tst = out + set.path if width != 0 and len(tst) > width: target = width - len(out) patha = set.path[:len(set.path)/2-3] pathb = set.path[len(set.path)/2:] patha = patha[:target/2-3] pathb = pathb[-target/2:] out += patha + '...' + pathb else: out = tst if indent: istr = indent else: istr = '' return istr + out
def set_details(name, indent=None, width=None, usehex=False): """return string of cpuset details""" if width == None: width = 0 if isinstance(name, str): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException("passing bogus set=%s" % name) else: set = name l = [] l.append(set.name.rjust(12)) cs = set.cpus if cs == '': cs = '*****' elif usehex: cs = cset.cpuspec_to_hex(cs) l.append(cs.rjust(10)) if set.cpu_exclusive: l.append('y') else: l.append('n') cs = set.mems if cs == '': cs = '*****' elif usehex: cs = cset.cpuspec_to_hex(cs) l.append(cs.rjust(7)) if set.mem_exclusive: l.append('y') else: l.append('n') l.append(str(len(set.tasks)).rjust(5)) l.append(str(len(set.subsets)).rjust(4)) if config.mread: l.append(set.path) l2 = [] for line in l: l2.append(line.strip()) return ';'.join(l2) out = ' '.join(l) + ' ' tst = out + set.path if width != 0 and len(tst) > width: target = width - len(out) patha = set.path[:len(set.path) // 2 - 3] pathb = set.path[len(set.path // 2):] patha = patha[:target // 2 - 3] pathb = pathb[-target // 2:] out += patha + '...' + pathb else: out = tst if indent: istr = indent else: istr = '' return istr + out
def destroy_sets(sets, recurse=False, force=False): """destroy cpusets in list of sets, recurse if true, if force destroy if tasks running""" log.debug('enter destroy_sets, sets=%s, force=%s', sets, force) nl = [] if isinstance(sets, list): nl.extend(sets) else: nl.append(sets) # check that sets passed are ok, will raise if one is bad sl2 = [] for s in nl: st = cset.unique_set(s) sl2.append(st) if len(st.subsets) > 0: if not recurse: raise CpusetException( 'cpuset "%s" has subsets, delete them first, or use --recurse' % st.path) elif not force: raise CpusetException( 'cpuset "%s" has subsets, use --force to destroy' % st.path) sl2.extend(st.subsets) for node in st.subsets: for nd in cset.walk_set(node): sl2.append(nd) # ok, good to go if recurse: sl2.reverse() for s in sl2: s = cset.unique_set(s) # skip the root set!!! or you'll have problems... if s.path == '/': continue log.info( '--> processing cpuset "%s", moving %s tasks to parent "%s"...', s.name, len(s.tasks), s.parent.path) proc.move(s, s.parent) log.info('--> deleting cpuset "%s"', s.path) destroy(s) log.info('done')
def destroy_sets(sets, recurse=False, force=False): """destroy cpusets in list of sets, recurse if true, if force destroy if tasks running""" log.debug('enter destroy_sets, sets=%s, force=%s', sets, force) nl = [] if isinstance(sets, list): nl.extend(sets) else: nl.append(sets) # check that sets passed are ok, will raise if one is bad sl2 = [] for s in nl: st = cset.unique_set(s) sl2.append(st) if len(st.subsets) > 0: if not recurse: raise CpusetException( 'cpuset "%s" has subsets, delete them first, or use --recurse' % st.path) elif not force: raise CpusetException( 'cpuset "%s" has subsets, use --force to destroy' % st.path) sl2.extend(st.subsets) for node in st.subsets: for nd in cset.walk_set(node): sl2.append(nd) # ok, good to go if recurse: sl2.reverse() for s in sl2: s = cset.unique_set(s) # skip the root set!!! or you'll have problems... if s.path == '/': continue log.info('--> processing cpuset "%s", moving %s tasks to parent "%s"...', s.name, len(s.tasks), s.parent.path) proc.move(s, s.parent) log.info('--> deleting cpuset "%s"', s.path) destroy(s) log.info('done')
def active(name): """check that cpuset by name or cset is ready to be used""" log.debug("entering active, name=%s", name) if isinstance(name, str): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException("passing bogus name=%s" % name) else: set = name if set.cpus == '': raise CpusetException('"%s" cpuset not active, no cpus defined' % set.path) if set.mems == '': raise CpusetException('"%s" cpuset not active, no mems defined' % set.path)
def active(name): """check that cpuset by name or cset is ready to be used""" log.debug("entering active, name=%s", name) if isstr(name): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException("passing bogus name=%s" % name) else: set = name if set.cpus == '': raise CpusetException('"%s" cpuset not active, no cpus defined' % set.path) if set.mems == '': raise CpusetException('"%s" cpuset not active, no mems defined' % set.path)
def modify(name, cpuspec=None, memspec=None, cx=None, mx=None): """modify one cpuset by name, cpuspec, memspec, cpu and mem exclusive flags""" log.debug('entering modify, name=%s cpuspec=%s memspec=%s cx=%s mx=%s', name, cpuspec, memspec, cx, mx) if isstr(name): nset = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException( "passed name=%s, which is not a string or CpuSet" % name) else: nset = name log.debug('modifying cpuset "%s"', nset.name) if cpuspec: nset.cpus = cpuspec if memspec: nset.mems = memspec
def run(tset, args, usr_par=None, grp_par=None): if isinstance(tset, str): s = cset.unique_set(tset) elif not isinstance(tset, cset.CpuSet): raise CpusetException( "passed set=%s, which is not a string or CpuSet" % tset) else: s = tset log.debug('entering run, set=%s args=%s ', s.path, args) set.active(s) # check user if usr_par: try: user = pwd.getpwnam(usr_par)[2] except KeyError: try: user = pwd.getpwuid(int(usr_par))[2] except: raise CpusetException('unknown user: "******"' % usr_par) if grp_par: try: group = grp.getgrnam(grp_par)[2] except KeyError: try: group = grp.getgrgid(int(grp_par))[2] except: raise CpusetException('unknown group: "%s"' % grp_par) elif usr_par: # if user is specified but group is not, and user is not root, # then use the users group if user != 0: try: group = grp.getgrnam('users')[2] grp_par = True except: pass # just forget it # move myself into target cpuset and exec child move_pidspec(str(os.getpid()), s) log.info( '--> last message, executed args into cpuset "%s", new pid is: %s', s.path, os.getpid()) # change user and group before exec if grp_par: os.setgid(group) if usr_par: os.setuid(user) os.environ["LOGNAME"] = usr_par os.environ["USERNAME"] = usr_par os.environ["USER"] = usr_par os.execvp(args[0], args)
def run(tset, args, usr_par=None, grp_par=None): if isinstance(tset, str): s = cset.unique_set(tset) elif not isinstance(tset, cset.CpuSet): raise CpusetException( "passed set=%s, which is not a string or CpuSet" % tset) else: s = tset log.debug('entering run, set=%s args=%s ', s.path, args) set.active(s) # check user if usr_par: try: user = pwd.getpwnam(usr_par)[2] except KeyError: try: user = pwd.getpwuid(int(usr_par))[2] except: raise CpusetException('unknown user: "******"' % usr_par) if grp_par: try: group = grp.getgrnam(grp_par)[2] except KeyError: try: group = grp.getgrgid(int(grp_par))[2] except: raise CpusetException('unknown group: "%s"' % grp_par) elif usr_par: # if user is specified but group is not, and user is not root, # then use the users group if user != 0: try: group = grp.getgrnam('users')[2] grp_par = True except: pass # just forget it # move myself into target cpuset and exec child move_pidspec(str(os.getpid()), s) log.info('--> last message, executed args into cpuset "%s", new pid is: %s', s.path, os.getpid()) # change user and group before exec if grp_par: os.setgid(group) if usr_par: os.setuid(user) os.environ["LOGNAME"] = usr_par os.environ["USERNAME"] = usr_par os.environ["USER"] = usr_par os.execvp(args[0], args)
def modify(name, cpuspec=None, memspec=None, cx=None, mx=None): """modify one cpuset by name, cpuspec, memspec, cpu and mem exclusive flags""" log.debug('entering modify, name=%s cpuspec=%s memspec=%s cx=%s mx=%s', name, cpuspec, memspec, cx, mx) if isinstance(name, str): nset = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException( "passed name=%s, which is not a string or CpuSet" % name) else: nset = name log.debug('modifying cpuset "%s"', nset.name) if cpuspec: nset.cpus = cpuspec if memspec: nset.mems = memspec if cx: nset.cpu_exclusive = cx if mx: nset.mem_exclusive = mx
def selective_move(fset, tset, plist=None, kthread=None, force=None, threads=None): log.debug('entering selective_move, fset=%s tset=%s plist=%s kthread=%s force=%s', fset, tset, plist, kthread, force) task_check = [] tasks = [] task_heap = [] utsk = 0 ktsk = 0 autsk = 0 aktsk = 0 utsknr = 0 ktsknr = 0 ktskb = 0 sstsk = 0 target = cset.unique_set(tset) if fset: fset = cset.unique_set(fset) if fset == target and not force: raise CpusetException( "error, same source/destination cpuset, use --force if ok") task_check = fset.tasks if plist: task_heap = plist else: task_heap = cset.unique_set(fset).tasks log.debug('processing task heap') for task in task_heap: try: # kernel threads do not have an excutable image os.readlink('/proc/'+task+'/exe') autsk += 1 if fset and not force: try: task_check.index(task) tasks.append(task) log.debug(' added task %s', task) utsk += 1 if threads: log.debug(' thread matching, looking for threads for task %s', task) dirs = os.listdir('/proc/'+task+'/task') if len(dirs) > 1: for thread in dirs: if thread != task: log.debug(' adding thread %s', thread) tasks.append(thread) utsk += 1 except ValueError: log.debug(' task %s not running in %s, skipped', task, fset.name) utsknr += 1 else: if not force and cset.lookup_task_from_cpusets(task) == target.path: log.debug(' task %s moving to orgination set %s, skipped', task, target.path) sstsk += 1 else: tasks.append(task) utsk += 1 except OSError: aktsk += 1 try: # this is in try because the task may not exist by the # time we do this, in that case, just ignore it if kthread: if force: tasks.append(task) ktsk += 1 else: if is_unbound(task): tasks.append(task) ktsk += 1 elif cset.lookup_task_from_cpusets(task) == target.path: log.debug(' task %s moving to orgination set %s, skipped', task, target.path) sstsk += 1 else: log.debug(' kernel thread %s is bound, not adding', task) ktskb += 1 except: log.debug(' kernel thread %s not found , perhaps it went away', task) ktsknr += 1 # ok, move 'em log.debug('moving %d tasks to %s ...', len(tasks), tset.name) if len(tasks) == 0: log.info('**> no task matched move criteria') if sstsk > 0: raise CpusetException('same source/destination cpuset, use --force if ok') elif len(task_heap) > 0 and not kthread: raise CpusetException('if you want to move kernel threads, use -k') elif ktskb > 0: raise CpusetException('kernel tasks are bound, use --force if ok') return if utsk > 0: l = [] l.append('moving') l.append(str(utsk)) l.append('userspace tasks to') l.append(tset.path) log.info(' '.join(l)) if utsknr > 0: l = [] l.append('--> not moving') l.append(str(utsknr)) l.append('tasks (not in fromset, use --force)') log.info(' '.join(l)) if ktsk > 0 or kthread: l = [] l.append('moving') l.append(str(ktsk)) l.append('kernel threads to:') l.append(tset.path) log.info(' '.join(l)) if ktskb > 0: l = [] l.append('--> not moving') l.append(str(ktskb)) l.append('threads (not unbound, use --force)') log.info(' '.join(l)) if aktsk > 0 and force and not kthread and autsk == 0: log.info('*** not moving kernel threads, need both --force and --kthread') if ktsknr > 0: l = [] l.append('--> not moving') l.append(str(ktsknr)) l.append('tasks because they are missing (race)') move(None, target, tasks)
def func(parser, options, args): log.debug("entering func, options=%s, args=%s", options, args) global verbose if options.verbose: verbose = options.verbose cset.rescan() tset = None if options.list or options.exc: if options.set: tset = cset.unique_set(options.set) elif options.toset: tset = cset.unique_set(options.toset) elif len(args) > 0: if options.exc: tset = cset.unique_set(args[0]) del args[0] else: tset = args else: raise CpusetException("cpuset not specified") try: log.debug("operating on set %s", tset.path) except: log.debug("operating on sets %s", tset) if options.exc: run(tset, args, options.user, options.group) if options.list: list_sets(tset) return if options.move or options.kthread: fset = None tset = None # first, we need to know the destination if options.toset: tset = cset.unique_set(options.toset) elif options.set and options.pid: tset = cset.unique_set(options.set) elif options.set and options.fromset: tset = cset.unique_set(options.set) elif len(args) > 0: if len(args) > 1 and options.pid == None: options.pid = args[0] if len(args) < 3: tset = cset.unique_set(args[1]) else: # "-m 123 set1 set2" shortcut fset = cset.unique_set(args[1]) tset = cset.unique_set(args[2]) # take care of set1->set2 shortcut pids = pidspec_to_list(options.pid, threads=options.threads) if len(pids) == 1: try: fset = cset.unique_set(pids[0]) options.pid = None except: pass # must be real pidspec else: if len(args) < 2: tset = cset.unique_set(args[0]) else: fset = cset.unique_set(args[0]) tset = cset.unique_set(args[1]) else: raise CpusetException("destination cpuset not specified") set.active(tset) # next, if there is a pidspec, move just that if options.pid: if options.fromset and not options.force: fset = cset.unique_set(options.fromset) elif options.toset and options.set: fset = cset.unique_set(options.set) pids = pidspec_to_list(options.pid, fset, options.threads) if len(pids): log.info('moving following pidspec: %s' % ','.join(pids)) selective_move(None, tset, pids, options.kthread, options.force) else: log.info('**> no tasks moved') log.info('done') else: fset = None # here we assume move everything from fromset to toset if options.fromset: fset = cset.unique_set(options.fromset) elif options.set: fset = cset.unique_set(options.set) elif len(args) > 0: # this must be the fromset, then... fset = cset.unique_set(args[0]) if fset == None: raise CpusetException("origination cpuset not specified") nt = len(fset.tasks) if nt == 0: raise CpusetException('no tasks to move from cpuset "%s"' % fset.path) if options.move: log.info('moving all tasks from %s to %s', fset.name, tset.path) selective_move(fset, tset, None, options.kthread, options.force, options.threads) else: log.info('moving all kernel threads from %s to %s', fset.path, tset.path) # this is a -k "move", so only move kernel threads pids = [] for task in fset.tasks: try: os.readlink('/proc/'+task+'/exe') except: pids.append(task) selective_move(fset, tset, pids, options.kthread, options.force) log.info('done') return # default no options is list list_sets(args)
set.create(SYS_SET, cpuspec_inv, memspec, True, False) except Exception, instance: # unroll try: set.destroy(USR_SET) except: pass try: set.destroy(SYS_SET) except: pass log.critical('--> failed to create shield, hint: do other cpusets exist?') raise instance log.info('--> activating shielding:') else: log.debug("shielding exists, modifying cpuspec") # note, since we're going to modify the cpu assigments to these sets, # they cannot be exclusive, the following modify() calls will make # them exclusive again cset.unique_set(USR_SET).cpu_exclusive = False cset.unique_set(SYS_SET).cpu_exclusive = False set.modify(USR_SET, cpuspec, memspec, False, False) set.modify(SYS_SET, cpuspec_inv, memspec, False, False) # reset cpu exlusivity cset.unique_set(USR_SET).cpu_exclusive = True cset.unique_set(SYS_SET).cpu_exclusive = True log.info('--> shielding modified with:') # move root tasks into system set root_tasks = cset.unique_set('/').tasks log.debug("number of root tasks are: %s", len(root_tasks)) # figure out what in root set is not a kernel thread tasks = [] for task in root_tasks: try: os.readlink('/proc/'+task+'/exe')
except: pass try: set.destroy(SYS_SET) except: pass log.critical( '--> failed to create shield, hint: do other cpusets exist?') raise instance log.info('--> activating shielding:') else: log.debug("shielding exists, modifying cpuspec") # note, since we're going to modify the cpu assigments to these sets, # they cannot be exclusive, the following modify() calls will make # them exclusive again cset.unique_set(USR_SET).cpu_exclusive = False cset.unique_set(SYS_SET).cpu_exclusive = False set.modify(USR_SET, cpuspec, memspec, False, False) set.modify(SYS_SET, cpuspec_inv, memspec, False, False) # reset cpu exlusivity cset.unique_set(USR_SET).cpu_exclusive = True cset.unique_set(SYS_SET).cpu_exclusive = True log.info('--> shielding modified with:') # move root tasks into system set root_tasks = cset.unique_set('/').tasks log.debug("number of root tasks are: %s", len(root_tasks)) # figure out what in root set is not a kernel thread tasks = [] for task in root_tasks: try: os.readlink('/proc/' + task + '/exe')
def pidspec_to_list(pidspec, fset=None, threads=False): """create a list of process ids out of a pidspec""" log.debug('entering pidspecToList, pidspec=%s fset=%s threads=%s', pidspec, fset, threads) if fset: if isinstance(fset, str): fset = cset.unique_set(fset) elif not isinstance(fset, cset.CpuSet): raise CpusetException("passed fset=%s, which is not a string or CpuSet" % fset) log.debug('from-set specified as: %s', fset.path) if not isinstance(pidspec, str): raise CpusetException('pidspec=%s is not a string' % pidspec) groups = pidspec.split(',') plist = [] nifs = 0 if fset: chktsk = fset.tasks log.debug('parsing groups: %s', groups) for sub in groups: items = sub.split('-') if len(items) == 1: if not len(items[0]): # two consecutive commas in pidspec, just continue processing continue # one pid in this group if fset: try: chktsk.index(items[0]) plist.append(items[0]) log.debug(' added single pid: %s', items[0]) except: log.debug(' task %s not running in %s, skipped', items[0], fset.name) nifs += 1 else: plist.append(items[0]) log.debug(' added single pid: %s', items[0]) elif len(items) == 2: # a range of pids, only include those that exist rng = [str(x) for x in range(int(items[0]), int(items[1])+1) if os.access('/proc/'+str(x), os.F_OK)] if fset: for tsk in rng: try: chktsk.index(tsk) plist.append(tsk) log.debug(' added task from range: %s', tsk) except: log.debug(' task %s not running in %s, skipped', tsk, fset.name) nifs += 1 else: plist.extend(rng) log.debug(' added range of pids from %s-%s: %s', items[0], items[1], rng) else: raise CpusetException('pidspec=%s has bad group=%s' % (pidspec, items)) log.debug('raw parsed pid list of %s tasks: %s', len(plist), plist) if nifs > 0: if nifs > 1: nmsg = "tasks" else: nmsg = "task" log.info('**> skipped %s %s, not in origination set "%s"', nifs, nmsg, fset.name) log.debug('checking for duplicates...') pdict = {} dups = 0 for task in plist: if task in pdict: dups += 1 continue pdict[task] = True log.debug('found %s duplicates', dups) if threads: log.debug('thread matching activated, looking for threads...') dups = 0 hits = 0 for task in pdict.keys(): dirs = os.listdir('/proc/'+str(task)+'/task') if len(dirs) > 1: hits += 1 for thread in dirs: if thread in pdict: dups += 1 continue pdict[thread] = True log.debug('found %s multithreaded containers and %s duplicates', hits, dups) plist = pdict.keys() log.debug('returning parsed pid list of %s tasks: %s', len(plist), plist) return plist
def func(parser, options, args): log.debug("entering func, options=%s, args=%s", options, args) global verbose if options.verbose: verbose = options.verbose cset.rescan() tset = None if options.list or options.exc: if options.set: tset = cset.unique_set(options.set) elif options.toset: tset = cset.unique_set(options.toset) elif len(args) > 0: if options.exc: tset = cset.unique_set(args[0]) del args[0] else: tset = args else: raise CpusetException("cpuset not specified") try: log.debug("operating on set %s", tset.path) except: log.debug("operating on sets %s", tset) if options.exc: run(tset, args, options.user, options.group) if options.list: list_sets(tset) return if options.move or options.kthread: fset = None tset = None # first, we need to know the destination if options.toset: tset = cset.unique_set(options.toset) elif options.set and options.pid: tset = cset.unique_set(options.set) elif options.set and options.fromset: tset = cset.unique_set(options.set) elif len(args) > 0: if len(args) > 1 and options.pid == None: options.pid = args[0] if len(args) < 3: tset = cset.unique_set(args[1]) else: # "-m 123 set1 set2" shortcut fset = cset.unique_set(args[1]) tset = cset.unique_set(args[2]) # take care of set1->set2 shortcut pids = pidspec_to_list(options.pid, threads=options.threads) if len(pids) == 1: try: fset = cset.unique_set(pids[0]) options.pid = None except: pass # must be real pidspec else: if len(args) < 2: tset = cset.unique_set(args[0]) else: fset = cset.unique_set(args[0]) tset = cset.unique_set(args[1]) else: raise CpusetException("destination cpuset not specified") set.active(tset) # next, if there is a pidspec, move just that if options.pid: if options.fromset and not options.force: fset = cset.unique_set(options.fromset) elif options.toset and options.set: fset = cset.unique_set(options.set) pids = pidspec_to_list(options.pid, fset, options.threads) if len(pids): log.info('moving following pidspec: %s' % ','.join(pids)) selective_move(None, tset, pids, options.kthread, options.force) else: log.info('**> no tasks moved') log.info('done') else: fset = None # here we assume move everything from fromset to toset if options.fromset: fset = cset.unique_set(options.fromset) elif options.set: fset = cset.unique_set(options.set) elif len(args) > 0: # this must be the fromset, then... fset = cset.unique_set(args[0]) if fset == None: raise CpusetException("origination cpuset not specified") nt = len(fset.tasks) if nt == 0: raise CpusetException('no tasks to move from cpuset "%s"' % fset.path) if options.move: log.info('moving all tasks from %s to %s', fset.name, tset.path) selective_move(fset, tset, None, options.kthread, options.force, options.threads) else: log.info('moving all kernel threads from %s to %s', fset.path, tset.path) # this is a -k "move", so only move kernel threads pids = [] for task in fset.tasks: try: os.readlink('/proc/' + task + '/exe') except: pids.append(task) selective_move(fset, tset, pids, options.kthread, options.force) log.info('done') return # default no options is list list_sets(args)
def setUp(self): cset.rescan() self.test_set = cset.unique_set("user")
def selective_move(fset, tset, plist=None, kthread=None, force=None, threads=None): log.debug( 'entering selective_move, fset=%s tset=%s plist=%s kthread=%s force=%s', fset, tset, plist, kthread, force) task_check = [] tasks = [] task_heap = [] utsk = 0 ktsk = 0 autsk = 0 aktsk = 0 utsknr = 0 ktsknr = 0 ktskb = 0 sstsk = 0 target = cset.unique_set(tset) if fset: fset = cset.unique_set(fset) if fset == target and not force: raise CpusetException( "error, same source/destination cpuset, use --force if ok") task_check = fset.tasks if plist: task_heap = plist else: task_heap = cset.unique_set(fset).tasks log.debug('processing task heap') for task in task_heap: try: # kernel threads do not have an excutable image os.readlink('/proc/' + task + '/exe') autsk += 1 if fset and not force: try: task_check.index(task) tasks.append(task) log.debug(' added task %s', task) utsk += 1 if threads: log.debug( ' thread matching, looking for threads for task %s', task) dirs = os.listdir('/proc/' + task + '/task') if len(dirs) > 1: for thread in dirs: if thread != task: log.debug(' adding thread %s', thread) tasks.append(thread) utsk += 1 except ValueError: log.debug(' task %s not running in %s, skipped', task, fset.name) utsknr += 1 else: if not force and cset.lookup_task_from_cpusets( task) == target.path: log.debug(' task %s moving to orgination set %s, skipped', task, target.path) sstsk += 1 else: tasks.append(task) utsk += 1 except OSError: aktsk += 1 try: # this is in try because the task may not exist by the # time we do this, in that case, just ignore it if kthread: if force: tasks.append(task) ktsk += 1 else: if is_unbound(task): tasks.append(task) ktsk += 1 elif cset.lookup_task_from_cpusets( task) == target.path: log.debug( ' task %s moving to orgination set %s, skipped', task, target.path) sstsk += 1 else: log.debug(' kernel thread %s is bound, not adding', task) ktskb += 1 except: log.debug(' kernel thread %s not found , perhaps it went away', task) ktsknr += 1 # ok, move 'em log.debug('moving %d tasks to %s ...', len(tasks), tset.name) if len(tasks) == 0: log.info('**> no task matched move criteria') if sstsk > 0: raise CpusetException( 'same source/destination cpuset, use --force if ok') elif len(task_heap) > 0 and not kthread: raise CpusetException('if you want to move kernel threads, use -k') elif ktskb > 0: raise CpusetException('kernel tasks are bound, use --force if ok') return if utsk > 0: l = [] l.append('moving') l.append(str(utsk)) l.append('userspace tasks to') l.append(tset.path) log.info(' '.join(l)) if utsknr > 0: l = [] l.append('--> not moving') l.append(str(utsknr)) l.append('tasks (not in fromset, use --force)') log.info(' '.join(l)) if ktsk > 0 or kthread: l = [] l.append('moving') l.append(str(ktsk)) l.append('kernel threads to:') l.append(tset.path) log.info(' '.join(l)) if ktskb > 0: l = [] l.append('--> not moving') l.append(str(ktskb)) l.append('threads (not unbound, use --force)') log.info(' '.join(l)) if aktsk > 0 and force and not kthread and autsk == 0: log.info( '*** not moving kernel threads, need both --force and --kthread') if ktsknr > 0: l = [] l.append('--> not moving') l.append(str(ktsknr)) l.append('tasks because they are missing (race)') move(None, target, tasks)
def make_shield(cpuspec, kthread): memspec = '0' # FIXME: for numa, we probably want a more intelligent scheme log.debug("entering make_shield, cpuspec=%s kthread=%s", cpuspec, kthread) # create base cpusets for shield cset.cpuspec_check(cpuspec) cpuspec_inv = cset.cpuspec_inverse(cpuspec) try: shield_exists() except: log.debug("shielding does not exist, creating") try: set.create(USR_SET, cpuspec, memspec, True, False) set.create(SYS_SET, cpuspec_inv, memspec, True, False) except Exception as instance: # unroll try: set.destroy(USR_SET) except: pass try: set.destroy(SYS_SET) except: pass log.critical('--> failed to create shield, hint: do other cpusets exist?') raise instance log.info('--> activating shielding:') else: log.debug("shielding exists, modifying cpuspec") # note, since we're going to modify the cpu assigments to these sets, # they cannot be exclusive, the following modify() calls will make # them exclusive again cset.unique_set(USR_SET).cpu_exclusive = False cset.unique_set(SYS_SET).cpu_exclusive = False set.modify(USR_SET, cpuspec, memspec, False, False) set.modify(SYS_SET, cpuspec_inv, memspec, False, False) # reset cpu exlusivity cset.unique_set(USR_SET).cpu_exclusive = True cset.unique_set(SYS_SET).cpu_exclusive = True log.info('--> shielding modified with:') # move root tasks into system set root_tasks = cset.unique_set('/').tasks log.debug("number of root tasks are: %s", len(root_tasks)) # figure out what in root set is not a kernel thread tasks = [] for task in root_tasks: try: os.readlink('/proc/'+task+'/exe') tasks.append(task) except: pass if len(tasks) != 0: log.info("moving %s tasks from root into system cpuset...", len(tasks)) proc.move('root', SYS_SET, tasks, verbose) # move kernel theads into system set if asked for if kthread == 'on': root_tasks = cset.unique_set('/').tasks tasks = [] for task in root_tasks: try: if proc.is_unbound(task): tasks.append(task) except: pass if len(tasks) != 0: log.info("kthread shield activated, moving %s tasks into system cpuset...", len(tasks)) proc.move('root', SYS_SET, tasks, verbose) # print out stats print_all_stats()
def pidspec_to_list(pidspec, fset=None, threads=False): """create a list of process ids out of a pidspec""" log.debug('entering pidspecToList, pidspec=%s fset=%s threads=%s', pidspec, fset, threads) if fset: if isinstance(fset, str): fset = cset.unique_set(fset) elif not isinstance(fset, cset.CpuSet): raise CpusetException( "passed fset=%s, which is not a string or CpuSet" % fset) log.debug('from-set specified as: %s', fset.path) if not isinstance(pidspec, str): raise CpusetException('pidspec=%s is not a string' % pidspec) groups = pidspec.split(',') plist = [] nifs = 0 if fset: chktsk = fset.tasks log.debug('parsing groups: %s', groups) for sub in groups: items = sub.split('-') if len(items) == 1: if not len(items[0]): # two consecutive commas in pidspec, just continue processing continue # one pid in this group if fset: try: chktsk.index(items[0]) plist.append(items[0]) log.debug(' added single pid: %s', items[0]) except: log.debug(' task %s not running in %s, skipped', items[0], fset.name) nifs += 1 else: plist.append(items[0]) log.debug(' added single pid: %s', items[0]) elif len(items) == 2: # a range of pids, only include those that exist rng = [ str(x) for x in range(int(items[0]), int(items[1]) + 1) if os.access('/proc/' + str(x), os.F_OK) ] if fset: for tsk in rng: try: chktsk.index(tsk) plist.append(tsk) log.debug(' added task from range: %s', tsk) except: log.debug(' task %s not running in %s, skipped', tsk, fset.name) nifs += 1 else: plist.extend(rng) log.debug(' added range of pids from %s-%s: %s', items[0], items[1], rng) else: raise CpusetException('pidspec=%s has bad group=%s' % (pidspec, items)) log.debug('raw parsed pid list of %s tasks: %s', len(plist), plist) if nifs > 0: if nifs > 1: nmsg = "tasks" else: nmsg = "task" log.info('**> skipped %s %s, not in origination set "%s"', nifs, nmsg, fset.name) log.debug('checking for duplicates...') pdict = {} dups = 0 for task in plist: if task in pdict: dups += 1 continue pdict[task] = True log.debug('found %s duplicates', dups) if threads: log.debug('thread matching activated, looking for threads...') dups = 0 hits = 0 for task in pdict.keys(): dirs = os.listdir('/proc/' + str(task) + '/task') if len(dirs) > 1: hits += 1 for thread in dirs: if thread in pdict: dups += 1 continue pdict[thread] = True log.debug('found %s multithreaded containers and %s duplicates', hits, dups) plist = pdict.keys() log.debug('returning parsed pid list of %s tasks: %s', len(plist), plist) return plist