← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/buildd-status-dict into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/buildd-status-dict into lp:launchpad.

Commit message:
Use the new status_dict method of build slaves rather than parsing information out of a tuple.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #680514 in Launchpad itself: "No way to discover version of launchpad-buildd installed on builders"
  https://bugs.launchpad.net/launchpad/+bug/680514

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/buildd-status-dict/+merge/189873

Convert buildd-manager to use the status_dict XML-RPC method of build slaves, rather than constructing an equivalent dict from the tuple returned by the status method.  This saves a good deal of code in the master and will allow us to decommission the old method from the slave; it's also a prerequisite for letting the master detect and display slave versions.
-- 
https://code.launchpad.net/~cjwatson/launchpad/buildd-status-dict/+merge/189873
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/buildd-status-dict into lp:launchpad.
=== modified file 'lib/lp/buildmaster/interactor.py'
--- lib/lp/buildmaster/interactor.py	2013-10-03 07:25:53 +0000
+++ lib/lp/buildmaster/interactor.py	2013-10-08 14:43:20 +0000
@@ -109,9 +109,9 @@
         """Return the protocol version and the builder methods supported."""
         return self._with_timeout(self._server.callRemote('info'))
 
-    def status(self):
+    def status_dict(self):
         """Return the status of the build daemon."""
-        return self._with_timeout(self._server.callRemote('status'))
+        return self._with_timeout(self._server.callRemote('status_dict'))
 
     def ensurepresent(self, sha1sum, url, username, password):
         # XXX: Nothing external calls this. Make it private.
@@ -256,18 +256,8 @@
             potentially other values included by the current build
             behavior.
         """
-        status_sentence = yield slave.status()
-        status = {'builder_status': status_sentence[0]}
-
-        # Extract detailed status and log information if present.
-        # Although build_id is also easily extractable here, there is no
-        # valid reason for anything to use it, so we exclude it.
-        if status['builder_status'] == 'BuilderStatus.WAITING':
-            status['build_status'] = status_sentence[1]
-        else:
-            if status['builder_status'] == 'BuilderStatus.BUILDING':
-                status['logtail'] = status_sentence[2]
-        defer.returnValue((status_sentence, status))
+        status = yield slave.status_dict()
+        defer.returnValue(status)
 
     @classmethod
     @defer.inlineCallbacks
@@ -283,25 +273,10 @@
             finished.  Its return value is True if the slave is lost,
             False otherwise.
         """
-        # 'ident_position' dict relates the position of the job identifier
-        # token in the sentence received from status(), according to the
-        # two statuses we care about. See lp:launchpad-buildd
-        # for further information about sentence format.
-        ident_position = {
-            'BuilderStatus.BUILDING': 1,
-            'BuilderStatus.ABORTING': 1,
-            'BuilderStatus.WAITING': 2
-            }
-
-        # Determine the slave's current build cookie. For BUILDING, ABORTING
-        # and WAITING we extract the string from the slave status
-        # sentence, and for IDLE it is None.
-        status_sentence = yield slave.status()
-        status = status_sentence[0]
-        if status not in ident_position.keys():
-            slave_cookie = None
-        else:
-            slave_cookie = status_sentence[ident_position[status]]
+        # Determine the slave's current build cookie.
+        status_dict = yield slave.status_dict()
+        status = status_dict['builder_status']
+        slave_cookie = status_dict.get('build_id')
 
         if slave_cookie == expected_cookie:
             # The master and slave agree about the current job. Continue.
@@ -486,9 +461,8 @@
         # impossible to get past rescueIfLost unless the slave matches
         # the DB, and this method isn't called unless the DB says
         # there's a job.
-        statuses = yield cls.slaveStatus(slave)
-        status_sentence, status_dict = statuses
-        builder_status = status_dict['builder_status']
+        status = yield cls.slaveStatus(slave)
+        builder_status = status['builder_status']
         if builder_status == 'BuilderStatus.BUILDING':
             # Build still building, collect the logtail.
             if vitals.build_queue.job.status != JobStatus.RUNNING:
