Repository: aurora
Updated Branches:
  refs/heads/master 95daf471f -> 0b025a7d0


Create ExecutorSettings closer to command line arguments.

This is prep work for https://issues.apache.org/jira/browse/AURORA-1376

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


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

Branch: refs/heads/master
Commit: 0b025a7d0e83f651724d66908c1956e11e90c9b7
Parents: 95daf47
Author: Bill Farner <[email protected]>
Authored: Wed Nov 11 08:57:26 2015 -0800
Committer: Bill Farner <[email protected]>
Committed: Wed Nov 11 08:57:26 2015 -0800

----------------------------------------------------------------------
 config/legacy_untested_classes.txt              |   1 +
 .../aurora/benchmark/SchedulingBenchmarks.java  |   8 +-
 .../aurora/benchmark/StatusUpdateBenchmark.java |   7 +-
 .../apache/aurora/scheduler/ResourceSlot.java   |  80 +++++-----
 .../aurora/scheduler/app/SchedulerMain.java     | 102 ++++++++++---
 .../aurora/scheduler/base/CommandUtil.java      | 106 --------------
 .../scheduler/filter/SchedulingFilterImpl.java  |   2 +-
 .../aurora/scheduler/mesos/ExecutorConfig.java  |  70 +++++++++
 .../scheduler/mesos/ExecutorSettings.java       | 129 ++++------------
 .../aurora/scheduler/mesos/Executors.java       |  29 ++++
 .../scheduler/mesos/MesosTaskFactory.java       |  78 ++--------
 .../scheduler/mesos/TestExecutorSettings.java   |  74 ++++++++++
 .../preemptor/PreemptionVictimFilter.java       |   2 +-
 .../aurora/scheduler/ResourceSlotTest.java      |  14 --
 .../aurora/scheduler/app/SchedulerIT.java       |   7 +-
 .../aurora/scheduler/base/CommandUtilTest.java  |  98 -------------
 .../events/NotifyingSchedulingFilterTest.java   |   3 +-
 .../mesos/MesosTaskFactoryImplTest.java         | 146 +++++--------------
 .../aurora/scheduler/mesos/TaskExecutors.java   |  16 +-
 .../preemptor/PreemptionVictimFilterTest.java   |   2 +-
 20 files changed, 397 insertions(+), 577 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/config/legacy_untested_classes.txt
----------------------------------------------------------------------
diff --git a/config/legacy_untested_classes.txt 
b/config/legacy_untested_classes.txt
index b77265c..aac822b 100644
--- a/config/legacy_untested_classes.txt
+++ b/config/legacy_untested_classes.txt
@@ -6,6 +6,7 @@ 
org/apache/aurora/auth/UnsecureAuthModule$UnsecureCapabilityValidator$2
 org/apache/aurora/auth/UnsecureAuthModule$UnsecureSessionValidator
 org/apache/aurora/scheduler/app/SchedulerMain$1
 org/apache/aurora/scheduler/app/SchedulerMain$2
+org/apache/aurora/scheduler/app/SchedulerMain$2$1
 org/apache/aurora/scheduler/app/SchedulerMain$3
 org/apache/aurora/scheduler/app/SchedulerMain$4
 org/apache/aurora/scheduler/async/OfferQueue$OfferQueueImpl$2

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java 
b/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
index c210c0d..b4ca01b 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
@@ -44,6 +44,7 @@ import org.apache.aurora.scheduler.filter.SchedulingFilter;
 import org.apache.aurora.scheduler.filter.SchedulingFilterImpl;
 import org.apache.aurora.scheduler.mesos.Driver;
 import org.apache.aurora.scheduler.mesos.ExecutorSettings;
+import org.apache.aurora.scheduler.mesos.TestExecutorSettings;
 import org.apache.aurora.scheduler.offers.OfferManager;
 import org.apache.aurora.scheduler.preemptor.BiCache;
 import org.apache.aurora.scheduler.preemptor.ClusterStateImpl;
@@ -148,12 +149,7 @@ public class SchedulingBenchmarks {
               
bind(TaskIdGenerator.class).to(TaskIdGenerator.TaskIdGeneratorImpl.class);
               bind(SchedulingFilter.class).to(SchedulingFilterImpl.class);
               bind(SchedulingFilterImpl.class).in(Singleton.class);
-              bind(ExecutorSettings.class)
-                  .toInstance(ExecutorSettings.newBuilder()
-                      .setExecutorPath("/executor/thermos")
-                      .setThermosObserverRoot("/var/run/thermos")
-                      .build());
-
+              
bind(ExecutorSettings.class).toInstance(TestExecutorSettings.THERMOS_EXECUTOR);
               bind(Storage.class).toInstance(storage);
               bind(Driver.class).toInstance(new FakeDriver());
               bind(RescheduleCalculator.class).toInstance(new 
FakeRescheduleCalculator());

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
----------------------------------------------------------------------
diff --git 
a/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java 
b/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
index 197184b..6236a53 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
@@ -60,6 +60,7 @@ import org.apache.aurora.scheduler.mesos.DriverFactory;
 import org.apache.aurora.scheduler.mesos.DriverSettings;
 import org.apache.aurora.scheduler.mesos.ExecutorSettings;
 import org.apache.aurora.scheduler.mesos.MesosSchedulerImpl;
+import org.apache.aurora.scheduler.mesos.TestExecutorSettings;
 import org.apache.aurora.scheduler.offers.OfferManager;
 import org.apache.aurora.scheduler.preemptor.ClusterStateImpl;
 import org.apache.aurora.scheduler.scheduling.RescheduleCalculator;
@@ -228,11 +229,7 @@ public class StatusUpdateBenchmark {
                         .build()));
             bind(RescheduleCalculator.class).toInstance(new 
FakeRescheduleCalculator());
             bind(Clock.class).toInstance(new FakeClock());
