← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/dispatchBuildToSlave-common into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/dispatchBuildToSlave-common into lp:launchpad.

Commit message:
Pull a common dispatchBuildToSlave up into the base BuildFarmJobBehaviour.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/dispatchBuildToSlave-common/+merge/224389

This branch pulls the common complexity of IBuildFarmJobBehaviour.dispatchBuildToSlave up into the base class. Concrete derivatives just implement a much simpler, and Twisted-free, composeBuildRequest method.

I also rewrote the source file URL determination bits of BinaryPackageBuildBehaviour to make a bit more sense, and added what seems to be the only test for P3A build dispatching.

Logging and tests are still trainwrecks, but this branch is big enough.
-- 
https://code.launchpad.net/~wgrant/launchpad/dispatchBuildToSlave-common/+merge/224389
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/dispatchBuildToSlave-common into lp:launchpad.
=== modified file 'lib/lp/buildmaster/interactor.py'
--- lib/lp/buildmaster/interactor.py	2014-06-24 09:28:25 +0000
+++ lib/lp/buildmaster/interactor.py	2014-06-25 07:15:42 +0000
@@ -181,27 +181,17 @@
         p.spawnProcess(resume_argv[0], tuple(resume_argv))
         return d
 
-    def cacheFile(self, logger, libraryfilealias):
-        """Make sure that the file at 'libraryfilealias' is on the slave.
-
-        :param logger: A python `Logger` object.
-        :param libraryfilealias: An `ILibraryFileAlias`.
-        """
-        url = libraryfilealias.http_url
-        logger.info(
-            "Asking builder on %s to ensure it has file %s (%s, %s)" % (
-                self._file_cache_url, libraryfilealias.filename, url,
-                libraryfilealias.content.sha1))
-        return self.sendFileToSlave(libraryfilealias.content.sha1, url)
-
-    def sendFileToSlave(self, sha1, url, username="", password=""):
+    @defer.inlineCallbacks
+    def sendFileToSlave(self, sha1, url, username="", password="",
+                        logger=None):
         """Helper to send the file at 'url' with 'sha1' to this builder."""
-        d = self.ensurepresent(sha1, url, username, password)
-
-        def check_present((present, info)):
-            if not present:
-                raise CannotFetchFile(url, info)
-        return d.addCallback(check_present)
+        if logger is not None:
+            logger.info(
+                "Asking %s to ensure it has %s (%s%s)" % (
+                    self.url, sha1, url, ' with auth' if username else ''))
+        present, info = yield self.ensurepresent(sha1, url, username, password)
+        if not present:
+            raise CannotFetchFile(url, info)
 
     def build(self, buildid, builder_type, chroot_sha1, filemap, args):
         """Build a thing on this build slave.

=== modified file 'lib/lp/buildmaster/interfaces/buildfarmjobbehaviour.py'
--- lib/lp/buildmaster/interfaces/buildfarmjobbehaviour.py	2014-05-08 23:52:43 +0000
+++ lib/lp/buildmaster/interfaces/buildfarmjobbehaviour.py	2014-06-25 07:15:42 +0000
@@ -25,6 +25,15 @@
         :param logger: A logger to be used to log diagnostic information.
         """
 
