/* * Copyright 2015 Netflix, Inc. * * 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 com.netflix.fenzo; import org.apache.mesos.Protos; import java.util.*; public class LeaseProvider { public static VirtualMachineLease getLeaseOffer(final String hostname, final double cpus, final double memory, final List<VirtualMachineLease.Range> portRanges) { return getLeaseOffer(hostname, cpus, memory, 0.0, portRanges, null); } public static VirtualMachineLease getLeaseOffer(final String hostname, final double cpus, final double memory, final double network, final List<VirtualMachineLease.Range> portRanges) { return getLeaseOffer(hostname, cpus, memory, network, portRanges, null); } public static VirtualMachineLease getLeaseOffer(final String hostname, final double cpus, final double memory, final List<VirtualMachineLease.Range> portRanges, final Map<String, Protos.Attribute> attributesMap) { return getLeaseOffer(hostname, cpus, memory, 0.0, portRanges, attributesMap); } public static VirtualMachineLease getLeaseOffer(final String hostname, final double cpus, final double memory, final double disk, final double network, final List<VirtualMachineLease.Range> portRanges, final Map<String, Protos.Attribute> attributesMap) { return getLeaseOffer(hostname, cpus, memory, disk, network, portRanges, attributesMap, null); } public static VirtualMachineLease getLeaseOffer(final String hostname, final double cpus, final double memory, final double disk, final double network, final List<VirtualMachineLease.Range> portRanges, final Map<String, Protos.Attribute> attributesMap, Map<String, Double> scalarResources) { final long offeredTime = System.currentTimeMillis(); final String id = UUID.randomUUID().toString(); final String vmId = UUID.randomUUID().toString(); final Map<String, Double> scalars = scalarResources==null? Collections.<String, Double>emptyMap() : scalarResources; return new VirtualMachineLease() { @Override public String getId() { return id; } @Override public long getOfferedTime() { return offeredTime; } @Override public String hostname() { return hostname; } @Override public String getVMID() { return vmId; } @Override public double cpuCores() { return cpus; } @Override public double memoryMB() { return memory; } public double networkMbps() { return network; } @Override public double diskMB() { return disk; } @Override public List<Range> portRanges() { return portRanges; } @Override public Protos.Offer getOffer() { return Protos.Offer.getDefaultInstance() .toBuilder() .setId(Protos.OfferID.getDefaultInstance().toBuilder().setValue(id).build()) .setHostname(hostname) .setSlaveId(Protos.SlaveID.getDefaultInstance().toBuilder().setValue(vmId).build()) .setFrameworkId(Protos.FrameworkID.getDefaultInstance().toBuilder().setValue("Testing").build()) .build(); } @Override public Map<String, Protos.Attribute> getAttributeMap() { return attributesMap==null? null : attributesMap; } @Override public Double getScalarValue(String name) { return scalars.get(name); } @Override public Map<String, Double> getScalarValues() { return scalars; } }; } public static VirtualMachineLease getLeaseOffer(final String hostname, final double cpus, final double memory, final double network, final List<VirtualMachineLease.Range> portRanges, final Map<String, Protos.Attribute> attributesMap) { return getLeaseOffer(hostname, cpus, memory, 500000, network, portRanges, attributesMap); } public static VirtualMachineLease getLeaseOffer(final String hostname, final double cpus, final double memory, final int portBegin, final int portEnd) { List<VirtualMachineLease.Range> ranges = new ArrayList<>(1); ranges.add(new VirtualMachineLease.Range(portBegin, portEnd)); return getLeaseOffer(hostname, cpus, memory, ranges); } public static List<VirtualMachineLease> getLeases(int numHosts, double cpus, double memory, int portBeg, int portEnd) { return getLeases(numHosts, cpus, memory, 0.0, portBeg, portEnd); } public static List<VirtualMachineLease> getLeases(int numHosts, double cpus, double memory, double network, int portBeg, int portEnd) { return getLeases(0, numHosts, cpus, memory, network, portBeg, portEnd); } public static List<VirtualMachineLease> getLeases(int hostSuffixBegin, int numHosts, double cpus, double memory, int portBeg, int portEnd) { return getLeases(hostSuffixBegin, numHosts, cpus, memory, 0.0, portBeg, portEnd); } public static List<VirtualMachineLease> getLeases(int hostSuffixBegin, int numHosts, double cpus, double memory, double network, int portBeg, int portEnd) { VirtualMachineLease.Range range = new VirtualMachineLease.Range(portBeg, portEnd); List<VirtualMachineLease.Range> ranges = new ArrayList<>(1); ranges.add(range); return getLeases(hostSuffixBegin, numHosts, cpus, memory, network, ranges); } public static List<VirtualMachineLease> getLeases(int numHosts, double cpus, double memory, List<VirtualMachineLease.Range> ports) { return getLeases(0, numHosts, cpus, memory, ports); } public static List<VirtualMachineLease> getLeases(int hostSuffixBegin, int numHosts, double cpus, double memory, List<VirtualMachineLease.Range> ports) { return getLeases(hostSuffixBegin, numHosts, cpus, memory, 0.0, ports); } public static List<VirtualMachineLease> getLeases(int hostSuffixBegin, int numHosts, double cpus, double memory, double network, List<VirtualMachineLease.Range> ports) { List<VirtualMachineLease> leases = new ArrayList<>(numHosts); for(int i=hostSuffixBegin; i<(hostSuffixBegin+numHosts); i++) leases.add(getLeaseOffer("host"+i, cpus, memory, network, ports)); return leases; } private static List<VirtualMachineLease.Range> getRangesAfterConsuming(List<VirtualMachineLease.Range> orig, int consumePort) { List<VirtualMachineLease.Range> result = new ArrayList<>(); for(int i=0; i<orig.size(); i++) { VirtualMachineLease.Range range = orig.get(i); if(consumePort<range.getBeg() || consumePort>range.getEnd()) { result.add(range); continue; } if(range.getBeg() != range.getEnd()) { if(consumePort>range.getBeg()) { VirtualMachineLease.Range split = new VirtualMachineLease.Range(range.getBeg(), consumePort-1); result.add(split); } if(consumePort<range.getEnd()) result.add(new VirtualMachineLease.Range(consumePort+1, range.getEnd())); } for(int j=i+1; j<orig.size(); j++) result.add(orig.get(j)); return result; } throw new IllegalArgumentException("Unexpected to not find " + consumePort + " within the ranges provided"); } public static VirtualMachineLease getConsumedLease(VMAssignmentResult result) { double cpus=0.0; double memory=0.0; double network = 0.0; List<Integer> ports = new ArrayList<>(); for(TaskAssignmentResult r: result.getTasksAssigned()) { cpus += r.getRequest().getCPUs(); memory += r.getRequest().getMemory(); network += r.getRequest().getNetworkMbps(); ports.addAll(r.getAssignedPorts()); } double totalCpus=0.0; double totalMem=0.0; double totalNetwork=0.0; List<VirtualMachineLease.Range> totPortRanges = new ArrayList<>(); String hostname=""; Map<String, Protos.Attribute> attributes = null; for(VirtualMachineLease l: result.getLeasesUsed()) { hostname = l.hostname(); attributes = l.getAttributeMap(); totalCpus += l.cpuCores(); totalMem += l.memoryMB(); totalNetwork += l.networkMbps(); totPortRanges.addAll(l.portRanges()); } for(Integer port: ports) totPortRanges = getRangesAfterConsuming(totPortRanges, port); return getLeaseOffer(hostname, totalCpus-cpus, totalMem-memory, totalNetwork-network, totPortRanges, attributes); } public static VirtualMachineLease getConsumedLease(VirtualMachineLease orig, double consumedCpu, double consumedMemory, List<Integer> consumedPorts) { final double cpu = orig.cpuCores() - consumedCpu; final double memory = orig.memoryMB() - consumedMemory; List<VirtualMachineLease.Range> ranges = orig.portRanges(); for(Integer port: consumedPorts) { ranges = getRangesAfterConsuming(ranges, port); } return getLeaseOffer(orig.hostname(), cpu, memory, 0.0, ranges, orig.getAttributeMap()); } }