diff options
author | Jon Bratseth <bratseth@verizonmedia.com> | 2020-03-27 15:02:03 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@verizonmedia.com> | 2020-03-27 15:02:03 +0100 |
commit | b18e2939b6632e7bf02cc12dea096dabecb9e754 (patch) | |
tree | 6c6657cd78bf60e1f862c2308c329ef32843857b | |
parent | bcaf74cc7cddd26f315ea9c60ceb8a5f9b665168 (diff) |
Activate autoscaling
11 files changed, 148 insertions, 39 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java index 7dd2dc7be17..e56e426b499 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java @@ -18,20 +18,42 @@ import java.util.Optional; */ public class Application { - private Map<ClusterSpec.Id, Cluster> clusters = new HashMap<>(); + private final Map<ClusterSpec.Id, Cluster> clusters; + + public Application() { + this(Map.of()); + } + + private Application(Map<ClusterSpec.Id, Cluster> clusters) { + this.clusters = Map.copyOf(clusters); + } /** Returns the cluster with the given id or null if none */ public Cluster cluster(ClusterSpec.Id id) { return clusters.get(id); } + public Application with(ClusterSpec.Id id, Cluster cluster) { + Map<ClusterSpec.Id, Cluster> clusters = new HashMap<>(this.clusters); + clusters.put(id, cluster); + return new Application(clusters); + } + /** - * Sets the min and max resource limits of the given cluster. - * This will create the cluster with these limits if it does not exist. + * Returns an application with the given cluster having the min and max resource limits of the given cluster. * If the cluster has a target which is not inside the new limits, the target is removed. */ - public void setClusterLimits(ClusterSpec.Id id, ClusterResources min, ClusterResources max, Mutex applicationLock) { - Cluster cluster = clusters.computeIfAbsent(id, clusterId -> new Cluster(min, max, Optional.empty())); - if (cluster.targetResources().isPresent() && ! cluster.targetResources().get().isWithin(min, max)) - clusters.put(id, cluster.withoutTarget()); + public Application withClusterLimits(ClusterSpec.Id id, ClusterResources min, ClusterResources max) { + Cluster cluster = clusters.get(id); + return with(id, new Cluster(min, max, cluster == null ? Optional.empty() : cluster.targetResources())); + } + + /** + * Returns an application with the given target for the given cluster, + * if it exists and the target is within the bounds + */ + public Application withClusterTarget(ClusterSpec.Id id, ClusterResources target) { + Cluster cluster = clusters.get(id); + if (cluster == null) return this; + return with(id, cluster.withTarget(target)); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java index 1409857df1a..879fcc5f6cb 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.provision.applications; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.transaction.Mutex; import java.util.concurrent.ConcurrentHashMap; @@ -21,4 +22,8 @@ public class Applications { return applications.computeIfAbsent(applicationId, id -> create ? new Application() : null); } + public void set(ApplicationId id, Application application, Mutex applicationLock) { + applications.put(id, application); + } + } 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 d4f7f10abfd..6ff827ac92b 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 @@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.applications; import com.yahoo.config.provision.ClusterResources; +import java.util.Objects; import java.util.Optional; /** @@ -18,9 +19,14 @@ public class Cluster { private final Optional<ClusterResources> targetResources; Cluster(ClusterResources minResources, ClusterResources maxResources, Optional<ClusterResources> targetResources) { - this.minResources = minResources; - this.maxResources = maxResources; - this.targetResources = targetResources; + this.minResources = Objects.requireNonNull(minResources); + this.maxResources = Objects.requireNonNull(maxResources); + Objects.requireNonNull(targetResources); + + if (targetResources.isPresent() && ! targetResources.get().isWithin(minResources, maxResources)) + this.targetResources = Optional.empty(); + else + this.targetResources = targetResources; } /** Returns the configured minimal resources in this cluster */ diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java index 7a36103f337..f553a4c76a4 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java @@ -73,6 +73,10 @@ public class AllocatableClusterResources { public int groups() { return groups; } public ClusterSpec.Type clusterType() { return clusterType; } + public ClusterResources toAdvertisedClusterResources() { + return new ClusterResources(nodes, groups, advertisedResources); + } + @Override public String toString() { return "$" + cost() + ": " + realResources(); 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 dc9699a7a0b..6612525685a 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 @@ -9,6 +9,7 @@ import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.host.FlavorOverrides; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; +import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; import com.yahoo.vespa.hosted.provision.provisioning.NodeResourceLimits; @@ -66,7 +67,7 @@ public class Autoscaler { * @param clusterNodes the list of all the active nodes in a cluster * @return a new suggested allocation for this cluster, or empty if it should not be rescaled at this time */ - public Optional<AllocatableClusterResources> autoscale(List<Node> clusterNodes) { + public Optional<AllocatableClusterResources> autoscale(Cluster cluster, List<Node> clusterNodes) { if (clusterNodes.stream().anyMatch(node -> node.status().wantToRetire() || node.allocation().get().membership().retired() || node.allocation().get().isRemovable())) { 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 3f26725da15..064c7db5e60 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 @@ -6,8 +6,11 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Deployer; import com.yahoo.config.provision.NodeResources; +import com.yahoo.transaction.Mutex; import com.yahoo.vespa.hosted.provision.Node; 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.AllocatableClusterResources; import com.yahoo.vespa.hosted.provision.autoscale.Autoscaler; import com.yahoo.vespa.hosted.provision.autoscale.NodeMetricsDb; @@ -52,22 +55,49 @@ public class AutoscalingMaintainer extends Maintainer { private void autoscale(ApplicationId application, List<Node> applicationNodes) { try (MaintenanceDeployment deployment = new MaintenanceDeployment(application, deployer, nodeRepository())) { if ( ! deployment.isValid()) return; // Another config server will consider this application - nodesByCluster(applicationNodes).forEach((clusterId, clusterNodes) -> autoscale(application, clusterId, clusterNodes)); + nodesByCluster(applicationNodes).forEach((clusterId, clusterNodes) -> autoscale(application, clusterId, clusterNodes, deployment)); } } - private void autoscale(ApplicationId application, ClusterSpec.Id clusterId, List<Node> clusterNodes) { - Optional<AllocatableClusterResources> target = autoscaler.autoscale(clusterNodes); - if (target.isEmpty()) return; + private void autoscale(ApplicationId applicationId, + ClusterSpec.Id clusterId, + List<Node> clusterNodes, + MaintenanceDeployment deployment) { + Application application = nodeRepository().applications().get(applicationId, true); + Cluster cluster = application.cluster(clusterId); + if (cluster == null) return; // no information on limits for this cluster + Optional<AllocatableClusterResources> target = autoscaler.autoscale(cluster, clusterNodes); + if (target.isEmpty()) return; // current resources are fine + if (cluster.minResources().equals(cluster.maxResources())) // autoscaling is deactivated + logAutoscaleSuggestion(target.get(), applicationId, clusterId, clusterNodes); + else + autoscaleTo(target.get(), applicationId, clusterId, application, deployment); + } + + private void autoscaleTo(AllocatableClusterResources target, + ApplicationId applicationId, + ClusterSpec.Id clusterId, + Application application, + MaintenanceDeployment deployment) { + nodeRepository().applications().set(applicationId, + application.withClusterTarget(clusterId, target.toAdvertisedClusterResources()), + deployment.applicationLock().get()); + deployment.activate(); + } + + private void logAutoscaleSuggestion(AllocatableClusterResources target, + ApplicationId application, + ClusterSpec.Id clusterId, + List<Node> clusterNodes) { Instant lastLogTime = lastLogged.get(new Pair<>(application, clusterId)); if (lastLogTime != null && lastLogTime.isAfter(nodeRepository().clock().instant().minus(Duration.ofHours(1)))) return; - int currentGroups = (int) clusterNodes.stream().map(node -> node.allocation().get().membership().cluster().group()).distinct().count(); + int currentGroups = (int)clusterNodes.stream().map(node -> node.allocation().get().membership().cluster().group()).distinct().count(); ClusterSpec.Type clusterType = clusterNodes.get(0).allocation().get().membership().cluster().type(); - log.info("Autoscale: " + application + " " + clusterType + " " + clusterId + + log.info("Scaling suggestion: " + application + " " + clusterType + " " + clusterId + "\nfrom " + toString(clusterNodes.size(), currentGroups, clusterNodes.get(0).flavor().resources()) + - "\nto " + toString(target.get().nodes(), target.get().groups(), target.get().advertisedResources())); + "\nto " + toString(target.nodes(), target.groups(), target.advertisedResources())); lastLogged.put(new Pair<>(application, clusterId), nodeRepository().clock().instant()); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java index 856de2609be..c21c9d68c8a 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java @@ -36,10 +36,8 @@ class MaintenanceDeployment implements Closeable { public MaintenanceDeployment(ApplicationId application, Deployer deployer, NodeRepository nodeRepository) { this.application = application; Optional<Mutex> lock = tryLock(application, nodeRepository); - try { deployment = tryDeployment(lock, application, deployer, nodeRepository); - this.lock = lock; lock = Optional.empty(); } finally { @@ -52,6 +50,16 @@ class MaintenanceDeployment implements Closeable { return deployment.isPresent(); } + /** + * Returns the application lock held by this, or empty if it is not held. + * + * @throws IllegalStateException id this is called when closed + */ + public Optional<Mutex> applicationLock() { + if (closed) throw new IllegalStateException(this + "is closed"); + return lock; + } + public boolean prepare() { return doStep(() -> deployment.get().prepare()); } @@ -61,7 +69,7 @@ class MaintenanceDeployment implements Closeable { } private boolean doStep(Runnable action) { - if (closed) throw new IllegalStateException("Deployment of '" + application + "' is closed"); + if (closed) throw new IllegalStateException(this + "' is closed"); if ( ! isValid()) return false; try { action.run(); @@ -101,4 +109,9 @@ class MaintenanceDeployment implements Closeable { closed = true; } + @Override + public String toString() { + return "deployment of " + application; + } + } 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 083f8db5aa5..6ae89f6c9ed 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 @@ -148,7 +148,8 @@ public class NodeRepositoryProvisioner implements Provisioner { private ClusterResources decideTargetResources(ApplicationId applicationId, ClusterSpec.Id clusterId, Capacity requested) { try (Mutex lock = nodeRepository.lock(applicationId)) { Application application = nodeRepository.applications().get(applicationId, true); - application.setClusterLimits(clusterId, requested.minResources(), requested.maxResources(), lock); + application = application.withClusterLimits(clusterId, requested.minResources(), requested.maxResources()); + nodeRepository.applications().set(applicationId, application, lock); return application.cluster(clusterId).targetResources() .orElse(currentResources(applicationId, clusterId, requested) .orElse(requested.minResources())); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java index d154af4f025..f02acdc1fca 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java @@ -2,12 +2,15 @@ package com.yahoo.vespa.hosted.provision.autoscale; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ClusterResources; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeResources; import com.yahoo.test.ManualClock; import com.yahoo.vespa.hosted.provision.Node; +import com.yahoo.vespa.hosted.provision.applications.Application; +import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock; import org.junit.Test; @@ -47,7 +50,13 @@ public class AutoscalingIntegrationTest { tester.nodeMetricsDb().gc(tester.clock()); } - var scaledResources = autoscaler.autoscale(tester.nodeRepository().getNodes(application1)); + ClusterResources min = new ClusterResources(2, 1, nodes); + ClusterResources max = new ClusterResources(2, 1, nodes); + + Application application = tester.nodeRepository().applications().get(application1, true).withClusterLimits(cluster1.id(), min, max); + tester.nodeRepository().applications().set(application1, application, tester.nodeRepository().lock(application1)); + var scaledResources = autoscaler.autoscale(application.cluster(cluster1.id()), + tester.nodeRepository().getNodes(application1)); assertTrue(scaledResources.isPresent()); } 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 39259bf44f8..f3b6606a970 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 @@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.autoscale; import com.google.common.collect.Sets; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.CloudName; +import com.yahoo.config.provision.ClusterResources; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.Flavor; @@ -31,6 +32,8 @@ public class AutoscalingTest { @Test public void testAutoscalingSingleContentGroup() { NodeResources resources = new NodeResources(3, 100, 100, 1); + ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1)); + ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1)); AutoscalingTester tester = new AutoscalingTester(resources); ApplicationId application1 = tester.applicationId("application1"); @@ -39,37 +42,39 @@ public class AutoscalingTest { // deploy tester.deploy(application1, cluster1, 5, 1, resources); - assertTrue("No measurements -> No change", tester.autoscale(application1).isEmpty()); + assertTrue("No measurements -> No change", tester.autoscale(application1, cluster1.id(), min, max).isEmpty()); tester.addMeasurements(Resource.cpu, 0.25f, 1f, 60, application1); - assertTrue("Too few measurements -> No change", tester.autoscale(application1).isEmpty()); + assertTrue("Too few measurements -> No change", tester.autoscale(application1, cluster1.id(), min, max).isEmpty()); tester.addMeasurements(Resource.cpu, 0.25f, 1f, 60, application1); AllocatableClusterResources scaledResources = tester.assertResources("Scaling up since resource usage is too high", 15, 1, 1.3, 28.6, 28.6, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); tester.deploy(application1, cluster1, scaledResources); - assertTrue("Cluster in flux -> No further change", tester.autoscale(application1).isEmpty()); + assertTrue("Cluster in flux -> No further change", tester.autoscale(application1, cluster1.id(), min, max).isEmpty()); tester.deactivateRetired(application1, cluster1, scaledResources); tester.addMeasurements(Resource.cpu, 0.8f, 1f, 3, application1); assertTrue("Load change is large, but insufficient measurements for new config -> No change", - tester.autoscale(application1).isEmpty()); + tester.autoscale(application1, cluster1.id(), min, max).isEmpty()); tester.addMeasurements(Resource.cpu, 0.19f, 1f, 100, application1); - assertEquals("Load change is small -> No change", Optional.empty(), tester.autoscale(application1)); + assertEquals("Load change is small -> No change", Optional.empty(), tester.autoscale(application1, cluster1.id(), min, max)); tester.addMeasurements(Resource.cpu, 0.1f, 1f, 120, application1); tester.assertResources("Scaling down since resource usage has gone down significantly", 26, 1, 0.6, 16.0, 16.0, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); } /** We prefer fewer nodes for container clusters as (we assume) they all use the same disk and memory */ @Test public void testAutoscalingSingleContainerGroup() { NodeResources resources = new NodeResources(3, 100, 100, 1); + ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1)); + ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1)); AutoscalingTester tester = new AutoscalingTester(resources); ApplicationId application1 = tester.applicationId("application1"); @@ -81,7 +86,7 @@ public class AutoscalingTest { tester.addMeasurements(Resource.cpu, 0.25f, 1f, 120, application1); AllocatableClusterResources scaledResources = tester.assertResources("Scaling up since cpu usage is too high", 7, 1, 2.6, 80.0, 80.0, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); tester.deploy(application1, cluster1, scaledResources); tester.deactivateRetired(application1, cluster1, scaledResources); @@ -89,12 +94,14 @@ public class AutoscalingTest { tester.addMeasurements(Resource.cpu, 0.1f, 1f, 120, application1); tester.assertResources("Scaling down since cpu usage has gone down", 4, 1, 2.4, 68.6, 68.6, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); } @Test public void testAutoscalingGroupSize1() { NodeResources resources = new NodeResources(3, 100, 100, 1); + ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1)); + ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1)); AutoscalingTester tester = new AutoscalingTester(resources); ApplicationId application1 = tester.applicationId("application1"); @@ -105,12 +112,14 @@ public class AutoscalingTest { tester.addMeasurements(Resource.cpu, 0.25f, 1f, 120, application1); tester.assertResources("Scaling up since resource usage is too high", 7, 7, 2.5, 80.0, 80.0, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); } @Test public void testAutoscalingGroupSize3() { NodeResources resources = new NodeResources(3, 100, 100, 1); + ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1)); + ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1)); AutoscalingTester tester = new AutoscalingTester(resources); ApplicationId application1 = tester.applicationId("application1"); @@ -121,12 +130,14 @@ public class AutoscalingTest { tester.addMeasurements(Resource.cpu, 0.22f, 1f, 120, application1); tester.assertResources("Scaling up since resource usage is too high", 9, 3, 2.7, 83.3, 83.3, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); } @Test public void testAutoscalingAvoidsIllegalConfigurations() { NodeResources resources = new NodeResources(3, 100, 100, 1); + ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1)); + ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1)); AutoscalingTester tester = new AutoscalingTester(resources); ApplicationId application1 = tester.applicationId("application1"); @@ -137,11 +148,13 @@ public class AutoscalingTest { tester.addMeasurements(Resource.memory, 0.02f, 1f, 120, application1); tester.assertResources("Scaling down", 6, 1, 3.0, 4.0, 100.0, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); } @Test public void testAutoscalingAws() { + ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1)); + ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1)); List<Flavor> flavors = new ArrayList<>(); flavors.add(new Flavor("aws-xlarge", new NodeResources(3, 200, 100, 1, NodeResources.DiskSpeed.fast, NodeResources.StorageType.remote))); flavors.add(new Flavor("aws-large", new NodeResources(3, 150, 100, 1, NodeResources.DiskSpeed.fast, NodeResources.StorageType.remote))); @@ -160,7 +173,7 @@ public class AutoscalingTest { tester.addMeasurements(Resource.memory, 0.9f, 0.6f, 120, application1); AllocatableClusterResources scaledResources = tester.assertResources("Scaling up since resource usage is too high.", 8, 1, 3, 83, 34.3, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); tester.deploy(application1, cluster1, scaledResources); tester.deactivateRetired(application1, cluster1, scaledResources); @@ -168,7 +181,7 @@ public class AutoscalingTest { tester.addMeasurements(Resource.memory, 0.3f, 0.6f, 1000, application1); tester.assertResources("Scaling down since resource usage has gone down", 5, 1, 3, 83, 36, - tester.autoscale(application1)); + tester.autoscale(application1, cluster1.id(), min, max)); } } 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 efb97841623..8043d5b2d39 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 @@ -20,6 +20,7 @@ import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; +import com.yahoo.vespa.hosted.provision.applications.Application; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.IP; import com.yahoo.vespa.hosted.provision.provisioning.FatalProvisioningException; @@ -140,8 +141,12 @@ class AutoscalingTester { } } - public Optional<AllocatableClusterResources> autoscale(ApplicationId application) { - return autoscaler.autoscale(nodeRepository().getNodes(application, Node.State.active)); + public Optional<AllocatableClusterResources> autoscale(ApplicationId applicationId, ClusterSpec.Id clusterId, + ClusterResources min, ClusterResources max) { + Application application = nodeRepository().applications().get(applicationId, true).withClusterLimits(clusterId, min, max); + nodeRepository().applications().set(applicationId, application, nodeRepository().lock(applicationId)); + return autoscaler.autoscale(application.cluster(clusterId), + nodeRepository().getNodes(applicationId, Node.State.active)); } public AllocatableClusterResources assertResources(String message, |