diff options
4 files changed, 58 insertions, 48 deletions
diff --git a/config-provisioning/abi-spec.json b/config-provisioning/abi-spec.json index f942ae56d64..1469577ed8d 100644 --- a/config-provisioning/abi-spec.json +++ b/config-provisioning/abi-spec.json @@ -621,6 +621,9 @@ "public double memoryGb()", "public double diskGb()", "public com.yahoo.config.provision.NodeResources$DiskSpeed diskSpeed()", + "public com.yahoo.config.provision.NodeResources withDiskSpeed(com.yahoo.config.provision.NodeResources$DiskSpeed)", + "public com.yahoo.config.provision.NodeResources subtract(com.yahoo.config.provision.NodeResources)", + "public com.yahoo.config.provision.NodeResources add(com.yahoo.config.provision.NodeResources)", "public boolean allocateByLegacyName()", "public java.util.Optional legacyName()", "public boolean equals(java.lang.Object)", diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporter.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporter.java index d8e6b832d5a..5de621634ea 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporter.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporter.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.maintenance; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Flavor; +import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; import com.yahoo.jdisc.Metric; import com.yahoo.vespa.applicationmodel.HostName; @@ -216,20 +217,28 @@ public class MetricsReporter extends Maintainer { private void updateDockerMetrics(LockedNodeList nodes) { // Capacity flavors for docker DockerHostCapacity capacity = new DockerHostCapacity(nodes); - metric.set("hostedVespa.docker.totalCapacityCpu", capacity.getCapacityTotal().vcpu(), null); - metric.set("hostedVespa.docker.totalCapacityMem", capacity.getCapacityTotal().memoryGb(), null); - metric.set("hostedVespa.docker.totalCapacityDisk", capacity.getCapacityTotal().diskGb(), null); - metric.set("hostedVespa.docker.freeCapacityCpu", capacity.getFreeCapacityTotal().vcpu(), null); - metric.set("hostedVespa.docker.freeCapacityMem", capacity.getFreeCapacityTotal().memoryGb(), null); - metric.set("hostedVespa.docker.freeCapacityDisk", capacity.getFreeCapacityTotal().diskGb(), null); + metric.set("hostedVespa.docker.totalCapacityCpu", + capacity.getCapacityTotal(NodeResources.DiskSpeed.any).vcpu(), null); + metric.set("hostedVespa.docker.totalCapacityMem", + capacity.getCapacityTotal(NodeResources.DiskSpeed.any).memoryGb(), null); + metric.set("hostedVespa.docker.totalCapacityDisk", + capacity.getCapacityTotal(NodeResources.DiskSpeed.any).diskGb(), null); + metric.set("hostedVespa.docker.freeCapacityCpu", + capacity.getFreeCapacityTotal(NodeResources.DiskSpeed.any).vcpu(), null); + metric.set("hostedVespa.docker.freeCapacityMem", + capacity.getFreeCapacityTotal(NodeResources.DiskSpeed.any).memoryGb(), null); + metric.set("hostedVespa.docker.freeCapacityDisk", + capacity.getFreeCapacityTotal(NodeResources.DiskSpeed.any).diskGb(), null); List<Flavor> dockerFlavors = nodeRepository().getAvailableFlavors().getFlavors().stream() .filter(f -> f.getType().equals(Flavor.Type.DOCKER_CONTAINER)) .collect(Collectors.toList()); for (Flavor flavor : dockerFlavors) { Metric.Context context = getContextAt("flavor", flavor.name()); - metric.set("hostedVespa.docker.freeCapacityFlavor", capacity.freeCapacityInFlavorEquivalence(flavor), context); - metric.set("hostedVespa.docker.hostsAvailableFlavor", capacity.getNofHostsAvailableFor(flavor), context); + metric.set("hostedVespa.docker.freeCapacityFlavor", + capacity.freeCapacityInFlavorEquivalence(flavor), context); + metric.set("hostedVespa.docker.hostsAvailableFlavor", + capacity.getNofHostsAvailableFor(flavor), context); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacity.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacity.java index 5dc41b54b61..a38d6cc1040 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacity.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacity.java @@ -30,31 +30,25 @@ public class DockerHostCapacity { * Used in prioritizing hosts for allocation in <b>descending</b> order. */ int compare(Node hostA, Node hostB) { - int comp = compare(freeCapacityOf(hostB, false), - freeCapacityOf(hostA, false)); - if (comp == 0) { - comp = compare(freeCapacityOf(hostB, false), - 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 result = compare(freeCapacityOf(hostB, false), freeCapacityOf(hostA, false)); + if (result != 0) return result; + + result = compare(freeCapacityOf(hostB, false), freeCapacityOf(hostA, false)); + if (result != 0) return result; + + // If resources are equal we want to assign to the one with the most IPaddresses free + return freeIPs(hostB) - freeIPs(hostA); } int compareWithoutInactive(Node hostA, Node hostB) { - int comp = compare(freeCapacityOf(hostB, true), - freeCapacityOf(hostA, true)); - if (comp == 0) { - comp = compare(freeCapacityOf(hostB, true), - 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; + int result = compare(freeCapacityOf(hostB, true), freeCapacityOf(hostA, true)); + if (result != 0) return result; + + result = compare(freeCapacityOf(hostB, true), freeCapacityOf(hostA, true)); + if (result != 0) return result; + + // If resources are equal we want to assign to the one with the most IPaddresses free + return freeIPs(hostB) - freeIPs(hostA); } private int compare(NodeResources a, NodeResources b) { @@ -76,34 +70,38 @@ public class DockerHostCapacity { return dockerHost.ipAddressPool().findUnused(allNodes).size(); } - // TODO: Capacity cannot be added when some have slow disks - public NodeResources getFreeCapacityTotal() { + /** Return total free capacity for a given disk speed (or for any disk speed) */ + public NodeResources getFreeCapacityTotal(NodeResources.DiskSpeed speed) { return allNodes.asList().stream() - .filter(n -> n.type().equals(NodeType.host)) - .map(n -> freeCapacityOf(n, false)) - .reduce(new NodeResources(0, 0, 0), NodeResources::add); + .filter(n -> n.type().equals(NodeType.host)) + .filter(n -> speed == NodeResources.DiskSpeed.any || n.flavor().resources().diskSpeed() == speed) + .map(n -> freeCapacityOf(n, false)) + .reduce(new NodeResources(0, 0, 0), NodeResources::add) + .withDiskSpeed(speed); // Set speed to 'any' if necvessary } - // TODO: Capacity cannot be added when some have slow disks - public NodeResources getCapacityTotal() { + /** Return total capacity for a given disk speed (or for any disk speed) */ + public NodeResources getCapacityTotal(NodeResources.DiskSpeed speed) { return allNodes.asList().stream() - .filter(n -> n.type().equals(NodeType.host)) - .map(host -> host.flavor().resources()) - .reduce(new NodeResources(0, 0, 0), NodeResources::add); + .filter(n -> n.type().equals(NodeType.host)) + .filter(n -> speed == NodeResources.DiskSpeed.any || n.flavor().resources().diskSpeed() == speed) + .map(host -> host.flavor().resources()) + .reduce(new NodeResources(0, 0, 0), NodeResources::add) + .withDiskSpeed(speed); // Set speed to 'any' if necessary } 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); + .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, flavor.resources())) - .count(); + .filter(n -> n.type().equals(NodeType.host)) + .filter(n -> hasCapacity(n, flavor.resources())) + .count(); } private int canFitNumberOf(Node node, Flavor flavor) { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacityTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacityTest.java index 2d753ded98e..d5d4bcc954d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacityTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerHostCapacityTest.java @@ -97,7 +97,7 @@ public class DockerHostCapacityTest { @Test public void getCapacityTotal() { - NodeResources total = capacity.getCapacityTotal(); + NodeResources total = capacity.getCapacityTotal(NodeResources.DiskSpeed.any); assertEquals(21.0, total.vcpu(), 0.1); assertEquals(30.0, total.memoryGb(), 0.1); assertEquals(36.0, total.diskGb(), 0.1); @@ -105,7 +105,7 @@ public class DockerHostCapacityTest { @Test public void getFreeCapacityTotal() { - NodeResources totalFree = capacity.getFreeCapacityTotal(); + NodeResources totalFree = capacity.getFreeCapacityTotal(NodeResources.DiskSpeed.any); assertEquals(15.0, totalFree.vcpu(), 0.1); assertEquals(14.0, totalFree.memoryGb(), 0.1); assertEquals(24.0, totalFree.diskGb(), 0.1); |