obslock: add reason to indicate what command is being run.

This commit is contained in:
Jimmy Berry 2017-04-28 16:09:34 -05:00
parent f6ec028ea5
commit 77f79f9175
2 changed files with 13 additions and 10 deletions

View File

@ -334,7 +334,7 @@ def do_staging(self, subcmd, opts, *args):
if opts.wipe_cache:
Cache.delete_all()
lock = OBSLock(opts.apiurl, opts.project)
lock = OBSLock(opts.apiurl, opts.project, reason=cmd)
if cmd == 'unlock':
lock.release()
return

View File

@ -28,7 +28,7 @@ from osc.core import http_POST
class OBSLock(object):
"""Implement a distributed lock using a shared OBS resource."""
def __init__(self, apiurl, project, ttl=3600):
def __init__(self, apiurl, project, ttl=3600, reason=None):
self.apiurl = apiurl
self.project = project
self.lock = conf.config[project]['lock']
@ -36,21 +36,24 @@ class OBSLock(object):
# TTL is measured in seconds
self.ttl = ttl
self.user = conf.config['api_host_options'][apiurl]['user']
self.reason = reason
self.locked = False
def _signature(self):
"""Create a signature with a timestamp."""
return '%s@%s' % (self.user, datetime.isoformat(datetime.utcnow()))
reason = str(self.reason).replace('@', 'at').replace('#', 'hash')
return '%s#%s@%s' % (self.user, reason, datetime.isoformat(datetime.utcnow()))
def _parse(self, signature):
"""Parse a signature into an user and a timestamp."""
user, ts = None, None
user, reason, ts = None, None, None
try:
user, ts_str = signature.split('@')
rest, ts_str = signature.split('@')
user, reason = rest.split('#')
ts = datetime.strptime(ts_str, '%Y-%m-%dT%H:%M:%S.%f')
except (AttributeError, ValueError):
pass
return user, ts
return user, reason, ts
def _read(self):
url = makeurl(self.apiurl, ['source', self.lock, '_attribute', '%s:LockedBy' % self.ns])
@ -79,20 +82,20 @@ class OBSLock(object):
warnings.warn('Locking attribute is not found. Create one to avoid race conditions.')
return self
user, ts = self._parse(self._read())
user, reason, ts = self._parse(self._read())
if user and ts:
now = datetime.utcnow()
if now < ts:
raise Exception('Lock acquired from the future [%s] by [%s]. Try later.' % (ts, user))
delta = now - ts
if delta.seconds < self.ttl:
print 'Lock acquired by [%s] %s ago. Try later.' % (user, delta)
print 'Lock acquired by [%s] %s ago, reason <%s>. Try later.' % (user, delta, reason)
exit(-1)
# raise Exception('Lock acquired by [%s]. Try later.' % user)
self._write(self._signature())
time.sleep(1)
user, ts = self._parse(self._read())
user, _, _ = self._parse(self._read())
if user != self.user:
raise Exception('Race condition, [%s] wins. Try later.' % user)
@ -104,7 +107,7 @@ class OBSLock(object):
if not self.lock:
return
user, ts = self._parse(self._read())
user, reason, _ = self._parse(self._read())
if user == self.user:
self._write('')