launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #15810
[Merge] lp:~wgrant/launchpad/builderinteractor-c-b-b into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/builderinteractor-c-b-b into lp:launchpad.
Commit message:
Move Builder.current_build_behavior to BuilderInteractor, as it's only used by buildd-manager.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/builderinteractor-c-b-b/+merge/182290
This branch eliminates Builder.current_build_behavior. The property now lives on BuilderInteractor, in buildd-manager's exclusive domain, with a cache (possibly unnecessary, but I didn't want to remove the caching yet) predicated on builder.currentjob. It's no longer able to be set directly, though it can be overridden by tests.
Builder._getCurrentBuildBehavior used to always clear the Builder.currentjob cache, which doesn't really fly after the move to BuilderInteractor. Since Builder.currentjob just finds the builder's assigned BuildQueue, I adjusted various BuildQueue methods to invalidate the cache themselves.
--
https://code.launchpad.net/~wgrant/launchpad/builderinteractor-c-b-b/+merge/182290
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/builderinteractor-c-b-b into lp:launchpad.
=== modified file 'lib/lp/buildmaster/doc/builder.txt'
--- lib/lp/buildmaster/doc/builder.txt 2012-12-26 01:32:19 +0000
+++ lib/lp/buildmaster/doc/builder.txt 2013-08-27 07:55:38 +0000
@@ -27,19 +27,6 @@
>>> print builder.failnotes
None
-Builders can take on different behaviors depending on the type of build
-they are currently processing. Each builder provides an attribute
-(current_build_behavior) to which all the build-type specific behavior
-for the current build is delegated. In the sample data, bob's current
-behavior is dealing with binary packages.
-
- >>> from zope.security.proxy import isinstance
- >>> from lp.soyuz.model.binarypackagebuildbehavior import (
- ... BinaryPackageBuildBehavior)
- >>> isinstance(
- ... builder.current_build_behavior, BinaryPackageBuildBehavior)
- True
-
BuilderSet
==========
=== modified file 'lib/lp/buildmaster/doc/buildfarmjobbehavior.txt'
--- lib/lp/buildmaster/doc/buildfarmjobbehavior.txt 2013-06-20 05:50:00 +0000
+++ lib/lp/buildmaster/doc/buildfarmjobbehavior.txt 2013-08-27 07:55:38 +0000
@@ -90,14 +90,15 @@
First, we'll reset the current build behavior and destroy the current job.
- >>> bob.current_build_behavior = None
>>> bob.currentjob.destroySelf()
Attempting to use any other build-related functionality when a builder is
idle, such as making a call to log the start of a build, will raise an
appropriate exception.
- >>> bob.current_build_behavior.logStartBuild(None)
+ >>> from lp.buildmaster.model.builder import BuilderInteractor
+ >>> interactor = BuilderInteractor(bob)
+ >>> interactor.current_build_behavior.logStartBuild(None)
Traceback (most recent call last):
...
BuildBehaviorMismatch: Builder was idle when asked to log the start of a
@@ -106,7 +107,7 @@
If a slave is working on a job while we think it is idle, it will always be
aborted.
- >>> bob.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/interfaces/builder.py'
--- lib/lp/buildmaster/interfaces/builder.py 2013-08-19 12:01:51 +0000
+++ lib/lp/buildmaster/interfaces/builder.py 2013-08-27 07:55:38 +0000
@@ -169,10 +169,6 @@
title=_('Failure Count'), required=False, default=0,
description=_("Number of consecutive failures for this builder.")))
- current_build_behavior = Field(
- title=u"The current behavior of the builder for the current job.",
- required=False)
-
def gotFailure():
"""Increment failure_count on the builder."""
=== modified file 'lib/lp/buildmaster/model/builder.py'
--- lib/lp/buildmaster/model/builder.py 2013-08-21 12:16:34 +0000
+++ lib/lp/buildmaster/model/builder.py 2013-08-27 07:55:38 +0000
@@ -20,7 +20,6 @@
from urlparse import urlparse
import xmlrpclib
-from lazr.restful.utils import safe_hasattr
from sqlobject import (
BoolCol,
ForeignKey,
@@ -42,7 +41,10 @@
from twisted.web.client import downloadPage
from zope.component import getUtility
from zope.interface import implements
-from zope.security.proxy import removeSecurityProxy
+from zope.security.proxy import (
+ isinstance as zope_isinstance,
+ removeSecurityProxy,
+ )
from lp.app.errors import NotFoundError
from lp.buildmaster.interfaces.builder import (
@@ -76,10 +78,7 @@
from lp.services.job.model.job import Job
from lp.services.librarian.interfaces import ILibraryFileAliasSet
from lp.services.librarian.utils import copy_and_close
-from lp.services.propertycache import (
- cachedproperty,
- get_property_cache,
- )
+from lp.services.propertycache import cachedproperty
from lp.services.twistedsupport import cancel_on_timeout
from lp.services.twistedsupport.processmonitor import ProcessWithTimeout
from lp.services.webapp import urlappend
@@ -393,25 +392,57 @@
class BuilderInteractor(object):
- def __init__(self, builder, override_slave=None):
+ _cached_build_behavior = None
+ _cached_currentjob = None
+
+ _cached_slave = None
+ _cached_slave_attrs = None
+
+ # Tests can override current_build_behavior and slave.
+ _override_behavior = None
+ _override_slave = None
+
+ def __init__(self, builder, override_slave=None, override_behavior=None):
self.builder = builder
- self._slave = override_slave
+ self._override_slave = override_slave
+ self._override_behavior = override_behavior
- @cachedproperty
+ @property
def slave(self):
"""See IBuilder."""
- if self._slave is not None:
- return self._slave
- if self.builder.virtualized:
- timeout = config.builddmaster.virtualized_socket_timeout
- else:
- timeout = config.builddmaster.socket_timeout
- return BuilderSlave.makeBuilderSlave(
- self.builder.url, self.builder.vm_host, timeout)
+ if self._override_slave is not None:
+ return self._override_slave
+ # The slave cache is invalidated when the builder's URL, VM host
+ # or virtualisation change.
+ new_slave_attrs = (
+ self.builder.url, self.builder.vm_host, self.builder.virtualized)
+ if self._cached_slave_attrs != new_slave_attrs:
+ if self.builder.virtualized:
+ timeout = config.builddmaster.virtualized_socket_timeout
+ else:
+ timeout = config.builddmaster.socket_timeout
+ self._cached_slave = BuilderSlave.makeBuilderSlave(
+ self.builder.url, self.builder.vm_host, timeout)
+ self._cached_slave_attrs = new_slave_attrs
+ return self._cached_slave
@property
def current_build_behavior(self):
- return removeSecurityProxy(self.builder.current_build_behavior)
+ """Return the current build behavior."""
+ if self._override_behavior is not None:
+ return self._override_behavior
+ # The current_build_behavior cache is invalidated when
+ # builder.currentjob changes.
+ currentjob = self.builder.currentjob
+ if currentjob is None:
+ if not isinstance(
+ 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.setBuilderInteractor(self)
+ self._cached_currentjob = currentjob
+ return self._cached_build_behavior
def slaveStatus(self):
"""Get the slave status for this builder.
@@ -553,7 +584,7 @@
return d.addCallback(got_resume_ok).addErrback(got_resume_bad)
- def startBuild(self, build_queue_item, logger):
+ def _startBuild(self, build_queue_item, logger):
"""Start a build on this builder.
:param build_queue_item: A BuildQueueItem to build.
@@ -563,8 +594,12 @@
value is None, or a Failure that contains an exception
explaining what went wrong.
"""
- removeSecurityProxy(self.builder).current_build_behavior = (
- build_queue_item.required_build_behavior)
+ needed_bfjb = type(removeSecurityProxy(
+ build_queue_item.required_build_behavior))
+ 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)
# Make sure the request is valid; an exception is raised if it's not.
@@ -615,7 +650,7 @@
logger = self._getSlaveScannerLogger()
# Using maybeDeferred ensures that any exceptions are also
# wrapped up and caught later.
- d = defer.maybeDeferred(self.startBuild, candidate, logger)
+ d = defer.maybeDeferred(self._startBuild, candidate, logger)
return d
def resetOrFail(self, logger, exception):
@@ -771,51 +806,6 @@
# give up and mark it builderok=False.
FAILURE_THRESHOLD = 5
- def __storm_invalidated__(self):
- """Clear cached properties."""
- super(Builder, self).__storm_invalidated__()
- self._current_build_behavior = None
-
- def _getCurrentBuildBehavior(self):
- """Return the current build behavior."""
- self._clean_currentjob_cache()
- if not safe_hasattr(self, '_current_build_behavior'):
- self._current_build_behavior = None
-
- if (self._current_build_behavior is None or
- isinstance(self._current_build_behavior, IdleBuildBehavior)):
- # If we don't currently have a current build behavior set,
- # or we are currently idle, then...
- currentjob = self.currentjob
- if currentjob is not None:
- # ...we'll set it based on our current job.
- self._current_build_behavior = (
- currentjob.required_build_behavior)
- self._current_build_behavior.setBuilderInteractor(
- BuilderInteractor(self))
- return self._current_build_behavior
- elif self._current_build_behavior is None:
- # If we don't have a current job or an idle behavior
- # already set, then we just set the idle behavior
- # before returning.
- self._current_build_behavior = IdleBuildBehavior()
- return self._current_build_behavior
-
- else:
- # We did have a current non-idle build behavior set, so
- # we just return it.
- return self._current_build_behavior
-
- def _setCurrentBuildBehavior(self, new_behavior):
- """Set the current build behavior."""
- self._current_build_behavior = new_behavior
- if self._current_build_behavior is not None:
- self._current_build_behavior.setBuilderInteractor(
- BuilderInteractor(self))
-
- current_build_behavior = property(
- _getCurrentBuildBehavior, _setCurrentBuildBehavior)
-
def _getBuilderok(self):
return self._builderok
@@ -829,21 +819,16 @@
def gotFailure(self):
"""See `IBuilder`."""
self.failure_count += 1
- self._clean_currentjob_cache()
def resetFailureCount(self):
"""See `IBuilder`."""
self.failure_count = 0
- self._clean_currentjob_cache()
@cachedproperty
def currentjob(self):
"""See IBuilder"""
return getUtility(IBuildQueueSet).getByBuilder(self)
- def _clean_currentjob_cache(self):
- del get_property_cache(self).currentjob
-
def failBuilder(self, reason):
"""See IBuilder"""
# XXX cprov 2007-04-17: ideally we should be able to notify the
=== modified file 'lib/lp/buildmaster/model/buildqueue.py'
--- lib/lp/buildmaster/model/buildqueue.py 2013-06-20 05:50:00 +0000
+++ lib/lp/buildmaster/model/buildqueue.py 2013-08-27 07:55:38 +0000
@@ -182,9 +182,12 @@
"""Remove this record and associated job/specific_job."""
job = self.job
specific_job = self.specific_job
+ builder = self.builder
SQLBase.destroySelf(self)
specific_job.cleanUp()
job.destroySelf()
+ if builder is not None:
+ del get_property_cache(builder).currentjob
self._clear_specific_job_cache()
def manualScore(self, value):
@@ -219,9 +222,12 @@
if self.job.status != JobStatus.RUNNING:
self.job.start()
self.specific_job.jobStarted()
+ if builder is not None:
+ del get_property_cache(builder).currentjob
def reset(self):
"""See `IBuildQueue`."""
+ builder = self.builder
self.builder = None
if self.job.status != JobStatus.WAITING:
self.job.queue()
@@ -229,6 +235,8 @@
self.job.date_finished = None
self.logtail = None
self.specific_job.jobReset()
+ if builder is not None:
+ del get_property_cache(builder).currentjob
def cancel(self):
"""See `IBuildQueue`."""
=== modified file 'lib/lp/buildmaster/tests/mock_slaves.py'
--- lib/lp/buildmaster/tests/mock_slaves.py 2013-08-21 07:41:34 +0000
+++ lib/lp/buildmaster/tests/mock_slaves.py 2013-08-27 07:55:38 +0000
@@ -37,7 +37,6 @@
CorruptBuildCookie,
)
from lp.buildmaster.model.builder import BuilderSlave
-from lp.buildmaster.model.buildfarmjobbehavior import IdleBuildBehavior
from lp.services.config import config
from lp.testing.sampledata import I386_ARCHITECTURE_NAME
@@ -52,9 +51,8 @@
class MockBuilder:
"""Emulates a IBuilder class."""
- def __init__(self, name='mock-builder', behavior=None, builderok=True,
- manual=False, virtualized=True, vm_host=None):
- self.current_build_behavior = behavior or IdleBuildBehavior()
+ def __init__(self, name='mock-builder', builderok=True, manual=False,
+ virtualized=True, vm_host=None):
self.currentjob = None
self.builderok = builderok
self.manual = manual
=== modified file 'lib/lp/buildmaster/tests/test_builder.py'
--- lib/lp/buildmaster/tests/test_builder.py 2013-08-21 07:41:34 +0000
+++ lib/lp/buildmaster/tests/test_builder.py 2013-08-27 07:55:38 +0000
@@ -229,24 +229,23 @@
builder, build = self._setupBinaryBuildAndBuilder()
candidate = build.queueBuild()
building_slave = BuildingSlave()
- self.patch(
- BuilderSlave, 'makeBuilderSlave', FakeMethod(building_slave))
+ interactor = BuilderInteractor(builder, building_slave)
candidate.markAsBuilding(builder)
# At this point we should see a valid behaviour on the builder:
self.assertFalse(
zope_isinstance(
- builder.current_build_behavior, IdleBuildBehavior))
+ interactor.current_build_behavior, IdleBuildBehavior))
# Now reset the job and try to rescue the builder.
candidate.destroySelf()
self.layer.txn.commit()
builder = getUtility(IBuilderSet)[builder.name]
- d = BuilderInteractor(builder).rescueIfLost()
+ d = interactor.rescueIfLost()
def check_builder(ignored):
self.assertIsInstance(
- removeSecurityProxy(builder.current_build_behavior),
+ removeSecurityProxy(interactor.current_build_behavior),
IdleBuildBehavior)
return d.addCallback(check_builder)
@@ -260,9 +259,8 @@
# A slave that's 'lost' should be aborted; when the slave is
# broken then abort() should also throw a fault.
slave = LostBuildingBrokenSlave()
- lostbuilding_builder = MockBuilder(behavior=CorruptBehavior())
- d = BuilderInteractor(lostbuilding_builder, slave).updateStatus(
- BufferLogger())
+ interactor = BuilderInteractor(MockBuilder(), slave, CorruptBehavior())
+ d = interactor.updateStatus(BufferLogger())
def check_slave_status(failure):
self.assertIn('abort', slave.call_log)
@@ -360,8 +358,8 @@
def test_recover_ok_slave(self):
# An idle slave is not rescued.
slave = OkSlave()
- builder = MockBuilder(behavior=TrivialBehavior())
- d = BuilderInteractor(builder, slave).rescueIfLost()
+ d = BuilderInteractor(
+ MockBuilder(), slave, TrivialBehavior()).rescueIfLost()
def check_slave_calls(ignored):
self.assertNotIn('abort', slave.call_log)
@@ -373,8 +371,8 @@
# rescueIfLost does not attempt to abort or clean a builder that is
# WAITING.
waiting_slave = WaitingSlave()
- builder = MockBuilder(behavior=TrivialBehavior())
- d = BuilderInteractor(builder, waiting_slave).rescueIfLost()
+ d = BuilderInteractor(
+ MockBuilder(), waiting_slave, TrivialBehavior()).rescueIfLost()
def check_slave_calls(ignored):
self.assertNotIn('abort', waiting_slave.call_log)
@@ -389,8 +387,8 @@
# builder is reset for a new build, and the corrupt build is
# discarded.
waiting_slave = WaitingSlave()
- builder = MockBuilder(behavior=CorruptBehavior())
- d = BuilderInteractor(builder, waiting_slave).rescueIfLost()
+ d = BuilderInteractor(
+ MockBuilder(), waiting_slave, CorruptBehavior()).rescueIfLost()
def check_slave_calls(ignored):
self.assertNotIn('abort', waiting_slave.call_log)
@@ -402,8 +400,8 @@
# rescueIfLost does not attempt to abort or clean a builder that is
# BUILDING.
building_slave = BuildingSlave()
- builder = MockBuilder(behavior=TrivialBehavior())
- d = BuilderInteractor(builder, building_slave).rescueIfLost()
+ d = BuilderInteractor(
+ MockBuilder(), building_slave, TrivialBehavior()).rescueIfLost()
def check_slave_calls(ignored):
self.assertNotIn('abort', building_slave.call_log)
@@ -415,8 +413,8 @@
# If a slave is BUILDING with a build id we don't recognize, then we
# abort the build, thus stopping it in its tracks.
building_slave = BuildingSlave()
- builder = MockBuilder(behavior=CorruptBehavior())
- d = BuilderInteractor(builder, building_slave).rescueIfLost()
+ d = BuilderInteractor(
+ MockBuilder(), building_slave, CorruptBehavior()).rescueIfLost()
def check_slave_calls(ignored):
self.assertIn('abort', building_slave.call_log)
@@ -821,7 +819,7 @@
class TestCurrentBuildBehavior(TestCaseWithFactory):
- """This test ensures the get/set behavior of IBuilder's
+ """This test ensures the get/set behavior of BuilderInteractor's
current_build_behavior property.
"""
@@ -831,6 +829,7 @@
"""Create a new builder ready for testing."""
super(TestCurrentBuildBehavior, self).setUp()
self.builder = self.factory.makeBuilder(name='builder')
+ self.interactor = BuilderInteractor(self.builder)
# Have a publisher and a ppa handy for some of the tests below.
self.publisher = make_publisher()
@@ -848,25 +847,17 @@
nor a current build.
"""
self.assertIsInstance(
- self.builder.current_build_behavior, IdleBuildBehavior)
-
- def test_set_behavior_sets_builder(self):
- """Setting a builder's behavior also associates the behavior with the
- builder."""
- behavior = IBuildFarmJobBehavior(self.buildfarmjob)
- self.builder.current_build_behavior = behavior
-
- self.assertEqual(behavior, self.builder.current_build_behavior)
- self.assertEqual(behavior._builder, self.builder)
+ 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
-
- self.assertIsInstance(
- self.builder.current_build_behavior, BinaryPackageBuildBehavior)
+ behavior = removeSecurityProxy(self.interactor.current_build_behavior)
+ self.assertIsInstance(behavior, BinaryPackageBuildBehavior)
+ self.assertEqual(behavior._builder, self.builder)
+ self.assertEqual(behavior._interactor, self.interactor)
class TestSlave(TestCase):
=== modified file 'lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py'
--- lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 2013-07-29 17:31:27 +0000
+++ lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 2013-08-27 07:55:38 +0000
@@ -16,7 +16,7 @@
from lp.archiveuploader.uploadprocessor import parse_build_upload_leaf_name
from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.interfaces.builder import CorruptBuildCookie
-from lp.buildmaster.model.builder import BuilderSlave
+from lp.buildmaster.model.builder import BuilderInteractor
from lp.buildmaster.model.buildfarmjobbehavior import BuildFarmJobBehaviorBase
from lp.buildmaster.tests.mock_slaves import WaitingSlave
from lp.registry.interfaces.pocket import PackagePublishingPocket
@@ -217,11 +217,11 @@
self.builder = self.factory.makeBuilder()
self.build.buildqueue_record.builder = self.builder
self.build.buildqueue_record.setDateStarted(UTC_NOW)
- self.behavior = removeSecurityProxy(
- self.builder.current_build_behavior)
self.slave = WaitingSlave('BuildStatus.OK')
self.slave.valid_file_hashes.append('test_file_hash')
- self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(self.slave))
+ self.interactor = BuilderInteractor(self.builder, self.slave)
+ self.behavior = removeSecurityProxy(
+ 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-19 23:23:19 +0000
+++ lib/lp/code/model/tests/test_recipebuilder.py 2013-08-27 07:55:38 +0000
@@ -375,7 +375,8 @@
queue_record.builder = self.factory.makeBuilder()
slave = WaitingSlave('BuildStatus.OK')
self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(slave))
- return removeSecurityProxy(queue_record.builder.current_build_behavior)
+ interactor = BuilderInteractor(queue_record.builder)
+ return removeSecurityProxy(interactor.current_build_behavior)
def assertDeferredNotifyCount(self, status, behavior, expected_count):
d = behavior.handleStatus(status, None, {'filemap': {}})
=== modified file 'lib/lp/soyuz/browser/tests/builder-views.txt'
--- lib/lp/soyuz/browser/tests/builder-views.txt 2013-01-22 02:06:59 +0000
+++ lib/lp/soyuz/browser/tests/builder-views.txt 2013-08-27 07:55:38 +0000
@@ -220,7 +220,6 @@
>>> login("foo.bar@xxxxxxxxxxxxx")
>>> private_job = store.get(BuildQueue, private_job_id)
>>> private_job.builder = None
- >>> frog.current_build_behavior = None
>>> login('no-priv@xxxxxxxxxxxxx')
>>> nopriv_view = getMultiAdapter((frog, empty_request), name="+index")
=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py'
--- lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py 2013-08-22 04:07:24 +0000
+++ lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py 2013-08-27 07:55:38 +0000
@@ -13,7 +13,6 @@
from storm.store import Store
from testtools.deferredruntest import AsynchronousDeferredRunTest
import transaction
-from twisted.internet import defer
from twisted.trial.unittest import TestCase as TrialTestCase
from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
@@ -48,6 +47,9 @@
get_sources_list_for_building,
)
from lp.soyuz.enums import ArchivePurpose
+from lp.soyuz.model.binarypackagebuildbehavior import (
+ BinaryPackageBuildBehavior,
+ )
from lp.testing import TestCaseWithFactory
from lp.testing.dbuser import switch_dbuser
from lp.testing.fakemethod import FakeMethod
@@ -71,16 +73,16 @@
super(TestBinaryBuildPackageBehavior, self).setUp()
switch_dbuser('testadmin')
- def assertExpectedInteraction(self, ignored, call_log, builder, build,
+ def assertExpectedInteraction(self, ignored, call_log, interactor, build,
chroot, archive, archive_purpose,
component=None, extra_urls=None,
filemap_names=None):
expected = self.makeExpectedInteraction(
- builder, build, chroot, archive, archive_purpose, component,
+ interactor, build, chroot, archive, archive_purpose, component,
extra_urls, filemap_names)
self.assertEqual(call_log, expected)
- def makeExpectedInteraction(self, builder, build, chroot, archive,
+ def makeExpectedInteraction(self, interactor, build, chroot, archive,
archive_purpose, component=None,
extra_urls=None, filemap_names=None):
"""Build the log of calls that we expect to be made to the slave.
@@ -96,7 +98,8 @@
in order to trick the slave into building correctly.
:return: A list of the calls we expect to be made.
"""
- job = removeSecurityProxy(builder.current_build_behavior).buildfarmjob
+ job = removeSecurityProxy(
+ interactor.current_build_behavior).buildfarmjob
build_id = job.generateSlaveBuildCookie()
ds_name = build.distro_arch_series.distroseries.name
suite = ds_name + pocketsuffix[build.pocket]
@@ -128,18 +131,12 @@
build_log = [
('build', build_id, 'binarypackage', chroot.content.sha1,
filemap_names, extra_args)]
- if builder.virtualized:
+ if interactor.builder.virtualized:
result = [('echo', 'ping')] + upload_logs + build_log
else:
result = upload_logs + build_log
return result
- def startBuild(self, builder, candidate):
- builder = removeSecurityProxy(builder)
- candidate = removeSecurityProxy(candidate)
- return defer.maybeDeferred(
- BuilderInteractor(builder).startBuild, candidate, BufferLogger())
-
def test_non_virtual_ppa_dispatch(self):
# When the BinaryPackageBuildBehavior dispatches PPA builds to
# non-virtual builders, it stores the chroot on the server and
@@ -149,17 +146,18 @@
archive = self.factory.makeArchive(virtualized=False)
slave = OkSlave()
builder = self.factory.makeBuilder(virtualized=False)
- self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(slave))
build = self.factory.makeBinaryPackageBuild(
builder=builder, archive=archive)
lf = self.factory.makeLibraryFileAlias()
transaction.commit()
build.distro_arch_series.addOrUpdateChroot(lf)
- candidate = build.queueBuild()
- d = self.startBuild(builder, candidate)
+ bq = build.queueBuild()
+ bq.markAsBuilding(builder)
+ interactor = BuilderInteractor(builder, slave)
+ d = interactor._startBuild(bq, BufferLogger())
d.addCallback(
- self.assertExpectedInteraction, slave.call_log,
- builder, build, lf, archive, ArchivePurpose.PRIMARY, 'universe')
+ self.assertExpectedInteraction, slave.call_log, interactor, build,
+ lf, archive, ArchivePurpose.PRIMARY, 'universe')
return d
def test_virtual_ppa_dispatch(self):
@@ -169,14 +167,15 @@
slave = OkSlave()
builder = self.factory.makeBuilder(
virtualized=True, vm_host="foohost")
- self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(slave))
build = self.factory.makeBinaryPackageBuild(
builder=builder, archive=archive)
lf = self.factory.makeLibraryFileAlias()
transaction.commit()
build.distro_arch_series.addOrUpdateChroot(lf)
- candidate = build.queueBuild()
- d = self.startBuild(builder, candidate)
+ bq = build.queueBuild()
+ bq.markAsBuilding(builder)
+ interactor = BuilderInteractor(builder, slave)
+ d = interactor._startBuild(bq, BufferLogger())
def check_build(ignored):
# We expect the first call to the slave to be a resume call,
@@ -184,8 +183,8 @@
expected_resume_call = slave.call_log.pop(0)
self.assertEqual('resume', expected_resume_call)
self.assertExpectedInteraction(
- ignored, slave.call_log,
- builder, build, lf, archive, ArchivePurpose.PPA)
+ ignored, slave.call_log, interactor, build, lf, archive,
+ ArchivePurpose.PPA)
return d.addCallback(check_build)
def test_partner_dispatch_no_publishing_history(self):
@@ -193,17 +192,18 @@
virtualized=False, purpose=ArchivePurpose.PARTNER)
slave = OkSlave()
builder = self.factory.makeBuilder(virtualized=False)
- self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(slave))
build = self.factory.makeBinaryPackageBuild(
builder=builder, archive=archive)
lf = self.factory.makeLibraryFileAlias()
transaction.commit()
build.distro_arch_series.addOrUpdateChroot(lf)
- candidate = build.queueBuild()
- d = self.startBuild(builder, candidate)
+ bq = build.queueBuild()
+ bq.markAsBuilding(builder)
+ interactor = BuilderInteractor(builder, slave)
+ d = interactor._startBuild(bq, BufferLogger())
d.addCallback(
- self.assertExpectedInteraction, slave.call_log,
- builder, build, lf, archive, ArchivePurpose.PARTNER)
+ self.assertExpectedInteraction, slave.call_log, interactor, build,
+ lf, archive, ArchivePurpose.PARTNER)
return d
def test_dont_dispatch_release_builds(self):
Follow ups