@@ -497,7 +471,7 @@
                 raise AssertionError(
                     "Job not running when assigned and slave building.")
             vitals.build_queue.logtail = encoding.guess(
-                str(status_dict.get('logtail')))
+                str(status.get('logtail')))
             transaction.commit()
         elif builder_status == 'BuilderStatus.ABORTING':
             # Build is being aborted.
@@ -508,10 +482,8 @@
             # Build has finished. Delegate handling to the build itself.
             builder = builder_factory[vitals.name]
             behavior = behavior_factory(vitals.build_queue, builder, slave)
-            behavior.updateSlaveStatus(status_sentence, status_dict)
             yield behavior.handleStatus(
-                vitals.build_queue, cls.extractBuildStatus(status_dict),
-                status_dict)
+                vitals.build_queue, cls.extractBuildStatus(status), status)
         else:
             raise AssertionError("Unknown status %s" % builder_status)
 

=== modified file 'lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py'
--- lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py	2013-09-18 06:38:31 +0000
+++ lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py	2013-10-08 14:43:20 +0000
@@ -41,22 +41,11 @@
     def getBuildCookie():
         """Return a string which uniquely identifies the job."""
 
-    def updateSlaveStatus(status_sentence, status_dict):
-        """Update the slave status dict with custom values for this behavior.
-
-        :param status_sentence: The value returned by the build slave's
-           status() method.
-        :param status_dict: A dict of the processed slave status values
-           provided by all types: builder_status, build_id, and optionally
-           build_status or logtail. This should have any behaviour-specific
-           values added to it.
-        """
-
     def handleStatus(bq, status, status_dict):
         """Update the build from a WAITING slave result.
 
         :param bq: The `BuildQueue` currently being processed.
         :param status: The tail of the BuildStatus (eg. OK or PACKAGEFAIL).
         :param status_dict: Slave status dict from
-           `BuilderInteractor.slaveStatus` and `updateSlaveStatus`.
+           `BuilderInteractor.slaveStatus`.
         """

=== modified file 'lib/lp/buildmaster/model/buildfarmjobbehavior.py'
--- lib/lp/buildmaster/model/buildfarmjobbehavior.py	2013-09-18 06:38:31 +0000
+++ lib/lp/buildmaster/model/buildfarmjobbehavior.py	2013-10-08 14:43:20 +0000
@@ -57,12 +57,6 @@
         """The default behavior is a no-op."""
         pass
 
-    def updateSlaveStatus(self, raw_slave_status, status):
-        """See `IBuildFarmJobBehavior`.
-
-        The default behavior is that we don't add any extra values."""
-        pass
-
     def getBuildCookie(self):
         """See `IPackageBuild`."""
         return '%s-%s' % (self.build.job_type.name, self.build.id)

=== modified file 'lib/lp/buildmaster/tests/mock_slaves.py'
--- lib/lp/buildmaster/tests/mock_slaves.py	2013-09-23 07:22:45 +0000
+++ lib/lp/buildmaster/tests/mock_slaves.py	2013-10-08 14:43:20 +0000
@@ -73,8 +73,8 @@
         self.call_log = []
         self.arch_tag = arch_tag
 
-    def status(self):
-        return defer.succeed(('BuilderStatus.IDLE', ''))
+    def status_dict(self):
+        return defer.succeed({'builder_status': 'BuilderStatus.IDLE'})
 
     def ensurepresent(self, sha1, url, user=None, password=None):
         self.call_log.append(('ensurepresent', url, user, password))
@@ -133,11 +133,14 @@
         super(BuildingSlave, self).__init__()
         self.build_id = build_id
 
-    def status(self):
-        self.call_log.append('status')
+    def status_dict(self):
+        self.call_log.append('status_dict')
         buildlog = xmlrpclib.Binary("This is a build log")
