aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository/src/main/java
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@yahooinc.com>2024-04-17 16:39:32 +0200
committerHåkon Hallingstad <hakon@yahooinc.com>2024-04-17 16:39:32 +0200
commit41e07031f1d807096f8053feb1e3606f6d3854f8 (patch)
treebc3a8ee9aa1aa0c1889d023e1df76202ed9b8bee /node-repository/src/main/java
parent69bda751ffc40a4351300c33e7c1f0868ecae248 (diff)
Propagate cloud account to ResourcesCalculator
Diffstat (limited to 'node-repository/src/main/java')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java25
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java9
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java5
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java12
8 files changed, 37 insertions, 30 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java
index cb70eb977c4..be20f45922c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.provision.autoscale;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
@@ -35,19 +36,21 @@ public class AllocatableResources {
/** Fake allocatable resources from requested capacity */
public AllocatableResources(ClusterResources requested,
ClusterSpec clusterSpec,
- NodeRepository nodeRepository) {
+ NodeRepository nodeRepository,
+ Optional<CloudAccount> enclaveAccount) {
this.nodes = requested.nodes();
this.groups = requested.groups();
- this.realResources = nodeRepository.resourcesCalculator().requestToReal(requested.nodeResources(), nodeRepository.exclusiveAllocation(clusterSpec), false);
+ this.realResources = nodeRepository.resourcesCalculator().requestToReal(requested.nodeResources(), enclaveAccount,
+ nodeRepository.exclusiveAllocation(clusterSpec), false);
this.advertisedResources = requested.nodeResources();
this.clusterSpec = clusterSpec;
this.fulfilment = 1;
}
- public AllocatableResources(NodeList nodes, NodeRepository nodeRepository) {
+ public AllocatableResources(NodeList nodes, NodeRepository nodeRepository, Optional<CloudAccount> enclaveAccount) {
this.nodes = nodes.size();
this.groups = (int)nodes.stream().map(node -> node.allocation().get().membership().cluster().group()).distinct().count();
- this.realResources = averageRealResourcesOf(nodes.asList(), nodeRepository); // Average since we average metrics over nodes
+ this.realResources = averageRealResourcesOf(nodes.asList(), nodeRepository, enclaveAccount); // Average since we average metrics over nodes
this.advertisedResources = nodes.requestedResources();
this.clusterSpec = nodes.clusterSpec();
this.fulfilment = 1;
@@ -155,7 +158,7 @@ public class AllocatableResources {
(fulfilment < 1.0 ? " (fulfilment " + fulfilment + ")" : "");
}
- private static NodeResources averageRealResourcesOf(List<Node> nodes, NodeRepository nodeRepository) {
+ private static NodeResources averageRealResourcesOf(List<Node> nodes, NodeRepository nodeRepository, Optional<CloudAccount> enclaveAccount) {
NodeResources sum = new NodeResources(0, 0, 0, 0).justNumbers();
for (Node node : nodes) {
sum = sum.add(nodeRepository.resourcesCalculator().realResourcesOf(node, nodeRepository).justNumbers());
@@ -180,17 +183,20 @@ public class AllocatableResources {
// We decide resources: Add overhead to what we'll request (advertised) to make sure real becomes (at least) cappedNodeResources
var allocatableResources = calculateAllocatableResources(wantedResources,
nodeRepository,
+ model.cloudAccount(),
clusterSpec,
applicationLimits,
exclusive,
true);
var worstCaseRealResources = nodeRepository.resourcesCalculator().requestToReal(allocatableResources.advertisedResources,
+ model.cloudAccount(),
exclusive,
false);
if ( ! systemLimits.isWithinRealLimits(worstCaseRealResources, clusterSpec)) {
allocatableResources = calculateAllocatableResources(wantedResources,
nodeRepository,
+ model.cloudAccount(),
clusterSpec,
applicationLimits,
exclusive,
@@ -210,7 +216,7 @@ public class AllocatableResources {
for (Flavor flavor : nodeRepository.flavors().getFlavors()) {
// Flavor decide resources: Real resources are the worst case real resources we'll get if we ask for these advertised resources
NodeResources advertisedResources = nodeRepository.resourcesCalculator().advertisedResourcesOf(flavor);
- NodeResources realResources = nodeRepository.resourcesCalculator().requestToReal(advertisedResources, exclusive, false);
+ NodeResources realResources = nodeRepository.resourcesCalculator().requestToReal(advertisedResources, model.cloudAccount(), exclusive, false);
// Adjust where we don't need exact match to the flavor
if (flavor.resources().storageType() == NodeResources.StorageType.remote) {
@@ -251,20 +257,21 @@ public class AllocatableResources {
private static AllocatableResources calculateAllocatableResources(ClusterResources wantedResources,
NodeRepository nodeRepository,
+ Optional<CloudAccount> enclaveAccount,
ClusterSpec clusterSpec,
Limits applicationLimits,
boolean exclusive,
boolean bestCase) {
var systemLimits = nodeRepository.nodeResourceLimits();
- var advertisedResources = nodeRepository.resourcesCalculator().realToRequest(wantedResources.nodeResources(), exclusive, bestCase);
+ var advertisedResources = nodeRepository.resourcesCalculator().realToRequest(wantedResources.nodeResources(), enclaveAccount, exclusive, bestCase);
advertisedResources = systemLimits.enlargeToLegal(advertisedResources, clusterSpec, exclusive, true); // Ask for something legal
advertisedResources = applicationLimits.cap(advertisedResources); // Overrides other conditions, even if it will then fail
- var realResources = nodeRepository.resourcesCalculator().requestToReal(advertisedResources, exclusive, bestCase); // What we'll really get
+ var realResources = nodeRepository.resourcesCalculator().requestToReal(advertisedResources, enclaveAccount, exclusive, bestCase); // What we'll really get
if ( ! systemLimits.isWithinRealLimits(realResources, clusterSpec)
&& advertisedResources.storageType() == NodeResources.StorageType.any) {
// Since local disk reserves some of the storage, try to constrain to remote disk
advertisedResources = advertisedResources.with(NodeResources.StorageType.remote);
- realResources = nodeRepository.resourcesCalculator().requestToReal(advertisedResources, exclusive, bestCase);
+ realResources = nodeRepository.resourcesCalculator().requestToReal(advertisedResources, enclaveAccount, exclusive, bestCase);
}
return new AllocatableResources(wantedResources.with(realResources),
advertisedResources,
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
index 45ef2d1d7b5..61d4ced1367 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
@@ -10,7 +10,6 @@ import com.yahoo.vespa.hosted.provision.NodeRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import java.util.stream.Collectors;
import static com.yahoo.vespa.hosted.provision.autoscale.Autoscaler.headroomRequiredToScaleDown;
@@ -38,9 +37,7 @@ public class AllocationOptimizer {
* @return the best allocation, if there are any possible legal allocations, fulfilling the target
* fully or partially, within the limits
*/
- public Optional<AllocatableResources> findBestAllocation(Load loadAdjustment,
- ClusterModel model,
- Limits limits) {
+ public Optional<AllocatableResources> findBestAllocation(Load loadAdjustment, ClusterModel model, Limits limits) {
return findBestAllocations(loadAdjustment, model, limits).stream().findFirst();
}
@@ -51,9 +48,7 @@ public class AllocationOptimizer {
* @return the best allocations, if there are any possible legal allocations, fulfilling the target
* fully or partially, within the limits. The list contains the three best allocations, sorted from most to least preferred.
*/
- public List<AllocatableResources> findBestAllocations(Load loadAdjustment,
- ClusterModel model,
- Limits limits) {
+ public List<AllocatableResources> findBestAllocations(Load loadAdjustment, ClusterModel model, Limits limits) {
if (limits.isEmpty())
limits = Limits.of(new ClusterResources(minimumNodes, 1, NodeResources.unspecified()),
new ClusterResources(maximumNodes, maximumNodes, NodeResources.unspecified()),
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java
index 40819e709de..cdba43fe57b 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java
@@ -84,7 +84,7 @@ public class Autoscaler {
clusterNodes.not().retired().clusterSpec(),
cluster,
clusterNodes,
- new AllocatableResources(clusterNodes.not().retired(), nodeRepository),
+ new AllocatableResources(clusterNodes.not().retired(), nodeRepository, cluster.cloudAccount()),
nodeRepository.metricsDb(),
nodeRepository.clock());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java
index 986ab830283..d5db3ceddfa 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java
@@ -1,6 +1,7 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.autoscale;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;
@@ -12,6 +13,7 @@ import com.yahoo.vespa.hosted.provision.provisioning.CapacityPolicies;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
+import java.util.Optional;
import java.util.OptionalDouble;
/**
@@ -123,6 +125,7 @@ public class ClusterModel {
public Application application() { return application; }
public ClusterSpec clusterSpec() { return clusterSpec; }
+ public Optional<CloudAccount> cloudAccount() { return cluster.cloudAccount(); }
public AllocatableResources current() { return current; }
private ClusterNodesTimeseries nodeTimeseries() { return nodeTimeseries; }
private ClusterTimeseries clusterTimeseries() { return clusterTimeseries; }
@@ -438,6 +441,7 @@ public class ClusterModel {
clusterSpec,
application.id());
return nodeRepository.resourcesCalculator().requestToReal(initialResources,
+ cluster.cloudAccount(),
nodeRepository.exclusiveAllocation(clusterSpec),
false).memoryGb();
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
index 2bec9aa6115..c96aec10bdb 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
@@ -90,7 +90,7 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer {
NodeList clusterNodes = nodeRepository().nodes().list(Node.State.active).owner(applicationId).cluster(clusterId);
cluster = updateCompletion(cluster, clusterNodes);
- var current = new AllocatableResources(clusterNodes.not().retired(), nodeRepository()).advertisedResources();
+ var current = new AllocatableResources(clusterNodes.not().retired(), nodeRepository(), cluster.cloudAccount()).advertisedResources();
// Autoscale unless an autoscaling is already in progress
Autoscaling autoscaling = null;
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java
index 0d6a98f50a3..541b3b9ff1d 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java
@@ -1,6 +1,7 @@
// Copyright Vespa.ai. 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.CloudAccount;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
@@ -41,10 +42,10 @@ public class EmptyProvisionServiceProvider implements ProvisionServiceProvider {
public NodeResources advertisedResourcesOf(Flavor flavor) { return flavor.resources(); }
@Override
- public NodeResources requestToReal(NodeResources resources, boolean exclusive, boolean bestCase) { return resources; }
+ public NodeResources requestToReal(NodeResources resources, Optional<CloudAccount> enclaveAccount, boolean exclusive, boolean bestCase) { return resources; }
@Override
- public NodeResources realToRequest(NodeResources resources, boolean exclusive, boolean bestCase) { return resources; }
+ public NodeResources realToRequest(NodeResources resources, Optional<CloudAccount> enclaveAccount, boolean exclusive, boolean bestCase) { return resources; }
@Override
public long reservedDiskSpaceInBase2Gb(NodeType nodeType, boolean sharedHost) { return 0; }
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java
index e474ae6eea3..80c8acd4955 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java
@@ -1,12 +1,15 @@
// Copyright Vespa.ai. 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.CloudAccount;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.Nodelike;
+import java.util.Optional;
+
/**
* Some cloud providers advertise that a certain amount of resources are available in a flavor
* but then actually provide less.
@@ -28,13 +31,14 @@ public interface HostResourcesCalculator {
* Used with exclusive hosts:
* Returns the lowest possible real resources we'll get if requesting the given advertised resources
*/
- NodeResources requestToReal(NodeResources advertisedResources, boolean exclusiveAllocation, boolean bestCase);
+ NodeResources requestToReal(NodeResources advertisedResources, Optional<CloudAccount> enclaveAccount,
+ boolean exclusiveAllocation, boolean bestCase);
/**
* Used with shared hosts:
* Returns the advertised resources we need to request to be sure to get at least the given real resources.
*/
- NodeResources realToRequest(NodeResources realResources, boolean exclusiveAllocation, boolean bestCase);
+ NodeResources realToRequest(NodeResources realResources, Optional<CloudAccount> enclaveAccount, boolean exclusiveAllocation, boolean bestCase);
/**
* Returns the disk space to reserve in base2 GB. This space is reserved for use by the host, e.g. for storing
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 8e910a4d61c..bbf5a46a21c 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
@@ -187,8 +187,8 @@ public class NodeRepositoryProvisioner implements Provisioner {
boolean firstDeployment = nodes.isEmpty();
var current =
firstDeployment // start at min, preserve current resources otherwise
- ? new AllocatableResources(initialResourcesFrom(requested, clusterSpec, application.id()), clusterSpec, nodeRepository)
- : new AllocatableResources(nodes, nodeRepository);
+ ? new AllocatableResources(initialResourcesFrom(requested, clusterSpec, application.id()), clusterSpec, nodeRepository, requested.cloudAccount())
+ : new AllocatableResources(nodes, nodeRepository, requested.cloudAccount());
var model = new ClusterModel(nodeRepository, application, clusterSpec, cluster, nodes, current, nodeRepository.metricsDb(), nodeRepository.clock());
return within(Limits.of(requested), model, firstDeployment);
}
@@ -199,9 +199,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
/** Make the minimal adjustments needed to the current resources to stay within the limits */
- private ClusterResources within(Limits limits,
- ClusterModel model,
- boolean firstDeployment) {
+ private ClusterResources within(Limits limits, ClusterModel model, boolean firstDeployment) {
if (limits.min().equals(limits.max())) return limits.min();
// Don't change current deployments that are still legal
@@ -209,9 +207,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
return model.current().advertisedResources();
// Otherwise, find an allocation that preserves the current resources as well as possible
- return allocationOptimizer.findBestAllocation(Load.one(),
- model,
- limits)
+ return allocationOptimizer.findBestAllocation(Load.one(), model, limits)
.orElseThrow(() -> newNoAllocationPossible(model.current().clusterSpec(), limits))
.advertisedResources();
}