Merge branch 'space_comma'

Merges #140
'Remove all bad-whitespaces and Add necessary whitespaces.'
This commit is contained in:
Mike McLean 2016-08-29 14:37:18 -04:00
commit bf0270cb4b
12 changed files with 736 additions and 736 deletions

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,7 @@ import types
import pprint import pprint
import resource import resource
import xmlrpclib import xmlrpclib
from xmlrpclib import getparser,dumps,Fault from xmlrpclib import getparser, dumps, Fault
from koji.server import WSGIWrapper from koji.server import WSGIWrapper
import koji import koji
@ -69,7 +69,7 @@ class HandlerRegistry(object):
self.register_function(self.system_methodHelp, name="system.methodHelp") self.register_function(self.system_methodHelp, name="system.methodHelp")
self.argspec_cache = {} self.argspec_cache = {}
def register_function(self, function, name = None): def register_function(self, function, name=None):
if name is None: if name is None:
name = function.__name__ name = function.__name__
self.funcs[name] = function self.funcs[name] = function
@ -91,10 +91,10 @@ class HandlerRegistry(object):
if not callable(function): if not callable(function):
continue continue
if prefix is not None: if prefix is not None:
name = "%s.%s" %(prefix,name) name = "%s.%s" %(prefix, name)
self.register_function(function, name=name) self.register_function(function, name=name)
def register_instance(self,instance): def register_instance(self, instance):
self.register_module(instance) self.register_module(instance)
def register_plugin(self, plugin): def register_plugin(self, plugin):
@ -135,7 +135,7 @@ class HandlerRegistry(object):
def list_api(self): def list_api(self):
funcs = [] funcs = []
for name,func in self.funcs.items(): for name, func in self.funcs.items():
#the keys in self.funcs determine the name of the method as seen over xmlrpc #the keys in self.funcs determine the name of the method as seen over xmlrpc
#func.__name__ might differ (e.g. for dotted method names) #func.__name__ might differ (e.g. for dotted method names)
args = self._getFuncArgs(func) args = self._getFuncArgs(func)
@ -242,8 +242,8 @@ class ModXMLRPCRequestHandler(object):
self.traceback = True self.traceback = True
# report exception back to server # report exception back to server
e_class, e = sys.exc_info()[:2] e_class, e = sys.exc_info()[:2]
faultCode = getattr(e_class,'faultCode',1) faultCode = getattr(e_class, 'faultCode', 1)
tb_type = context.opts.get('KojiTraceback',None) tb_type = context.opts.get('KojiTraceback', None)
tb_str = ''.join(traceback.format_exception(*sys.exc_info())) tb_str = ''.join(traceback.format_exception(*sys.exc_info()))
if issubclass(e_class, koji.GenericError): if issubclass(e_class, koji.GenericError):
if context.opts.get('KojiDebug'): if context.opts.get('KojiDebug'):
@ -259,7 +259,7 @@ class ModXMLRPCRequestHandler(object):
elif tb_type == "extended": elif tb_type == "extended":
faultString = koji.format_exc_plus() faultString = koji.format_exc_plus()
else: else:
faultString = "%s: %s" % (e_class,e) faultString = "%s: %s" % (e_class, e)
self.logger.warning(tb_str) self.logger.warning(tb_str)
response = dumps(Fault(faultCode, faultString)) response = dumps(Fault(faultCode, faultString))
@ -277,7 +277,7 @@ class ModXMLRPCRequestHandler(object):
return self._dispatch(method, params) return self._dispatch(method, params)
def check_session(self): def check_session(self):
if not hasattr(context,"session"): if not hasattr(context, "session"):
#we may be called again by one of our meta-calls (like multiCall) #we may be called again by one of our meta-calls (like multiCall)
#so we should only create a session if one does not already exist #so we should only create a session if one does not already exist
context.session = koji.auth.Session() context.session = koji.auth.Session()
@ -285,7 +285,7 @@ class ModXMLRPCRequestHandler(object):
context.session.validate() context.session.validate()
except koji.AuthLockError: except koji.AuthLockError:
#might be ok, depending on method #might be ok, depending on method
if context.method not in ('exclusiveSession','login', 'krbLogin', 'logout'): if context.method not in ('exclusiveSession', 'login', 'krbLogin', 'logout'):
raise raise
def enforce_lockout(self): def enforce_lockout(self):
@ -350,7 +350,7 @@ class ModXMLRPCRequestHandler(object):
return results return results
def handle_request(self,req): def handle_request(self, req):
"""Handle a single XML-RPC request""" """Handle a single XML-RPC request"""
pass pass
@ -393,9 +393,9 @@ def load_config(environ):
# to aid in the transition from PythonOptions to hub.conf, we only load # to aid in the transition from PythonOptions to hub.conf, we only load
# the configfile if it is explicitly configured # the configfile if it is explicitly configured
if cf == '/etc/koji-hub/hub.conf': if cf == '/etc/koji-hub/hub.conf':
cfdir = modpy_opts.get('ConfigDir', '/etc/koji-hub/hub.conf.d') cfdir = modpy_opts.get('ConfigDir', '/etc/koji-hub/hub.conf.d')
else: else:
cfdir = modpy_opts.get('ConfigDir', None) cfdir = modpy_opts.get('ConfigDir', None)
if not cf and not cfdir: if not cf and not cfdir:
logger.warn('Warning: configuring Koji via PythonOptions is deprecated. Use hub.conf') logger.warn('Warning: configuring Koji via PythonOptions is deprecated. Use hub.conf')
else: else:
@ -694,10 +694,10 @@ def server_setup(environ):
plugins = load_plugins(opts) plugins = load_plugins(opts)
registry = get_registry(opts, plugins) registry = get_registry(opts, plugins)
policy = get_policy(opts, plugins) policy = get_policy(opts, plugins)
koji.db.provideDBopts(database = opts["DBName"], koji.db.provideDBopts(database=opts["DBName"],
user = opts["DBUser"], user=opts["DBUser"],
password = opts.get("DBPass",None), password=opts.get("DBPass", None),
host = opts.get("DBHost", None)) host=opts.get("DBHost", None))
except Exception: except Exception:
tb_str = ''.join(traceback.format_exception(*sys.exc_info())) tb_str = ''.join(traceback.format_exception(*sys.exc_info()))
logger.error(tb_str) logger.error(tb_str)
@ -774,7 +774,7 @@ def application(environ, start_response):
time.time() - start) time.time() - start)
finally: finally:
#make sure context gets cleaned up #make sure context gets cleaned up
if hasattr(context,'cnx'): if hasattr(context, 'cnx'):
try: try:
context.cnx.close() context.cnx.close()
except Exception: except Exception:
@ -789,7 +789,7 @@ def get_registry(opts, plugins):
functions = kojihub.RootExports() functions = kojihub.RootExports()
hostFunctions = kojihub.HostExports() hostFunctions = kojihub.HostExports()
registry.register_instance(functions) registry.register_instance(functions)
registry.register_module(hostFunctions,"host") registry.register_module(hostFunctions, "host")
registry.register_function(koji.auth.login) registry.register_function(koji.auth.login)
registry.register_function(koji.auth.krbLogin) registry.register_function(koji.auth.krbLogin)
registry.register_function(koji.auth.sslLogin) registry.register_function(koji.auth.sslLogin)

View file