-        return defer.succeed(
-            ('BuilderStatus.BUILDING', self.build_id, buildlog))
+        return defer.succeed({
+            'builder_status': 'BuilderStatus.BUILDING',
+            'build_id': self.build_id,
+            'logtail': buildlog,
+            })
 
     def getFile(self, sum, file_to_write):
         self.call_log.append('getFile')
@@ -167,11 +170,15 @@
         # can update this list as needed.
         self.valid_file_hashes = ['buildlog']
 
-    def status(self):
-        self.call_log.append('status')
-        return defer.succeed((
-            'BuilderStatus.WAITING', self.state, self.build_id, self.filemap,
-            self.dependencies))
+    def status_dict(self):
+        self.call_log.append('status_dict')
+        return defer.succeed({
+            'builder_status': 'BuilderStatus.WAITING',
+            'build_status': self.state,
+            'build_id': self.build_id,
+            'filemap': self.filemap,
+            'dependencies': self.dependencies,
+            })
 
     def getFile(self, hash, file_to_write):
         self.call_log.append('getFile')
@@ -187,9 +194,12 @@
 class AbortingSlave(OkSlave):
     """A mock slave that looks like it's in the process of aborting."""
 
-    def status(self):
-        self.call_log.append('status')
-        return defer.succeed(('BuilderStatus.ABORTING', '1-1'))
+    def status_dict(self):
+        self.call_log.append('status_dict')
+        return defer.succeed({
+            'builder_status': 'BuilderStatus.ABORTING',
+            'build_id': '1-1',
+            })
 
 
 class LostBuildingBrokenSlave:
@@ -201,9 +211,12 @@
     def __init__(self):
         self.call_log = []
 
-    def status(self):
-        self.call_log.append('status')
-        return defer.succeed(('BuilderStatus.BUILDING', '1000-10000'))
+    def status_dict(self):
+        self.call_log.append('status_dict')
+        return defer.succeed({
+            'builder_status': 'BuilderStatus.BUILDING',
+            'build_id': '1000-10000',
+            })
 
     def abort(self):
         self.call_log.append('abort')
@@ -220,8 +233,8 @@
     def __init__(self):
         self.call_log = []
 
-    def status(self):
-        self.call_log.append('status')
+    def status_dict(self):
+        self.call_log.append('status_dict')
         return defer.fail(xmlrpclib.Fault(8001, "Broken slave"))
 
 

=== modified file 'lib/lp/buildmaster/tests/test_interactor.py'
--- lib/lp/buildmaster/tests/test_interactor.py	2013-10-02 05:47:26 +0000
+++ lib/lp/buildmaster/tests/test_interactor.py	2013-10-08 14:43:20 +0000
@@ -192,7 +192,7 @@
         lost = yield BuilderInteractor.rescueIfLost(
             extract_vitals_from_db(MockBuilder()), waiting_slave, 'trivial')
         self.assertFalse(lost)
-        self.assertEqual(['status'], waiting_slave.call_log)
+        self.assertEqual(['status_dict'], waiting_slave.call_log)
 
     @defer.inlineCallbacks
     def test_recover_waiting_slave_with_bad_id(self):
@@ -205,7 +205,7 @@
         lost = yield BuilderInteractor.rescueIfLost(
             extract_vitals_from_db(MockBuilder()), waiting_slave, 'trivial')
         self.assertTrue(lost)
-        self.assertEqual(['status', 'clean'], waiting_slave.call_log)
+        self.assertEqual(['status_dict', 'clean'], waiting_slave.call_log)
 
     @defer.inlineCallbacks
     def test_recover_building_slave_with_good_id(self):
@@ -215,7 +215,7 @@
         lost = yield BuilderInteractor.rescueIfLost(
             extract_vitals_from_db(MockBuilder()), building_slave, 'trivial')
         self.assertFalse(lost)
-        self.assertEqual(['status'], building_slave.call_log)
+        self.assertEqual(['status_dict'], building_slave.call_log)
 
     @defer.inlineCallbacks
     def test_recover_building_slave_with_bad_id(self):
