summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2022-07-17 11:53:57 +0200
committerJon Bratseth <bratseth@gmail.com>2022-07-17 11:53:57 +0200
commit6b0773217a52659c8698076a5a57561d542f9bc0 (patch)
tree85c4b278e2b9418d7b0fde86a30e7178b69d96a7
parent80d967ebd1e8b0639f975c75e4f03da5dec61ee3 (diff)
Introduce fixture
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java1
-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.java7
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java156
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java32
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java83
9 files changed, 194 insertions, 95 deletions
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 7fa369da9c6..41fa9499353 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
@@ -67,7 +67,6 @@ public class AllocationOptimizer {
limits, target, current, clusterModel));
var allocatableResources = AllocatableClusterResources.from(next, current.clusterSpec(), limits,
hosts, nodeRepository);
-
if (allocatableResources.isEmpty()) continue;
if (bestAllocation.isEmpty() || allocatableResources.get().preferableTo(bestAllocation.get()))
bestAllocation = allocatableResources;
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 ed1fbcd3ff8..ac072639cfe 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
@@ -61,8 +61,8 @@ public class Autoscaler {
private Advice autoscale(Application application, Cluster cluster, NodeList clusterNodes, Limits limits) {
ClusterModel clusterModel = new ClusterModel(application,
- cluster,
clusterNodes.clusterSpec(),
+ cluster,
clusterNodes,
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 34e31671491..5b1ee6cc496 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
@@ -48,8 +48,8 @@ public class ClusterModel {
private Double maxQueryGrowthRate = null;
public ClusterModel(Application application,
- Cluster cluster,
ClusterSpec clusterSpec,
+ Cluster cluster,
NodeList clusterNodes,
MetricsDb metricsDb,
Clock clock) {
@@ -169,7 +169,6 @@ public class ClusterModel {
// Assume we have missed timely recording completion if it is longer than 4 days
totalDuration = totalDuration.plus(maximum(Duration.ofDays(4), event.duration().get()));
}
-
if (completedEventCount == 0) { // Use defaults
if (clusterSpec.isStateful()) return Duration.ofHours(12);
return Duration.ofMinutes(10);
@@ -210,13 +209,13 @@ public class ClusterModel {
* as QuestDb is known to temporarily fail during reading of data.
*/
public static Optional<ClusterModel> create(Application application,
- Cluster cluster,
ClusterSpec clusterSpec,
+ Cluster cluster,
NodeList clusterNodes,
MetricsDb metricsDb,
Clock clock) {
try {
- return Optional.of(new ClusterModel(application, cluster, clusterSpec, clusterNodes, metricsDb, clock));
+ return Optional.of(new ClusterModel(application, clusterSpec, cluster, clusterNodes, metricsDb, clock));
}
catch (Exception e) {
log.log(Level.WARNING, "Failed creating a cluster model for " + application + " " + cluster, e);
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 64865c15529..4ffe04d748c 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
@@ -171,7 +171,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
firstDeployment // start at min, preserve current resources otherwise
? new AllocatableClusterResources(initialResourcesFrom(requested, clusterSpec, application.id()), clusterSpec, nodeRepository)
: new AllocatableClusterResources(nodes.asList(), nodeRepository);
- var clusterModel = new ClusterModel(application, cluster, clusterSpec, nodes, nodeRepository.metricsDb(), nodeRepository.clock());
+ var clusterModel = new ClusterModel(application, clusterSpec, cluster, nodes, nodeRepository.metricsDb(), nodeRepository.clock());
return within(Limits.of(requested), currentResources, firstDeployment, clusterModel);
}
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 f0b8e77ee56..1c10de8498a 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
@@ -62,7 +62,7 @@ public class ApplicationSerializer {
NodeList nodes = applicationNodes.not().retired().cluster(cluster.id());
if (nodes.isEmpty()) return;
ClusterResources currentResources = nodes.toResources();
- Optional<ClusterModel> clusterModel = ClusterModel.create(application, cluster, nodes.clusterSpec(), nodes, metricsDb, nodeRepository.clock());
+ Optional<ClusterModel> clusterModel = ClusterModel.create(application, nodes.clusterSpec(), cluster, nodes, metricsDb, nodeRepository.clock());
Cursor clusterObject = clustersObject.setObject(cluster.id().value());
clusterObject.setString("type", nodes.clusterSpec().type().name());
toSlime(cluster.minResources(), clusterObject.setObject("min"));
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 667dffef2a6..bb441c6621c 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
@@ -37,8 +37,8 @@ public class AutoscalingIntegrationTest {
new MockHttpClient(tester.clock()));
Autoscaler autoscaler = new Autoscaler(tester.nodeRepository());
- ApplicationId application1 = tester.applicationId("test1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "test");
+ ApplicationId application1 = AutoscalingTester.applicationId("test1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "test");
Set<String> hostnames = tester.deploy(application1, cluster1, 2, 1, nodes)
.stream().map(HostSpec::hostname)
.collect(Collectors.toSet());
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 d3142b3cc7f..273c909220b 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
@@ -44,8 +44,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
// deploy
tester.deploy(application1, cluster1, 5, 1, hostResources);
@@ -89,36 +89,30 @@ public class AutoscalingTest {
tester.autoscale(application1, cluster1, capacity));
}
+ /** Using too many resources for a short period is proof we should scale up regardless of the time that takes. */
+ @Test
+ public void test_autoscaling_up_is_fast_TODO() {
+ var fixture = AutoscalingTester.fixture().build();
+ fixture.tester().clock().advance(Duration.ofDays(1)); // TODO: Remove the need for this
+ fixture.applyLoad(1.0, 1.0, 1.0, 120); // TODO: Make this low
+ fixture.tester().assertResources("Scaling up since resource usage is too high",
+ 10, 1, 9.4, 8.5, 92.6,
+ fixture.autoscale());
+ }
+
/** We prefer fewer nodes for container clusters as (we assume) they all use the same disk and memory */
@Test
public void test_autoscaling_single_container_group() {
- 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));
- var capacity = Capacity.from(min, max);
- AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
-
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
-
- // deploy
- tester.deploy(application1, cluster1, 5, 1, resources);
- tester.addCpuMeasurements(0.25f, 1f, 120, application1);
- tester.clock().advance(Duration.ofMinutes(-10 * 5));
- tester.addQueryRateMeasurements(application1, cluster1.id(), 10, t -> t == 0 ? 20.0 : 10.0); // Query traffic only
- ClusterResources scaledResources = tester.assertResources("Scaling up since cpu usage is too high",
- 7, 1, 2.5, 80.0, 50.5,
- tester.autoscale(application1, cluster1, capacity));
-
- tester.deploy(application1, cluster1, scaledResources);
- tester.deactivateRetired(application1, cluster1, scaledResources);
-
- tester.addCpuMeasurements(0.1f, 1f, 120, application1);
- tester.clock().advance(Duration.ofMinutes(-10 * 5));
- tester.addQueryRateMeasurements(application1, cluster1.id(), 10, t -> t == 0 ? 20.0 : 10.0); // Query traffic only
- tester.assertResources("Scaling down since cpu usage has gone down",
- 4, 1, 2.5, 68.6, 27.4,
- tester.autoscale(application1, cluster1, capacity));
+ var fixture = AutoscalingTester.fixture().clusterType(ClusterSpec.Type.container).build();
+ fixture.applyCpuLoad(0.25f, 120);
+ ClusterResources scaledResources = fixture.tester().assertResources("Scaling up since cpu usage is too high",
+ 5, 1, 3.8, 8.0, 50.5,
+ fixture.autoscale());
+ fixture.deploy(scaledResources);
+ fixture.applyCpuLoad(0.1f, 120);
+ fixture.tester().assertResources("Scaling down since cpu usage has gone down",
+ 4, 1, 2.5, 6.4, 25.5,
+ fixture.autoscale());
}
@Test
@@ -126,8 +120,8 @@ public class AutoscalingTest {
NodeResources hostResources = new NodeResources(3, 100, 100, 1, NodeResources.DiskSpeed.slow);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
// deploy with slow
tester.deploy(application1, cluster1, 5, 1, hostResources);
@@ -158,8 +152,8 @@ public class AutoscalingTest {
NodeResources hostResources = new NodeResources(3, 100, 100, 1);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
// Initial deployment
NodeResources resources = new NodeResources(1, 10, 10, 1);
@@ -192,8 +186,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 5, 1,
@@ -214,8 +208,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 5, 1, resources);
@@ -233,8 +227,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
NodeResources defaultResources =
new CapacityPolicies(tester.nodeRepository()).defaultNodeResources(cluster1, application1, false);
@@ -261,8 +255,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 5, 5, new NodeResources(3.0, 10, 10, 1));
@@ -282,8 +276,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 5, 1, resources);
@@ -308,8 +302,8 @@ public class AutoscalingTest {
tester.provisioning().makeReadyNodes(5, remoteFlavor.name(), NodeType.host, 8);
tester.provisioning().activateTenantHosts();
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 3, 1, min.nodeResources());
@@ -331,8 +325,8 @@ public class AutoscalingTest {
ClusterResources max = min;
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 5, 1, resources);
@@ -352,8 +346,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 2, 1, resources);
@@ -370,8 +364,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 2, 1, resources);
@@ -388,8 +382,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 5, 5, resources);
@@ -409,8 +403,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 6, 2, resources);
@@ -433,8 +427,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
// deploy
tester.deploy(application1, cluster1, 6, 2, resources);
@@ -456,8 +450,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
// deploy
tester.deploy(application1, cluster1, 6, 2, new NodeResources(10, 100, 100, 1));
@@ -478,8 +472,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
// deploy
tester.deploy(application1, cluster1, 6, 1, hostResources.withVcpu(hostResources.vcpu() / 2));
@@ -499,8 +493,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(hostResources);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
tester.deploy(application1, cluster1, 6, 1, hostResources.withVcpu(hostResources.vcpu() / 2));
@@ -532,8 +526,8 @@ public class AutoscalingTest {
hostResources,
new OnlySubtractingWhenForecastingCalculator(0));
- ApplicationId application1 = tester.applicationId("app1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("app1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
tester.deploy(application1, cluster1, min);
tester.addMeasurements(1.0f, 1.0f, 0.7f, 0, 1000, application1);
@@ -549,8 +543,8 @@ public class AutoscalingTest {
hostResources,
new OnlySubtractingWhenForecastingCalculator(15));
- ApplicationId application1 = tester.applicationId("app1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("app1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
tester.deploy(application1, cluster1, min);
tester.addMeasurements(1.0f, 1.0f, 0.7f, 0, 1000, application1);
@@ -579,8 +573,8 @@ public class AutoscalingTest {
Environment.prod, RegionName.from("us-east")),
flavors);
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.content, "cluster1");
// deploy (Why 103 Gb memory? See AutoscalingTester.MockHostResourcesCalculator
tester.deploy(application1, cluster1, 5, 1, new NodeResources(3, 103, 100, 1));
@@ -611,8 +605,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
tester.deploy(application1, cluster1, 5, 1, resources);
tester.addQueryRateMeasurements(application1, cluster1.id(), 100, t -> t == 0 ? 20.0 : 10.0); // Query traffic only
@@ -645,8 +639,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(maxResources.withVcpu(maxResources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
tester.deploy(application1, cluster1, 5, 1, midResources);
Duration timeAdded = tester.addQueryRateMeasurements(application1, cluster1.id(), 100, t -> t == 0 ? 20.0 : 10.0);
@@ -691,8 +685,8 @@ public class AutoscalingTest {
var capacity = Capacity.from(min, max);
AutoscalingTester tester = new AutoscalingTester(maxResources.withVcpu(maxResources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
tester.deploy(application1, cluster1, 5, 1, midResources);
tester.addCpuMeasurements(0.4f, 1f, 120, application1);
@@ -744,8 +738,8 @@ public class AutoscalingTest {
Capacity capacity = Capacity.from(min, max, false, true);
AutoscalingTester tester = new AutoscalingTester(Environment.dev, resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
tester.deploy(application1, cluster1, capacity);
tester.addQueryRateMeasurements(application1, cluster1.id(),
@@ -764,8 +758,8 @@ public class AutoscalingTest {
Capacity capacity = Capacity.from(min, max, true, true);
AutoscalingTester tester = new AutoscalingTester(Environment.dev, resources.withVcpu(resources.vcpu() * 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
tester.deploy(application1, cluster1, capacity);
tester.addQueryRateMeasurements(application1, cluster1.id(),
@@ -785,8 +779,8 @@ public class AutoscalingTest {
AutoscalingTester tester = new AutoscalingTester(Environment.dev,
new NodeResources(10, 16, 100, 2));
- ApplicationId application1 = tester.applicationId("application1");
- ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1");
+ ApplicationId application1 = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1");
tester.deploy(application1, cluster1, capacity);
tester.addQueryRateMeasurements(application1, cluster1.id(),
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 f860b3e5d81..862eb744162 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
@@ -91,13 +91,15 @@ class AutoscalingTester {
capacityPolicies = new CapacityPolicies(provisioningTester.nodeRepository());
}
+ public static Fixture.Builder fixture() { return new Fixture.Builder(); }
+
public ProvisioningTester provisioning() { return provisioningTester; }
- public ApplicationId applicationId(String applicationName) {
+ public static ApplicationId applicationId(String applicationName) {
return ApplicationId.from("tenant1", applicationName, "instance1");
}
- public ClusterSpec clusterSpec(ClusterSpec.Type type, String clusterId) {
+ public static ClusterSpec clusterSpec(ClusterSpec.Type type, String clusterId) {
return ClusterSpec.request(type, ClusterSpec.Id.from(clusterId)).vespaVersion("7").build();
}
@@ -128,7 +130,7 @@ class AutoscalingTester {
}
public void deactivateRetired(ApplicationId application, ClusterSpec cluster, ClusterResources resources) {
- try (Mutex lock = nodeRepository().nodes().lock(application)){
+ try (Mutex lock = nodeRepository().nodes().lock(application)) {
for (Node node : nodeRepository().nodes().list(Node.State.active).owner(application)) {
if (node.allocation().get().membership().retired())
nodeRepository().nodes().write(node.with(node.allocation().get().removable(true, true)), lock);
@@ -137,6 +139,16 @@ class AutoscalingTester {
deploy(application, cluster, resources);
}
+ public ClusterModel clusterModel(ApplicationId applicationId, ClusterSpec clusterSpec) {
+ var application = nodeRepository().applications().get(applicationId).get();
+ return new ClusterModel(application,
+ clusterSpec,
+ application.cluster(clusterSpec.id()).get(),
+ nodeRepository().nodes().list(Node.State.active).cluster(clusterSpec.id()),
+ nodeRepository().metricsDb(),
+ nodeRepository().clock());
+ }
+
/**
* Adds measurements with the given resource value and ideal values for the other resources,
* scaled to take one node redundancy into account.
@@ -236,6 +248,10 @@ class AutoscalingTester {
}
}
+ public void addMeasurements(float cpu, float memory, float disk, int count, ApplicationId applicationId) {
+ addMeasurements(cpu, memory, disk, 0, true, true, count, applicationId);
+ }
+
public void addMeasurements(float cpu, float memory, float disk, int generation, int count, ApplicationId applicationId) {
addMeasurements(cpu, memory, disk, generation, true, true, count, applicationId);
}
@@ -304,13 +320,21 @@ class AutoscalingTester {
ClusterSpec.Id cluster,
int measurements,
IntFunction<Double> queryRate) {
+ return addQueryRateMeasurements(application, cluster, measurements, Duration.ofMinutes(5), queryRate);
+ }
+
+ public Duration addQueryRateMeasurements(ApplicationId application,
+ ClusterSpec.Id cluster,
+ int measurements,
+ Duration samplingInterval,
+ IntFunction<Double> queryRate) {
Instant initialTime = clock().instant();
for (int i = 0; i < measurements; i++) {
nodeMetricsDb().addClusterMetrics(application,
Map.of(cluster, new ClusterMetricSnapshot(clock().instant(),
queryRate.apply(i),
0.0)));
- clock().advance(Duration.ofMinutes(5));
+ clock().advance(samplingInterval);
}
return Duration.between(initialTime, clock().instant());
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java
new file mode 100644
index 00000000000..416f61d62d3
--- /dev/null
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java
@@ -0,0 +1,83 @@
+// Copyright Yahoo. 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.ApplicationId;
+import com.yahoo.config.provision.Capacity;
+import com.yahoo.config.provision.ClusterResources;
+import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.NodeResources;
+
+import java.time.Duration;
+
+/**
+ * Fixture for autoscaling tests.
+ *
+ * @author bratseth
+ */
+public class Fixture {
+
+ final AutoscalingTester tester;
+ final ApplicationId application;
+ final ClusterSpec cluster;
+ final Capacity capacity;
+
+ public Fixture(Fixture.Builder builder) {
+ application = builder.application;
+ cluster = builder.cluster;
+ capacity = Capacity.from(builder.min, builder.max);
+ tester = new AutoscalingTester(builder.hostResources);
+ tester.deploy(builder.application, builder.cluster, 5, 1, builder.nodeResources);
+ }
+
+ public AutoscalingTester tester() { return tester; }
+
+ public Autoscaler.Advice autoscale() {
+ return tester.autoscale(application, cluster, capacity);
+ }
+
+ public void deploy(ClusterResources resources) {
+ tester.deploy(application, cluster, resources);
+ }
+
+ public void deactivateRetired(ClusterResources resources) {
+ tester.deactivateRetired(application, cluster, resources);
+ }
+
+ public void applyLoad(double cpuLoad, double memoryLoad, double diskLoad, int measurements) {
+ Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements
+ tester().addMeasurements((float)cpuLoad, (float)memoryLoad, (float)diskLoad, measurements, application);
+ tester().clock().advance(samplingInterval.negated().multipliedBy(measurements));
+ tester().addQueryRateMeasurements(application, cluster.id(), measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only
+ }
+
+ public void applyCpuLoad(double cpuLoad, int measurements) {
+ Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements
+ tester().addCpuMeasurements((float)cpuLoad, 1.0f, measurements, application);
+ tester().clock().advance(samplingInterval.negated().multipliedBy(measurements));
+ tester().addQueryRateMeasurements(application, cluster.id(), measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only
+ }
+
+ public static class Builder {
+
+ NodeResources hostResources = new NodeResources(100, 100, 100, 1);
+ NodeResources nodeResources = new NodeResources(3, 10, 100, 1);
+ ClusterResources min = new ClusterResources(2, 1,
+ new NodeResources(1, 1, 1, 1, NodeResources.DiskSpeed.any));
+ ClusterResources max = new ClusterResources(20, 1,
+ new NodeResources(100, 1000, 1000, 1, NodeResources.DiskSpeed.any));
+
+ ApplicationId application = AutoscalingTester.applicationId("application1");
+ ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("cluster1")).vespaVersion("7").build();
+
+ public Fixture.Builder clusterType(ClusterSpec.Type type) {
+ cluster = ClusterSpec.request(type, cluster.id()).vespaVersion("7").build();
+ return this;
+ }
+
+ public Fixture build() {
+ return new Fixture(this);
+ }
+
+ }
+
+}