Merge branch 'space_comma'
Merges #140 'Remove all bad-whitespaces and Add necessary whitespaces.'
This commit is contained in:
commit
bf0270cb4b
12 changed files with 736 additions and 736 deletions
1000
hub/kojihub.py
1000
hub/kojihub.py
File diff suppressed because it is too large
Load diff
|
|
@ -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)
|
||||||
|
|
|
||||||
180
koji/__init__.py
180
koji/__init__.py
|
|
@ -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'))
|
||||||
|
|
|
||||||
94
koji/auth.py
94
koji/auth.py
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
14
koji/db.py
14
koji/db.py
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue