Skip to content

Commit

Permalink
Merge branch 'master' into nine
Browse files Browse the repository at this point in the history
Conflicts:
	master/buildbot/master.py
	master/buildbot/test/unit/test_process_builder.py

NOTE: test_master.py identified an additional error in
master/buildbot/status/master.py, fixed in this commit.
  • Loading branch information
djmitche committed Nov 5, 2012
2 parents da469c1 + 536a998 commit c872709
Show file tree
Hide file tree
Showing 25 changed files with 290 additions and 95 deletions.
15 changes: 7 additions & 8 deletions master/buildbot/buildslave.py
Expand Up @@ -187,6 +187,7 @@ def startService(self):
self.startMissingTimer()
return service.MultiService.startService(self)

@defer.inlineCallbacks
def reconfigService(self, new_config):
# Given a new BuildSlave, configure this one identically. Because
# BuildSlave objects are remotely referenced, we can't replace them
Expand All @@ -200,7 +201,8 @@ def reconfigService(self, new_config):
self.password != new.password or
new_config.slavePortnum != self.registered_port):
if self.registration:
self.registration.unregister()
yield self.registration.unregister()
self.registration = None
self.password = new.password
self.registered_port = new_config.slavePortnum
self.registration = self.master.pbmanager.register(
Expand Down Expand Up @@ -229,18 +231,15 @@ def reconfigService(self, new_config):
# update the attached slave's notion of which builders are attached.
# This assumes that the relevant builders have already been configured,
# which is why the reconfig_priority is set low in this class.
d = self.updateSlave()

# and chain up
d.addCallback(lambda _ :
config.ReconfigurableServiceMixin.reconfigService(self,
new_config))
yield self.updateSlave()

return d
yield config.ReconfigurableServiceMixin.reconfigService(self,
new_config)

def stopService(self):
if self.registration:
self.registration.unregister()
self.registration = None
self.stopMissingTimer()
return service.MultiService.stopService(self)

Expand Down
4 changes: 3 additions & 1 deletion master/buildbot/changes/pb.py
Expand Up @@ -149,7 +149,9 @@ def _register(self, port):
def _unregister(self):
self.registered_port = None
if self.registration:
return self.registration.unregister()
reg = self.registration
self.registration = None
return reg.unregister()
else:
return defer.succeed(None)

Expand Down
6 changes: 5 additions & 1 deletion master/buildbot/config.py
Expand Up @@ -655,7 +655,7 @@ class BuilderConfig:
def __init__(self, name=None, slavename=None, slavenames=None,
builddir=None, slavebuilddir=None, factory=None, category=None,
nextSlave=None, nextBuild=None, locks=None, env=None,
properties=None, mergeRequests=None):
properties=None, mergeRequests=None, description=None):

errors = ConfigErrors([])