@@ -225,7 +225,7 @@
         lost = yield BuilderInteractor.rescueIfLost(
             extract_vitals_from_db(MockBuilder()), building_slave, 'trivial')
         self.assertTrue(lost)
-        self.assertEqual(['status', 'abort'], building_slave.call_log)
+        self.assertEqual(['status_dict', 'abort'], building_slave.call_log)
 
 
 class TestBuilderInteractorSlaveStatus(TestCase):
@@ -235,27 +235,30 @@
     run_tests_with = AsynchronousDeferredRunTest
 
     @defer.inlineCallbacks
-    def assertStatus(self, slave, builder_status=None,
-                     build_status=None, logtail=False, filemap=None,
+    def assertStatus(self, slave, builder_status=None, build_status=None,
+                     build_id=False, logtail=False, filemap=None,
                      dependencies=None):
-        statuses = yield BuilderInteractor.slaveStatus(slave)
-        status_dict = statuses[1]
+        status = yield BuilderInteractor.slaveStatus(slave)
 
         expected = {}
         if builder_status is not None:
             expected["builder_status"] = builder_status
         if build_status is not None:
             expected["build_status"] = build_status
-        if dependencies is not None:
+        if filemap is not None:
+            expected["filemap"] = filemap
             expected["dependencies"] = dependencies
 
-        # We don't care so much about the content of the logtail,
-        # just that it's there.
+        # We don't care so much about the build_id or the content of the
+        # logtail, just that they're there.
+        if build_id:
+            self.assertIn("build_id", status)
+            del status["build_id"]
         if logtail:
-            tail = status_dict.pop("logtail")
+            tail = status.pop("logtail")
             self.assertIsInstance(tail, xmlrpclib.Binary)
 
-        self.assertEqual(expected, status_dict)
+        self.assertEqual(expected, status)
 
     def test_slaveStatus_idle_slave(self):
         self.assertStatus(
@@ -264,16 +267,17 @@
     def test_slaveStatus_building_slave(self):
         self.assertStatus(
             BuildingSlave(), builder_status='BuilderStatus.BUILDING',
-            logtail=True)
+            build_id=True, logtail=True)
 
     def test_slaveStatus_waiting_slave(self):
         self.assertStatus(
             WaitingSlave(), builder_status='BuilderStatus.WAITING',
-            build_status='BuildStatus.OK', filemap={})
+            build_status='BuildStatus.OK', build_id=True, filemap={})
 
     def test_slaveStatus_aborting_slave(self):
         self.assertStatus(
-            AbortingSlave(), builder_status='BuilderStatus.ABORTING')
+            AbortingSlave(), builder_status='BuilderStatus.ABORTING',
+            build_id=True)
 
 
 class TestBuilderInteractorDB(TestCaseWithFactory):
@@ -441,28 +445,26 @@
              ['sourcepackagerecipe',
               'translation-templates', 'binarypackage', 'debian']])
 
+    @defer.inlineCallbacks
     def test_initial_status(self):
-        # Calling 'status' returns the current status of the slave. The
+        # Calling 'status_dict' returns the current status of the slave. The
         # initial status is IDLE.
         self.slave_helper.getServerSlave()
         slave = self.slave_helper.getClientSlave()
-        d = slave.status()
-        return d.addCallback(self.assertEqual, [BuilderStatus.IDLE, ''])
+        status = yield slave.status_dict()
+        self.assertEqual(BuilderStatus.IDLE, status['builder_status'])
 
+    @defer.inlineCallbacks
     def test_status_after_build(self):
-        # Calling 'status' returns the current status of the slave. After a
-        # build has been triggered, the status is BUILDING.
+        # Calling 'status_dict' returns the current status of the slave.
+        # After a build has been triggered, the status is BUILDING.
         slave = self.slave_helper.getClientSlave()
         build_id = 'status-build-id'
