Hello community, here is the log from the commit of package cpuset for openSUSE:Factory checked in at 2018-12-11 15:49:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cpuset (Old) and /work/SRC/openSUSE:Factory/.cpuset.new.19453 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cpuset" Tue Dec 11 15:49:30 2018 rev:30 rq:657094 version:1.6 Changes: -------- --- /work/SRC/openSUSE:Factory/cpuset/cpuset.changes 2018-03-28 10:34:08.339094925 +0200 +++ /work/SRC/openSUSE:Factory/.cpuset.new.19453/cpuset.changes 2018-12-11 15:49:32.678093056 +0100 @@ -1,0 +2,5 @@ +Tue Dec 11 07:49:13 UTC 2018 - [email protected] + +- Update to 6c46d71a1c6e, release v1.6 + +------------------------------------------------------------------- Old: ---- v1.6pre1.tar.gz New: ---- v1.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cpuset.spec ++++++ --- /var/tmp/diff_new_pack.BFgNwN/_old 2018-12-11 15:49:33.278092393 +0100 +++ /var/tmp/diff_new_pack.BFgNwN/_new 2018-12-11 15:49:33.278092393 +0100 @@ -17,7 +17,6 @@ # -%define realver 1.6pre1 %if 0%{?suse_version} < 1315 %define pyver python %else @@ -29,13 +28,13 @@ BuildArch: noarch %endif Name: cpuset -Version: 1.6~pre1 +Version: 1.6 Release: 0 Summary: Allows manipulation of cpusets on system and provides higher level functions License: GPL-2.0-only Group: System/Management -URL: https://github.com/lpechacek/cpuset -Source: https://github.com/lpechacek/cpuset/archive/v%{realver}.tar.gz +Url: https://github.com/lpechacek/cpuset +Source: https://github.com/lpechacek/cpuset/archive/v%{version}.tar.gz BuildRequires: %{pyver}-setuptools Requires: %{pyver}-future @@ -47,7 +46,7 @@ shielding setup. %prep -%setup -q -n %{name}-%{realver} +%setup -q %build %{pyver} setup.py build @@ -68,7 +67,6 @@ install -m 0444 doc/*.html %{buildroot}/%{_defaultdocdir}/%{name}/html/ %files -%defattr(-,root,root) %doc %{_docdir}/%{name} %{_bindir}/cset %if 0%{?suse_version} < 1315 ++++++ v1.6pre1.tar.gz -> v1.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/NEWS new/cpuset-1.6/NEWS --- old/cpuset-1.6pre1/NEWS 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/NEWS 2018-12-10 17:34:12.000000000 +0100 @@ -1,4 +1,14 @@ ============================================================ +Cpuset 1.6 (December 10, 2018) +https://github.com/lpechacek/cpuset +http://download.opensuse.org/repositories/home:/LPechacek:/cpuset-release/ + +Update to 1.6 includes following changes: + +* Fixes for Python 2 compatibility +* Code compaction for improved maintainability + +============================================================ Cpuset 1.6pre1 (February 8, 2018) https://github.com/lpechacek/cpuset http://download.opensuse.org/repositories/home:/LPechacek:/cpuset-release/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/commands/common.py new/cpuset-1.6/cpuset/commands/common.py --- old/cpuset-1.6pre1/cpuset/commands/common.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/commands/common.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,8 +1,10 @@ """Common functions and variables for all commands """ +from __future__ import unicode_literals __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/commands/mem.py new/cpuset-1.6/cpuset/commands/mem.py --- old/cpuset-1.6pre1/cpuset/commands/mem.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/commands/mem.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,8 +1,10 @@ """Memory node manipulation command """ +from __future__ import unicode_literals __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/commands/proc.py new/cpuset-1.6/cpuset/commands/proc.py --- old/cpuset-1.6pre1/cpuset/commands/proc.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/commands/proc.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,11 +1,12 @@ """Process manipulation command """ +from __future__ import unicode_literals from builtins import str -from builtins import range +from future.utils import lrange __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. -Copyright (C) 2013-2017 SUSE +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify @@ -324,7 +325,7 @@ l = [] if isinstance(args, list): for s in args: - if isinstance(s, str): + if isstr(s): l.extend(cset.find_sets(s)) elif not isinstance(s, cset.CpuSet): raise CpusetException( @@ -333,7 +334,7 @@ else: l.append(s) else: - if isinstance(args, str): + if isstr(args): l.extend(cset.find_sets(args)) elif not isinstance(args, cset.CpuSet): raise CpusetException( @@ -354,14 +355,14 @@ 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): + if isstr(fromset): 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): + if isstr(toset): tset = cset.unique_set(toset) elif not isinstance(toset, cset.CpuSet): raise CpusetException( @@ -527,7 +528,7 @@ move(None, target, tasks) def run(tset, args, usr_par=None, grp_par=None): - if isinstance(tset, str): + if isstr(tset): s = cset.unique_set(tset) elif not isinstance(tset, cset.CpuSet): raise CpusetException( @@ -592,11 +593,11 @@ log.debug('entering pidspecToList, pidspec=%s fset=%s threads=%s', pidspec, fset, threads) if fset: - if isinstance(fset, str): fset = cset.unique_set(fset) + if isstr(fset): 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): + if not isstr(pidspec): raise CpusetException('pidspec=%s is not a string' % pidspec) groups = pidspec.split(',') plist = [] @@ -623,7 +624,7 @@ 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) + rng = [str(x) for x in lrange(int(items[0]), int(items[1])+1) if os.access('/proc/'+str(x), os.F_OK)] if fset: for tsk in rng: @@ -706,21 +707,21 @@ pid = str(pid) if not os.access('/proc/'+pid, os.F_OK): raise CpusetException('task "%s" does not exist' % pid) - status = io.open('/proc/'+pid+'/status', 'r', encoding="ascii").readlines() + status = io.open('/proc/'+pid+'/status', 'r',encoding="iso8859-1").readlines() stdict = {} for line in status: try: stdict[line.split()[0][:-1]] = line.split(':')[1].strip() except: pass # sometimes, we get an extra \n out of this file... - stat = io.open('/proc/'+pid+'/stat', 'r', encoding="ascii").readline() + stat = io.open('/proc/'+pid+'/stat', 'r',encoding="iso8859-1").readline() # we assume parentheses appear only around the name stat_right_paren = stat.rfind(')') stat_left_paren = stat.find('(') stat = [stat[:stat_left_paren-1]] + \ [stat[stat_left_paren:stat_right_paren+1]] + \ stat[stat_right_paren+2:].split() - cmdline = io.open('/proc/'+pid+'/cmdline', encoding="ascii").readline() + cmdline = io.open('/proc/'+pid+'/cmdline',encoding="iso8859-1").readline() # assume that a zero delimits the cmdline (it does now...) cmdline = cmdline.replace('\0', ' ') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/commands/set.py new/cpuset-1.6/cpuset/commands/set.py --- old/cpuset-1.6pre1/cpuset/commands/set.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/commands/set.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,10 +1,11 @@ """Cpuset manipulation command """ +from __future__ import unicode_literals from builtins import str __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. -Copyright (C) 2013-2017 SUSE +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify @@ -288,7 +289,7 @@ def destroy(name): """destroy one cpuset by name as cset or string""" log.debug('entering destroy, name=%s', name) - if isinstance(name, str): + if isstr(name): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException( @@ -402,7 +403,7 @@ """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): + if isstr(name): nset = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException( @@ -418,7 +419,7 @@ 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): + if isstr(name): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException("passing bogus name=%s" % name) @@ -442,7 +443,7 @@ def set_details(name, indent=None, width=None, usehex=False): """return string of cpuset details""" if width == None: width = 0 - if isinstance(name, str): + if isstr(name): set = cset.unique_set(name) elif not isinstance(name, cset.CpuSet): raise CpusetException("passing bogus set=%s" % name) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/commands/shield.py new/cpuset-1.6/cpuset/commands/shield.py --- old/cpuset-1.6pre1/cpuset/commands/shield.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/commands/shield.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,10 +1,11 @@ """Shield supercommand """ +from __future__ import unicode_literals from builtins import str __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. -Copyright (C) 2013-2017 SUSE +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/config.py new/cpuset-1.6/cpuset/config.py --- old/cpuset-1.6pre1/cpuset/config.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/config.py 2018-12-10 17:34:12.000000000 +0100 @@ -7,13 +7,14 @@ Anything found in the configuration files in the list of paths will override these defaults. """ +from __future__ import unicode_literals from __future__ import print_function from future import standard_library standard_library.install_aliases() __copyright__ = """ Copyright (C) 2009-2010 Novell Inc. -Copyright (C) 2013-2017 SUSE +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/cset.py new/cpuset-1.6/cpuset/cset.py --- old/cpuset-1.6pre1/cpuset/cset.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/cset.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,10 +1,11 @@ """Cpuset class and cpuset graph, importing module will create model """ +from __future__ import unicode_literals from __future__ import print_function +from future.utils import lrange import io from builtins import str -from builtins import range from builtins import object __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. @@ -79,16 +80,11 @@ log.debug("starting bottom-up discovery walk...") for dir, dirs, files in os.walk(path, topdown=False): log.debug("*** walking %s", dir) - if dir != CpuSet.basepath: - node = CpuSet(dir) - else: - node = self + node = self if dir == CpuSet.basepath else CpuSet(dir) node.subsets = [] for sub in dirs: - if len(sub) > 0: - relpath = os.path.join(dir,sub).replace(CpuSet.basepath, '') - else: - relpath = '/' + relpath = (os.path.join(dir,sub).replace(CpuSet.basepath, '') + if len(sub) > 0 else '/') node.subsets.append(CpuSet.sets[relpath]) log.debug("%s has %i subsets: [%s]", dir, len(node.subsets), '|'.join(dirs)) @@ -114,10 +110,8 @@ else: # one new cpuset node log.debug("new cpuset node absolute: %s", path) - if len(path) > len(CpuSet.basepath): - path = path.replace(CpuSet.basepath, '') - else: - path = '/' + path = (path.replace(CpuSet.basepath, '') + if len(path) > len(CpuSet.basepath) else '/') log.debug(" relative: %s", path) if path in CpuSet.sets: log.debug("the cpuset %s already exists, skipping", path) @@ -135,32 +129,14 @@ def locate_cpusets(self): log.debug("locating cpuset filesystem...") - cpuset = re.compile(r"none (/.+) cpuset .+") - cgroup = re.compile(r"none (/.+) cgroup .+") - cpuset1 = re.compile(r"cpuset (/.+) cpuset .+") - cgroup1 = re.compile(r"cgroup (/.+) cgroup .+") + cpuset_mount_regex = re.compile(r"^[^ ]+ (/.+) (?:cpuset |cgroup (?:[^ ]*,)?cpuset[, ])") path = None - f = io.open("/proc/mounts", encoding="ascii") + f = io.open("/proc/mounts",encoding="iso8859-1") for line in f: - res = cpuset.search(line) - if res: - path = res.group(1) - break - res = cpuset1.search(line) + res = cpuset_mount_regex.search(line) if res: path = res.group(1) break - else: - if cgroup.search(line): - groups = line.split() - if re.search("cpuset", groups[3]): - path = groups[1] - break - if cgroup1.search(line): - groups = line.split() - if re.search("cpuset", groups[3]): - path = groups[1] - break f.close() if not path: @@ -183,71 +159,58 @@ self.name = path[path.rfind('/')+1:] log.debug("...name=%s", self.name) + def read_first_line_from(self, file_to_read): + f = io.open(CpuSet.basepath+self.path+file_to_read, encoding="iso8859-1") + retval = f.readline().strip() + f.close() + return retval + + def write_value_to(self, file_to_write, value): + log.debug("-> prop_set %s.%s = %s", self.path, file_to_write, value) + f = io.open(CpuSet.basepath+self.path+file_to_write, 'w', encoding="iso8859-1") + f.write(str(value)) + f.close() + + def write_01_to(self, file_to_write, value): + self.write_value_to(file_to_write, '1' if value else '0') + # Properties of cpuset node def delprop(self): raise AttributeError("deletion of properties not allowed") def getcpus(self): - f = io.open(CpuSet.basepath+self.path+CpuSet.cpus_path, encoding="ascii") - return f.readline()[:-1] + return self.read_first_line_from(CpuSet.cpus_path) def setcpus(self, newval): cpuspec_check(newval) - f = io.open(CpuSet.basepath+self.path+CpuSet.cpus_path,'w', encoding="ascii") - f.write(str(newval)) - f.close() - log.debug("-> prop_set %s.cpus = %s", self.path, newval) + self.write_value_to(CpuSet.cpus_path, newval) cpus = property(fget=getcpus, fset=setcpus, fdel=delprop, doc="CPU specifier") def getmems(self): - f = io.open(CpuSet.basepath+self.path+CpuSet.mems_path, encoding="ascii") - return f.readline()[:-1] + return self.read_first_line_from(CpuSet.mems_path) def setmems(self, newval): # FIXME: check format for correctness - f = io.open(CpuSet.basepath+self.path+CpuSet.mems_path,'w', encoding="ascii") - f.write(str(newval)) - f.close() - log.debug("-> prop_set %s.mems = %s", self.path, newval) + self.write_value_to(CpuSet.mems_path, newval) mems = property(getmems, setmems, delprop, "Mem node specifier") def getcpuxlsv(self): - f = io.open(CpuSet.basepath+self.path+CpuSet.cpu_exclusive_path, encoding="ascii") - if f.readline()[:-1] == '1': - return True - else: - return False + return self.read_first_line_from(CpuSet.cpu_exclusive_path) == '1' def setcpuxlsv(self, newval): - log.debug("-> prop_set %s.cpu_exclusive = %s", self.path, newval) - f = io.open(CpuSet.basepath+self.path+CpuSet.cpu_exclusive_path,'w', encoding="ascii") - if newval: - f.write('1') - else: - f.write('0') - f.close() + self.write_01_to(CpuSet.cpu_exclusive_path, newval) cpu_exclusive = property(getcpuxlsv, setcpuxlsv, delprop, "CPU exclusive flag") def getmemxlsv(self): - f = io.open(CpuSet.basepath+self.path+CpuSet.mem_exclusive_path, encoding="ascii") - if f.readline()[:-1] == '1': - return True - else: - return False + return self.read_first_line_from(CpuSet.mem_exclusive_path) == '1' def setmemxlsv(self, newval): - log.debug("-> prop_set %s.mem_exclusive = %s", self.path, newval) - f = io.open(CpuSet.basepath+self.path+CpuSet.mem_exclusive_path,'w', encoding="ascii") - if newval: - f.write('1') - else: - f.write('0') - f.close() + self.write_01_to(CpuSet.mem_exclusive_path, newval) mem_exclusive = property(getmemxlsv, setmemxlsv, delprop, "Memory exclusive flag") def gettasks(self): - f = io.open(CpuSet.basepath+self.path+CpuSet.tasks_path, encoding="ascii") - lst = [] - for task in f: lst.append(task[:-1]) - return lst + f = io.open(CpuSet.basepath+self.path+CpuSet.tasks_path,encoding="iso8859-1") + lst = map(lambda line: line.strip(), f.readlines()) + f.close() + return list(lst) def settasks(self, tasklist): notfound = [] unmovable = [] @@ -259,7 +222,7 @@ prog = False for task in tasklist: try: - f = io.open(CpuSet.basepath+self.path+CpuSet.tasks_path,'w', encoding="ascii") + f = io.open(CpuSet.basepath+self.path+CpuSet.tasks_path,'w',encoding="iso8859-1") f.write(task) f.close() except Exception as err: @@ -291,7 +254,9 @@ log.debug("entering lookup_task_from_proc, pid = %s", str(pid)) path = "/proc/"+str(pid)+"/cpuset" if os.access(path, os.F_OK): - set = io.open(path, encoding="ascii").readline()[:-1] + f = io.open(path,encoding="iso8859-1") + set = f.readline().strip() + f.close() log.debug('lookup_task_from_proc: found task %s cpuset: %s', str(pid), set) return set # FIXME: add search for threads here... @@ -419,8 +384,8 @@ number |= 1 << int(items[0]) elif len(items) == 2: il = [int(ii) for ii in items] - if il[1] >= il[0]: rng = list(range(il[0], il[1]+1)) - else: rng = list(range(il[1], il[0]+1)) + if il[1] >= il[0]: rng = lrange(il[0], il[1]+1) + else: rng = lrange(il[1], il[0]+1) log.debug(' group=%s has cpu range of %s', sub, rng) for num in rng: number |= 1 << num else: @@ -442,7 +407,7 @@ def cpuspec_inverse(cpuspec): """calculate inverse of cpu specification""" - cpus = [0 for x in range(maxcpu+1)] + cpus = [0 for x in lrange(maxcpu+1)] groups = cpuspec.split(',') log.debug("cpuspec_inverse(%s) maxcpu=%d groups=%d", cpuspec, maxcpu, len(groups)) @@ -455,29 +420,23 @@ continue cpus[int(items[0])] = 1 elif len(items) == 2: - for x in range(int(items[0]), int(items[1])+1): + for x in lrange(int(items[0]), int(items[1])+1): cpus[x] = 1 else: raise CpusetException("cpuspec(%s) has bad group %s" % (cpuspec, set)) log.debug("cpuspec array: %s", cpus) # calculate inverse of array - for x in range(0, len(cpus)): - if cpus[x] == 0: - cpus[x] = 1 - else: - cpus[x] = 0 + for x in lrange(0, len(cpus)): + cpus[x] = int(cpus[x] == 0) log.debug(" inverse: %s", cpus) # build cpuspec expression nspec = "" ingrp = False - for x in range(0, len(cpus)): + for x in lrange(0, len(cpus)): if cpus[x] == 0 and ingrp: nspec += str(begin) if x > begin+1: - if cpus[x] == 1: - nspec += '-' + str(x) - else: - nspec += '-' + str(x-1) + nspec += '-' + str(x if cpus[x] else x-1) ingrp = False if cpus[x] == 1: if not ingrp: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/main.py new/cpuset-1.6/cpuset/main.py --- old/cpuset-1.6pre1/cpuset/main.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/main.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,5 +1,6 @@ """Front end command line tool for Linux cpusets """ +from __future__ import unicode_literals from __future__ import print_function from __future__ import absolute_import @@ -8,7 +9,7 @@ from builtins import str __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. -Copyright (C) 2013-2017 SUSE +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/util.py new/cpuset-1.6/cpuset/util.py --- old/cpuset-1.6pre1/cpuset/util.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/util.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,13 +1,14 @@ """Utility functions """ +from __future__ import unicode_literals from __future__ import print_function +from future.utils import lrange from builtins import chr -from builtins import range from builtins import object __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. -Copyright (C) 2013-2017 SUSE +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify @@ -42,34 +43,23 @@ class CpusetExists(CpusetException): pass -# a twirling bar progress indicator -class TwirlyBar(object): - def __init__(self): - import sys - self.__dict__['__call__'] = self.tick - self.__state = 0 - self.__bar = ('|', '/', '-', '\\') - - def tick(self): - if not config.mread: - print('\b' + self.__bar[self.__state] + '\b', end=' ') - self.__state = self.__state + 1 - if self.__state > 3: self.__state = 0 - - def fastick(self): - for x in range(10): - self.tick() - time.sleep(0.04) +try: + basestring # attempt to evaluate basestring + def isstr(s): + return isinstance(s, basestring) +except NameError: + def isstr(s): + return isinstance(s, str) # a progress bar indicator class ProgressBar(object): def __init__(self, finalcount, progresschar=None): - self.__dict__['__call__'] = self.progress self.finalcount=finalcount self.blockcount=0 - # Use ascii block char for progress if none passed + self.finished=False + # Use dark shade (U+2593) char for progress if none passed if not progresschar: - self.block=chr(178) + self.block='\u2593' else: self.block=progresschar if config.mread: @@ -77,11 +67,17 @@ self.f=sys.stdout if not self.finalcount: return self.f.write('[') - for i in range(50): self.f.write(' ') + for i in lrange(50): self.f.write(' ') self.f.write(']%') - for i in range(52): self.f.write('\b') + for i in lrange(52): self.f.write('\b') + + def __call__(self, count): + self.progress(count) def progress(self, count): + if self.finished: + return + count=min(count, self.finalcount) if self.finalcount: @@ -89,14 +85,17 @@ if percentcomplete < 1: percentcomplete=1 else: percentcomplete=100 + self.finished=True + return blockcount=percentcomplete//2 if not config.mread: if blockcount > self.blockcount: - for i in range(self.blockcount,blockcount): + for i in lrange(self.blockcount,blockcount): self.f.write(self.block) self.f.flush() - if percentcomplete == 100: self.f.write("]\n") + if percentcomplete == 100: + self.f.write("]\n") + self.finished=True self.blockcount=blockcount - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset/version.py new/cpuset-1.6/cpuset/version.py --- old/cpuset-1.6pre1/cpuset/version.py 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset/version.py 2018-12-10 17:34:12.000000000 +0100 @@ -1,5 +1,8 @@ +from __future__ import unicode_literals + __copyright__ = """ Copyright (C) 2007-2010 Novell Inc. +Copyright (C) 2013-2018 SUSE Author: Alex Tsariounov <[email protected]> This program is free software; you can redistribute it and/or modify @@ -16,4 +19,4 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -version = '1.6pre1' +version = '1.6' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/cpuset.spec new/cpuset-1.6/cpuset.spec --- old/cpuset-1.6pre1/cpuset.spec 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/cpuset.spec 2018-12-10 17:34:12.000000000 +0100 @@ -1,39 +1,44 @@ -# -# Spec file for package cpuset -# -# Copyright (c) 2008-2010 Novell, Inc. Waltham, MA, USA -# This file and all modifications and additions to the pristine -# package are under the same license as the package itself. -# -# Please submit bugfixes or comments via -# https://github.com/lpechacek/cpuset/issues -# Or -# https://bugzilla.opensuse.org -# -# For supported products, via https://bugzilla.suse.com -# - -# norootforbuild - +# +# spec file for package cpuset +# +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2008-2011 Novell, Inc. Waltham, MA, USA +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%if 0%{?suse_version} < 1315 +%define pyver python +%else +%define pyver python3 +%endif +%if 0%{?suse_version} && 0%{?suse_version} <= 1110 +%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +%else +BuildArch: noarch +%endif Name: cpuset -Version: 1.6pre1 -Release: 1 -License: GPL-2.0 -BuildRoot: %{_tmppath}/%{name}-%{version}-build -Url: https://github.com/lpechacek/cpuset -Group: System/Management +Version: 1.6 +Release: 0 Summary: Allows manipulation of cpusets on system and provides higher level functions -Source: %{name}-%{version}.tar.gz -BuildRequires: python-devel - -%if 0%{?suse_version} > 0 -%py_requires -%endif - -%{!?python_sitelib: %define python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +License: GPL-2.0-only +Group: System/Management +URL: https://github.com/lpechacek/cpuset +Source: https://github.com/lpechacek/cpuset/archive/v%{version}.tar.gz +BuildRequires: %{pyver}-setuptools +Requires: %{pyver}-future %description - Cpuset is a Python application to make using the cpusets facilities in the Linux kernel easier. The actual included command is called cset and it allows manipulation of cpusets on the system and provides higher @@ -41,42 +46,34 @@ shielding setup. %prep -%setup - +%setup -q -n %{name}-%{version} %build -CFLAGS="%{optflags}" \ -%{__python} setup.py build +%{pyver} setup.py build #make doc ->not yet, asciidoc is missing... - %install # Install binaries, but do not install docs via setup.py -%{__python} setup.py install --root=%{buildroot} --prefix=%{_prefix} --install-data=/eraseme -%{__rm} -rf %{buildroot}/eraseme +%{pyver} setup.py install --root=%{buildroot} --prefix=%{_prefix} --install-data=/eraseme +rm -rf %{buildroot}/eraseme # Install documentation -%{__mkdir_p} %{buildroot}/%{_defaultdocdir}/cpuset -%{__cp} NEWS README INSTALL AUTHORS COPYING cset.init.d %{buildroot}/%{_defaultdocdir}/cpuset/ -%{__mkdir_p} %{buildroot}/%{_mandir}/man1 -cd doc -%{__gzip} *.1 -%{__cp} *.1.gz %{buildroot}/%{_mandir}/man1 -%{__cp} *.txt %{buildroot}/%{_defaultdocdir}/cpuset/ -%{__mkdir} %{buildroot}/%{_defaultdocdir}/cpuset/html -%{__cp} *.html %{buildroot}/%{_defaultdocdir}/cpuset/html/ +mkdir -p %{buildroot}/%{_mandir}/man1 +mkdir -p %{buildroot}/%{_defaultdocdir}/%{name}/html +install -m 0444 doc/*.1 %{buildroot}/%{_mandir}/man1 -%clean -%{__rm} -rf %{buildroot} - +install -m 0444 NEWS README AUTHORS COPYING cset.init.d doc/*.txt %{buildroot}/%{_defaultdocdir}/%{name} +install -m 0444 doc/*.html %{buildroot}/%{_defaultdocdir}/%{name}/html/ %files -%defattr(-,root,root) +%doc %{_docdir}/%{name} %{_bindir}/cset +%if 0%{?suse_version} < 1315 %{python_sitelib}/* +%else +%{python3_sitelib}/* +%endif %{_mandir}/man1/* -%{_defaultdocdir}/* - %changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/doc/cset-proc.txt new/cpuset-1.6/doc/cset-proc.txt --- old/cpuset-1.6pre1/doc/cset-proc.txt 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/doc/cset-proc.txt 2018-12-10 17:34:12.000000000 +0100 @@ -1,7 +1,7 @@ cset-proc(1) ============ Alex Tsariounov <[email protected]> -v1.6pre1, February 2018 +v1.6, December 2018 NAME ---- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/doc/cset-set.txt new/cpuset-1.6/doc/cset-set.txt --- old/cpuset-1.6pre1/doc/cset-set.txt 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/doc/cset-set.txt 2018-12-10 17:34:12.000000000 +0100 @@ -1,7 +1,7 @@ cset-set(1) =========== Alex Tsariounov <[email protected]> -v1.6pre1, February 2018 +v1.6, December 2018 NAME ---- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/doc/cset-shield.txt new/cpuset-1.6/doc/cset-shield.txt --- old/cpuset-1.6pre1/doc/cset-shield.txt 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/doc/cset-shield.txt 2018-12-10 17:34:12.000000000 +0100 @@ -1,7 +1,7 @@ cset-shield(1) ============== Alex Tsariounov <[email protected]> -v1.6pre1, February 2018 +v1.6, December 2018 NAME ---- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/doc/cset.txt new/cpuset-1.6/doc/cset.txt --- old/cpuset-1.6pre1/doc/cset.txt 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/doc/cset.txt 2018-12-10 17:34:12.000000000 +0100 @@ -1,7 +1,7 @@ cset(1) ====== Alex Tsariounov <[email protected]> -v1.6pre1, February 2018 +v1.6, December 2018 NAME ---- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/t/README new/cpuset-1.6/t/README --- old/cpuset-1.6pre1/t/README 2018-02-08 08:34:29.000000000 +0100 +++ new/cpuset-1.6/t/README 2018-12-10 17:34:12.000000000 +0100 @@ -1,4 +1,24 @@ CPUSET Tests ============ +* trigger-all.sh + - a shell script designed to trigger most code paths in cpuset + - as a side effect it can be used to check if something broke after a code + change + - procedure (as root): + 1) run trigger-all.sh with known-good version of cset utility, store output + into a file + 2) re-run the same test with your changed version - use both Python 2 and 3 + - storing script output into files + 3) compare these three files side by side (e.g. in vimdiff) looking for + irregularities + Hints: Use PYTHONIOENCODING=utf-8 to get correct output of test_util.py when + redirected into pipe. Consider filtering out numbers from script output as + they change (primarily PIDs) and typically form just noise. See + run-trigger-all.sh for an example. +* test_cset.py (run from trigger-all.sh) + - the test assumes 4 CPUs + - run test as root + - set up a shield before running the test: + cset shield -s -c 2-3 -k on diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/t/run-trigger-all.sh new/cpuset-1.6/t/run-trigger-all.sh --- old/cpuset-1.6pre1/t/run-trigger-all.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/cpuset-1.6/t/run-trigger-all.sh 2018-12-10 17:34:12.000000000 +0100 @@ -0,0 +1,4 @@ +#!/bin/bash + +PYTHONIOENCODING=utf-8 PYTHON_INTERPRETER=python2 bash -x t/trigger_all.sh 2>&1 | sed '/^[^+]/s/[[:digit:]]\+/NUMBER/g;/^+/{s/python[23]/PYTHON_INTERPRETER/;s/\(shield\|-p\|-s\) [[:digit:]]\+/\1 NUMBER/g}' > t/trigger_all-python2 +PYTHONIOENCODING=utf-8 PYTHON_INTERPRETER=python3 bash -x t/trigger_all.sh 2>&1 | sed '/^[^+]/s/[[:digit:]]\+/NUMBER/g;/^+/{s/python[23]/PYTHON_INTERPRETER/;s/\(shield\|-p\|-s\) [[:digit:]]\+/\1 NUMBER/g}' > t/trigger_all-python3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/t/test_cset.py new/cpuset-1.6/t/test_cset.py --- old/cpuset-1.6pre1/t/test_cset.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cpuset-1.6/t/test_cset.py 2018-12-10 17:34:12.000000000 +0100 @@ -0,0 +1,110 @@ +# Prepare system for the test with: +# cset shield -s -c 2-3 -k on +# The test assumes 4 CPUs. +# +# Feel free to improve the unit test. + +from __future__ import unicode_literals +from __future__ import print_function +from cpuset import cset +from cpuset.util import CpusetException +import unittest + +class TestCpuSetProperties(unittest.TestCase): + + def setUp(self): + cset.rescan() + self.test_set=cset.unique_set("user") + + def test_cpus(self): + self.test_set.cpus = "2-3" + self.assertEqual(self.test_set.cpus, "2-3") + with self.assertRaises(AttributeError): + del self.test_set.cpus + + def test_mems(self): + self.test_set.mems = "0" + self.assertEqual(self.test_set.mems, "0") + with self.assertRaises(AttributeError): + del self.test_set.mems + + def test_cpu_excl(self): + self.test_set.cpu_exclusive = "" + self.assertFalse(self.test_set.cpu_exclusive) + with self.assertRaises(AttributeError): + del self.test_set.cpu_exclusive + + def test_mem_excl(self): + self.test_set.mem_exclusive = "" + self.assertFalse(self.test_set.mem_exclusive) + with self.assertRaises(AttributeError): + del self.test_set.mem_exclusive + + def test_tasks(self): + self.test_set.tasks = "" + self.assertEqual(self.test_set.tasks, []) + with self.assertRaises(AttributeError): + del self.test_set.tasks + + def test_unused_code(self): + # unused + self.assertEqual(cset.lookup_task_from_proc(1), "/system") + with self.assertRaises(CpusetException): + cset.lookup_task_from_proc(99999999999) + + # unused + broken + #print(cset.lookup_task_from_cpusets(1)) + with self.assertRaises(CpusetException): + cset.lookup_task_from_cpusets(99999999999) + + 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 test_cpuspec_check(self): + # these overlap with cpuset_inverse tests bellow + # remove them after the code duplicaton is eliminated + self.assertEqual(cset.cpuspec_check("0-3"), None) + self.assertEqual(cset.cpuspec_check("0-1,,3"), None) + with self.assertRaises(CpusetException): + print('check of 1-2-3:', cset.cpuspec_check("1-2-3")) + with self.assertRaises(CpusetException): + print('check of 1!2-3:', cset.cpuspec_check("1!2-3")) + with self.assertRaises(CpusetException): + # 999999 CPUs ought to be enough for anybody + cset.cpuspec_check("999999", usemax=True) + with self.assertRaises(CpusetException): + print('check of -3:', cset.cpuspec_check("-3")) + + def test_cpuspec_to_hex(self): + self.assertEqual(cset.cpuspec_to_hex("0-3"), "f") + self.assertEqual(cset.cpuspec_to_hex("0-1,,3"), "b") + with self.assertRaises(CpusetException): + cset.cpuspec_to_hex("1-2-3") + # ^^ remove them after the code duplicaton is eliminated + + def test_memspec_check(self): + self.assertEqual(cset.memspec_check("0-3"), None) + with self.assertRaises(CpusetException): + cset.memspec_check("0!3") + + def test_cpuspec_inverse(self): + self.assertEqual(cset.cpuspec_inverse("0,2"), "1,3") + self.assertEqual(cset.cpuspec_inverse("0-1"), "2-3") + self.assertEqual(cset.cpuspec_inverse("2-3"), "0-1") + self.assertEqual(cset.cpuspec_inverse("0-1,3"), "2") + self.assertEqual(cset.cpuspec_inverse("0,2-3"), "1") + self.assertEqual(cset.cpuspec_inverse("0,,3-3"), "1-2") + with self.assertRaises(CpusetException): + cset.cpuspec_inverse("1-2-3") + + def test_calc_cpumask(self): + self.assertEqual(cset.calc_cpumask(4), "1f") + +if __name__ == '__main__': + unittest.main() + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/t/test_util.py new/cpuset-1.6/t/test_util.py --- old/cpuset-1.6pre1/t/test_util.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cpuset-1.6/t/test_util.py 2018-12-10 17:34:12.000000000 +0100 @@ -0,0 +1,23 @@ +from __future__ import print_function +from cpuset import util,config +import time + +print("invocation with max set - progress bar should appear") +p = util.ProgressBar(15) +for n in range(18): + time.sleep(0.07) + p(n) + +print("invocation without max set - nothing should appear") +p = util.ProgressBar(0) +for n in range(18): + time.sleep(0.07) + p(n) + +print("invocation with max set and machine readable output set - nothing should appear") +config.mread=True +p = util.ProgressBar(15) +for n in range(18): + time.sleep(0.07) + p(n) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cpuset-1.6pre1/t/trigger_all.sh new/cpuset-1.6/t/trigger_all.sh --- old/cpuset-1.6pre1/t/trigger_all.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/cpuset-1.6/t/trigger_all.sh 2018-12-10 17:34:12.000000000 +0100 @@ -0,0 +1,68 @@ +#!/bin/bash + +PROG_PATH=$(dirname $0)/.. +PYTHON_INTERPRETER=${PYTHON_INTERPRETER:-"python3"} + +cd $PROG_PATH +ln -s . bin +$PYTHON_INTERPRETER bin/cset help # bin/ preix to trigget more code paths +$PYTHON_INTERPRETER cset version +$PYTHON_INTERPRETER cset -l /dev/shm/cset.log copyright +$PYTHON_INTERPRETER cset shield -c 2-3 -e /bin/true +$PYTHON_INTERPRETER cset shield /bin/true # and another way to exec a command behind the shield +$PYTHON_INTERPRETER cset shield -r +$PYTHON_INTERPRETER cset -m shield -s -c 3 -k off # -m for "machine readable output" +$PYTHON_INTERPRETER cset shield -s # surprisingly this is a way to print out user shield stats +$PYTHON_INTERPRETER cset shield -u # and system shield stats +$PYTHON_INTERPRETER cset shield -s -c 2-3 -k on # trigger shield modify operation +$PYTHON_INTERPRETER cset shield -s -p $$ +$PYTHON_INTERPRETER cset shield -s -p $$ --force # just to trigger one more code path +$PYTHON_INTERPRETER cset shield -s $$ +$PYTHON_INTERPRETER cset shield $$ # same as "-s -p <PID> +$PYTHON_INTERPRETER cset shield -v # trigger shield stats routines, -v for verbose +$PYTHON_INTERPRETER cset shield -v -v # -v -v for more verbosity +$PYTHON_INTERPRETER cset shield -u -p $$ +$PYTHON_INTERPRETER cset shield -k on +$PYTHON_INTERPRETER cset shield -k off + +#----------------- command set --------------------- +$PYTHON_INTERPRETER cset set +$PYTHON_INTERPRETER cset set -l -v +$PYTHON_INTERPRETER cset set -l -x root +$PYTHON_INTERPRETER cset -m set -l -r -s root +$PYTHON_INTERPRETER cset set -s user -n intermediate +$PYTHON_INTERPRETER cset set -n test intermediate +$PYTHON_INTERPRETER cset set -s test/one -c 2 +$PYTHON_INTERPRETER cset set -s test/two -c 3 +$PYTHON_INTERPRETER cset proc -m -s test/one -p $$ # move this process to test/two to trigger more code paths +$PYTHON_INTERPRETER cset set -s test/one -n root/to_delete # intentionally fail +$PYTHON_INTERPRETER cset set -s test/one -n to_delete +$PYTHON_INTERPRETER cset set -d test/to_delete +$PYTHON_INTERPRETER cset set -s test -d -r --force +$PYTHON_INTERPRETER cset set -s user -c 2-3 +$PYTHON_INTERPRETER cset set -s user --mem_exclusive --cpu_exclusive + +#----------------- command proc --------------------- +$PYTHON_INTERPRETER cset proc -l system +$PYTHON_INTERPRETER cset -m proc -l -s system +$PYTHON_INTERPRETER cset proc -e -s user -u lpechacek -g nobody -- /bin/true +$PYTHON_INTERPRETER cset proc -e -s user -u lpechacek -- /bin/true +# fifty shades of move operation +$PYTHON_INTERPRETER cset proc -m -s system -t user -p 1000-3000 --threads +$PYTHON_INTERPRETER cset proc -m -s user -p 1000-2000 --threads +$PYTHON_INTERPRETER cset proc -m -s user -t system --threads +$PYTHON_INTERPRETER cset proc -m -k -f 2-2000 user # -k for kernel threads, -f force +$PYTHON_INTERPRETER cset proc -m 1000-2000 user system +$PYTHON_INTERPRETER cset proc -m -p 1000-2000 system user +$PYTHON_INTERPRETER cset -m proc -v -m -p 1000-2000 system # -m for machine readable output, -v for verbose +$PYTHON_INTERPRETER cset proc -v -m -p $$ user # -v for verbose output +$PYTHON_INTERPRETER cset proc -m user system +$PYTHON_INTERPRETER cset proc -k -s root -t system + +# the below tests assume empty user set +PYTHONPATH=. $PYTHON_INTERPRETER t/test_cset.py +PYTHONPATH=. $PYTHON_INTERPRETER t/test_util.py + +# clean up +PYTHONPATH=. $PYTHON_INTERPRETER cset set -d -r --force user +PYTHONPATH=. $PYTHON_INTERPRETER cset set -d system