Expand Down Expand Up @@ -729,6 +729,8 @@ def __init__(self, name=None, slavename=None, slavenames=None,
self.properties = properties or {}
self.mergeRequests = mergeRequests

self.description = description

if errors:
raise errors

Expand Down Expand Up @@ -757,6 +759,8 @@ def getConfigDict(self):
rv['properties'] = self.properties
if self.mergeRequests:
rv['mergeRequests'] = self.mergeRequests
if self.description:
rv['description'] = self.description
return rv


Expand Down
3 changes: 3 additions & 0 deletions master/buildbot/interfaces.py
Expand Up @@ -300,6 +300,9 @@ def getName():
def getCategory():
"""Return the category of this builder (a string)."""

def getDescription():
"""Return the description of this builder (a string)."""

def getState():
# TODO: this isn't nearly as meaningful as it used to be
"""Return a tuple (state, builds) for this Builder. 'state' is the
Expand Down
1 change: 1 addition & 0 deletions master/buildbot/master.py
Expand Up @@ -242,6 +242,7 @@ def sighup(*args):

@defer.inlineCallbacks
def stopService(self):
yield service.MultiService.stopService(self)
if self.masterid is not None:
yield self.data.updates.masterStopped(
name=self.name, masterid=self.masterid)
Expand Down
9 changes: 8 additions & 1 deletion master/buildbot/pbmanager.py
Expand Up @@ -66,7 +66,6 @@ def _unregister(self, registration):
return disp.disownServiceParent()
return defer.succeed(None)


class Registration(object):
def __init__(self, pbmanager, portstr, username):
self.portstr = portstr
Expand All @@ -76,6 +75,10 @@ def __init__(self, pbmanager, portstr, username):

self.pbmanager = pbmanager

def __repr__(self):
return "<pbmanager.Registration for %s on %s>" % \
(self.username, self.portstr)

def unregister(self):
"""
Unregister this registration, removing the username from the port, and
Expand Down Expand Up @@ -110,6 +113,10 @@ def __init__(self, portstr):
self.serverFactory.unsafeTracebacks = True
self.port = strports.listen(portstr, self.serverFactory)

def __repr__(self):
return "<pbmanager.Dispatcher for %s on %s>" % \
(", ".join(self.users.keys()), self.portstr)

def stopService(self):
# stop listening on the port when shut down
d = defer.maybeDeferred(self.port.stopListening)
Expand Down
4 changes: 3 additions & 1 deletion master/buildbot/process/builder.py
Expand Up @@ -85,10 +85,12 @@ def reconfigService(self, new_config):
self.builder_status = self.master.status.builderAdded(
builder_config.name,
builder_config.builddir,
builder_config.category)
builder_config.category,
builder_config.description)

self.config = builder_config

self.builder_status.setDescription(builder_config.description)
self.builder_status.setCategory(builder_config.category)
self.builder_status.setSlavenames(self.config.slavenames)
self.builder_status.setCacheSize(new_config.caches['Builds'])
Expand Down
2 changes: 1 addition & 1 deletion master/buildbot/scripts/sample.cfg
Expand Up @@ -107,7 +107,7 @@ c['status'].append(html.WebStatus(http_port=8010, authz=authz_cfg))
# 'titleURL') and is embedded in the title of the waterfall HTML page.

c['title'] = "Pyflakes"
c['titleURL'] = "http://divmod.org/trac/wiki/DivmodPyflakes"
c['titleURL'] = "https://launchpad.net/pyflakes"

# the 'buildbotURL' string should point to the location where the buildbot's
# internal web server (usually the html.WebStatus page) is visible. This
Expand Down
10 changes: 9 additions & 1 deletion master/buildbot/status/builder.py
Expand Up @@ -62,9 +62,10 @@ class BuilderStatus(styles.Versioned):
currentBigState = "offline" # or idle/waiting/interlocked/building
basedir = None # filled in by our parent

def __init__(self, buildername, category, master):
def __init__(self, buildername, category, master, description):
self.name = buildername
self.category = category
self.description = description
self.master = master

self.slavenames = []
Expand Down Expand Up @@ -269,6 +270,13 @@ def getName(self):
# str(self.name) may be a workaround
return self.name

def setDescription(self, description):
# used during reconfig
self.description = description

def getDescription(self):
return self.description

def getState(self):
return (self.currentBigState, self.currentBuilds)

Expand Down
9 changes: 4 additions & 5 deletions master/buildbot/status/master.py
Expand Up @@ -90,9 +90,6 @@ def stopService(self):
self._buildset_new_consumer.stopConsuming()
self._buildset_new_consumer = None

self._build_request_sub.unsubscribe()
self._build_request_sub = None

self._change_consumer.stopConsuming()
self._change_consumer = None

Expand Down Expand Up @@ -317,7 +314,7 @@ def announceNewBuilder(self, target, name, builder_status):
if t:
builder_status.subscribe(t)

