aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject git commit: Increment Mesos version to 0.20.0
Date Wed, 03 Sep 2014 23:04:27 GMT
Repository: incubator-aurora
Updated Branches:
  refs/heads/master 24f3eae38 -> 467bc5604


Increment Mesos version to 0.20.0

Bugs closed: AURORA-674

Reviewed at https://reviews.apache.org/r/25208/


Project: http://git-wip-us.apache.org/repos/asf/incubator-aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-aurora/commit/467bc560
Tree: http://git-wip-us.apache.org/repos/asf/incubator-aurora/tree/467bc560
Diff: http://git-wip-us.apache.org/repos/asf/incubator-aurora/diff/467bc560

Branch: refs/heads/master
Commit: 467bc56049cc775eaf61520a464b363d44023024
Parents: 24f3eae
Author: Joe Smith <yasumoto7@gmail.com>
Authored: Wed Sep 3 15:55:17 2014 -0700
Committer: Maxim Khutornenko <maxim@apache.org>
Committed: Wed Sep 3 15:55:17 2014 -0700

----------------------------------------------------------------------
 3rdparty/python/BUILD                           |  3 +-
 Vagrantfile                                     |  6 +-
 build.gradle                                    |  2 +-
 examples/vagrant/provision-dev-cluster.sh       |  4 +-
 src/main/python/apache/aurora/executor/BUILD    |  7 +-
 .../apache/aurora/executor/aurora_executor.py   | 42 ++++-------
 .../python/apache/aurora/executor/bin/BUILD     |  2 +
 .../aurora/executor/bin/gc_executor_main.py     |  4 +-
 .../executor/bin/thermos_executor_main.py       |  4 +-
 .../python/apache/aurora/executor/common/BUILD  |  3 +
 .../aurora/executor/common/health_checker.py    |  5 +-
 .../aurora/executor/common/kill_manager.py      |  6 +-
 .../aurora/executor/common/status_checker.py    | 31 ++------
 .../apache/aurora/executor/executor_base.py     | 27 ++++---
 .../apache/aurora/executor/gc_executor.py       | 27 +++----
 .../aurora/executor/thermos_task_runner.py      | 13 ++--
 src/test/python/apache/aurora/executor/BUILD    | 31 ++++++--
 .../python/apache/aurora/executor/common/BUILD  | 24 ++++++
 .../executor/common/test_executor_timeout.py    | 39 ++++++++++
 .../executor/common/test_health_checker.py      |  7 +-
 .../aurora/executor/common/test_kill_manager.py | 42 +++++++++++
 .../executor/common/test_status_checker.py      |  7 +-
 .../aurora/executor/test_executor_base.py       | 79 ++++++++++++++++++++
 .../apache/aurora/executor/test_gc_executor.py  | 12 +--
 .../aurora/executor/test_status_manager.py      | 50 +++++++++++++
 .../aurora/executor/test_thermos_executor.py    | 54 ++++++-------
 .../aurora/executor/test_thermos_task_runner.py | 16 ++--
 27 files changed, 391 insertions(+), 156 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/3rdparty/python/BUILD
----------------------------------------------------------------------
diff --git a/3rdparty/python/BUILD b/3rdparty/python/BUILD
index edc446e..5e96b91 100644
--- a/3rdparty/python/BUILD
+++ b/3rdparty/python/BUILD
@@ -33,7 +33,8 @@ make_link('argparse', '1.2.1')
 make_link('bottle', '0.11.6')
 make_link('Flask', '0.9')
 make_link('mako', '0.4.0')
-make_link('mesos', '0.19.1')
+make_link('mesos.interface', '0.20.0')
+make_link('mesos.native', '0.20.0')
 make_link('mock', '1.0.1')
 make_link('mox', '0.5.3')
 make_link('psutil', '1.1.2')

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/Vagrantfile
----------------------------------------------------------------------
diff --git a/Vagrantfile b/Vagrantfile
index c8cb2d4..ea0b252 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -18,11 +18,7 @@
 VAGRANTFILE_API_VERSION = "2"
 
 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
