You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2015/01/26 21:49:39 UTC
incubator-aurora git commit: Fix impedance mismatch between offer
matching and task launching.
Repository: incubator-aurora
Updated Branches:
refs/heads/master 7ba6226fa -> b39f6ee14
Fix impedance mismatch between offer matching and task launching.
Bugs closed: AURORA-1050
Reviewed at https://reviews.apache.org/r/30203/
Project: http://git-wip-us.apache.org/repos/asf/incubator-aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-aurora/commit/b39f6ee1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-aurora/tree/b39f6ee1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-aurora/diff/b39f6ee1
Branch: refs/heads/master
Commit: b39f6ee144d008e31baf79f19b88cbedead86c10
Parents: 7ba6226
Author: Bill Farner <wf...@apache.org>
Authored: Mon Jan 26 12:46:58 2015 -0800
Committer: Bill Farner <wf...@apache.org>
Committed: Mon Jan 26 12:46:58 2015 -0800
----------------------------------------------------------------------
.../apache/aurora/scheduler/ResourceSlot.java | 92 ++++++----
.../aurora/scheduler/app/SchedulerMain.java | 20 ++-
.../async/preemptor/LiveClusterState.java | 1 +
.../async/preemptor/PreemptionVictim.java | 10 +-
.../async/preemptor/PreemptorImpl.java | 18 +-
.../scheduler/configuration/Resources.java | 19 +-
.../scheduler/filter/SchedulingFilter.java | 4 +-
.../scheduler/filter/SchedulingFilterImpl.java | 16 +-
.../scheduler/mesos/ExecutorSettings.java | 67 +++++++
.../scheduler/mesos/MesosTaskFactory.java | 123 ++-----------
.../aurora/scheduler/ResourceSlotTest.java | 37 ++++
.../aurora/scheduler/UserTaskLauncherTest.java | 65 +------
.../aurora/scheduler/app/SchedulerIT.java | 8 +-
.../async/preemptor/PreemptorImplTest.java | 19 +-
.../events/NotifyingSchedulingFilterTest.java | 3 +-
.../filter/SchedulingFilterImplTest.java | 17 +-
.../mesos/MesosTaskFactoryImplTest.java | 176 ++++++-------------
.../apache/aurora/scheduler/mesos/Offers.java | 65 +++++++
.../aurora/scheduler/mesos/TaskExecutors.java | 47 +++++
.../aurora/e2e/http/http_example_updated.aurora | 2 +-
.../org/apache/aurora/e2e/validate_serverset.py | 6 +-
21 files changed, 441 insertions(+), 374 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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 0b15834..1a158b4 100644
--- a/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
+++ b/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
@@ -14,18 +14,21 @@
package org.apache.aurora.scheduler;
import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
-import com.twitter.common.args.Arg;
-import com.twitter.common.args.CmdLine;
import com.twitter.common.quantity.Amount;
import com.twitter.common.quantity.Data;
+import org.apache.aurora.scheduler.async.preemptor.PreemptionVictim;
import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.mesos.ExecutorSettings;
import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
+import org.apache.mesos.Protos;
import static org.apache.mesos.Protos.Offer;
@@ -38,32 +41,58 @@ public final class ResourceSlot {
private final Resources resources;
/**
- * Extra CPU allocated for each executor.
+ * 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
- @CmdLine(name = "thermos_executor_cpu",
- help = "The number of CPU cores to allocate for each instance of the executor.")
- public static final Arg<Double> EXECUTOR_OVERHEAD_CPUS = Arg.create(0.25);
-
- /**
- * Extra RAM allocated for the executor.
- */
- @VisibleForTesting
- @CmdLine(name = "thermos_executor_ram",
- help = "The amount of RAM to allocate for each instance of the executor.")
- public static final Arg<Amount<Long, Data>> EXECUTOR_OVERHEAD_RAM =
- Arg.create(Amount.of(128L, Data.MB));
+ public static final Resources MIN_THERMOS_RESOURCES = new Resources(
+ 0.01,
+ Amount.of(256L, Data.MB),
+ Amount.of(1L, Data.MB),
+ 0);
private ResourceSlot(Resources r) {
this.resources = r;
}
- public static ResourceSlot from(ITaskConfig task) {
- return from(
- task.getNumCpus(),
- Amount.of(task.getRamMb(), Data.MB),
- Amount.of(task.getDiskMb(), Data.MB),
- task.getRequestedPorts().size());
+ public static ResourceSlot from(ITaskConfig task, ExecutorSettings executorSettings) {
+ return from(Resources.from(task), executorSettings);
+ }
+
+ public static ResourceSlot from(PreemptionVictim victim, ExecutorSettings executorSettings) {
+ return from(victim.getResources(), executorSettings);
+ }
+
+ private static ResourceSlot from(Resources resources, ExecutorSettings executorSettings) {
+ // Apply a flat 'tax' of executor overhead resources to the task.
+ Resources requiredTaskResources = Resources.sum(
+ resources,
+ executorSettings.getExecutorOverhead());
+
+ // Upsize tasks smaller than the minimum resources required to run the executor.
+ return new ResourceSlot(maxElements(requiredTaskResources, MIN_THERMOS_RESOURCES));
+ }
+
+ /**
+ * Generates a Resource where each resource component is a max out of the two components.
+ *
+ * @param a A resource to compare.
+ * @param b A resource to compare.
+ *
+ * @return Returns a Resources instance where each component is a max of the two components.
+ */
+ @VisibleForTesting
+ static Resources maxElements(Resources a, Resources b) {
+ double maxCPU = Math.max(a.getNumCpus(), b.getNumCpus());
+ Amount<Long, Data> maxRAM = Amount.of(
+ Math.max(a.getRam().as(Data.MB), b.getRam().as(Data.MB)),
+ Data.MB);
+ Amount<Long, Data> maxDisk = Amount.of(
+ Math.max(a.getDisk().as(Data.MB), b.getDisk().as(Data.MB)),
+ Data.MB);
+ int maxPorts = Math.max(a.getNumPorts(), b.getNumPorts());
+
+ return new Resources(maxCPU, maxRAM, maxDisk, maxPorts);
}
public static ResourceSlot from(Offer offer) {
@@ -86,19 +115,6 @@ public final class ResourceSlot {
return resources.getNumPorts();
}
- @VisibleForTesting
- public static ResourceSlot from(
- double cpu,
- Amount<Long, Data> ram,
- Amount<Long, Data> disk,
- int ports) {
- double totalCPU = cpu + EXECUTOR_OVERHEAD_CPUS.get();
- Amount<Long, Data> totalRAM =
- Amount.of(ram.as(Data.MB) + EXECUTOR_OVERHEAD_RAM.get().as(Data.MB), Data.MB);
-
- return new ResourceSlot(new Resources(totalCPU, totalRAM, disk, ports));
- }
-
@Override
public boolean equals(Object o) {
if (!(o instanceof ResourceSlot)) {
@@ -129,6 +145,14 @@ public final class ResourceSlot {
return new ResourceSlot(r);
}
+ public static ResourceSlot subtract(ResourceSlot a, Resources b) {
+ return new ResourceSlot(Resources.subtract(a.resources, b));
+ }
+
+ public List<Protos.Resource> toResourceList(Set<Integer> selectedPorts) {
+ return resources.toResourceList(selectedPorts);
+ }
+
public static final Ordering<ResourceSlot> ORDER = new Ordering<ResourceSlot>() {
@Override
public int compare(ResourceSlot left, ResourceSlot right) {
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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 dd64a22..24b61c1 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
@@ -51,8 +51,8 @@ import org.apache.aurora.scheduler.configuration.Resources;
import org.apache.aurora.scheduler.cron.quartz.CronModule;
import org.apache.aurora.scheduler.log.mesos.MesosLogStreamModule;
import org.apache.aurora.scheduler.mesos.CommandLineDriverSettingsModule;
+import org.apache.aurora.scheduler.mesos.ExecutorSettings;
import org.apache.aurora.scheduler.mesos.LibMesosLoadingModule;
-import org.apache.aurora.scheduler.mesos.MesosTaskFactory.ExecutorSettings;
import org.apache.aurora.scheduler.storage.backup.BackupModule;
import org.apache.aurora.scheduler.storage.db.DbModule;
import org.apache.aurora.scheduler.storage.db.MigrationModule;
@@ -66,9 +66,6 @@ import org.apache.aurora.scheduler.thrift.auth.ThriftAuthModule;
import static com.twitter.common.logging.RootLogConfig.Configuration;
-import static org.apache.aurora.scheduler.ResourceSlot.EXECUTOR_OVERHEAD_CPUS;
-import static org.apache.aurora.scheduler.ResourceSlot.EXECUTOR_OVERHEAD_RAM;
-
/**
* Launcher for the aurora scheduler.
*/
@@ -106,6 +103,21 @@ public class SchedulerMain extends AbstractApplication {
private static final Arg<? extends Class<? extends Module>> AUTH_MODULE =
Arg.create(UnsecureAuthModule.class);
+ /**
+ * Extra CPU allocated for each executor.
+ */
+ @CmdLine(name = "thermos_executor_cpu",
+ help = "The number of CPU cores to allocate for each instance of the executor.")
+ private static final Arg<Double> EXECUTOR_OVERHEAD_CPUS = Arg.create(0.25);
+
+ /**
+ * Extra RAM allocated for the executor.
+ */
+ @CmdLine(name = "thermos_executor_ram",
+ help = "The amount of RAM to allocate for each instance of the executor.")
+ private static final Arg<Amount<Long, Data>> EXECUTOR_OVERHEAD_RAM =
+ Arg.create(Amount.of(128L, Data.MB));
+
private static final Iterable<Class<?>> AUTH_MODULE_CLASSES = ImmutableList.<Class<?>>builder()
.add(SessionValidator.class)
.add(CapabilityValidator.class)
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/main/java/org/apache/aurora/scheduler/async/preemptor/LiveClusterState.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/async/preemptor/LiveClusterState.java b/src/main/java/org/apache/aurora/scheduler/async/preemptor/LiveClusterState.java
index e6bd1b5..38cb173 100644
--- a/src/main/java/org/apache/aurora/scheduler/async/preemptor/LiveClusterState.java
+++ b/src/main/java/org/apache/aurora/scheduler/async/preemptor/LiveClusterState.java
@@ -33,6 +33,7 @@ import static java.util.Objects.requireNonNull;
import static org.apache.aurora.gen.ScheduleStatus.PREEMPTING;
import static org.apache.aurora.scheduler.base.Tasks.SCHEDULED_TO_ASSIGNED;
+// TODO(wfarner): Remove this in favor of CachedClusterState.
class LiveClusterState implements ClusterState {
@VisibleForTesting
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptionVictim.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptionVictim.java b/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptionVictim.java
index 024a689..80c2023 100644
--- a/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptionVictim.java
+++ b/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptionVictim.java
@@ -15,7 +15,7 @@ package org.apache.aurora.scheduler.async.preemptor;
import java.util.Objects;
-import org.apache.aurora.scheduler.ResourceSlot;
+import org.apache.aurora.scheduler.configuration.Resources;
import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
@@ -27,7 +27,7 @@ public final class PreemptionVictim {
private final boolean production;
private final String role;
private final int priority;
- private final ResourceSlot resources;
+ private final Resources resources;
private final String taskId;
private PreemptionVictim(
@@ -35,7 +35,7 @@ public final class PreemptionVictim {
boolean production,
String role,
int priority,
- ResourceSlot resources,
+ Resources resources,
String taskId) {
this.slaveHost = slaveHost;
@@ -53,7 +53,7 @@ public final class PreemptionVictim {
config.isProduction(),
config.getOwner().getRole(),
config.getPriority(),
- ResourceSlot.from(config),
+ Resources.from(task.getTask()),
task.getTaskId());
}
@@ -73,7 +73,7 @@ public final class PreemptionVictim {
return priority;
}
- public ResourceSlot getResources() {
+ public Resources getResources() {
return resources;
}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImpl.java b/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImpl.java
index 0204d14..10c4f06 100644
--- a/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImpl.java
+++ b/src/main/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImpl.java
@@ -48,6 +48,7 @@ import org.apache.aurora.scheduler.filter.AttributeAggregate;
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.mesos.ExecutorSettings;
import org.apache.aurora.scheduler.state.StateManager;
import org.apache.aurora.scheduler.storage.Storage;
import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
@@ -104,6 +105,7 @@ class PreemptorImpl implements Preemptor {
private final Clock clock;
private final AtomicLong missingAttributes;
private final ClusterState clusterState;
+ private final ExecutorSettings executorSettings;
/**
* Creates a new preemptor.
@@ -125,7 +127,8 @@ class PreemptorImpl implements Preemptor {
@PreemptionDelay Amount<Long, Time> preemptionCandidacyDelay,
Clock clock,
StatsProvider statsProvider,
- ClusterState clusterState) {
+ ClusterState clusterState,
+ ExecutorSettings executorSettings) {
this.storage = requireNonNull(storage);
this.stateManager = requireNonNull(stateManager);
@@ -135,6 +138,7 @@ class PreemptorImpl implements Preemptor {
this.clock = requireNonNull(clock);
missingAttributes = statsProvider.makeCounter("preemptor_missing_attributes");
this.clusterState = requireNonNull(clusterState);
+ this.executorSettings = requireNonNull(executorSettings);
}
private static final Function<HostOffer, ResourceSlot> OFFER_TO_RESOURCE_SLOT =
@@ -161,11 +165,11 @@ class PreemptorImpl implements Preemptor {
}
};
- private static final Function<PreemptionVictim, ResourceSlot> VICTIM_TO_RESOURCES =
+ private final Function<PreemptionVictim, ResourceSlot> victimToResources =
new Function<PreemptionVictim, ResourceSlot>() {
@Override
public ResourceSlot apply(PreemptionVictim victim) {
- return victim.getResources();
+ return ResourceSlot.from(victim, executorSettings);
}
};
@@ -179,8 +183,8 @@ class PreemptorImpl implements Preemptor {
// TODO(zmanji) Consider using Dominant Resource Fairness for ordering instead of the vector
// ordering
- private static final Ordering<PreemptionVictim> RESOURCE_ORDER =
- ResourceSlot.ORDER.onResultOf(VICTIM_TO_RESOURCES).reverse();
+ private final Ordering<PreemptionVictim> resourceOrder =
+ ResourceSlot.ORDER.onResultOf(victimToResources).reverse();
private static final Function<PreemptionVictim, String> VICTIM_TO_HOST =
new Function<PreemptionVictim, String>() {
@@ -240,13 +244,13 @@ class PreemptorImpl implements Preemptor {
List<PreemptionVictim> toPreemptTasks = Lists.newArrayList();
- Iterable<PreemptionVictim> sortedVictims = RESOURCE_ORDER.immutableSortedCopy(preemptableTasks);
+ Iterable<PreemptionVictim> sortedVictims = resourceOrder.immutableSortedCopy(preemptableTasks);
for (PreemptionVictim victim : sortedVictims) {
toPreemptTasks.add(victim);
ResourceSlot totalResource = ResourceSlot.sum(
- ResourceSlot.sum(Iterables.transform(toPreemptTasks, VICTIM_TO_RESOURCES)),
+ ResourceSlot.sum(Iterables.transform(toPreemptTasks, victimToResources)),
slackResources);
Optional<IHostAttributes> attributes = getHostAttributes(host);
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/main/java/org/apache/aurora/scheduler/configuration/Resources.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/configuration/Resources.java b/src/main/java/org/apache/aurora/scheduler/configuration/Resources.java
index 65c4b52..b5a3140 100644
--- a/src/main/java/org/apache/aurora/scheduler/configuration/Resources.java
+++ b/src/main/java/org/apache/aurora/scheduler/configuration/Resources.java
@@ -147,6 +147,16 @@ public class Resources {
return Objects.hash(numCpus, ram, disk, numPorts);
}
+ @Override
+ public String toString() {
+ return com.google.common.base.Objects.toStringHelper(this)
+ .add("numCpus", numCpus)
+ .add("ram", ram)
+ .add("disk", disk)
+ .add("numPorts", numPorts)
+ .toString();
+ }
+
/**
* Extracts the resources required from a task.
*
@@ -193,13 +203,10 @@ public class Resources {
getNumAvailablePorts(offer.getResourcesList()));
}
- private static final Resources NO_RESOURCES =
+ @VisibleForTesting
+ public static final Resources NONE =
new Resources(0, Amount.of(0L, Data.BITS), Amount.of(0L, Data.BITS), 0);
- private static Resources none() {
- return NO_RESOURCES;
- }
-
/**
* a - b.
*/
@@ -222,7 +229,7 @@ public class Resources {
* sum(rs).
*/
public static Resources sum(Iterable<Resources> rs) {
- Resources sum = none();
+ Resources sum = NONE;
for (Resources r : rs) {
double numCpus = sum.getNumCpus() + r.getNumCpus();
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilter.java b/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilter.java
index c2a342c..6a43bcd 100644
--- a/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilter.java
+++ b/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilter.java
@@ -221,8 +221,8 @@ public interface SchedulingFilter {
return task.getConstraints();
}
- public ResourceSlot getResourceSlot() {
- return ResourceSlot.from(task);
+ public ITaskConfig getTask() {
+ return task;
}
public AttributeAggregate getJobState() {
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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 1cb56f1..f06fdae 100644
--- a/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilterImpl.java
+++ b/src/main/java/org/apache/aurora/scheduler/filter/SchedulingFilterImpl.java
@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
+import com.google.inject.Inject;
import com.twitter.common.quantity.Amount;
import com.twitter.common.quantity.Data;
@@ -30,10 +31,13 @@ import org.apache.aurora.gen.MaintenanceMode;
import org.apache.aurora.gen.TaskConstraint;
import org.apache.aurora.scheduler.ResourceSlot;
import org.apache.aurora.scheduler.configuration.ConfigurationManager;
+import org.apache.aurora.scheduler.mesos.ExecutorSettings;
import org.apache.aurora.scheduler.storage.entities.IAttribute;
import org.apache.aurora.scheduler.storage.entities.IConstraint;
import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
+import static java.util.Objects.requireNonNull;
+
import static org.apache.aurora.gen.MaintenanceMode.DRAINED;
import static org.apache.aurora.gen.MaintenanceMode.DRAINING;
import static org.apache.aurora.scheduler.configuration.ConfigurationManager.DEDICATED_ATTRIBUTE;
@@ -132,6 +136,14 @@ public class SchedulingFilterImpl implements SchedulingFilter {
}
});
+ private final ExecutorSettings executorSettings;
+
+ @Inject
+ @VisibleForTesting
+ public SchedulingFilterImpl(ExecutorSettings executorSettings) {
+ this.executorSettings = requireNonNull(executorSettings);
+ }
+
private Iterable<Veto> getConstraintVetoes(
Iterable<IConstraint> taskConstraints,
AttributeAggregate jobState,
@@ -183,7 +195,9 @@ public class SchedulingFilterImpl implements SchedulingFilter {
request.getConstraints(),
request.getJobState(),
resource.getAttributes().getAttributes()))
- .addAll(getResourceVetoes(resource.getResourceSlot(), request.getResourceSlot()))
+ .addAll(getResourceVetoes(
+ resource.getResourceSlot(),
+ ResourceSlot.from(request.getTask(), executorSettings)))
.build();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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
new file mode 100644
index 0000000..baacb71
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
@@ -0,0 +1,67 @@
+/**
+ * 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 com.google.common.base.Optional;
+
+import org.apache.aurora.scheduler.configuration.Resources;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Configuration for the executor to run, and resource overhead required for it.
+ */
+public class ExecutorSettings {
+ private final String executorPath;
+ private final List<String> executorResources;
+ private final String thermosObserverRoot;
+ private final Optional<String> executorFlags;
+ private final Resources executorOverhead;
+
+ public ExecutorSettings(
+ String executorPath,
+ List<String> executorResources,
+ String thermosObserverRoot,
+ Optional<String> executorFlags,
+ Resources executorOverhead) {
+
+ this.executorPath = requireNonNull(executorPath);
+ this.executorResources = requireNonNull(executorResources);
+ this.thermosObserverRoot = requireNonNull(thermosObserverRoot);
+ this.executorFlags = requireNonNull(executorFlags);
+ this.executorOverhead = requireNonNull(executorOverhead);
+ }
+
+ public String getExecutorPath() {
+ return executorPath;
+ }
+
+ public List<String> getExecutorResources() {
+ return executorResources;
+ }
+
+ public String getThermosObserverRoot() {
+ return thermosObserverRoot;
+ }
+
+ public Optional<String> getExecutorFlags() {
+ return executorFlags;
+ }
+
+ public Resources getExecutorOverhead() {
+ return executorOverhead;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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 846914e..5340d65 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
@@ -20,7 +20,6 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.protobuf.ByteString;
@@ -29,12 +28,12 @@ import com.twitter.common.quantity.Data;
import org.apache.aurora.Protobufs;
import org.apache.aurora.codec.ThriftBinaryCodec;
+import org.apache.aurora.scheduler.ResourceSlot;
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;
import org.apache.aurora.scheduler.configuration.Resources;
-
import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
import org.apache.aurora.scheduler.storage.entities.IDockerContainer;
import org.apache.aurora.scheduler.storage.entities.IJobKey;
@@ -66,77 +65,12 @@ public interface MesosTaskFactory {
*/
TaskInfo createFrom(IAssignedTask task, SlaveID slaveId) throws SchedulerException;
- class ExecutorSettings {
-
- private final String executorPath;
- private final List<String> executorResources;
- private final String thermosObserverRoot;
- private final Optional<String> executorFlags;
- private final Resources executorOverhead;
-
- public ExecutorSettings(
- String executorPath,
- List<String> executorResources,
- String thermosObserverRoot,
- Optional<String> executorFlags,
- Resources executorOverhead) {
-
- this.executorPath = requireNonNull(executorPath);
- this.executorResources = requireNonNull(executorResources);
- this.thermosObserverRoot = requireNonNull(thermosObserverRoot);
- this.executorFlags = requireNonNull(executorFlags);
- this.executorOverhead = requireNonNull(executorOverhead);
- }
-
- String getExecutorPath() {
- return executorPath;
- }
-
- List<String> getExecutorResources() {
- return executorResources;
- }
-
- String getThermosObserverRoot() {
- return thermosObserverRoot;
- }
-
- Optional<String> getExecutorFlags() {
- return executorFlags;
- }
-
- Resources getExecutorOverhead() {
- return executorOverhead;
- }
- }
-
// TODO(wfarner): Move this class to its own file to reduce visibility to package private.
class MesosTaskFactoryImpl implements MesosTaskFactory {
private static final Logger LOG = Logger.getLogger(MesosTaskFactoryImpl.class.getName());
private static final String EXECUTOR_PREFIX = "thermos-";
/**
- * 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
- static final Resources MIN_THERMOS_RESOURCES = new Resources(
- 0.01,
- Amount.of(256L, Data.MB),
- Amount.of(1L, Data.MB),
- 0);
-
- /**
- * Minimum resources to allocate for a task. Mesos rejects tasks that have no CPU, no RAM, or
- * no Disk.
- */
- @VisibleForTesting
- static final Resources MIN_TASK_RESOURCES = new Resources(
- 0.01,
- Amount.of(1L, Data.MB),
- Amount.of(1L, Data.MB),
- 0);
-
- /**
* Name to associate with task executors.
*/
@VisibleForTesting
@@ -168,26 +102,16 @@ public interface MesosTaskFactory {
}
/**
- * Generates a Resource where each resource component is a max out of the two components.
- *
- * @param a A resource to compare.
- * @param b A resource to compare.
- *
- * @return Returns a Resources instance where each component is a max of the two components.
+ * 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 Resources maxElements(Resources a, Resources b) {
- double maxCPU = Math.max(a.getNumCpus(), b.getNumCpus());
- Amount<Long, Data> maxRAM = Amount.of(
- Math.max(a.getRam().as(Data.MB), b.getRam().as(Data.MB)),
- Data.MB);
- Amount<Long, Data> maxDisk = Amount.of(
- Math.max(a.getDisk().as(Data.MB), b.getDisk().as(Data.MB)),
- Data.MB);
- int maxPorts = Math.max(a.getNumPorts(), b.getNumPorts());
-
- return new Resources(maxCPU, maxRAM, maxDisk, maxPorts);
- }
+ static final Resources RESOURCES_EPSILON = new Resources(
+ 0.01,
+ Amount.of(1L, Data.MB),
+ Amount.of(1L, Data.MB),
+ 0);
@Override
public TaskInfo createFrom(IAssignedTask task, SlaveID slaveId) throws SchedulerException {
@@ -202,33 +126,20 @@ public interface MesosTaskFactory {
throw new SchedulerException("Internal error.", e);
}
- // The objective of the below code is to allocate a task and executor that is in a container
- // of task + executor overhead size. Mesos stipulates that we cannot allocate 0 sized tasks or
- // executors and we should always ensure the ExecutorInfo has enough resources to launch or
- // run an executor. Therefore the total desired container size (task + executor overhead) is
- // partitioned to a small portion that is always allocated to the executor and the rest to the
- // task. If the remaining resources are not enough for the task a small epsilon is allocated
- // to the task.
-
ITaskConfig config = task.getTask();
- Resources taskResources = Resources.from(config);
- Resources containerResources =
- Resources.sum(taskResources, executorSettings.getExecutorOverhead());
-
- taskResources = Resources.subtract(containerResources, MIN_THERMOS_RESOURCES);
- // It is possible that the final task resources will be negative.
- // This ensures the task resources are positive.
- Resources finalTaskResources = maxElements(taskResources, MIN_TASK_RESOURCES);
+ ResourceSlot resourceSlot =
+ ResourceSlot.subtract(ResourceSlot.from(config, executorSettings), RESOURCES_EPSILON);
// TODO(wfarner): Re-evaluate if/why we need to continue handling unset assignedPorts field.
- List<Resource> resources = finalTaskResources
+ List<Resource> resources = resourceSlot
.toResourceList(task.isSetAssignedPorts()
? ImmutableSet.copyOf(task.getAssignedPorts().values())
: ImmutableSet.<Integer>of());
- LOG.fine("Setting task resources to "
- + Iterables.transform(resources, Protobufs.SHORT_TOSTRING));
-
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Setting task resources to "
+ + Iterables.transform(resources, Protobufs.SHORT_TOSTRING));
+ }
TaskInfo.Builder taskBuilder =
TaskInfo.newBuilder()
.setName(JobKeys.canonicalString(Tasks.ASSIGNED_TO_JOB_KEY.apply(task)))
@@ -302,7 +213,7 @@ public interface MesosTaskFactory {
.setExecutorId(getExecutorId(task.getTaskId()))
.setName(EXECUTOR_NAME)
.setSource(getInstanceSourceName(config, task.getInstanceId()))
- .addAllResources(MIN_THERMOS_RESOURCES.toResourceList());
+ .addAllResources(RESOURCES_EPSILON.toResourceList());
}
private void configureContainerVolumes(ContainerInfo.Builder containerBuilder) {
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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
new file mode 100644
index 0000000..b4dbab7
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
@@ -0,0 +1,37 @@
+/**
+ * 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;
+
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Data;
+
+import org.apache.aurora.scheduler.configuration.Resources;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class ResourceSlotTest {
+
+ @Test
+ public void testMaxElements() {
+ Resources highRAM = new Resources(1, Amount.of(8L, Data.GB), Amount.of(10L, Data.MB), 0);
+ Resources rest = new Resources(10, Amount.of(1L, Data.MB), Amount.of(10L, Data.GB), 1);
+
+ Resources result = ResourceSlot.maxElements(highRAM, rest);
+ assertEquals(result.getNumCpus(), 10, 0.001);
+ assertEquals(result.getRam(), Amount.of(8L, Data.GB));
+ assertEquals(result.getDisk(), Amount.of(10L, Data.GB));
+ assertEquals(result.getNumPorts(), 1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/test/java/org/apache/aurora/scheduler/UserTaskLauncherTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/UserTaskLauncherTest.java b/src/test/java/org/apache/aurora/scheduler/UserTaskLauncherTest.java
index 7ba9464..f96110c 100644
--- a/src/test/java/org/apache/aurora/scheduler/UserTaskLauncherTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/UserTaskLauncherTest.java
@@ -13,57 +13,38 @@
*/
package org.apache.aurora.scheduler;
-import java.util.Set;
-
-import com.google.common.base.Function;
import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import com.twitter.common.collections.Pair;
import com.twitter.common.testing.easymock.EasyMockTest;
import org.apache.aurora.gen.HostAttributes;
import org.apache.aurora.gen.ScheduleStatus;
import org.apache.aurora.scheduler.async.OfferQueue;
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.mesos.Offers;
import org.apache.aurora.scheduler.state.StateManager;
import org.apache.aurora.scheduler.storage.Storage.StorageException;
import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
import org.apache.aurora.scheduler.storage.testing.StorageTestUtil;
-import org.apache.mesos.Protos.Attribute;
-import org.apache.mesos.Protos.FrameworkID;
import org.apache.mesos.Protos.OfferID;
-import org.apache.mesos.Protos.Resource;
-import org.apache.mesos.Protos.SlaveID;
import org.apache.mesos.Protos.TaskID;
import org.apache.mesos.Protos.TaskState;
import org.apache.mesos.Protos.TaskStatus;
-import org.apache.mesos.Protos.Value.Range;
-import org.apache.mesos.Protos.Value.Ranges;
-import org.apache.mesos.Protos.Value.Scalar;
-import org.apache.mesos.Protos.Value.Text;
-import org.apache.mesos.Protos.Value.Type;
import org.junit.Before;
import org.junit.Test;
import static org.apache.aurora.gen.ScheduleStatus.FAILED;
import static org.apache.aurora.gen.ScheduleStatus.RUNNING;
-import static org.apache.aurora.scheduler.configuration.ConfigurationManager.HOST_CONSTRAINT;
-import static org.apache.mesos.Protos.Offer;
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertTrue;
public class UserTaskLauncherTest extends EasyMockTest {
- private static final String FRAMEWORK_ID = "FrameworkId";
-
- private static final SlaveID SLAVE_ID = SlaveID.newBuilder().setValue("SlaveId").build();
- private static final String SLAVE_HOST_1 = "SlaveHost1";
-
private static final String TASK_ID_A = "task_id_a";
private static final OfferID OFFER_ID = OfferID.newBuilder().setValue("OfferId").build();
- private static final HostOffer OFFER = createOffer(SLAVE_ID, SLAVE_HOST_1, 4, 1024, 1024);
+ private static final HostOffer OFFER = new HostOffer(
+ Offers.createOffer(4, 1024, 1024, Pair.of(80, 80)),
+ IHostAttributes.build(new HostAttributes()));
private OfferQueue offerQueue;
private StateManager stateManager;
@@ -179,42 +160,4 @@ public class UserTaskLauncherTest extends EasyMockTest {
.build();
launcher.statusUpdate(status);
}
-
- private static HostOffer createOffer(SlaveID slave, String slaveHost, double cpu,
- double ramMb, double diskMb) {
- return createOffer(slave, slaveHost, cpu, ramMb, diskMb,
- ImmutableSet.<Pair<Integer, Integer>>of());
- }
-
- private static HostOffer createOffer(SlaveID slave, String slaveHost, double cpu,
- double ramMb, double diskMb, Set<Pair<Integer, Integer>> ports) {
-
- Ranges portRanges = Ranges.newBuilder()
- .addAllRange(Iterables.transform(ports, new Function<Pair<Integer, Integer>, Range>() {
- @Override
- public Range apply(Pair<Integer, Integer> range) {
- return Range.newBuilder().setBegin(range.getFirst()).setEnd(range.getSecond()).build();
- }
- }))
- .build();
-
- Offer mesosOffer = Offer.newBuilder()
- .addResources(Resource.newBuilder().setType(Type.SCALAR).setName(Resources.CPUS)
- .setScalar(Scalar.newBuilder().setValue(cpu)))
- .addResources(Resource.newBuilder().setType(Type.SCALAR).setName(Resources.RAM_MB)
- .setScalar(Scalar.newBuilder().setValue(ramMb)))
- .addResources(Resource.newBuilder().setType(Type.SCALAR).setName(Resources.DISK_MB)
- .setScalar(Scalar.newBuilder().setValue(diskMb)))
- .addResources(Resource.newBuilder().setType(Type.RANGES).setName(Resources.PORTS)
- .setRanges(portRanges))
- .addAttributes(Attribute.newBuilder().setType(Type.TEXT)
- .setName(HOST_CONSTRAINT)
- .setText(Text.newBuilder().setValue(slaveHost)))
- .setSlaveId(slave)
- .setHostname(slaveHost)
- .setFrameworkId(FrameworkID.newBuilder().setValue(FRAMEWORK_ID).build())
- .setId(OFFER_ID)
- .build();
- return new HostOffer(mesosOffer, IHostAttributes.build(new HostAttributes()));
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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 65b4836..6575b7d 100644
--- a/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
+++ b/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
@@ -84,7 +84,7 @@ import org.apache.aurora.scheduler.log.Log.Position;
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.MesosTaskFactory.ExecutorSettings;
+import org.apache.aurora.scheduler.mesos.ExecutorSettings;
import org.apache.aurora.scheduler.storage.backup.BackupModule;
import org.apache.aurora.scheduler.storage.log.EntrySerializer;
import org.apache.aurora.scheduler.storage.log.LogStorageModule;
@@ -106,8 +106,6 @@ import org.junit.Test;
import static com.twitter.common.testing.easymock.EasyMockTest.createCapture;
-import static org.apache.aurora.scheduler.ResourceSlot.EXECUTOR_OVERHEAD_CPUS;
-import static org.apache.aurora.scheduler.ResourceSlot.EXECUTOR_OVERHEAD_RAM;
import static org.apache.mesos.Protos.FrameworkInfo;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createControl;
@@ -199,8 +197,8 @@ public class SchedulerIT extends BaseZooKeeperTest {
bind(DriverSettings.class).toInstance(SETTINGS);
bind(Log.class).toInstance(log);
Resources executorOverhead = new Resources(
- EXECUTOR_OVERHEAD_CPUS.get(),
- EXECUTOR_OVERHEAD_RAM.get(),
+ 0.1,
+ Amount.of(1L, Data.MB),
Amount.of(0L, Data.MB),
0);
bind(ExecutorSettings.class)
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/test/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImplTest.java b/src/test/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImplTest.java
index 36dbcf7..4c2448f 100644
--- a/src/test/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImplTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/async/preemptor/PreemptorImplTest.java
@@ -53,6 +53,7 @@ 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.SchedulingFilterImpl;
+import org.apache.aurora.scheduler.mesos.TaskExecutors;
import org.apache.aurora.scheduler.state.StateManager;
import org.apache.aurora.scheduler.storage.AttributeStore;
import org.apache.aurora.scheduler.storage.Storage;
@@ -130,7 +131,8 @@ public class PreemptorImplTest extends EasyMockTest {
PREEMPTION_DELAY,
clock,
statsProvider,
- new LiveClusterState(storageUtil.storage));
+ new LiveClusterState(storageUtil.storage),
+ TaskExecutors.NO_OVERHEAD_EXECUTOR);
preemptor.findPreemptionSlotFor(pendingTask.getAssignedTask().getTaskId(), emptyJob);
}
@@ -317,7 +319,7 @@ public class PreemptorImplTest extends EasyMockTest {
// Ensures a production task can preempt 2 tasks on the same host.
@Test
public void testProductionPreemptingManyNonProduction() throws Exception {
- schedulingFilter = new SchedulingFilterImpl();
+ schedulingFilter = new SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
ScheduledTask a1 = makeTask(USER_A, JOB_A, TASK_ID_A + "_a1");
a1.getAssignedTask().getTask().setNumCpus(1).setRamMb(512);
@@ -349,7 +351,7 @@ public class PreemptorImplTest extends EasyMockTest {
// Ensures we select the minimal number of tasks to preempt
@Test
public void testMinimalSetPreempted() throws Exception {
- schedulingFilter = new SchedulingFilterImpl();
+ schedulingFilter = new SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
ScheduledTask a1 = makeTask(USER_A, JOB_A, TASK_ID_A + "_a1");
a1.getAssignedTask().getTask().setNumCpus(4).setRamMb(4096);
@@ -384,7 +386,7 @@ public class PreemptorImplTest extends EasyMockTest {
// Ensures a production task *never* preempts a production task from another job.
@Test
public void testProductionJobNeverPreemptsProductionJob() throws Exception {
- schedulingFilter = new SchedulingFilterImpl();
+ schedulingFilter = new SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
ScheduledTask p1 = makeProductionTask(USER_A, JOB_A, TASK_ID_A + "_p1");
p1.getAssignedTask().getTask().setNumCpus(2).setRamMb(1024);
@@ -409,7 +411,7 @@ public class PreemptorImplTest extends EasyMockTest {
// Ensures that we can preempt if a task + offer can satisfy a pending task.
@Test
public void testPreemptWithOfferAndTask() throws Exception {
- schedulingFilter = new SchedulingFilterImpl();
+ schedulingFilter = new SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
setUpHost(HOST_A, RACK_A);
@@ -437,7 +439,7 @@ public class PreemptorImplTest extends EasyMockTest {
// Ensures we can preempt if two tasks and an offer can satisfy a pending task.
@Test
public void testPreemptWithOfferAndMultipleTasks() throws Exception {
- schedulingFilter = new SchedulingFilterImpl();
+ schedulingFilter = new SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
setUpHost(HOST_A, RACK_A);
@@ -470,7 +472,7 @@ public class PreemptorImplTest extends EasyMockTest {
// Ensures we don't preempt if a host has enough slack to satisfy a pending task.
@Test
public void testPreemptWithLargeOffer() throws Exception {
- schedulingFilter = new SchedulingFilterImpl();
+ schedulingFilter = new SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
setUpHost(HOST_A, RACK_A);
@@ -527,7 +529,8 @@ public class PreemptorImplTest extends EasyMockTest {
PREEMPTION_DELAY,
clock,
statsProvider,
- new LiveClusterState(storage));
+ new LiveClusterState(storage),
+ TaskExecutors.NO_OVERHEAD_EXECUTOR);
assertEquals(
Optional.<String>absent(),
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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 0b41156..ab7817f 100644
--- a/src/test/java/org/apache/aurora/scheduler/events/NotifyingSchedulingFilterTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/events/NotifyingSchedulingFilterTest.java
@@ -29,6 +29,7 @@ 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.AttributeStore;
import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
@@ -47,7 +48,7 @@ public class NotifyingSchedulingFilterTest extends EasyMockTest {
.setDiskMb(1024));
private static final String TASK_ID = "taskId";
private static final UnusedResource RESOURCE = new UnusedResource(
- ResourceSlot.from(TASK),
+ ResourceSlot.from(TASK, TaskExecutors.NO_OVERHEAD_EXECUTOR),
IHostAttributes.build(new HostAttributes().setHost("host").setMode(MaintenanceMode.NONE)));
private ResourceRequest request;
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/test/java/org/apache/aurora/scheduler/filter/SchedulingFilterImplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/filter/SchedulingFilterImplTest.java b/src/test/java/org/apache/aurora/scheduler/filter/SchedulingFilterImplTest.java
index 265c38d..52ee7c1 100644
--- a/src/test/java/org/apache/aurora/scheduler/filter/SchedulingFilterImplTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/filter/SchedulingFilterImplTest.java
@@ -21,8 +21,7 @@ import com.google.common.base.Optional;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
-import com.twitter.common.quantity.Amount;
-import com.twitter.common.quantity.Data;
+import com.twitter.common.collections.Pair;
import com.twitter.common.testing.easymock.EasyMockTest;
import org.apache.aurora.gen.AssignedTask;
@@ -42,6 +41,8 @@ import org.apache.aurora.scheduler.configuration.ConfigurationManager;
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.Offers;
+import org.apache.aurora.scheduler.mesos.TaskExecutors;
import org.apache.aurora.scheduler.storage.AttributeStore;
import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
@@ -88,10 +89,7 @@ public class SchedulingFilterImplTest extends EasyMockTest {
private static final long DEFAULT_RAM = 1000;
private static final long DEFAULT_DISK = 2000;
private static final ResourceSlot DEFAULT_OFFER = ResourceSlot.from(
- DEFAULT_CPUS,
- Amount.of(DEFAULT_RAM, Data.MB),
- Amount.of(DEFAULT_DISK, Data.MB),
- 0);
+ Offers.createOffer(DEFAULT_CPUS, DEFAULT_RAM, DEFAULT_DISK, Pair.of(80, 80)));
private AttributeAggregate emptyJob;
@@ -102,7 +100,7 @@ public class SchedulingFilterImplTest extends EasyMockTest {
@Before
public void setUp() {
- defaultFilter = new SchedulingFilterImpl();
+ defaultFilter = new SchedulingFilterImpl(TaskExecutors.NO_OVERHEAD_EXECUTOR);
attributeStore = createMock(AttributeStore.Mutable.class);
emptyJob = new AttributeAggregate(
Suppliers.ofInstance(ImmutableSet.<IScheduledTask>of()),
@@ -125,10 +123,7 @@ public class SchedulingFilterImplTest extends EasyMockTest {
control.replay();
ResourceSlot twoPorts = ResourceSlot.from(
- DEFAULT_CPUS,
- Amount.of(DEFAULT_RAM, Data.MB),
- Amount.of(DEFAULT_DISK, Data.MB),
- 2);
+ Offers.createOffer(DEFAULT_CPUS, DEFAULT_RAM, DEFAULT_DISK, Pair.of(80, 81)));
ITaskConfig noPortTask = ITaskConfig.build(makeTask(DEFAULT_CPUS, DEFAULT_RAM, DEFAULT_DISK)
.newBuilder()
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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 22faccf..ce3bea5 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.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.twitter.common.quantity.Amount;
import com.twitter.common.quantity.Data;
import org.apache.aurora.gen.AssignedTask;
@@ -27,10 +26,11 @@ import org.apache.aurora.gen.Identity;
import org.apache.aurora.gen.JobKey;
import org.apache.aurora.gen.MesosContainer;
import org.apache.aurora.gen.TaskConfig;
+import org.apache.aurora.scheduler.ResourceSlot;
import org.apache.aurora.scheduler.configuration.Resources;
-import org.apache.aurora.scheduler.mesos.MesosTaskFactory.ExecutorSettings;
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.CommandInfo;
import org.apache.mesos.Protos.CommandInfo.URI;
import org.apache.mesos.Protos.ExecutorInfo;
@@ -39,15 +39,14 @@ import org.apache.mesos.Protos.TaskInfo;
import org.junit.Before;
import org.junit.Test;
-import static org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl.MIN_TASK_RESOURCES;
-import static org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl.MIN_THERMOS_RESOURCES;
+import static org.apache.aurora.scheduler.ResourceSlot.MIN_THERMOS_RESOURCES;
+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.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
public class MesosTaskFactoryImplTest {
- private static final String EXECUTOR_PATH = "/twitter/fake/executor.pex";
- private static final String EXECUTOR_WRAPPER_PATH = "/twitter/fake/executor.sh";
+ private static final String EXECUTOR_WRAPPER_PATH = "/fake/executor_wrapper.sh";
private static final IAssignedTask TASK = IAssignedTask.build(new AssignedTask()
.setInstanceId(2)
.setTaskId("task-id")
@@ -63,22 +62,11 @@ public class MesosTaskFactoryImplTest {
.setContainer(Container.mesos(new MesosContainer()))
.setRequestedPorts(ImmutableSet.of("http"))));
private static final IAssignedTask TASK_WITH_DOCKER = IAssignedTask.build(TASK.newBuilder()
- .setTask(
- new TaskConfig(TASK.getTask().newBuilder())
- .setContainer(Container.docker(new DockerContainer("testimage")))));
+ .setTask(
+ new TaskConfig(TASK.getTask().newBuilder())
+ .setContainer(Container.docker(new DockerContainer("testimage")))));
private static final SlaveID SLAVE = SlaveID.newBuilder().setValue("slave-id").build();
- private static final Resources SOME_EXECUTOR_OVERHEAD = new Resources(
- 0.01,
- Amount.of(256L, Data.MB),
- Amount.of(0L, Data.MB),
- 0);
-
- private static final Resources NO_EXECUTOR_OVERHEAD = new Resources(
- 0,
- Amount.of(0L, Data.MB),
- Amount.of(0L, Data.MB),
- 0);
private MesosTaskFactory taskFactory;
private ExecutorSettings config;
@@ -87,30 +75,27 @@ public class MesosTaskFactoryImplTest {
.setExecutorId(MesosTaskFactoryImpl.getExecutorId(TASK.getTaskId()))
.setName(MesosTaskFactoryImpl.EXECUTOR_NAME)
.setSource(MesosTaskFactoryImpl.getInstanceSourceName(TASK.getTask(), TASK.getInstanceId()))
- .addAllResources(MIN_THERMOS_RESOURCES.toResourceList())
+ .addAllResources(MesosTaskFactoryImpl.RESOURCES_EPSILON.toResourceList())
.setCommand(CommandInfo.newBuilder()
.setValue("./executor.pex")
.setShell(true)
- .addUris(URI.newBuilder().setValue(EXECUTOR_PATH).setExecutable(true)))
+ .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.sh")
+ .setValue("./executor_wrapper.sh")
.setShell(true)
- .addUris(URI.newBuilder().setValue(EXECUTOR_PATH).setExecutable(true))
+ .addUris(URI.newBuilder().setValue(NO_OVERHEAD_EXECUTOR.getExecutorPath())
+ .setExecutable(true))
.addUris(URI.newBuilder().setValue(EXECUTOR_WRAPPER_PATH).setExecutable(true)))
.build();
@Before
public void setUp() {
- config = new ExecutorSettings(
- EXECUTOR_PATH,
- ImmutableList.<String>of(),
- "/var/run/thermos",
- Optional.<String>absent(),
- SOME_EXECUTOR_OVERHEAD);
+ config = TaskExecutors.SOME_OVERHEAD_EXECUTOR;
}
@Test
@@ -118,117 +103,64 @@ public class MesosTaskFactoryImplTest {
taskFactory = new MesosTaskFactoryImpl(config);
TaskInfo task = taskFactory.createFrom(TASK, SLAVE);
assertEquals(DEFAULT_EXECUTOR, task.getExecutor());
-
- double taskCPU = config.getExecutorOverhead().getNumCpus()
- + TASK.getTask().getNumCpus()
- - MIN_THERMOS_RESOURCES.getNumCpus();
- long taskRamMB = config.getExecutorOverhead().getRam().as(Data.MB)
- + TASK.getTask().getRamMb()
- - MIN_THERMOS_RESOURCES.getRam().as(Data.MB);
- long taskDiskMB = config.getExecutorOverhead().getDisk().as(Data.MB)
- + TASK.getTask().getDiskMb()
- - MIN_THERMOS_RESOURCES.getDisk().as(Data.MB);
-
- assertTrue(taskCPU > 0.0);
- assertTrue(taskRamMB > 0);
- assertTrue(taskDiskMB > 0);
-
- assertEquals(ImmutableSet.of(
- Resources.makeMesosResource(Resources.CPUS, taskCPU),
- Resources.makeMesosResource(Resources.DISK_MB, taskDiskMB),
- Resources.makeMesosResource(Resources.RAM_MB, taskRamMB),
- Resources.makeMesosRangeResource(
- Resources.PORTS,
- ImmutableSet.copyOf(TASK.getAssignedPorts().values()))
- ),
- ImmutableSet.copyOf(task.getResourcesList()));
+ checkTaskResources(TASK.getTask(), task);
}
@Test
public void testCreateFromPortsUnset() {
taskFactory = new MesosTaskFactoryImpl(config);
AssignedTask assignedTask = TASK.newBuilder();
+ assignedTask.getTask().unsetRequestedPorts();
assignedTask.unsetAssignedPorts();
TaskInfo task = taskFactory.createFrom(IAssignedTask.build(assignedTask), SLAVE);
-
- double taskCPU = config.getExecutorOverhead().getNumCpus()
- + TASK.getTask().getNumCpus()
- - MIN_THERMOS_RESOURCES.getNumCpus();
- long taskRamMB = config.getExecutorOverhead().getRam().as(Data.MB)
- + TASK.getTask().getRamMb()
- - MIN_THERMOS_RESOURCES.getRam().as(Data.MB);
- long taskDiskMB = config.getExecutorOverhead().getDisk().as(Data.MB)
- + TASK.getTask().getDiskMb()
- - MIN_THERMOS_RESOURCES.getDisk().as(Data.MB);
-
- assertTrue(taskCPU > 0.0);
- assertTrue(taskRamMB > 0);
- assertTrue(taskDiskMB > 0);
-
- assertEquals(DEFAULT_EXECUTOR, task.getExecutor());
- assertEquals(ImmutableSet.of(
- Resources.makeMesosResource(Resources.CPUS, taskCPU),
- Resources.makeMesosResource(Resources.DISK_MB, taskDiskMB),
- Resources.makeMesosResource(Resources.RAM_MB, taskRamMB)
- ),
- ImmutableSet.copyOf(task.getResourcesList()));
+ checkTaskResources(ITaskConfig.build(assignedTask.getTask()), task);
}
@Test
public void testExecutorInfoNoOverhead() {
// 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 = new ExecutorSettings(
- EXECUTOR_PATH,
- ImmutableList.<String>of(),
- "/var/run/thermos",
- Optional.<String>absent(),
- NO_EXECUTOR_OVERHEAD);
+ config = NO_OVERHEAD_EXECUTOR;
taskFactory = new MesosTaskFactoryImpl(config);
TaskInfo task = taskFactory.createFrom(TASK, SLAVE);
assertEquals(DEFAULT_EXECUTOR, task.getExecutor());
- double taskCPU = config.getExecutorOverhead().getNumCpus()
- + TASK.getTask().getNumCpus()
- - MIN_THERMOS_RESOURCES.getNumCpus();
+ // 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));
+ checkTaskResources(ITaskConfig.build(dummyTask), task);
+ }
- long taskDiskMB = config.getExecutorOverhead().getDisk().as(Data.MB)
- + TASK.getTask().getDiskMb()
- - MIN_THERMOS_RESOURCES.getDisk().as(Data.MB);
+ @Test
+ public void testSmallTaskUpsizing() {
+ // A very small task should be upsized to support the minimum resources required by the
+ // executor.
- assertTrue(taskCPU > 0.0);
- assertTrue(taskDiskMB > 0);
+ config = NO_OVERHEAD_EXECUTOR;
+ taskFactory = new MesosTaskFactoryImpl(config);
- assertEquals(ImmutableSet.of(
- Resources.makeMesosResource(Resources.CPUS, taskCPU),
- Resources.makeMesosResource(Resources.RAM_MB, MIN_TASK_RESOURCES.getRam().as(Data.MB)),
- Resources.makeMesosResource(Resources.DISK_MB, taskDiskMB),
- Resources.makeMesosRangeResource(
- Resources.PORTS,
- ImmutableSet.copyOf(TASK.getAssignedPorts().values()))
- ),
- ImmutableSet.copyOf(task.getResourcesList()));
+ AssignedTask builder = TASK.newBuilder();
+ builder.getTask()
+ .setNumCpus(0.001)
+ .setRamMb(1)
+ .setDiskMb(0)
+ .setRequestedPorts(ImmutableSet.<String>of());
+ IAssignedTask assignedTask =
+ IAssignedTask.build(builder.setAssignedPorts(ImmutableMap.<String, Integer>of()));
+
+ assertEquals(
+ MIN_THERMOS_RESOURCES,
+ getTotalTaskResources(taskFactory.createFrom(assignedTask, SLAVE)));
}
- @Test
- public void testMaxElements() {
- Resources highRAM = new Resources(1, Amount.of(8L, Data.GB), Amount.of(10L, Data.MB), 0);
- Resources rest = new Resources(10, Amount.of(1L, Data.MB), Amount.of(10L, Data.GB), 1);
-
- Resources result = MesosTaskFactoryImpl.maxElements(highRAM, rest);
- assertEquals(result.getNumCpus(), 10, 0.001);
- assertEquals(result.getRam(), Amount.of(8L, Data.GB));
- assertEquals(result.getDisk(), Amount.of(10L, Data.GB));
- assertEquals(result.getNumPorts(), 1);
+ private void checkTaskResources(ITaskConfig task, TaskInfo taskInfo) {
+ assertEquals(
+ Resources.sum(Resources.from(task), config.getExecutorOverhead()),
+ getTotalTaskResources(taskInfo));
}
private TaskInfo getDockerTaskInfo() {
- config = new ExecutorSettings(
- EXECUTOR_PATH,
- ImmutableList.<String>of(),
- "/var/run/thermos",
- Optional.<String>absent(),
- SOME_EXECUTOR_OVERHEAD);
+ config = TaskExecutors.SOME_OVERHEAD_EXECUTOR;
taskFactory = new MesosTaskFactoryImpl(config);
return taskFactory.createFrom(TASK_WITH_DOCKER, SLAVE);
}
@@ -246,19 +178,25 @@ public class MesosTaskFactoryImplTest {
ImmutableList.<String>of(),
"",
Optional.<String>absent(),
- SOME_EXECUTOR_OVERHEAD);
+ Resources.NONE);
}
@Test
public void testExecutorAndWrapper() {
config = new ExecutorSettings(
EXECUTOR_WRAPPER_PATH,
- ImmutableList.of(EXECUTOR_PATH),
+ ImmutableList.of(SOME_OVERHEAD_EXECUTOR.getExecutorPath()),
"/var/run/thermos",
Optional.<String>absent(),
- SOME_EXECUTOR_OVERHEAD);
+ SOME_OVERHEAD_EXECUTOR.getExecutorOverhead());
taskFactory = new MesosTaskFactoryImpl(config);
TaskInfo taskInfo = taskFactory.createFrom(TASK, SLAVE);
assertEquals(EXECUTOR_WITH_WRAPPER, taskInfo.getExecutor());
}
+
+ private static Resources getTotalTaskResources(TaskInfo task) {
+ Resources taskResources = Resources.from(task.getResourcesList());
+ Resources executorResources = Resources.from(task.getExecutor().getResourcesList());
+ return Resources.sum(taskResources, executorResources);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/test/java/org/apache/aurora/scheduler/mesos/Offers.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/mesos/Offers.java b/src/test/java/org/apache/aurora/scheduler/mesos/Offers.java
new file mode 100644
index 0000000..83eec5d
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/mesos/Offers.java
@@ -0,0 +1,65 @@
+/**
+ * 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.twitter.common.collections.Pair;
+
+import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.mesos.Protos;
+import org.apache.mesos.Protos.Offer;
+import org.apache.mesos.Protos.OfferID;
+import org.apache.mesos.Protos.Resource;
+import org.apache.mesos.Protos.SlaveID;
+import org.apache.mesos.Protos.Value.Range;
+import org.apache.mesos.Protos.Value.Ranges;
+import org.apache.mesos.Protos.Value.Scalar;
+import org.apache.mesos.Protos.Value.Type;
+
+import static org.apache.aurora.scheduler.configuration.ConfigurationManager.HOST_CONSTRAINT;
+
+public final class Offers {
+ private Offers() {
+ // Utility class.
+ }
+
+ public static Offer createOffer(
+ double cpu,
+ double ramMb,
+ double diskMb,
+ Pair<Integer, Integer> portRange) {
+
+ Ranges portRanges = Ranges.newBuilder()
+ .addRange(Range
+ .newBuilder().setBegin(portRange.getFirst()).setEnd(portRange.getSecond()).build())
+ .build();
+
+ return Offer.newBuilder()
+ .addResources(Resource.newBuilder().setType(Type.SCALAR).setName(Resources.CPUS)
+ .setScalar(Scalar.newBuilder().setValue(cpu)))
+ .addResources(Resource.newBuilder().setType(Type.SCALAR).setName(Resources.RAM_MB)
+ .setScalar(Scalar.newBuilder().setValue(ramMb)))
+ .addResources(Resource.newBuilder().setType(Type.SCALAR).setName(Resources.DISK_MB)
+ .setScalar(Scalar.newBuilder().setValue(diskMb)))
+ .addResources(Resource.newBuilder().setType(Type.RANGES).setName(Resources.PORTS)
+ .setRanges(portRanges))
+ .addAttributes(Protos.Attribute.newBuilder().setType(Type.TEXT)
+ .setName(HOST_CONSTRAINT)
+ .setText(Protos.Value.Text.newBuilder().setValue("slavehost")))
+ .setSlaveId(SlaveID.newBuilder().setValue("SlaveId").build())
+ .setHostname("slavehost")
+ .setFrameworkId(Protos.FrameworkID.newBuilder().setValue("framework-id").build())
+ .setId(OfferID.newBuilder().setValue("OfferId").build())
+ .build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/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
new file mode 100644
index 0000000..efe62ce
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
@@ -0,0 +1,47 @@
+/**
+ * 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.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Data;
+
+import org.apache.aurora.scheduler.configuration.Resources;
+
+/**
+ * Utility class to contain constants related to setting up executor settings.
+ */
+public final class TaskExecutors {
+
+ private TaskExecutors() {
+ // Utility class.
+ }
+
+ private static final String EXECUTOR_PATH = "/fake/executor.pex";
+
+ public static final ExecutorSettings NO_OVERHEAD_EXECUTOR = new ExecutorSettings(
+ EXECUTOR_PATH,
+ ImmutableList.<String>of(),
+ "/var/run/thermos",
+ Optional.<String>absent(),
+ Resources.NONE);
+
+ public static final ExecutorSettings SOME_OVERHEAD_EXECUTOR = new ExecutorSettings(
+ EXECUTOR_PATH,
+ ImmutableList.<String>of(),
+ "/var/run/thermos",
+ Optional.<String>absent(),
+ new Resources(0.01, Amount.of(256L, Data.MB), Amount.of(0L, Data.MB), 0));
+}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/test/sh/org/apache/aurora/e2e/http/http_example_updated.aurora
----------------------------------------------------------------------
diff --git a/src/test/sh/org/apache/aurora/e2e/http/http_example_updated.aurora b/src/test/sh/org/apache/aurora/e2e/http/http_example_updated.aurora
index 67d3dbb..98f5c47 100644
--- a/src/test/sh/org/apache/aurora/e2e/http/http_example_updated.aurora
+++ b/src/test/sh/org/apache/aurora/e2e/http/http_example_updated.aurora
@@ -35,7 +35,7 @@ health_check_config = HealthCheckConfig(initial_interval_secs=5, interval_secs=1
job = Job(
name = 'http_example',
cluster = 'devcluster',
- instances = 4,
+ instances = 3,
update_config = update_config,
health_check_config = health_check_config,
task = test_task,
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b39f6ee1/src/test/sh/org/apache/aurora/e2e/validate_serverset.py
----------------------------------------------------------------------
diff --git a/src/test/sh/org/apache/aurora/e2e/validate_serverset.py b/src/test/sh/org/apache/aurora/e2e/validate_serverset.py
index 66fa965..352cef8 100644
--- a/src/test/sh/org/apache/aurora/e2e/validate_serverset.py
+++ b/src/test/sh/org/apache/aurora/e2e/validate_serverset.py
@@ -32,14 +32,14 @@ def wait_until_znodes(count, timeout=30):
return []
-# job is created with 4 znodes.
-znodes = wait_until_znodes(4, timeout=10)
+# job is created with 3 znodes.
+znodes = wait_until_znodes(3, timeout=10)
if not znodes:
sys.exit(DID_NOT_REGISTER)
client.delete(znodes[0])
-znodes = wait_until_znodes(4, timeout=10)
+znodes = wait_until_znodes(3, timeout=10)
if not znodes:
sys.exit(DID_NOT_RECOVER_FROM_EXPIRY)