@ -101,33 +101,33 @@ class Enum(dict):
Can quickly map forward or reverse Can quickly map forward or reverse
""" """
def __init__(self,*args): def __init__(self, *args):
self._order = tuple(*args) self._order = tuple(*args)
super(Enum,self).__init__([(value,n) for n,value in enumerate(self._order)]) super(Enum, self).__init__([(value, n) for n, value in enumerate(self._order)])
def __getitem__(self,key): def __getitem__(self, key):
if isinstance(key,int) or isinstance(key,slice): if isinstance(key, int) or isinstance(key, slice):
return self._order.__getitem__(key) return self._order.__getitem__(key)
else: else:
return super(Enum,self).__getitem__(key) return super(Enum, self).__getitem__(key)
def get(self,key,default=None): def get(self, key, default=None):
try: try:
return self.__getitem__(key) return self.__getitem__(key)
except (IndexError,KeyError): except (IndexError, KeyError):
return default return default
def getnum(self,key,default=None): def getnum(self, key, default=None):
try: try:
value = self.__getitem__(key) value = self.__getitem__(key)
except (IndexError,KeyError): except (IndexError, KeyError):
return default return default
if isinstance(key,int): if isinstance(key, int):
return key return key
else: else:
return value return value
def _notImplemented(self,*args,**opts): def _notImplemented(self, *args, **opts):
raise NotImplementedError raise NotImplementedError
# deprecated # deprecated
@ -352,12 +352,12 @@ class MultiCallInProgress(object):
#A function to get create an exception from a fault #A function to get create an exception from a fault
def convertFault(fault): def convertFault(fault):
"""Convert a fault to the corresponding Exception type, if possible""" """Convert a fault to the corresponding Exception type, if possible"""
code = getattr(fault,'faultCode',None) code = getattr(fault, 'faultCode', None)
if code is None: if code is None:
return fault return fault
for v in globals().values(): for v in globals().values():
if type(v) == type(Exception) and issubclass(v,GenericError) and \ if type(v) == type(Exception) and issubclass(v, GenericError) and \
code == getattr(v,'faultCode',None): code == getattr(v, 'faultCode', None):
ret = v(fault.faultString) ret = v(fault.faultString)
ret.fromFault = True ret.fromFault = True
return ret return ret
@ -373,22 +373,22 @@ def listFaults():
desc: the description of the exception (docstring) desc: the description of the exception (docstring)
""" """
ret = [] ret = []
for n,v in globals().items(): for n, v in globals().items():
if type(v) == type(Exception) and issubclass(v,GenericError): if type(v) == type(Exception) and issubclass(v, GenericError):
code = getattr(v,'faultCode',None) code = getattr(v, 'faultCode', None)
if code is None: if code is None:
continue continue
info = {} info = {}
info['faultCode'] = code info['faultCode'] = code
info['name'] = n info['name'] = n
info['desc'] = getattr(v,'__doc__',None) info['desc'] = getattr(v, '__doc__', None)
ret.append(info) ret.append(info)
ret.sort(lambda a,b: cmp(a['faultCode'],b['faultCode'])) ret.sort(lambda a, b: cmp(a['faultCode'], b['faultCode']))
return ret return ret
#functions for encoding/decoding optional arguments #functions for encoding/decoding optional arguments
def encode_args(*args,**opts): def encode_args(*args, **opts):
"""The function encodes optional arguments as regular arguments. """The function encodes optional arguments as regular arguments.
This is used to allow optional arguments in xmlrpc calls This is used to allow optional arguments in xmlrpc calls
@ -408,11 +408,11 @@ def decode_args(*args):
opts = {} opts = {}
if len(args) > 0: if len(args) > 0:
last = args[-1] last = args[-1]
if type(last) == dict and last.get('__starstar',False): if type(last) == dict and last.get('__starstar', False):
del last['__starstar'] del last['__starstar']
opts = last opts = last
args = args[:-1] args = args[:-1]
return args,opts return args, opts
def decode_args2(args, names, strict=True): def decode_args2(args, names, strict=True):
"An alternate form of decode_args, returns a dictionary" "An alternate form of decode_args, returns a dictionary"
@ -492,9 +492,9 @@ def daemonize():
fd0 = os.open('/dev/null', os.O_RDONLY) fd0 = os.open('/dev/null', os.O_RDONLY)
fd1 = os.open('/dev/null', os.O_RDWR) fd1 = os.open('/dev/null', os.O_RDWR)
fd2 = os.open('/dev/null', os.O_RDWR) fd2 = os.open('/dev/null', os.O_RDWR)
os.dup2(fd0,0) os.dup2(fd0, 0)
os.dup2(fd1,1) os.dup2(fd1, 1)
os.dup2(fd2,2) os.dup2(fd2, 2)
os.close(fd0) os.close(fd0)
os.close(fd1) os.close(fd1)
os.close(fd2) os.close(fd2)
@ -539,7 +539,7 @@ def rpm_hdr_size(f, ofs=None):
# now read two 4-byte integers which tell us # now read two 4-byte integers which tell us
# - # of index entries # - # of index entries
# - bytes of data in header # - bytes of data in header
data = [ ord(x) for x in fo.read(8) ] data = [ord(x) for x in fo.read(8)]
il = multibyte(data[0:4]) il = multibyte(data[0:4])
dl = multibyte(data[4:8]) dl = multibyte(data[4:8])
@ -547,7 +547,7 @@ def rpm_hdr_size(f, ofs=None):
hdrsize = 8 + 16 * il + dl hdrsize = 8 + 16 * il + dl
# hdrsize rounded up to nearest 8 bytes # hdrsize rounded up to nearest 8 bytes
hdrsize = hdrsize + ( 8 - ( hdrsize % 8 ) ) % 8 hdrsize = hdrsize + (8 - (hdrsize % 8)) % 8
# add eight bytes for section header # add eight bytes for section header
hdrsize = hdrsize + 8 hdrsize = hdrsize + 8
@ -575,7 +575,7 @@ class RawHeader(object):
# read two 4-byte integers which tell us # read two 4-byte integers which tell us
# - # of index entries (each 16 bytes long) # - # of index entries (each 16 bytes long)
# - bytes of data in header # - bytes of data in header
data = [ ord(x) for x in self.header[8:12] ] data = [ord(x) for x in self.header[8:12]]
il = multibyte(data[:4]) il = multibyte(data[:4])
dl = multibyte(data[4:8]) dl = multibyte(data[4:8])
@ -585,7 +585,7 @@ class RawHeader(object):
entry = [] entry = []
for j in xrange(4): for j in xrange(4):
ofs = 16 + i*16 + j*4 ofs = 16 + i*16 + j*4
data = [ ord(x) for x in self.header[ofs:ofs+4] ] data = [ord(x) for x in self.header[ofs:ofs+4]]
entry.append(multibyte(data)) entry.append(multibyte(data))
#print "Tag: %d, Type: %d, Offset: %x, Count: %d" % tuple(entry) #print "Tag: %d, Type: %d, Offset: %x, Count: %d" % tuple(entry)
index[entry[0]] = entry index[entry[0]] = entry
@ -599,7 +599,7 @@ class RawHeader(object):
store = 16 + il * 16 store = 16 + il * 16
#print "start is: %d" % start #print "start is: %d" % start
#print "index length: %d" % il #print "index length: %d" % il
print "Store at offset %d (%0x)" % (store,store) print "Store at offset %d (%0x)" % (store, store)
#sort entries by offset, dtype #sort entries by offset, dtype
#also rearrange: tag, dtype, offset, count -> offset, dtype, tag, count #also rearrange: tag, dtype, offset, count -> offset, dtype, tag, count
order = [(x[2], x[1], x[0], x[3]) for x in self.index.itervalues()] order = [(x[2], x[1], x[0], x[3]) for x in self.index.itervalues()]
@ -637,7 +637,7 @@ class RawHeader(object):
#integer #integer
n = 1 << (dtype - 2) n = 1 << (dtype - 2)
for i in xrange(count): for i in xrange(count):
data = [ ord(x) for x in self.header[pos:pos+n] ] data = [ord(x) for x in self.header[pos:pos+n]]
print "%r" % data print "%r" % data
num = multibyte(data) num = multibyte(data)
print "Int(%d): %d" % (n, num) print "Int(%d): %d" % (n, num)
@ -690,7 +690,7 @@ class RawHeader(object):
if dtype >= 2 and dtype <= 5: if dtype >= 2 and dtype <= 5:
n = 1 << (dtype - 2) n = 1 << (dtype - 2)
# n-byte integer # n-byte integer
data = [ ord(x) for x in self.header[pos:pos+n] ] data = [ord(x) for x in self.header[pos:pos+n]]
return multibyte(data) return multibyte(data)
elif dtype == 6: elif dtype == 6:
# string (null terminated) # string (null terminated)
@ -743,7 +743,7 @@ def __parse_packet_header(pgp_packet):
offset = 1 offset = 1
length = len(pgp_packet) - offset length = len(pgp_packet) - offset
else: else:
(fmt, offset) = { 0:('>B', 2), 1:('>H', 3), 2:('>I', 5) }[len_type] (fmt, offset) = {0:('>B', 2), 1:('>H', 3), 2:('>I', 5)}[len_type]
length = struct.unpack(fmt, pgp_packet[1:offset])[0] length = struct.unpack(fmt, pgp_packet[1:offset])[0]
else: else:
tag = byte0 & 0x3F tag = byte0 & 0x3F
@ -852,14 +852,14 @@ def get_rpm_header(f, ts=None):
fo.close() fo.close()
return hdr return hdr
def get_header_field(hdr,name): def get_header_field(hdr, name):
"""Extract named field from an rpm header""" """Extract named field from an rpm header"""
idx = getattr(rpm,"RPMTAG_%s" % name.upper(),None) idx = getattr(rpm, "RPMTAG_%s" % name.upper(), None)
if idx is None: if idx is None:
raise GenericError, "No such rpm header field: %s" % name raise GenericError, "No such rpm header field: %s" % name
return hdr[idx] return hdr[idx]
def get_header_fields(X,fields): def get_header_fields(X, fields):
"""Extract named fields from an rpm header and return as a dictionary """Extract named fields from an rpm header and return as a dictionary
X may be either the rpm header or the rpm filename X may be either the rpm header or the rpm filename
@ -870,16 +870,16 @@ def get_header_fields(X,fields):
hdr = X hdr = X
ret = {} ret = {}
for f in fields: for f in fields:
ret[f] = get_header_field(hdr,f) ret[f] = get_header_field(hdr, f)
return ret return ret
def parse_NVR(nvr): def parse_NVR(nvr):
"""split N-V-R into dictionary of data""" """split N-V-R into dictionary of data"""
ret = {} ret = {}
p2 = nvr.rfind("-",0) p2 = nvr.rfind("-", 0)
if p2 == -1 or p2 == len(nvr) - 1: if p2 == -1 or p2 == len(nvr) - 1:
raise GenericError("invalid format: %s" % nvr) raise GenericError("invalid format: %s" % nvr)
p1 = nvr.rfind("-",0,p2) p1 = nvr.rfind("-", 0, p2)
if p1 == -1 or p1 == p2 - 1: if p1 == -1 or p1 == p2 - 1:
raise GenericError("invalid format: %s" % nvr) raise GenericError("invalid format: %s" % nvr)
ret['release'] = nvr[p2+1:] ret['release'] = nvr[p2+1:]
@ -927,23 +927,23 @@ def canonArch(arch):
"""Given an arch, return the "canonical" arch""" """Given an arch, return the "canonical" arch"""
#XXX - this could stand to be smarter, and we should probably #XXX - this could stand to be smarter, and we should probably
# have some other related arch-mangling functions. # have some other related arch-mangling functions.
if fnmatch(arch,'i?86') or arch == 'athlon': if fnmatch(arch, 'i?86') or arch == 'athlon':
return 'i386' return 'i386'
elif arch == 'ia32e': elif arch == 'ia32e':
return 'x86_64' return 'x86_64'
elif fnmatch(arch,'ppc64le'): elif fnmatch(arch, 'ppc64le'):
return 'ppc64le' return 'ppc64le'
elif fnmatch(arch,'ppc64*'): elif fnmatch(arch, 'ppc64*'):
return 'ppc64' return 'ppc64'
elif fnmatch(arch,'sparc64*'): elif fnmatch(arch, 'sparc64*'):
return 'sparc64' return 'sparc64'
elif fnmatch(arch,'sparc*'): elif fnmatch(arch, 'sparc*'):
return 'sparc' return 'sparc'
elif fnmatch(arch, 'alpha*'): elif fnmatch(arch, 'alpha*'):
return 'alpha' return 'alpha'
elif fnmatch(arch,'arm*h*'): elif fnmatch(arch, 'arm*h*'):
return 'armhfp' return 'armhfp'
elif fnmatch(arch,'arm*'): elif fnmatch(arch, 'arm*'):
return 'arm' return 'arm'
else: else:
return arch return arch
@ -1058,13 +1058,13 @@ def mavenLabel(maveninfo):
def hex_string(s): def hex_string(s):
"""Converts a string to a string of hex digits""" """Converts a string to a string of hex digits"""
return ''.join([ '%02x' % ord(x) for x in s ]) return ''.join(['%02x' % ord(x) for x in s])
def make_groups_spec(grplist,name='buildsys-build',buildgroup=None): def make_groups_spec(grplist, name='buildsys-build', buildgroup=None):
"""Return specfile contents representing the group""" """Return specfile contents representing the group"""
if buildgroup is None: if buildgroup is None:
buildgroup=name buildgroup = name
data = [ data = [
"""# """#
# This specfile represents buildgroups for mock # This specfile represents buildgroups for mock
@ -1087,7 +1087,7 @@ BuildArch: noarch
seen_grp = {} seen_grp = {}
seen_pkg = {} seen_pkg = {}
#index groups #index groups
groups = dict([(g['name'],g) for g in grplist]) groups = dict([(g['name'], g) for g in grplist])
for group_name in need: for group_name in need:
if seen_grp.has_key(group_name): if seen_grp.has_key(group_name):
continue continue
@ -1098,7 +1098,7 @@ BuildArch: noarch
continue continue
data.append("#Group: %s\n" % group_name) data.append("#Group: %s\n" % group_name)
pkglist = list(group['packagelist']) pkglist = list(group['packagelist'])
pkglist.sort(lambda a,b: cmp(a['package'], b['package'])) pkglist.sort(lambda a, b: cmp(a['package'], b['package']))
for pkg in pkglist: for pkg in pkglist:
pkg_name = pkg['package'] pkg_name = pkg['package']
if seen_pkg.has_key(pkg_name): if seen_pkg.has_key(pkg_name):
@ -1137,10 +1137,10 @@ def generate_comps(groups, expand_groups=False):
<!-- Auto-generated by the build system --> <!-- Auto-generated by the build system -->
<comps> <comps>
""" ] """]
groups = list(groups) groups = list(groups)
group_idx = dict([(g['name'],g) for g in groups]) group_idx = dict([(g['name'], g) for g in groups])
groups.sort(lambda a,b:cmp(a['name'],b['name'])) groups.sort(lambda a, b: cmp(a['name'], b['name']))
for g in groups: for g in groups:
group_id = g['name'] group_id = g['name']
name = g['display_name'] name = g['display_name']
@ -1167,7 +1167,7 @@ def generate_comps(groups, expand_groups=False):
""" <grouplist> """ <grouplist>
""") """)
grouplist = list(g['grouplist']) grouplist = list(g['grouplist'])
grouplist.sort(lambda a,b:cmp(a['name'],b['name'])) grouplist.sort(lambda a, b: cmp(a['name'], b['name']))
for x in grouplist: for x in grouplist:
#['req_id','type','is_metapkg','name'] #['req_id','type','is_metapkg','name']
name = x['name'] name = x['name']
@ -1203,7 +1203,7 @@ def generate_comps(groups, expand_groups=False):
""") """)
if g['packagelist']: if g['packagelist']:
packagelist = list(g['packagelist']) packagelist = list(g['packagelist'])
packagelist.sort(lambda a,b:cmp(a['package'],b['package'])) packagelist.sort(lambda a, b: cmp(a['package'], b['package']))
for p in packagelist: for p in packagelist:
data.append( data.append(
""" %s """ %s
@ -1212,7 +1212,7 @@ def generate_comps(groups, expand_groups=False):
if expand_groups and g['grouplist']: if expand_groups and g['grouplist']:
#add a requires entry for all packages in groups required by buildgroup #add a requires entry for all packages in groups required by buildgroup
need = [req['name'] for req in g['grouplist']] need = [req['name'] for req in g['grouplist']]
seen_grp = { g['name'] : 1} seen_grp = {g['name'] : 1}
seen_pkg = {} seen_pkg = {}
for p in g['packagelist']: for p in g['packagelist']:
seen_pkg[p['package']] = 1 seen_pkg[p['package']] = 1
@ -1230,7 +1230,7 @@ def generate_comps(groups, expand_groups=False):
""" <!-- Expanding Group: %s --> """ <!-- Expanding Group: %s -->
""" % group_name) """ % group_name)
pkglist = list(group['packagelist']) pkglist = list(group['packagelist'])
pkglist.sort(lambda a,b: cmp(a['package'], b['package'])) pkglist.sort(lambda a, b: cmp(a['package'], b['package']))
for pkg in pkglist: for pkg in pkglist:
pkg_name = pkg['package'] pkg_name = pkg['package']
if seen_pkg.has_key(pkg_name): if seen_pkg.has_key(pkg_name):
@ -1278,11 +1278,11 @@ def genMockConfig(name, arch, managed=False, repoid=None, tag_name=None, **opts)
if topurls: if topurls:
#XXX - PathInfo isn't quite right for this, but it will do for now #XXX - PathInfo isn't quite right for this, but it will do for now
pathinfos = [PathInfo(topdir=_u) for _u in topurls] pathinfos = [PathInfo(topdir=_u) for _u in topurls]
urls = ["%s/%s" % (_p.repo(repoid,tag_name), arch) for _p in pathinfos] urls = ["%s/%s" % (_p.repo(repoid, tag_name), arch) for _p in pathinfos]
else: else:
pathinfo = PathInfo(topdir=opts.get('topdir', '/mnt/koji')) pathinfo = PathInfo(topdir=opts.get('topdir', '/mnt/koji'))
repodir = pathinfo.repo(repoid,tag_name) repodir = pathinfo.repo(repoid, tag_name)
urls = ["file://%s/%s" % (repodir,arch)] urls = ["file://%s/%s" % (repodir, arch)]
if managed: if managed:
buildroot_id = opts.get('buildroot_id') buildroot_id = opts.get('buildroot_id')
@ -1639,7 +1639,7 @@ class PathInfo(object):
#else #else
return self.topdir + ("/vol/%s" % volume) return self.topdir + ("/vol/%s" % volume)
def build(self,build): def build(self, build):
"""Return the directory where a build belongs""" """Return the directory where a build belongs"""
return self.volumedir(build.get('volume_name')) + ("/packages/%(name)s/%(version)s/%(release)s" % build) return self.volumedir(build.get('volume_name')) + ("/packages/%(name)s/%(version)s/%(release)s" % build)
@ -1674,7 +1674,7 @@ class PathInfo(object):
"""Return the directory where the image for the build are stored""" """Return the directory where the image for the build are stored"""
return self.build(build) + '/images' return self.build(build) + '/images'
def rpm(self,rpminfo): def rpm(self, rpminfo):
"""Return the path (relative to build_dir) where an rpm belongs""" """Return the path (relative to build_dir) where an rpm belongs"""
return "%(arch)s/%(name)s-%(version)s-%(release)s.%(arch)s.rpm" % rpminfo return "%(arch)s/%(name)s-%(version)s-%(release)s.%(arch)s.rpm" % rpminfo
@ -1690,11 +1690,11 @@ class PathInfo(object):
"""Return the path for build logs""" """Return the path for build logs"""
return "%s/data/logs" % self.build(build) return "%s/data/logs" % self.build(build)
def repo(self,repo_id,tag_str): def repo(self, repo_id, tag_str):
"""Return the directory where a repo belongs""" """Return the directory where a repo belongs"""
return self.topdir + ("/repos/%(tag_str)s/%(repo_id)s" % locals()) return self.topdir + ("/repos/%(tag_str)s/%(repo_id)s" % locals())
def repocache(self,tag_str): def repocache(self, tag_str):
"""Return the directory where a repo belongs""" """Return the directory where a repo belongs"""
return self.topdir + ("/repos/%(tag_str)s/cache" % locals()) return self.topdir + ("/repos/%(tag_str)s/cache" % locals())
@ -1733,7 +1733,7 @@ class VirtualMethod(object):
def __getattr__(self, name): def __getattr__(self, name):
return type(self)(self.__func, "%s.%s" % (self.__name, name)) return type(self)(self.__func, "%s.%s" % (self.__name, name))
def __call__(self, *args, **opts): def __call__(self, *args, **opts):
return self.__func(self.__name,args,opts) return self.__func(self.__name, args, opts)
class ClientSession(object): class ClientSession(object):
@ -1783,7 +1783,7 @@ class ClientSession(object):
# set a default 12 hour connection timeout. # set a default 12 hour connection timeout.
# Some Koji operations can take a long time to return, but after 12 # Some Koji operations can take a long time to return, but after 12
# hours we can assume something is seriously wrong. # hours we can assume something is seriously wrong.
timeout = self.opts.setdefault('timeout', 60 * 60 * 12) timeout = self.opts.setdefault('timeout', 60 * 60 * 12)
self._timeout_compat = False self._timeout_compat = False
if timeout: if timeout:
if sys.version_info[:3] < (2, 6, 0) and 'ssl_context' not in cnxOpts: if sys.version_info[:3] < (2, 6, 0) and 'ssl_context' not in cnxOpts:
@ -1795,7 +1795,7 @@ class ClientSession(object):
self._cnxClass = cnxClass self._cnxClass = cnxClass
self._close_connection() self._close_connection()
def setSession(self,sinfo): def setSession(self, sinfo):
"""Set the session info """Set the session info
If sinfo is None, logout.""" If sinfo is None, logout."""
@ -1810,8 +1810,8 @@ class ClientSession(object):
self.callnum = 0 self.callnum = 0
self.sinfo = sinfo self.sinfo = sinfo
def login(self,opts=None): def login(self, opts=None):
sinfo = self.callMethod('login',self.opts['user'], self.opts['password'],opts) sinfo = self.callMethod('login', self.opts['user'], self.opts['password'], opts)
if not sinfo: if not sinfo:
return False return False
self.setSession(sinfo) self.setSession(sinfo)
@ -1821,7 +1821,7 @@ class ClientSession(object):
def subsession(self): def subsession(self):
"Create a subsession" "Create a subsession"
sinfo = self.callMethod('subsession') sinfo = self.callMethod('subsession')
return type(self)(self.baseurl,self.opts,sinfo) return type(self)(self.baseurl, self.opts, sinfo)
def krb_login(self, principal=None, keytab=None, ccache=None, proxyuser=None): def krb_login(self, principal=None, keytab=None, ccache=None, proxyuser=None):
"""Log in using Kerberos. If principal is not None and keytab is """Log in using Kerberos. If principal is not None and keytab is
@ -1974,7 +1974,7 @@ class ClientSession(object):
except: except:
pass pass
def callMethod(self,name,*args,**opts): def callMethod(self, name, *args, **opts):
"""compatibility wrapper for _callMethod""" """compatibility wrapper for _callMethod"""
return self._callMethod(name, args, opts) return self._callMethod(name, args, opts)
@ -1984,7 +1984,7 @@ class ClientSession(object):
kwargs = {} kwargs = {}
if name == 'rawUpload': if name == 'rawUpload':
return self._prepUpload(*args, **kwargs) return self._prepUpload(*args, **kwargs)
args = encode_args(*args,**kwargs) args = encode_args(*args, **kwargs)
if self.logged_in: if self.logged_in:
sinfo = self.sinfo.copy() sinfo = self.sinfo.copy()
sinfo['callnum'] = self.callnum sinfo['callnum'] = self.callnum
@ -2089,9 +2089,9 @@ class ClientSession(object):
handler, headers, request = self._prepCall(name, args, kwargs) handler, headers, request = self._prepCall(name, args, kwargs)
tries = 0 tries = 0
self.retries = 0 self.retries = 0
debug = self.opts.get('debug',False) debug = self.opts.get('debug', False)
max_retries = self.opts.get('max_retries',30) max_retries = self.opts.get('max_retries', 30)
interval = self.opts.get('retry_interval',20) interval = self.opts.get('retry_interval', 20)
while True: while True:
tries += 1 tries += 1
self.retries += 1 self.retries += 1
@ -2107,7 +2107,7 @@ class ClientSession(object):
#try to convert the fault to a known exception #try to convert the fault to a known exception
err = convertFault(fault) err = convertFault(fault)
if isinstance(err, ServerOffline): if isinstance(err, ServerOffline):
if self.opts.get('offline_retry',False): if self.opts.get('offline_retry', False):
secs = self.opts.get('offline_retry_interval', interval) secs = self.opts.get('offline_retry_interval', interval)
self.logger.debug("Server offline. Retrying in %i seconds", secs) self.logger.debug("Server offline. Retrying in %i seconds", secs)
time.sleep(secs) time.sleep(secs)
@ -2130,7 +2130,7 @@ class ClientSession(object):
if not self.logged_in: if not self.logged_in:
#in the past, non-logged-in sessions did not retry. For compatibility purposes #in the past, non-logged-in sessions did not retry. For compatibility purposes
#this behavior is governed by the anon_retry opt. #this behavior is governed by the anon_retry opt.
if not self.opts.get('anon_retry',False): if not self.opts.get('anon_retry', False):
raise raise
if tries > max_retries: if tries > max_retries:
raise raise
@ -2174,10 +2174,10 @@ class ClientSession(object):
raise err raise err
return ret return ret
def __getattr__(self,name): def __getattr__(self, name):
#if name[:1] == '_': #if name[:1] == '_':
# raise AttributeError, "no attribute %r" % name # raise AttributeError, "no attribute %r" % name
return VirtualMethod(self._callMethod,name) return VirtualMethod(self._callMethod, name)
def fastUpload(self, localfile, path, name=None, callback=None, blocksize=None, overwrite=False): def fastUpload(self, localfile, path, name=None, callback=None, blocksize=None, overwrite=False):
if blocksize is None: if blocksize is None:
@ -2278,14 +2278,14 @@ class ClientSession(object):
self.fastUpload(localfile, path, name, callback, blocksize, overwrite) self.fastUpload(localfile, path, name, callback, blocksize, overwrite)
return return
start=time.time() start = time.time()
# XXX - stick in a config or something # XXX - stick in a config or something
retries=3 retries = 3
fo = file(localfile, "r") #specify bufsize? fo = file(localfile, "r") #specify bufsize?
totalsize = os.path.getsize(localfile) totalsize = os.path.getsize(localfile)
ofs = 0 ofs = 0
md5sum = md5_constructor() md5sum = md5_constructor()
debug = self.opts.get('debug',False) debug = self.opts.get('debug', False)
if callback: if callback:
callback(0, totalsize, 0, 0, 0) callback(0, totalsize, 0, 0, 0)
while True: while True:
@ -2307,7 +2307,7 @@ class ClientSession(object):
tries = 0 tries = 0
while True: while True:
if debug: if debug:
self.logger.debug("uploadFile(%r,%r,%r,%r,%r,...)" %(path,name,sz,digest,offset)) self.logger.debug("uploadFile(%r,%r,%r,%r,%r,...)" %(path, name, sz, digest, offset))
if self.callMethod('uploadFile', path, name, encode_int(sz), digest, encode_int(offset), data): if self.callMethod('uploadFile', path, name, encode_int(sz), digest, encode_int(offset), data):
break break
if tries <= retries: if tries <= retries:
@ -2326,9 +2326,9 @@ class ClientSession(object):
if t2 <= 0: if t2 <= 0:
t2 = 1 t2 = 1
if debug: if debug:
self.logger.debug("Uploaded %d bytes in %f seconds (%f kbytes/sec)" % (size,t1,size/t1/1024)) self.logger.debug("Uploaded %d bytes in %f seconds (%f kbytes/sec)" % (size, t1, size/t1/1024))
if debug: if debug:
self.logger.debug("Total: %d bytes in %f seconds (%f kbytes/sec)" % (ofs,t2,ofs/t2/1024)) self.logger.debug("Total: %d bytes in %f seconds (%f kbytes/sec)" % (ofs, t2, ofs/t2/1024))
if callback: if callback:
callback(ofs, totalsize, size, t1, t2) callback(ofs, totalsize, size, t1, t2)
fo.close() fo.close()
@ -2359,7 +2359,7 @@ class DBHandler(logging.Handler):
self.cnx = cnx self.cnx = cnx
self.table = table self.table = table
if mapping is None: if mapping is None:
self.mapping = { 'message': '%(message)s' } self.mapping = {'message': '%(message)s'}
else: else:
self.mapping = mapping self.mapping = mapping
@ -2391,7 +2391,7 @@ class DBHandler(logging.Handler):
values = ",".join(values) values = ",".join(values)
command = "INSERT INTO %s (%s) VALUES (%s)" % (self.table, columns, values) command = "INSERT INTO %s (%s) VALUES (%s)" % (self.table, columns, values)
#note we're letting cursor.execute do the escaping #note we're letting cursor.execute do the escaping
cursor.execute(command,data) cursor.execute(command, data)
cursor.close() cursor.close()
#self.cnx.commit() #self.cnx.commit()
#XXX - commiting here is most likely wrong, but we need to set commit_pending or something #XXX - commiting here is most likely wrong, but we need to set commit_pending or something
@ -2405,7 +2405,7 @@ TIMESTAMP_RE = re.compile("(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)")
def parse_timestamp(ts): def parse_timestamp(ts):
"""Parse a timestamp returned from a query""" """Parse a timestamp returned from a query"""
m = TIMESTAMP_RE.search(ts) m = TIMESTAMP_RE.search(ts)
t = tuple([int(x) for x in m.groups()]) + (0,0,0) t = tuple([int(x) for x in m.groups()]) + (0, 0, 0)
return time.mktime(t) return time.mktime(t)
def formatTime(value): def formatTime(value):
@ -2609,7 +2609,7 @@ def add_file_logger(logger, fn):
return return
if not os.path.isfile(fn): if not os.path.isfile(fn):
return return
if not os.access(fn,os.W_OK): if not os.access(fn, os.W_OK):
return return
handler = logging.handlers.RotatingFileHandler(fn, maxBytes=1024*1024*10, backupCount=5) handler = logging.handlers.RotatingFileHandler(fn, maxBytes=1024*1024*10, backupCount=5)
handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s')) handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s'))