-  config.vm.box = "precise64"
-
-  # The url from where the 'config.vm.box' box will be fetched if it
-  # doesn't already exist on the user's system.
-  config.vm.box_url = "http://files.vagrantup.com/precise64.box"
+  config.vm.box = "ubuntu/trusty64"
 
   config.vm.define "devcluster" do |dev|
     dev.vm.network :private_network, ip: "192.168.33.7"

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 9871e8d..494c544 100644
--- a/build.gradle
+++ b/build.gradle
@@ -167,7 +167,7 @@ dependencies {
   compile 'javax.servlet:servlet-api:2.5'
   compile "log4j:log4j:${log4jRev}"
   compile 'org.antlr:stringtemplate:3.2.1'
-  compile 'org.apache.mesos:mesos:0.19.1'
+  compile 'org.apache.mesos:mesos:0.20.0'
   compile thriftLib
   compile 'org.apache.zookeeper:zookeeper:3.3.4'
   compile 'org.mybatis:mybatis:3.2.7'

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/examples/vagrant/provision-dev-cluster.sh
----------------------------------------------------------------------
diff --git a/examples/vagrant/provision-dev-cluster.sh b/examples/vagrant/provision-dev-cluster.sh
index 2ce74f8..0b46e31 100755
--- a/examples/vagrant/provision-dev-cluster.sh
+++ b/examples/vagrant/provision-dev-cluster.sh
@@ -30,14 +30,14 @@ update-alternatives --set java /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
 # that want to advertise the hostname to the user, or other components.
 hostname 192.168.33.7
 
-MESOS_VERSION=0.19.1
+MESOS_VERSION=0.20.0
 
 function prepare_extras() {
   pushd aurora
     # Fetch the mesos egg, needed to build python components.
     mkdir -p third_party
     pushd third_party
-      wget -c http://downloads.mesosphere.io/master/ubuntu/12.04/mesos-${MESOS_VERSION}-py2.7-linux-x86_64.egg \
+      wget -c http://downloads.mesosphere.io/master/ubuntu/14.04/mesos-${MESOS_VERSION}-py2.7-linux-x86_64.egg \
         -O mesos-${MESOS_VERSION}-py2.7-linux-x86_64.egg
     popd
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/BUILD b/src/main/python/apache/aurora/executor/BUILD
index c1c50db..1ad8f82 100644
--- a/src/main/python/apache/aurora/executor/BUILD
+++ b/src/main/python/apache/aurora/executor/BUILD
@@ -18,6 +18,7 @@ python_library(
   name = 'thermos_task_runner',
   sources = ['thermos_task_runner.py'],
   dependencies = [
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:twitter.common.dirutil'),
     pants('3rdparty/python:twitter.common.log'),
     pants('3rdparty/python:twitter.common.quantity'),
@@ -68,7 +69,7 @@ python_library(
   name = 'executor_base',
   sources = ['executor_base.py'],
   dependencies = [
-    pants('3rdparty/python:mesos'),
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:twitter.common.log'),
   ]
 )
@@ -79,7 +80,7 @@ python_library(
   dependencies = [
     pants(':status_manager'),
     pants(':executor_base'),
-    pants('3rdparty/python:mesos'),
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:pystachio'),
     pants('3rdparty/python:twitter.common.app'),
     pants('3rdparty/python:twitter.common.concurrent'),
@@ -110,7 +111,7 @@ python_library(
   dependencies = [
     pants(':executor_detector'),
     pants(':executor_base'),
-    pants('3rdparty/python:mesos'),
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:psutil'),
     pants('3rdparty/python:twitter.common.collections'),
     pants('3rdparty/python:twitter.common.exceptions'),

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/aurora_executor.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/aurora_executor.py b/src/main/python/apache/aurora/executor/aurora_executor.py
index 8985aeb..79a2485 100644
--- a/src/main/python/apache/aurora/executor/aurora_executor.py
+++ b/src/main/python/apache/aurora/executor/aurora_executor.py
@@ -17,7 +17,7 @@ import threading
 import time
 import traceback
 
-import mesos_pb2 as mesos_pb
+from mesos.interface import mesos_pb2
 from twitter.common import log
 from twitter.common.concurrent import deadline, defer, Timeout
 from twitter.common.metrics import Observable
@@ -25,7 +25,7 @@ from twitter.common.quantity import Amount, Time
 
 from .common.kill_manager import KillManager
 from .common.sandbox import DirectorySandbox, SandboxProvider
-from .common.status_checker import ChainedStatusChecker, ExitState
+from .common.status_checker import ChainedStatusChecker
 from .common.task_info import assigned_task_from_mesos_task
 from .common.task_runner import TaskError, TaskRunner, TaskRunnerProvider
 from .executor_base import ExecutorBase
@@ -95,7 +95,7 @@ class AuroraExecutor(ExecutorBase, Observable):
         - Set up necessary HealthCheckers
         - Set up StatusManager, and attach HealthCheckers
     """
-    self.send_update(driver, self._task_id, mesos_pb.TASK_STARTING, 'Initializing sandbox.')
+    self.send_update(driver, self._task_id, mesos_pb2.TASK_STARTING, 'Initializing sandbox.')
 
     if not self._initialize_sandbox(driver, assigned_task):
       return
@@ -106,17 +106,17 @@ class AuroraExecutor(ExecutorBase, Observable):
       self._runner = self._runner_provider.from_assigned_task(assigned_task, self._sandbox)
     except TaskError as e:
       self.runner_aborted.set()
-      self._die(driver, mesos_pb.TASK_FAILED, str(e))
+      self._die(driver, mesos_pb2.TASK_FAILED, str(e))
       return
 
     if not isinstance(self._runner, TaskRunner):
-      self._die(driver, mesos_pb.TASK_FAILED, 'Unrecognized task!')
+      self._die(driver, mesos_pb2.TASK_FAILED, 'Unrecognized task!')
       return
 
     if not self._start_runner(driver, assigned_task):
       return
 
-    self.send_update(driver, self._task_id, mesos_pb.TASK_RUNNING)
+    self.send_update(driver, self._task_id, mesos_pb2.TASK_RUNNING)
 
     self._start_status_manager(driver, assigned_task)
 
@@ -127,25 +127,25 @@ class AuroraExecutor(ExecutorBase, Observable):
       deadline(self._sandbox.create, timeout=self.SANDBOX_INITIALIZATION_TIMEOUT,
                daemon=True, propagate=True)
     except Timeout:
-      self._die(driver, mesos_pb.TASK_FAILED, 'Timed out waiting for sandbox to initialize!')
+      self._die(driver, mesos_pb2.TASK_FAILED, 'Timed out waiting for sandbox to initialize!')
       return
     except self._sandbox.Error as e:
-      self._die(driver, mesos_pb.TASK_FAILED, 'Failed to initialize sandbox: %s' % e)
+      self._die(driver, mesos_pb2.TASK_FAILED, 'Failed to initialize sandbox: %s' % e)
       return
     self.sandbox_created.set()
     return True
 
   def _start_runner(self, driver, assigned_task):
     if self.runner_aborted.is_set():
-      self._die(driver, mesos_pb.TASK_KILLED, 'Task killed during initialization.')
+      self._die(driver, mesos_pb2.TASK_KILLED, 'Task killed during initialization.')
 
     try:
       deadline(self._runner.start, timeout=self.START_TIMEOUT, propagate=True)
     except TaskError as e:
-      self._die(driver, mesos_pb.TASK_FAILED, 'Task initialization failed: %s' % e)
+      self._die(driver, mesos_pb2.TASK_FAILED, 'Task initialization failed: %s' % e)
       return False
     except Timeout:
-      self._die(driver, mesos_pb.TASK_LOST, 'Timed out waiting for task to start!')
+      self._die(driver, mesos_pb2.TASK_LOST, 'Timed out waiting for task to start!')
       return False
 
     self.runner_started.set()
@@ -188,20 +188,6 @@ class AuroraExecutor(ExecutorBase, Observable):
     self.log('Activating kill manager.')
     self._kill_manager.kill(reason)
 
-  @classmethod
-  def translate_exit_state_to_mesos(cls, exit_state):
-    # Put into executor_base?
-    if exit_state == ExitState.FAILED:
-      return mesos_pb.TASK_FAILED
-    elif exit_state == ExitState.KILLED:
-      return mesos_pb.TASK_KILLED
-    elif exit_state == ExitState.FINISHED:
-      return mesos_pb.TASK_FINISHED
-    elif exit_state == ExitState.LOST:
-      return mesos_pb.TASK_LOST
-    log.error('Unknown exit state, defaulting to TASK_FINISHED.')
-    return mesos_pb.TASK_FINISHED
-
   def _shutdown(self, status_result):
     runner_status = self._runner.status
 
@@ -222,7 +208,7 @@ class AuroraExecutor(ExecutorBase, Observable):
     self.send_update(
         self._driver,
         self._task_id,
-        self.translate_exit_state_to_mesos(exit_status.status),
+        exit_status.status,
         status_result.reason)
 
     self.terminated.set()
@@ -255,7 +241,7 @@ class AuroraExecutor(ExecutorBase, Observable):
 
     if self._runner:
       log.error('Already running a task! %s' % self._task_id)
-      self.send_update(driver, task.task_id.value, mesos_pb.TASK_LOST,
+      self.send_update(driver, task.task_id.value, mesos_pb2.TASK_LOST,
           "Task already running on this executor: %s" % self._task_id)
       return
 
@@ -264,7 +250,7 @@ class AuroraExecutor(ExecutorBase, Observable):
 
     assigned_task = self.validate_task(task)
     if not assigned_task:
-      self.send_update(driver, self._task_id, mesos_pb.TASK_FAILED,
+      self.send_update(driver, self._task_id, mesos_pb2.TASK_FAILED,
           'Could not deserialize task.')
       defer(driver.stop, delay=self.STOP_WAIT)
       return

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/bin/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/bin/BUILD b/src/main/python/apache/aurora/executor/bin/BUILD
index 9351715..aeb8aee 100644
--- a/src/main/python/apache/aurora/executor/bin/BUILD
+++ b/src/main/python/apache/aurora/executor/bin/BUILD
@@ -18,6 +18,7 @@ python_binary(
   entry_point = 'apache.aurora.executor.bin.thermos_executor_main:proxy_main',
   always_write_cache = True,
   dependencies = [
+    pants('3rdparty/python:mesos.native'),
     pants('3rdparty/python:twitter.common.app'),
     pants('3rdparty/python:twitter.common.log'),
     pants('3rdparty/python:twitter.common.metrics'),
@@ -38,6 +39,7 @@ python_binary(
   entry_point = 'apache.aurora.executor.bin.gc_executor_main:proxy_main',
   always_write_cache = True,
   dependencies = [
+    pants('3rdparty/python:mesos.native'),
     pants('3rdparty/python:twitter.common.app'),
     pants('3rdparty/python:twitter.common.log'),
     pants('3rdparty/python:twitter.common.metrics'),

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/bin/gc_executor_main.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/bin/gc_executor_main.py b/src/main/python/apache/aurora/executor/bin/gc_executor_main.py
index bc20dad..890bfaa 100644
--- a/src/main/python/apache/aurora/executor/bin/gc_executor_main.py
+++ b/src/main/python/apache/aurora/executor/bin/gc_executor_main.py
@@ -19,7 +19,7 @@ slave.
 
 """
 
-import mesos
+from mesos.native import MesosExecutorDriver
 from twitter.common import app, log
 from twitter.common.log.options import LogOptions
 from twitter.common.metrics.sampler import DiskMetricWriter
@@ -48,7 +48,7 @@ def proxy_main():
     metric_writer.start()
 
     # Create driver stub
-    driver = mesos.MesosExecutorDriver(thermos_gc_executor)
+    driver = MesosExecutorDriver(thermos_gc_executor)
 
     # Start GC executor
     driver.run()

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/bin/thermos_executor_main.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/bin/thermos_executor_main.py b/src/main/python/apache/aurora/executor/bin/thermos_executor_main.py
index aacc19a..9df9b4b 100644
--- a/src/main/python/apache/aurora/executor/bin/thermos_executor_main.py
+++ b/src/main/python/apache/aurora/executor/bin/thermos_executor_main.py
@@ -21,7 +21,7 @@ slave.
 
 import os
 
-import mesos
+from mesos.native import MesosExecutorDriver
 from twitter.common import app, log
 from twitter.common.log.options import LogOptions
 
@@ -101,7 +101,7 @@ def proxy_main():
     )
 
     # Create driver stub
-    driver = mesos.MesosExecutorDriver(thermos_executor)
+    driver = MesosExecutorDriver(thermos_executor)
 
     # This is an ephemeral executor -- shutdown if we receive no tasks within a certain
     # time period

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/common/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/common/BUILD b/src/main/python/apache/aurora/executor/common/BUILD
index 0a4d35a..335ebc4 100644
--- a/src/main/python/apache/aurora/executor/common/BUILD
+++ b/src/main/python/apache/aurora/executor/common/BUILD
@@ -16,6 +16,7 @@ python_library(
   name = 'status_checker',
   sources = ['status_checker.py'],
   dependencies = [
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:twitter.common.lang'),
     pants('3rdparty/python:twitter.common.log'),
     pants('3rdparty/python:twitter.common.metrics'),
@@ -37,6 +38,7 @@ python_library(
   dependencies = [
     pants(':status_checker'),
     pants(':task_info'),
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:twitter.common.log'),
     pants('3rdparty/python:twitter.common.exceptions'),
     pants('src/main/python/apache/aurora/common:http_signaler'),
@@ -72,6 +74,7 @@ python_library(
   name = 'kill_manager',
   sources = ['kill_manager.py'],
   dependencies = [
+    pants('3rdparty/python:mesos.interface'),
     pants(':status_checker'),
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/common/health_checker.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/common/health_checker.py b/src/main/python/apache/aurora/executor/common/health_checker.py
index 671f497..603fff3 100644
--- a/src/main/python/apache/aurora/executor/common/health_checker.py
+++ b/src/main/python/apache/aurora/executor/common/health_checker.py
@@ -15,12 +15,13 @@
 import threading
 import time
 
+from mesos.interface.mesos_pb2 import TaskState
 from twitter.common import log
 from twitter.common.exceptions import ExceptionalThread
 
 from apache.aurora.common.http_signaler import HttpSignaler
 
-from .status_checker import ExitState, StatusChecker, StatusCheckerProvider, StatusResult
+from .status_checker import StatusChecker, StatusCheckerProvider, StatusResult
 from .task_info import mesos_task_instance_from_assigned_task, resolve_ports
 
 
@@ -58,7 +59,7 @@ class HealthCheckerThread(StatusChecker, ExceptionalThread):
   @property
   def status(self):
     if not self._healthy:
-      return StatusResult('Failed health check! %s' % self._reason, ExitState.FAILED)
+      return StatusResult('Failed health check! %s' % self._reason, TaskState.Value('TASK_FAILED'))
 
   def run(self):
     log.debug('Health checker thread started.')

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/common/kill_manager.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/common/kill_manager.py b/src/main/python/apache/aurora/executor/common/kill_manager.py
index 6e482cf..2317267 100644
--- a/src/main/python/apache/aurora/executor/common/kill_manager.py
+++ b/src/main/python/apache/aurora/executor/common/kill_manager.py
@@ -12,7 +12,9 @@
 # limitations under the License.
 #
 
-from .status_checker import ExitState, StatusChecker, StatusResult
+from mesos.interface.mesos_pb2 import TaskState
+
+from .status_checker import StatusChecker, StatusResult
 
 
 class KillManager(StatusChecker):
@@ -27,7 +29,7 @@ class KillManager(StatusChecker):
   @property
   def status(self):
     if self._killed:
-      return StatusResult(self._reason, ExitState.KILLED)
+      return StatusResult(self._reason, TaskState.Value('TASK_KILLED'))
 
   def name(self):
     return 'kill_manager'

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/common/status_checker.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/common/status_checker.py b/src/main/python/apache/aurora/executor/common/status_checker.py
index eda30e3..624921d 100644
--- a/src/main/python/apache/aurora/executor/common/status_checker.py
+++ b/src/main/python/apache/aurora/executor/common/status_checker.py
@@ -14,39 +14,24 @@
 
 from abc import abstractmethod, abstractproperty
 
+from mesos.interface.mesos_pb2 import TaskState
 from twitter.common import log
 from twitter.common.lang import Interface
 from twitter.common.metrics import NamedGauge, Observable
 
 
-# This mirrors mesos_pb2 TaskStatus without explicitly depending upon it.
-#
-# The dependency is a 30MB egg, so for smaller applications that just need
-# the status text, we proxy them.  The actual conversion betwen ExitState
-# and TaskStatus is done in the StatusManager.
-class ExitState(object):
-  FAILED = object()
-  FINISHED = object()
-  KILLED = object()
-  LOST = object()
-
-  ALL_STATES = {
-    FAILED: 'FAILED',
-    FINISHED: 'FINISHED',
-    KILLED: 'KILLED',
-    LOST: 'LOST',
-  }
-
-
 class StatusResult(object):
   """
-    Encapsulates a reason for failure and an optional reason which defaults to
-    ExitState.FAILED.
+    Encapsulates a reason for failure and a status value from mesos.interface.mesos_pb2.TaskStatus.
+    As mesos 0.20.0 uses protobuf 2.5.0, see the EnumTypeWrapper[1] docs for more information.
+
+    https://code.google.com/p/protobuf/source/browse/tags/2.5.0/
+        python/google/protobuf/internal/enum_type_wrapper.py
   """
 
   def __init__(self, reason, status):
     self._reason = reason
-    if status not in ExitState.ALL_STATES:
+    if status not in TaskState.values():
       raise ValueError('Unknown task state: %r' % status)
     self._status = status
 
@@ -62,7 +47,7 @@ class StatusResult(object):
     return '%s(%r, status=%r)' % (
         self.__class__.__name__,
         self._reason,
-        ExitState.ALL_STATES[self._status])
+        TaskState.Name(self._status))
 
 
 class StatusChecker(Observable, Interface):

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/executor_base.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/executor_base.py b/src/main/python/apache/aurora/executor/executor_base.py
index c632b77..1db97cc 100644
--- a/src/main/python/apache/aurora/executor/executor_base.py
+++ b/src/main/python/apache/aurora/executor/executor_base.py
@@ -12,27 +12,26 @@
 # limitations under the License.
 #
 
-import mesos
-import mesos_pb2 as mesos_pb
+from mesos.interface import Executor, mesos_pb2
 from twitter.common import log
 
 
-class ExecutorBase(mesos.Executor):
+class ExecutorBase(Executor):
   # Statuses are hard, let's go shopping.
   STATES_TO_STR = {
-      mesos_pb.TASK_STARTING: 'STARTING',
-      mesos_pb.TASK_RUNNING: 'RUNNING',
-      mesos_pb.TASK_FINISHED: 'FINISHED',
-      mesos_pb.TASK_FAILED: 'FAILED',
-      mesos_pb.TASK_KILLED: 'KILLED',
-      mesos_pb.TASK_LOST: 'LOST',
+      mesos_pb2.TASK_STARTING: 'STARTING',
+      mesos_pb2.TASK_RUNNING: 'RUNNING',
+      mesos_pb2.TASK_FINISHED: 'FINISHED',
+      mesos_pb2.TASK_FAILED: 'FAILED',
+      mesos_pb2.TASK_KILLED: 'KILLED',
+      mesos_pb2.TASK_LOST: 'LOST',
   }
 
   TERMINAL_STATES = frozenset([
-        mesos_pb.TASK_FAILED,
-        mesos_pb.TASK_FINISHED,
-        mesos_pb.TASK_KILLED,
-        mesos_pb.TASK_LOST,
+        mesos_pb2.TASK_FAILED,
+        mesos_pb2.TASK_FINISHED,
+        mesos_pb2.TASK_KILLED,
+        mesos_pb2.TASK_LOST,
   ])
 
   @classmethod
@@ -63,7 +62,7 @@ class ExecutorBase(mesos.Executor):
     self.log('disconnected() called')
 
   def send_update(self, driver, task_id, state, message=None):
-    update = mesos_pb.TaskStatus()
+    update = mesos_pb2.TaskStatus()
     if not isinstance(state, int):
       raise TypeError('Invalid state type %s, should be int.' % type(state))
     if state not in self.STATES_TO_STR:

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/gc_executor.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/gc_executor.py b/src/main/python/apache/aurora/executor/gc_executor.py
index c45d5eb..572c106 100644
--- a/src/main/python/apache/aurora/executor/gc_executor.py
+++ b/src/main/python/apache/aurora/executor/gc_executor.py
@@ -24,8 +24,8 @@ import os
 import threading
 import time
 
-import mesos_pb2 as mesos_pb
 import psutil
+from mesos.interface import mesos_pb2
 from thrift.TSerialization import deserialize as thrift_deserialize
 from thrift.TSerialization import serialize as thrift_serialize
 from twitter.common.collections import OrderedDict
@@ -62,11 +62,11 @@ THERMOS_TO_TWITTER_STATES = {
 
 
 THERMOS_TO_MESOS_STATES = {
-    TaskState.ACTIVE: mesos_pb.TASK_RUNNING,
-    TaskState.SUCCESS: mesos_pb.TASK_FINISHED,
-    TaskState.FAILED: mesos_pb.TASK_FAILED,
-    TaskState.KILLED: mesos_pb.TASK_KILLED,
-    TaskState.LOST: mesos_pb.TASK_LOST,
+    TaskState.ACTIVE: mesos_pb2.TASK_RUNNING,
+    TaskState.SUCCESS: mesos_pb2.TASK_FINISHED,
+    TaskState.FAILED: mesos_pb2.TASK_FAILED,
+    TaskState.KILLED: mesos_pb2.TASK_KILLED,
+    TaskState.LOST: mesos_pb2.TASK_LOST,
 }
 
 
@@ -288,7 +288,7 @@ class ThermosGCExecutor(ExecutorBase, ExceptionalThread, Observable):
           self.send_update(
               driver,
               task_id,
-              THERMOS_TO_MESOS_STATES.get(last_state, mesos_pb.TASK_LOST),
+              THERMOS_TO_MESOS_STATES.get(last_state, mesos_pb2.TASK_LOST),
               'Task finish detected by GC executor.')
         else:
           local_gc.update(self.should_gc_task(task_id))
@@ -298,7 +298,8 @@ class ThermosGCExecutor(ExecutorBase, ExceptionalThread, Observable):
       if task_id not in local_task_ids and task_id in sched_active:
         self.log('Know nothing about task %s, telling scheduler of LOSS.' % task_id)
         updates[task_id] = ScheduleStatus.LOST
-        self.send_update(driver, task_id, mesos_pb.TASK_LOST, 'GC executor found no trace of task.')
+        self.send_update(
+            driver, task_id, mesos_pb2.TASK_LOST, 'GC executor found no trace of task.')
       if task_id not in local_task_ids and task_id in sched_starting:
         self.log('Know nothing about task %s, but scheduler says STARTING - passing' % task_id)
 
@@ -354,7 +355,7 @@ class ThermosGCExecutor(ExecutorBase, ExceptionalThread, Observable):
       if self._terminate_task(task_id, kill=False):
         updates[task_id] = ScheduleStatus.LOST
         self.send_update(
-            driver, task_id, mesos_pb.TASK_LOST, 'GC executor detected failed task runner.')
+            driver, task_id, mesos_pb2.TASK_LOST, 'GC executor detected failed task runner.')
 
     return updates
 
@@ -441,7 +442,7 @@ class ThermosGCExecutor(ExecutorBase, ExceptionalThread, Observable):
       self._driver.sendFrameworkMessage(thrift_serialize(
           SchedulerMessage(deletedTasks=DeletedTasks(taskIds=deleted_tasks))))
     self.send_update(
-        self._driver, task.task_id.value, mesos_pb.TASK_FINISHED, 'Garbage collection finished.')
+        self._driver, task.task_id.value, mesos_pb2.TASK_FINISHED, 'Garbage collection finished.')
     self.log('Garbage collection complete [task_id=%s]' % task_id)
     self._task_id = self._start_time = None
 
@@ -480,7 +481,7 @@ class ThermosGCExecutor(ExecutorBase, ExceptionalThread, Observable):
       except KeyError:  # no enqueued GC tasks
         pass
       else:
-        self.send_update(self._driver, prev_task_id, mesos_pb.TASK_FINISHED,
+        self.send_update(self._driver, prev_task_id, mesos_pb2.TASK_FINISHED,
                          'Garbage collection skipped - GC executor shutting down')
         # TODO(jon) Remove this once external MESOS-243 is resolved.
         self.log('Sleeping briefly to mitigate https://issues.apache.org/jira/browse/MESOS-243')
@@ -507,7 +508,7 @@ class ThermosGCExecutor(ExecutorBase, ExceptionalThread, Observable):
     except Exception as err:
       self.log('Error deserializing task: %s' % err)
       self.send_update(
-          self._driver, task_id, mesos_pb.TASK_FAILED, 'Deserialization of GC task failed')
+          self._driver, task_id, mesos_pb2.TASK_FAILED, 'Deserialization of GC task failed')
       return
     try:
       prev_task_id, _ = self._gc_task_queue.popitem(0)
@@ -517,7 +518,7 @@ class ThermosGCExecutor(ExecutorBase, ExceptionalThread, Observable):
       self.log('=> Dropping previously queued GC with task_id %s' % prev_task_id)
       self._dropped_tasks.increment()
       self.log('=> Updating scheduler')
-      self.send_update(self._driver, prev_task_id, mesos_pb.TASK_FINISHED,
+      self.send_update(self._driver, prev_task_id, mesos_pb2.TASK_FINISHED,
                        'Garbage collection skipped - GC executor received another task')
     self.log('=> Adding %s to GC queue' % task_id)
     self._gc_task_queue[task_id] = (task, art.retainedTasks, self._clock.time())

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/main/python/apache/aurora/executor/thermos_task_runner.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/thermos_task_runner.py b/src/main/python/apache/aurora/executor/thermos_task_runner.py
index 03a40e6..7b346e2 100644
--- a/src/main/python/apache/aurora/executor/thermos_task_runner.py
+++ b/src/main/python/apache/aurora/executor/thermos_task_runner.py
@@ -20,6 +20,7 @@ import subprocess
 import threading
 import time
 
+from mesos.interface import mesos_pb2
 from twitter.common import log
 from twitter.common.dirutil import chmod_plus_x, safe_mkdtemp
 from twitter.common.log.options import LogOptions
@@ -31,7 +32,7 @@ from apache.thermos.config.loader import ThermosTaskWrapper
 from apache.thermos.core import runner as core
 from apache.thermos.monitoring.monitor import TaskMonitor
 
-from .common.status_checker import ExitState, StatusResult
+from .common.status_checker import StatusResult
 from .common.task_info import mesos_task_instance_from_assigned_task, resolve_ports
 from .common.task_runner import TaskError, TaskRunner, TaskRunnerProvider
 
@@ -41,11 +42,11 @@ from gen.apache.thermos.ttypes import TaskState
 class ThermosTaskRunner(TaskRunner):
   ESCALATION_WAIT = Amount(5, Time.SECONDS)
   EXIT_STATE_MAP = {
-      TaskState.ACTIVE: StatusResult('Runner died while task was active.', ExitState.LOST),
-      TaskState.FAILED: StatusResult('Task failed.', ExitState.FAILED),
-      TaskState.KILLED: StatusResult('Task killed.', ExitState.KILLED),
-      TaskState.LOST: StatusResult('Task lost.', ExitState.LOST),
-      TaskState.SUCCESS: StatusResult('Task finished.', ExitState.FINISHED),
+      TaskState.ACTIVE: StatusResult('Runner died while task was active.', mesos_pb2.TASK_LOST),
+      TaskState.FAILED: StatusResult('Task failed.', mesos_pb2.TASK_FAILED),
+      TaskState.KILLED: StatusResult('Task killed.', mesos_pb2.TASK_KILLED),
+      TaskState.LOST: StatusResult('Task lost.', mesos_pb2.TASK_LOST),
+      TaskState.SUCCESS: StatusResult('Task finished.', mesos_pb2.TASK_FINISHED),
   }
   MAX_WAIT = Amount(1, Time.MINUTES)
   PEX_NAME = 'thermos_runner.pex'

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/BUILD b/src/test/python/apache/aurora/executor/BUILD
index 3152ec0..4d43e25 100644
--- a/src/test/python/apache/aurora/executor/BUILD
+++ b/src/test/python/apache/aurora/executor/BUILD
@@ -15,9 +15,7 @@
 python_test_suite(name = 'all',
   dependencies = [
     pants(':executor-small'),
-
-    # TODO(jfarrell): AURORA-14 for executor_builds, gc_executor and thermos_executor
-    # pants(':executor-large'),
+    pants(':executor-large'),
   ]
 )
 
@@ -25,8 +23,10 @@ python_test_suite(name = 'all',
 python_test_suite(
   name = 'executor-small',
   dependencies = [
+    pants(':executor_base'),
     pants(':executor_detector'),
     pants(':executor_vars'),
+    pants(':status_manager'),
     pants(':thermos_task_runner'),
     pants('src/test/python/apache/aurora/executor/common:all'),
   ],
@@ -36,7 +36,8 @@ python_test_suite(
 python_test_suite(
   name = 'executor-large',
   dependencies = [
-    pants(':executor_builds'),
+    # TODO(jfarrell): AURORA-14 for executor_builds
+    #pants(':executor_builds'),
     pants(':gc_executor'),
     pants(':thermos_executor'),
   ]
@@ -93,17 +94,37 @@ python_tests(name = 'thermos_executor',
 python_tests(name = 'thermos_task_runner',
   sources = ['test_thermos_task_runner.py'],
   dependencies = [
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:twitter.common.contextutil'),
     pants('3rdparty/python:twitter.common.dirutil'),
     pants('3rdparty/python:twitter.common.log'),
     pants('3rdparty/python:twitter.common.quantity'),
     pants('src/main/python/apache/aurora/config:schema'),
     pants('src/main/python/apache/aurora/executor/common:sandbox'),
-    pants('src/main/python/apache/aurora/executor/common:status_checker'),
     pants('src/main/python/apache/aurora/executor:thermos_task_runner'),
   ]
 )
 
+python_tests(name = 'executor_base',
+  sources = ['test_executor_base.py'],
+  dependencies = [
+    pants('3rdparty/python:mesos.interface'),
+    pants('3rdparty/python:mock'),
+    pants('3rdparty/python:twitter.common.log'),
+    pants('src/main/python/apache/aurora/executor:executor_base'),
+  ],
+)
+
+python_tests(name = 'status_manager',
+  sources = ['test_status_manager.py'],
+  dependencies = [
+    pants('3rdparty/python:mesos.interface'),
+    pants('3rdparty/python:mock'),
+    pants('src/main/python/apache/aurora/executor:status_manager'),
+    pants('src/main/python/apache/aurora/executor/common:status_checker'),
+  ],
+)
+
 python_tests(name = 'executor_vars',
   sources = ['test_executor_vars.py'],
   dependencies = [

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/common/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/common/BUILD b/src/test/python/apache/aurora/executor/common/BUILD
index 6316c7f..3229fac 100644
--- a/src/test/python/apache/aurora/executor/common/BUILD
+++ b/src/test/python/apache/aurora/executor/common/BUILD
@@ -17,6 +17,7 @@ python_test_suite(
   dependencies = [
     pants(':announcer'),
     pants(':directory_sandbox'),
+    pants(':executor_timeout'),
     pants(':health_checker'),
     pants(':status_checker'),
     pants(':task_info'),
@@ -48,6 +49,7 @@ python_tests(
   name = 'health_checker',
   sources = ['test_health_checker.py'],
   dependencies = [
+    pants('3rdparty/python:mesos.interface'),
     pants('3rdparty/python:mox'),
     pants('3rdparty/python:twitter.common.testing'),
     pants('src/main/python/apache/aurora/executor/common:health_checker'),
@@ -58,11 +60,22 @@ python_tests(
   name = 'status_checker',
   sources = ['test_status_checker.py'],
   dependencies = [
+    pants('3rdparty/python:mesos.interface'),
     pants('src/main/python/apache/aurora/executor/common:status_checker'),
   ]
 )
 
 python_tests(
+  name = 'kill_manager',
+  sources = ['test_kill_manager.py'],
+  dependencies = [
+    pants('3rdparty/python:mesos.interface'),
+    pants('src/main/python/apache/aurora/executor/common:kill_manager'),
+    pants('src/main/python/apache/aurora/executor/common:status_checker'),
+  ],
+)
+
+python_tests(
   name = 'task_info',
   sources = ['test_task_info.py'],
   dependencies = [
@@ -71,3 +84,14 @@ python_tests(
     pants('src/main/thrift/org/apache/aurora/gen:py-thrift'),
   ]
 )
+
+python_tests(
+  name = 'executor_timeout',
+  sources = ['test_executor_timeout.py'],
+  dependencies = [
+    pants('3rdparty/python:mesos.interface'),
+    pants('3rdparty/python:mock'),
+    pants('3rdparty/python:twitter.common.quantity'),
+    pants('src/main/python/apache/aurora/executor/common:executor_timeout'),
+  ],
+)

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/common/test_executor_timeout.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/common/test_executor_timeout.py b/src/test/python/apache/aurora/executor/common/test_executor_timeout.py
new file mode 100644
index 0000000..ce4cfc8
--- /dev/null
+++ b/src/test/python/apache/aurora/executor/common/test_executor_timeout.py
@@ -0,0 +1,39 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from threading import Event
+from unittest import TestCase
+
+import mock
+from mesos.interface import ExecutorDriver
+from twitter.common.quantity import Amount, Time
+
+from apache.aurora.executor.common.executor_timeout import ExecutorTimeout
+
+
+class TestExecutorTimeout(TestCase):
+  def test_run(self):
+    event = Event()
+    mock_driver = mock.Mock(spec=ExecutorDriver)
+    event.set()
+    executor_timeout = ExecutorTimeout(event, mock_driver, timeout=Amount(0, Time.SECONDS))
+    executor_timeout.run()
+    assert mock_driver.stop.call_count == 0
+
+  def test_run_timeout(self):
+    event = Event()
+    mock_driver = mock.Mock(spec=ExecutorDriver)
+    executor_timeout = ExecutorTimeout(event, mock_driver, timeout=Amount(0, Time.SECONDS))
+    executor_timeout.run()
+    mock_driver.stop.assert_called_once_with()

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/common/test_health_checker.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/common/test_health_checker.py b/src/test/python/apache/aurora/executor/common/test_health_checker.py
index baeaba2..490d4c8 100644
--- a/src/test/python/apache/aurora/executor/common/test_health_checker.py
+++ b/src/test/python/apache/aurora/executor/common/test_health_checker.py
@@ -16,6 +16,7 @@ import time
 import unittest
 
 import mox
+from mesos.interface.mesos_pb2 import TaskState
 from twitter.common.testing.clock import ThreadedClock
 
 from apache.aurora.executor.common.health_checker import HealthCheckerThread
@@ -54,7 +55,7 @@ class TestHealthChecker(unittest.TestCase):
     assert hct.status is None
     self._clock.tick(5)
     thread_yield()
-    assert hct.status is not None
+    assert hct.status.status == TaskState.Value('TASK_FAILED')
     hct.stop()
     self.verify()
 
@@ -67,7 +68,7 @@ class TestHealthChecker(unittest.TestCase):
       initial_interval_secs=0,
       clock=self._clock)
     hct.start()
-    assert hct.status is not None
+    assert hct.status.status == TaskState.Value('TASK_FAILED')
     hct.stop()
     self.verify()
 
@@ -102,6 +103,6 @@ class TestHealthChecker(unittest.TestCase):
     assert hct.status is None
     self._clock.tick(interval_secs)
     thread_yield()
-    assert hct.status is not None
+    assert hct.status.status == TaskState.Value('TASK_FAILED')
     hct.stop()
     self.verify()

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/common/test_kill_manager.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/common/test_kill_manager.py b/src/test/python/apache/aurora/executor/common/test_kill_manager.py
new file mode 100644
index 0000000..f3d43af
--- /dev/null
+++ b/src/test/python/apache/aurora/executor/common/test_kill_manager.py
@@ -0,0 +1,42 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from unittest import TestCase
+
+from mesos.interface import mesos_pb2
+
+from apache.aurora.executor.common.kill_manager import KillManager
+
+
+class TestKillManager(TestCase):
+  def setUp(self):
+    self.kill_manager = KillManager()
+
+  def test_status(self):
+    reason = 'reason'
+    assert self.kill_manager.status is None
+    self.kill_manager.kill(reason)
+    result = self.kill_manager.status
+    assert result.reason == reason
+    assert result.status == mesos_pb2.TaskState.Value('TASK_KILLED')
+
+  def test_name(self):
+    assert self.kill_manager.name() == 'kill_manager'
+
+  def test_kill(self):
+    reason = 'reason'
+    assert self.kill_manager._killed is False
+    self.kill_manager.kill(reason)
+    assert self.kill_manager._reason == reason
+    assert self.kill_manager._killed is True

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/common/test_status_checker.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/common/test_status_checker.py b/src/test/python/apache/aurora/executor/common/test_status_checker.py
index 6ca4fd4..5be1981 100644
--- a/src/test/python/apache/aurora/executor/common/test_status_checker.py
+++ b/src/test/python/apache/aurora/executor/common/test_status_checker.py
@@ -14,9 +14,10 @@
 
 import threading
 
+from mesos.interface.mesos_pb2 import TaskState
+
 from apache.aurora.executor.common.status_checker import (
     ChainedStatusChecker,
-    ExitState,
     Healthy,
     StatusChecker,
     StatusResult
@@ -61,11 +62,11 @@ def test_chained_health_interface():
     assert si.started.is_set()
 
   assert chained_si.status is None
-  reason = StatusResult('derp', ExitState.FAILED)
+  reason = StatusResult('derp', TaskState.Value('TASK_FAILED'))
   si2.set_status(reason)
   assert chained_si.status == reason
   assert chained_si.status.reason == 'derp'
-  assert chained_si.status.status == ExitState.FAILED
+  assert TaskState.Name(chained_si.status.status) == 'TASK_FAILED'
 
   for si in (si1, si2):
     assert not si.stopped.is_set()

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/test_executor_base.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/test_executor_base.py b/src/test/python/apache/aurora/executor/test_executor_base.py
new file mode 100644
index 0000000..e4135ce
--- /dev/null
+++ b/src/test/python/apache/aurora/executor/test_executor_base.py
@@ -0,0 +1,79 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from unittest import TestCase
+
+import mock
+from mesos.interface import ExecutorDriver, mesos_pb2
+from twitter.common import log
+
+from apache.aurora.executor.executor_base import ExecutorBase
+
+
+class TestExecutorBase(TestCase):
+  def setUp(self):
+    self.executor_base = ExecutorBase()
+
+  def test_status_is_terminal(self):
+    for terminal_status in ExecutorBase.TERMINAL_STATES:
+      assert ExecutorBase.status_is_terminal(terminal_status)
+    assert not ExecutorBase.status_is_terminal('RUNNING')
+    assert not ExecutorBase.status_is_terminal('BASSCANNON')
+
+  @mock.patch('twitter.common.log.info', spec=log.info)
+  def test_log(self, mock_info):
+    test_message = 'testing'
+    self.executor_base.log(test_message)
+    mock_info.assert_called_once_with('Executor [None]: %s' % test_message)
+
+  def test_registered(self):
+    driver = ExecutorDriver()
+    executor_info = mesos_pb2.ExecutorInfo()
+    framework_info = mesos_pb2.FrameworkInfo()
+    slave_info = mesos_pb2.SlaveInfo()
+
+    self.executor_base.registered(driver, executor_info, framework_info, slave_info)
+    assert self.executor_base._driver == driver
+    assert self.executor_base._executor_info == executor_info
+    assert self.executor_base._framework_info == framework_info
+    assert self.executor_base._slave_info == slave_info
+
+  def test_reregistered(self):
+    driver = ExecutorDriver()
+    slave_info = mesos_pb2.SlaveInfo()
+    self.executor_base.reregistered(driver, slave_info)
+
+  def test_disconnected(self):
+    driver = ExecutorDriver()
+    self.executor_base.disconnected(driver)
+
+  @mock.patch('mesos.interface.mesos_pb2.TaskStatus', spec=mesos_pb2.TaskStatus)
+  def test_send_update(self, MockTaskStatus):
+    driver = mock.Mock(ExecutorDriver)
+    task_id = 'task_id'
+    state = mesos_pb2.TASK_RUNNING
+    message = 'test_message'
+    self.executor_base.send_update(driver, task_id, state, message)
+    driver.sendStatusUpdate.assert_called_once_with(MockTaskStatus.return_value)
+    assert MockTaskStatus.return_value.state == state
+    assert MockTaskStatus.return_value.task_id.value == task_id
+    assert MockTaskStatus.return_value.message == message
+
+  def test_frameworkMessage(self):
+    driver = ExecutorDriver()
+    self.executor_base.frameworkMessage(driver, 'test_message')
+
+  def test_error(self):
+    driver = ExecutorDriver()
+    self.executor_base.error(driver, 'message')

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/test_gc_executor.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/test_gc_executor.py b/src/test/python/apache/aurora/executor/test_gc_executor.py
index 0b2278a..e9bc7eb 100644
--- a/src/test/python/apache/aurora/executor/test_gc_executor.py
+++ b/src/test/python/apache/aurora/executor/test_gc_executor.py
@@ -22,8 +22,8 @@ import unittest
 from collections import namedtuple
 from itertools import product
 
-import mesos_pb2 as mesos
 import mock
+from mesos.interface import mesos_pb2
 from thrift.TSerialization import deserialize as thrift_deserialize
 from thrift.TSerialization import serialize as thrift_serialize
 from twitter.common.concurrent import deadline, Timeout
@@ -113,7 +113,7 @@ class ProxyDriver(object):
 
 
 def serialize_art(art, task_id=TASK_ID):
-  td = mesos.TaskInfo()
+  td = mesos_pb2.TaskInfo()
   td.slave_id.value = 'ignore_me'
   td.task_id.value = task_id
   td.data = thrift_serialize(art)
@@ -333,7 +333,7 @@ def run_gc_with(active_executors, retained_tasks, lose=False):
   assert len(proxy_driver.updates) >= 1
   if not lose:  # if the task is lost it will be cleaned out of band (by clean_orphans),
                 # so we don't care when the GC task actually finishes
-    assert proxy_driver.updates[-1][0] == mesos.TASK_FINISHED
+    assert proxy_driver.updates[-1][0] == mesos_pb2.TASK_FINISHED
     assert proxy_driver.updates[-1][1] == TASK_ID
   return executor, proxy_driver
 
@@ -345,7 +345,7 @@ def test_gc_with_loss():
   assert len(executor.gcs) == len(FINISHED_TASKS)
   assert len(proxy_driver.messages) == 0
   assert len(proxy_driver.updates) >= 1
-  assert StatusUpdate(mesos.TASK_LOST, ACTIVE_TASKS[0]) in proxy_driver.updates
+  assert StatusUpdate(mesos_pb2.TASK_LOST, ACTIVE_TASKS[0]) in proxy_driver.updates
 
 
 def test_gc_with_starting_task():
@@ -464,7 +464,7 @@ def test_gc_multiple_launchtasks():
     assert len(executor._gc_task_queue) == 1
   assert not proxy_driver.stopped.is_set()
   assert len(proxy_driver.updates) >= 1
-  assert StatusUpdate(mesos.TASK_FINISHED, TASK2) in proxy_driver.updates
+  assert StatusUpdate(mesos_pb2.TASK_FINISHED, TASK2) in proxy_driver.updates
 
 
 def test_gc_shutdown():
@@ -497,7 +497,7 @@ def test_gc_shutdown_queued():
   proxy_driver.stopped.wait(timeout=1.0)
   assert proxy_driver.stopped.is_set()
   assert len(proxy_driver.updates) == 1
-  assert proxy_driver.updates[-1][0] == mesos.TASK_FINISHED
+  assert proxy_driver.updates[-1][0] == mesos_pb2.TASK_FINISHED
   assert proxy_driver.updates[-1][1] == TASK2_ID
 
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/test_status_manager.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/test_status_manager.py b/src/test/python/apache/aurora/executor/test_status_manager.py
new file mode 100644
index 0000000..8a0d48b
--- /dev/null
+++ b/src/test/python/apache/aurora/executor/test_status_manager.py
@@ -0,0 +1,50 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import time
+from unittest import TestCase
+
+import mock
+from mesos.interface.mesos_pb2 import TaskState
+
+from apache.aurora.executor.common.status_checker import StatusChecker
+from apache.aurora.executor.status_manager import StatusManager
+
+
+class FakeStatusChecker(StatusChecker):
+  def __init__(self):
+    self.call_count = 0
+
+  @property
+  def status(self):
+    if self.call_count == 2:
+      return TaskState.Value('TASK_KILLED')
+    self.call_count += 1
+    return None
+
+
+class TestStatusManager(TestCase):
+  def setUp(self):
+    self.callback_called = False
+
+  def test_run(self):
+    checker = FakeStatusChecker()
+    def callback(result):
+      assert result == TaskState.Value('TASK_KILLED')
+      self.callback_called = True
+    mock_time = mock.Mock(spec=time)
+    status_manager = StatusManager(checker, callback, mock_time)
+    status_manager.run()
+    assert mock_time.sleep.call_count == 2
+    assert self.callback_called is True

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/test_thermos_executor.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/test_thermos_executor.py b/src/test/python/apache/aurora/executor/test_thermos_executor.py
index 55747a1..f6ca4df 100644
--- a/src/test/python/apache/aurora/executor/test_thermos_executor.py
+++ b/src/test/python/apache/aurora/executor/test_thermos_executor.py
@@ -22,7 +22,7 @@ import time
 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
 from collections import defaultdict
 
-import mesos_pb2 as mesos_pb
+from mesos.interface import mesos_pb2
 from thrift.TSerialization import serialize
 from twitter.common import log
 from twitter.common.contextutil import temporary_dir
@@ -140,7 +140,7 @@ def make_task(thermos_config, assigned_ports={}, **kw):
           owner=Identity(role=role, user=role)),
       assignedPorts=assigned_ports,
       **kw)
-  td = mesos_pb.TaskInfo()
+  td = mesos_pb2.TaskInfo()
   td.task_id.value = task_id
   td.name = thermos_config.task().name().get()
   td.data = serialize(at)
@@ -210,8 +210,8 @@ def make_executor(
   updates = proxy_driver.method_calls['sendStatusUpdate']
   assert len(updates) == 2
   status_updates = [arg_tuple[0][0] for arg_tuple in updates]
-  assert status_updates[0].state == mesos_pb.TASK_STARTING
-  assert status_updates[1].state == mesos_pb.TASK_RUNNING
+  assert status_updates[0].state == mesos_pb2.TASK_STARTING
+  assert status_updates[1].state == mesos_pb2.TASK_RUNNING
 
   # wait for the runner to bind to a task
   while True:
@@ -297,9 +297,9 @@ class TestThermosExecutor(object):
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
     status_updates = [arg_tuple[0][0] for arg_tuple in updates]
-    assert status_updates[0].state == mesos_pb.TASK_STARTING
-    assert status_updates[1].state == mesos_pb.TASK_RUNNING
-    assert status_updates[2].state == mesos_pb.TASK_FINISHED
+    assert status_updates[0].state == mesos_pb2.TASK_STARTING
+    assert status_updates[1].state == mesos_pb2.TASK_RUNNING
+    assert status_updates[2].state == mesos_pb2.TASK_FINISHED
 
   def test_basic_as_job(self):
     proxy_driver = ProxyDriver()
@@ -321,9 +321,9 @@ class TestThermosExecutor(object):
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
     status_updates = [arg_tuple[0][0] for arg_tuple in updates]
-    assert status_updates[0].state == mesos_pb.TASK_STARTING
-    assert status_updates[1].state == mesos_pb.TASK_RUNNING
-    assert status_updates[2].state == mesos_pb.TASK_FINISHED
+    assert status_updates[0].state == mesos_pb2.TASK_STARTING
+    assert status_updates[1].state == mesos_pb2.TASK_RUNNING
+    assert status_updates[2].state == mesos_pb2.TASK_FINISHED
 
   def test_runner_disappears(self):
     proxy_driver = ProxyDriver()
@@ -339,7 +339,7 @@ class TestThermosExecutor(object):
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
-    assert updates[-1][0][0].state == mesos_pb.TASK_LOST
+    assert updates[-1][0][0].state == mesos_pb2.TASK_LOST
 
   def test_task_killed(self):
     proxy_driver = ProxyDriver()
@@ -351,7 +351,7 @@ class TestThermosExecutor(object):
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
-    assert updates[-1][0][0].state == mesos_pb.TASK_KILLED
+    assert updates[-1][0][0].state == mesos_pb2.TASK_KILLED
 
   def test_killTask(self):  # noqa
     proxy_driver = ProxyDriver()
@@ -359,13 +359,13 @@ class TestThermosExecutor(object):
     with temporary_dir() as checkpoint_root:
       _, executor = make_executor(proxy_driver, checkpoint_root, SLEEP60_MTI)
       # send two, expect at most one delivered
-      executor.killTask(proxy_driver, mesos_pb.TaskID(value='sleep60-001'))
-      executor.killTask(proxy_driver, mesos_pb.TaskID(value='sleep60-001'))
+      executor.killTask(proxy_driver, mesos_pb2.TaskID(value='sleep60-001'))
+      executor.killTask(proxy_driver, mesos_pb2.TaskID(value='sleep60-001'))
       executor.terminated.wait()
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
-    assert updates[-1][0][0].state == mesos_pb.TASK_KILLED
+    assert updates[-1][0][0].state == mesos_pb2.TASK_KILLED
 
   def test_shutdown(self):
     proxy_driver = ProxyDriver()
@@ -377,7 +377,7 @@ class TestThermosExecutor(object):
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
-    assert updates[-1][0][0].state == mesos_pb.TASK_KILLED
+    assert updates[-1][0][0].state == mesos_pb2.TASK_KILLED
 
   def test_task_lost(self):
     proxy_driver = ProxyDriver()
@@ -389,7 +389,7 @@ class TestThermosExecutor(object):
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
-    assert updates[-1][0][0].state == mesos_pb.TASK_LOST
+    assert updates[-1][0][0].state == mesos_pb2.TASK_LOST
 
   def test_task_health_failed(self):
     proxy_driver = ProxyDriver()
@@ -407,7 +407,7 @@ class TestThermosExecutor(object):
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
-    assert updates[-1][0][0].state == mesos_pb.TASK_FAILED
+    assert updates[-1][0][0].state == mesos_pb2.TASK_FAILED
 
   def test_task_health_ok(self):
     proxy_driver = ProxyDriver()
@@ -424,7 +424,7 @@ class TestThermosExecutor(object):
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 3
-    assert updates[-1][0][0].state == mesos_pb.TASK_FINISHED
+    assert updates[-1][0][0].state == mesos_pb2.TASK_FINISHED
 
   def test_failing_runner_start(self):
     proxy_driver = ProxyDriver()
@@ -438,7 +438,7 @@ class TestThermosExecutor(object):
       proxy_driver.wait_stopped()
 
       updates = proxy_driver.method_calls['sendStatusUpdate']
-      assert updates[-1][0][0].state == mesos_pb.TASK_FAILED
+      assert updates[-1][0][0].state == mesos_pb2.TASK_FAILED
 
   def test_failing_runner_initialize(self):
     proxy_driver = ProxyDriver()
@@ -451,7 +451,7 @@ class TestThermosExecutor(object):
       proxy_driver.wait_stopped()
 
       updates = proxy_driver.method_calls['sendStatusUpdate']
-      assert updates[-1][0][0].state == mesos_pb.TASK_FAILED
+      assert updates[-1][0][0].state == mesos_pb2.TASK_FAILED
 
   def test_slow_runner_initialize(self):
     proxy_driver = ProxyDriver()
@@ -468,7 +468,7 @@ class TestThermosExecutor(object):
 
       updates = proxy_driver.method_calls['sendStatusUpdate']
       assert len(updates) == 2
-      assert updates[-1][0][0].state == mesos_pb.TASK_FAILED
+      assert updates[-1][0][0].state == mesos_pb2.TASK_FAILED
 
       te._sandbox._init_start.set()
 
@@ -483,7 +483,7 @@ class TestThermosExecutor(object):
           sandbox_provider=SlowSandboxProvider)
       te.launchTask(proxy_driver, task)
       te.sandbox_initialized.wait()
-      te.killTask(proxy_driver, mesos_pb.TaskID(value=task.task_id.value))
+      te.killTask(proxy_driver, mesos_pb2.TaskID(value=task.task_id.value))
       assert te.runner_aborted.is_set()
       assert not te.sandbox_created.is_set()
 
@@ -502,13 +502,13 @@ class TestThermosExecutor(object):
 
       updates = proxy_driver.method_calls['sendStatusUpdate']
       assert len(updates) == 2
-      assert updates[-1][0][0].state == mesos_pb.TASK_KILLED
+      assert updates[-1][0][0].state == mesos_pb2.TASK_KILLED
 
   def test_launchTask_deserialization_fail(self):  # noqa
     proxy_driver = ProxyDriver()
 
     role = getpass.getuser()
-    task_info = mesos_pb.TaskInfo()
+    task_info = mesos_pb2.TaskInfo()
     task_info.name = task_info.task_id.value = 'broken'
     task_info.data = serialize(
         AssignedTask(
@@ -524,8 +524,8 @@ class TestThermosExecutor(object):
 
     updates = proxy_driver.method_calls['sendStatusUpdate']
     assert len(updates) == 2
-    assert updates[0][0][0].state == mesos_pb.TASK_STARTING
-    assert updates[1][0][0].state == mesos_pb.TASK_FAILED
+    assert updates[0][0][0].state == mesos_pb2.TASK_STARTING
+    assert updates[1][0][0].state == mesos_pb2.TASK_FAILED
 
 
 def test_waiting_executor():

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/467bc560/src/test/python/apache/aurora/executor/test_thermos_task_runner.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/test_thermos_task_runner.py b/src/test/python/apache/aurora/executor/test_thermos_task_runner.py
index f7af70f..8e4042b 100644
--- a/src/test/python/apache/aurora/executor/test_thermos_task_runner.py
+++ b/src/test/python/apache/aurora/executor/test_thermos_task_runner.py
@@ -20,6 +20,7 @@ import sys
 import tempfile
 import time
 
+from mesos.interface.mesos_pb2 import TaskState
 from twitter.common import log
 from twitter.common.contextutil import temporary_dir
 from twitter.common.dirutil import safe_rmtree
@@ -28,7 +29,6 @@ from twitter.common.quantity import Amount, Time
 
 from apache.aurora.config.schema.base import MB, MesosTaskInstance, Process, Resources, Task
 from apache.aurora.executor.common.sandbox import DirectorySandbox
-from apache.aurora.executor.common.status_checker import ExitState
 from apache.aurora.executor.thermos_task_runner import ThermosTaskRunner
 
 TASK = MesosTaskInstance(
@@ -106,13 +106,13 @@ class TestThermosTaskRunnerIntegration(object):
       self.run_to_completion(task_runner)
 
       assert task_runner.status is not None
-      assert task_runner.status.status == ExitState.FINISHED
+      assert TaskState.Name(task_runner.status.status) == 'TASK_FINISHED'
 
       # no-op
       task_runner.stop()
 
       assert task_runner.status is not None
-      assert task_runner.status.status == ExitState.FINISHED
+      assert TaskState.Name(task_runner.status.status) == 'TASK_FINISHED'
 
   def test_integration_failed(self):
     with self.yield_sleepy(ThermosTaskRunner, sleep=0, exit_code=1) as task_runner:
@@ -122,13 +122,13 @@ class TestThermosTaskRunnerIntegration(object):
       self.run_to_completion(task_runner)
 
       assert task_runner.status is not None
-      assert task_runner.status.status == ExitState.FAILED
+      assert TaskState.Name(task_runner.status.status) == 'TASK_FAILED'
 
       # no-op
       task_runner.stop()
 
       assert task_runner.status is not None
-      assert task_runner.status.status == ExitState.FAILED
+      assert TaskState.Name(task_runner.status.status) == 'TASK_FAILED'
 
   def test_integration_stop(self):
     with self.yield_sleepy(ThermosTaskRunner, sleep=1000, exit_code=0) as task_runner:
@@ -140,7 +140,7 @@ class TestThermosTaskRunnerIntegration(object):
       task_runner.stop()
 
       assert task_runner.status is not None
-      assert task_runner.status.status == ExitState.KILLED
+      assert TaskState.Name(task_runner.status.status) == 'TASK_KILLED'
 
   def test_integration_lose(self):
     with self.yield_sleepy(ThermosTaskRunner, sleep=1000, exit_code=0) as task_runner:
@@ -153,7 +153,7 @@ class TestThermosTaskRunnerIntegration(object):
       task_runner.stop()
 
       assert task_runner.status is not None
-      assert task_runner.status.status == ExitState.LOST
+      assert TaskState.Name(task_runner.status.status) == 'TASK_LOST'
 
   def test_integration_quitquitquit(self):
     ignorant_script = ';'.join([
@@ -173,4 +173,4 @@ class TestThermosTaskRunnerIntegration(object):
       task_runner.forked.wait()
       task_runner.stop(timeout=Amount(5, Time.SECONDS))
       assert task_runner.status is not None
-      assert task_runner.status.status == ExitState.KILLED
+      assert TaskState.Name(task_runner.status.status) == 'TASK_KILLED'


Mime
View raw message