aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wfar...@apache.org
Subject aurora git commit: When scheduling, skip offers with no CPU and no mem
Date Thu, 19 Oct 2017 01:14:07 GMT
Repository: aurora
Updated Branches:
  refs/heads/master 15cb049f3 -> 0622f3483


When scheduling, skip offers with no CPU and no mem

There's no reason for us to evaluate offers with no CPUs or memory,
so reject them early in the offer lifecycle.

This is an incremental performance optimization, but it may net significant
improvements based on observations in some very large clusters.

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


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

Branch: refs/heads/master
Commit: 0622f3483d2ec9d13f681c8791e7ce3cb9a7db77
Parents: 15cb049
Author: Bill Farner <wfarner@apache.org>
Authored: Wed Oct 18 18:14:02 2017 -0700
Committer: Bill Farner <wfarner@apache.org>
Committed: Wed Oct 18 18:14:02 2017 -0700

----------------------------------------------------------------------
 .../org/apache/aurora/scheduler/HostOffer.java  | 23 ++++-
 .../aurora/scheduler/http/Utilization.java      |  2 +-
 .../preemptor/PreemptionVictimFilter.java       |  2 +-
 .../aurora/scheduler/resources/ResourceBag.java |  2 +-
 .../aurora/scheduler/state/TaskAssigner.java    |  8 +-
 .../scheduler/stats/TaskStatCalculator.java     |  2 +-
 .../apache/aurora/scheduler/HostOfferTest.java  | 88 ++++++++++++++++++++
 .../scheduler/offers/OfferManagerImplTest.java  | 37 +++++---
 .../apache/aurora/scheduler/offers/Offers.java  |  8 ++
 .../scheduler/resources/ResourceTestUtil.java   |  2 +-
 .../state/FirstFitTaskAssignerTest.java         | 63 +++++++++-----
 11 files changed, 198 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/main/java/org/apache/aurora/scheduler/HostOffer.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/HostOffer.java b/src/main/java/org/apache/aurora/scheduler/HostOffer.java
index bc40d07..acc637a 100644
--- a/src/main/java/org/apache/aurora/scheduler/HostOffer.java
+++ b/src/main/java/org/apache/aurora/scheduler/HostOffer.java
@@ -24,6 +24,7 @@ import com.google.common.cache.LoadingCache;
 
 import org.apache.aurora.scheduler.base.Conversions;
 import org.apache.aurora.scheduler.resources.ResourceBag;
+import org.apache.aurora.scheduler.resources.ResourceType;
 import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
 
 import static java.util.Objects.requireNonNull;
