Allow workers to send back metadata

To help with debugging, allow workers to send back information about
itself such as hostname and ips. This will allow for an RPC/Client
call to get the information on running jobs.

Change-Id: I03b553293923cd65b3a9651a8877aa23688d2909
This commit is contained in:
Joshua Hesketh 2014-01-12 14:35:40 +08:00
parent 90be3219b9
commit ba8776a30a
4 changed files with 105 additions and 3 deletions

View File

@ -87,8 +87,8 @@ follows:
**ZUUL_PIPELINE**
The Zuul pipeline that is building this job
**ZUUL_URL**
The url for the zuul server as configured in zuul.conf.
A test runner may use this URL as the basis for fetching
The url for the zuul server as configured in zuul.conf.
A test runner may use this URL as the basis for fetching
git commits.
The following additional parameters will only be provided for builds
@ -195,6 +195,30 @@ encoded in JSON format:
The URL with the status or results of the build. Will be used in
the status page and the final report.
To help with debugging builds a worker may send back some optional
metadata:
**worker_name** (optional)
The name of the worker.
**worker_hostname** (optional)
The hostname of the worker.
**worker_ips** (optional)
A list of IPs for the worker.
**worker_fqdn** (optional)
The FQDN of the worker.
**worker_program** (optional)
The program name of the worker. For example Jenkins or turbo-hipster.
**worker_version** (optional)
The version of the software running the job.
**worker_extra** (optional)
A dictionary of any extra metadata you may want to pass along.
It should then immediately send a WORK_STATUS packet with a value of 0
percent complete. It may then optionally send subsequent WORK_STATUS
packets with updated completion values.

View File

@ -494,12 +494,23 @@ class FakeBuild(threading.Thread):
'name': self.name,
'number': self.number,
'manager': self.worker.worker_id,
'worker_name': 'My Worker',
'worker_hostname': 'localhost',
'worker_ips': ['127.0.0.1', '192.168.1.1'],
'worker_fqdn': 'zuul.example.org',
'worker_program': 'FakeBuilder',
'worker_version': 'v1.1',
'worker_extra': {'something': 'else'}
}
self.log.debug('Running build %s' % self.unique)
self.job.sendWorkData(json.dumps(data))
self.log.debug('Sent WorkData packet with %s' % json.dumps(data))
self.job.sendWorkStatus(0, 100)
if self.worker.hold_jobs_in_build:
self.log.debug('Holding build %s' % self.unique)
self._wait()
self.log.debug("Build %s continuing" % self.unique)
@ -3570,3 +3581,41 @@ class TestScheduler(testtools.TestCase):
self.assertEqual(queue.window, 2)
self.assertEqual(queue.window_floor, 1)
self.assertEqual(C.data['status'], 'MERGED')
def test_worker_update_metadata(self):
"Test if a worker can send back metadata about itself"
self.worker.hold_jobs_in_build = True
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
A.addApproval('CRVW', 2)
self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
self.waitUntilSettled()
self.assertEqual(len(self.launcher.builds), 1)
self.log.debug('Current builds:')
self.log.debug(self.launcher.builds)
start = time.time()
while True:
if time.time() - start > 10:
raise Exception("Timeout waiting for gearman server to report "
+ "back to the client")
build = self.launcher.builds.values()[0]
if build.worker.name == "My Worker":
break
else:
time.sleep(0)
self.log.debug(build)
self.assertEqual("My Worker", build.worker.name)
self.assertEqual("localhost", build.worker.hostname)
self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
self.assertEqual("zuul.example.org", build.worker.fqdn)
self.assertEqual("FakeBuilder", build.worker.program)
self.assertEqual("v1.1", build.worker.version)
self.assertEqual({'something': 'else'}, build.worker.extra)
self.worker.hold_jobs_in_build = False
self.worker.release()
self.waitUntilSettled()

View File

@ -381,6 +381,8 @@ class Gearman(object):
if build:
# Allow URL to be updated
build.url = data.get('url') or build.url
# Update information about worker
build.worker.updateFromData(data)
if build.number is None:
self.log.info("Build %s started" % job)

View File

@ -627,9 +627,36 @@ class Build(object):
self.canceled = False
self.retry = False
self.parameters = {}
self.worker = Worker()
def __repr__(self):
return '<Build %s of %s>' % (self.uuid, self.job.name)
return ('<Build %s of %s on %s>' %
(self.uuid, self.job.name, self.worker))
class Worker(object):
"""A model of the worker running a job"""
def __init__(self):
self.name = "Unknown"
self.hostname = None
self.ips = []
self.fqdn = None
self.program = None
self.version = None
self.extra = {}
def updateFromData(self, data):
"""Update worker information if contained in the WORK_DATA response."""
self.name = data.get('worker_name', self.name)
self.hostname = data.get('worker_hostname', self.hostname)
self.ips = data.get('worker_ips', self.ips)
self.fqdn = data.get('worker_fqdn', self.fqdn)
self.program = data.get('worker_program', self.program)
self.version = data.get('worker_version', self.version)
self.extra = data.get('worker_extra', self.extra)
def __repr__(self):
return '<Worker %s>' % self.name
class BuildSet(object):