You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by ma...@apache.org on 2015/08/08 00:44:14 UTC

aurora git commit: Resources: moving Resources to scheduler package.

Repository: aurora
Updated Branches:
  refs/heads/master 92fc094f8 -> cbc42c484


Resources: moving Resources to scheduler package.

Bugs closed: AURORA-1415

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


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

Branch: refs/heads/master
Commit: cbc42c484cc599d41d5a4bd23c373a64e9b71466
Parents: 92fc094
Author: Maxim Khutornenko <ma...@apache.org>
Authored: Fri Aug 7 15:40:34 2015 -0700
Committer: Maxim Khutornenko <ma...@apache.org>
Committed: Fri Aug 7 15:40:34 2015 -0700

----------------------------------------------------------------------
 .../org/apache/aurora/benchmark/Offers.java     |   2 +-
 .../apache/aurora/scheduler/ResourceSlot.java   |   1 -
 .../org/apache/aurora/scheduler/Resources.java  | 350 +++++++++++++++++++
 .../aurora/scheduler/app/SchedulerMain.java     |   2 +-
 .../scheduler/configuration/Resources.java      | 350 -------------------
 .../scheduler/mesos/ExecutorSettings.java       |   2 +-
 .../scheduler/mesos/MesosTaskFactory.java       |   2 +-
 .../scheduler/preemptor/PreemptionVictim.java   |   2 +-
 .../aurora/scheduler/state/TaskAssigner.java    |   2 +-
 .../scheduler/stats/AsyncStatsModule.java       |   2 +-
 .../aurora/scheduler/ResourceSlotTest.java      |   1 -
 .../apache/aurora/scheduler/ResourcesTest.java  | 217 ++++++++++++
 .../aurora/scheduler/app/SchedulerIT.java       |   2 +-
 .../local/simulator/ClusterSimulatorModule.java |   2 +-
 .../scheduler/configuration/ResourcesTest.java  | 217 ------------
 .../mesos/MesosTaskFactoryImplTest.java         |   2 +-
 .../apache/aurora/scheduler/mesos/Offers.java   |   2 +-
 .../aurora/scheduler/mesos/TaskExecutors.java   |   2 +-
 .../preemptor/PreemptionVictimFilterTest.java   |   2 +-
 19 files changed, 580 insertions(+), 582 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/jmh/java/org/apache/aurora/benchmark/Offers.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/Offers.java b/src/jmh/java/org/apache/aurora/benchmark/Offers.java
index e40db74..269c196 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/Offers.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/Offers.java
@@ -20,7 +20,7 @@ import com.twitter.common.quantity.Amount;
 import com.twitter.common.quantity.Data;
 
 import org.apache.aurora.scheduler.HostOffer;
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.offers.OfferManager;
 import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
 import org.apache.mesos.Protos;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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 eb14ffe..e10656b 100644
--- a/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
+++ b/src/main/java/org/apache/aurora/scheduler/ResourceSlot.java
@@ -26,7 +26,6 @@ import com.google.common.collect.Ordering;
 import com.twitter.common.quantity.Amount;
 import com.twitter.common.quantity.Data;
 
-import org.apache.aurora.scheduler.configuration.Resources;
 import org.apache.aurora.scheduler.mesos.ExecutorSettings;
 import org.apache.aurora.scheduler.preemptor.PreemptionVictim;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/main/java/org/apache/aurora/scheduler/Resources.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/Resources.java b/src/main/java/org/apache/aurora/scheduler/Resources.java
