launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #15812
[Merge] lp:~wgrant/launchpad/builderinteractor-privatise into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/builderinteractor-privatise into lp:launchpad with lp:~wgrant/launchpad/builderinteractor-extract as a prerequisite.
Commit message:
Privatise and reshuffle bits and pieces around BuilderInteractor.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/builderinteractor-privatise/+merge/182375
Privatise and reshuffle bits and pieces around BuilderInteractor.
--
https://code.launchpad.net/~wgrant/launchpad/builderinteractor-privatise/+merge/182375
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/builderinteractor-privatise into lp:launchpad.
=== modified file 'lib/lp/buildmaster/doc/buildfarmjobbehavior.txt'
--- lib/lp/buildmaster/doc/buildfarmjobbehavior.txt 2013-08-27 12:14:18 +0000
+++ lib/lp/buildmaster/doc/buildfarmjobbehavior.txt 2013-08-27 12:14:18 +0000
@@ -98,7 +98,7 @@
>>> from lp.buildmaster.interactor import BuilderInteractor
>>> interactor = BuilderInteractor(bob)
- >>> interactor.current_build_behavior.logStartBuild(None)
+ >>> interactor._current_build_behavior.logStartBuild(None)
Traceback (most recent call last):
...
BuildBehaviorMismatch: Builder was idle when asked to log the start of a
@@ -107,7 +107,7 @@
If a slave is working on a job while we think it is idle, it will always be
aborted.
- >>> interactor.current_build_behavior.verifySlaveBuildCookie('foo')
+ >>> interactor._current_build_behavior.verifySlaveBuildCookie('foo')
Traceback (most recent call last):
...
CorruptBuildCookie: No job assigned to builder
=== modified file 'lib/lp/buildmaster/doc/buildqueue.txt'
--- lib/lp/buildmaster/doc/buildqueue.txt 2012-12-26 01:32:19 +0000
+++ lib/lp/buildmaster/doc/buildqueue.txt 2013-08-27 12:14:18 +0000
@@ -99,16 +99,6 @@
(True, 1000)
-The BuildQueue item is responsible for providing the required build behavior
-for the item.
-
- >>> from zope.security.proxy import isinstance
- >>> from lp.soyuz.model.binarypackagebuildbehavior import (
- ... BinaryPackageBuildBehavior)
- >>> isinstance(bq.required_build_behavior, BinaryPackageBuildBehavior)
- True
-
-
== Dispatching and Reseting jobs ==
The sampledata contains an active job, being built by the 'bob'
=== modified file 'lib/lp/buildmaster/interactor.py'
--- lib/lp/buildmaster/interactor.py 2013-08-27 12:14:18 +0000
+++ lib/lp/buildmaster/interactor.py 2013-08-27 12:14:18 +0000
@@ -5,7 +5,6 @@
__all__ = [
'BuilderInteractor',
- 'ProxyWithConnectionTimeout',
]
import gzip
@@ -16,10 +15,7 @@
from urlparse import urlparse
import xmlrpclib
-from twisted.internet import (
- defer,
- reactor as default_reactor,
- )
+from twisted.internet import defer
from twisted.web import xmlrpc
from twisted.web.client import downloadPage
from zope.component import getUtility
@@ -35,6 +31,9 @@
CannotResumeHost,
CorruptBuildCookie,
)
+from lp.buildmaster.interfaces.buildfarmjobbehavior import (
+ IBuildFarmJobBehavior,
+ )
from lp.buildmaster.model.buildfarmjobbehavior import IdleBuildBehavior
from lp.services.config import config
from lp.services.helpers import filenameToContentType
@@ -50,38 +49,6 @@
noisy = False
-class ProxyWithConnectionTimeout(xmlrpc.Proxy):
- """Extend Twisted's Proxy to provide a configurable connection timeout."""
-
- def __init__(self, url, user=None, password=None, allowNone=False,
- useDateTime=False, timeout=None):
- xmlrpc.Proxy.__init__(
- self, url, user, password, allowNone, useDateTime)
- self.timeout = timeout
-
- def callRemote(self, method, *args):
- """Basically a carbon copy of the parent but passes the timeout
- to connectTCP."""
-
- def cancel(d):
- factory.deferred = None
- connector.disconnect()
- factory = self.queryFactory(
- self.path, self.host, method, self.user,
- self.password, self.allowNone, args, cancel, self.useDateTime)
- if self.secure:
- from twisted.internet import ssl
- connector = default_reactor.connectSSL(
- self.host, self.port or 443, factory,
- ssl.ClientContextFactory(),
- timeout=self.timeout)
- else:
- connector = default_reactor.connectTCP(
- self.host, self.port or 80, factory,
- timeout=self.timeout)
- return factory.deferred
-
-
class BuilderSlave(object):
"""Add in a few useful methods for the XMLRPC slave.
@@ -123,8 +90,8 @@
"""
rpc_url = urlappend(builder_url.encode('utf-8'), 'rpc')
if proxy is None:
- server_proxy = ProxyWithConnectionTimeout(
- rpc_url, allowNone=True, timeout=timeout)
+ server_proxy = xmlrpc.Proxy(
+ rpc_url, allowNone=True, connectTimeout=timeout)
server_proxy.queryFactory = QuietQueryFactory
else:
server_proxy = proxy
@@ -264,7 +231,7 @@
_cached_slave = None
_cached_slave_attrs = None
- # Tests can override current_build_behavior and slave.
+ # Tests can override _current_build_behavior and slave.
_override_behavior = None
_override_slave = None
@@ -293,11 +260,11 @@
return self._cached_slave
@property
- def current_build_behavior(self):
+ def _current_build_behavior(self):
"""Return the current build behavior."""
if self._override_behavior is not None:
return self._override_behavior
- # The current_build_behavior cache is invalidated when
+ # The _current_build_behavior cache is invalidated when
# builder.currentjob changes.
currentjob = self.builder.currentjob
if currentjob is None:
@@ -305,7 +272,8 @@
self._cached_build_behavior, IdleBuildBehavior):
self._cached_build_behavior = IdleBuildBehavior()
elif currentjob != self._cached_currentjob:
- self._cached_build_behavior = currentjob.required_build_behavior
+ self._cached_build_behavior = IBuildFarmJobBehavior(
+ currentjob.specific_job)
self._cached_build_behavior.setBuilderInteractor(self)
self._cached_currentjob = currentjob
return self._cached_build_behavior
@@ -332,30 +300,12 @@
if status['builder_status'] == 'BuilderStatus.BUILDING':
status['logtail'] = status_sentence[2]
- self.current_build_behavior.updateSlaveStatus(
+ self._current_build_behavior.updateSlaveStatus(
status_sentence, status)
return status
return d.addCallback(got_status)
- def slaveStatusSentence(self):
- """Get the slave status sentence for this builder.
-
- :return: A Deferred which fires when the slave dialog is complete.
- Its value is a tuple with the first element containing the
- slave status, build_id-queue-id and then optionally more
- elements depending on the status.
- """
- return self.slave.status()
-
- def verifySlaveBuildCookie(self, slave_build_id):
- """Verify that a slave's build cookie is consistent.
-
- This should delegate to the current `IBuildFarmJobBehavior`.
- """
- return self.current_build_behavior.verifySlaveBuildCookie(
- slave_build_id)
-
def isAvailable(self):
"""Whether or not a builder is available for building new jobs.
@@ -364,7 +314,7 @@
"""
if not self.builder.builderok:
return defer.succeed(False)
- d = self.slaveStatusSentence()
+ d = self.slave.status()
def catch_fault(failure):
failure.trap(xmlrpclib.Fault, socket.error)
@@ -395,7 +345,7 @@
'BuilderStatus.WAITING': 2
}
- d = self.slaveStatusSentence()
+ d = self.slave.status()
def got_status(status_sentence):
"""After we get the status, clean if we have to.
@@ -403,7 +353,7 @@
Always return status_sentence.
"""
# Isolate the BuilderStatus string, always the first token in
- # IBuilder.slaveStatusSentence().
+ # BuilderSlave.status().
status = status_sentence[0]
# If the cookie test below fails, it will request an abort of the
@@ -442,7 +392,8 @@
return
slave_build_id = status_sentence[ident_position[status]]
try:
- self.verifySlaveBuildCookie(slave_build_id)
+ self._current_build_behavior.verifySlaveBuildCookie(
+ slave_build_id)
except CorruptBuildCookie as reason:
if status == 'BuilderStatus.WAITING':
d = self.cleanSlave()
@@ -536,15 +487,15 @@
explaining what went wrong.
"""
needed_bfjb = type(removeSecurityProxy(
- build_queue_item.required_build_behavior))
- if not zope_isinstance(self.current_build_behavior, needed_bfjb):
+ IBuildFarmJobBehavior(build_queue_item.specific_job)))
+ if not zope_isinstance(self._current_build_behavior, needed_bfjb):
raise AssertionError(
"Inappropriate IBuildFarmJobBehavior: %r is not a %r" %
- (self.current_build_behavior, needed_bfjb))
- self.current_build_behavior.logStartBuild(logger)
+ (self._current_build_behavior, needed_bfjb))
+ self._current_build_behavior.logStartBuild(logger)
# Make sure the request is valid; an exception is raised if it's not.
- self.current_build_behavior.verifyBuildRequest(logger)
+ self._current_build_behavior.verifyBuildRequest(logger)
# Set the build behavior depending on the provided build queue item.
if not self.builder.builderok:
@@ -558,7 +509,7 @@
d = defer.succeed(None)
def ping_done(ignored):
- return self.current_build_behavior.dispatchBuildToSlave(
+ return self._current_build_behavior.dispatchBuildToSlave(
build_queue_item.id, logger)
def resume_done(ignored):
@@ -659,7 +610,7 @@
:return: A Deferred that fires when the slave dialog is finished.
"""
- return self.current_build_behavior.updateBuild(queueItem)
+ return self._current_build_behavior.updateBuild(queueItem)
def transferSlaveFileToLibrarian(self, file_sha1, filename, private):
"""Transfer a file from the slave to the librarian.
=== modified file 'lib/lp/buildmaster/interfaces/buildqueue.py'
--- lib/lp/buildmaster/interfaces/buildqueue.py 2013-01-07 02:40:55 +0000
+++ lib/lp/buildmaster/interfaces/buildqueue.py 2013-08-27 12:14:18 +0000
@@ -19,7 +19,6 @@
Bool,
Choice,
Datetime,
- Field,
Int,
Text,
Timedelta,
@@ -72,10 +71,6 @@
title=_('Job type'), required=True, vocabulary=BuildFarmJobType,
description=_("The type of this job."))
- required_build_behavior = Field(
- title=_('The builder behavior required to run this job.'),
- required=False, readonly=True)
-
estimated_duration = Timedelta(
title=_("Estimated Job Duration"), required=True,
description=_("Estimated job duration interval."))
=== modified file 'lib/lp/buildmaster/model/buildqueue.py'
--- lib/lp/buildmaster/model/buildqueue.py 2013-08-27 12:14:18 +0000
+++ lib/lp/buildmaster/model/buildqueue.py 2013-08-27 12:14:18 +0000
@@ -33,9 +33,6 @@
from lp.app.errors import NotFoundError
from lp.buildmaster.enums import BuildFarmJobType
from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
-from lp.buildmaster.interfaces.buildfarmjobbehavior import (
- IBuildFarmJobBehavior,
- )
from lp.buildmaster.interfaces.buildqueue import (
IBuildQueue,
IBuildQueueSet,
@@ -128,11 +125,6 @@
processor = ForeignKey(dbName='processor', foreignKey='Processor')
virtualized = BoolCol(dbName='virtualized')
- @property
- def required_build_behavior(self):
- """See `IBuildQueue`."""
- return IBuildFarmJobBehavior(self.specific_job)
-
@cachedproperty
def specific_job(self):
"""See `IBuildQueue`."""
=== modified file 'lib/lp/buildmaster/tests/test_builder.py'
--- lib/lp/buildmaster/tests/test_builder.py 2013-08-27 12:14:18 +0000
+++ lib/lp/buildmaster/tests/test_builder.py 2013-08-27 12:14:18 +0000
@@ -32,7 +32,6 @@
from lp.buildmaster.interactor import (
BuilderInteractor,
BuilderSlave,
- ProxyWithConnectionTimeout,
)
from lp.buildmaster.interfaces.builder import (
CannotFetchFile,
@@ -232,7 +231,7 @@
# At this point we should see a valid behaviour on the builder:
self.assertFalse(
zope_isinstance(
- interactor.current_build_behavior, IdleBuildBehavior))
+ interactor._current_build_behavior, IdleBuildBehavior))
# Now reset the job and try to rescue the builder.
candidate.destroySelf()
@@ -242,7 +241,7 @@
def check_builder(ignored):
self.assertIsInstance(
- removeSecurityProxy(interactor.current_build_behavior),
+ removeSecurityProxy(interactor._current_build_behavior),
IdleBuildBehavior)
return d.addCallback(check_builder)
@@ -473,7 +472,7 @@
AbortedSlave(), builder_status='BuilderStatus.ABORTED')
def test_isAvailable_with_not_builderok(self):
- # isAvailable() is a wrapper around slaveStatusSentence()
+ # isAvailable() is a wrapper around BuilderSlave.status()
builder = MockBuilder()
builder.builderok = False
d = BuilderInteractor(builder).isAvailable()
@@ -817,7 +816,7 @@
class TestCurrentBuildBehavior(TestCaseWithFactory):
"""This test ensures the get/set behavior of BuilderInteractor's
- current_build_behavior property.
+ _current_build_behavior property.
"""
layer = LaunchpadZopelessLayer
@@ -844,14 +843,14 @@
nor a current build.
"""
self.assertIsInstance(
- self.interactor.current_build_behavior, IdleBuildBehavior)
+ self.interactor._current_build_behavior, IdleBuildBehavior)
def test_current_job_behavior(self):
"""The current behavior is set automatically from the current job."""
# Set the builder attribute on the buildqueue record so that our
# builder will think it has a current build.
self.build.buildqueue_record.builder = self.builder
- behavior = removeSecurityProxy(self.interactor.current_build_behavior)
+ behavior = removeSecurityProxy(self.interactor._current_build_behavior)
self.assertIsInstance(behavior, BinaryPackageBuildBehavior)
self.assertEqual(behavior._builder, self.builder)
self.assertEqual(behavior._interactor, self.interactor)
@@ -1135,12 +1134,6 @@
self.assertTrue(d.called)
return assert_fails_with(d, CancelledError)
- def test_BuilderSlave_uses_ProxyWithConnectionTimeout(self):
- # Make sure that BuilderSlaves use the custom proxy class.
- slave = BuilderSlave.makeBuilderSlave(
- "url", "host", config.builddmaster.socket_timeout)
- self.assertIsInstance(slave._server, ProxyWithConnectionTimeout)
-
class TestSlaveWithLibrarian(TestCaseWithFactory):
"""Tests that need more of Launchpad to run."""
=== modified file 'lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py'
--- lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 2013-08-27 12:14:18 +0000
+++ lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 2013-08-27 12:14:18 +0000
@@ -17,6 +17,9 @@
from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.interactor import BuilderInteractor
from lp.buildmaster.interfaces.builder import CorruptBuildCookie
+from lp.buildmaster.interfaces.buildfarmjobbehavior import (
+ IBuildFarmJobBehavior,
+ )
from lp.buildmaster.model.buildfarmjobbehavior import BuildFarmJobBehaviorBase
from lp.buildmaster.tests.mock_slaves import WaitingSlave
from lp.registry.interfaces.pocket import PackagePublishingPocket
@@ -183,8 +186,8 @@
def setUp(self):
super(TestGetUploadMethodsMixin, self).setUp()
self.build = self.makeBuild()
- self.behavior = removeSecurityProxy(
- self.build.buildqueue_record.required_build_behavior)
+ self.behavior = IBuildFarmJobBehavior(
+ self.build.buildqueue_record.specific_job)
def test_getUploadDirLeafCookie_parseable(self):
# getUploadDirLeaf should return a directory name
@@ -221,7 +224,7 @@
self.slave.valid_file_hashes.append('test_file_hash')
self.interactor = BuilderInteractor(self.builder, self.slave)
self.behavior = removeSecurityProxy(
- self.interactor.current_build_behavior)
+ self.interactor._current_build_behavior)
# We overwrite the buildmaster root to use a temp directory.
tempdir = tempfile.mkdtemp()
=== modified file 'lib/lp/code/model/tests/test_recipebuilder.py'
--- lib/lp/code/model/tests/test_recipebuilder.py 2013-08-27 12:14:18 +0000
+++ lib/lp/code/model/tests/test_recipebuilder.py 2013-08-27 12:14:18 +0000
@@ -372,7 +372,7 @@
queue_record.builder = self.factory.makeBuilder()
slave = WaitingSlave('BuildStatus.OK')
interactor = BuilderInteractor(queue_record.builder, slave)
- return removeSecurityProxy(interactor.current_build_behavior)
+ return removeSecurityProxy(interactor._current_build_behavior)
def assertDeferredNotifyCount(self, status, behavior, expected_count):
d = behavior.handleStatus(status, None, {'filemap': {}})
=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py'
--- lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py 2013-08-27 12:14:18 +0000
+++ lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py 2013-08-27 12:14:18 +0000
@@ -23,6 +23,9 @@
BuilderSlave,
)
from lp.buildmaster.interfaces.builder import CannotBuild
+from lp.buildmaster.interfaces.buildfarmjobbehavior import (
+ IBuildFarmJobBehavior,
+ )
from lp.buildmaster.tests.mock_slaves import (
AbortedSlave,
AbortingSlave,
@@ -96,7 +99,7 @@
:return: A list of the calls we expect to be made.
"""
job = removeSecurityProxy(
- interactor.current_build_behavior).buildfarmjob
+ interactor._current_build_behavior).buildfarmjob
build_id = job.generateSlaveBuildCookie()
ds_name = build.distro_arch_series.distroseries.name
suite = ds_name + pocketsuffix[build.pocket]
@@ -218,7 +221,7 @@
transaction.commit()
build.distro_arch_series.addOrUpdateChroot(lf)
candidate = build.queueBuild()
- behavior = candidate.required_build_behavior
+ behavior = IBuildFarmJobBehavior(candidate.specific_job)
behavior.setBuilderInteractor(BuilderInteractor(builder))
e = self.assertRaises(
AssertionError, behavior.verifyBuildRequest, BufferLogger())
@@ -239,7 +242,7 @@
transaction.commit()
build.distro_arch_series.addOrUpdateChroot(lf)
candidate = build.queueBuild()
- behavior = candidate.required_build_behavior
+ behavior = IBuildFarmJobBehavior(candidate.specific_job)
behavior.setBuilderInteractor(BuilderInteractor(builder))
e = self.assertRaises(
AssertionError, behavior.verifyBuildRequest, BufferLogger())
@@ -258,7 +261,7 @@
transaction.commit()
build.distro_arch_series.addOrUpdateChroot(lf)
candidate = build.queueBuild()
- behavior = candidate.required_build_behavior
+ behavior = IBuildFarmJobBehavior(candidate.specific_job)
behavior.setBuilderInteractor(BuilderInteractor(builder))
e = self.assertRaises(
AssertionError, behavior.verifyBuildRequest, BufferLogger())
@@ -273,7 +276,7 @@
build = self.factory.makeBinaryPackageBuild(
builder=builder, archive=archive)
candidate = build.queueBuild()
- behavior = candidate.required_build_behavior
+ behavior = IBuildFarmJobBehavior(candidate.specific_job)
behavior.setBuilderInteractor(BuilderInteractor(builder))
e = self.assertRaises(
CannotBuild, behavior.verifyBuildRequest, BufferLogger())
@@ -284,7 +287,7 @@
# The uploadprocessor relies on this format.
build = self.factory.makeBinaryPackageBuild()
candidate = build.queueBuild()
- behavior = candidate.required_build_behavior
+ behavior = IBuildFarmJobBehavior(candidate.specific_job)
cookie = removeSecurityProxy(behavior).getBuildCookie()
expected_cookie = "PACKAGEBUILD-%d" % build.id
self.assertEqual(expected_cookie, cookie)
@@ -324,7 +327,7 @@
self.build.distro_arch_series.addOrUpdateChroot(lf)
self.candidate = self.build.queueBuild()
self.candidate.markAsBuilding(self.builder)
- self.behavior = self.candidate.required_build_behavior
+ self.behavior = IBuildFarmJobBehavior(self.candidate.specific_job)
self.behavior.setBuilderInteractor(BuilderInteractor(self.builder))
# This is required so that uploaded files from the buildd don't
# hang around between test runs.
Follow ups