-        d = self.slave_helper.triggerGoodBuild(slave, build_id)
-        d.addCallback(lambda ignored: slave.status())
-
-        def check_status(status):
-            self.assertEqual([BuilderStatus.BUILDING, build_id], status[:2])
-            [log_file] = status[2:]
-            self.assertIsInstance(log_file, xmlrpclib.Binary)
-
-        return d.addCallback(check_status)
+        yield self.slave_helper.triggerGoodBuild(slave, build_id)
+        status = yield slave.status_dict()
+        self.assertEqual(BuilderStatus.BUILDING, status['builder_status'])
+        self.assertEqual(build_id, status['build_id'])
+        self.assertIsInstance(status['logtail'], xmlrpclib.Binary)
 
     def test_ensurepresent_not_there(self):
         # ensurepresent checks to see if a file is there.
@@ -609,7 +611,7 @@
         return self.assertCancelled(self.slave.info())
 
     def test_timeout_status(self):
-        return self.assertCancelled(self.slave.status())
+        return self.assertCancelled(self.slave.status_dict())
 
     def test_timeout_ensurepresent(self):
         return self.assertCancelled(

=== modified file 'lib/lp/buildmaster/tests/test_manager.py'
--- lib/lp/buildmaster/tests/test_manager.py	2013-10-07 05:09:49 +0000
+++ lib/lp/buildmaster/tests/test_manager.py	2013-10-08 14:43:20 +0000
@@ -649,7 +649,7 @@
         scanner.checkCancellation = FakeMethod(defer.succeed(False))
 
         yield scanner.scan()
-        self.assertEqual(['status'], slave.call_log)
+        self.assertEqual(['status_dict'], slave.call_log)
         self.assertEqual(1, interactor.updateBuild.call_count)
         self.assertEqual(0, bq.reset.call_count)
 
@@ -672,11 +672,11 @@
         # XXX: checkCancellation needs more than a FakeBuildQueue.
         scanner.checkCancellation = FakeMethod(defer.succeed(False))
 
-        # A single scan will call status(), notice that the slave is
+        # A single scan will call status_dict(), notice that the slave is
         # lost, abort() the slave, then reset() the job without calling
         # updateBuild().
         yield scanner.scan()
-        self.assertEqual(['status', 'abort'], slave.call_log)
+        self.assertEqual(['status_dict', 'abort'], slave.call_log)
         self.assertEqual(0, interactor.updateBuild.call_count)
         self.assertEqual(1, bq.reset.call_count)
 
@@ -696,11 +696,11 @@
             slave_factory=FakeMethod(slave),
             behavior_factory=FakeMethod(None))
 
-        # A single scan will call status(), notice that the slave is
+        # A single scan will call status_dict(), notice that the slave is
         # lost, abort() the slave, then reset() the job without calling
         # updateBuild().
         yield scanner.scan()
-        self.assertEqual(['status', 'abort'], slave.call_log)
+        self.assertEqual(['status_dict', 'abort'], slave.call_log)
         self.assertEqual(0, interactor.updateBuild.call_count)
 
     def test_getExpectedCookie_caches(self):

=== modified file 'lib/lp/code/model/recipebuilder.py'
--- lib/lp/code/model/recipebuilder.py	2013-09-18 06:38:31 +0000
+++ lib/lp/code/model/recipebuilder.py	2013-10-08 14:43:20 +0000
@@ -189,20 +189,3 @@
                 "to the series status of %s." %
                     (build.title, build.id, build.pocket.name,
                      build.distroseries.name))
-
-    def updateSlaveStatus(self, raw_slave_status, status):
-        """Parse the recipe build specific status info into the status dict.
-
-        This includes:
-        * filemap => dictionary or None
-        * dependencies => string or None
-        """
-        build_status_with_files = (
-            'BuildStatus.OK',
-            'BuildStatus.PACKAGEFAIL',
-            'BuildStatus.DEPFAIL',
-            )
-        if (status['builder_status'] == 'BuilderStatus.WAITING' and
-            status['build_status'] in build_status_with_files):
-            status['filemap'] = raw_slave_status[3]
-            status['dependencies'] = raw_slave_status[4]