+    def composeBuildRequest(logger):
+        """Compose parameters for a slave build request.
+
+        :param logger: A logger to be used to log diagnostic information.
+        :return: A tuple of (
+            "builder type", `DistroArchSeries` to build against,
+            {filename: `sendFileToSlave` arguments}, {extra build arguments})
+        """
+
     def dispatchBuildToSlave(build_queue_item_id, logger):
         """Dispatch a specific build to the slave.
 

=== modified file 'lib/lp/buildmaster/model/buildfarmjobbehaviour.py'
--- lib/lp/buildmaster/model/buildfarmjobbehaviour.py	2014-06-20 10:19:30 +0000
+++ lib/lp/buildmaster/model/buildfarmjobbehaviour.py	2014-06-25 07:15:42 +0000
@@ -23,6 +23,7 @@
     BuildFarmJobType,
     BuildStatus,
     )
+from lp.buildmaster.interfaces.builder import CannotBuild
 from lp.services.config import config
 from lp.services.helpers import filenameToContentType
 from lp.services.librarian.interfaces import ILibraryFileAliasSet
@@ -56,6 +57,53 @@
         """See `IPackageBuild`."""
         return '%s-%s' % (self.build.job_type.name, self.build.id)
 
+    @defer.inlineCallbacks
+    def dispatchBuildToSlave(self, build_queue_id, logger):
+        """See `IBuildFarmJobBehaviour`."""
+        builder_type, das, files, args = self.composeBuildRequest(logger)
+
+        # First cache the chroot and any other files that the job needs.
+        chroot = das.getChroot()
+        if chroot is None:
+            raise CannotBuild(
+                "Unable to find a chroot for %s" % das.displayname)
+        filename_to_sha1 = {}
+        dl = []
+        dl.append(self._slave.sendFileToSlave(
+            logger=logger, url=chroot.http_url, sha1=chroot.content.sha1))
+        for filename, params in files.items():
+            filename_to_sha1[filename] = params['sha1']
+            dl.append(self._slave.sendFileToSlave(logger=logger, **params))
+        yield defer.gatherResults(dl)
+
+        # Generate a string which can be used to cross-check when
+        # obtaining results so we know we are referring to the right
+        # database object in subsequent runs.
+        buildid = "%s-%s" % (self.build.id, build_queue_id)
+        cookie = self.getBuildCookie()
+        chroot_sha1 = chroot.content.sha1
+        logger.debug(
+            "Initiating build %s on %s" % (buildid, self._builder.url))
+
+        (status, info) = yield self._slave.build(
+            cookie, builder_type, chroot_sha1, filename_to_sha1, args)
+
+        message = """%s (%s):
+        ***** RESULT *****
+        %s
+        %s
+        %s: %s
+        ******************
+        """ % (
+            self._builder.name,
+            self._builder.url,
+            filename_to_sha1,
+            args,
+            status,
+            info,
+            )
+        logger.info(message)
+
     def getUploadDirLeaf(self, build_cookie, now=None):
         """See `IPackageBuild`."""
         if now is None:

=== modified file 'lib/lp/buildmaster/tests/mock_slaves.py'
--- lib/lp/buildmaster/tests/mock_slaves.py	2014-06-20 10:45:08 +0000
+++ lib/lp/buildmaster/tests/mock_slaves.py	2014-06-25 07:15:42 +0000
@@ -127,7 +127,8 @@
         self.call_log.append('resume')
         return defer.succeed(("", "", 0))
 
-    def sendFileToSlave(self, sha1, url, username="", password=""):
+    def sendFileToSlave(self, sha1, url, username="", password="",
+                        logger=None):
         d = self.ensurepresent(sha1, url, username, password)
 
         def check_present((present, info)):
@@ -136,10 +137,6 @@
 
         return d.addCallback(check_present)
 
-    def cacheFile(self, logger, libraryfilealias):
-        return self.sendFileToSlave(
-            libraryfilealias.content.sha1, libraryfilealias.http_url)
-
     def getFiles(self, files):
         dl = defer.gatherResults([
             self.getFile(builder_file, local_file)

=== modified file 'lib/lp/buildmaster/tests/test_interactor.py'
--- lib/lp/buildmaster/tests/test_interactor.py	2014-06-24 09:28:25 +0000
+++ lib/lp/buildmaster/tests/test_interactor.py	2014-06-25 07:15:42 +0000
@@ -55,7 +55,6 @@
     WaitingSlave,
     )
 from lp.services.config import config
-from lp.services.log.logger import DevNullLogger
 from lp.soyuz.model.binarypackagebuildbehaviour import (
     BinaryPackageBuildBehaviour,
     )

=== modified file 'lib/lp/code/model/recipebuilder.py'
--- lib/lp/code/model/recipebuilder.py	2014-04-25 11:33:29 +0000
+++ lib/lp/code/model/recipebuilder.py	2014-06-25 07:15:42 +0000
@@ -110,56 +110,16 @@
         args['distroseries_name'] = self.build.distroseries.name
         return args
 
-    def dispatchBuildToSlave(self, build_queue_id, logger):
-        """See `IBuildFarmJobBehaviour`."""
-
-        distroseries = self.build.distroseries
-        # Start the binary package build on the slave builder. First
-        # we send the chroot.
-        distroarchseries = distroseries.getDistroArchSeriesByProcessor(
+    def composeBuildRequest(self, logger):
+        das = self.build.distroseries.getDistroArchSeriesByProcessor(
             self._builder.processor)
-        if distroarchseries is None:
-            raise CannotBuild("Unable to find distroarchseries for %s in %s" %
+        if das is None:
+            raise CannotBuild(
+                "Unable to find distroarchseries for %s in %s" %
                 (self._builder.processor.name,
-                self.build.distroseries.displayname))
-        args = self._extraBuildArgs(distroarchseries, logger)
-        chroot = distroarchseries.getChroot()
-        if chroot is None:
-            raise CannotBuild("Unable to find a chroot for %s" %
-                              distroarchseries.displayname)
-        logger.info(
-            "Sending chroot file for recipe build to %s" % self._builder.name)
-        d = self._slave.cacheFile(logger, chroot)
-
-        def got_cache_file(ignored):
-            # Generate a string which can be used to cross-check when
-            # obtaining results so we know we are referring to the right
-            # database object in subsequent runs.
-            buildid = "%s-%s" % (self.build.id, build_queue_id)
-            cookie = self.getBuildCookie()
-            chroot_sha1 = chroot.content.sha1
-            logger.info(
-                "Initiating build %s on %s" % (buildid, self._builder.url))
-
-            return self._slave.build(
-                cookie, "sourcepackagerecipe", chroot_sha1, {}, args)
-
-        def log_build_result((status, info)):
-            message = """%s (%s):
-            ***** RESULT *****
-            %s
-            %s: %s
-            ******************
-            """ % (
-                self._builder.name,
-                self._builder.url,
-                args,
-                status,
-                info,
-                )
-            logger.info(message)
-
-        return d.addCallback(got_cache_file).addCallback(log_build_result)
+                 self.build.distroseries.displayname))
+        return (
+            "sourcepackagerecipe", das, {}, self._extraBuildArgs(das, logger))
 
     def verifyBuildRequest(self, logger):
         """Assert some pre-build checks.

