Skip to content

Commit

Permalink
add a couple of 'wait for jobs' methods
Browse files Browse the repository at this point in the history
These let you wait for a list of jobs (job IDs or actual job
dicts) to be complete, and for the jobs for a specified BUILD
to appear and to be complete. These are things that various
Fedora scheduling/reporting tools need to do, and putting them
in the client library seems reasonable.
  • Loading branch information
AdamWill committed Sep 2, 2015
1 parent 6948b8f commit 9155b6a
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
62 changes: 62 additions & 0 deletions openqa_client/client.py
Expand Up @@ -143,3 +143,65 @@ def openqa_request(self, method, path, params={}):
url = '{0}{1}'.format(self.baseurl, path)
req = requests.Request(method=method, url=url, params=params)
return self.do_request(req)

def wait_jobs(self, jobs, waittime=180, delay=60):
"""Wait up to 'waittime' minutes, checking every 'delay'
seconds, for the specified jobs (an iterable of job IDs) to
be 'done' or 'cancelled'. Returns a list of the job dicts
(with the useless outer dict which just has a single 'job:'
key stripped). You can also pass an existing iterable of
job dicts as 'jobs': if they are all done the list will be
returned immediately, unmodified, otherwise the ids will be
yanked out and used and the waiting will proceed. If waittime
is set to 0, we will query just once and either succeed or
fail immediately.
"""
# First check if we got a list of dicts and they're all done,
# and return right away if so.
try:
done = [job['id'] for job in jobs if job['state'] in ('done', 'cancelled')]
if len(done) == len(jobs):
return jobs
else:
jobs = [job['id'] for job in jobs]
except TypeError:
# Job list is just IDs, not dicts
pass

waitstart = time.time()
done = {}
while True:
for job in jobs:
if job not in done:
path = 'jobs/{0}'.format(str(job))
jobdict = self.openqa_request('GET', path)['job']
if jobdict['state'] in ('done', 'cancelled'):
done[job] = jobdict

if len(done) == len(jobs):
return done.values()
else:
if time.time() - waitstart > waittime * 60:
raise openqa_client.exceptions.WaitError("Waited too long!")
time.sleep(delay)

def wait_build_jobs(self, build, waittime=480, delay=60):
"""Wait up to 'waittime' minutes, checking every 'delay'
seconds, for jobs for the specified BUILD to appear and
complete. This method waits for some jobs to appear for the
specified BUILD at all, then hands off to wait_jobs() to wait
for them to be complete. If waittime is set to 0, we will
query just once and either succeed or fail immediately.
"""
waitstart = time.time()
jobs = []
while True:
jobs = self.openqa_request('GET', 'jobs', params={'build': build})['jobs']
if jobs:
# call wait_jobs with the remaining waittime
waited = (time.time() - waitstart) // 60
return self.wait_jobs(jobs, waittime=max(0, waittime - waited))
else:
if time.time() - waitstart > waittime * 60:
raise openqa_client.exceptions.WaitError("Waited too long!")
time.sleep(delay)
4 changes: 4 additions & 0 deletions openqa_client/exceptions.py
Expand Up @@ -28,3 +28,7 @@ class RequestError(Exception):
method, URL, and status code.
"""
pass

class WaitError(Exception):
"""Error raised when some kind of wait has gone on too long."""
pass

0 comments on commit 9155b6a

Please sign in to comment.