/**
* 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.resources;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.StreamSupport;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import org.apache.aurora.scheduler.TierInfo;
import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
import org.apache.mesos.v1.Protos.Offer;
import org.apache.mesos.v1.Protos.Resource;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static org.apache.aurora.scheduler.resources.ResourceManager.getOfferResources;
/**
* Allocate resources from an accepted Mesos Offer to TaskInfo and ExecutorInfo.
*/
public final class AcceptedOffer {
/**
* Reserved resource filter.
*/
@VisibleForTesting
static final Predicate<Resource> RESERVED = e -> e.hasRole() && !e.getRole().equals("*");
/**
* Get proper value for {@link org.apache.mesos.Protos.TaskInfo}'s resources.
* @return A list of Resource used for TaskInfo.
*/
public Iterable<Resource> getTaskResources() {
return taskResources;
}
/**
* Get proper value for {@link org.apache.mesos.Protos.ExecutorInfo}'s resources.
* @return A list of Resource used for ExecutorInfo.
*/
public Iterable<Resource> getExecutorResources() {
return executorResources;
}
private final Iterable<Resource> taskResources;
private final Iterable<Resource> executorResources;
public static AcceptedOffer create(
Offer offer,
IAssignedTask task,
ResourceBag executorOverhead,
TierInfo tierInfo) throws ResourceManager.InsufficientResourcesException {
ImmutableList.Builder<Resource> taskResources = ImmutableList.builder();
ImmutableList.Builder<Resource> executorResources = ImmutableList.builder();
ResourceManager.bagFromResources(task.getTask().getResources())
.streamResourceVectors()
.forEach(entry -> {
ResourceType type = entry.getKey();
Iterable<Resource.Builder> offerResources = StreamSupport
.stream(getOfferResources(offer, tierInfo, entry.getKey()).spliterator(), false)
// Note the reverse order of args in .compare(): we want RESERVED resources first.
.sorted((l, r) -> Boolean.compare(RESERVED.test(r), RESERVED.test(l)))
.map(Resource::toBuilder)
.collect(toList());
boolean isRevocable = type.isMesosRevocable() && tierInfo.isRevocable();
taskResources.addAll(type.getMesosResourceConverter().toMesosResource(
offerResources,
type.getMapper().isPresent()
? () -> type.getMapper().get().getAssigned(task)
: () -> entry.getValue(),
isRevocable));
if (executorOverhead.getResourceVectors().containsKey(type)) {
executorResources.addAll(type.getMesosResourceConverter().toMesosResource(
offerResources,
() -> executorOverhead.getResourceVectors().get(type),
isRevocable));
}
});
return new AcceptedOffer(taskResources.build(), executorResources.build());
}
private AcceptedOffer(
List<Resource> taskResources,
List<Resource> executorResources) {
this.taskResources = requireNonNull(taskResources);
this.executorResources = requireNonNull(executorResources);
}
}