-            bind(ExecutorSettings.class)
-                .toInstance(ExecutorSettings.newBuilder()
-                    .setExecutorPath("/executor/thermos")
-                    .setThermosObserverRoot("/var/run/thermos")
-                    .build());
+            
bind(ExecutorSettings.class).toInstance(TestExecutorSettings.THERMOS_EXECUTOR);
             bind(StatsProvider.class).toInstance(new FakeStatsProvider());
             bind(EventSink.class).toInstance(new EventSink() {
               @Override

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java 
b/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
index c665c32..7003b2f 100644
--- a/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
+++ b/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
@@ -15,13 +15,13 @@ package org.apache.aurora.scheduler;
 
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -30,16 +30,17 @@ import com.google.common.collect.Range;
 
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Data;
-
 import org.apache.aurora.scheduler.base.Numbers;
-import org.apache.aurora.scheduler.mesos.ExecutorSettings;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 import org.apache.mesos.Protos;
+import org.apache.mesos.Protos.ExecutorInfo;
+import org.apache.mesos.Protos.Resource;
+import org.apache.mesos.Protos.Resource.Builder;
+import org.apache.mesos.Protos.TaskInfo;
 
 import static java.util.Objects.requireNonNull;
 
 import static org.apache.aurora.common.quantity.Data.BYTES;
-
 import static org.apache.aurora.scheduler.ResourceType.CPUS;
 import static org.apache.aurora.scheduler.ResourceType.DISK_MB;
 import static org.apache.aurora.scheduler.ResourceType.PORTS;
@@ -74,17 +75,6 @@ public final class ResourceSlot {
   }
 
   /**
-   * Minimum resources required to run Thermos. In the wild Thermos needs 
about 0.01 CPU and
-   * about 170MB (peak usage) of RAM. The RAM requirement has been rounded up 
to a power of 2.
-   */
-  @VisibleForTesting
-  public static final ResourceSlot MIN_THERMOS_RESOURCES = new ResourceSlot(
-      0.01,
-      Amount.of(256L, Data.MB),
-      Amount.of(1L, Data.MB),
-      0);
-
-  /**
    * Extracts the resources required from a task.
    *
    * @param task Task to get resources from.
@@ -120,6 +110,39 @@ public final class ResourceSlot {
   }
 
   /**
+   * Ensures that the revocable setting on the executor and task CPU resources 
match.
+   *
+   * @param task Task to check for resource type alignment.
+   * @return A possibly-modified task, with aligned CPU resource types.
+   */
+  public static TaskInfo matchResourceTypes(TaskInfo task) {
+    TaskInfo.Builder taskBuilder = task.toBuilder();
+
+    Optional<Resource> revocableTaskCpu = 
taskBuilder.getResourcesList().stream()
+        .filter(r -> r.getName().equals(CPUS.getName()))
+        .filter(Resource::hasRevocable)
+        .findFirst();
+    ExecutorInfo.Builder executorBuilder = taskBuilder.getExecutorBuilder();
+
+    Consumer<Builder> matchRevocable = new Consumer<Builder>() {
+      @Override
+      public void accept(Builder builder) {
+        if (revocableTaskCpu.isPresent()) {
+          builder.setRevocable(revocableTaskCpu.get().getRevocable());
+        } else {
+          builder.clearRevocable();
+        }
+      }
+    };
+
+    executorBuilder.getResourcesBuilderList().stream()
+        .filter(r -> r.getName().equals(CPUS.getName()))
+        .forEach(matchRevocable);
+
+    return taskBuilder.build();
+  }
+
+  /**
    * Convenience method for adapting to Mesos resources without applying a 
port range.
    *
    * @see {@link #toResourceList(java.util.Set, TierInfo)}
@@ -131,20 +154,6 @@ public final class ResourceSlot {
   }
 
   /**
-   * Adds executor resource overhead.
-   *
-   * @param executorSettings Executor settings to get executor overhead from.
-   * @return ResourceSlot with overhead applied.
-   */
-  public ResourceSlot withOverhead(ExecutorSettings executorSettings) {
-    // Apply a flat 'tax' of executor overhead resources to the task.
-    ResourceSlot requiredTaskResources = 
add(executorSettings.getExecutorOverhead());
-
-    // Upsize tasks smaller than the minimum resources required to run the 
executor.
-    return maxElements(requiredTaskResources, MIN_THERMOS_RESOURCES);
-  }
-
-  /**
    * Creates a mesos resource of integer ranges.
    *
    * @param resourceType Resource type.
@@ -323,18 +332,17 @@ public final class ResourceSlot {
       int portC = Integer.compare(left.getNumPorts(), right.getNumPorts());
       int cpuC = Double.compare(left.getNumCpus(), right.getNumCpus());
 
-      FluentIterable<Integer> vector =
-          FluentIterable.from(ImmutableList.of(diskC, ramC, portC, cpuC));
+      List<Integer> vector = ImmutableList.of(diskC, ramC, portC, cpuC);
 
-      if (vector.allMatch(IS_ZERO))  {
+      if (vector.stream().allMatch(IS_ZERO))  {
         return 0;
       }
 
-      if (vector.filter(Predicates.not(IS_ZERO)).allMatch(e -> e > 0)) {
+      if (vector.stream().filter(IS_ZERO.negate()).allMatch(e -> e > 0)) {
         return 1;
       }
 
-      if (vector.filter(Predicates.not(IS_ZERO)).allMatch(e -> e < 0)) {
+      if (vector.stream().filter(IS_ZERO.negate()).allMatch(e -> e < 0)) {
         return -1;
       }
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java 
b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
index 99b8744..fb4f0a0 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
@@ -17,16 +17,18 @@ import java.lang.Thread.UncaughtExceptionHandler;
 import java.net.InetSocketAddress;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
+import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
@@ -37,6 +39,7 @@ import com.google.inject.Injector;
 import com.google.inject.Module;
 import com.google.inject.util.Modules;
 
+import org.apache.aurora.GuavaUtils;
 import org.apache.aurora.GuavaUtils.ServiceManagerIface;
 import org.apache.aurora.common.application.Lifecycle;
 import org.apache.aurora.common.args.Arg;
@@ -45,6 +48,7 @@ import 
org.apache.aurora.common.args.ArgScanner.ArgScanException;
 import org.apache.aurora.common.args.CmdLine;
 import org.apache.aurora.common.args.constraints.NotEmpty;
 import org.apache.aurora.common.args.constraints.NotNull;
+import org.apache.aurora.common.base.MorePreconditions;
 import org.apache.aurora.common.inject.Bindings;
 import org.apache.aurora.common.logging.RootLogConfig;
 import org.apache.aurora.common.quantity.Amount;
@@ -56,13 +60,15 @@ import 
org.apache.aurora.common.zookeeper.SingletonService.LeadershipListener;
 import org.apache.aurora.gen.ServerInfo;
 import org.apache.aurora.gen.Volume;
 import org.apache.aurora.scheduler.AppStartup;
-import org.apache.aurora.scheduler.ResourceSlot;
+import org.apache.aurora.scheduler.ResourceType;
 import org.apache.aurora.scheduler.SchedulerLifecycle;
 import org.apache.aurora.scheduler.cron.quartz.CronModule;
 import org.apache.aurora.scheduler.http.HttpService;
 import org.apache.aurora.scheduler.log.mesos.MesosLogStreamModule;
 import org.apache.aurora.scheduler.mesos.CommandLineDriverSettingsModule;
+import org.apache.aurora.scheduler.mesos.ExecutorConfig;
 import org.apache.aurora.scheduler.mesos.ExecutorSettings;
+import org.apache.aurora.scheduler.mesos.Executors;
 import org.apache.aurora.scheduler.mesos.LibMesosLoadingModule;
 import org.apache.aurora.scheduler.stats.StatsModule;
 import org.apache.aurora.scheduler.storage.Storage;
@@ -74,9 +80,18 @@ import 
org.apache.aurora.scheduler.storage.log.SnapshotStoreImpl;
 import 
org.apache.aurora.scheduler.zookeeper.guice.client.ZooKeeperClientModule;
 import 
org.apache.aurora.scheduler.zookeeper.guice.client.ZooKeeperClientModule.ClientConfig;
 import 
org.apache.aurora.scheduler.zookeeper.guice.client.flagged.FlaggedClientConfig;
+import org.apache.mesos.Protos;
+import org.apache.mesos.Protos.CommandInfo;
+import org.apache.mesos.Protos.CommandInfo.URI;
+import org.apache.mesos.Protos.ExecutorInfo;
+import org.apache.mesos.Protos.Resource;
+import org.apache.mesos.Protos.Value.Scalar;
+import org.apache.mesos.Protos.Value.Type;
 
 import static org.apache.aurora.common.logging.RootLogConfig.Configuration;
 import static org.apache.aurora.gen.apiConstants.THRIFT_API_VERSION;
+import static org.apache.aurora.scheduler.ResourceType.CPUS;
+import static org.apache.aurora.scheduler.ResourceType.RAM_MB;
 
 /**
  * Launcher for the aurora scheduler.
@@ -201,6 +216,42 @@ public class SchedulerMain {
         new DbModule.GarbageCollectorModule());
   }
 
+  private static Resource makeResource(ResourceType type, double value) {
+    return Resource.newBuilder()
+        .setType(Type.SCALAR)
+        .setName(type.getName())
+        .setScalar(Scalar.newBuilder().setValue(value))
+        .build();
+  }
+
+  private static String uriBasename(String uri) {
+    int lastSlash = uri.lastIndexOf('/');
+    if (lastSlash == -1) {
+      return uri;
+    } else {
+      String basename = uri.substring(lastSlash + 1);
+      MorePreconditions.checkNotBlank(basename, "URI must not end with a 
slash.");
+
+      return basename;
+    }
+  }
+
+  private static CommandInfo makeExecutorCommand() {
+    Stream<String> resourcesToFetch = Stream.concat(
+        ImmutableList.of(THERMOS_EXECUTOR_PATH.get()).stream(),
+        THERMOS_EXECUTOR_RESOURCES.get().stream());
+
+    return CommandInfo.newBuilder()
+        // Default to the value of $MESOS_SANDBOX if present.  This is 
necessary for docker tasks,
+        // in which case the mesos agent is responsible for setting 
$MESOS_SANDBOX.
+        .setValue("${MESOS_SANDBOX=.}/" + 
uriBasename(THERMOS_EXECUTOR_PATH.get())
+            + " " + 
Optional.ofNullable(THERMOS_EXECUTOR_FLAGS.get()).orElse(""))
+        .addAllUris(resourcesToFetch
+            .map(r -> URI.newBuilder().setValue(r).setExecutable(true).build())
+            .collect(GuavaUtils.toImmutableList()))
+        .build();
+  }
+
   /**
    * Runs the scheduler by including modules configured from command line 
arguments in
    * addition to the provided environment-specific module.
@@ -228,21 +279,38 @@ public class SchedulerMain {
         new AbstractModule() {
           @Override
           protected void configure() {
-            ResourceSlot executorOverhead = new ResourceSlot(
-                EXECUTOR_OVERHEAD_CPUS.get(),
-                EXECUTOR_OVERHEAD_RAM.get(),
-                Amount.of(0L, Data.MB),
-                0);
-
-            bind(ExecutorSettings.class)
-                .toInstance(ExecutorSettings.newBuilder()
-                    .setExecutorPath(THERMOS_EXECUTOR_PATH.get())
-                    .setExecutorResources(THERMOS_EXECUTOR_RESOURCES.get())
-                    .setThermosObserverRoot(THERMOS_OBSERVER_ROOT.get())
-                    
.setExecutorFlags(Optional.fromNullable(THERMOS_EXECUTOR_FLAGS.get()))
-                    .setExecutorOverhead(executorOverhead)
-                    .setGlobalContainerMounts(GLOBAL_CONTAINER_MOUNTS.get())
-                    .build());
+            List<Protos.Volume> volumeMounts =
+                ImmutableList.<Protos.Volume>builder()
+                    .add(Protos.Volume.newBuilder()
+                        .setHostPath(THERMOS_OBSERVER_ROOT.get())
+                        .setContainerPath(THERMOS_OBSERVER_ROOT.get())
+                        .setMode(Protos.Volume.Mode.RW)
+                        .build())
+                    .addAll(Iterables.transform(
+                        GLOBAL_CONTAINER_MOUNTS.get(),
+                        new Function<Volume, Protos.Volume>() {
+                          @Override
+                          public Protos.Volume apply(Volume v) {
+                            return Protos.Volume.newBuilder()
+                                .setHostPath(v.getHostPath())
+                                .setContainerPath(v.getContainerPath())
+                                
.setMode(Protos.Volume.Mode.valueOf(v.getMode().getValue()))
+                                .build();
+                          }
+                        }))
+                .build();
+
+            bind(ExecutorSettings.class).toInstance(new ExecutorSettings(
+                new ExecutorConfig(
+                    ExecutorInfo.newBuilder()
+                        .setName("aurora.task")
+                        // Necessary as executorId is a required field.
+                        .setExecutorId(Executors.PLACEHOLDER_EXECUTOR_ID)
+                        .setCommand(makeExecutorCommand())
+                        .addResources(makeResource(CPUS, 
EXECUTOR_OVERHEAD_CPUS.get()))
+                        .addResources(makeResource(RAM_MB, 
EXECUTOR_OVERHEAD_RAM.get().as(Data.MB)))
+                        .build(),
+                    volumeMounts)));
 
             bind(IServerInfo.class).toInstance(
                 IServerInfo.build(

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/base/CommandUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/base/CommandUtil.java 
b/src/main/java/org/apache/aurora/scheduler/base/CommandUtil.java
deleted file mode 100644
index aa5ce8b..0000000
--- a/src/main/java/org/apache/aurora/scheduler/base/CommandUtil.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * 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.
- */
-package org.apache.aurora.scheduler.base;
-
-import java.util.List;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-
-import org.apache.aurora.common.base.MorePreconditions;
-import org.apache.mesos.Protos.CommandInfo;
-import org.apache.mesos.Protos.CommandInfo.URI;
-
-/**
- * Utility class for constructing {@link CommandInfo} objects given an 
executor URI.
- */
-public final class CommandUtil {
-
-  private static final Function<String, URI> STRING_TO_URI_RESOURCE = new 
Function<String, URI>() {
-    @Override
-    public URI apply(String resource) {
-      return URI.newBuilder().setValue(resource).setExecutable(true).build();
-    }
-  };
-
-  private CommandUtil() {
-    // Utility class.
-  }
-
-  /**
-   * Gets the last part of the path of a URI.
-   *
-   * @param uri URI to parse
-   * @return The last segment of the URI.
-   */
-  public static String uriBasename(String uri) {
-    int lastSlash = uri.lastIndexOf('/');
-    if (lastSlash == -1) {
-      return uri;
-    } else {
-      String basename = uri.substring(lastSlash + 1);
-      MorePreconditions.checkNotBlank(basename, "URI must not end with a 
slash.");
-
-      return basename;
-    }
-  }
-
-  /**
-   * Creates a description of a command that will fetch and execute the given 
URI to an executor
-   * binary.
-   *
-   * @param executorUri A URI to the executor
-   * @param executorResources A list of URIs to be fetched into the sandbox 
with the executor.
-   * @return A populated CommandInfo with correct resources set and command 
set.
-   */
-  public static CommandInfo create(String executorUri, List<String> 
executorResources) {
-    return create(
-        executorUri,
-        executorResources,
-        "./",
-        Optional.absent()).build();
-  }
-
-  /**
-   * Creates a description of a command that will fetch and execute the given 
URI to an executor
-   * binary.
-   *
-   * @param executorUri A URI to the executor
-   * @param executorResources A list of URIs to be fetched into the sandbox 
with the executor.
-   * @param commandBasePath The relative base path of the executor.
-   * @param extraArguments Extra command line arguments to add to the 
generated command.
-   * @return A CommandInfo.Builder populated with resources and a command.
-   */
-  public static CommandInfo.Builder create(
-      String executorUri,
-      List<String> executorResources,
-      String commandBasePath,
-      Optional<String> extraArguments) {
-
-    Preconditions.checkNotNull(executorResources);
-    MorePreconditions.checkNotBlank(executorUri);
-    MorePreconditions.checkNotBlank(commandBasePath);
-    CommandInfo.Builder builder = CommandInfo.newBuilder();
-
-    builder.addAllUris(Iterables.transform(executorResources, 
STRING_TO_URI_RESOURCE));
-    builder.addUris(STRING_TO_URI_RESOURCE.apply(executorUri));
-
-    String cmdLine = commandBasePath
-        + uriBasename(executorUri)
-        + " " + extraArguments.or("");
-    return builder.setValue(cmdLine.trim());
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilterImpl.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilterImpl.java 
b/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilterImpl.java
index fb0f7cc..52776c9 100644
--- a/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilterImpl.java
+++ b/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilterImpl.java
@@ -204,6 +204,6 @@ public class SchedulingFilterImpl implements 
SchedulingFilter {
     // 4. Resource check (lowest score).
     return getResourceVetoes(
         resource.getResourceSlot(),
-        ResourceSlot.from(request.getTask()).withOverhead(executorSettings));
+        
ResourceSlot.from(request.getTask()).add(executorSettings.getExecutorOverhead()));
   }
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorConfig.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorConfig.java 
b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorConfig.java
new file mode 100644
index 0000000..b6aa2e1
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorConfig.java
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+package org.apache.aurora.scheduler.mesos;
+
+import java.util.List;
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+import org.apache.mesos.Protos.ExecutorInfo;
+import org.apache.mesos.Protos.Volume;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Executor-related configuration used to populate task descriptions.
+ */
+public class ExecutorConfig {
+
+  private final ExecutorInfo executor;
+  private final List<Volume> volumeMounts;
+
+  public ExecutorConfig(ExecutorInfo executor, List<Volume> volumeMounts) {
+    this.executor = requireNonNull(executor);
+    this.volumeMounts = requireNonNull(volumeMounts);
+  }
+
+  public ExecutorInfo getExecutor() {
+    return executor;
+  }
+
+  public List<Volume> getVolumeMounts() {
+    return volumeMounts;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof ExecutorConfig)) {
+      return false;
+    }
+
+    ExecutorConfig other = (ExecutorConfig) obj;
+    return Objects.equals(executor, other.executor)
+        && Objects.equals(volumeMounts, other.volumeMounts);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(executor, volumeMounts);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("executor", executor)
+        .add("volumeMounts", volumeMounts)
+        .toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java 
b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
index b3c9138..b7f3023 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
@@ -13,124 +13,59 @@
  */
 package org.apache.aurora.scheduler.mesos;
 
-import java.util.List;
+import java.util.Objects;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-
-import org.apache.aurora.gen.Volume;
+import org.apache.aurora.common.quantity.Amount;
+import org.apache.aurora.common.quantity.Data;
 import org.apache.aurora.scheduler.ResourceSlot;
+import org.apache.aurora.scheduler.ResourceType;
 
 import static java.util.Objects.requireNonNull;
 
 /**
  * Configuration for the executor to run, and resource overhead required for 
it.
  */
-public final class ExecutorSettings {
-  private final String executorPath;
-  private final List<String> executorResources;
-  private final String thermosObserverRoot;
-  private final Optional<String> executorFlags;
-  private final ResourceSlot executorOverhead;
-  private final List<Volume> globalContainerMounts;
-
-  ExecutorSettings(
-      String executorPath,
-      List<String> executorResources,
-      String thermosObserverRoot,
-      Optional<String> executorFlags,
-      ResourceSlot executorOverhead,
-      List<Volume> globalContainerMounts) {
-
-    this.executorPath = requireNonNull(executorPath);
-    this.executorResources = requireNonNull(executorResources);
-    this.thermosObserverRoot = requireNonNull(thermosObserverRoot);
-    this.executorFlags = requireNonNull(executorFlags);
-    this.executorOverhead = requireNonNull(executorOverhead);
-    this.globalContainerMounts = requireNonNull(globalContainerMounts);
-  }
-
-  public String getExecutorPath() {
-    return executorPath;
-  }
+public class ExecutorSettings {
+  private final ExecutorConfig config;
 
-  public List<String> getExecutorResources() {
-    return executorResources;
+  public ExecutorSettings(ExecutorConfig config) {
+    this.config = requireNonNull(config);
   }
 
-  public String getThermosObserverRoot() {
-    return thermosObserverRoot;
+  public ExecutorConfig getExecutorConfig() {
+    // TODO(wfarner): Replace this with a generic name-based accessor once 
tasks can specify the
+    // executor they wish to use.
+    return config;
   }
 
-  public Optional<String> getExecutorFlags() {
-    return executorFlags;
+  private double getExecutorResourceValue(ResourceType resource) {
+    return config.getExecutor().getResourcesList().stream()
+        .filter(r -> r.getName().equals(resource.getName()))
+        .findFirst()
+        .map(r -> r.getScalar().getValue())
+        .orElse(0D);
   }
 
   public ResourceSlot getExecutorOverhead() {
-    return executorOverhead;
+    return new ResourceSlot(
+        getExecutorResourceValue(ResourceType.CPUS),
+        Amount.of((long) getExecutorResourceValue(ResourceType.RAM_MB), 
Data.MB),
+        Amount.of((long) getExecutorResourceValue(ResourceType.DISK_MB), 
Data.MB),
+        0);
   }
 
-  public List<Volume> getGlobalContainerMounts() {
-    return globalContainerMounts;
+  @Override
+  public int hashCode() {
+    return Objects.hash(config);
   }
 
-  public static Builder newBuilder() {
-    return new Builder();
-  }
-
-  public static final class Builder {
-    private String executorPath;
-    private List<String> executorResources;
-    private String thermosObserverRoot;
-    private Optional<String> executorFlags;
-    private ResourceSlot executorOverhead;
-    private List<Volume> globalContainerMounts;
-
-    Builder() {
-      executorResources = ImmutableList.of();
-      executorFlags = Optional.absent();
-      executorOverhead = ResourceSlot.NONE;
-      globalContainerMounts = ImmutableList.of();
-    }
-
-    public Builder setExecutorPath(String executorPath) {
-      this.executorPath = executorPath;
-      return this;
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof ExecutorSettings)) {
+      return false;
     }
 
-    public Builder setExecutorResources(List<String> executorResources) {
-      this.executorResources = executorResources;
-      return this;
-    }
-
-    public Builder setThermosObserverRoot(String thermosObserverRoot) {
-      this.thermosObserverRoot = thermosObserverRoot;
-      return this;
-    }
-
-    public Builder setExecutorFlags(Optional<String> executorFlags) {
-      this.executorFlags = executorFlags;
-      return this;
-    }
-
-    public Builder setExecutorOverhead(ResourceSlot executorOverhead) {
-      this.executorOverhead = executorOverhead;
-      return this;
-    }
-
-    public Builder setGlobalContainerMounts(List<Volume> 
globalContainerMounts) {
-      this.globalContainerMounts = globalContainerMounts;
-      return this;
-    }
-
-    public ExecutorSettings build() {
-      return new ExecutorSettings(
-          executorPath,
-          executorResources,
-          thermosObserverRoot,
-          executorFlags,
-          executorOverhead,
-          globalContainerMounts);
-    }
+    ExecutorSettings other = (ExecutorSettings) obj;
+    return Objects.equals(config, other.config);
   }
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/mesos/Executors.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/mesos/Executors.java 
b/src/main/java/org/apache/aurora/scheduler/mesos/Executors.java
new file mode 100644
index 0000000..21152f5
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/Executors.java
@@ -0,0 +1,29 @@
+/**
+ * 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.
+ */
+package org.apache.aurora.scheduler.mesos;
+
+import org.apache.mesos.Protos.ExecutorID;
+
+/**
+ * Utility class for executor-related fields.
+ */
+public final class Executors {
+  private Executors() {
+    // Utility class.
+  }
+
+  public static final ExecutorID PLACEHOLDER_EXECUTOR_ID = 
ExecutorID.newBuilder()
+      .setValue("PLACEHOLDER")
+      .build();
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java 
b/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
index f6ba2c4..f1c2059 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
@@ -27,11 +27,8 @@ import com.google.protobuf.ByteString;
 
 import org.apache.aurora.Protobufs;
 import org.apache.aurora.codec.ThriftBinaryCodec;
-import org.apache.aurora.common.quantity.Amount;
-import org.apache.aurora.common.quantity.Data;
 import org.apache.aurora.scheduler.ResourceSlot;
 import org.apache.aurora.scheduler.TierManager;
-import org.apache.aurora.scheduler.base.CommandUtil;
 import org.apache.aurora.scheduler.base.JobKeys;
 import org.apache.aurora.scheduler.base.SchedulerException;
 import org.apache.aurora.scheduler.base.Tasks;
@@ -41,7 +38,6 @@ import 
org.apache.aurora.scheduler.storage.entities.IDockerParameter;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 import org.apache.mesos.Protos;
-import org.apache.mesos.Protos.CommandInfo;
 import org.apache.mesos.Protos.ContainerInfo;
 import org.apache.mesos.Protos.ExecutorID;
 import org.apache.mesos.Protos.ExecutorInfo;
@@ -49,7 +45,6 @@ import org.apache.mesos.Protos.Resource;
 import org.apache.mesos.Protos.SlaveID;
 import org.apache.mesos.Protos.TaskID;
 import org.apache.mesos.Protos.TaskInfo;
-import org.apache.mesos.Protos.Volume;
 
 import static java.util.Objects.requireNonNull;
 
@@ -73,12 +68,6 @@ public interface MesosTaskFactory {
     private static final Logger LOG = 
Logger.getLogger(MesosTaskFactoryImpl.class.getName());
     private static final String EXECUTOR_PREFIX = "thermos-";
 
-    /**
-     * Name to associate with task executors.
-     */
-    @VisibleForTesting
-    static final String EXECUTOR_NAME = "aurora.task";
-
     private final ExecutorSettings executorSettings;
     private final TierManager tierManager;
 
@@ -106,18 +95,6 @@ public interface MesosTaskFactory {
       return String.format("%s.%s", getJobSourceName(task), instanceId);
     }
 
-    /**
-     * Resources to 'allocate' to the executor in the ExecutorInfo.  We do 
this since mesos
-     * disallows an executor with zero resources, but the tasks end up in the 
same container
-     * anyway.
-     */
-    @VisibleForTesting
-    static final ResourceSlot RESOURCES_EPSILON = new ResourceSlot(
-        0.01,
-        Amount.of(32L, Data.MB),
-        Amount.of(1L, Data.MB),
-        0);
-
     @Override
     public TaskInfo createFrom(IAssignedTask task, SlaveID slaveId) throws 
SchedulerException {
       requireNonNull(task);
@@ -132,12 +109,9 @@ public interface MesosTaskFactory {
       }
 
       ITaskConfig config = task.getTask();
-      ResourceSlot resourceSlot = ResourceSlot.from(config)
-          .withOverhead(executorSettings)
-          .subtract(RESOURCES_EPSILON);
 
       // TODO(wfarner): Re-evaluate if/why we need to continue handling unset 
assignedPorts field.
-      List<Resource> resources = resourceSlot.toResourceList(
+      List<Resource> resources = ResourceSlot.from(config).toResourceList(
           task.isSetAssignedPorts()
               ? ImmutableSet.copyOf(task.getAssignedPorts().values())
               : ImmutableSet.of(),
@@ -163,7 +137,7 @@ public interface MesosTaskFactory {
         throw new SchedulerException("Task had no supported container set.");
       }
 
-      return taskBuilder.build();
+      return ResourceSlot.matchResourceTypes(taskBuilder.build());
     }
 
     private void configureTaskForNoContainer(
@@ -171,14 +145,7 @@ public interface MesosTaskFactory {
         ITaskConfig config,
         TaskInfo.Builder taskBuilder) {
 
-      CommandInfo commandInfo = CommandUtil.create(
-          executorSettings.getExecutorPath(),
-          executorSettings.getExecutorResources(),
-          "./",
-          executorSettings.getExecutorFlags()).build();
-
-      ExecutorInfo.Builder executorBuilder = configureTaskForExecutor(task, 
config, commandInfo);
-      taskBuilder.setExecutor(executorBuilder.build());
+      taskBuilder.setExecutor(configureTaskForExecutor(task, config).build());
     }
 
     private void configureTaskForDockerContainer(
@@ -203,50 +170,23 @@ public interface MesosTaskFactory {
 
       configureContainerVolumes(containerBuilder);
 
-      // TODO(SteveNiemitz): Allow users to specify an executor per container 
type.
-      CommandInfo.Builder commandInfoBuilder = CommandUtil.create(
-          executorSettings.getExecutorPath(),
-          executorSettings.getExecutorResources(),
-          "$MESOS_SANDBOX/",
-          executorSettings.getExecutorFlags());
-
-      ExecutorInfo.Builder execBuilder =
-          configureTaskForExecutor(task, taskConfig, 
commandInfoBuilder.build())
-              .setContainer(containerBuilder.build());
+      ExecutorInfo.Builder execBuilder = configureTaskForExecutor(task, 
taskConfig)
+          .setContainer(containerBuilder.build());
 
       taskBuilder.setExecutor(execBuilder.build());
     }
 
     private ExecutorInfo.Builder configureTaskForExecutor(
         IAssignedTask task,
-        ITaskConfig config,
-        CommandInfo commandInfo) {
+        ITaskConfig config) {
 
-      return ExecutorInfo.newBuilder()
-          .setCommand(commandInfo)
+      return executorSettings.getExecutorConfig().getExecutor().toBuilder()
           .setExecutorId(getExecutorId(task.getTaskId()))
-          .setName(EXECUTOR_NAME)
-          .setSource(getInstanceSourceName(config, task.getInstanceId()))
-          
.addAllResources(RESOURCES_EPSILON.toResourceList(tierManager.getTier(config)));
+          .setSource(getInstanceSourceName(config, task.getInstanceId()));
     }
 
     private void configureContainerVolumes(ContainerInfo.Builder 
containerBuilder) {
-      containerBuilder.addVolumes(
-          Volume.newBuilder()
-              .setContainerPath(executorSettings.getThermosObserverRoot())
-              .setHostPath(executorSettings.getThermosObserverRoot())
-              .setMode(Volume.Mode.RW)
-              .build());
-
-      for (org.apache.aurora.gen.Volume v : 
executorSettings.getGlobalContainerMounts()) {
-        // This has already been validated to be correct in ExecutorSettings().
-        containerBuilder.addVolumes(
-            Volume.newBuilder()
-                .setHostPath(v.getHostPath())
-                .setContainerPath(v.getContainerPath())
-                .setMode(Volume.Mode.valueOf(v.getMode().getValue()))
-                .build());
-      }
+      
containerBuilder.addAllVolumes(executorSettings.getExecutorConfig().getVolumeMounts());
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java 
b/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java
new file mode 100644
index 0000000..ad5927c
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/TestExecutorSettings.java
@@ -0,0 +1,74 @@
+/**
+ * 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.
+ */
+package org.apache.aurora.scheduler.mesos;
+
+import com.google.common.collect.ImmutableList;
+
+import org.apache.aurora.scheduler.ResourceSlot;
+import org.apache.aurora.scheduler.ResourceType;
+import org.apache.aurora.scheduler.TierInfo;
+import org.apache.mesos.Protos.CommandInfo;
+import org.apache.mesos.Protos.CommandInfo.URI;
+import org.apache.mesos.Protos.ExecutorInfo;
+import org.apache.mesos.Protos.Resource;
+import org.apache.mesos.Protos.Value.Scalar;
+import org.apache.mesos.Protos.Value.Type;
+
+/**
+ * Test utility class for executor fields.
+ */
+public final class TestExecutorSettings {
+  private TestExecutorSettings() {
+    // Utility class.
+  }
+
+  public static final ExecutorInfo THERMOS_EXECUTOR_INFO = 
ExecutorInfo.newBuilder()
+      .setExecutorId(Executors.PLACEHOLDER_EXECUTOR_ID)
+      .setCommand(CommandInfo.newBuilder().setValue("thermos_executor.pex")
+          .addAllArguments(ImmutableList.of(
+              "--announcer-enable",
+              "--announcer-ensemble",
+              "localhost:2181"))
+          .addAllUris(ImmutableList.of(
+              URI.newBuilder()
+                  .setValue("/home/vagrant/aurora/dist/thermos_executor.pex")
+                  .setExecutable(true)
+                  .setExtract(false)
+                  .setCache(false).build())))
+      .addAllResources(ImmutableList.of(
+          Resource.newBuilder()
+              .setName(ResourceType.CPUS.getName())
+              .setType(Type.SCALAR)
+              .setScalar(Scalar.newBuilder().setValue(0.25))
+              .build(),
+          Resource.newBuilder()
+              .setName(ResourceType.RAM_MB.getName())
+              .setType(Type.SCALAR)
+              .setScalar(Scalar.newBuilder().setValue(128))
+              .build()
+      ))
+      .build();
+
+  public static final ExecutorConfig THERMOS_CONFIG =
+      new ExecutorConfig(THERMOS_EXECUTOR_INFO, ImmutableList.of());
+
+  public static final ExecutorSettings THERMOS_EXECUTOR = new 
ExecutorSettings(THERMOS_CONFIG);
+
+  public static ExecutorSettings thermosOnlyWithOverhead(ResourceSlot 
overhead) {
+    ExecutorConfig config = THERMOS_EXECUTOR.getExecutorConfig();
+    ExecutorInfo.Builder executor = config.getExecutor().toBuilder();
+    
executor.clearResources().addAllResources(overhead.toResourceList(TierInfo.DEFAULT));
+    return new ExecutorSettings(new ExecutorConfig(executor.build(), 
config.getVolumeMounts()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilter.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilter.java
 
b/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilter.java
index 67d7f07..b14ab68 100644
--- 
a/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilter.java
+++ 
b/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilter.java
@@ -130,7 +130,7 @@ public interface PreemptionVictimFilter {
               // resource. We can still use RAM, DISK and PORTS as they are 
not compressible.
               slot = new ResourceSlot(0.0, slot.getRam(), slot.getDisk(), 
slot.getNumPorts());
             }
-            return slot.withOverhead(executorSettings);
+            return slot.add(executorSettings.getExecutorOverhead());
           }
         };
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java 
b/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
index 6fad334..175151a 100644
--- a/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
@@ -23,17 +23,13 @@ import com.google.common.collect.Iterables;
 import org.apache.aurora.common.collections.Pair;
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Data;
-
 import org.apache.aurora.gen.TaskConfig;
-import org.apache.aurora.scheduler.mesos.ExecutorSettings;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 import org.apache.mesos.Protos;
 import org.junit.Test;
 
-import static org.apache.aurora.scheduler.ResourceSlot.MIN_THERMOS_RESOURCES;
 import static org.apache.aurora.scheduler.ResourceSlot.makeMesosRangeResource;
 import static org.apache.aurora.scheduler.ResourceSlot.makeMesosResource;
-import static org.apache.aurora.scheduler.ResourceSlot.maxElements;
 import static org.apache.aurora.scheduler.ResourceSlot.sum;
 import static org.apache.aurora.scheduler.ResourceType.CPUS;
 import static org.apache.aurora.scheduler.ResourceType.DISK_MB;
@@ -93,16 +89,6 @@ public class ResourceSlotTest {
   }
 
   @Test
-  public void testWithOverhead() {
-    assertEquals(maxElements(TWO, MIN_THERMOS_RESOURCES), ONE.withOverhead(
-        ExecutorSettings.newBuilder()
-            .setExecutorOverhead(ONE)
-            .setExecutorPath("ignored")
-            .setThermosObserverRoot("ignored")
-            .build()));
-  }
-
-  @Test
   public void testToResourceListNoRevocable() {
     ResourceSlot resources = ResourceSlot.from(TASK);
     Set<Integer> ports = ImmutableSet.of(80, 443);

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java 
b/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
index f63d6f1..da7d1e0 100644
--- a/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
+++ b/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
@@ -79,6 +79,7 @@ import org.apache.aurora.scheduler.log.Log.Stream;
 import org.apache.aurora.scheduler.mesos.DriverFactory;
 import org.apache.aurora.scheduler.mesos.DriverSettings;
 import org.apache.aurora.scheduler.mesos.ExecutorSettings;
+import org.apache.aurora.scheduler.mesos.TestExecutorSettings;
 import org.apache.aurora.scheduler.storage.backup.BackupModule;
 import org.apache.aurora.scheduler.storage.entities.IServerInfo;
 import org.apache.aurora.scheduler.storage.log.EntrySerializer;
@@ -195,11 +196,7 @@ public class SchedulerIT extends BaseZooKeeperTest {
             Amount.of(0L, Data.MB),
             0);
         bind(ExecutorSettings.class)
-            .toInstance(ExecutorSettings.newBuilder()
-                .setExecutorPath("/executor/thermos")
-                .setThermosObserverRoot("/var/run/thermos")
-                .setExecutorOverhead(executorOverhead)
-                .build());
+            
.toInstance(TestExecutorSettings.thermosOnlyWithOverhead(executorOverhead));
         install(new BackupModule(backupDir, SnapshotStoreImpl.class));
 
         bind(IServerInfo.class).toInstance(

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/test/java/org/apache/aurora/scheduler/base/CommandUtilTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/aurora/scheduler/base/CommandUtilTest.java 
b/src/test/java/org/apache/aurora/scheduler/base/CommandUtilTest.java
deleted file mode 100644
index cd02957..0000000
--- a/src/test/java/org/apache/aurora/scheduler/base/CommandUtilTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * 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.
- */
-package org.apache.aurora.scheduler.base;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.protobuf.TextFormat;
-
-import org.apache.mesos.Protos.CommandInfo;
-import org.apache.mesos.Protos.CommandInfo.URI;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class CommandUtilTest {
-
-  private static final Optional<String> NO_EXTRA_ARGS = Optional.absent();
-  private static final ImmutableList<String> NO_RESOURCES = ImmutableList.of();
-  private static final String PATH = "./";
-
-  @Test
-  public void testUriBasename() {
-    test("c", "c");
-    test("c", "/a/b/c");
-    test("foo.zip", "hdfs://twitter.com/path/foo.zip");
-  }
-
-  @Test
-  public void testExecutorOnlyCommand() {
-    CommandInfo cmd =
-        CommandUtil.create("test/executor", NO_RESOURCES, PATH, 
NO_EXTRA_ARGS).build();
-    assertEquals("./executor", cmd.getValue());
-    assertEquals("test/executor", cmd.getUris(0).getValue());
-  }
-
-  @Test
-  public void testWrapperAndExecutorCommand() {
-    CommandInfo cmd = CommandUtil.create(
-        "test/wrapper",
-        ImmutableList.of("test/executor"),
-        PATH,
-        NO_EXTRA_ARGS).build();
-    assertEquals("./wrapper", cmd.getValue());
-    assertEquals("test/executor", cmd.getUris(0).getValue());
-    assertEquals("test/wrapper", cmd.getUris(1).getValue());
-  }
-
-  @Test(expected = NullPointerException.class)
-  public void testBadParameters() {
-    CommandUtil.create(null, NO_RESOURCES, PATH, NO_EXTRA_ARGS);
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void testBadUri() {
-    CommandUtil.create("a/b/c/", NO_RESOURCES, PATH, NO_EXTRA_ARGS);
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void testEmptyUri() {
-    CommandUtil.create("", NO_RESOURCES, PATH, NO_EXTRA_ARGS);
-  }
-
-  @Test
-  public void testBackwardsCompatibility() {
-    // This test ensures if we specify just a URI and no other resources that 
we get the same
-    // executorInfo. The ExecutorInfo needs to remain constant because Mesos 
will reject executors
-    // with the same id but different executorInfo. See MESOS-2309 for more 
details. This is
-    // required because Aurora's GC executor has a constant id.
-
-    String uri = "/usr/local/bin/test_executor";
-    String expectedValue = "uris { value: \"/usr/local/bin/test_executor\" "
-        + "executable: true } value: \"./test_executor\"";
-    CommandInfo actual = CommandUtil.create(uri, NO_RESOURCES, PATH, 
NO_EXTRA_ARGS).build();
-
-    assertEquals(expectedValue, TextFormat.shortDebugString(actual));
-  }
-
-  private void test(String basename, String uri) {
-    CommandInfo expectedCommand = CommandInfo.newBuilder()
-        .addUris(URI.newBuilder().setValue(uri).setExecutable(true))
-        .setValue("./" + basename)
-        .build();
-    assertEquals(
-        expectedCommand,
-        CommandUtil.create(uri, NO_RESOURCES, PATH, NO_EXTRA_ARGS).build());
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/test/java/org/apache/aurora/scheduler/events/NotifyingSchedulingFilterTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/aurora/scheduler/events/NotifyingSchedulingFilterTest.java
 
b/src/test/java/org/apache/aurora/scheduler/events/NotifyingSchedulingFilterTest.java
index 0576704..b9f9f52 100644
--- 
a/src/test/java/org/apache/aurora/scheduler/events/NotifyingSchedulingFilterTest.java
+++ 
b/src/test/java/org/apache/aurora/scheduler/events/NotifyingSchedulingFilterTest.java
@@ -29,7 +29,6 @@ import org.apache.aurora.scheduler.filter.SchedulingFilter;
 import org.apache.aurora.scheduler.filter.SchedulingFilter.ResourceRequest;
 import org.apache.aurora.scheduler.filter.SchedulingFilter.UnusedResource;
 import org.apache.aurora.scheduler.filter.SchedulingFilter.Veto;
-import org.apache.aurora.scheduler.mesos.TaskExecutors;
 import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 import org.junit.Before;
@@ -46,7 +45,7 @@ public class NotifyingSchedulingFilterTest extends 
EasyMockTest {
       .setDiskMb(1024));
   private static final TaskGroupKey GROUP_KEY = TaskGroupKey.from(TASK);
   private static final UnusedResource RESOURCE = new UnusedResource(
-      ResourceSlot.from(TASK).withOverhead(TaskExecutors.NO_OVERHEAD_EXECUTOR),
+      ResourceSlot.from(TASK),
       IHostAttributes.build(new 
HostAttributes().setHost("host").setMode(MaintenanceMode.NONE)));
   private static final ResourceRequest REQUEST =
       new ResourceRequest(TASK, AttributeAggregate.EMPTY);

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java 
b/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
index dddf795..50853cf 100644
--- 
a/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
+++ 
b/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
@@ -17,7 +17,6 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
-import org.apache.aurora.common.quantity.Data;
 import org.apache.aurora.common.testing.easymock.EasyMockTest;
 import org.apache.aurora.gen.AssignedTask;
 import org.apache.aurora.gen.Container;
@@ -26,9 +25,7 @@ import org.apache.aurora.gen.DockerParameter;
 import org.apache.aurora.gen.Identity;
 import org.apache.aurora.gen.JobKey;
 import org.apache.aurora.gen.MesosContainer;
-import org.apache.aurora.gen.Mode;
 import org.apache.aurora.gen.TaskConfig;
-import org.apache.aurora.gen.Volume;
 import org.apache.aurora.scheduler.ResourceSlot;
 import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.TierManager;
@@ -36,30 +33,28 @@ import 
org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl;
 import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 import org.apache.mesos.Protos;
-import org.apache.mesos.Protos.CommandInfo;
-import org.apache.mesos.Protos.CommandInfo.URI;
 import org.apache.mesos.Protos.ContainerInfo.DockerInfo;
 import org.apache.mesos.Protos.ExecutorInfo;
 import org.apache.mesos.Protos.Parameter;
 import org.apache.mesos.Protos.Resource;
 import org.apache.mesos.Protos.SlaveID;
 import org.apache.mesos.Protos.TaskInfo;
+import org.apache.mesos.Protos.Volume;
+import org.apache.mesos.Protos.Volume.Mode;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.apache.aurora.scheduler.ResourceSlot.MIN_THERMOS_RESOURCES;
 import static org.apache.aurora.scheduler.TierInfo.DEFAULT;
 import static org.apache.aurora.scheduler.base.TaskTestUtil.REVOCABLE_TIER;
-import static 
org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl.RESOURCES_EPSILON;
 import static 
org.apache.aurora.scheduler.mesos.TaskExecutors.NO_OVERHEAD_EXECUTOR;
-import static 
org.apache.aurora.scheduler.mesos.TaskExecutors.SOME_OVERHEAD_EXECUTOR;
+import static 
org.apache.aurora.scheduler.mesos.TestExecutorSettings.THERMOS_CONFIG;
+import static 
org.apache.aurora.scheduler.mesos.TestExecutorSettings.THERMOS_EXECUTOR;
 import static org.easymock.EasyMock.expect;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class MesosTaskFactoryImplTest extends EasyMockTest {
 
-  private static final String EXECUTOR_WRAPPER_PATH = 
"/fake/executor_wrapper.sh";
   private static final ITaskConfig TASK_CONFIG = ITaskConfig.build(new 
TaskConfig()
       .setJob(new JobKey("role", "environment", "job-name"))
       .setOwner(new Identity("role", "user"))
@@ -79,7 +74,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
       .setTask(
           new TaskConfig(TASK.getTask().newBuilder())
               .setContainer(Container.docker(
-                      new DockerContainer("testimage")))));
+                  new DockerContainer("testimage")))));
   private static final IAssignedTask TASK_WITH_DOCKER_PARAMS = 
IAssignedTask.build(TASK.newBuilder()
       .setTask(
           new TaskConfig(TASK.getTask().newBuilder())
@@ -93,54 +88,44 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
   private ExecutorSettings config;
   private TierManager tierManager;
 
-  private static final ExecutorInfo DEFAULT_EXECUTOR = 
ExecutorInfo.newBuilder()
-      .setExecutorId(MesosTaskFactoryImpl.getExecutorId(TASK.getTaskId()))
-      .setName(MesosTaskFactoryImpl.EXECUTOR_NAME)
-      .setSource(MesosTaskFactoryImpl.getInstanceSourceName(TASK.getTask(), 
TASK.getInstanceId()))
-      .addAllResources(RESOURCES_EPSILON.toResourceList(DEFAULT))
-      .setCommand(CommandInfo.newBuilder()
-          .setValue("./executor.pex")
-          
.addUris(URI.newBuilder().setValue(NO_OVERHEAD_EXECUTOR.getExecutorPath())
-              .setExecutable(true)))
-      .build();
-
-  private static final ExecutorInfo EXECUTOR_WITH_WRAPPER =
-      ExecutorInfo.newBuilder(DEFAULT_EXECUTOR)
-          .setCommand(CommandInfo.newBuilder()
-              .setValue("./executor_wrapper.sh")
-              
.addUris(URI.newBuilder().setValue(NO_OVERHEAD_EXECUTOR.getExecutorPath())
-                  .setExecutable(true))
-              
.addUris(URI.newBuilder().setValue(EXECUTOR_WRAPPER_PATH).setExecutable(true)))
-          .build();
+  private static final ExecutorInfo DEFAULT_EXECUTOR = 
THERMOS_CONFIG.getExecutor();
 
   @Before
   public void setUp() {
-    config = TaskExecutors.SOME_OVERHEAD_EXECUTOR;
+    config = THERMOS_EXECUTOR;
     tierManager = createMock(TierManager.class);
   }
 
+  private static ExecutorInfo populateDynamicFields(ExecutorInfo executor, 
IAssignedTask task) {
+    return executor.toBuilder()
+        .setExecutorId(MesosTaskFactoryImpl.getExecutorId(task.getTaskId()))
+        .setSource(
+            MesosTaskFactoryImpl.getInstanceSourceName(task.getTask(), 
task.getInstanceId()))
+        .build();
+  }
+
   @Test
   public void testExecutorInfoUnchanged() {
-    expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEFAULT).times(2);
+    expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEFAULT);
     taskFactory = new MesosTaskFactoryImpl(config, tierManager);
 
     control.replay();
 
     TaskInfo task = taskFactory.createFrom(TASK, SLAVE);
-    assertEquals(DEFAULT_EXECUTOR, task.getExecutor());
+
+    assertEquals(populateDynamicFields(DEFAULT_EXECUTOR, TASK), 
task.getExecutor());
     checkTaskResources(TASK.getTask(), task);
   }
 
   @Test
   public void testTaskInfoRevocable() {
-    
expect(tierManager.getTier(TASK_CONFIG)).andReturn(REVOCABLE_TIER).times(2);
+    expect(tierManager.getTier(TASK_CONFIG)).andReturn(REVOCABLE_TIER);
     taskFactory = new MesosTaskFactoryImpl(config, tierManager);
 
     control.replay();
 
     TaskInfo task = taskFactory.createFrom(TASK, SLAVE);
     checkTaskResources(TASK.getTask(), task);
-    
assertTrue(task.getExecutor().getResourcesList().stream().anyMatch(Resource::hasRevocable));
     
assertTrue(task.getResourcesList().stream().anyMatch(Resource::hasRevocable));
   }
 
@@ -150,7 +135,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
     builder.getTask().unsetRequestedPorts();
     builder.unsetAssignedPorts();
     IAssignedTask assignedTask = IAssignedTask.build(builder);
-    
expect(tierManager.getTier(assignedTask.getTask())).andReturn(DEFAULT).times(2);
+    expect(tierManager.getTier(assignedTask.getTask())).andReturn(DEFAULT);
     taskFactory = new MesosTaskFactoryImpl(config, tierManager);
 
     control.replay();
@@ -164,47 +149,24 @@ public class MesosTaskFactoryImplTest extends 
EasyMockTest {
     // Here the ram required for the executor is greater than the sum of task 
resources
     // + executor overhead. We need to ensure we allocate a non-zero amount of 
ram in this case.
     config = NO_OVERHEAD_EXECUTOR;
-    expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEFAULT).times(2);
+    expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEFAULT);
     taskFactory = new MesosTaskFactoryImpl(config, tierManager);
 
     control.replay();
 
     TaskInfo task = taskFactory.createFrom(TASK, SLAVE);
-    assertEquals(DEFAULT_EXECUTOR, task.getExecutor());
+    assertEquals(
+        
populateDynamicFields(NO_OVERHEAD_EXECUTOR.getExecutorConfig().getExecutor(), 
TASK),
+        task.getExecutor());
 
     // Simulate the upsizing needed for the task to meet the minimum thermos 
requirements.
-    TaskConfig dummyTask = TASK.getTask().newBuilder()
-        .setRamMb(ResourceSlot.MIN_THERMOS_RESOURCES.getRam().as(Data.MB));
+    TaskConfig dummyTask = TASK.getTask().newBuilder();
     checkTaskResources(ITaskConfig.build(dummyTask), task);
   }
 
-  @Test
-  public void testSmallTaskUpsizing() {
-    // A very small task should be upsized to support the minimum resources 
required by the
-    // executor.
-
-    config = NO_OVERHEAD_EXECUTOR;
-    AssignedTask builder = TASK.newBuilder();
-    builder.getTask()
-        .setNumCpus(0.001)
-        .setRamMb(1)
-        .setDiskMb(0)
-        .setRequestedPorts(ImmutableSet.of());
-    IAssignedTask assignedTask =
-        IAssignedTask.build(builder.setAssignedPorts(ImmutableMap.of()));
-    
expect(tierManager.getTier(assignedTask.getTask())).andReturn(DEFAULT).times(2);
-    taskFactory = new MesosTaskFactoryImpl(config, tierManager);
-
-    control.replay();
-
-    assertEquals(
-        MIN_THERMOS_RESOURCES,
-        getTotalTaskResources(taskFactory.createFrom(assignedTask, SLAVE)));
-  }
-
   private void checkTaskResources(ITaskConfig task, TaskInfo taskInfo) {
     assertEquals(
-        ResourceSlot.from(task).withOverhead(config),
+        ResourceSlot.from(task).add(config.getExecutorOverhead()),
         getTotalTaskResources(taskInfo));
   }
 
@@ -214,7 +176,7 @@ public class MesosTaskFactoryImplTest extends EasyMockTest {
 
   private TaskInfo getDockerTaskInfo(IAssignedTask task) {
     config = TaskExecutors.SOME_OVERHEAD_EXECUTOR;
-    expect(tierManager.getTier(task.getTask())).andReturn(DEFAULT).times(2);
+    expect(tierManager.getTier(task.getTask())).andReturn(DEFAULT);
     taskFactory = new MesosTaskFactoryImpl(config, tierManager);
 
     control.replay();
@@ -237,54 +199,26 @@ public class MesosTaskFactoryImplTest extends 
EasyMockTest {
     assertEquals(ImmutableList.of(parameters), docker.getParametersList());
   }
 
-  @Test(expected = NullPointerException.class)
-  public void testInvalidExecutorSettings() {
-    control.replay();
-
-    ExecutorSettings.newBuilder()
-        .setExecutorPath(null)
-        .setThermosObserverRoot("")
-        .build();
-  }
-
-  @Test
-  public void testExecutorAndWrapper() {
-    config = ExecutorSettings.newBuilder()
-        .setExecutorPath(EXECUTOR_WRAPPER_PATH)
-        
.setExecutorResources(ImmutableList.of(SOME_OVERHEAD_EXECUTOR.getExecutorPath()))
-        .setThermosObserverRoot("/var/run/thermos")
-        .setExecutorOverhead(SOME_OVERHEAD_EXECUTOR.getExecutorOverhead())
-        .build();
-    expect(tierManager.getTier(TASK_CONFIG)).andReturn(DEFAULT).times(2);
-    taskFactory = new MesosTaskFactoryImpl(config, tierManager);
-
-    control.replay();
-
-    TaskInfo taskInfo = taskFactory.createFrom(TASK, SLAVE);
-    assertEquals(EXECUTOR_WITH_WRAPPER, taskInfo.getExecutor());
-  }
-
   @Test
   public void testGlobalMounts() {
-    config = ExecutorSettings.newBuilder()
-        .setExecutorPath(EXECUTOR_WRAPPER_PATH)
-        
.setExecutorResources(ImmutableList.of(SOME_OVERHEAD_EXECUTOR.getExecutorPath()))
-        .setThermosObserverRoot("/var/run/thermos")
-        .setExecutorOverhead(SOME_OVERHEAD_EXECUTOR.getExecutorOverhead())
-        .setGlobalContainerMounts(ImmutableList.of(new Volume("/container", 
"/host", Mode.RO)))
-        .build();
-    
expect(tierManager.getTier(TASK_WITH_DOCKER.getTask())).andReturn(DEFAULT).times(2);
+    config = new ExecutorSettings(new ExecutorConfig(
+        TestExecutorSettings.THERMOS_EXECUTOR_INFO,
+        ImmutableList.of(
+            Volume.newBuilder()
+                .setHostPath("/host")
+                .setContainerPath("/container")
+                .setMode(Mode.RO)
+                .build())));
+
+    expect(tierManager.getTier(TASK_WITH_DOCKER.getTask())).andReturn(DEFAULT);
     taskFactory = new MesosTaskFactoryImpl(config, tierManager);
 
     control.replay();
 
     TaskInfo taskInfo = taskFactory.createFrom(TASK_WITH_DOCKER, SLAVE);
-    Protos.Volume expected = Protos.Volume.newBuilder()
-        .setHostPath("/host")
-        .setContainerPath("/container")
-        .setMode(Protos.Volume.Mode.RO)
-        .build();
-    
assertTrue(taskInfo.getExecutor().getContainer().getVolumesList().contains(expected));
+    assertEquals(
+        config.getExecutorConfig().getVolumeMounts(),
+        taskInfo.getExecutor().getContainer().getVolumesList());
   }
 
   private static ResourceSlot getTotalTaskResources(TaskInfo task) {

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java 
b/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
index d098725..a258d06 100644
--- a/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
+++ b/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
@@ -15,7 +15,6 @@ package org.apache.aurora.scheduler.mesos;
 
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Data;
-
 import org.apache.aurora.scheduler.ResourceSlot;
 
 /**
@@ -27,19 +26,10 @@ public final class TaskExecutors {
     // Utility class.
   }
 
-  private static final String EXECUTOR_PATH = "/fake/executor.pex";
-
   public static final ExecutorSettings NO_OVERHEAD_EXECUTOR =
-      ExecutorSettings.newBuilder()
-          .setExecutorPath(EXECUTOR_PATH)
-          .setThermosObserverRoot("/var/run/thermos")
-          .build();
+      TestExecutorSettings.thermosOnlyWithOverhead(ResourceSlot.NONE);
 
   public static final ExecutorSettings SOME_OVERHEAD_EXECUTOR =
-      ExecutorSettings.newBuilder()
-          .setExecutorPath(EXECUTOR_PATH)
-          .setThermosObserverRoot("/var/run/thermos")
-          .setExecutorOverhead(
-              new ResourceSlot(0.01, Amount.of(256L, Data.MB), Amount.of(0L, 
Data.MB), 0))
-          .build();
+      TestExecutorSettings.thermosOnlyWithOverhead(
+          new ResourceSlot(0.01, Amount.of(256L, Data.MB), Amount.of(0L, 
Data.MB), 0));
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/0b025a7d/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
 
b/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
index 8ce8da8..5cb8508 100644
--- 
a/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
+++ 
b/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
@@ -268,7 +268,7 @@ public class PreemptionVictimFilterTest extends 
EasyMockTest {
   @Test
   public void testMinimalSetPreempted() throws Exception {
     schedulingFilter = new 
SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
-    
expect(tierManager.getTier(EasyMock.anyObject())).andReturn(DEFAULT).times(9);
+    
expect(tierManager.getTier(EasyMock.anyObject())).andReturn(DEFAULT).atLeastOnce();
     ScheduledTask a1 = makeTask(USER_A, JOB_A, TASK_ID_A + "_a1");
     a1.getAssignedTask().getTask().setNumCpus(4).setRamMb(4096);
 

Reply via email to