new file mode 100644
index 0000000..e380245
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/Resources.java
@@ -0,0 +1,350 @@
+/**
+ * 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.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ContiguousSet;
+import com.google.common.collect.DiscreteDomain;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Data;
+
+import org.apache.aurora.scheduler.base.Numbers;
+import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
+import org.apache.mesos.Protos.Offer;
+import org.apache.mesos.Protos.Resource;
+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 java.util.Objects.requireNonNull;
+
+/**
+ * A container for multiple resource vectors.
+ * TODO(wfarner): Collapse this in with ResourceAggregates AURORA-105.
+ */
+public class Resources {
+
+  public static final String CPUS = "cpus";
+  public static final String RAM_MB = "mem";
+  public static final String DISK_MB = "disk";
+  public static final String PORTS = "ports";
+
+  private static final Function<Range, Set<Integer>> RANGE_TO_MEMBERS =
+      new Function<Range, Set<Integer>>() {
+        @Override
+        public Set<Integer> apply(Range range) {
+          return ContiguousSet.create(
+              com.google.common.collect.Range.closed((int) range.getBegin(), (int) range.getEnd()),
+              DiscreteDomain.integers());
+        }
+      };
+
+  private final double numCpus;
+  private final Amount<Long, Data> disk;
+  private final Amount<Long, Data> ram;
+  private final int numPorts;
+
+  /**
+   * Creates a new resources object.
+   *
+   * @param numCpus Number of CPUs.
+   * @param ram Amount of RAM.
+   * @param disk Amount of disk.
+   * @param numPorts Number of ports.
+   */
+  public Resources(double numCpus, Amount<Long, Data> ram, Amount<Long, Data> disk, int numPorts) {
+    this.numCpus = numCpus;
+    this.ram = requireNonNull(ram);
+    this.disk = requireNonNull(disk);
+    this.numPorts = numPorts;
+  }
+
+  /**
+   * Adapts this resources object to a list of mesos resources.
+   *
+   * @param selectedPorts The ports selected, to be applied as concrete task ranges.
+   * @return Mesos resources.
+   */
+  public List<Resource> toResourceList(Set<Integer> selectedPorts) {
+    ImmutableList.Builder<Resource> resourceBuilder =
+        ImmutableList.<Resource>builder()
+            .add(Resources.makeMesosResource(CPUS, numCpus))
+            .add(Resources.makeMesosResource(DISK_MB, disk.as(Data.MB)))
+            .add(Resources.makeMesosResource(RAM_MB, ram.as(Data.MB)));
+    if (!selectedPorts.isEmpty()) {
+      resourceBuilder.add(Resources.makeMesosRangeResource(Resources.PORTS, selectedPorts));
+    }
+
+    return resourceBuilder.build();
+  }
+
+  /**
+   * Convenience method for adapting to mesos resources without applying a port range.
+   *
+   * @see {@link #toResourceList(java.util.Set)}
+   * @return Mesos resources.
+   */
+  public List<Resource> toResourceList() {
+    return toResourceList(ImmutableSet.of());
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof Resources)) {
+      return false;
+    }
+
+    Resources other = (Resources) o;
+    return Objects.equals(numCpus, other.numCpus)
+        && Objects.equals(ram, other.ram)
+        && Objects.equals(disk, other.disk)
+        && Objects.equals(numPorts, other.numPorts);
+  }
+
+  @Override
+  public int hashCode() {
+    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.
+   *
+   * @param task Task to get resources from.
+   * @return The resources required by the task.
+   */
+  public static Resources from(ITaskConfig task) {
+    requireNonNull(task);
+    return new Resources(
+        task.getNumCpus(),
+        Amount.of(task.getRamMb(), Data.MB),
+        Amount.of(task.getDiskMb(), Data.MB),
+        task.getRequestedPorts().size());
+  }
+
+  /**
+   * Extracts the resources specified in a list of resource objects.
+   *
+   * @param resources Resources to translate.
+   * @return The canonical resources.
+   */
+  public static Resources from(List<Resource> resources) {
+    requireNonNull(resources);
+    return new Resources(
+        getScalarValue(resources, CPUS),
+        Amount.of((long) getScalarValue(resources, RAM_MB), Data.MB),
+        Amount.of((long) getScalarValue(resources, DISK_MB), Data.MB),
+        getNumAvailablePorts(resources)
+    );
+  }
+
+  /**
+   * Extracts the resources available in a slave offer.
+   *
+   * @param offer Offer to get resources from.
+   * @return The resources available in the offer.
+   */
+  public static Resources from(Offer offer) {
+    requireNonNull(offer);
+    return new Resources(
+        getScalarValue(offer, CPUS),
+        Amount.of((long) getScalarValue(offer, RAM_MB), Data.MB),
+        Amount.of((long) getScalarValue(offer, DISK_MB), Data.MB),
+        getNumAvailablePorts(offer.getResourcesList()));
+  }
+
+  @VisibleForTesting
+  public static final Resources NONE =
+      new Resources(0, Amount.of(0L, Data.BITS), Amount.of(0L, Data.BITS), 0);
+
+  private static int getNumAvailablePorts(List<Resource> resource) {
+    int offeredPorts = 0;
+    for (Range range : getPortRanges(resource)) {
+      offeredPorts += 1 + range.getEnd() - range.getBegin();
+    }
+    return offeredPorts;
+  }
+
+  private static double getScalarValue(Offer offer, String key) {
+    return getScalarValue(offer.getResourcesList(), key);
+  }
+
+  private static double getScalarValue(List<Resource> resources, String key) {
+    Resource resource = getResource(resources, key);
+    if (resource == null) {
+      return 0;
+    }
+
+    return resource.getScalar().getValue();
+  }
+
+  private static Resource getResource(List<Resource> resource, String key) {
+    return Iterables.find(resource, withName(key), null);
+  }
+
+  private static Predicate<Resource> withName(final String name) {
+    return new Predicate<Resource>() {
+      @Override
+      public boolean apply(Resource resource) {
+        return resource.getName().equals(name);
+      }
+    };
+  }
+
+  private static Iterable<Range> getPortRanges(List<Resource> resources) {
+    Resource resource = getResource(resources, Resources.PORTS);
+    if (resource == null) {
+      return ImmutableList.of();
+    }
+
+    return resource.getRanges().getRangeList();
+  }
+
+  /**
+   * Creates a scalar mesos resource.
+   *
+   * @param name Name of the resource.
+   * @param value Value for the resource.
+   * @return A mesos resource.
+   */
+  public static Resource makeMesosResource(String name, double value) {
+    return Resource.newBuilder().setName(name).setType(Type.SCALAR)
+        .setScalar(Scalar.newBuilder().setValue(value)).build();
+  }
+
+  private static final Function<com.google.common.collect.Range<Integer>, Range> RANGE_TRANSFORM =
+      new Function<com.google.common.collect.Range<Integer>, Range>() {
+        @Override
+        public Range apply(com.google.common.collect.Range<Integer> input) {
+          return Range.newBuilder()
+              .setBegin(input.lowerEndpoint())
+              .setEnd(input.upperEndpoint())
+              .build();
+        }
+      };
+
+  /**
+   * Creates a mesos resource of integer ranges.
+   *
+   * @param name Name of the resource
+   * @param values Values to translate into ranges.
+   * @return A mesos ranges resource.
+   */
+  @VisibleForTesting
+  public static Resource makeMesosRangeResource(String name, Set<Integer> values) {
+    return Resource.newBuilder()
+        .setName(name)
+        .setType(Type.RANGES)
+        .setRanges(Ranges.newBuilder()
+            .addAllRange(Iterables.transform(Numbers.toRanges(values), RANGE_TRANSFORM)))
+        .build();
+  }
+
+  /**
+   * Number of CPUs.
+   *
+   * @return CPUs.
+   */
+  public double getNumCpus() {
+    return numCpus;
+  }
+
+  /**
+   * Disk amount.
+   *
+   * @return Disk.
+   */
+  public Amount<Long, Data> getDisk() {
+    return disk;
+  }
+
+  /**
+   * RAM amount.
+   *
+   * @return RAM.
+   */
+  public Amount<Long, Data> getRam() {
+    return ram;
+  }
+
+  /**
+   * Number of ports.
+   *
+   * @return Port count.
+   */
+  public int getNumPorts() {
+    return numPorts;
+  }
+
+  /**
+   * Thrown when there are insufficient resources to satisfy a request.
+   */
+  static class InsufficientResourcesException extends RuntimeException {
+    public InsufficientResourcesException(String message) {
+      super(message);
+    }
+  }
+
+  /**
+   * Attempts to grab {@code numPorts} from the given resource {@code offer}.
+   *
+   * @param offer The offer to grab ports from.
+   * @param numPorts The number of ports to grab.
+   * @return The set of ports grabbed.
+   * @throws InsufficientResourcesException if not enough ports were available.
+   */
+  public static Set<Integer> getPorts(Offer offer, int numPorts)
+      throws InsufficientResourcesException {
+
+    requireNonNull(offer);
+
+    if (numPorts == 0) {
+      return ImmutableSet.of();
+    }
+
+    List<Integer> availablePorts = Lists.newArrayList(Sets.newHashSet(
+        Iterables.concat(
+            Iterables.transform(getPortRanges(offer.getResourcesList()), RANGE_TO_MEMBERS))));
+
+    if (availablePorts.size() < numPorts) {
+      throw new InsufficientResourcesException(
+          String.format("Could not get %d ports from %s", numPorts, offer));
+    }
+
+    Collections.shuffle(availablePorts);
+    return ImmutableSet.copyOf(availablePorts.subList(0, numPorts));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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 554a380..102069a 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
@@ -47,8 +47,8 @@ import com.twitter.common.zookeeper.guice.client.ZooKeeperClientModule.ClientCon
 import com.twitter.common.zookeeper.guice.client.flagged.FlaggedClientConfig;
 
 import org.apache.aurora.gen.Volume;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.SchedulerLifecycle;
-import org.apache.aurora.scheduler.configuration.Resources;
 import org.apache.aurora.scheduler.cron.quartz.CronModule;
 import org.apache.aurora.scheduler.http.HttpService;
 import org.apache.aurora.scheduler.log.mesos.MesosLogStreamModule;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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
deleted file mode 100644
index 6db3efb..0000000
--- a/src/main/java/org/apache/aurora/scheduler/configuration/Resources.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.configuration;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ContiguousSet;
-import com.google.common.collect.DiscreteDomain;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.twitter.common.quantity.Amount;
-import com.twitter.common.quantity.Data;
-
-import org.apache.aurora.scheduler.base.Numbers;
-import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
-import org.apache.mesos.Protos.Offer;
-import org.apache.mesos.Protos.Resource;
-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 java.util.Objects.requireNonNull;
-
-/**
- * A container for multiple resource vectors.
- * TODO(wfarner): Collapse this in with ResourceAggregates AURORA-105.
- */
-public class Resources {
-
-  public static final String CPUS = "cpus";
-  public static final String RAM_MB = "mem";
-  public static final String DISK_MB = "disk";
-  public static final String PORTS = "ports";
-
-  private static final Function<Range, Set<Integer>> RANGE_TO_MEMBERS =
-      new Function<Range, Set<Integer>>() {
-        @Override
-        public Set<Integer> apply(Range range) {
-          return ContiguousSet.create(
-              com.google.common.collect.Range.closed((int) range.getBegin(), (int) range.getEnd()),
-              DiscreteDomain.integers());
-        }
-      };
-
-  private final double numCpus;
-  private final Amount<Long, Data> disk;
-  private final Amount<Long, Data> ram;
-  private final int numPorts;
-
-  /**
-   * Creates a new resources object.
-   *
-   * @param numCpus Number of CPUs.
-   * @param ram Amount of RAM.
-   * @param disk Amount of disk.
-   * @param numPorts Number of ports.
-   */
-  public Resources(double numCpus, Amount<Long, Data> ram, Amount<Long, Data> disk, int numPorts) {
-    this.numCpus = numCpus;
-    this.ram = requireNonNull(ram);
-    this.disk = requireNonNull(disk);
-    this.numPorts = numPorts;
-  }
-
-  /**
-   * Adapts this resources object to a list of mesos resources.
-   *
-   * @param selectedPorts The ports selected, to be applied as concrete task ranges.
-   * @return Mesos resources.
-   */
-  public List<Resource> toResourceList(Set<Integer> selectedPorts) {
-    ImmutableList.Builder<Resource> resourceBuilder =
-        ImmutableList.<Resource>builder()
-            .add(Resources.makeMesosResource(CPUS, numCpus))
-            .add(Resources.makeMesosResource(DISK_MB, disk.as(Data.MB)))
-            .add(Resources.makeMesosResource(RAM_MB, ram.as(Data.MB)));
-    if (!selectedPorts.isEmpty()) {
-      resourceBuilder.add(Resources.makeMesosRangeResource(Resources.PORTS, selectedPorts));
-    }
-
-    return resourceBuilder.build();
-  }
-
-  /**
-   * Convenience method for adapting to mesos resources without applying a port range.
-   *
-   * @see {@link #toResourceList(java.util.Set)}
-   * @return Mesos resources.
-   */
-  public List<Resource> toResourceList() {
-    return toResourceList(ImmutableSet.of());
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof Resources)) {
-      return false;
-    }
-
-    Resources other = (Resources) o;
-    return Objects.equals(numCpus, other.numCpus)
-        && Objects.equals(ram, other.ram)
-        && Objects.equals(disk, other.disk)
-        && Objects.equals(numPorts, other.numPorts);
-  }
-
-  @Override
-  public int hashCode() {
-    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.
-   *
-   * @param task Task to get resources from.
-   * @return The resources required by the task.
-   */
-  public static Resources from(ITaskConfig task) {
-    requireNonNull(task);
-    return new Resources(
-        task.getNumCpus(),
-        Amount.of(task.getRamMb(), Data.MB),
-        Amount.of(task.getDiskMb(), Data.MB),
-        task.getRequestedPorts().size());
-  }
-
-  /**
-   * Extracts the resources specified in a list of resource objects.
-   *
-   * @param resources Resources to translate.
-   * @return The canonical resources.
-   */
-  public static Resources from(List<Resource> resources) {
-    requireNonNull(resources);
-    return new Resources(
-        getScalarValue(resources, CPUS),
-        Amount.of((long) getScalarValue(resources, RAM_MB), Data.MB),
-        Amount.of((long) getScalarValue(resources, DISK_MB), Data.MB),
-        getNumAvailablePorts(resources)
-    );
-  }
-
-  /**
-   * Extracts the resources available in a slave offer.
-   *
-   * @param offer Offer to get resources from.
-   * @return The resources available in the offer.
-   */
-  public static Resources from(Offer offer) {
-    requireNonNull(offer);
-    return new Resources(
-        getScalarValue(offer, CPUS),
-        Amount.of((long) getScalarValue(offer, RAM_MB), Data.MB),
-        Amount.of((long) getScalarValue(offer, DISK_MB), Data.MB),
-        getNumAvailablePorts(offer.getResourcesList()));
-  }
-
-  @VisibleForTesting
-  public static final Resources NONE =
-      new Resources(0, Amount.of(0L, Data.BITS), Amount.of(0L, Data.BITS), 0);
-
-  private static int getNumAvailablePorts(List<Resource> resource) {
-    int offeredPorts = 0;
-    for (Range range : getPortRanges(resource)) {
-      offeredPorts += 1 + range.getEnd() - range.getBegin();
-    }
-    return offeredPorts;
-  }
-
-  private static double getScalarValue(Offer offer, String key) {
-    return getScalarValue(offer.getResourcesList(), key);
-  }
-
-  private static double getScalarValue(List<Resource> resources, String key) {
-    Resource resource = getResource(resources, key);
-    if (resource == null) {
-      return 0;
-    }
-
-    return resource.getScalar().getValue();
-  }
-
-  private static Resource getResource(List<Resource> resource, String key) {
-    return Iterables.find(resource, withName(key), null);
-  }
-
-  private static Predicate<Resource> withName(final String name) {
-    return new Predicate<Resource>() {
-      @Override
-      public boolean apply(Resource resource) {
-        return resource.getName().equals(name);
-      }
-    };
-  }
-
-  private static Iterable<Range> getPortRanges(List<Resource> resources) {
-    Resource resource = getResource(resources, Resources.PORTS);
-    if (resource == null) {
-      return ImmutableList.of();
-    }
-
-    return resource.getRanges().getRangeList();
-  }
-
-  /**
-   * Creates a scalar mesos resource.
-   *
-   * @param name Name of the resource.
-   * @param value Value for the resource.
-   * @return A mesos resource.
-   */
-  public static Resource makeMesosResource(String name, double value) {
-    return Resource.newBuilder().setName(name).setType(Type.SCALAR)
-        .setScalar(Scalar.newBuilder().setValue(value)).build();
-  }
-
-  private static final Function<com.google.common.collect.Range<Integer>, Range> RANGE_TRANSFORM =
-      new Function<com.google.common.collect.Range<Integer>, Range>() {
-        @Override
-        public Range apply(com.google.common.collect.Range<Integer> input) {
-          return Range.newBuilder()
-              .setBegin(input.lowerEndpoint())
-              .setEnd(input.upperEndpoint())
-              .build();
-        }
-      };
-
-  /**
-   * Creates a mesos resource of integer ranges.
-   *
-   * @param name Name of the resource
-   * @param values Values to translate into ranges.
-   * @return A mesos ranges resource.
-   */
-  @VisibleForTesting
-  public static Resource makeMesosRangeResource(String name, Set<Integer> values) {
-    return Resource.newBuilder()
-        .setName(name)
-        .setType(Type.RANGES)
-        .setRanges(Ranges.newBuilder()
-            .addAllRange(Iterables.transform(Numbers.toRanges(values), RANGE_TRANSFORM)))
-        .build();
-  }
-
-  /**
-   * Number of CPUs.
-   *
-   * @return CPUs.
-   */
-  public double getNumCpus() {
-    return numCpus;
-  }
-
-  /**
-   * Disk amount.
-   *
-   * @return Disk.
-   */
-  public Amount<Long, Data> getDisk() {
-    return disk;
-  }
-
-  /**
-   * RAM amount.
-   *
-   * @return RAM.
-   */
-  public Amount<Long, Data> getRam() {
-    return ram;
-  }
-
-  /**
-   * Number of ports.
-   *
-   * @return Port count.
-   */
-  public int getNumPorts() {
-    return numPorts;
-  }
-
-  /**
-   * Thrown when there are insufficient resources to satisfy a request.
-   */
-  static class InsufficientResourcesException extends RuntimeException {
-    public InsufficientResourcesException(String message) {
-      super(message);
-    }
-  }
-
-  /**
-   * Attempts to grab {@code numPorts} from the given resource {@code offer}.
-   *
-   * @param offer The offer to grab ports from.
-   * @param numPorts The number of ports to grab.
-   * @return The set of ports grabbed.
-   * @throws InsufficientResourcesException if not enough ports were available.
-   */
-  public static Set<Integer> getPorts(Offer offer, int numPorts)
-      throws InsufficientResourcesException {
-
-    requireNonNull(offer);
-
-    if (numPorts == 0) {
-      return ImmutableSet.of();
-    }
-
-    List<Integer> availablePorts = Lists.newArrayList(Sets.newHashSet(
-        Iterables.concat(
-            Iterables.transform(getPortRanges(offer.getResourcesList()), RANGE_TO_MEMBERS))));
-
-    if (availablePorts.size() < numPorts) {
-      throw new InsufficientResourcesException(
-          String.format("Could not get %d ports from %s", numPorts, offer));
-    }
-
-    Collections.shuffle(availablePorts);
-    return ImmutableSet.copyOf(availablePorts.subList(0, numPorts));
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
index 325f556..44011f8 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
@@ -19,7 +19,7 @@ import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 
 import org.apache.aurora.gen.Volume;
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 
 import static java.util.Objects.requireNonNull;
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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 4562b3b..c160a53 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/MesosTaskFactory.java
@@ -30,11 +30,11 @@ 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.Resources;
 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.IDockerParameter;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictim.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictim.java b/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictim.java
index a93fa22..8d2f069 100644
--- a/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictim.java
+++ b/src/main/java/org/apache/aurora/scheduler/preemptor/PreemptionVictim.java
@@ -15,7 +15,7 @@ package org.apache.aurora.scheduler.preemptor;
 
 import java.util.Objects;
 
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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 ae59efa..14d70df 100644
--- a/src/main/java/org/apache/aurora/scheduler/state/TaskAssigner.java
+++ b/src/main/java/org/apache/aurora/scheduler/state/TaskAssigner.java
@@ -33,8 +33,8 @@ import com.twitter.common.stats.Stats;
 
 import org.apache.aurora.scheduler.HostOffer;
 import org.apache.aurora.scheduler.ResourceSlot;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.base.TaskGroupKey;
-import org.apache.aurora.scheduler.configuration.Resources;
 import org.apache.aurora.scheduler.filter.SchedulingFilter;
 import org.apache.aurora.scheduler.filter.SchedulingFilter.ResourceRequest;
 import org.apache.aurora.scheduler.filter.SchedulingFilter.UnusedResource;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/main/java/org/apache/aurora/scheduler/stats/AsyncStatsModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/stats/AsyncStatsModule.java b/src/main/java/org/apache/aurora/scheduler/stats/AsyncStatsModule.java
index b96c84c..81b1640 100644
--- a/src/main/java/org/apache/aurora/scheduler/stats/AsyncStatsModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/stats/AsyncStatsModule.java
@@ -30,9 +30,9 @@ import com.twitter.common.quantity.Time;
 
 import org.apache.aurora.gen.ResourceAggregate;
 import org.apache.aurora.scheduler.HostOffer;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.SchedulerServicesModule;
 import org.apache.aurora.scheduler.base.Conversions;
-import org.apache.aurora.scheduler.configuration.Resources;
 import org.apache.aurora.scheduler.offers.OfferManager;
 import org.apache.aurora.scheduler.stats.SlotSizeCounter.MachineResource;
 import org.apache.aurora.scheduler.stats.SlotSizeCounter.MachineResourceProvider;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java b/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
index 896833d..d1294e2 100644
--- a/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/ResourceSlotTest.java
@@ -16,7 +16,6 @@ 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;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/test/java/org/apache/aurora/scheduler/ResourcesTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/ResourcesTest.java b/src/test/java/org/apache/aurora/scheduler/ResourcesTest.java
new file mode 100644
index 0000000..8bc56b2
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/ResourcesTest.java
@@ -0,0 +1,217 @@
+/**
+ * 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.Set;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.twitter.common.collections.Pair;
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Data;
+
+import org.apache.aurora.gen.TaskConfig;
+import org.apache.aurora.scheduler.Resources.InsufficientResourcesException;
+import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
+import org.apache.mesos.Protos;
+import org.apache.mesos.Protos.Resource;
+import org.apache.mesos.Protos.Value.Range;
+import org.apache.mesos.Protos.Value.Ranges;
+import org.apache.mesos.Protos.Value.Type;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
+
+public class ResourcesTest {
+
+  private static final String NAME = "resource_name";
+
+  @Test
+  public void testPortRangeExact() {
+    Resource portsResource = createPortRange(Pair.of(1, 5));
+    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 5);
+    assertEquals(5, ports.size());
+  }
+
+  @Test
+  public void testOnePortAvailable() {
+    Resource portsResource = createPortRange(Pair.of(3, 3));
+    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 1);
+    assertEquals(1, ports.size());
+  }
+
+  @Test
+  public void testPortRangeAbundance() {
+    Resource portsResource = createPortRange(Pair.of(1, 10));
+    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 5);
+    assertEquals(5, ports.size());
+  }
+
+  @Test
+  public void testPortRangeExhaust() {
+    Resource portsResource = createPortRanges(Pair.of(1, 2), Pair.of(10, 15));
+
+    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 7);
+    assertEquals(7, ports.size());
+
+    ports = Resources.getPorts(createOffer(portsResource), 8);
+    assertEquals(8, ports.size());
+
+    try {
+      Resources.getPorts(createOffer(portsResource), 9);
+      fail("Ports should not have been sufficient");
+    } catch (InsufficientResourcesException e) {
+      // Expected.
+    }
+  }
+
+  @Test
+  public void testGetNoPorts() {
+    Resource portsResource = createPortRange(Pair.of(1, 5));
+    assertEquals(ImmutableSet.of(), Resources.getPorts(createOffer(portsResource), 0));
+  }
+
+  @Test(expected = Resources.InsufficientResourcesException.class)
+  public void testPortRangeScarcity() {
+    Resource portsResource = createPortRange(Pair.of(1, 2));
+    Resources.getPorts(createOffer(portsResource), 5);
+  }
+
+  private Resource createPortRange(Pair<Integer, Integer> range) {
+    return createPortRanges(ImmutableSet.of(range));
+  }
+
+  private Resource createPortRanges(Pair<Integer, Integer> rangeA, Pair<Integer, Integer> rangeB) {
+    return createPortRanges(
+        ImmutableSet.<Pair<Integer, Integer>>builder().add(rangeA).add(rangeB).build());
+  }
+
+  private Resource createPortRanges(Set<Pair<Integer, Integer>> ports) {
+    Ranges.Builder ranges = Ranges.newBuilder();
+    for (Pair<Integer, Integer> range : ports) {
+      ranges.addRange(Range.newBuilder().setBegin(range.getFirst()).setEnd(range.getSecond()));
+    }
+
+    return Resource.newBuilder()
+        .setName(Resources.PORTS)
+        .setType(Type.RANGES)
+        .setRanges(ranges)
+        .build();
+  }
+
+  private Protos.Offer createOffer(Resource resources) {
+    return Protos.Offer.newBuilder()
+        .setId(Protos.OfferID.newBuilder().setValue("offer-id"))
+        .setFrameworkId(Protos.FrameworkID.newBuilder().setValue("framework-id"))
+        .setSlaveId(Protos.SlaveID.newBuilder().setValue("slave-id"))
+        .setHostname("hostname")
+        .addResources(resources).build();
+  }
+
+  @Test
+  public void testRangeResourceEmpty() {
+    expectRanges(ImmutableSet.of(), ImmutableSet.of());
+  }
+
+  @Test
+  public void testRangeResourceOneEntry() {
+    expectRanges(ImmutableSet.of(Pair.of(5L, 5L)), ImmutableSet.of(5));
+    expectRanges(ImmutableSet.of(Pair.of(0L, 0L)), ImmutableSet.of(0));
+  }
+
+  @Test
+  public void testRangeResourceNonContiguous() {
+    expectRanges(ImmutableSet.of(Pair.of(1L, 1L), Pair.of(3L, 3L), Pair.of(5L, 5L)),
+        ImmutableSet.of(5, 1, 3));
+  }
+
+  @Test
+  public void testRangeResourceContiguous() {
+    expectRanges(ImmutableSet.of(Pair.of(1L, 2L), Pair.of(4L, 5L), Pair.of(7L, 9L)),
+        ImmutableSet.of(8, 2, 4, 5, 7, 9, 1));
+  }
+
+  private static final ITaskConfig TASK = ITaskConfig.build(new TaskConfig()
+      .setNumCpus(1.0)
+      .setRamMb(1024)
+      .setDiskMb(2048)
+      .setRequestedPorts(ImmutableSet.of("http", "debug")));
+
+  @Test
+  public void testAccessors() {
+    Resources resources = Resources.from(TASK);
+    assertEquals(TASK.getNumCpus(), resources.getNumCpus(), 1e-9);
+    assertEquals(Amount.of(TASK.getRamMb(), Data.MB), resources.getRam());
+    assertEquals(Amount.of(TASK.getDiskMb(), Data.MB), resources.getDisk());
+    assertEquals(TASK.getRequestedPorts().size(), resources.getNumPorts());
+  }
+
+  @Test
+  public void testToResourceList() {
+    Resources resources = Resources.from(TASK);
+    Set<Integer> ports = ImmutableSet.of(80, 443);
+    assertEquals(
+        ImmutableSet.of(
+            Resources.makeMesosResource(Resources.CPUS, TASK.getNumCpus()),
+            Resources.makeMesosResource(Resources.RAM_MB, TASK.getRamMb()),
+            Resources.makeMesosResource(Resources.DISK_MB, TASK.getDiskMb()),
+            Resources.makeMesosRangeResource(Resources.PORTS, ports)),
+        ImmutableSet.copyOf(resources.toResourceList(ports)));
+  }
+
+  @Test
+  public void testToResourceListInversible() {
+    Resources resources = Resources.from(TASK);
+    Resources inverse = Resources.from(resources.toResourceList(ImmutableSet.of(80, 443)));
+    assertEquals(resources, inverse);
+    assertEquals(resources.hashCode(), inverse.hashCode());
+  }
+
+  @Test
+  public void testEqualsBadType() {
+    Resources resources = Resources.from(TASK);
+    assertNotEquals(resources, "Hello");
+    assertNotEquals(resources, null);
+  }
+
+  @Test
+  public void testToResourceListNoPorts() {
+    Resources resources = Resources.from(TASK);
+    assertEquals(
+        ImmutableSet.of(
+            Resources.makeMesosResource(Resources.CPUS, TASK.getNumCpus()),
+            Resources.makeMesosResource(Resources.RAM_MB, TASK.getRamMb()),
+            Resources.makeMesosResource(Resources.DISK_MB, TASK.getDiskMb())),
+        ImmutableSet.copyOf(resources.toResourceList(ImmutableSet.of())));
+  }
+
+  private void expectRanges(Set<Pair<Long, Long>> expected, Set<Integer> values) {
+    Resource resource = Resources.makeMesosRangeResource(NAME, values);
+    assertEquals(Type.RANGES, resource.getType());
+    assertEquals(NAME, resource.getName());
+
+    Set<Pair<Long, Long>> actual = ImmutableSet.copyOf(Iterables.transform(
+        resource.getRanges().getRangeList(),
+        new Function<Range, Pair<Long, Long>>() {
+          @Override
+          public Pair<Long, Long> apply(Range range) {
+            return Pair.of(range.getBegin(), range.getEnd());
+          }
+        }));
+    assertEquals(expected, actual);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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 23c2693..8d8f8a2 100644
--- a/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
+++ b/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
@@ -76,8 +76,8 @@ import org.apache.aurora.gen.storage.SaveTasks;
 import org.apache.aurora.gen.storage.Snapshot;
 import org.apache.aurora.gen.storage.Transaction;
 import org.apache.aurora.gen.storage.storageConstants;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.configuration.ConfigurationManager;
-import org.apache.aurora.scheduler.configuration.Resources;
 import org.apache.aurora.scheduler.log.Log;
 import org.apache.aurora.scheduler.log.Log.Entry;
 import org.apache.aurora.scheduler.log.Log.Position;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java b/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
index cd0f981..24278ba 100644
--- a/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
+++ b/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
@@ -24,7 +24,7 @@ import com.google.inject.multibindings.Multibinder;
 import com.twitter.common.application.modules.LifecycleModule;
 import com.twitter.common.base.Command;
 
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.mesos.Protos;
 import org.apache.mesos.Protos.Offer;
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/test/java/org/apache/aurora/scheduler/configuration/ResourcesTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/configuration/ResourcesTest.java b/src/test/java/org/apache/aurora/scheduler/configuration/ResourcesTest.java
deleted file mode 100644
index 9335141..0000000
--- a/src/test/java/org/apache/aurora/scheduler/configuration/ResourcesTest.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.configuration;
-
-import java.util.Set;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.twitter.common.collections.Pair;
-import com.twitter.common.quantity.Amount;
-import com.twitter.common.quantity.Data;
-
-import org.apache.aurora.gen.TaskConfig;
-import org.apache.aurora.scheduler.configuration.Resources.InsufficientResourcesException;
-import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
-import org.apache.mesos.Protos;
-import org.apache.mesos.Protos.Resource;
-import org.apache.mesos.Protos.Value.Range;
-import org.apache.mesos.Protos.Value.Ranges;
-import org.apache.mesos.Protos.Value.Type;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.fail;
-
-public class ResourcesTest {
-
-  private static final String NAME = "resource_name";
-
-  @Test
-  public void testPortRangeExact() {
-    Resource portsResource = createPortRange(Pair.of(1, 5));
-    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 5);
-    assertEquals(5, ports.size());
-  }
-
-  @Test
-  public void testOnePortAvailable() {
-    Resource portsResource = createPortRange(Pair.of(3, 3));
-    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 1);
-    assertEquals(1, ports.size());
-  }
-
-  @Test
-  public void testPortRangeAbundance() {
-    Resource portsResource = createPortRange(Pair.of(1, 10));
-    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 5);
-    assertEquals(5, ports.size());
-  }
-
-  @Test
-  public void testPortRangeExhaust() {
-    Resource portsResource = createPortRanges(Pair.of(1, 2), Pair.of(10, 15));
-
-    Set<Integer> ports = Resources.getPorts(createOffer(portsResource), 7);
-    assertEquals(7, ports.size());
-
-    ports = Resources.getPorts(createOffer(portsResource), 8);
-    assertEquals(8, ports.size());
-
-    try {
-      Resources.getPorts(createOffer(portsResource), 9);
-      fail("Ports should not have been sufficient");
-    } catch (InsufficientResourcesException e) {
-      // Expected.
-    }
-  }
-
-  @Test
-  public void testGetNoPorts() {
-    Resource portsResource = createPortRange(Pair.of(1, 5));
-    assertEquals(ImmutableSet.of(), Resources.getPorts(createOffer(portsResource), 0));
-  }
-
-  @Test(expected = Resources.InsufficientResourcesException.class)
-  public void testPortRangeScarcity() {
-    Resource portsResource = createPortRange(Pair.of(1, 2));
-    Resources.getPorts(createOffer(portsResource), 5);
-  }
-
-  private Resource createPortRange(Pair<Integer, Integer> range) {
-    return createPortRanges(ImmutableSet.of(range));
-  }
-
-  private Resource createPortRanges(Pair<Integer, Integer> rangeA, Pair<Integer, Integer> rangeB) {
-    return createPortRanges(
-        ImmutableSet.<Pair<Integer, Integer>>builder().add(rangeA).add(rangeB).build());
-  }
-
-  private Resource createPortRanges(Set<Pair<Integer, Integer>> ports) {
-    Ranges.Builder ranges = Ranges.newBuilder();
-    for (Pair<Integer, Integer> range : ports) {
-      ranges.addRange(Range.newBuilder().setBegin(range.getFirst()).setEnd(range.getSecond()));
-    }
-
-    return Resource.newBuilder()
-        .setName(Resources.PORTS)
-        .setType(Type.RANGES)
-        .setRanges(ranges)
-        .build();
-  }
-
-  private Protos.Offer createOffer(Resource resources) {
-    return Protos.Offer.newBuilder()
-        .setId(Protos.OfferID.newBuilder().setValue("offer-id"))
-        .setFrameworkId(Protos.FrameworkID.newBuilder().setValue("framework-id"))
-        .setSlaveId(Protos.SlaveID.newBuilder().setValue("slave-id"))
-        .setHostname("hostname")
-        .addResources(resources).build();
-  }
-
-  @Test
-  public void testRangeResourceEmpty() {
-    expectRanges(ImmutableSet.of(), ImmutableSet.of());
-  }
-
-  @Test
-  public void testRangeResourceOneEntry() {
-    expectRanges(ImmutableSet.of(Pair.of(5L, 5L)), ImmutableSet.of(5));
-    expectRanges(ImmutableSet.of(Pair.of(0L, 0L)), ImmutableSet.of(0));
-  }
-
-  @Test
-  public void testRangeResourceNonContiguous() {
-    expectRanges(ImmutableSet.of(Pair.of(1L, 1L), Pair.of(3L, 3L), Pair.of(5L, 5L)),
-        ImmutableSet.of(5, 1, 3));
-  }
-
-  @Test
-  public void testRangeResourceContiguous() {
-    expectRanges(ImmutableSet.of(Pair.of(1L, 2L), Pair.of(4L, 5L), Pair.of(7L, 9L)),
-        ImmutableSet.of(8, 2, 4, 5, 7, 9, 1));
-  }
-
-  private static final ITaskConfig TASK = ITaskConfig.build(new TaskConfig()
-      .setNumCpus(1.0)
-      .setRamMb(1024)
-      .setDiskMb(2048)
-      .setRequestedPorts(ImmutableSet.of("http", "debug")));
-
-  @Test
-  public void testAccessors() {
-    Resources resources = Resources.from(TASK);
-    assertEquals(TASK.getNumCpus(), resources.getNumCpus(), 1e-9);
-    assertEquals(Amount.of(TASK.getRamMb(), Data.MB), resources.getRam());
-    assertEquals(Amount.of(TASK.getDiskMb(), Data.MB), resources.getDisk());
-    assertEquals(TASK.getRequestedPorts().size(), resources.getNumPorts());
-  }
-
-  @Test
-  public void testToResourceList() {
-    Resources resources = Resources.from(TASK);
-    Set<Integer> ports = ImmutableSet.of(80, 443);
-    assertEquals(
-        ImmutableSet.of(
-            Resources.makeMesosResource(Resources.CPUS, TASK.getNumCpus()),
-            Resources.makeMesosResource(Resources.RAM_MB, TASK.getRamMb()),
-            Resources.makeMesosResource(Resources.DISK_MB, TASK.getDiskMb()),
-            Resources.makeMesosRangeResource(Resources.PORTS, ports)),
-        ImmutableSet.copyOf(resources.toResourceList(ports)));
-  }
-
-  @Test
-  public void testToResourceListInversible() {
-    Resources resources = Resources.from(TASK);
-    Resources inverse = Resources.from(resources.toResourceList(ImmutableSet.of(80, 443)));
-    assertEquals(resources, inverse);
-    assertEquals(resources.hashCode(), inverse.hashCode());
-  }
-
-  @Test
-  public void testEqualsBadType() {
-    Resources resources = Resources.from(TASK);
-    assertNotEquals(resources, "Hello");
-    assertNotEquals(resources, null);
-  }
-
-  @Test
-  public void testToResourceListNoPorts() {
-    Resources resources = Resources.from(TASK);
-    assertEquals(
-        ImmutableSet.of(
-            Resources.makeMesosResource(Resources.CPUS, TASK.getNumCpus()),
-            Resources.makeMesosResource(Resources.RAM_MB, TASK.getRamMb()),
-            Resources.makeMesosResource(Resources.DISK_MB, TASK.getDiskMb())),
-        ImmutableSet.copyOf(resources.toResourceList(ImmutableSet.of())));
-  }
-
-  private void expectRanges(Set<Pair<Long, Long>> expected, Set<Integer> values) {
-    Resource resource = Resources.makeMesosRangeResource(NAME, values);
-    assertEquals(Type.RANGES, resource.getType());
-    assertEquals(NAME, resource.getName());
-
-    Set<Pair<Long, Long>> actual = ImmutableSet.copyOf(Iterables.transform(
-        resource.getRanges().getRangeList(),
-        new Function<Range, Pair<Long, Long>>() {
-          @Override
-          public Pair<Long, Long> apply(Range range) {
-            return Pair.of(range.getBegin(), range.getEnd());
-          }
-        }));
-    assertEquals(expected, actual);
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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 d19f5af..c74cc7f 100644
--- a/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/mesos/MesosTaskFactoryImplTest.java
@@ -29,7 +29,7 @@ import org.apache.aurora.gen.Mode;
 import org.apache.aurora.gen.TaskConfig;
 import org.apache.aurora.gen.Volume;
 import org.apache.aurora.scheduler.ResourceSlot;
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.mesos.MesosTaskFactory.MesosTaskFactoryImpl;
 import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/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
index c10d5b6..e29829d 100644
--- a/src/test/java/org/apache/aurora/scheduler/mesos/Offers.java
+++ b/src/test/java/org/apache/aurora/scheduler/mesos/Offers.java
@@ -15,7 +15,7 @@ package org.apache.aurora.scheduler.mesos;
 
 import com.twitter.common.collections.Pair;
 
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.mesos.Protos;
 import org.apache.mesos.Protos.Offer;
 import org.apache.mesos.Protos.OfferID;

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java b/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
index ebd8177..14820f2 100644
--- a/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
+++ b/src/test/java/org/apache/aurora/scheduler/mesos/TaskExecutors.java
@@ -16,7 +16,7 @@ package org.apache.aurora.scheduler.mesos;
 import com.twitter.common.quantity.Amount;
 import com.twitter.common.quantity.Data;
 
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 
 /**
  * Utility class to contain constants related to setting up executor settings.

http://git-wip-us.apache.org/repos/asf/aurora/blob/cbc42c48/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java b/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
index 997d326..4bae195 100644
--- a/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptionVictimFilterTest.java
@@ -36,7 +36,7 @@ import org.apache.aurora.gen.ScheduledTask;
 import org.apache.aurora.gen.TaskConfig;
 import org.apache.aurora.gen.TaskEvent;
 import org.apache.aurora.scheduler.HostOffer;
-import org.apache.aurora.scheduler.configuration.Resources;
+import org.apache.aurora.scheduler.Resources;
 import org.apache.aurora.scheduler.filter.SchedulingFilter;
 import org.apache.aurora.scheduler.filter.SchedulingFilter.Veto;
 import org.apache.aurora.scheduler.filter.SchedulingFilterImpl;