=== modified file 'lib/lp/code/model/tests/test_recipebuilder.py'
--- lib/lp/code/model/tests/test_recipebuilder.py	2014-05-08 23:52:43 +0000
+++ lib/lp/code/model/tests/test_recipebuilder.py	2014-06-25 07:15:42 +0000
@@ -306,8 +306,7 @@
             self.assertThat(
                 logger.getLogBuffer(),
                 StartsWith(dedent("""\
-                  INFO Sending chroot file for recipe build to bob-de-bouwer
-                  INFO Initiating build 1-someid on http://fake:0000
+                  DEBUG Initiating build 1-someid on http://fake:0000
                   """)))
             self.assertEquals(["ensurepresent", "build"],
                               [call[0] for call in slave.call_log])

=== modified file 'lib/lp/soyuz/model/binarypackagebuildbehaviour.py'
--- lib/lp/soyuz/model/binarypackagebuildbehaviour.py	2014-04-25 11:33:29 +0000
+++ lib/lp/soyuz/model/binarypackagebuildbehaviour.py	2014-06-25 07:15:42 +0000
@@ -9,7 +9,6 @@
     'BinaryPackageBuildBehaviour',
     ]
 
-from twisted.internet import defer
 from zope.interface import implements
 
 from lp.buildmaster.interfaces.builder import CannotBuild
@@ -26,6 +25,7 @@
     get_sources_list_for_building,
     )
 from lp.soyuz.enums import ArchivePurpose
