diff options
Diffstat (limited to 'node-repository/src/main/java')
4 files changed, 33 insertions, 30 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java index 6a81c17d362..65e0bc558b2 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java @@ -197,9 +197,11 @@ public class Cluster { Duration totalDuration = Duration.ZERO; for (ScalingEvent event : scalingEvents()) { if (event.duration().isEmpty()) continue; + // Assume we have missed timely recording completion if it is longer than 4 days, so ignore + if ( ! event.duration().get().minus(Duration.ofDays(4)).isNegative()) continue; + completedEventCount++; - // Assume we have missed timely recording completion if it is longer than 4 days - totalDuration = totalDuration.plus(maximum(Duration.ofDays(4), event.duration().get())); + totalDuration = totalDuration.plus(event.duration().get()); } if (completedEventCount == 0) { // Use defaults if (clusterSpec.isStateful()) return Duration.ofHours(12); @@ -223,10 +225,4 @@ public class Cluster { return duration; } - private static Duration maximum(Duration largestAllowed, Duration duration) { - if ( ! duration.minus(largestAllowed).isNegative()) - return largestAllowed; - return duration; - } - } 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 4f94f0fab53..f01f5a30870 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 @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import ai.vespa.metrics.ConfigServerMetrics; import com.yahoo.collections.Pair; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; @@ -18,6 +19,7 @@ import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.Node.State; import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.NodeRepository; +import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.node.Allocation; import com.yahoo.vespa.hosted.provision.node.ClusterId; import com.yahoo.vespa.hosted.provision.persistence.CacheStats; @@ -118,7 +120,7 @@ public class MetricsReporter extends NodeRepositoryMaintainer { byCluster.forEach((clusterId, clusterNodes) -> { Metric.Context context = getContext(dimensions(clusterId.application(), clusterId.cluster())); updateExclusiveSwitchMetrics(clusterNodes, nodes, context); - updateClusterCostMetrics(clusterNodes, context); + updateClusterCostMetrics(clusterId, clusterNodes, context); }); } @@ -129,9 +131,16 @@ public class MetricsReporter extends NodeRepositoryMaintainer { metric.set("nodes.exclusiveSwitchFraction", exclusiveSwitchRatio,context); } - private void updateClusterCostMetrics(List<Node> clusterNodes, Metric.Context context) { + private void updateClusterCostMetrics(ClusterId clusterId, + List<Node> clusterNodes, Metric.Context context) { + var cluster = nodeRepository().applications().get(clusterId.application()) + .flatMap(application -> application.cluster(clusterId.cluster())); + if (cluster.isEmpty()) return; double cost = clusterNodes.stream().mapToDouble(node -> node.resources().cost()).sum(); - metric.set("cluster.cost", cost, context); + metric.set(ConfigServerMetrics.CLUSTER_COST.baseName(), cost, context); + metric.set(ConfigServerMetrics.CLUSTER_LOAD_IDEAL_CPU.baseName(), cluster.get().target().ideal().cpu(), context); + metric.set(ConfigServerMetrics.CLUSTER_LOAD_IDEAL_MEMORY.baseName(), cluster.get().target().ideal().memory(), context); + metric.set(ConfigServerMetrics.CLUSTER_LOAD_IDEAL_DISK.baseName(), cluster.get().target().ideal().disk(), context); } private void updateZoneMetrics() { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java index 32fe9ba9f7b..5def863113c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java @@ -50,7 +50,7 @@ public abstract class OsUpgrader { /** The duration this leaves new nodes alone before scheduling any upgrade */ private Duration gracePeriod() { - return Duration.ofDays(1); + return nodeRepository.zone().system().isCd() ? Duration.ofHours(4) : Duration.ofDays(1); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index 237a6657ccc..b0c7a25095e 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -269,34 +269,32 @@ public class NodeRepositoryProvisioner implements Provisioner { private IllegalArgumentException newNoAllocationPossible(ClusterSpec spec, Limits limits) { StringBuilder message = new StringBuilder("No allocation possible within ").append(limits); - if (nodeRepository.exclusiveAllocation(spec)) - message.append(". Nearest allowed node resources: ").append(findNearestNodeResources(limits)); + if (nodeRepository.exclusiveAllocation(spec) && findNearestNodeResources(limits).isPresent()) + message.append(". Nearest allowed node resources: ").append(findNearestNodeResources(limits).get()); return new IllegalArgumentException(message.toString()); } - private NodeResources findNearestNodeResources(Limits limits) { - NodeResources nearestMin = nearestFlavorResources(limits.min().nodeResources()); - NodeResources nearestMax = nearestFlavorResources(limits.max().nodeResources()); - if (limits.min().nodeResources().distanceTo(nearestMin) < limits.max().nodeResources().distanceTo(nearestMax)) + private Optional<NodeResources> findNearestNodeResources(Limits limits) { + Optional<NodeResources> nearestMin = nearestFlavorResources(limits.min().nodeResources()); + Optional<NodeResources> nearestMax = nearestFlavorResources(limits.max().nodeResources()); + if (nearestMin.isEmpty()) return nearestMax; + if (nearestMax.isEmpty()) return nearestMin; + if (limits.min().nodeResources().distanceTo(nearestMin.get()) < limits.max().nodeResources().distanceTo(nearestMax.get())) return nearestMin; else return nearestMax; } /** Returns the advertised flavor resources which are nearest to the given resources */ - private NodeResources nearestFlavorResources(NodeResources requestedResources) { - NodeResources nearestHostResources = nodeRepository.flavors().getFlavors().stream() - .map(flavor -> nodeRepository.resourcesCalculator().advertisedResourcesOf(flavor)) - .filter(resources -> resources.diskSpeed().compatibleWith(requestedResources.diskSpeed())) - .filter(resources -> resources.storageType().compatibleWith(requestedResources.storageType())) - .filter(resources -> resources.architecture().compatibleWith(requestedResources.architecture())) - .min(Comparator.comparingDouble(resources -> resources.distanceTo(requestedResources))) - .orElseThrow() - .withBandwidthGbps(requestedResources.bandwidthGbps()); - if ( nearestHostResources.storageType() == NodeResources.StorageType.remote) - nearestHostResources = nearestHostResources.withDiskGb(requestedResources.diskGb()); - return nearestHostResources; + private Optional<NodeResources> nearestFlavorResources(NodeResources requestedResources) { + return nodeRepository.flavors().getFlavors().stream() + .map(flavor -> nodeRepository.resourcesCalculator().advertisedResourcesOf(flavor)) + .filter(resources -> resources.satisfies(requestedResources)) + .min(Comparator.comparingDouble(resources -> resources.distanceTo(requestedResources))) + .map(resources -> resources.withBandwidthGbps(requestedResources.bandwidthGbps())) + .map(resources -> resources.storageType() == NodeResources.StorageType.remote ? + resources.withDiskGb(requestedResources.diskGb()) : resources); } } |