def builderAdded(self, name, basedir, category=None):
def builderAdded(self, name, basedir, category=None, description=None):
"""
@rtype: L{BuilderStatus}
"""
Expand Down Expand Up @@ -347,12 +344,14 @@ def builderAdded(self, name, basedir, category=None):
log.msg("error follows:")
log.err()
if not builder_status:
builder_status = builder.BuilderStatus(name, category, self.master)
builder_status = builder.BuilderStatus(name, category, self.master,
description)
builder_status.addPointEvent(["builder", "created"])
log.msg("added builder %s in category %s" % (name, category))
# an unpickled object might not have category set from before,
# so set it here to make sure
builder_status.category = category
builder_status.description = description
builder_status.master = self.master
builder_status.basedir = os.path.join(self.basedir, basedir)
builder_status.name = name # it might have been updated
Expand Down
21 changes: 18 additions & 3 deletions master/buildbot/status/web/baseweb.py
Expand Up @@ -19,6 +19,7 @@
from zope.interface import implements
from twisted.python import log
from twisted.application import strports, service
from twisted.internet import defer
from twisted.web import server, distrib, static
from twisted.spread import pb
from twisted.web.util import Redirect
Expand Down Expand Up @@ -318,6 +319,10 @@ def __init__(self, http_port=None, distrib_port=None, allowForce=None,
# If we were given a site object, go ahead and use it. (if not, we add one later)
self.site = site

# keep track of our child services
self.http_svc = None
self.distrib_svc = None

# store the log settings until we create the site object
self.logRotateLength = logRotateLength
self.maxRotatedFiles = maxRotatedFiles
Expand Down Expand Up @@ -439,11 +444,11 @@ def _openLogFile(self, path):
self.site.buildbot_service = self

if self.http_port is not None:
s = strports.service(self.http_port, self.site)
self.http_svc = s = strports.service(self.http_port, self.site)
s.setServiceParent(self)
if self.distrib_port is not None:
f = pb.PBServerFactory(distrib.ResourcePublisher(self.site))
s = strports.service(self.distrib_port, f)
self.distrib_svc = s = strports.service(self.distrib_port, f)
s.setServiceParent(self)

self.setupSite()
Expand Down Expand Up @@ -490,6 +495,7 @@ def putChild(self, name, child_resource):
def registerChannel(self, channel):
self.channels[channel] = 1 # weakrefs

@defer.inlineCallbacks
def stopService(self):
for channel in self.channels:
try:
Expand All @@ -498,7 +504,16 @@ def stopService(self):
log.msg("WebStatus.stopService: error while disconnecting"
" leftover clients")
log.err()
return service.MultiService.stopService(self)
yield service.MultiService.stopService(self)

# having shut them down, now remove our child services so they don't
# start up again if we're re-started
if self.http_svc:
yield self.http_svc.disownServiceParent()
self.http_svc = None
if self.distrib_svc:
yield self.distrib_svc.disownServiceParent()
self.distrib_svc = None

def getStatus(self):
return self.master.getStatus()
Expand Down
1 change: 1 addition & 0 deletions master/buildbot/status/web/builder.py
Expand Up @@ -246,6 +246,7 @@ def content(self, req, cxt):
b = self.builder_status

cxt['name'] = b.getName()
cxt['description'] = b.getDescription()
req.setHeader('Cache-Control', 'no-cache')
slaves = b.getSlaves()
connected_slaves = [s for s in slaves if s.isConnected()]
Expand Down
4 changes: 4 additions & 0 deletions master/buildbot/status/web/templates/builder.html
Expand Up @@ -8,6 +8,10 @@ <h1>Builder {{ name }}</h1>

<p>(<a href="{{ path_to_root }}waterfall?show={{ name }}">view in waterfall</a>)</p>

{% if description %}
<div class="BuilderDescription">{{ description }}</div>
{% endif %}

<div class="column">

{% if current %}
Expand Down
13 changes: 11 additions & 2 deletions master/buildbot/test/fake/fakemaster.py
Expand Up @@ -50,7 +50,7 @@ class FakeBotMaster(object):

class FakeStatus(object):

def builderAdded(self, name, basedir, category=None):
def builderAdded(self, name, basedir, category=None, description=None):
return FakeBuilderStatus()

def getBuilderNames(self):
Expand All @@ -61,8 +61,17 @@ def getSlaveNames(self):

class FakeBuilderStatus(object):

def setDescription(self, description):
self._description = description

def getDescription(self):
return self._description

def setCategory(self, category):
pass
self._category = category

def getCategory(self):
return self._category

def setSlavenames(self, names):
pass
Expand Down

0 comments on commit c872709

Please sign in to comment.