From 12c2f5618c52e9092144d063b020841d1dd25663 Mon Sep 17 00:00:00 2001 From: Dominique Leuenberger Date: Mon, 9 Feb 2015 17:25:43 +0100 Subject: [PATCH] Locking: Let's get some locking mechanism so we hopefully step less on each others toes. --- osclib/stagingapi.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/osclib/stagingapi.py b/osclib/stagingapi.py index e793ca9a..44dcb99f 100644 --- a/osclib/stagingapi.py +++ b/osclib/stagingapi.py @@ -8,12 +8,14 @@ import json import logging import urllib2 import time +import sys import re from xml.etree import cElementTree as ET import yaml from osc import oscerr +from osc import conf from osc.core import change_review_state from osc.core import delete_package from osc.core import get_request @@ -36,8 +38,10 @@ class StagingAPI(object): Initialize instance variables """ + user = conf.config['api_host_options'][apiurl]['user'] self.apiurl = apiurl self.opensuse = opensuse + self.grab_lock('openSUSE:Factory:Staging', user) self.rings = ( 'openSUSE:{}:Rings:0-Bootstrap'.format(self.opensuse), 'openSUSE:{}:Rings:1-MinimalX'.format(self.opensuse), @@ -46,6 +50,9 @@ class StagingAPI(object): self.ring_packages = self._generate_ring_packages() self.packages_staged = self._get_staged_requests() + def __del__(self): + self.release_lock('openSUSE:Factory:Staging') + def makeurl(self, l, query=None): """ Wrapper around osc's makeurl passing our apiurl @@ -84,6 +91,42 @@ class StagingAPI(object): return self.retried_PUT(url, data) raise e + def read_lock(self, project): + url = self.makeurl(['source', project, '_attribute', 'openSUSE:LockedBy']) + root = ET.parse(http_GET(url)).getroot() + try: + lockedby = root[0][0].text + except IndexError: + # There was no value specified we could parse - assume unlocked + lockedby = None + return lockedby + + def set_lock(self, project, user): + url = self.makeurl(['source', project, '_attribute', 'openSUSE:LockedBy']) + try: + schema = "%s" + http_POST(url, data=schema % user) + except: + print "Failed to acquire lock - exiting" + sys.exit(2) + + def grab_lock(self, project, user): + lockedby = self.read_lock(project) + if lockedby != None: + print "Staging tasks are currently executed by %s - project locked" % lockedby + sys.exit(9) + self.set_lock(project, user) + # wait 2s to see if the lock is now actually ours or if we were racing somebody + time.sleep(2) + + lockedby = self.read_lock(project) + if lockedby != user: + print "Lock was stolen by '%s' - ABORTING" % lockedby + sys.exit(8) + + def release_lock(self, project): + self.set_lock(project, '') + def _generate_ring_packages(self): """ Generate dictionary with names of the rings