View file

@ -51,7 +51,7 @@ RetryWhitelist = [
class Session(object): class Session(object):
def __init__(self,args=None,hostip=None): def __init__(self, args=None, hostip=None):
self.logged_in = False self.logged_in = False
self.id = None self.id = None
self.master = None self.master = None
@ -66,12 +66,12 @@ class Session(object):
self.callnum = None self.callnum = None
#get session data from request #get session data from request
if args is None: if args is None:
environ = getattr(context,'environ',{}) environ = getattr(context, 'environ', {})
args = environ.get('QUERY_STRING','') args = environ.get('QUERY_STRING', '')
if not args: if not args:
self.message = 'no session args' self.message = 'no session args'
return return
args = cgi.parse_qs(args,strict_parsing=True) args = cgi.parse_qs(args, strict_parsing=True)
if hostip is None: if hostip is None:
hostip = context.environ['REMOTE_ADDR'] hostip = context.environ['REMOTE_ADDR']
#XXX - REMOTE_ADDR not promised by wsgi spec #XXX - REMOTE_ADDR not promised by wsgi spec
@ -108,7 +108,7 @@ class Session(object):
AND hostip = %%(hostip)s AND hostip = %%(hostip)s
FOR UPDATE FOR UPDATE
""" % ",".join(fields) """ % ",".join(fields)
c.execute(q,locals()) c.execute(q, locals())
row = c.fetchone() row = c.fetchone()
if not row: if not row:
raise koji.AuthError, 'Invalid session or bad credentials' raise koji.AuthError, 'Invalid session or bad credentials'
@ -120,13 +120,13 @@ class Session(object):
if callnum is not None: if callnum is not None:
try: try:
callnum = int(callnum) callnum = int(callnum)
except (ValueError,TypeError): except (ValueError, TypeError):
raise koji.AuthError, "Invalid callnum: %r" % callnum raise koji.AuthError, "Invalid callnum: %r" % callnum
lastcall = session_data['callnum'] lastcall = session_data['callnum']
if lastcall is not None: if lastcall is not None:
if lastcall > callnum: if lastcall > callnum:
raise koji.SequenceError, "%d > %d (session %d)" \ raise koji.SequenceError, "%d > %d (session %d)" \
% (lastcall,callnum,id) % (lastcall, callnum, id)
elif lastcall == callnum: elif lastcall == callnum:
#Some explanation: #Some explanation:
#This function is one of the few that performs its own commit. #This function is one of the few that performs its own commit.
@ -147,10 +147,10 @@ class Session(object):
# we used to get a row lock here as an attempt to maintain sanity of exclusive # we used to get a row lock here as an attempt to maintain sanity of exclusive
# sessions, but it was an imperfect approach and the lock could cause some # sessions, but it was an imperfect approach and the lock could cause some
# performance issues. # performance issues.
fields = ('name','status','usertype') fields = ('name', 'status', 'usertype')
q = """SELECT %s FROM users WHERE id=%%(user_id)s""" % ','.join(fields) q = """SELECT %s FROM users WHERE id=%%(user_id)s""" % ','.join(fields)
c.execute(q,session_data) c.execute(q, session_data)
user_data = dict(zip(fields,c.fetchone())) user_data = dict(zip(fields, c.fetchone()))
if user_data['status'] != koji.USER_STATUS['NORMAL']: if user_data['status'] != koji.USER_STATUS['NORMAL']:
raise koji.AuthError, 'logins by %s are not allowed' % user_data['name'] raise koji.AuthError, 'logins by %s are not allowed' % user_data['name']
@ -163,7 +163,7 @@ class Session(object):
q = """SELECT id FROM sessions WHERE user_id=%(user_id)s q = """SELECT id FROM sessions WHERE user_id=%(user_id)s
AND "exclusive" = TRUE AND expired = FALSE""" AND "exclusive" = TRUE AND expired = FALSE"""
#should not return multiple rows (unique constraint) #should not return multiple rows (unique constraint)
c.execute(q,session_data) c.execute(q, session_data)
row = c.fetchone() row = c.fetchone()
if row: if row:
(excl_id,) = row (excl_id,) = row
@ -180,7 +180,7 @@ class Session(object):
# update timestamp # update timestamp
q = """UPDATE sessions SET update_time=NOW() WHERE id = %(id)i""" q = """UPDATE sessions SET update_time=NOW() WHERE id = %(id)i"""
c.execute(q,locals()) c.execute(q, locals())
#save update time #save update time
context.cnx.commit() context.cnx.commit()
@ -188,7 +188,7 @@ class Session(object):
#see earlier note near RetryError #see earlier note near RetryError
if callnum is not None: if callnum is not None:
q = """UPDATE sessions SET callnum=%(callnum)i WHERE id = %(id)i""" q = """UPDATE sessions SET callnum=%(callnum)i WHERE id = %(id)i"""
c.execute(q,locals()) c.execute(q, locals())
# record the login data # record the login data
self.id = id self.id = id
@ -211,7 +211,7 @@ class Session(object):
if name == 'perms': if name == 'perms':
if self._perms is None: if self._perms is None:
#in a dict for quicker lookup #in a dict for quicker lookup
self._perms = dict([[name,1] for name in get_user_perms(self.user_id)]) self._perms = dict([[name, 1] for name in get_user_perms(self.user_id)])
return self._perms return self._perms
elif name == 'groups': elif name == 'groups':
if self._groups is None: if self._groups is None:
@ -252,11 +252,11 @@ class Session(object):
if status != koji.USER_STATUS['NORMAL']: if status != koji.USER_STATUS['NORMAL']:
raise koji.AuthError, 'logins by %s are not allowed' % name raise koji.AuthError, 'logins by %s are not allowed' % name
def login(self,user,password,opts=None): def login(self, user, password, opts=None):
"""create a login session""" """create a login session"""
if opts is None: if opts is None:
opts = {} opts = {}
if not isinstance(password,str) or len(password) == 0: if not isinstance(password, str) or len(password) == 0:
raise koji.AuthError, 'invalid username or password' raise koji.AuthError, 'invalid username or password'
if self.logged_in: if self.logged_in:
raise koji.GenericError, "Already logged in" raise koji.GenericError, "Already logged in"
@ -271,7 +271,7 @@ class Session(object):
c = context.cnx.cursor() c = context.cnx.cursor()
q = """SELECT id FROM users q = """SELECT id FROM users
WHERE name = %(user)s AND password = %(password)s""" WHERE name = %(user)s AND password = %(password)s"""
c.execute(q,locals()) c.execute(q, locals())
r = c.fetchone() r = c.fetchone()
if not r: if not r:
raise koji.AuthError, 'invalid username or password' raise koji.AuthError, 'invalid username or password'
@ -419,7 +419,7 @@ class Session(object):
sinfo = self.createSession(user_id, hostip, koji.AUTHTYPE_SSL) sinfo = self.createSession(user_id, hostip, koji.AUTHTYPE_SSL)
return sinfo return sinfo
def makeExclusive(self,force=False): def makeExclusive(self, force=False):
"""Make this session exclusive""" """Make this session exclusive"""
c = context.cnx.cursor() c = context.cnx.cursor()
if self.master is not None: if self.master is not None:
@ -431,24 +431,24 @@ class Session(object):
session_id = self.id session_id = self.id
#acquire a row lock on the user entry #acquire a row lock on the user entry
q = """SELECT id FROM users WHERE id=%(user_id)s FOR UPDATE""" q = """SELECT id FROM users WHERE id=%(user_id)s FOR UPDATE"""
c.execute(q,locals()) c.execute(q, locals())
# check that no other sessions for this user are exclusive # check that no other sessions for this user are exclusive
q = """SELECT id FROM sessions WHERE user_id=%(user_id)s q = """SELECT id FROM sessions WHERE user_id=%(user_id)s
AND expired = FALSE AND "exclusive" = TRUE AND expired = FALSE AND "exclusive" = TRUE
FOR UPDATE""" FOR UPDATE"""
c.execute(q,locals()) c.execute(q, locals())
row = c.fetchone() row = c.fetchone()
if row: if row:
if force: if force:
#expire the previous exclusive session and try again #expire the previous exclusive session and try again
(excl_id,) = row (excl_id,) = row
q = """UPDATE sessions SET expired=TRUE,"exclusive"=NULL WHERE id=%(excl_id)s""" q = """UPDATE sessions SET expired=TRUE,"exclusive"=NULL WHERE id=%(excl_id)s"""
c.execute(q,locals()) c.execute(q, locals())
else: else:
raise koji.AuthLockError, "Cannot get exclusive session" raise koji.AuthLockError, "Cannot get exclusive session"
#mark this session exclusive #mark this session exclusive
q = """UPDATE sessions SET "exclusive"=TRUE WHERE id=%(session_id)s""" q = """UPDATE sessions SET "exclusive"=TRUE WHERE id=%(session_id)s"""
c.execute(q,locals()) c.execute(q, locals())
context.cnx.commit() context.cnx.commit()
def makeShared(self): def makeShared(self):
@ -456,7 +456,7 @@ class Session(object):
c = context.cnx.cursor() c = context.cnx.cursor()
session_id = self.id session_id = self.id
q = """UPDATE sessions SET "exclusive"=NULL WHERE id=%(session_id)s""" q = """UPDATE sessions SET "exclusive"=NULL WHERE id=%(session_id)s"""
c.execute(q,locals()) c.execute(q, locals())
context.cnx.commit() context.cnx.commit()
def logout(self): def logout(self):
@ -497,7 +497,7 @@ class Session(object):
# generate a random key # generate a random key
alnum = string.ascii_letters + string.digits alnum = string.ascii_letters + string.digits
key = "%s-%s" %(user_id, key = "%s-%s" %(user_id,
''.join([ random.choice(alnum) for x in range(1,20) ])) ''.join([random.choice(alnum) for x in range(1, 20)]))
# use sha? sha.new(phrase).hexdigest() # use sha? sha.new(phrase).hexdigest()
# get a session id # get a session id
@ -510,7 +510,7 @@ class Session(object):
INSERT INTO sessions (id, user_id, key, hostip, authtype, master) INSERT INTO sessions (id, user_id, key, hostip, authtype, master)
VALUES (%(session_id)i, %(user_id)i, %(key)s, %(hostip)s, %(authtype)i, %(master)s) VALUES (%(session_id)i, %(user_id)i, %(key)s, %(hostip)s, %(authtype)i, %(master)s)
""" """
c.execute(q,locals()) c.execute(q, locals())
context.cnx.commit() context.cnx.commit()
#return session info #return session info
@ -522,7 +522,7 @@ class Session(object):
raise koji.AuthError, "Not logged in" raise koji.AuthError, "Not logged in"
master = self.master master = self.master
if master is None: if master is None:
master=self.id master = self.id
return self.createSession(self.user_id, self.hostip, self.authtype, return self.createSession(self.user_id, self.hostip, self.authtype,
master=master) master=master)
@ -553,7 +553,7 @@ class Session(object):
def isUser(self, user_id): def isUser(self, user_id):
if not self.logged_in: if not self.logged_in:
return False return False
return ( self.user_id == user_id or self.hasGroup(user_id) ) return (self.user_id == user_id or self.hasGroup(user_id))
def assertUser(self, user_id): def assertUser(self, user_id):
if not self.isUser(user_id) and not self.hasPerm('admin'): if not self.isUser(user_id) and not self.hasPerm('admin'):
@ -563,10 +563,10 @@ class Session(object):
'''Using session data, find host id (if there is one)''' '''Using session data, find host id (if there is one)'''
if self.user_id is None: if self.user_id is None:
return None return None
c=context.cnx.cursor() c = context.cnx.cursor()
q="""SELECT id FROM host WHERE user_id = %(uid)d""" q = """SELECT id FROM host WHERE user_id = %(uid)d"""
c.execute(q,{'uid' : self.user_id }) c.execute(q, {'uid' : self.user_id})
r=c.fetchone() r = c.fetchone()
c.close() c.close()
if r: if r:
return r[0] return r[0]
@ -582,7 +582,7 @@ class Session(object):
If no user with the given princpal if found, return None.""" If no user with the given princpal if found, return None."""
c = context.cnx.cursor() c = context.cnx.cursor()
q = """SELECT id FROM users WHERE krb_principal = %(krb_principal)s""" q = """SELECT id FROM users WHERE krb_principal = %(krb_principal)s"""
c.execute(q,locals()) c.execute(q, locals())
r = c.fetchone() r = c.fetchone()
c.close() c.close()
if r: if r:
@ -647,7 +647,7 @@ class Session(object):
c = context.cnx.cursor() c = context.cnx.cursor()
q = """SELECT krb_principal FROM users q = """SELECT krb_principal FROM users
WHERE name = %(user_name)s""" WHERE name = %(user_name)s"""
c.execute(q,locals()) c.execute(q, locals())
r = c.fetchone() r = c.fetchone()
if not r: if not r:
return self.createUser(user_name, krb_principal=krb_principal) return self.createUser(user_name, krb_principal=krb_principal)
@ -668,7 +668,7 @@ def get_user_groups(user_id):
FROM user_groups JOIN users ON group_id = users.id FROM user_groups JOIN users ON group_id = users.id
WHERE active = TRUE AND users.usertype=%(t_group)i WHERE active = TRUE AND users.usertype=%(t_group)i
AND user_id=%(user_id)i""" AND user_id=%(user_id)i"""
c.execute(q,locals()) c.execute(q, locals())
return dict(c.fetchall()) return dict(c.fetchall())
def get_user_perms(user_id): def get_user_perms(user_id):
@ -676,22 +676,22 @@ def get_user_perms(user_id):
q = """SELECT name q = """SELECT name
FROM user_perms JOIN permissions ON perm_id = permissions.id FROM user_perms JOIN permissions ON perm_id = permissions.id
WHERE active = TRUE AND user_id=%(user_id)s""" WHERE active = TRUE AND user_id=%(user_id)s"""
c.execute(q,locals()) c.execute(q, locals())
#return a list of permissions by name #return a list of permissions by name
return [row[0] for row in c.fetchall()] return [row[0] for row in c.fetchall()]
def get_user_data(user_id): def get_user_data(user_id):
c = context.cnx.cursor() c = context.cnx.cursor()
fields = ('name','status','usertype') fields = ('name', 'status', 'usertype')
q = """SELECT %s FROM users WHERE id=%%(user_id)s""" % ','.join(fields) q = """SELECT %s FROM users WHERE id=%%(user_id)s""" % ','.join(fields)
c.execute(q,locals()) c.execute(q, locals())
row = c.fetchone() row = c.fetchone()
if not row: if not row:
return None return None
return dict(zip(fields,row)) return dict(zip(fields, row))
def login(*args,**opts): def login(*args, **opts):
return context.session.login(*args,**opts) return context.session.login(*args, **opts)
def krbLogin(*args, **opts): def krbLogin(*args, **opts):
return context.session.krbLogin(*args, **opts) return context.session.krbLogin(*args, **opts)
@ -708,9 +708,9 @@ def subsession():
def logoutChild(session_id): def logoutChild(session_id):
return context.session.logoutChild(session_id) return context.session.logoutChild(session_id)
def exclusiveSession(*args,**opts): def exclusiveSession(*args, **opts):
"""Make this session exclusive""" """Make this session exclusive"""
return context.session.makeExclusive(*args,**opts) return context.session.makeExclusive(*args, **opts)
def sharedSession(): def sharedSession():
"""Drop out of exclusive mode""" """Drop out of exclusive mode"""
@ -720,18 +720,18 @@ def sharedSession():
if __name__ == '__main__': if __name__ == '__main__':
# XXX - testing defaults # XXX - testing defaults
import db import db
db.setDBopts( database = "test", user = "test") db.setDBopts(database="test", user="test")
print "Connecting to db" print "Connecting to db"
context.cnx = db.connect() context.cnx = db.connect()
print "starting session 1" print "starting session 1"
sess = Session(None,hostip='127.0.0.1') sess = Session(None, hostip='127.0.0.1')
print "Session 1: %s" % sess print "Session 1: %s" % sess
print "logging in with session 1" print "logging in with session 1"
session_info = sess.login('host/1','foobar',{'hostip':'127.0.0.1'}) session_info = sess.login('host/1', 'foobar', {'hostip':'127.0.0.1'})
#wrap values in lists #wrap values in lists
session_info = dict([ [k,[v]] for k,v in session_info.iteritems()]) session_info = dict([[k, [v]] for k, v in session_info.iteritems()])
print "Session 1: %s" % sess print "Session 1: %s" % sess
print "Session 1 info: %r" % session_info print "Session 1 info: %r" % session_info
print "Creating session 2" print "Creating session 2"
s2 = Session(session_info,'127.0.0.1') s2 = Session(session_info, '127.0.0.1')
print "Session 2: %s " % s2 print "Session 2: %s " % s2

View file

@ -48,7 +48,7 @@ class ThreadLocal(object):
if not tdict.has_key(id): if not tdict.has_key(id):
tdict[id] = _data() tdict[id] = _data()
data = tdict[id] data = tdict[id]
return object.__setattr__(data,key,value) return object.__setattr__(data, key, value)
def __delattr__(self, key): def __delattr__(self, key):
id = thread.get_ident() id = thread.get_ident()
@ -65,7 +65,7 @@ class ThreadLocal(object):
id = thread.get_ident() id = thread.get_ident()
tdict = object.__getattribute__(self, '_tdict') tdict = object.__getattribute__(self, '_tdict')
return "(current thread: %s) {" % id + \ return "(current thread: %s) {" % id + \
", ".join([ "%s : %s" %(k,v.__dict__) for (k,v) in tdict.iteritems() ]) + \ ", ".join(["%s : %s" %(k, v.__dict__) for (k, v) in tdict.iteritems()]) + \
"}" "}"
def _threadclear(self): def _threadclear(self):
@ -92,13 +92,13 @@ if __name__ == '__main__':
import random import random
import time import time
def test(): def test():
context.foo=random.random() context.foo = random.random()
time.sleep(1.5+random.random()) time.sleep(1.5+random.random())
context._threadclear() context._threadclear()
print context print context
for x in xrange(1,10): for x in xrange(1, 10):
thread.start_new_thread(test,()) thread.start_new_thread(test, ())
time.sleep(4) time.sleep(4)
print print
@ -106,7 +106,7 @@ if __name__ == '__main__':
context.foo = 1 context.foo = 1
context.bar = 2 context.bar = 2
print context.foo,context.bar print context.foo, context.bar
print context print context
context._threadclear() context._threadclear()
print context print context

View file

@ -163,12 +163,12 @@ def log_output(session, path, args, outfile, uploadpath, cwd=None, logerror=0, a
class SCM(object): class SCM(object):
"SCM abstraction class" "SCM abstraction class"
types = { 'CVS': ('cvs://',), types = {'CVS': ('cvs://',),
'CVS+SSH': ('cvs+ssh://',), 'CVS+SSH': ('cvs+ssh://',),
'GIT': ('git://', 'git+http://', 'git+https://', 'git+rsync://'), 'GIT': ('git://', 'git+http://', 'git+https://', 'git+rsync://'),
'GIT+SSH': ('git+ssh://',), 'GIT+SSH': ('git+ssh://',),
'SVN': ('svn://', 'svn+http://', 'svn+https://'), 'SVN': ('svn://', 'svn+http://', 'svn+https://'),
'SVN+SSH': ('svn+ssh://',) } 'SVN+SSH': ('svn+ssh://',)}
def is_scm_url(url): def is_scm_url(url):
""" """
@ -265,15 +265,15 @@ class SCM(object):
query = query[:-1] query = query[:-1]
# check for validity: params should be empty, query may be empty, everything else should be populated # check for validity: params should be empty, query may be empty, everything else should be populated
if params : if params:
raise koji.GenericError, 'Unable to parse SCM URL: %s . Params element %s should be empty.' % (self.url, params) raise koji.GenericError, 'Unable to parse SCM URL: %s . Params element %s should be empty.' % (self.url, params)
if not scheme : if not scheme:
raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the scheme element.' % self.url raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the scheme element.' % self.url
if not netloc : if not netloc:
raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the netloc element.' % self.url raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the netloc element.' % self.url
if not path : if not path:
raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the path element.' % self.url raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the path element.' % self.url
if not fragment : if not fragment:
raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the fragment element.' % self.url raise koji.GenericError, 'Unable to parse SCM URL: %s . Could not find the fragment element.' % self.url
# return parsed values # return parsed values
@ -445,8 +445,8 @@ class SCM(object):
# Currently only required for GIT checkouts # Currently only required for GIT checkouts
# Run the command in the directory the source was checked out into # Run the command in the directory the source was checked out into
if self.scmtype.startswith('GIT') and globals().get('KOJIKAMID'): if self.scmtype.startswith('GIT') and globals().get('KOJIKAMID'):
_run(['git', 'config', 'core.autocrlf', 'true'], chdir=update_checkout_dir, fatal=True) _run(['git', 'config', 'core.autocrlf', 'true'], chdir=update_checkout_dir, fatal=True)
_run(['git', 'config', 'core.safecrlf', 'true'], chdir=update_checkout_dir, fatal=True) _run(['git', 'config', 'core.safecrlf', 'true'], chdir=update_checkout_dir, fatal=True)
_run(update_checkout_cmd, chdir=update_checkout_dir, fatal=True) _run(update_checkout_cmd, chdir=update_checkout_dir, fatal=True)
if self.use_common and not globals().get('KOJIKAMID'): if self.use_common and not globals().get('KOJIKAMID'):
@ -484,7 +484,7 @@ class TaskManager(object):
def findHandlers(self, vars): def findHandlers(self, vars):
"""Find and index task handlers""" """Find and index task handlers"""
for v in vars.values(): for v in vars.values():
if type(v) == type(koji.tasks.BaseTaskHandler) and issubclass(v,koji.tasks.BaseTaskHandler): if type(v) == type(koji.tasks.BaseTaskHandler) and issubclass(v, koji.tasks.BaseTaskHandler):
for method in v.Methods: for method in v.Methods:
self.handlers[method] = v self.handlers[method] = v
@ -497,7 +497,7 @@ class TaskManager(object):
for task_id in self.pids.keys(): for task_id in self.pids.keys():
self.cleanupTask(task_id) self.cleanupTask(task_id)
self.session.host.freeTasks(self.tasks.keys()) self.session.host.freeTasks(self.tasks.keys())
self.session.host.updateHost(task_load=0.0,ready=False) self.session.host.updateHost(task_load=0.0, ready=False)
def updateBuildroots(self, nolocal=False): def updateBuildroots(self, nolocal=False):
"""Handle buildroot cleanup/maintenance """Handle buildroot cleanup/maintenance
@ -511,10 +511,10 @@ class TaskManager(object):
If nolocal is True, do not try to scan local buildroots. If nolocal is True, do not try to scan local buildroots.
""" """
#query buildroots in db that are not expired #query buildroots in db that are not expired
states = [ koji.BR_STATES[x] for x in ('INIT','WAITING','BUILDING') ] states = [koji.BR_STATES[x] for x in ('INIT', 'WAITING', 'BUILDING')]
db_br = self.session.listBuildroots(hostID=self.host_id,state=tuple(states)) db_br = self.session.listBuildroots(hostID=self.host_id, state=tuple(states))
# index by id # index by id
db_br = dict([(row['id'],row) for row in db_br]) db_br = dict([(row['id'], row) for row in db_br])
st_expired = koji.BR_STATES['EXPIRED'] st_expired = koji.BR_STATES['EXPIRED']
for id, br in db_br.items(): for id, br in db_br.items():
task_id = br['task_id'] task_id = br['task_id']
@ -522,13 +522,13 @@ class TaskManager(object):
# not associated with a task # not associated with a task
# this makes no sense now, but may in the future # this makes no sense now, but may in the future
self.logger.warn("Expiring taskless buildroot: %(id)i/%(tag_name)s/%(arch)s" % br) self.logger.warn("Expiring taskless buildroot: %(id)i/%(tag_name)s/%(arch)s" % br)
self.session.host.setBuildRootState(id,st_expired) self.session.host.setBuildRootState(id, st_expired)
elif not self.tasks.has_key(task_id): elif not self.tasks.has_key(task_id):
#task not running - expire the buildroot #task not running - expire the buildroot
#TODO - consider recycling hooks here (with strong sanity checks) #TODO - consider recycling hooks here (with strong sanity checks)
self.logger.info("Expiring buildroot: %(id)i/%(tag_name)s/%(arch)s" % br) self.logger.info("Expiring buildroot: %(id)i/%(tag_name)s/%(arch)s" % br)
self.logger.debug("Buildroot task: %r, Current tasks: %r" % (task_id,self.tasks.keys())) self.logger.debug("Buildroot task: %r, Current tasks: %r" % (task_id, self.tasks.keys()))
self.session.host.setBuildRootState(id,st_expired) self.session.host.setBuildRootState(id, st_expired)
continue continue
if nolocal: if nolocal:
return return
@ -544,8 +544,8 @@ class TaskManager(object):
if task_id: if task_id:
tasks.append(task_id) tasks.append(task_id)
#index #index
missed_br = dict([(row['id'],row) for row in missed_br]) missed_br = dict([(row['id'], row) for row in missed_br])
tasks = dict([(row['id'],row) for row in self.session.getTaskInfo(tasks)]) tasks = dict([(row['id'], row) for row in self.session.getTaskInfo(tasks)])
for id in local_only: for id in local_only:
# Cleaning options # Cleaning options
# - wait til later # - wait til later
@ -611,13 +611,13 @@ class TaskManager(object):
if flist: if flist:
self.logger.info("%s: clearing rootdir" % desc) self.logger.info("%s: clearing rootdir" % desc)
for fn in flist: for fn in flist:
safe_rmtree("%s/%s" % (rootdir,fn), unmount=True, strict=False) safe_rmtree("%s/%s" % (rootdir, fn), unmount=True, strict=False)
resultdir = "%s/result" % topdir resultdir = "%s/result" % topdir
if os.path.isdir(resultdir): if os.path.isdir(resultdir):
self.logger.info("%s: clearing resultdir" % desc) self.logger.info("%s: clearing resultdir" % desc)
safe_rmtree(resultdir, unmount=True, strict=False) safe_rmtree(resultdir, unmount=True, strict=False)
else: else:
self.logger.debug("Recent buildroot: %s: %i seconds" % (desc,age)) self.logger.debug("Recent buildroot: %s: %i seconds" % (desc, age))
self.logger.debug("Local buildroots: %d" % len(local_br)) self.logger.debug("Local buildroots: %d" % len(local_br))
self.logger.debug("Active buildroots: %d" % len(db_br)) self.logger.debug("Active buildroots: %d" % len(db_br))
self.logger.debug("Expired/stray buildroots: %d" % len(local_only)) self.logger.debug("Expired/stray buildroots: %d" % len(local_only))
@ -629,10 +629,10 @@ class TaskManager(object):
for f in os.listdir(configdir): for f in os.listdir(configdir):
if not f.endswith('.cfg'): if not f.endswith('.cfg'):
continue continue
fn = "%s/%s" % (configdir,f) fn = "%s/%s" % (configdir, f)
if not os.path.isfile(fn): if not os.path.isfile(fn):
continue continue
fo = file(fn,'r') fo = file(fn, 'r')
id = None id = None
name = None name = None
for n in xrange(10): for n in xrange(10):
@ -687,10 +687,10 @@ class TaskManager(object):
stale.append(id) stale.append(id)
continue continue
tasks[id] = task tasks[id] = task
if task.get('alert',False): if task.get('alert', False):
#wake up the process #wake up the process
self.logger.info("Waking up task: %r" % task) self.logger.info("Waking up task: %r" % task)
os.kill(self.pids[id],signal.SIGUSR2) os.kill(self.pids[id], signal.SIGUSR2)
if not task['waiting']: if not task['waiting']:
task_load += task['weight'] task_load += task['weight']
self.logger.debug("Task Load: %s" % task_load) self.logger.debug("Task Load: %s" % task_load)
@ -719,21 +719,21 @@ class TaskManager(object):
# - task is forcibly reassigned/unassigned # - task is forcibly reassigned/unassigned
tinfo = self.session.getTaskInfo(id) tinfo = self.session.getTaskInfo(id)
if tinfo is None: if tinfo is None:
raise koji.GenericError, "Invalid task %r (pid %r)" % (id,pid) raise koji.GenericError, "Invalid task %r (pid %r)" % (id, pid)
elif tinfo['state'] == koji.TASK_STATES['CANCELED']: elif tinfo['state'] == koji.TASK_STATES['CANCELED']:
self.logger.info("Killing canceled task %r (pid %r)" % (id,pid)) self.logger.info("Killing canceled task %r (pid %r)" % (id, pid))
if self.cleanupTask(id): if self.cleanupTask(id):
del self.pids[id] del self.pids[id]
elif tinfo['host_id'] != self.host_id: elif tinfo['host_id'] != self.host_id:
self.logger.info("Killing reassigned task %r (pid %r)" % (id,pid)) self.logger.info("Killing reassigned task %r (pid %r)" % (id, pid))
if self.cleanupTask(id): if self.cleanupTask(id):
del self.pids[id] del self.pids[id]
else: else:
self.logger.info("Lingering task %r (pid %r)" % (id,pid)) self.logger.info("Lingering task %r (pid %r)" % (id, pid))
def getNextTask(self): def getNextTask(self):
self.ready = self.readyForTask() self.ready = self.readyForTask()
self.session.host.updateHost(self.task_load,self.ready) self.session.host.updateHost(self.task_load, self.ready)
if not self.ready: if not self.ready:
self.logger.info("Not ready for task") self.logger.info("Not ready for task")
return False return False
@ -753,8 +753,8 @@ class TaskManager(object):
our_avail = host['capacity'] - host['task_load'] our_avail = host['capacity'] - host['task_load']
for chan in host['channels']: for chan in host['channels']:
for arch in host['arches'].split() + ['noarch']: for arch in host['arches'].split() + ['noarch']:
bin = "%s:%s" % (chan,arch) bin = "%s:%s" % (chan, arch)
bin_hosts.setdefault(bin,[]).append(host) bin_hosts.setdefault(bin, []).append(host)
if host['id'] == self.host_id: if host['id'] == self.host_id:
bins[bin] = 1 bins[bin] = 1
self.logger.debug("bins: %r" % bins) self.logger.debug("bins: %r" % bins)
@ -1069,7 +1069,7 @@ class TaskManager(object):
#XXX - add more checks #XXX - add more checks
return True return True
def takeTask(self,task): def takeTask(self, task):
"""Attempt to open the specified task """Attempt to open the specified task
Returns True if successful, False otherwise Returns True if successful, False otherwise
@ -1089,7 +1089,7 @@ class TaskManager(object):
if hasattr(handler, 'checkHost'): if hasattr(handler, 'checkHost'):
try: try:
valid_host = handler.checkHost(self.hostdata) valid_host = handler.checkHost(self.hostdata)
except (SystemExit,KeyboardInterrupt): except (SystemExit, KeyboardInterrupt):
raise raise
except: except:
valid_host = False valid_host = False
@ -1129,7 +1129,7 @@ class TaskManager(object):
self.subsessions[task_id] = session_id self.subsessions[task_id] = session_id
return True return True
def forkTask(self,handler): def forkTask(self, handler):
#get the subsession before we fork #get the subsession before we fork
newhub = self.session.subsession() newhub = self.session.subsession()
session_id = newhub.sinfo['session-id'] session_id = newhub.sinfo['session-id']
@ -1147,7 +1147,7 @@ class TaskManager(object):
self.session = newhub self.session = newhub
handler.session = self.session handler.session = self.session
#set a do-nothing handler for sigusr2 #set a do-nothing handler for sigusr2
signal.signal(signal.SIGUSR2,lambda *args: None) signal.signal(signal.SIGUSR2, lambda *args: None)
self.runTask(handler) self.runTask(handler)
finally: finally:
#diediedie #diediedie
@ -1156,7 +1156,7 @@ class TaskManager(object):
finally: finally:
os._exit(0) os._exit(0)
def runTask(self,handler): def runTask(self, handler):
try: try:
response = (handler.run(),) response = (handler.run(),)
# note that we wrap response in a singleton tuple # note that we wrap response in a singleton tuple
@ -1168,7 +1168,7 @@ class TaskManager(object):
response = xmlrpclib.dumps(fault) response = xmlrpclib.dumps(fault)
tb = ''.join(traceback.format_exception(*sys.exc_info())).replace(r"\n", "\n") tb = ''.join(traceback.format_exception(*sys.exc_info())).replace(r"\n", "\n")
self.logger.warn("FAULT:\n%s" % tb) self.logger.warn("FAULT:\n%s" % tb)
except (SystemExit,koji.tasks.ServerExit,KeyboardInterrupt): except (SystemExit, koji.tasks.ServerExit, KeyboardInterrupt):
#we do not trap these #we do not trap these
raise raise
except koji.tasks.ServerRestart: except koji.tasks.ServerRestart:
@ -1180,7 +1180,7 @@ class TaskManager(object):
self.logger.warn("TRACEBACK: %s" % tb) self.logger.warn("TRACEBACK: %s" % tb)
# report exception back to server # report exception back to server
e_class, e = sys.exc_info()[:2] e_class, e = sys.exc_info()[:2]
faultCode = getattr(e_class,'faultCode',1) faultCode = getattr(e_class, 'faultCode', 1)
if issubclass(e_class, koji.GenericError): if issubclass(e_class, koji.GenericError):
#just pass it through #just pass it through
tb = str(e) tb = str(e)

View file

@ -81,15 +81,15 @@ class CursorWrapper:
def _timed_call(self, method, args, kwargs): def _timed_call(self, method, args, kwargs):
start = time.time() start = time.time()
ret = getattr(self.cursor,method)(*args,**kwargs) ret = getattr(self.cursor, method)(*args, **kwargs)
self.logger.debug("%s operation completed in %.4f seconds", method, time.time() - start) self.logger.debug("%s operation completed in %.4f seconds", method, time.time() - start)
return ret return ret
def fetchone(self,*args,**kwargs): def fetchone(self, *args, **kwargs):
return self._timed_call('fetchone',args,kwargs) return self._timed_call('fetchone', args, kwargs)
def fetchall(self,*args,**kwargs): def fetchall(self, *args, **kwargs):
return self._timed_call('fetchall',args,kwargs) return self._timed_call('fetchall', args, kwargs)
def quote(self, operation, parameters): def quote(self, operation, parameters):
if _quoteparams is not None: if _quoteparams is not None:
@ -97,7 +97,7 @@ class CursorWrapper:
elif hasattr(self.cursor, "_quoteparams"): elif hasattr(self.cursor, "_quoteparams"):
quote = self.cursor._quoteparams quote = self.cursor._quoteparams
else: else:
quote = lambda a,b: a % b quote = lambda a, b: a % b
try: try:
return quote(operation, parameters) return quote(operation, parameters)
except Exception: except Exception:
@ -167,5 +167,5 @@ def connect():
return DBWrapper(conn) return DBWrapper(conn)
if __name__ == "__main__": if __name__ == "__main__":
setDBopts( database = "test", user = "test") setDBopts(database="test", user="test")
print "This is a Python library" print "This is a Python library"

View file

@ -268,7 +268,7 @@ class SimpleRuleSet(object):
return tests, negate, action return tests, negate, action
def get_test_handler(self, str): def get_test_handler(self, str):
name = str.split(None,1)[0] name = str.split(None, 1)[0]
try: try:
return self.tests[name](str) return self.tests[name](str)
except KeyError: except KeyError:
@ -284,7 +284,7 @@ class SimpleRuleSet(object):
if isinstance(action, list): if isinstance(action, list):
_recurse(action, index) _recurse(action, index)
else: else:
name = action.split(None,1)[0] name = action.split(None, 1)[0]
index[name] = 1 index[name] = 1
index = {} index = {}
_recurse(self.ruleset, index) _recurse(self.ruleset, index)

View file

@ -31,10 +31,10 @@ class SSLConnection:
def __del__(self): def __del__(self):
self.__dict__["conn"].close() self.__dict__["conn"].close()
def __getattr__(self,name): def __getattr__(self, name):
return getattr(self.__dict__["conn"], name) return getattr(self.__dict__["conn"], name)
def __setattr__(self,name, value): def __setattr__(self, name, value):
setattr(self.__dict__["conn"], name, value) setattr(self.__dict__["conn"], name, value)
def settimeout(self, timeout): def settimeout(self, timeout):
@ -61,7 +61,7 @@ class SSLConnection:
c, a = self.__dict__["conn"].accept() c, a = self.__dict__["conn"].accept()
return (SSLConnection(c), a) return (SSLConnection(c), a)
def makefile(self, mode='r', bufsize=-1): def makefile(self, mode='r', bufsize=-1):
""" """
We need to use socket._fileobject Because SSL.Connection We need to use socket._fileobject Because SSL.Connection
doesn't have a 'dup'. Not exactly sure WHY this is, but doesn't have a 'dup'. Not exactly sure WHY this is, but

View file

@ -36,7 +36,7 @@ def scan_mounts(topdir):
"""Search path for mountpoints""" """Search path for mountpoints"""
mplist = [] mplist = []
topdir = os.path.normpath(topdir) topdir = os.path.normpath(topdir)
fo = open('/proc/mounts','r') fo = open('/proc/mounts', 'r')
for line in fo.readlines(): for line in fo.readlines():
path = line.split()[1] path = line.split()[1]
if path.startswith(topdir): if path.startswith(topdir):
@ -53,9 +53,9 @@ def umount_all(topdir):
for path in scan_mounts(topdir): for path in scan_mounts(topdir):
logger.debug('Unmounting %s' % path) logger.debug('Unmounting %s' % path)
cmd = ['umount', '-l', path] cmd = ['umount', '-l', path]
rv = os.spawnvp(os.P_WAIT,cmd[0],cmd) rv = os.spawnvp(os.P_WAIT, cmd[0], cmd)
if rv != 0: if rv != 0:
raise koji.GenericError, 'umount failed (exit code %r) for %s' % (rv,path) raise koji.GenericError, 'umount failed (exit code %r) for %s' % (rv, path)
#check mounts again #check mounts again
remain = scan_mounts(topdir) remain = scan_mounts(topdir)
if remain: if remain:
@ -83,7 +83,7 @@ def safe_rmtree(path, unmount=False, strict=True):
#first rm -f non-directories #first rm -f non-directories
logger.debug('Scrubbing files in %s' % path) logger.debug('Scrubbing files in %s' % path)
rv = os.system("find '%s' -xdev \\! -type d -print0 |xargs -0 rm -f" % path) rv = os.system("find '%s' -xdev \\! -type d -print0 |xargs -0 rm -f" % path)
msg = 'file removal failed (code %r) for %s' % (rv,path) msg = 'file removal failed (code %r) for %s' % (rv, path)
if rv != 0: if rv != 0:
logger.warn(msg) logger.warn(msg)
if strict: if strict:
@ -94,7 +94,7 @@ def safe_rmtree(path, unmount=False, strict=True):
#with -depth, we start at the bottom and work up #with -depth, we start at the bottom and work up
logger.debug('Scrubbing directories in %s' % path) logger.debug('Scrubbing directories in %s' % path)
rv = os.system("find '%s' -xdev -depth -type d -print0 |xargs -0 rmdir" % path) rv = os.system("find '%s' -xdev -depth -type d -print0 |xargs -0 rmdir" % path)
msg = 'dir removal failed (code %r) for %s' % (rv,path) msg = 'dir removal failed (code %r) for %s' % (rv, path)
if rv != 0: if rv != 0:
logger.warn(msg) logger.warn(msg)
if strict: if strict:
@ -128,7 +128,7 @@ class BaseTaskHandler(object):
raise koji.GenericError, 'method "%s" is not supported' % method raise koji.GenericError, 'method "%s" is not supported' % method
self.method = method self.method = method
# handle named parameters # handle named parameters
self.params,self.opts = koji.decode_args(*params) self.params, self.opts = koji.decode_args(*params)
self.session = session self.session = session
self.options = options self.options = options
if workdir is None: if workdir is None:
@ -137,7 +137,7 @@ class BaseTaskHandler(object):
self.logger = logging.getLogger("koji.build.BaseTaskHandler") self.logger = logging.getLogger("koji.build.BaseTaskHandler")
self.manager = None self.manager = None
def setManager(self,manager): def setManager(self, manager):
"""Set the manager attribute """Set the manager attribute
This is only used for foreground tasks to give them access This is only used for foreground tasks to give them access
@ -173,7 +173,7 @@ class BaseTaskHandler(object):
Note that task weight is partially ignored while the task is sleeping. Note that task weight is partially ignored while the task is sleeping.
""" """
return getattr(self,'_taskWeight',1.0) return getattr(self, '_taskWeight', 1.0)
def createWorkdir(self): def createWorkdir(self):
if self.workdir is None: if self.workdir is None:
@ -206,10 +206,10 @@ class BaseTaskHandler(object):
the database and will send the subprocess corresponding to the the database and will send the subprocess corresponding to the
subtask a SIGUSR2 to wake it up when subtasks complete. subtask a SIGUSR2 to wake it up when subtasks complete.
""" """
if isinstance(subtasks,int): if isinstance(subtasks, int):
# allow single integer w/o enclosing list # allow single integer w/o enclosing list
subtasks = [subtasks] subtasks = [subtasks]
self.session.host.taskSetWait(self.id,subtasks) self.session.host.taskSetWait(self.id, subtasks)
self.logger.debug("Waiting on %r" % subtasks) self.logger.debug("Waiting on %r" % subtasks)
while True: while True:
finished, unfinished = self.session.host.taskWait(self.id) finished, unfinished = self.session.host.taskWait(self.id)
@ -387,12 +387,12 @@ class ForkTask(BaseTaskHandler):
Methods = ['fork'] Methods = ['fork']
def handler(self, n=5, m=37): def handler(self, n=5, m=37):
for i in xrange(n): for i in xrange(n):
os.spawnvp(os.P_NOWAIT, 'sleep', ['sleep',str(m)]) os.spawnvp(os.P_NOWAIT, 'sleep', ['sleep', str(m)])
class WaitTestTask(BaseTaskHandler): class WaitTestTask(BaseTaskHandler):
Methods = ['waittest'] Methods = ['waittest']
_taskWeight = 0.1 _taskWeight = 0.1
def handler(self,count,seconds=10): def handler(self, count, seconds=10):
tasks = [] tasks = []
for i in xrange(count): for i in xrange(count):
task_id = self.session.host.subtask(method='sleep', task_id = self.session.host.subtask(method='sleep',
@ -407,7 +407,7 @@ class WaitTestTask(BaseTaskHandler):
class SubtaskTask(BaseTaskHandler): class SubtaskTask(BaseTaskHandler):
Methods = ['subtask'] Methods = ['subtask']
_taskWeight = 0.1 _taskWeight = 0.1
def handler(self,n=4): def handler(self, n=4):
if n > 0: if n > 0:
task_id = self.session.host.subtask(method='subtask', task_id = self.session.host.subtask(method='subtask',
arglist=[n-1], arglist=[n-1],
@ -426,7 +426,7 @@ class DefaultTask(BaseTaskHandler):
"""Used when no matching method is found""" """Used when no matching method is found"""
Methods = ['default'] Methods = ['default']
_taskWeight = 0.1 _taskWeight = 0.1
def handler(self,*args,**opts): def handler(self, *args, **opts):
raise koji.GenericError, "Invalid method: %s" % self.method raise koji.GenericError, "Invalid method: %s" % self.method
@ -523,7 +523,7 @@ class DependantTask(BaseTaskHandler):
for task in wait_list[:]: for task in wait_list[:]:
if self.session.taskFinished(task): if self.session.taskFinished(task):
info = self.session.getTaskInfo(task) info = self.session.getTaskInfo(task)
if info and koji.TASK_STATES[info['state']] in ['CANCELED','FAILED']: if info and koji.TASK_STATES[info['state']] in ['CANCELED', 'FAILED']:
raise koji.GenericError, "Dependency %s failed to complete." % info['id'] raise koji.GenericError, "Dependency %s failed to complete." % info['id']
wait_list.remove(task) wait_list.remove(task)
# let the system rest before polling again # let the system rest before polling again
@ -532,7 +532,7 @@ class DependantTask(BaseTaskHandler):
subtasks = [] subtasks = []
for task in task_list: for task in task_list:
# **((len(task)>2 and task[2]) or {}) expands task[2] into opts if it exists, allows for things like 'priority=15' # **((len(task)>2 and task[2]) or {}) expands task[2] into opts if it exists, allows for things like 'priority=15'
task_id = self.session.host.subtask(method=task[0], arglist=task[1], parent=self.id, **((len(task)>2 and task[2]) or {})) task_id = self.session.host.subtask(method=task[0], arglist=task[1], parent=self.id, **((len(task) > 2 and task[2]) or {}))
if task_id: if task_id:
subtasks.append(task_id) subtasks.append(task_id)
if subtasks: if subtasks:

View file

@ -375,7 +375,7 @@ def eventFromOpts(session, opts):
rinfo = session.repoInfo(repo) rinfo = session.repoInfo(repo)
if rinfo: if rinfo:
return {'id' : rinfo['create_event'], return {'id' : rinfo['create_event'],
'ts' : rinfo['create_ts'] } 'ts' : rinfo['create_ts']}
return None return None
def filedigestAlgo(hdr): def filedigestAlgo(hdr):
@ -427,7 +427,7 @@ def setup_rlimits(opts, logger=None):
except ValueError: except ValueError:
logger.error("Invalid resource limit: %s=%s", key, opts[key]) logger.error("Invalid resource limit: %s=%s", key, opts[key])
continue continue
if len(limits) not in (1,2): if len(limits) not in (1, 2):
logger.error("Invalid resource limit: %s=%s", key, opts[key]) logger.error("Invalid resource limit: %s=%s", key, opts[key])
continue continue
if len(limits) == 1: if len(limits) == 1:

View file

@ -80,7 +80,7 @@ class TestImportImageInternal(unittest.TestCase):
cursor = mock.MagicMock() cursor = mock.MagicMock()
context.cnx.cursor.return_value = cursor context.cnx.cursor.return_value = cursor
context.session.host_id = 42 context.session.host_id = 42
get_build.return_value = {'id': 2 } get_build.return_value = {'id': 2}
get_rpm.return_value = rpm get_rpm.return_value = rpm
get_archive_type.return_value = 4 get_archive_type.return_value = 4
work.return_value = self.tempdir work.return_value = self.tempdir