zuul/zuul/merger/client.py

118 lines
3.9 KiB
Python

# Copyright 2014 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import logging
from uuid import uuid4
import gear
def getJobData(job):
if not len(job.data):
return {}
d = job.data[-1]
if not d:
return {}
return json.loads(d)
class MergeGearmanClient(gear.Client):
def __init__(self, merge_client):
super(MergeGearmanClient, self).__init__()
self.__merge_client = merge_client
def handleWorkComplete(self, packet):
job = super(MergeGearmanClient, self).handleWorkComplete(packet)
self.__merge_client.onBuildCompleted(job)
return job
def handleWorkFail(self, packet):
job = super(MergeGearmanClient, self).handleWorkFail(packet)
self.__merge_client.onBuildCompleted(job)
return job
def handleWorkException(self, packet):
job = super(MergeGearmanClient, self).handleWorkException(packet)
self.__merge_client.onBuildCompleted(job)
return job
def handleDisconnect(self, job):
job = super(MergeGearmanClient, self).handleDisconnect(job)
self.__merge_client.onBuildCompleted(job)
class MergeClient(object):
log = logging.getLogger("zuul.MergeClient")
def __init__(self, config, sched):
self.config = config
self.sched = sched
server = self.config.get('gearman', 'server')
if self.config.has_option('gearman', 'port'):
port = self.config.get('gearman', 'port')
else:
port = 4730
self.log.debug("Connecting to gearman at %s:%s" % (server, port))
self.gearman = MergeGearmanClient(self)
self.gearman.addServer(server, port)
self.log.debug("Waiting for gearman")
self.gearman.waitForServer()
self.build_sets = {}
def stop(self):
self.gearman.shutdown()
def areMergesOutstanding(self):
if self.build_sets:
return True
return False
def submitJob(self, name, data, build_set):
uuid = str(uuid4().hex)
self.log.debug("Submitting job %s with data %s" % (name, data))
job = gear.Job(name,
json.dumps(data),
unique=uuid)
self.build_sets[uuid] = build_set
self.gearman.submitJob(job)
def mergeChanges(self, items, build_set):
data = dict(items=items)
self.submitJob('merger:merge', data, build_set)
def updateRepo(self, project, url, build_set):
data = dict(project=project,
url=url)
self.submitJob('merger:update', data, build_set)
def onBuildCompleted(self, job):
build_set = self.build_sets.get(job.unique)
if build_set:
data = getJobData(job)
zuul_url = data.get('zuul_url')
merged = data.get('merged', False)
updated = data.get('updated', False)
commit = data.get('commit')
self.log.info("Merge %s complete, merged: %s, updated: %s, "
"commit: %s" %
(job, merged, updated, build_set.commit))
self.sched.onMergeCompleted(build_set, zuul_url,
merged, updated, commit)
# The test suite expects the build_set to be removed from
# the internal dict after the wake flag is set.
del self.build_sets[job.unique]
else:
self.log.error("Unable to find build set for uuid %s" % job.unique)