org.apache.aurora.scheduler.offers.OfferOrderBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.aurora.scheduler.offers.OfferOrderBuilder.java

Source

/**
 * 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.offers;

import java.time.Instant;
import java.util.List;

import com.google.common.collect.Ordering;

import org.apache.aurora.scheduler.HostOffer;
import org.apache.aurora.scheduler.resources.ResourceType;

import static org.apache.aurora.gen.MaintenanceMode.DRAINED;
import static org.apache.aurora.gen.MaintenanceMode.DRAINING;
import static org.apache.aurora.gen.MaintenanceMode.NONE;
import static org.apache.aurora.gen.MaintenanceMode.SCHEDULED;
import static org.apache.aurora.scheduler.resources.ResourceManager.bagFromMesosResources;
import static org.apache.aurora.scheduler.resources.ResourceManager.getNonRevocableOfferResources;
import static org.apache.aurora.scheduler.resources.ResourceManager.getRevocableOfferResources;

/**
 * Utility class for creating compounded offer orders based on some combination of offer ordering.
 */
final class OfferOrderBuilder {
    private OfferOrderBuilder() {

    }

    private static final Ordering<HostOffer> AURORA_MAINTENANCE_COMPARATOR = Ordering
            .explicit(NONE, SCHEDULED, DRAINING, DRAINED).onResultOf(offer -> offer.getAttributes().getMode());

    // We should not prefer offers from agents that are scheduled to become unavailable.
    // We should also sort the unavailability start to prefer agents that are starting
    // maintenance later.
    private static final Ordering<HostOffer> MESOS_MAINTENANCE_COMPARATOR = Ordering.natural().reverse()
            .onResultOf(o -> o.getUnavailabilityStart().or(Instant.MAX));

    private static final Ordering<HostOffer> BASE_COMPARATOR = AURORA_MAINTENANCE_COMPARATOR
            .compound(MESOS_MAINTENANCE_COMPARATOR);

    private static final Ordering<Object> RANDOM_COMPARATOR = Ordering.arbitrary();
    private static final Ordering<HostOffer> CPU_COMPARATOR = nonRevocableResourceOrdering(ResourceType.CPUS);
    private static final Ordering<HostOffer> RAM_COMPARATOR = nonRevocableResourceOrdering(ResourceType.RAM_MB);
    private static final Ordering<HostOffer> DISK_COMPARATOR = nonRevocableResourceOrdering(ResourceType.DISK_MB);
    private static final Ordering<HostOffer> REVOCABLE_CPU_COMPARATOR = revocableResourceOrdering(
            ResourceType.CPUS);

    private static Ordering<HostOffer> nonRevocableResourceOrdering(ResourceType resourceType) {
        return Ordering.natural().onResultOf(
                o -> bagFromMesosResources(getNonRevocableOfferResources(o.getOffer())).valueOf(resourceType));
    }

    private static Ordering<HostOffer> revocableResourceOrdering(ResourceType resourceType) {
        return Ordering.natural().onResultOf(o -> {
            Double resource = bagFromMesosResources(getRevocableOfferResources(o.getOffer())).valueOf(resourceType);
            // resource will be 0.0 if there is no revocable cpus available. Since the purpose of
            // this ordering is to bin-pack revocable then we push those offers to the back.
            return resource.equals(0.0) ? Double.MAX_VALUE : resource;
        });
    }

    private static Ordering<HostOffer> getOrdering(Ordering<HostOffer> base, OfferOrder order) {
        // Random is Ordering<Object> so accepting base as a parameter and compounding in here is the
        // cleanest way I could come up with to avoid a whole bunch of type finagling.
        switch (order) {
        case CPU:
            return base.compound(CPU_COMPARATOR);
        case DISK:
            return base.compound(DISK_COMPARATOR);
        case MEMORY:
            return base.compound(RAM_COMPARATOR);
        case REVOCABLE_CPU:
            return base.compound(REVOCABLE_CPU_COMPARATOR);
        default:
            return base.compound(RANDOM_COMPARATOR);
        }
    }

    private static Ordering<HostOffer> create(Ordering<HostOffer> base, List<OfferOrder> order) {
        if (order.isEmpty()) {
            return base;
        }
        Ordering<HostOffer> compounded = getOrdering(base, order.get(0));
        if (order.size() > 1) {
            return create(compounded, order.subList(1, order.size()));
        } else {
            return compounded;
        }
    }

    /**
     * Create a total offer ordering, based on a general machine maintenance ordering. Additional
     * ordering is compounded based on the list order.
     *
     * @param order The list of offer orders. They will be compounded in the list order.
     * @return A HostOffer ordering.
     */
    static Ordering<HostOffer> create(List<OfferOrder> order) {
        return create(BASE_COMPARATOR, order);
    }
}