=== modified file 'lib/lp/soyuz/model/binarypackagebuildbehavior.py'
--- lib/lp/soyuz/model/binarypackagebuildbehavior.py	2013-09-18 06:38:31 +0000
+++ lib/lp/soyuz/model/binarypackagebuildbehavior.py	2013-10-08 14:43:20 +0000
@@ -168,23 +168,6 @@
                     (build.title, build.id, build.pocket.name,
                      build.distro_series.name))
 
-    def updateSlaveStatus(self, raw_slave_status, status):
-        """Parse the binary build specific status info into the status dict.
-
-        This includes:
-        * filemap => dictionary or None
-        * dependencies => string or None
-        """
-        build_status_with_files = (
-            'BuildStatus.OK',
-            'BuildStatus.PACKAGEFAIL',
-            'BuildStatus.DEPFAIL',
-            )
-        if (status['builder_status'] == 'BuilderStatus.WAITING' and
-            status['build_status'] in build_status_with_files):
-            status['filemap'] = raw_slave_status[3]
-            status['dependencies'] = raw_slave_status[4]
-
     def _cachePrivateSourceOnSlave(self, logger):
         """Ask the slave to download source files for a private build.
 

=== modified file 'lib/lp/translations/model/translationtemplatesbuildbehavior.py'
--- lib/lp/translations/model/translationtemplatesbuildbehavior.py	2013-09-18 06:38:31 +0000
+++ lib/lp/translations/model/translationtemplatesbuildbehavior.py	2013-10-08 14:43:20 +0000
@@ -118,12 +118,6 @@
                 tarball, False, branch.owner, productseries=series,
                 approver_factory=TranslationBuildApprover)
 
-    def updateSlaveStatus(self, raw_slave_status, status):
-        """See `IBuildFarmJobBehavior`."""
-        if status['builder_status'] == 'BuilderStatus.WAITING':
-            if len(raw_slave_status) >= 4:
-                status['filemap'] = raw_slave_status[3]
-
     @defer.inlineCallbacks
     def handleStatus(self, queue_item, status, slave_status):
         """Deal with a finished build job.

=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py	2013-09-18 06:38:31 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py	2013-10-08 14:43:20 +0000
@@ -59,7 +59,7 @@
 class MakeBehaviorMixin(object):
     """Provide common test methods."""
 
