All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.vespa.hosted.provision.provisioning.DockerHostCapacity Maven / Gradle / Ivy

// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.provisioning;

import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Capacity calculation for docker hosts.
 * 

* The calculations is based on an immutable copy of nodes that represents * all capacities in the system - i.e. all nodes in the node repo give or take. * * @author smorgrav */ public class DockerHostCapacity { /** * An immutable list of nodes */ private final NodeList allNodes; public DockerHostCapacity(List allNodes) { this.allNodes = new NodeList(allNodes); } /** * Compare hosts on free capacity. *

* Used in prioritizing hosts for allocation in descending order. */ int compare(Node hostA, Node hostB) { int comp = freeCapacityOf(hostB, false).compare(freeCapacityOf(hostA, false)); if (comp == 0) { comp = freeCapacityOf(hostB, false).compare(freeCapacityOf(hostA, false)); if (comp == 0) { // If resources are equal - we want to assign to the one with the most IPaddresses free comp = freeIPs(hostB) - freeIPs(hostA); } } return comp; } int compareWithoutInactive(Node hostA, Node hostB) { int comp = freeCapacityOf(hostB, true).compare(freeCapacityOf(hostA, true)); if (comp == 0) { comp = freeCapacityOf(hostB, true).compare(freeCapacityOf(hostA, true)); if (comp == 0) { // If resources are equal - we want to assign to the one with the most IPaddresses free comp = freeIPs(hostB) - freeIPs(hostA); } } return comp; } /** * Checks the node capacity and free ip addresses to see * if we could allocate a flavor on the docker host. */ boolean hasCapacity(Node dockerHost, ResourceCapacity requestedCapacity) { return freeCapacityOf(dockerHost, false).hasCapacityFor(requestedCapacity) && freeIPs(dockerHost) > 0; } boolean hasCapacityWhenRetiredAndInactiveNodesAreGone(Node dockerHost, ResourceCapacity requestedCapacity) { return freeCapacityOf(dockerHost, true).hasCapacityFor(requestedCapacity) && freeIPs(dockerHost) > 0; } /** * Number of free (not allocated) IP addresses assigned to the dockerhost. */ int freeIPs(Node dockerHost) { return findFreeIps(dockerHost, allNodes.asList()).size(); } public ResourceCapacity getFreeCapacityTotal() { return allNodes.asList().stream() .filter(n -> n.type().equals(NodeType.host)) .map(n -> freeCapacityOf(n, false)) .reduce(new ResourceCapacity(), ResourceCapacity::add); } public ResourceCapacity getCapacityTotal() { return allNodes.asList().stream() .filter(n -> n.type().equals(NodeType.host)) .map(ResourceCapacity::new) .reduce(new ResourceCapacity(), ResourceCapacity::add); } public int freeCapacityInFlavorEquivalence(Flavor flavor) { return allNodes.asList().stream() .filter(n -> n.type().equals(NodeType.host)) .map(n -> canFitNumberOf(n, flavor)) .reduce(0, (a, b) -> a + b); } public long getNofHostsAvailableFor(Flavor flavor) { return allNodes.asList().stream() .filter(n -> n.type().equals(NodeType.host)) .filter(n -> hasCapacity(n, ResourceCapacity.of(flavor))) .count(); } private int canFitNumberOf(Node node, Flavor flavor) { int capacityFactor = freeCapacityOf(node, false).freeCapacityInFlavorEquivalence(flavor); int ips = freeIPs(node); return Math.min(capacityFactor, ips); } /** * Calculate the remaining capacity for the dockerHost. * @param dockerHost The host to find free capacity of. * * @return A default (empty) capacity if not a docker host, otherwise the free/unallocated/rest capacity */ public ResourceCapacity freeCapacityOf(Node dockerHost, boolean treatInactiveOrRetiredAsUnusedCapacity) { // Only hosts have free capacity if (!dockerHost.type().equals(NodeType.host)) return new ResourceCapacity(); ResourceCapacity hostCapacity = new ResourceCapacity(dockerHost); for (Node container : allNodes.childrenOf(dockerHost).asList()) { boolean isUsedCapacity = !(treatInactiveOrRetiredAsUnusedCapacity && isInactiveOrRetired(container)); if (isUsedCapacity) { hostCapacity.subtract(container); } } return hostCapacity; } private boolean isInactiveOrRetired(Node node) { boolean isInactive = node.state().equals(Node.State.inactive); boolean isRetired = false; if (node.allocation().isPresent()) { isRetired = node.allocation().get().membership().retired(); } return isInactive || isRetired; } /** * Compare the additional ip addresses against the set of used addresses on * child nodes. */ static Set findFreeIps(Node dockerHost, List allNodes) { Set freeIPAddresses = new HashSet<>(dockerHost.additionalIpAddresses()); for (Node child : new NodeList(allNodes).childrenOf(dockerHost).asList()) { freeIPAddresses.removeAll(child.ipAddresses()); } return freeIPAddresses; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy