diff options
author | Jon Bratseth <bratseth@gmail.com> | 2022-12-13 10:43:06 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@gmail.com> | 2022-12-13 10:43:06 +0100 |
commit | 5a6d0d6cd178109caaf237ee428fe1ffbf1fde1e (patch) | |
tree | 8f2169c859c2e1d74477bd06049cfc44456e9f42 | |
parent | 000fa3620f53736b7729dfd3fbdc468d00bbf355 (diff) |
Introduce Autoscsaling result object
15 files changed, 147 insertions, 121 deletions
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java index 23cdff15ad9..47982174d4f 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java @@ -173,6 +173,7 @@ public class FastHit extends Hit { * <a href="https://docs.vespa.ai/en/reference/schema-reference.html#summary-features">summary-features</a> * in the rank profile specified in the query producing this. */ + @Override public FeatureData features() { FeatureData data = (FeatureData)getField("summaryfeatures"); return data == null ? super.features() : data; diff --git a/container-search/src/main/java/com/yahoo/search/result/FeatureData.java b/container-search/src/main/java/com/yahoo/search/result/FeatureData.java index b1d64329927..2cb5e0e07e9 100644 --- a/container-search/src/main/java/com/yahoo/search/result/FeatureData.java +++ b/container-search/src/main/java/com/yahoo/search/result/FeatureData.java @@ -100,11 +100,11 @@ public class FeatureData implements Inspectable, JsonProducer { Inspector featureValue = getInspector(featureName); if ( ! featureValue.valid()) return null; - switch (featureValue.type()) { - case DOUBLE: return featureValue.asDouble(); - case DATA: throw new IllegalArgumentException("Feature '" + featureName + "' is a tensor, not a double"); - default: throw new IllegalStateException("Unexpected feature value type " + featureValue.type()); - } + return switch (featureValue.type()) { + case DOUBLE -> featureValue.asDouble(); + case DATA -> throw new IllegalArgumentException("Feature '" + featureName + "' is a tensor, not a double"); + default -> throw new IllegalStateException("Unexpected feature value type " + featureValue.type()); + }; } /** 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 14adc617497..eb317c62776 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 @@ -5,6 +5,7 @@ import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterResources; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.hosted.provision.autoscale.Autoscaler; +import com.yahoo.vespa.hosted.provision.autoscale.Autoscaling; import java.time.Instant; import java.util.ArrayList; @@ -27,8 +28,8 @@ public class Cluster { private final boolean exclusive; private final ClusterResources min, max; private final boolean required; - private final Optional<Suggestion> suggested; - private final Optional<ClusterResources> target; + private final Autoscaling suggested; + private final Autoscaling target; /** The maxScalingEvents last scaling events of this, sorted by increasing time (newest last) */ private final List<ScalingEvent> scalingEvents; @@ -39,8 +40,8 @@ public class Cluster { ClusterResources minResources, ClusterResources maxResources, boolean required, - Optional<Suggestion> suggestedResources, - Optional<ClusterResources> targetResources, + Autoscaling suggested, + Autoscaling target, List<ScalingEvent> scalingEvents, AutoscalingStatus autoscalingStatus) { this.id = Objects.requireNonNull(id); @@ -48,12 +49,12 @@ public class Cluster { this.min = Objects.requireNonNull(minResources); this.max = Objects.requireNonNull(maxResources); this.required = required; - this.suggested = Objects.requireNonNull(suggestedResources); - Objects.requireNonNull(targetResources); - if (targetResources.isPresent() && ! targetResources.get().isWithin(minResources, maxResources)) - this.target = Optional.empty(); + this.suggested = Objects.requireNonNull(suggested); + Objects.requireNonNull(target); + if (target.resources().isPresent() && ! target.resources().get().isWithin(minResources, maxResources)) + this.target = Autoscaling.empty(); else - this.target = targetResources; + this.target = target; this.scalingEvents = List.copyOf(scalingEvents); this.autoscalingStatus = autoscalingStatus; } @@ -80,19 +81,19 @@ public class Cluster { * have allocated at the moment (whether or not it actually has it), * or empty if the system currently has no target. */ - public Optional<ClusterResources> targetResources() { return target; } + public Autoscaling target() { return target; } /** - * The suggested size of this cluster, which may or may not be within the min and max limits, + * The suggested resources, which may or may not be within the min and max limits, * or empty if there is currently no recorded suggestion. */ - public Optional<Suggestion> suggestedResources() { return suggested; } + public Autoscaling suggested() { return suggested; } /** Returns true if there is a current suggestion and we should actually make this suggestion to users. */ public boolean shouldSuggestResources(ClusterResources currentResources) { - if (suggested.isEmpty()) return false; - if (suggested.get().resources().isWithin(min, max)) return false; - if ( ! Autoscaler.worthRescaling(currentResources, suggested.get().resources())) return false; + if (suggested.resources().isEmpty()) return false; + if (suggested.resources().get().isWithin(min, max)) return false; + if ( ! Autoscaler.worthRescaling(currentResources, suggested.resources().get())) return false; return true; } @@ -113,11 +114,11 @@ public class Cluster { suggested, target, scalingEvents, autoscalingStatus); } - public Cluster withSuggested(Optional<Suggestion> suggested) { + public Cluster withSuggested(Autoscaling suggested) { return new Cluster(id, exclusive, min, max, required, suggested, target, scalingEvents, autoscalingStatus); } - public Cluster withTarget(Optional<ClusterResources> target) { + public Cluster withTarget(Autoscaling target) { return new Cluster(id, exclusive, min, max, required, suggested, target, scalingEvents, autoscalingStatus); } @@ -168,44 +169,7 @@ public class Cluster { public static Cluster create(ClusterSpec.Id id, boolean exclusive, Capacity requested) { return new Cluster(id, exclusive, requested.minResources(), requested.maxResources(), requested.isRequired(), - Optional.empty(), Optional.empty(), List.of(), AutoscalingStatus.empty()); - } - - public static class Suggestion { - - private final ClusterResources resources; - private final Instant at; - - public Suggestion(ClusterResources resources, Instant at) { - this.resources = resources; - this.at = at; - } - - /** Returns the suggested resources */ - public ClusterResources resources() { return resources; } - - /** Returns the instant this suggestion was made */ - public Instant at() { return at; } - - @Override - public String toString() { - return "suggestion made at " + at + ": " + resources; - } - - @Override - public int hashCode() { - return Objects.hash(resources, at); - } - - @Override - public boolean equals(Object o) { - if ( ! (o instanceof Suggestion)) return false; - Suggestion other = (Suggestion)o; - if ( ! this.at.equals(other.at)) return false; - if ( ! this.resources.equals(other.resources)) return false; - return true; - } - + Autoscaling.empty(), Autoscaling.empty(), List.of(), AutoscalingStatus.empty()); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaling.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaling.java new file mode 100644 index 00000000000..9da17a39242 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaling.java @@ -0,0 +1,57 @@ +package com.yahoo.vespa.hosted.provision.autoscale; + +import com.yahoo.config.provision.ClusterResources; + +import java.time.Instant; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; + +/** + * An autoscaling result. + * + * @author bratseth + */ +public class Autoscaling { + + private final Optional<ClusterResources> resources; + private final Instant at; + + public Autoscaling(ClusterResources resources, Instant at) { + this(Optional.of(resources), at); + } + + public Autoscaling(Optional<ClusterResources> resources, Instant at) { + this.resources = resources; + this.at = at; + } + + /** Returns the resource target of this, or empty if non target. */ + public Optional<ClusterResources> resources() { + return resources; + } + + /** Returns the time this target was decided. */ + public Instant at() { return at; } + + @Override + public boolean equals(Object o) { + if ( ! (o instanceof Autoscaling other)) return false; + if ( ! this.at.equals(other.at)) return false; + if ( ! this.resources.equals(other.resources)) return false; + return true; + } + + @Override + public int hashCode() { + return Objects.hash(resources, at); + } + + @Override + public String toString() { + return "autoscaling to " + resources + ", made at " + at; + } + + public static Autoscaling empty() { return new Autoscaling(Optional.empty(), Instant.EPOCH); } + +} 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 679cecd4f3a..c3838dcee75 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 @@ -15,6 +15,7 @@ import com.yahoo.vespa.hosted.provision.applications.Applications; import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.autoscale.AllocatableClusterResources; import com.yahoo.vespa.hosted.provision.autoscale.Autoscaler; +import com.yahoo.vespa.hosted.provision.autoscale.Autoscaling; import com.yahoo.vespa.hosted.provision.autoscale.NodeMetricSnapshot; import com.yahoo.vespa.hosted.provision.node.History; import java.time.Duration; @@ -83,7 +84,7 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer { // 1. Update cluster info updatedCluster = updateCompletion(cluster.get(), clusterNodes) .with(advice.reason()) - .withTarget(advice.target()); + .withTarget(new Autoscaling(advice.target(), nodeRepository().clock().instant())); applications().put(application.get().with(updatedCluster), lock); var current = new AllocatableClusterResources(clusterNodes, nodeRepository()).advertisedResources(); @@ -100,7 +101,7 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer { } private boolean anyChanges(Autoscaler.Advice advice, Cluster cluster, Cluster updatedCluster, NodeList clusterNodes) { - if (advice.isPresent() && !cluster.targetResources().equals(advice.target())) return true; + if (advice.isPresent() && !cluster.target().resources().equals(advice.target())) return true; if (updatedCluster != cluster) return true; if ( ! advice.reason().equals(cluster.autoscalingStatus())) return true; if (advice.target().isPresent() && diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java index 531201f9484..536a1917eb1 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java @@ -13,6 +13,7 @@ import com.yahoo.vespa.hosted.provision.applications.Application; import com.yahoo.vespa.hosted.provision.applications.Applications; import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.autoscale.Autoscaler; +import com.yahoo.vespa.hosted.provision.autoscale.Autoscaling; import com.yahoo.vespa.hosted.provision.autoscale.MetricsDb; import java.time.Duration; @@ -82,11 +83,11 @@ public class ScalingSuggestionsMaintainer extends NodeRepositoryMaintainer { Optional<Cluster> cluster = application.cluster(clusterId); if (cluster.isEmpty()) return; var at = nodeRepository().clock().instant(); - var currentSuggestion = cluster.get().suggestedResources(); - if (currentSuggestion.isEmpty() - || currentSuggestion.get().at().isBefore(at.minus(Duration.ofDays(7))) - || isHigher(suggestion, currentSuggestion.get().resources())) - applications().put(application.with(cluster.get().withSuggested(Optional.of(new Cluster.Suggestion(suggestion, at)))), lock); + var currentSuggestion = cluster.get().suggested(); + if (currentSuggestion.resources().isEmpty() + || currentSuggestion.at().isBefore(at.minus(Duration.ofDays(7))) + || isHigher(suggestion, currentSuggestion.resources().get())) + applications().put(application.with(cluster.get().withSuggested(new Autoscaling(suggestion, at))), lock); } private boolean isHigher(ClusterResources r1, ClusterResources r2) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializer.java index 74088e8d269..f57c811b6d5 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializer.java @@ -14,6 +14,7 @@ import com.yahoo.vespa.hosted.provision.applications.AutoscalingStatus; import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.applications.ScalingEvent; import com.yahoo.vespa.hosted.provision.applications.Status; +import com.yahoo.vespa.hosted.provision.autoscale.Autoscaling; import java.io.IOException; import java.io.UncheckedIOException; @@ -22,7 +23,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; /** * Application JSON serializer @@ -51,7 +51,7 @@ public class ApplicationSerializer { private static final String requiredKey = "required"; private static final String suggestedKey = "suggested"; private static final String resourcesKey = "resources"; - private static final String targetResourcesKey = "target"; + private static final String targetKey = "target"; private static final String nodesKey = "nodes"; private static final String groupsKey = "groups"; private static final String nodeResourcesKey = "resources"; @@ -119,10 +119,9 @@ public class ApplicationSerializer { toSlime(cluster.minResources(), clusterObject.setObject(minResourcesKey)); toSlime(cluster.maxResources(), clusterObject.setObject(maxResourcesKey)); clusterObject.setBool(requiredKey, cluster.required()); - cluster.suggestedResources().ifPresent(suggested -> toSlime(suggested, clusterObject.setObject(suggestedKey))); - cluster.targetResources().ifPresent(target -> toSlime(target, clusterObject.setObject(targetResourcesKey))); + toSlime(cluster.suggested(), clusterObject.setObject(suggestedKey)); + toSlime(cluster.target(), clusterObject.setObject(targetKey)); scalingEventsToSlime(cluster.scalingEvents(), clusterObject.setArray(scalingEventsKey)); - clusterObject.setString(autoscalingStatusKey, cluster.autoscalingStatus().description()); // TODO: Remove after June 2021 toSlime(cluster.autoscalingStatus(), clusterObject.setObject(autoscalingStatusObjectKey)); } @@ -132,15 +131,15 @@ public class ApplicationSerializer { clusterResourcesFromSlime(clusterObject.field(minResourcesKey)), clusterResourcesFromSlime(clusterObject.field(maxResourcesKey)), clusterObject.field(requiredKey).asBool(), - optionalSuggestionFromSlime(clusterObject.field(suggestedKey)), - optionalClusterResourcesFromSlime(clusterObject.field(targetResourcesKey)), + autoscalingFromSlime(clusterObject.field(suggestedKey)), + autoscalingFromSlime(clusterObject.field(targetKey)), scalingEventsFromSlime(clusterObject.field(scalingEventsKey)), autoscalingStatusFromSlime(clusterObject.field(autoscalingStatusObjectKey), clusterObject)); } - private static void toSlime(Cluster.Suggestion suggestion, Cursor suggestionObject) { - toSlime(suggestion.resources(), suggestionObject.setObject(resourcesKey)); - suggestionObject.setLong(atKey, suggestion.at().toEpochMilli()); + private static void toSlime(Autoscaling autoscaling, Cursor autoscalingObject) { + autoscaling.resources().ifPresent(resources -> toSlime(resources, autoscalingObject.setObject(resourcesKey))); + autoscalingObject.setLong(atKey, autoscaling.at().toEpochMilli()); } private static void toSlime(ClusterResources resources, Cursor clusterResourcesObject) { @@ -149,25 +148,26 @@ public class ApplicationSerializer { NodeResourcesSerializer.toSlime(resources.nodeResources(), clusterResourcesObject.setObject(nodeResourcesKey)); } + private static Optional<ClusterResources> optionalClusterResourcesFromSlime(Inspector clusterResourcesObject) { + if ( ! clusterResourcesObject.valid()) return Optional.empty(); + return Optional.of(clusterResourcesFromSlime(clusterResourcesObject)); + } + private static ClusterResources clusterResourcesFromSlime(Inspector clusterResourcesObject) { return new ClusterResources((int)clusterResourcesObject.field(nodesKey).asLong(), (int)clusterResourcesObject.field(groupsKey).asLong(), NodeResourcesSerializer.resourcesFromSlime(clusterResourcesObject.field(nodeResourcesKey))); } - private static Optional<Cluster.Suggestion> optionalSuggestionFromSlime(Inspector suggestionObject) { - if ( ! suggestionObject.valid()) return Optional.empty(); - - if (suggestionObject.field(nodesKey).valid()) // TODO: Remove this line and the next after January 2021 - return Optional.of(new Cluster.Suggestion(clusterResourcesFromSlime(suggestionObject), Instant.EPOCH)); + private static Autoscaling autoscalingFromSlime(Inspector autoscalingObject) { + if ( ! autoscalingObject.valid()) return Autoscaling.empty(); - return Optional.of(new Cluster.Suggestion(clusterResourcesFromSlime(suggestionObject.field(resourcesKey)), - Instant.ofEpochMilli(suggestionObject.field(atKey).asLong()))); - } + if ( ! autoscalingObject.field(atKey).valid()) { // TODO: Remove clause after January 2023 + return new Autoscaling(optionalClusterResourcesFromSlime(autoscalingObject), Instant.EPOCH); + } - private static Optional<ClusterResources> optionalClusterResourcesFromSlime(Inspector clusterResourcesObject) { - return clusterResourcesObject.valid() ? Optional.of(clusterResourcesFromSlime(clusterResourcesObject)) - : Optional.empty(); + return new Autoscaling(optionalClusterResourcesFromSlime(autoscalingObject.field(resourcesKey)), + Instant.ofEpochMilli(autoscalingObject.field(atKey).asLong())); } private static void scalingEventsToSlime(List<ScalingEvent> scalingEvents, Cursor eventArray) { @@ -200,10 +200,6 @@ public class ApplicationSerializer { } private static AutoscalingStatus autoscalingStatusFromSlime(Inspector object, Inspector parent) { - // TODO: Remove this clause after June 2021 - if ( ! object.valid()) return new AutoscalingStatus(AutoscalingStatus.Status.unavailable, - parent.field(autoscalingStatusKey).asString()); - return new AutoscalingStatus(fromAutoscalingStatusCode(object.field(statusKey).asString()), object.field(descriptionKey).asString()); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java index 7947fe9f021..a85377229b4 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java @@ -118,8 +118,8 @@ class Activator { || ! previousResources.justNumbers().equals(currentResources.justNumbers())) { cluster = cluster.with(ScalingEvent.create(previousResources, currentResources, generation, at)); } - if (cluster.targetResources().isPresent() - && cluster.targetResources().get().justNumbers().equals(currentResources.justNumbers())) { + if (cluster.target().resources().isPresent() + && cluster.target().resources().get().justNumbers().equals(currentResources.justNumbers())) { cluster = cluster.with(new AutoscalingStatus(AutoscalingStatus.Status.ideal, "Cluster is ideally scaled within configured limits")); } 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 3256ae7c73a..59e67f65f8f 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 @@ -154,7 +154,7 @@ public class NodeRepositoryProvisioner implements Provisioner { .withCluster(clusterSpec.id(), clusterSpec.isExclusive(), requested); nodeRepository.applications().put(application, lock); var cluster = application.cluster(clusterSpec.id()).get(); - return cluster.targetResources().orElseGet(() -> currentResources(application, clusterSpec, cluster, requested)); + return cluster.target().resources().orElseGet(() -> currentResources(application, clusterSpec, cluster, requested)); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java index b6103bb23fa..9479696143b 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java @@ -77,8 +77,8 @@ public class ApplicationSerializer { toSlime(limits.max(), clusterObject.setObject("max")); toSlime(currentResources, clusterObject.setObject("current")); if (cluster.shouldSuggestResources(currentResources)) - cluster.suggestedResources().ifPresent(suggested -> toSlime(suggested.resources(), clusterObject.setObject("suggested"))); - cluster.targetResources().ifPresent(target -> toSlime(target, clusterObject.setObject("target"))); + cluster.suggested().resources().ifPresent(suggested -> toSlime(suggested, clusterObject.setObject("suggested"))); + cluster.target().resources().ifPresent(target -> toSlime(target, clusterObject.setObject("target"))); clusterModel.ifPresent(model -> clusterUtilizationToSlime(model, clusterObject.setObject("utilization"))); scalingEventsToSlime(cluster.scalingEvents(), clusterObject.setArray("scalingEvents")); clusterObject.setString("autoscalingStatusCode", cluster.autoscalingStatus().status().name()); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java index 4794c0b48b5..93e33051616 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java @@ -29,6 +29,7 @@ import com.yahoo.vespa.hosted.provision.NodeMutex; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.applications.Application; import com.yahoo.vespa.hosted.provision.applications.Cluster; +import com.yahoo.vespa.hosted.provision.autoscale.Autoscaling; import com.yahoo.vespa.hosted.provision.autoscale.MemoryMetricsDb; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.IP; @@ -59,6 +60,7 @@ import static com.yahoo.config.provision.NodeResources.StorageType.remote; * Instantiated by DI. */ public class MockNodeRepository extends NodeRepository { + public static final CloudAccount tenantAccount = CloudAccount.from("777888999000"); private final NodeFlavors flavors; @@ -193,11 +195,11 @@ public class MockNodeRepository extends NodeRepository { null), app1Id, provisioner); Application app1 = applications().get(app1Id).get(); Cluster cluster1 = app1.cluster(cluster1Id.id()).get(); - cluster1 = cluster1.withSuggested(Optional.of(new Cluster.Suggestion(new ClusterResources(6, 2, - new NodeResources(3, 20, 100, 1)), - clock().instant()))); - cluster1 = cluster1.withTarget(Optional.of(new ClusterResources(4, 1, - new NodeResources(3, 16, 100, 1)))); + cluster1 = cluster1.withSuggested(new Autoscaling(new ClusterResources(6, 2, + new NodeResources(3, 20, 100, 1)), + clock().instant())); + cluster1 = cluster1.withTarget(new Autoscaling(new ClusterResources(4, 1, + new NodeResources(3, 16, 100, 1)), clock().instant())); try (Mutex lock = applications().lock(app1Id)) { applications().put(app1.with(cluster1), lock); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java index f6c393a6f4d..abe25b05955 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java @@ -269,7 +269,7 @@ public class AutoscalingTest { .build(); // Redeployment without target: Uses current resource numbers with *requested* non-numbers (i.e disk-speed any) - assertTrue(fixture.tester().nodeRepository().applications().get(fixture.applicationId).get().cluster(fixture.clusterSpec.id()).get().targetResources().isEmpty()); + assertTrue(fixture.tester().nodeRepository().applications().get(fixture.applicationId).get().cluster(fixture.clusterSpec.id()).get().target().resources().isEmpty()); fixture.deploy(); assertEquals(DiskSpeed.any, fixture.nodes().first().get().allocation().get().requestedResources().diskSpeed()); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java index de5d3e8544e..fd98af21134 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java @@ -132,8 +132,8 @@ class AutoscalingTester { cluster.minResources(), cluster.maxResources(), cluster.required(), - cluster.suggestedResources(), - cluster.targetResources(), + cluster.suggested(), + cluster.target(), List.of(), // Remove scaling events cluster.autoscalingStatus()); cluster = cluster.with(ScalingEvent.create(cluster.minResources(), cluster.minResources(), diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java index f5ab822721f..c94d864ba9d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java @@ -18,6 +18,7 @@ import com.yahoo.vespa.hosted.provision.Node; 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.autoscale.Autoscaling; import com.yahoo.vespa.hosted.provision.autoscale.Load; import com.yahoo.vespa.hosted.provision.autoscale.NodeMetricSnapshot; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; @@ -71,9 +72,9 @@ public class ScalingSuggestionsMaintainerTest { maintainer.maintain(); assertEquals("8 nodes with [vcpu: 3.2, memory: 4.5 Gb, disk 10.0 Gb, bandwidth: 0.1 Gbps, architecture: x86_64]", - suggestionOf(app1, cluster1, tester).get().resources().toString()); + suggestionOf(app1, cluster1, tester).resources().get().toString()); assertEquals("8 nodes with [vcpu: 3.6, memory: 4.4 Gb, disk 11.8 Gb, bandwidth: 0.1 Gbps, architecture: x86_64]", - suggestionOf(app2, cluster2, tester).get().resources().toString()); + suggestionOf(app2, cluster2, tester).resources().get().toString()); // Utilization goes way down tester.clock().advance(Duration.ofHours(13)); @@ -81,20 +82,20 @@ public class ScalingSuggestionsMaintainerTest { maintainer.maintain(); assertEquals("Suggestion stays at the peak value observed", "8 nodes with [vcpu: 3.2, memory: 4.5 Gb, disk 10.0 Gb, bandwidth: 0.1 Gbps, architecture: x86_64]", - suggestionOf(app1, cluster1, tester).get().resources().toString()); + suggestionOf(app1, cluster1, tester).resources().get().toString()); // Utilization is still way down and a week has passed tester.clock().advance(Duration.ofDays(7)); addMeasurements(0.10f, 0.10f, 0.10f, 0, 500, app1, tester.nodeRepository()); maintainer.maintain(); assertEquals("Peak suggestion has been outdated", "3 nodes with [vcpu: 1.2, memory: 4.0 Gb, disk 10.0 Gb, bandwidth: 0.1 Gbps, architecture: x86_64]", - suggestionOf(app1, cluster1, tester).get().resources().toString()); + suggestionOf(app1, cluster1, tester).resources().get().toString()); assertTrue(shouldSuggest(app1, cluster1, tester)); tester.clock().advance(Duration.ofDays(3)); addMeasurements(0.7f, 0.7f, 0.7f, 0, 500, app1, tester.nodeRepository()); maintainer.maintain(); - var suggested = tester.nodeRepository().applications().get(app1).get().cluster(cluster1.id()).get().suggestedResources().get().resources(); + var suggested = tester.nodeRepository().applications().get(app1).get().cluster(cluster1.id()).get().suggested().resources().get(); tester.deploy(app1, cluster1, Capacity.from(suggested, suggested, false, true)); tester.clock().advance(Duration.ofDays(2)); addMeasurements(0.2f, 0.65f, 0.6f, @@ -102,12 +103,12 @@ public class ScalingSuggestionsMaintainerTest { maintainer.maintain(); assertEquals("Suggestion is to keep the current allocation", suggested, - suggestionOf(app1, cluster1, tester).get().resources()); + suggestionOf(app1, cluster1, tester).resources().get()); assertFalse("Suggestion is not made as it matches what we have", shouldSuggest(app1, cluster1, tester)); } - private Optional<Cluster.Suggestion> suggestionOf(ApplicationId app, ClusterSpec cluster, ProvisioningTester tester) { - return tester.nodeRepository().applications().get(app).get().cluster(cluster.id()).get().suggestedResources(); + private Autoscaling suggestionOf(ApplicationId app, ClusterSpec cluster, ProvisioningTester tester) { + return tester.nodeRepository().applications().get(app).get().cluster(cluster.id()).get().suggested(); } private boolean shouldSuggest(ApplicationId app, ClusterSpec cluster, ProvisioningTester tester) { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializerTest.java index e34f63d8062..e6460b4a610 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ApplicationSerializerTest.java @@ -11,6 +11,7 @@ import com.yahoo.vespa.hosted.provision.applications.AutoscalingStatus; import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.applications.ScalingEvent; import com.yahoo.vespa.hosted.provision.applications.Status; +import com.yahoo.vespa.hosted.provision.autoscale.Autoscaling; import org.junit.Test; import java.time.Instant; @@ -35,8 +36,8 @@ public class ApplicationSerializerTest { new ClusterResources( 8, 4, new NodeResources(1, 2, 3, 4)), new ClusterResources(12, 6, new NodeResources(3, 6, 21, 24)), true, - Optional.empty(), - Optional.empty(), + Autoscaling.empty(), + Autoscaling.empty(), List.of(), AutoscalingStatus.empty())); var minResources = new NodeResources(1, 2, 3, 4); @@ -45,10 +46,12 @@ public class ApplicationSerializerTest { new ClusterResources( 8, 4, minResources), new ClusterResources(14, 7, new NodeResources(3, 6, 21, 24)), false, - Optional.of(new Cluster.Suggestion(new ClusterResources(20, 10, - new NodeResources(0.5, 4, 14, 16)), - Instant.ofEpochMilli(1234L))), - Optional.of(new ClusterResources(10, 5, new NodeResources(2, 4, 14, 16))), + new Autoscaling(new ClusterResources(20, 10, + new NodeResources(0.5, 4, 14, 16)), + Instant.ofEpochMilli(1234L)), + new Autoscaling(new ClusterResources(10, 5, + new NodeResources(2, 4, 14, 16)), + Instant.ofEpochMilli(5678L)), List.of(new ScalingEvent(new ClusterResources(10, 5, minResources), new ClusterResources(12, 6, minResources), 7L, @@ -76,8 +79,8 @@ public class ApplicationSerializerTest { assertEquals(originalCluster.minResources(), serializedCluster.minResources()); assertEquals(originalCluster.maxResources(), serializedCluster.maxResources()); assertEquals(originalCluster.required(), serializedCluster.required()); - assertEquals(originalCluster.suggestedResources(), serializedCluster.suggestedResources()); - assertEquals(originalCluster.targetResources(), serializedCluster.targetResources()); + assertEquals(originalCluster.suggested(), serializedCluster.suggested()); + assertEquals(originalCluster.target(), serializedCluster.target()); assertEquals(originalCluster.scalingEvents(), serializedCluster.scalingEvents()); assertEquals(originalCluster.autoscalingStatus(), serializedCluster.autoscalingStatus()); } |