+from lp.soyuz.model.publishing import makePoolPath
 
 
 class BinaryPackageBuildBehaviour(BuildFarmJobBehaviourBase):
@@ -62,69 +62,36 @@
             distroname, distroseriesname, archname, sourcename, version,
             state))
 
-    def _buildFilemapStructure(self, ignored, logger):
+    def determineFilesToSend(self):
         # Build filemap structure with the files required in this build
         # and send them to the slave.
-        # If the build is private we tell the slave to get the files from the
-        # archive instead of the librarian because the slaves cannot
-        # access the restricted librarian.
-        dl = []
-        private = self.build.archive.private
-        if private:
-            dl.extend(self._cachePrivateSourceOnSlave(logger))
+        if self.build.archive.private:
+            # Builds in private archive may have restricted files that
+            # we can't obtain from the public librarian. Prepare a pool
+            # URL from which to fetch them.
+            pool_url = urlappend(
+                self.build.archive.archive_url,
+                makePoolPath(
+                    self.build.source_package_release.sourcepackagename.name,
+                    self.build.current_component.name))
         filemap = {}
         for source_file in self.build.source_package_release.files:
             lfa = source_file.libraryfile
-            filemap[lfa.filename] = lfa.content.sha1
-            if not private:
-                dl.append(
-                    self._slave.cacheFile(
-                        logger, source_file.libraryfile))
-        d = defer.gatherResults(dl)
-        return d.addCallback(lambda ignored: filemap)
-
-    def dispatchBuildToSlave(self, build_queue_id, logger):
-        """See `IBuildFarmJobBehaviour`."""
-
-        # Start the binary package build on the slave builder. First
-        # we send the chroot.
-        chroot = self.build.distro_arch_series.getChroot()
-        d = self._slave.cacheFile(logger, chroot)
-        d.addCallback(self._buildFilemapStructure, logger)
-
-        def got_filemap(filemap):
-            # Generate a string which can be used to cross-check when
-            # obtaining results so we know we are referring to the right
-            # database object in subsequent runs.
-            buildid = "%s-%s" % (self.build.id, build_queue_id)
-            cookie = self.getBuildCookie()
-            chroot_sha1 = chroot.content.sha1
-            logger.debug(
-                "Initiating build %s on %s" % (buildid, self._builder.url))
-
-            args = self._extraBuildArgs(self.build)
-            d = self._slave.build(
-                cookie, "binarypackage", chroot_sha1, filemap, args)
-
-            def got_build((status, info)):
-                message = """%s (%s):
-                ***** RESULT *****
-                %s
-                %s
-                %s: %s
-                ******************
-                """ % (
-                    self._builder.name,
-                    self._builder.url,
-                    filemap,
-                    args,
-                    status,
-                    info,
-                    )
-                logger.info(message)
-            return d.addCallback(got_build)
-
-        return d.addCallback(got_filemap)
+            if not self.build.archive.private:
+                filemap[lfa.filename] = {
+                    'sha1': lfa.content.sha1, 'url': lfa.http_url}
+            else:
+                filemap[lfa.filename] = {
+                    'sha1': lfa.content.sha1,
+                    'url': urlappend(pool_url, lfa.filename),
+                    'username': 'buildd',
+                    'password': self.build.archive.buildd_secret}
+        return filemap
+
+    def composeBuildRequest(self, logger):
+        return (
+            "binarypackage", self.build.distro_arch_series,
+            self.determineFilesToSend(), self._extraBuildArgs(self.build))
 
     def verifyBuildRequest(self, logger):
         """Assert some pre-build checks.
@@ -170,39 +137,6 @@
                     (build.title, build.id, build.pocket.name,
                      build.distro_series.name))
 
-    def _cachePrivateSourceOnSlave(self, logger):
-        """Ask the slave to download source files for a private build.
-
-        :param logger: A logger used for providing debug information.
-        :return: A list of Deferreds, each of which represents a request
-            to cache a file.
-        """
-        # The URL to the file in the archive consists of these parts:
-        # archive_url / makePoolPath() / filename
-        # Once this is constructed we add the http basic auth info.
-
-        # Avoid circular imports.
-        from lp.soyuz.model.publishing import makePoolPath
-
-        archive = self.build.archive
-        archive_url = archive.archive_url
-        component_name = self.build.current_component.name
-        dl = []
-        for source_file in self.build.source_package_release.files:
-            file_name = source_file.libraryfile.filename
-            sha1 = source_file.libraryfile.content.sha1
-            spn = self.build.source_package_release.sourcepackagename
-            poolpath = makePoolPath(spn.name, component_name)
-            url = urlappend(archive_url, poolpath)
-            url = urlappend(url, file_name)
-            logger.debug("Asking builder on %s to ensure it has file %s "
-                         "(%s, %s)" % (
-                            self._builder.url, file_name, url, sha1))
-            dl.append(
-                self._slave.sendFileToSlave(
-                    sha1, url, "buildd", archive.buildd_secret))
-        return dl
-
     def _extraBuildArgs(self, build):
         """
         Return the extra arguments required by the slave for the given build.

