From ed2da152e1af877c2665f77df1674bfcaa47dde5 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Mon, 1 Aug 2022 12:16:41 +0200 Subject: Use fixture and add test --- .../provision/autoscale/AutoscalingTest.java | 68 +++++++++++++--------- .../provision/autoscale/AutoscalingTester.java | 20 +++++-- .../vespa/hosted/provision/autoscale/Fixture.java | 31 +++++++--- 3 files changed, 80 insertions(+), 39 deletions(-) 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 a2eb5fba9f9..d247a9a0801 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 @@ -229,37 +229,53 @@ public class AutoscalingTest { } @Test - public void prefers_remote_disk_when_no_local_match() { - NodeResources resources = new NodeResources(3, 100, 50, 1); - ClusterResources min = new ClusterResources( 2, 1, resources); - ClusterResources max = min; - // AutoscalingTester hardcodes 3Gb memory overhead: - Flavor localFlavor = new Flavor("local", new NodeResources(3, 97, 75, 1, DiskSpeed.fast, StorageType.local)); - Flavor remoteFlavor = new Flavor("remote", new NodeResources(3, 97, 50, 1, DiskSpeed.fast, StorageType.remote)); - - var tester = new AutoscalingTester(new Zone(new Cloud.Builder().dynamicProvisioning(true).build(), - SystemName.defaultSystem(), Environment.prod, RegionName.defaultName()), - List.of(localFlavor, remoteFlavor)); - tester.provisioning().makeReadyNodes(5, localFlavor.name(), NodeType.host, 8); - tester.provisioning().makeReadyNodes(5, remoteFlavor.name(), NodeType.host, 8); - tester.provisioning().activateTenantHosts(); - - ApplicationId application1 = AutoscalingTester.applicationId("application1"); - ClusterSpec cluster1 = AutoscalingTester.clusterSpec(ClusterSpec.Type.container, "cluster1"); + public void container_prefers_remote_disk_when_no_local_match() { + var resources = new ClusterResources( 2, 1, new NodeResources(3, 100, 50, 1)); + var local = new NodeResources(3, 100, 75, 1, DiskSpeed.fast, StorageType.local); + var remote = new NodeResources(3, 100, 50, 1, DiskSpeed.fast, StorageType.remote); + var fixture = AutoscalingTester.fixture() + .zone(new Zone(new Cloud.Builder().dynamicProvisioning(true).build(), + SystemName.defaultSystem(), Environment.prod, RegionName.defaultName())) + .clusterType(ClusterSpec.Type.container) + .hostResources(local, remote) + .capacity(Capacity.from(resources)) + .initialResources(Optional.of(new ClusterResources(3, 1, resources.nodeResources()))) + .build(); - // deploy - tester.deploy(application1, cluster1, 3, 1, min.nodeResources()); - Duration timeAdded = tester.addDiskMeasurements(0.01f, 1f, 120, application1); - tester.clock().advance(timeAdded.negated()); - tester.addQueryRateMeasurements(application1, cluster1.id(), 10, t -> 10.0); // Query traffic only - Autoscaler.Advice suggestion = tester.suggest(application1, cluster1.id(), min, max); - tester.assertResources("Choosing the remote disk flavor as it has less disk", - 6, 1, 3.0, 100.0, 10.0, - suggestion); + fixture.tester().clock().advance(Duration.ofDays(2)); + fixture.applyLoad(0.01, 0.01, 0.01, 120); + Autoscaler.Advice suggestion = fixture.suggest(); + fixture.tester().assertResources("Choosing the remote disk flavor as it has less disk", + 2, 1, 3.0, 100.0, 10.0, + suggestion); assertEquals("Choosing the remote disk flavor as it has less disk", StorageType.remote, suggestion.target().get().nodeResources().storageType()); } + @Test + public void content_prefers_local_disk_when_no_local_match() { + var resources = new ClusterResources( 2, 1, new NodeResources(3, 100, 50, 1)); + var local = new NodeResources(3, 100, 75, 1, DiskSpeed.fast, StorageType.local); + var remote = new NodeResources(3, 100, 50, 1, DiskSpeed.fast, StorageType.remote); + var fixture = AutoscalingTester.fixture() + .zone(new Zone(new Cloud.Builder().dynamicProvisioning(true).build(), + SystemName.defaultSystem(), Environment.prod, RegionName.defaultName())) + .clusterType(ClusterSpec.Type.content) + .hostResources(local, remote) + .capacity(Capacity.from(resources)) + .initialResources(Optional.of(new ClusterResources(3, 1, resources.nodeResources()))) + .build(); + + fixture.tester().clock().advance(Duration.ofDays(2)); + fixture.applyLoad(0.01, 0.01, 0.01, 120); + Autoscaler.Advice suggestion = fixture.suggest(); + fixture.tester().assertResources("Always prefers local disk for content", + 2, 1, 3.0, 100.0, 75.0, + suggestion); + assertEquals("Always prefers local disk for content", + StorageType.local, suggestion.target().get().nodeResources().storageType()); + } + @Test public void suggestions_ignores_limits() { ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1)); 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 2a4dbe32ab5..daab3b1d469 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 @@ -30,10 +30,12 @@ import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester; import java.time.Duration; import java.time.Instant; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.IntFunction; +import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -54,16 +56,17 @@ class AutoscalingTester { } public AutoscalingTester(Environment environment, NodeResources hostResources) { - this(new Zone(environment, RegionName.from("us-east")), hostResources, null); + this(new Zone(environment, RegionName.from("us-east")), null, List.of(hostResources)); } - public AutoscalingTester(Zone zone, NodeResources hostResources, HostResourcesCalculator resourcesCalculator) { + public AutoscalingTester(Zone zone, HostResourcesCalculator resourcesCalculator, List hostResources) { this(zone, hostResources, resourcesCalculator, 20); } - private AutoscalingTester(Zone zone, NodeResources hostResources, HostResourcesCalculator resourcesCalculator, int hostCount) { - this(zone, List.of(new Flavor("hostFlavor", hostResources)), resourcesCalculator); - provisioningTester.makeReadyNodes(hostCount, "hostFlavor", NodeType.host, 8); + private AutoscalingTester(Zone zone, List hostResources, HostResourcesCalculator resourcesCalculator, int hostCount) { + this(zone, toFlavors(hostResources), resourcesCalculator); + for (Flavor flavor : toFlavors(hostResources)) + provisioningTester.makeReadyNodes(hostCount, flavor.name(), NodeType.host, 8); provisioningTester.activateTenantHosts(); } @@ -83,6 +86,13 @@ class AutoscalingTester { capacityPolicies = new CapacityPolicies(provisioningTester.nodeRepository()); } + private static List toFlavors(List resources) { + List flavors = new ArrayList<>(); + for (int i = 0; i < resources.size(); i++) + flavors.add(new Flavor("flavor" + i, resources.get(i))); + return flavors; + } + public static Fixture.Builder fixture() { return new Fixture.Builder(); } public ProvisioningTester provisioning() { return provisioningTester; } 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 index 896897f45c1..109f25ec0e1 100644 --- 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 @@ -13,8 +13,11 @@ import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; import java.time.Duration; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import java.util.function.IntFunction; +import java.util.stream.Collectors; /** * Fixture for autoscaling tests. @@ -32,7 +35,7 @@ public class Fixture { application = builder.application; cluster = builder.cluster; capacity = builder.capacity; - tester = new AutoscalingTester(builder.zone, builder.hostResources, builder.resourceCalculator); + tester = new AutoscalingTester(builder.zone, builder.resourceCalculator, builder.hostResources); var deployCapacity = initialResources.isPresent() ? Capacity.from(initialResources.get()) : capacity; tester.deploy(builder.application, builder.cluster, deployCapacity); } @@ -49,6 +52,11 @@ public class Fixture { return tester().autoscale(application, cluster, capacity); } + /** Compute an autoscaling suggestion for this. */ + public Autoscaler.Advice suggest() { + return tester().suggest(application, cluster.id(), capacity.minResources(), capacity.maxResources()); + } + /** Redeploy with the deployed capacity of this. */ public void deploy() { deploy(capacity); @@ -88,12 +96,19 @@ public class Fixture { } public void applyMemLoad(double memLoad, int measurements) { - Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements + Duration samplingInterval = Duration.ofSeconds(150L); // in addMemMeasurements tester().addMemMeasurements((float)memLoad, 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 void applyDiskLoad(double diskLoad, int measurements) { + Duration samplingInterval = Duration.ofSeconds(150L); // in addDiskMeasurements + tester().addDiskMeasurements((float)diskLoad, 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 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); @@ -114,15 +129,15 @@ public class Fixture { public static class Builder { - NodeResources hostResources = new NodeResources(100, 100, 100, 1); + ApplicationId application = AutoscalingTester.applicationId("application1"); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("cluster1")).vespaVersion("7").build(); + Zone zone = new Zone(Environment.prod, RegionName.from("us-east")); + List hostResources = List.of(new NodeResources(100, 100, 100, 1)); Optional initialResources = Optional.of(new ClusterResources(5, 1, new NodeResources(3, 10, 100, 1))); Capacity capacity = Capacity.from(new ClusterResources(2, 1, new NodeResources(1, 1, 1, 1, NodeResources.DiskSpeed.any)), 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(); - Zone zone = new Zone(Environment.prod, RegionName.from("us-east")); HostResourcesCalculator resourceCalculator = new AutoscalingTester.MockHostResourcesCalculator(zone, 0); public Fixture.Builder zone(Zone zone) { @@ -135,8 +150,8 @@ public class Fixture { return this; } - public Fixture.Builder hostResources(NodeResources hostResources) { - this.hostResources = hostResources; + public Fixture.Builder hostResources(NodeResources ... hostResources) { + this.hostResources = Arrays.stream(hostResources).collect(Collectors.toList()); return this; } -- cgit v1.2.3