-    def makeBehavior(self, branch=None, use_fake_chroot=True):
+    def makeBehavior(self, branch=None, use_fake_chroot=True, **kwargs):
         """Create a TranslationTemplatesBuildBehavior.
 
         Anything that might communicate with build slaves and such
@@ -68,7 +68,7 @@
         specific_job = self.factory.makeTranslationTemplatesBuildJob(
             branch=branch)
         behavior = IBuildFarmJobBehavior(specific_job)
-        slave = WaitingSlave()
+        slave = WaitingSlave(**kwargs)
         behavior.setBuilder(self.factory.makeBuilder(), slave)
         if use_fake_chroot:
             lf = self.factory.makeLibraryFileAlias()
@@ -182,7 +182,8 @@
 
     def test_handleStatus_OK(self):
         # Hopefully, a build will succeed and produce a tarball.
-        behavior = self.makeBehavior()
+        behavior = self.makeBehavior(
+            filemap={'translation-templates.tar.gz': 'foo'})
         behavior._uploadTarball = FakeMethod()
         queue_item = FakeBuildQueue(behavior)
         slave = behavior._slave
@@ -195,21 +196,14 @@
             self.assertNotIn('clean', slave_call_log)
             self.assertEqual(0, behavior._uploadTarball.call_count)
 
-            return slave.status()
+            return slave.status_dict()
 
         def got_status(status):
-            slave_call_log = slave.call_log
-            slave_status = {
-                'builder_status': status[0],
-                'build_status': status[1],
-                'filemap': {'translation-templates.tar.gz': 'foo'},
-                }
             return (
                 behavior.handleStatus(
-                    queue_item,
-                    BuilderInteractor.extractBuildStatus(slave_status),
-                    slave_status),
-                slave_call_log)
+                    queue_item, BuilderInteractor.extractBuildStatus(status),
+                    status),
+                slave.call_log)
 
         def build_updated(ignored):
             self.assertEqual(BuildStatus.FULLYBUILT, behavior.build.status)
@@ -227,7 +221,7 @@
 
     def test_handleStatus_failed(self):
         # Builds may also fail (and produce no tarball).
-        behavior = self.makeBehavior()
+        behavior = self.makeBehavior(state='BuildStatus.FAILEDTOBUILD')
         behavior._uploadTarball = FakeMethod()
         queue_item = FakeBuildQueue(behavior)
         slave = behavior._slave
@@ -235,24 +229,14 @@
 
         def got_dispatch((status, info)):
             # Now that we've dispatched, get the status.
-            return slave.status()
+            return slave.status_dict()
 
         def got_status(status):
-            raw_status = (
-                'BuilderStatus.WAITING',
-                'BuildStatus.FAILEDTOBUILD',
-                status[2],
-                )
-            slave_status = {
-                'builder_status': raw_status[0],
-                'build_status': raw_status[1],
-                }
-            behavior.updateSlaveStatus(raw_status, slave_status)
-            self.assertNotIn('filemap', slave_status)
+            del status['filemap']
             return behavior.handleStatus(
                 queue_item,
-                BuilderInteractor.extractBuildStatus(slave_status),
-                slave_status),
+                BuilderInteractor.extractBuildStatus(status),
+                status),
 
         def build_updated(ignored):
             self.assertEqual(BuildStatus.FAILEDTOBUILD, behavior.build.status)
@@ -277,24 +261,14 @@
         d = behavior.dispatchBuildToSlave(queue_item, logging)
 
         def got_dispatch((status, info)):
-            return slave.status()
+            return slave.status_dict()
 
         def got_status(status):
-            raw_status = (
-                'BuilderStatus.WAITING',
-                'BuildStatus.OK',
-                status[2],
-                )
-            slave_status = {
-                'builder_status': raw_status[0],
-                'build_status': raw_status[1],
-                }
-            behavior.updateSlaveStatus(raw_status, slave_status)
-            self.assertFalse('filemap' in slave_status)
+            del status['filemap']
             return behavior.handleStatus(
                 queue_item,
-                BuilderInteractor.extractBuildStatus(slave_status),
-                slave_status),
+                BuilderInteractor.extractBuildStatus(status),
+                status),
 
         def build_updated(ignored):
             self.assertEqual(BuildStatus.FULLYBUILT, behavior.build.status)
@@ -310,7 +284,8 @@
     def test_handleStatus_uploads(self):
         productseries = self.makeProductSeriesWithBranchForTranslation()
         branch = productseries.branch
-        behavior = self.makeBehavior(branch=branch)
+        behavior = self.makeBehavior(
+            branch=branch, filemap={'translation-templates.tar.gz': 'foo'})
         queue_item = FakeBuildQueue(behavior)
         slave = behavior._slave
 
@@ -325,20 +300,13 @@
 
         def got_dispatch((status, info)):
             slave.getFile = fake_getFile
-            slave.filemap = {'translation-templates.tar.gz': 'foo'}
-            return slave.status()
+            return slave.status_dict()
 
         def got_status(status):
-            slave_status = {
-                'builder_status': status[0],
-                'build_status': status[1],
-                'build_id': status[2],
-                }
-            behavior.updateSlaveStatus(status, slave_status)
             return behavior.handleStatus(
                 queue_item,
-                BuilderInteractor.extractBuildStatus(slave_status),
-                slave_status),
+                BuilderInteractor.extractBuildStatus(status),
+                status),
 
         def build_updated(ignored):
             self.assertEqual(BuildStatus.FULLYBUILT, behavior.build.status)


Follow ups