=== modified file 'lib/lp/soyuz/model/livefsbuildbehaviour.py'
--- lib/lp/soyuz/model/livefsbuildbehaviour.py	2014-06-24 13:26:13 +0000
+++ lib/lp/soyuz/model/livefsbuildbehaviour.py	2014-06-25 07:15:42 +0000
@@ -11,7 +11,6 @@
     'LiveFSBuildBehaviour',
     ]
 
-from twisted.internet import defer
 from zope.component import adapts
 from zope.interface import implements
 from zope.security.proxy import removeSecurityProxy
@@ -38,9 +37,6 @@
     adapts(ILiveFSBuild)
     implements(IBuildFarmJobBehaviour)
 
-    # Identify the type of job to the slave.
-    build_type = 'livefs'
-
     @property
     def displayname(self):
         ret = self.build.title
@@ -109,46 +105,10 @@
         args["archive_private"] = build.archive.private
         return args
 
-    @defer.inlineCallbacks
-    def dispatchBuildToSlave(self, build_queue_id, logger):
-        """See `IBuildFarmJobBehaviour`."""
-
-        # Start the build on the slave builder.  First we send the chroot.
-        distro_arch_series = self.build.distro_arch_series
-        chroot = distro_arch_series.getChroot()
-        if chroot is None:
-            raise CannotBuild(
-                "Unable to find a chroot for %s" %
-                distro_arch_series.displayname)
-        logger.info(
-            "Sending chroot file for live filesystem build to %s" %
-            self._builder.name)
-        yield self._slave.cacheFile(logger, chroot)
-
-        # Generate a string which can be used to cross-check when obtaining
-        # results so we know we are referring to the right database object
-        # in subsequent runs.
-        buildid = "%s-%s" % (self.build.id, build_queue_id)
-        logger.info("Initiating build %s on %s" % (buildid, self._builder.url))
-
-        cookie = self.getBuildCookie()
-        args = self._extraBuildArgs()
-        status, info = yield self._slave.build(
-            cookie, "livefs", chroot.content.sha1, {}, args)
-
-        message = """%s (%s):
-        ***** RESULT *****
-        %s
-        %s: %s
-        ******************
-        """ % (
-            self._builder.name,
-            self._builder.url,
-            args,
-            status,
-            info,
-            )
-        logger.info(message)
+    def composeBuildRequest(self, logger):
+        return (
+            "livefs", self.build.distro_arch_series, {},
+            self._extraBuildArgs())
 
     def verifySuccessfulBuild(self):
         """See `IBuildFarmJobBehaviour`."""

=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py'
--- lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py	2014-06-19 11:00:57 +0000
+++ lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py	2014-06-25 07:15:42 +0000
@@ -18,6 +18,7 @@
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
+from lp.archivepublisher.diskpool import poolify
 from lp.buildmaster.enums import (
     BuilderCleanStatus,
     BuildQueueStatus,
@@ -48,6 +49,7 @@
     pocketsuffix,
     )
 from lp.registry.interfaces.series import SeriesStatus
