osc-staging: skip lock for observation commands.

This commit is contained in:
Jimmy Berry 2017-05-08 19:39:15 -05:00
parent 5d7275d20f
commit f4523078b4
3 changed files with 32 additions and 7 deletions

View File

@ -76,6 +76,12 @@ def _full_project_name(self, project):
warnings.warn('%s project not recognized.' % project) warnings.warn('%s project not recognized.' % project)
return project return project
def lock_needed(cmd, opts):
return not(
cmd in ('acheck', 'check', 'frozenage', 'rebuild', 'unlock') or
(cmd == 'list' and not opts.supersede)
)
@cmdln.option('--move', action='store_true', @cmdln.option('--move', action='store_true',
help='force the selection to become a move') help='force the selection to become a move')
@ -352,12 +358,8 @@ def do_staging(self, subcmd, opts, *args):
if opts.wipe_cache: if opts.wipe_cache:
Cache.delete_all() Cache.delete_all()
lock = OBSLock(opts.apiurl, opts.project, reason=cmd) needed = lock_needed(cmd, opts)
if cmd == 'unlock': with OBSLock(opts.apiurl, opts.project, reason=cmd, needed=needed) as lock:
lock.release(force=True)
return
with lock:
api = StagingAPI(opts.apiurl, opts.project) api = StagingAPI(opts.apiurl, opts.project)
config.apply_remote(api) config.apply_remote(api)
@ -578,3 +580,5 @@ def do_staging(self, subcmd, opts, *args):
PrioCommand(api).perform(args[1:]) PrioCommand(api).perform(args[1:])
elif cmd == 'supersede': elif cmd == 'supersede':
SupersedeCommand(api).perform(args[1:]) SupersedeCommand(api).perform(args[1:])
elif cmd == 'unlock':
lock.release(force=True)

View File

@ -28,7 +28,7 @@ from osc.core import http_POST
class OBSLock(object): class OBSLock(object):
"""Implement a distributed lock using a shared OBS resource.""" """Implement a distributed lock using a shared OBS resource."""
def __init__(self, apiurl, project, ttl=3600, reason=None): def __init__(self, apiurl, project, ttl=3600, reason=None, needed=True):
self.apiurl = apiurl self.apiurl = apiurl
self.project = project self.project = project
self.lock = conf.config[project]['lock'] self.lock = conf.config[project]['lock']
@ -39,6 +39,7 @@ class OBSLock(object):
self.reason = reason self.reason = reason
self.reason_sub = None self.reason_sub = None
self.locked = False self.locked = False
self.needed = needed
def _signature(self): def _signature(self):
"""Create a signature with a timestamp.""" """Create a signature with a timestamp."""
@ -83,6 +84,8 @@ class OBSLock(object):
http_POST(url, data=data) http_POST(url, data=data)
def acquire(self): def acquire(self):
if not self.needed: return self
# If the project doesn't have locks configured, raise a # If the project doesn't have locks configured, raise a
# Warning (but continue the operation) # Warning (but continue the operation)
if not self.lock: if not self.lock:
@ -121,6 +124,8 @@ class OBSLock(object):
return self return self
def release(self, force=False): def release(self, force=False):
if not force and not self.needed: return
# If the project do not have locks configured, simply ignore # If the project do not have locks configured, simply ignore
# the operation. # the operation.
if not self.lock: if not self.lock:

View File

@ -122,3 +122,19 @@ class TestOBSLock(unittest.TestCase):
with lock: with lock:
_, reason, _, _ = lock._parse(lock._read()) _, reason, _, _ = lock._parse(lock._read())
self.assertEqual(reason, 'some reason at hashnight') self.assertEqual(reason, 'some reason at hashnight')
def test_needed(self):
lock1 = self.obs_lock()
lock2 = self.obs_lock()
lock2.user = 'user2'
lock2.needed = False
self.assertFalse(lock1.locked)
self.assertFalse(lock2.locked)
with lock1:
self.assertTrue(lock1.locked)
with lock2:
self.assertFalse(lock2.locked)
user, _, _, _ = lock2._parse(lock2._read())
self.assertEqual(user, lock1.user, 'lock1 remains')