@@ -40,9 +41,17 @@ public class HostOffer {
   private final IHostAttributes hostAttributes;
   private final LoadingCache<TierInfo, ResourceBag> resourceBagCache;
 
+  // Offers lacking CPU or mem are flagged so that they may be efficiently ignored during
+  // scheduling.  However, they are retained for other purposes such as preemption and cluster
+  // stats.
+  // When nonZeroCpuAndMem=true, it means that _any_ CPU or mem resource is available, regardless
+  // of whether the resource is revocable.
+  private final boolean nonZeroCpuAndMem;
+
   public HostOffer(Offer offer, IHostAttributes hostAttributes) {
     this.offer = requireNonNull(offer);
     this.hostAttributes = requireNonNull(hostAttributes);
+    this.nonZeroCpuAndMem = offerHasCpuAndMem(offer);
     this.resourceBagCache = CacheBuilder.newBuilder().build(
         new CacheLoader<TierInfo, ResourceBag>() {
           @Override
@@ -52,6 +61,12 @@ public class HostOffer {
         });
   }
 
+  private static boolean offerHasCpuAndMem(Offer offer) {
+    ResourceBag resources = bagFromMesosResources(offer.getResourcesList());
+    return resources.valueOf(ResourceType.CPUS) > 0.0
+        && resources.valueOf(ResourceType.RAM_MB) > 0.0;
+  }
+
   public Offer getOffer() {
     return offer;
   }
@@ -60,6 +75,10 @@ public class HostOffer {
     return hostAttributes;
   }
 
+  public boolean hasCpuAndMem() {
+    return nonZeroCpuAndMem;
+  }
+
   public ResourceBag getResourceBag(TierInfo tierInfo) {
     return resourceBagCache.getUnchecked(tierInfo);
   }
@@ -79,7 +98,8 @@ public class HostOffer {
     }
     HostOffer other = (HostOffer) o;
     return Objects.equals(offer, other.offer)
-        && Objects.equals(hostAttributes, other.hostAttributes);
+        && Objects.equals(hostAttributes, other.hostAttributes)
+        && nonZeroCpuAndMem == other.nonZeroCpuAndMem;
   }
 
   @Override
@@ -92,6 +112,7 @@ public class HostOffer {
     return MoreObjects.toStringHelper(this)
         .add("offer", offer)
         .add("hostAttributes", hostAttributes)
+        .add("nonZeroCpuAndMem", nonZeroCpuAndMem)
         .toString();
   }
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/main/java/org/apache/aurora/scheduler/http/Utilization.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/Utilization.java b/src/main/java/org/apache/aurora/scheduler/http/Utilization.java
index 3c77e29..efacd8c 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/Utilization.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/Utilization.java
@@ -136,7 +136,7 @@ public class Utilization {
     }
 
     private long valueOf(ResourceType type) {
-      return getBag().valueOf(type).longValue();
+      return (long) getBag().valueOf(type);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/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 1b12397..13ccbff 100644
--- a/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilter.java
+++ b/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilter.java
@@ -150,7 +150,7 @@ public interface PreemptionVictimFilter {
         boolean allLessOrEqual = true;
 
         for (ResourceType type : types) {
-          int compare = left.valueOf(type).compareTo(right.valueOf(type));
+          int compare = Double.compare(left.valueOf(type), right.valueOf(type));
           if (compare != 0) {
             allZero = false;
           }

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/main/java/org/apache/aurora/scheduler/resources/ResourceBag.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/resources/ResourceBag.java b/src/main/java/org/apache/aurora/scheduler/resources/ResourceBag.java
index d5db81b..eecd3f3 100644
--- a/src/main/java/org/apache/aurora/scheduler/resources/ResourceBag.java
+++ b/src/main/java/org/apache/aurora/scheduler/resources/ResourceBag.java
@@ -108,7 +108,7 @@ public class ResourceBag {
    * @param type Resource type to get value for.
    * @return Resource value or 0.0 if no mapping for {@code type} is found.
    */
-  public Double valueOf(ResourceType type) {
+  public double valueOf(ResourceType type) {
     return resourceVectors.getOrDefault(type, 0.0);
   }
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/main/java/org/apache/aurora/scheduler/state/TaskAssigner.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/state/TaskAssigner.java b/src/main/java/org/apache/aurora/scheduler/state/TaskAssigner.java
index e35720f..549fd29 100644
--- a/src/main/java/org/apache/aurora/scheduler/state/TaskAssigner.java
+++ b/src/main/java/org/apache/aurora/scheduler/state/TaskAssigner.java
@@ -292,7 +292,12 @@ public interface TaskAssigner {
       if (remainingTasks.hasNext()) {
         IAssignedTask task = remainingTasks.next();
         for (HostOffer offer : offerManager.getOffers(groupKey)) {
-          evaluatedOffers.incrementAndGet();
+
+          if (!offer.hasCpuAndMem()) {
+            // This offer lacks any type of CPU or mem resource, and therefore will never
match
+            // a task.
+            continue;
+          }
 
           String agentId = offer.getOffer().getAgentId().getValue();
 
@@ -309,6 +314,7 @@ public interface TaskAssigner {
             continue;
           }
 
+          evaluatedOffers.incrementAndGet();
           try {
             boolean offerUsed = evaluateOffer(
                 storeProvider, tierInfo, resourceRequest, groupKey, task, offer, assignmentResult);

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/main/java/org/apache/aurora/scheduler/stats/TaskStatCalculator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/stats/TaskStatCalculator.java b/src/main/java/org/apache/aurora/scheduler/stats/TaskStatCalculator.java
index b98aaaf..ac5cf24 100644
--- a/src/main/java/org/apache/aurora/scheduler/stats/TaskStatCalculator.java
+++ b/src/main/java/org/apache/aurora/scheduler/stats/TaskStatCalculator.java
@@ -45,7 +45,7 @@ class TaskStatCalculator implements Runnable {
       ResourceType type = r.getKey();
       String metricName =
           Joiner.on("_").join(prefix, type.getAuroraName(), type.getAuroraStatUnit()).toLowerCase();
-      counters.get(metricName).set(metric.getBag().valueOf(type).longValue());
+      counters.get(metricName).set((long) metric.getBag().valueOf(type));
     });
   }
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/test/java/org/apache/aurora/scheduler/HostOfferTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/HostOfferTest.java b/src/test/java/org/apache/aurora/scheduler/HostOfferTest.java
new file mode 100644
index 0000000..d6e5ff4
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/HostOfferTest.java
@@ -0,0 +1,88 @@
+/**
+ * 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 java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+import org.apache.aurora.gen.HostAttributes;
+import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
+import org.junit.Test;
+
+import static org.apache.aurora.gen.MaintenanceMode.NONE;
+import static org.apache.aurora.scheduler.resources.ResourceTestUtil.mesosScalar;
+import static org.apache.aurora.scheduler.resources.ResourceTestUtil.offer;
+import static org.apache.aurora.scheduler.resources.ResourceType.CPUS;
+import static org.apache.aurora.scheduler.resources.ResourceType.RAM_MB;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class HostOfferTest {
+
+  private static final IHostAttributes HOST_ATTRIBUTES_A =
+      IHostAttributes.build(new HostAttributes().setMode(NONE).setHost("host-a"));
+
+  @Test
+  public void testHasCpuOrMem() {
+    List<HostOffer> noCpuOrMem = ImmutableList.of(
+        new HostOffer(offer("no-resources"), HOST_ATTRIBUTES_A),
+        new HostOffer(
+            offer("no-cpu-explicit", mesosScalar(CPUS, 0), mesosScalar(RAM_MB, 1024)),
+            HOST_ATTRIBUTES_A),
+        new HostOffer(
+            offer("no-cpu-implicit", mesosScalar(RAM_MB, 1024)),
+            HOST_ATTRIBUTES_A),
+        new HostOffer(
+            offer("no-mem-explicit", mesosScalar(CPUS, 10), mesosScalar(RAM_MB, 0)),
+            HOST_ATTRIBUTES_A),
+        new HostOffer(
+            offer("no-mem-implicit", mesosScalar(CPUS, 10)),
+            HOST_ATTRIBUTES_A));
+    for (HostOffer offer : noCpuOrMem) {
+      assertFalse(offer.hasCpuAndMem());
+    }
+
+    List<HostOffer> hasCpuOrMem = ImmutableList.of(
+        new HostOffer(
+            offer(
+                "mixed-cpu-implicit-1",
+                mesosScalar(CPUS, 10, true),
+                mesosScalar(RAM_MB, 1024)),
+            HOST_ATTRIBUTES_A),
+        new HostOffer(
+            offer(
+                "mixed-cpu-implicit-2",
+                mesosScalar(CPUS, 10, false),
+                mesosScalar(RAM_MB, 1024)),
+            HOST_ATTRIBUTES_A),
+        new HostOffer(
+            offer(
+                "mixed-cpu-explicit-1",
+                mesosScalar(CPUS, 0, false),
+                mesosScalar(CPUS, 10, true),
+                mesosScalar(RAM_MB, 1024)),
+            HOST_ATTRIBUTES_A),
+        new HostOffer(
+            offer(
+                "mixed-cpu-explicit-2",
+                mesosScalar(CPUS, 10, false),
+                mesosScalar(CPUS, 0, true),
+                mesosScalar(RAM_MB, 1024)),
+            HOST_ATTRIBUTES_A));
+    for (HostOffer offer : hasCpuOrMem) {
+      assertTrue(offer.hasCpuAndMem());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/test/java/org/apache/aurora/scheduler/offers/OfferManagerImplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/offers/OfferManagerImplTest.java b/src/test/java/org/apache/aurora/scheduler/offers/OfferManagerImplTest.java
index 2cfdc09..815a7e8 100644
--- a/src/test/java/org/apache/aurora/scheduler/offers/OfferManagerImplTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/offers/OfferManagerImplTest.java
@@ -436,15 +436,19 @@ public class OfferManagerImplTest extends EasyMockTest {
     OfferManager cpuManager = createOrderedManager(ImmutableList.of(OfferOrder.CPU));
 
     HostOffer small = setMode(new HostOffer(
-        offer("host1", mesosScalar(CPUS, 1.0), mesosScalar(CPUS, 24.0, true)),
+        offer(
+            "host1",
+            mesosScalar(CPUS, 1.0),
+            mesosScalar(CPUS, 24.0, true),
+            mesosScalar(RAM_MB, 1024)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer medium = setMode(new HostOffer(
-        offer("host2", mesosScalar(CPUS, 5.0)),
+        offer("host2", mesosScalar(CPUS, 5.0), mesosScalar(RAM_MB, 1024)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer large = setMode(new HostOffer(
-        offer("host3", mesosScalar(CPUS, 10.0)),
+        offer("host3", mesosScalar(CPUS, 10.0), mesosScalar(RAM_MB, 1024)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     control.replay();
@@ -465,15 +469,23 @@ public class OfferManagerImplTest extends EasyMockTest {
     OfferManager cpuManager = createOrderedManager(ImmutableList.of(OfferOrder.REVOCABLE_CPU));
 
     HostOffer small = setMode(new HostOffer(
-        offer("host2", mesosScalar(CPUS, 5.0), mesosScalar(CPUS, 23.0, true)),
+        offer(
+            "host2",
+            mesosScalar(CPUS, 5.0),
+            mesosScalar(CPUS, 23.0, true),
+            mesosScalar(RAM_MB, 1024)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer medium = setMode(new HostOffer(
-        offer("host1", mesosScalar(CPUS, 3.0), mesosScalar(CPUS, 24.0, true)),
+        offer(
+            "host1",
+            mesosScalar(CPUS, 3.0),
+            mesosScalar(CPUS, 24.0, true),
+            mesosScalar(RAM_MB, 1024)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer large = setMode(new HostOffer(
-        offer("host3", mesosScalar(CPUS, 1.0)),
+        offer("host3", mesosScalar(CPUS, 1.0), mesosScalar(RAM_MB, 1024)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     control.replay();
@@ -493,15 +505,15 @@ public class OfferManagerImplTest extends EasyMockTest {
     OfferManager cpuManager = createOrderedManager(ImmutableList.of(OfferOrder.DISK));
 
     HostOffer small = setMode(new HostOffer(
-        offer("host1", mesosScalar(DISK_MB, 1.0)),
+        offer("host1", mesosScalar(CPUS, 1), mesosScalar(RAM_MB, 1), mesosScalar(DISK_MB,
1.0)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer medium = setMode(new HostOffer(
-        offer("host2", mesosScalar(DISK_MB, 5.0)),
+        offer("host2", mesosScalar(CPUS, 1), mesosScalar(RAM_MB, 1), mesosScalar(DISK_MB,
5.0)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer large = setMode(new HostOffer(
-        offer("host3", mesosScalar(DISK_MB, 10.0)),
+        offer("host3", mesosScalar(CPUS, 1), mesosScalar(RAM_MB, 1), mesosScalar(DISK_MB,
10.0)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     control.replay();
@@ -521,15 +533,15 @@ public class OfferManagerImplTest extends EasyMockTest {
     OfferManager cpuManager = createOrderedManager(ImmutableList.of(OfferOrder.MEMORY));
 
     HostOffer small = setMode(new HostOffer(
-        offer("host1", mesosScalar(RAM_MB, 1.0)),
+        offer("host1", mesosScalar(CPUS, 10), mesosScalar(RAM_MB, 1.0)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer medium = setMode(new HostOffer(
-        offer("host2", mesosScalar(RAM_MB, 5.0)),
+        offer("host2", mesosScalar(CPUS, 10), mesosScalar(RAM_MB, 5.0)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     HostOffer large = setMode(new HostOffer(
-        offer("host3", mesosScalar(RAM_MB, 10.0)),
+        offer("host3", mesosScalar(CPUS, 10), mesosScalar(RAM_MB, 10.0)),
         HOST_ATTRIBUTES_A), DRAINING);
 
     control.replay();
@@ -567,6 +579,7 @@ public class OfferManagerImplTest extends EasyMockTest {
         offer("host3",
             mesosScalar(CPUS, 10.0),
             mesosScalar(CPUS, 1.0),
+            mesosScalar(RAM_MB, 1024),
             mesosScalar(DISK_MB, 1.0)),
         HOST_ATTRIBUTES_A), DRAINING);
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/test/java/org/apache/aurora/scheduler/offers/Offers.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/offers/Offers.java b/src/test/java/org/apache/aurora/scheduler/offers/Offers.java
index 129b443..17d4f08 100644
--- a/src/test/java/org/apache/aurora/scheduler/offers/Offers.java
+++ b/src/test/java/org/apache/aurora/scheduler/offers/Offers.java
@@ -13,11 +13,16 @@
  */
 package org.apache.aurora.scheduler.offers;
 
+import com.google.common.collect.ImmutableList;
+
+import org.apache.aurora.scheduler.resources.ResourceType;
 import org.apache.mesos.v1.Protos.AgentID;
 import org.apache.mesos.v1.Protos.FrameworkID;
 import org.apache.mesos.v1.Protos.Offer;
 import org.apache.mesos.v1.Protos.OfferID;
 
+import static org.apache.aurora.scheduler.resources.ResourceTestUtil.mesosScalar;
+
 /**
  * Utility class for creating resource offers in unit tests.
  */
@@ -38,6 +43,9 @@ public final class Offers {
         .setFrameworkId(FrameworkID.newBuilder().setValue("framework_id"))
         .setAgentId(AgentID.newBuilder().setValue("slave_id-" + offerId))
         .setHostname(hostName)
+        .addAllResources(ImmutableList.of(
+            mesosScalar(ResourceType.CPUS, 10),
+            mesosScalar(ResourceType.RAM_MB, 1024)))
         .build();
   }
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java b/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java
index 765a527..9739e91 100644
--- a/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java
+++ b/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java
@@ -137,7 +137,7 @@ public final class ResourceTestUtil {
 
   public static Protos.Offer offer(String agentId, Protos.Resource... resources) {
     return Protos.Offer.newBuilder()
-        .setId(Protos.OfferID.newBuilder().setValue("offer-id"))
+        .setId(Protos.OfferID.newBuilder().setValue("offer-id-" + agentId))
         .setFrameworkId(Protos.FrameworkID.newBuilder().setValue("framework-id"))
         .setAgentId(Protos.AgentID.newBuilder().setValue(agentId))
         .setHostname("hostname")

http://git-wip-us.apache.org/repos/asf/aurora/blob/0622f348/src/test/java/org/apache/aurora/scheduler/state/FirstFitTaskAssignerTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/state/FirstFitTaskAssignerTest.java
b/src/test/java/org/apache/aurora/scheduler/state/FirstFitTaskAssignerTest.java
index a74efbd..5837250 100644
--- a/src/test/java/org/apache/aurora/scheduler/state/FirstFitTaskAssignerTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/state/FirstFitTaskAssignerTest.java
@@ -50,12 +50,8 @@ import org.apache.aurora.scheduler.updater.UpdateAgentReserver;
 import org.apache.mesos.v1.Protos.AgentID;
 import org.apache.mesos.v1.Protos.FrameworkID;
 import org.apache.mesos.v1.Protos.OfferID;
-import org.apache.mesos.v1.Protos.Resource;
 import org.apache.mesos.v1.Protos.TaskID;
 import org.apache.mesos.v1.Protos.TaskInfo;
-import org.apache.mesos.v1.Protos.Value.Range;
-import org.apache.mesos.v1.Protos.Value.Ranges;
-import org.apache.mesos.v1.Protos.Value.Type;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -67,8 +63,11 @@ import static org.apache.aurora.scheduler.base.TaskTestUtil.makeTask;
 import static org.apache.aurora.scheduler.filter.AttributeAggregate.empty;
 import static org.apache.aurora.scheduler.resources.ResourceManager.bagFromMesosResources;
 import static org.apache.aurora.scheduler.resources.ResourceTestUtil.mesosRange;
+import static org.apache.aurora.scheduler.resources.ResourceTestUtil.mesosScalar;
 import static org.apache.aurora.scheduler.resources.ResourceTestUtil.offer;
+import static org.apache.aurora.scheduler.resources.ResourceType.CPUS;
 import static org.apache.aurora.scheduler.resources.ResourceType.PORTS;
+import static org.apache.aurora.scheduler.resources.ResourceType.RAM_MB;
 import static org.apache.aurora.scheduler.state.TaskAssigner.FirstFitTaskAssigner.ASSIGNER_EVALUATED_OFFERS;
 import static org.apache.aurora.scheduler.state.TaskAssigner.FirstFitTaskAssigner.ASSIGNER_LAUNCH_FAILURES;
 import static org.apache.aurora.scheduler.state.TaskAssigner.FirstFitTaskAssigner.LAUNCH_FAILED_MSG;
@@ -85,7 +84,8 @@ import static org.junit.Assert.assertNotEquals;
 public class FirstFitTaskAssignerTest extends EasyMockTest {
 
   private static final int PORT = 1000;
-  private static final Offer MESOS_OFFER = offer(mesosRange(PORTS, PORT));
+  private static final Offer MESOS_OFFER =
+      offer(mesosScalar(CPUS, 1), mesosScalar(RAM_MB, 1024), mesosRange(PORTS, PORT));
   private static final String SLAVE_ID = MESOS_OFFER.getAgentId().getValue();
   private static final HostOffer OFFER =
       new HostOffer(MESOS_OFFER, IHostAttributes.build(new HostAttributes()
@@ -108,15 +108,13 @@ public class FirstFitTaskAssignerTest extends EasyMockTest {
   private static final HostOffer OFFER_2 = new HostOffer(
       Offer.newBuilder()
           .setId(OfferID.newBuilder().setValue("offerId0"))
-              .setFrameworkId(FrameworkID.newBuilder().setValue("frameworkId"))
-              .setAgentId(AgentID.newBuilder().setValue("slaveId0"))
-              .setHostname("hostName0")
-          .addResources(Resource.newBuilder()
-          .setName("ports")
-          .setType(Type.RANGES)
-          .setRanges(
-              Ranges.newBuilder().addRange(Range.newBuilder().setBegin(PORT).setEnd(PORT))))
-              .build(),
+          .setFrameworkId(FrameworkID.newBuilder().setValue("frameworkId"))
+          .setAgentId(AgentID.newBuilder().setValue("slaveId0"))
+          .setHostname("hostName0")
+          .addResources(mesosRange(PORTS, PORT))
+          .addResources(mesosScalar(CPUS, 1))
+          .addResources(mesosScalar(RAM_MB, 1024))
+          .build(),
       IHostAttributes.build(new HostAttributes()));
 
   private static final Set<String> NO_ASSIGNMENT = ImmutableSet.of();
@@ -298,7 +296,7 @@ public class FirstFitTaskAssignerTest extends EasyMockTest {
             ImmutableSet.of(TASK.getAssignedTask()),
             ImmutableMap.of(SLAVE_ID, TaskGroupKey.from(
                 ITaskConfig.build(new TaskConfig().setJob(new JobKey("other", "e", "n")))))));
-    assertEquals(1L, statsProvider.getLongValue(ASSIGNER_EVALUATED_OFFERS));
+    assertEquals(0, statsProvider.getLongValue(ASSIGNER_EVALUATED_OFFERS));
   }
 
   @Test
@@ -342,11 +340,9 @@ public class FirstFitTaskAssignerTest extends EasyMockTest {
             .setFrameworkId(FrameworkID.newBuilder().setValue("frameworkId"))
             .setAgentId(AgentID.newBuilder().setValue("slaveId0"))
             .setHostname("hostName0")
-            .addResources(Resource.newBuilder()
-                .setName("ports")
-                .setType(Type.RANGES)
-                .setRanges(
-                    Ranges.newBuilder().addRange(Range.newBuilder().setBegin(PORT).setEnd(PORT))))
+            .addResources(mesosRange(PORTS, PORT))
+            .addResources(mesosScalar(CPUS, 1))
+            .addResources(mesosScalar(RAM_MB, 1024))
             .build(),
         IHostAttributes.build(new HostAttributes()));
 
@@ -498,6 +494,33 @@ public class FirstFitTaskAssignerTest extends EasyMockTest {
     assertEquals(1L, statsProvider.getLongValue(ASSIGNER_EVALUATED_OFFERS));
   }
 
+  @Test
+  public void testSkipsOffersWithNoMemAndNoCpu() {
+    expectNoUpdateReservations(0);
+    expect(tierManager.getTier(TASK.getAssignedTask().getTask())).andReturn(DEV_TIER);
+
+    // Offer lacks CPU.
+    Offer mesosOffer = offer(mesosScalar(RAM_MB, 1024), mesosRange(PORTS, PORT));
+    HostOffer offer = new HostOffer(mesosOffer, IHostAttributes.build(new HostAttributes()
+        .setHost(mesosOffer.getHostname())
+        .setAttributes(ImmutableSet.of(
+            new Attribute("host", ImmutableSet.of(mesosOffer.getHostname()))))));
+
+    expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(offer));
+
+    control.replay();
+
+    assertEquals(
+        NO_ASSIGNMENT,
+        assigner.maybeAssign(
+            storeProvider,
+            resourceRequest,
+            TaskGroupKey.from(TASK.getAssignedTask().getTask()),
+            ImmutableSet.of(TASK.getAssignedTask()),
+            NO_RESERVATION));
+    assertEquals(0, statsProvider.getLongValue(ASSIGNER_EVALUATED_OFFERS));
+  }
+
   private void expectAssignTask(Offer offer) {
     expect(stateManager.assignTask(
         eq(storeProvider),


Mime
View raw message