+from lp.registry.interfaces.sourcepackage import SourcePackageFileType
 from lp.services.config import config
 from lp.services.librarian.interfaces import ILibraryFileAliasSet
 from lp.services.log.logger import BufferLogger
@@ -79,16 +81,16 @@
 
     def assertExpectedInteraction(self, ignored, call_log, builder, build,
                                   chroot, archive, archive_purpose,
-                                  component=None, extra_urls=None,
+                                  component=None, extra_uploads=None,
                                   filemap_names=None):
         expected = self.makeExpectedInteraction(
             builder, build, chroot, archive, archive_purpose, component,
-            extra_urls, filemap_names)
+            extra_uploads, filemap_names)
         self.assertEqual(call_log, expected)
 
     def makeExpectedInteraction(self, builder, build, chroot, archive,
                                 archive_purpose, component=None,
-                                extra_urls=None, filemap_names=None):
+                                extra_uploads=None, filemap_names=None):
         """Build the log of calls that we expect to be made to the slave.
 
         :param builder: The builder we are using to build the binary package.
@@ -113,12 +115,12 @@
             component = build.current_component.name
         if filemap_names is None:
             filemap_names = []
-        if extra_urls is None:
-            extra_urls = []
+        if extra_uploads is None:
+            extra_uploads = []
 
         upload_logs = [
-            ('ensurepresent', url, '', '')
-            for url in [chroot.http_url] + extra_urls]
+            ('ensurepresent',) + upload
+            for upload in [(chroot.http_url, '', '')] + extra_uploads]
 
         extra_args = {
             'arch_indep': arch_indep,
@@ -186,6 +188,40 @@
             lf, archive, ArchivePurpose.PPA)
         return d
 
+    def test_private_source_dispatch(self):
+        archive = self.factory.makeArchive(private=True)
+        slave = OkSlave()
+        builder = self.factory.makeBuilder()
+        builder.setCleanStatus(BuilderCleanStatus.CLEAN)
+        vitals = extract_vitals_from_db(builder)
+        build = self.factory.makeBinaryPackageBuild(
+            builder=builder, archive=archive)
+        sprf = build.source_package_release.addFile(
+            self.factory.makeLibraryFileAlias(db_only=True),
+            filetype=SourcePackageFileType.ORIG_TARBALL)
+        sprf_url = (
+            'http://private-ppa.launchpad.dev/%s/%s/ubuntu/pool/%s/%s'
+            % (archive.owner.name, archive.name,
+               poolify(
+                   build.source_package_release.sourcepackagename.name,
+                   'main'),
+               sprf.libraryfile.filename))
+        lf = self.factory.makeLibraryFileAlias()
+        transaction.commit()
+        build.distro_arch_series.addOrUpdateChroot(lf)
+        bq = build.queueBuild()
+        bq.markAsBuilding(builder)
+        interactor = BuilderInteractor()
+        d = interactor._startBuild(
+            bq, vitals, builder, slave,
+            interactor.getBuildBehaviour(bq, builder, slave), BufferLogger())
+        d.addCallback(
+            self.assertExpectedInteraction, slave.call_log, builder, build,
+            lf, archive, ArchivePurpose.PPA,
+            extra_uploads=[(sprf_url, 'buildd', u'sekrit')],
+            filemap_names=[sprf.libraryfile.filename])
+        return d
+
     def test_partner_dispatch_no_publishing_history(self):
         archive = self.factory.makeArchive(
             virtualized=False, purpose=ArchivePurpose.PARTNER)

=== modified file 'lib/lp/soyuz/tests/test_livefsbuildbehaviour.py'
--- lib/lp/soyuz/tests/test_livefsbuildbehaviour.py	2014-06-24 13:26:13 +0000
+++ lib/lp/soyuz/tests/test_livefsbuildbehaviour.py	2014-06-25 07:15:42 +0000
@@ -244,8 +244,7 @@
         self.assertStartsWith(
             logger.getLogBuffer(),
             dedent("""\
-                INFO Sending chroot file for live filesystem build to bob
-                INFO Initiating build 1-someid on http://fake:0000
+                DEBUG Initiating build 1-someid on http://fake:0000
                 """))
         self.assertEqual(
             ["ensurepresent", "build"], [call[0] for call in slave.call_log])

=== modified file 'lib/lp/translations/model/translationtemplatesbuildbehaviour.py'
--- lib/lp/translations/model/translationtemplatesbuildbehaviour.py	2014-06-20 11:56:17 +0000
+++ lib/lp/translations/model/translationtemplatesbuildbehaviour.py	2014-06-25 07:15:42 +0000
@@ -23,7 +23,6 @@
 
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.buildmaster.enums import BuildStatus
-from lp.buildmaster.interfaces.builder import CannotBuild
 from lp.buildmaster.interfaces.buildfarmjobbehaviour import (
     IBuildFarmJobBehaviour,
     )
@@ -55,31 +54,12 @@
             self.unsafe_chars, '_', self.build.branch.unique_name)
         return "translationtemplates_%s_%d.txt" % (safe_name, self.build.id)
 
-    def dispatchBuildToSlave(self, build_queue_item, logger):
-        """See `IBuildFarmJobBehaviour`."""
-        chroot = self._getChroot()
-        if chroot is None:
-            distroarchseries = self._getDistroArchSeries()
-            raise CannotBuild("Unable to find a chroot for %s" %
-                              distroarchseries.displayname)
-        chroot_sha1 = chroot.content.sha1
-        d = self._slave.cacheFile(logger, chroot)
-
-        def got_cache_file(ignored):
-            args = {
-                'arch_tag': self._getDistroArchSeries().architecturetag,
-                'branch_url': self.build.branch.composePublicURL(),
-                }
-
-            filemap = {}
-
-            return self._slave.build(
-                self.getBuildCookie(), self.build_type, chroot_sha1, filemap,
-                args)
-        return d.addCallback(got_cache_file)
-
-    def _getChroot(self):
-        return self._getDistroArchSeries().getChroot()
+    def composeBuildRequest(self, logger):
+        args = {
+            'arch_tag': self._getDistroArchSeries().architecturetag,
+            'branch_url': self.build.branch.composePublicURL(),
+            }
+        return ("translation-templates", self._getDistroArchSeries(), {}, args)
 
     def _getDistroArchSeries(self):
         ubuntu = getUtility(ILaunchpadCelebrities).ubuntu

=== modified file 'lib/lp/translations/stories/buildfarm/xx-build-summary.txt'
--- lib/lp/translations/stories/buildfarm/xx-build-summary.txt	2013-11-15 05:57:56 +0000
+++ lib/lp/translations/stories/buildfarm/xx-build-summary.txt	2014-06-25 07:15:42 +0000
@@ -25,7 +25,7 @@
     >>> class FakeSlave:
     ...     resume = FakeMethod(result=('stdout', 'stderr', 0))
     ...     build = FakeMethod()
-    ...     cacheFile = FakeMethod()
+    ...     sendFileToSlave = FakeMethod()
 
     >>> login(ANONYMOUS)
     >>> owner_email = factory.getUniqueString() + '@example.com'

=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuildbehaviour.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildbehaviour.py	2014-06-20 11:56:17 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildbehaviour.py	2014-06-25 07:15:42 +0000
@@ -9,6 +9,7 @@
 
 import pytz
 from testtools.deferredruntest import AsynchronousDeferredRunTest
+from testtools.testcase import ExpectedException
 from twisted.internet import defer
 from zope.component import getUtility
 
@@ -67,9 +68,9 @@
         slave = WaitingSlave(**kwargs)
         behaviour.setBuilder(self.factory.makeBuilder(), slave)
         if use_fake_chroot:
-            lf = self.factory.makeLibraryFileAlias()
+            behaviour._getDistroArchSeries().addOrUpdateChroot(
+                self.factory.makeLibraryFileAlias(db_only=True))
             self.layer.txn.commit()
-            behaviour._getChroot = lambda: lf
         return behaviour
 
     def makeProductSeriesWithBranchForTranslation(self):
@@ -99,13 +100,13 @@
         b2 = self.makeBehaviour()
         self.assertNotEqual(b1.getLogFileName(), b2.getLogFileName())
 
+    @defer.inlineCallbacks
     def test_dispatchBuildToSlave_no_chroot_fails(self):
         # dispatchBuildToSlave will fail if the chroot does not exist.
         behaviour = self.makeBehaviour(use_fake_chroot=False)
         switch_dbuser(config.builddmaster.dbuser)
-        self.assertRaises(
-            CannotBuild, behaviour.dispatchBuildToSlave, None,
-            logging)
+        with ExpectedException(CannotBuild):
+            yield behaviour.dispatchBuildToSlave(None, logging)
 
     def test_dispatchBuildToSlave(self):
         # dispatchBuildToSlave ultimately causes the slave's build
@@ -115,7 +116,7 @@
         switch_dbuser(config.builddmaster.dbuser)
         d = behaviour.dispatchBuildToSlave(FakeBuildQueue(behaviour), logging)
 
-        def got_dispatch((status, info)):
+        def got_dispatch(ignored):
             # call_log lives on the mock WaitingSlave and tells us what
             # calls to the slave that the behaviour class made.
             call_log = behaviour._slave.call_log
@@ -130,23 +131,14 @@
                 behaviour.build.branch.composePublicURL())
         return d.addCallback(got_dispatch)
 
-    def test_getChroot(self):
-        # _getChroot produces the current chroot for the current Ubuntu
-        # release, on the nominated architecture for
-        # architecture-independent builds.
+    def test_getDistroArchSeries(self):
+        # _getDistroArchSeries produces the nominated arch-indep
+        # architecture for the current Ubuntu series.
         ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
-        current_ubuntu = ubuntu.currentseries
-        distroarchseries = current_ubuntu.nominatedarchindep
-
-        # Set an arbitrary chroot file.
-        fake_chroot_file = getUtility(ILibraryFileAliasSet)[1]
-        distroarchseries.addOrUpdateChroot(fake_chroot_file)
-
-        behaviour = self.makeBehaviour(use_fake_chroot=False)
-        chroot = behaviour._getChroot()
-
-        self.assertNotEqual(None, chroot)
-        self.assertEqual(fake_chroot_file, chroot)
+        behaviour = self.makeBehaviour()
+        self.assertEqual(
+            ubuntu.currentseries.nominatedarchindep,
+            behaviour._getDistroArchSeries())
 
     def test_readTarball(self):
         behaviour = self.makeBehaviour()
@@ -177,7 +169,7 @@
 
         d = behaviour.dispatchBuildToSlave(queue_item, logging)
 
-        def got_dispatch((status, info)):
+        def got_dispatch(ignored):
             self.assertEqual(0, queue_item.destroySelf.call_count)
             self.assertEqual(0, behaviour._uploadTarball.call_count)
 
@@ -210,7 +202,7 @@
         slave = behaviour._slave
         d = behaviour.dispatchBuildToSlave(queue_item, logging)
 
-        def got_dispatch((status, info)):
+        def got_dispatch(ignored):
             # Now that we've dispatched, get the status.
             return slave.status()
 
@@ -242,7 +234,7 @@
         slave = behaviour._slave
         d = behaviour.dispatchBuildToSlave(queue_item, logging)
 
-        def got_dispatch((status, info)):
+        def got_dispatch(ignored):
             return slave.status()
 
         def got_status(status):
@@ -279,7 +271,7 @@
             copy_and_close(tar_file, file)
             return defer.succeed(None)
 
-        def got_dispatch((status, info)):
+        def got_dispatch(ignored):
             slave.getFile = fake_getFile
             return slave.status()
 


Follow ups