diff options
Diffstat (limited to 'node-repository/src/test/java')
11 files changed, 157 insertions, 118 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 64c5dff0718..bd31c7578b9 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 @@ -57,11 +57,15 @@ public class AutoscalingTest { @Test public void test_autoscaling_single_content_group() { - var fixture = DynamicProvisioningTester.fixture().awsProdSetup(true).build(); + var now = new ClusterResources(5, 1, new NodeResources(2, 16, 750, 1)); + var fixture = DynamicProvisioningTester.fixture() + .awsProdSetup(true) + .initialResources(Optional.of(now)) + .build(); fixture.loader().applyCpuLoad(0.7f, 10); var scaledResources = fixture.tester().assertResources("Scaling up since resource usage is too high", - 8, 1, 4.0, 9.3, 36.2, + 9, 1, 3.6, 8.5, 360.9, fixture.autoscale()); fixture.deploy(Capacity.from(scaledResources)); @@ -83,7 +87,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(7)); fixture.loader().applyCpuLoad(0.1f, 10); fixture.tester().assertResources("Scaling cpu down since usage has gone down significantly", - 7, 1, 1.1, 8.7, 25.4, + 8, 1, 1.0, 8.3, 338.4, fixture.autoscale()); } @@ -210,7 +214,7 @@ public class AutoscalingTest { fixture.loader().applyCpuLoad(0.70, 1); fixture.loader().applyCpuLoad(0.01, 100); fixture.tester().assertResources("Scaling up since peak resource usage is too high", - 9, 1, 4, 16.0, 25.5, + 9, 1, 4, 16.0, 150, fixture.autoscale()); } @@ -227,9 +231,9 @@ public class AutoscalingTest { @Test public void test_autoscaling_without_traffic_exclusive() { - var min = new ClusterResources(1, 1, new NodeResources(0.5, 4, 10, 0.3)); - var now = new ClusterResources(4, 1, new NodeResources(8, 16, 10, 0.3)); - var max = new ClusterResources(4, 1, new NodeResources(16, 32, 50, 0.3)); + var min = new ClusterResources(1, 1, new NodeResources(0.5, 4, 100, 0.3)); + var now = new ClusterResources(4, 1, new NodeResources(8, 16, 100, 0.3)); + var max = new ClusterResources(4, 1, new NodeResources(16, 32, 500, 0.3)); var fixture = DynamicProvisioningTester.fixture(min, now, max) .clusterType(ClusterSpec.Type.container) .awsProdSetup(false) @@ -238,7 +242,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(duration.negated()); fixture.loader().zeroTraffic(20, 1); fixture.tester().assertResources("Scaled down", - 2, 1, 2, 16, 10, + 2, 1, 2, 16, 100, fixture.autoscale()); } @@ -256,7 +260,7 @@ public class AutoscalingTest { fixture.completeLastScaling(); fixture.loader().applyCpuLoad(0.1f, 120); fixture.tester().assertResources("Scaling down since cpu usage has gone down", - 3, 1, 2, 16, 27.2, + 3, 1, 2, 16, 75.0, fixture.autoscale()); } @@ -283,7 +287,7 @@ public class AutoscalingTest { new NodeResources(100, 1000, 1000, 1, DiskSpeed.any)); var capacity = Capacity.from(min, max); ClusterResources scaledResources = fixture.tester().assertResources("Scaling up", - 13, 1, 1.5, 29.1, 26.7, + 13, 1, 1.5, 29.1, 87.3, fixture.autoscale(capacity)); assertEquals("Disk speed from new capacity is used", DiskSpeed.any, scaledResources.nodeResources().diskSpeed()); @@ -312,7 +316,6 @@ public class AutoscalingTest { fixture.deactivateRetired(capacity); fixture.tester().clock().advance(Duration.ofDays(1)); fixture.loader().applyCpuLoad(0.8, 120); - System.out.println("Autoscaling ----------"); assertEquals(DiskSpeed.any, fixture.autoscale(capacity).resources().get().nodeResources().diskSpeed()); } @@ -384,15 +387,15 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.4, 240); fixture.tester().assertResources("Scaling cpu up", - 6, 6, 5.0, 7.4, 10.0, + 6, 6, 5.0, 7.4, 22.3, fixture.autoscale()); } @Test public void autoscaling_respects_group_size_limit() { - var min = new ClusterResources( 2, 2, new NodeResources(1, 1, 1, 1)); - var now = new ClusterResources(5, 5, new NodeResources(3.0, 10, 10, 1)); - var max = new ClusterResources(18, 6, new NodeResources(100, 1000, 1000, 1)); + var min = new ClusterResources( 2, 2, new NodeResources(1, 1, 10, 1)); + var now = new ClusterResources(5, 5, new NodeResources(3.0, 10, 100, 1)); + var max = new ClusterResources(18, 6, new NodeResources(100, 1000, 10000, 1)); var fixture = DynamicProvisioningTester.fixture() .awsProdSetup(true) .initialResources(Optional.of(now)) @@ -401,7 +404,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.4, 240); fixture.tester().assertResources("Scaling cpu up", - 8, 4, 4.6, 4.2, 10.0, + 12, 6, 2.8, 4.2, 27.5, fixture.autoscale()); } @@ -457,7 +460,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(1.0, 120); fixture.tester().assertResources("Suggesting above capacity limit", - 13, 1, 4, 8, 13.6, + 13, 1, 4, 8, 100.0, fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); } @@ -480,9 +483,61 @@ public class AutoscalingTest { } @Test + public void too_small_disk_compared_to_memory() { + var resources = new ClusterResources(2, 1, new NodeResources(1, 10, 19, 1)); + var fixture = DynamicProvisioningTester.fixture() + .awsProdSetup(true) + .initialResources(Optional.of(resources)) + .build(); + assertEquals(2, fixture.tester().provisionLogger().applicationLog().size()); // tester deploys twice + assertEquals("WARNING: Requested disk (19.0Gb) in cluster 'cluster1' is not large enough to fit core/heap dumps. Minimum recommended disk resources is 2x memory for containers and 3x memory for content", + fixture.tester().provisionLogger().applicationLog().get(0)); + } + + @Test + public void autoscaling_shouldnt_choose_too_small_disk_compared_to_memory() { + var min = new ClusterResources(10, 1, new NodeResources(1, 10, 19, 1)); + var now = new ClusterResources(10, 1, new NodeResources(5, 50, 150, 1)); + var max = new ClusterResources(10, 1, new NodeResources(10, 100, 200, 1)); + var fixture = DynamicProvisioningTester.fixture() + .awsProdSetup(true) + .initialResources(Optional.of(now)) + .capacity(Capacity.from(min, max)) + .build(); + fixture.tester().clock().advance(Duration.ofDays(2)); + fixture.loader().applyLoad(new Load(0.5, 0.8, 0.1), 120); + fixture.tester().assertResources("Suggesting resources where disk is 3x memory (this is a content cluster)", + 11, 1, 13.0, 60.0, 179.9, + fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); + fixture.tester().assertResources("Autoscaling to resources where disk is 3x memory (this is a content cluster)", + 10, 1, 10.0, 66.2, 198.6, + fixture.tester().autoscale(fixture.applicationId, fixture.clusterSpec, Capacity.from(min, max))); + } + + @Test + public void autoscaling_shouldnt_choose_too_small_disk_compared_to_memory_exclusive() { + var min = new ClusterResources(10, 1, new NodeResources(1, 10, 19, 1, DiskSpeed.any, StorageType.remote)); + var now = new ClusterResources(10, 1, new NodeResources(16, 64, 192, 1, DiskSpeed.any, StorageType.remote)); + var max = new ClusterResources(10, 1, new NodeResources(30, 200, 500, 1, DiskSpeed.any, StorageType.remote)); + var fixture = DynamicProvisioningTester.fixture() + .awsProdSetup(false) + .initialResources(Optional.of(now)) + .capacity(Capacity.from(min, max)) + .build(); + fixture.tester().clock().advance(Duration.ofDays(2)); + fixture.loader().applyLoad(new Load(0.5, 0.8, 0.1), 120); + fixture.tester().assertResources("Suggesting resources where disk is 3x memory (this is a content cluster)", + 13, 1, 36.0, 72.0, 900.0, + fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); + fixture.tester().assertResources("Autoscaling to resources where disk is 3x memory (this is a content cluster)", + 10, 1, 16.0, 64, 247.5, + fixture.tester().autoscale(fixture.applicationId, fixture.clusterSpec, Capacity.from(min, max))); + } + + @Test public void test_autoscaling_group_size_unconstrained() { var min = new ClusterResources( 2, 2, new NodeResources(1, 1, 1, 1)); - var now = new ClusterResources(5, 5, new NodeResources(3, 100, 100, 1)); + var now = new ClusterResources(5, 5, new NodeResources(3, 100, 300, 1)); var max = new ClusterResources(20, 20, new NodeResources(10, 1000, 1000, 1)); var fixture = DynamicProvisioningTester.fixture() .awsProdSetup(true) @@ -492,7 +547,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.9, 120); fixture.tester().assertResources("Scaling up to 2 nodes, scaling memory and disk down at the same time", - 10, 5, 7.7, 41.5, 38.5, + 10, 5, 7.7, 41.5, 124.6, fixture.autoscale()); } @@ -509,7 +564,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.9, 120); fixture.tester().assertResources("Scaling up to 2 nodes, scaling memory and disk down at the same time", - 7, 7, 9.4, 78.6, 77.0, + 7, 7, 9.4, 78.6, 235.8, fixture.autoscale()); } @@ -528,7 +583,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(timePassed.negated()); fixture.loader().addLoadMeasurements(10, t -> t == 0 ? 200.0 : 100.0, t -> 10.0); fixture.tester().assertResources("Scaling up cpu, others down, changing to 1 group is cheaper", - 7, 1, 3.2, 43.3, 40.1, + 7, 1, 3.2, 43.3, 129.8, fixture.autoscale()); } @@ -548,7 +603,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(timePassed.negated()); fixture.loader().addLoadMeasurements(10, t -> t == 0 ? 20.0 : 10.0, t -> 100.0); fixture.tester().assertResources("Scaling down since resource usage is too high, changing to 1 group is cheaper", - 5, 1, 1.0, 62.6, 60.1, + 5, 1, 1.0, 62.6, 187.7, fixture.autoscale()); } @@ -565,7 +620,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(1)); fixture.loader().applyMemLoad(1.0, 1000); fixture.tester().assertResources("Increase group size to reduce memory load", - 8, 2, 13.9, 96.3, 60.1, + 8, 2, 13.9, 96.3, 288.8, fixture.autoscale()); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java index 4d2816cb14f..00ae9ac5a9d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java @@ -30,6 +30,7 @@ import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; import com.yahoo.vespa.hosted.provision.testutils.ServiceMonitorStub; import com.yahoo.vespa.service.duper.InfraApplication; import com.yahoo.vespa.service.duper.TenantHostApplication; +import com.yahoo.vespa.hosted.provision.testutils.InMemoryProvisionLogger; import java.time.Clock; import java.time.Duration; @@ -270,7 +271,7 @@ public class NodeFailTester { } public void activate(ApplicationId applicationId, ClusterSpec cluster, Capacity capacity) { - List<HostSpec> hosts = provisioner.prepare(applicationId, cluster, capacity, null); + List<HostSpec> hosts = provisioner.prepare(applicationId, cluster, capacity, new InMemoryProvisionLogger()); try (var lock = provisioner.lock(applicationId)) { NestedTransaction transaction = new NestedTransaction().add(new CuratorTransaction(curator)); provisioner.activate(hosts, new ActivationContext(0), new ApplicationTransaction(lock, transaction)); 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 1b677224295..8aaf0eb20e7 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 @@ -75,7 +75,7 @@ public class ScalingSuggestionsMaintainerTest { assertEquals("8 nodes with [vcpu: 3.2, memory: 4.5 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionOf(app1, cluster1, tester).resources().get().toString()); - assertEquals("8 nodes with [vcpu: 3.6, memory: 4.7 Gb, disk: 11.8 Gb, bandwidth: 0.1 Gbps, architecture: any]", + assertEquals("8 nodes with [vcpu: 3.6, memory: 4.7 Gb, disk: 14.2 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionOf(app2, cluster2, tester).resources().get().toString()); // Utilization goes way down diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java index 478b201d71b..7cf1b0d5177 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java @@ -94,7 +94,6 @@ public class DynamicAllocationTest { hostsWithChildren.add(node.parentHostname().get()); } assertEquals(4 - spareCount, hostsWithChildren.size()); - } /** @@ -342,8 +341,8 @@ public class DynamicAllocationTest { tester.activate(application, hosts); NodeList activeNodes = tester.nodeRepository().nodes().list().owner(application); - assertEquals(Set.of("127.0.127.2", "::2"), activeNodes.asList().get(0).ipConfig().primary()); - assertEquals(Set.of("127.0.127.13", "::d"), activeNodes.asList().get(1).ipConfig().primary()); + assertEquals(Set.of("127.0.127.2", "::2"), activeNodes.asList().get(1).ipConfig().primary()); + assertEquals(Set.of("127.0.127.13", "::d"), activeNodes.asList().get(0).ipConfig().primary()); } @Test diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java index e1e83ad2fb3..5539bb0cb6e 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java @@ -9,6 +9,7 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.HostSpec; +import com.yahoo.config.provision.NodeAllocationException; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeResources.Architecture; @@ -316,13 +317,6 @@ public class DynamicProvisioningTest { tester.assertNodes("Allocation specifies memory in the advertised amount", 2, 1, 2, 20, 40, app1, cluster1); - - // Redeploy the same - tester.activate(app1, cluster1, Capacity.from(resources(2, 1, 2, 20, 40), - resources(4, 1, 2, 20, 40))); - tester.assertNodes("Allocation specifies memory in the advertised amount", - 2, 1, 2, 20, 40, - app1, cluster1); } @Test @@ -340,7 +334,7 @@ public class DynamicProvisioningTest { .flagSource(flagSource) .build(); - ApplicationId app = ProvisioningTester.applicationId(); + ApplicationId app = ProvisioningTester.applicationId("a1"); ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("8").build(); Capacity capacity = Capacity.from(new ClusterResources(4, 2, new NodeResources(2, 4, 50, 0.1, DiskSpeed.any, StorageType.any, Architecture.any))); @@ -505,7 +499,7 @@ public class DynamicProvisioningTest { } @Test - public void gpu_host() { + public void gpu_host() { List<Flavor> flavors = List.of(new Flavor("gpu", new NodeResources(4, 16, 125, 10, fast, local, Architecture.x86_64, new NodeResources.GpuResources(1, 16)))); ProvisioningTester tester = new ProvisioningTester.Builder().dynamicProvisioning(true, false) diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java index b043a1cfb0f..4799d3b5577 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java @@ -24,12 +24,9 @@ import com.yahoo.vespa.hosted.provision.autoscale.Autoscaling; import com.yahoo.vespa.hosted.provision.autoscale.Fixture; import com.yahoo.vespa.hosted.provision.autoscale.MetricsDb; import com.yahoo.vespa.hosted.provision.node.IP; -import com.yahoo.vespa.hosted.provision.provisioning.CapacityPolicies; -import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; -import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester; +import com.yahoo.vespa.hosted.provision.testutils.InMemoryProvisionLogger; import java.time.Duration; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; @@ -38,13 +35,13 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** - * A provisioniong tester which + * A provisioning tester which * - Supports dynamic provisioning (only). * - Optionally replicates the actual AWS setup and logic used on Vespa Cloud. * - Supports autoscaling testing. * - * TODO: All provisioning testing should migrate to use this, and then the provisionging tester should be collapsed - * into this. + * TODO: All provisioning testing should migrate to use this, and then the provisioning tester should be collapsed + * into this. ... or we should just use autoscalingtester for everything. * * @author bratseth */ @@ -82,12 +79,7 @@ public class DynamicProvisioningTester { capacityPolicies = new CapacityPolicies(provisioningTester.nodeRepository()); } - private static List<Flavor> toFlavors(List<NodeResources> resources) { - List<Flavor> flavors = new ArrayList<>(); - for (int i = 0; i < resources.size(); i++) - flavors.add(new Flavor("flavor" + i, resources.get(i))); - return flavors; - } + public InMemoryProvisionLogger provisionLogger() { return provisioningTester.provisionLogger(); } public static Fixture.Builder fixture() { return new Fixture.Builder(); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InPlaceResizeProvisionTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InPlaceResizeProvisionTest.java index 0bb6dc61d1b..54f0507831d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InPlaceResizeProvisionTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InPlaceResizeProvisionTest.java @@ -57,7 +57,7 @@ public class InPlaceResizeProvisionTest { private final ProvisioningTester tester = new ProvisioningTester.Builder() .flagSource(flagSource) .zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - private final ApplicationId app = ProvisioningTester.applicationId(); + private final ApplicationId app = ProvisioningTester.applicationId("a1"); @Test public void single_group_same_cluster_size_resource_increase() { @@ -167,8 +167,6 @@ public class InPlaceResizeProvisionTest { assertEquals(0, listCluster(content1).retired().size()); } - - /** In this scenario there should be no resizing */ @Test public void increase_size_decrease_resources() { addParentHosts(14, largeResources.with(fast)); @@ -198,15 +196,15 @@ public class InPlaceResizeProvisionTest { assertSizeAndResources(listCluster(content1).retired(), 4, resources); assertSizeAndResources(listCluster(content1).not().retired(), 8, halvedResources); - // ... same with setting a node to want to retire - Node nodeToWantoToRetire = listCluster(content1).not().retired().asList().get(0); - try (NodeMutex lock = tester.nodeRepository().nodes().lockAndGetRequired(nodeToWantoToRetire)) { + // Here we'll unretire and resize one of the previously retired nodes as there is no rule against it + Node nodeToWantToRetire = listCluster(content1).not().retired().asList().get(0); + try (NodeMutex lock = tester.nodeRepository().nodes().lockAndGetRequired(nodeToWantToRetire)) { tester.nodeRepository().nodes().write(lock.node().withWantToRetire(true, Agent.system, tester.clock().instant()), lock); } new PrepareHelper(tester, app).prepare(content1, 8, 1, halvedResources).activate(); - assertTrue(listCluster(content1).retired().stream().anyMatch(n -> n.equals(nodeToWantoToRetire))); - assertEquals(5, listCluster(content1).retired().size()); + assertTrue(listCluster(content1).retired().stream().anyMatch(n -> n.equals(nodeToWantToRetire))); + assertEquals(4, listCluster(content1).retired().size()); assertSizeAndResources(listCluster(content1).not().retired(), 8, halvedResources); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java index 32db213c445..c82b29c7d65 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java @@ -24,17 +24,17 @@ public class NodeCandidateTest { @Test public void testOrdering() { List<NodeCandidate> expected = List.of( - new NodeCandidate.ConcreteNodeCandidate(node("01", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), false, true, true, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("02", Node.State.active), new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("04", Node.State.reserved), new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("03", Node.State.inactive), new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("05", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.active)), true, true, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("06", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.ready)), true, true, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("07", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.provisioned)), true, true, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("08", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.failed)), true, true, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("09", Node.State.ready), new NodeResources(1, 1, 1, 1), Optional.empty(), true, true, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("10", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("11", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, true, false) + new NodeCandidate.ConcreteNodeCandidate(node("01", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), false, true, true, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("02", Node.State.active), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("04", Node.State.reserved), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("03", Node.State.inactive), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("05", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.active)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("06", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.ready)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("07", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.provisioned)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("08", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.failed)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("09", Node.State.ready), false, new NodeResources(1, 1, 1, 1), Optional.empty(), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("10", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("11", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, true, false) ); assertOrder(expected); } @@ -148,7 +148,7 @@ public class NodeCandidateTest { Node parent = Node.create(hostname + "parent", hostname, new Flavor(totalHostResources), Node.State.ready, NodeType.host) .ipConfig(IP.Config.of(Set.of("::1"), Set.of("::2"))) .build(); - return new NodeCandidate.ConcreteNodeCandidate(node, totalHostResources.subtract(allocatedHostResources), Optional.of(parent), + return new NodeCandidate.ConcreteNodeCandidate(node, false, totalHostResources.subtract(allocatedHostResources), Optional.of(parent), false, exclusiveSwitch, false, true, false); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java index 477101e10e2..cb4644f179f 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java @@ -241,7 +241,7 @@ public class ProvisioningTest { public void application_deployment_variable_application_size() { ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - ApplicationId application1 = ProvisioningTester.applicationId(); + ApplicationId application1 = ProvisioningTester.applicationId("a1"); tester.makeReadyHosts(30, defaultResources); tester.activateTenantHosts(); @@ -498,7 +498,7 @@ public class ProvisioningTest { @Test public void test_changing_limits() { - Flavor hostFlavor = new Flavor(new NodeResources(20, 40, 100, 4)); + Flavor hostFlavor = new Flavor(new NodeResources(20, 40, 1000, 4)); ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))) .flavors(List.of(hostFlavor)) .build(); @@ -508,52 +508,52 @@ public class ProvisioningTest { ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build(); // Initial deployment - tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 2, 10, 20), - resources(8, 4, 4, 20, 40))); + tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 2, 10, 200), + resources(8, 4, 4, 20, 400))); tester.assertNodes("Initial allocation at min", - 4, 2, 2, 10, 20, + 4, 2, 2, 10, 200, app1, cluster1); // Move window above current allocation - tester.activate(app1, cluster1, Capacity.from(resources(8, 4, 4, 21, 40), - resources(10, 5, 5, 25, 50))); + tester.activate(app1, cluster1, Capacity.from(resources(8, 4, 4, 21, 400), + resources(10, 5, 5, 25, 500))); tester.assertNodes("New allocation at new min", - 8, 4, 4, 21, 40, + 8, 4, 4, 21, 400, app1, cluster1); // Move window below current allocation - tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 2, 10, 20), - resources(6, 3, 3, 15, 25))); + tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 2, 10, 200), + resources(6, 3, 3, 15, 250))); tester.assertNodes("Allocation preserving resources within new limits", - 6, 2, 3, 14.57, 25, + 6, 2, 3, 14.57, 250, app1, cluster1); // Widening window does not change allocation - tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 1, 5, 15), - resources(8, 4, 4, 21, 30))); + tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 1, 5, 150), + resources(8, 4, 4, 21, 300))); tester.assertNodes("Same allocation", - 6, 2, 3, 14.57, 25, + 6, 2, 3, 14.57, 250, app1, cluster1); // Changing limits in opposite directions cause a mixture of min and max - tester.activate(app1, cluster1, Capacity.from(resources(2, 1, 10, 30, 10), - resources(4, 2, 14, 40, 13))); + tester.activate(app1, cluster1, Capacity.from(resources(2, 1, 10, 30, 100), + resources(4, 2, 14, 40, 130))); tester.assertNodes("A mix of min and max", - 4, 1, 10, 30, 13, + 4, 1, 10, 30, 130, app1, cluster1); // Changing group size - tester.activate(app1, cluster1, Capacity.from(resources(6, 3, 8, 25, 10), - resources(9, 3, 12, 35, 15))); + tester.activate(app1, cluster1, Capacity.from(resources(6, 3, 8, 25, 100), + resources(9, 3, 12, 35, 150))); tester.assertNodes("Groups changed", - 9, 3, 8, 30, 13, + 9, 3, 8, 30, 130, app1, cluster1); // Stop specifying node resources tester.activate(app1, cluster1, Capacity.from(new ClusterResources(6, 3, NodeResources.unspecified()), new ClusterResources(9, 3, NodeResources.unspecified()))); tester.assertNodes("No change", - 9, 3, 8, 30, 13, + 9, 3, 8, 30, 130, app1, cluster1); } @@ -821,7 +821,7 @@ public class ProvisioningTest { public void highest_node_indexes_are_retired_first() { ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - ApplicationId application1 = ProvisioningTester.applicationId(); + ApplicationId application1 = ProvisioningTester.applicationId("a1"); tester.makeReadyHosts(14, defaultResources).activateTenantHosts(); @@ -833,17 +833,19 @@ public class ProvisioningTest { SystemState state2 = prepare(application1, 2, 2, 2, 2, defaultResources, tester); tester.activate(application1, state2.allHosts); - // content0 - assertFalse(state2.hostByMembership("content0", 0, 0).membership().get().retired()); - assertFalse(state2.hostByMembership("content0", 0, 1).membership().get().retired()); - assertTrue( state2.hostByMembership("content0", 0, 2).membership().get().retired()); - assertTrue( state2.hostByMembership("content0", 0, 3).membership().get().retired()); - - // content1 - assertFalse(state2.hostByMembership("content1", 0, 0).membership().get().retired()); - assertFalse(state2.hostByMembership("content1", 0, 1).membership().get().retired()); - assertTrue( state2.hostByMembership("content1", 0, 2).membership().get().retired()); - assertTrue( state2.hostByMembership("content1", 0, 3).membership().get().retired()); + List<Integer> unretiredInContent0Indices = state2.content0.stream().filter(h -> ! h.membership().get().retired()).map(h -> h.membership().get().index()).toList(); + for (var host : state2.content0) { + if ( ! host.membership().get().retired()) continue; + for (int unretiredIndex : unretiredInContent0Indices) + assertTrue(host.membership().get().index() > unretiredIndex); + } + + List<Integer> unretiredInContent1Indices = state2.content1.stream().filter(h -> ! h.membership().get().retired()).map(h -> h.membership().get().index()).toList(); + for (var host : state2.content1) { + if ( ! host.membership().get().retired()) continue; + for (int unretiredIndex : unretiredInContent1Indices) + assertTrue(host.membership().get().index() > unretiredIndex); + } } @Test @@ -857,7 +859,7 @@ public class ProvisioningTest { tester.deploy(application, spec, Capacity.from(new ClusterResources(6, 1, defaultResources))); - // Pick out a random application node and make it's parent larger, this will make it the spare host + // Pick out a random application node and make its parent larger, this will make it the spare host NodeList nodes = tester.nodeRepository().nodes().list(); Node randomNode = nodes.owner(application).shuffle(new Random()).first().get(); tester.nodeRepository().nodes().write(nodes.parentOf(randomNode).get() diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java index 7e85131eaf4..a3a90d58c2c 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java @@ -47,6 +47,7 @@ import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.IP; import com.yahoo.vespa.hosted.provision.node.filter.NodeHostFilter; import com.yahoo.vespa.hosted.provision.persistence.NameResolver; +import com.yahoo.vespa.hosted.provision.testutils.InMemoryProvisionLogger; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; import com.yahoo.vespa.hosted.provision.testutils.MockProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock; @@ -93,7 +94,7 @@ public class ProvisioningTester { private final HostProvisioner hostProvisioner; private final NodeRepositoryProvisioner provisioner; private final CapacityPolicies capacityPolicies; - private final ProvisionLogger provisionLogger; + private final InMemoryProvisionLogger provisionLogger; private final LoadBalancerServiceMock loadBalancerService; private int nextHost = 0; @@ -132,7 +133,7 @@ public class ProvisioningTester { 1000); this.provisioner = new NodeRepositoryProvisioner(nodeRepository, zone, provisionServiceProvider); this.capacityPolicies = new CapacityPolicies(nodeRepository); - this.provisionLogger = new NullProvisionLogger(); + this.provisionLogger = new InMemoryProvisionLogger(); this.loadBalancerService = loadBalancerService; } @@ -162,6 +163,7 @@ public class ProvisioningTester { public CapacityPolicies capacityPolicies() { return capacityPolicies; } public NodeList getNodes(ApplicationId id, Node.State ... inState) { return nodeRepository.nodes().list(inState).owner(id); } public InMemoryFlagSource flagSource() { return (InMemoryFlagSource) nodeRepository.flagSource(); } + public InMemoryProvisionLogger provisionLogger() { return provisionLogger; } public Node node(String hostname) { return nodeRepository.nodes().node(hostname).get(); } public int decideSize(Capacity capacity, ApplicationId application) { @@ -773,10 +775,6 @@ public class ProvisioningTester { } - private static class NullProvisionLogger implements ProvisionLogger { - @Override public void log(Level level, String message) { } - } - static class MockResourcesCalculator implements HostResourcesCalculator { private final int memoryTaxGb; diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java index 62f42b0d035..6ec189d98c3 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java @@ -23,6 +23,7 @@ import com.yahoo.config.provision.Zone; import com.yahoo.transaction.NestedTransaction; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; +import com.yahoo.yolean.Exceptions; import org.junit.Test; import java.util.HashSet; @@ -442,9 +443,8 @@ public class VirtualNodeProvisioningTest { "Could not satisfy request for 3 nodes with " + "[vcpu: 2.0, memory: 4.0 Gb, disk: 100.0 Gb, bandwidth: 1.0 Gbps, architecture: any] " + "in tenant2.app2 container cluster 'my-container' 6.39: " + - "Node allocation failure on group 0: " + "Not enough suitable nodes available due to host exclusivity constraints", - e.getMessage()); + Exceptions.toMessageString(e)); } // Adding 3 nodes of another application for the same tenant works @@ -469,8 +469,8 @@ public class VirtualNodeProvisioningTest { assertEquals("Could not satisfy request for 2 nodes with " + "[vcpu: 1.0, memory: 4.0 Gb, disk: 100.0 Gb, bandwidth: 1.0 Gbps, storage type: remote, architecture: any] " + "in tenant.app1 content cluster 'my-content'" + - " 6.42: Node allocation failure on group 0", - e.getMessage()); + " 6.42", + Exceptions.toMessageString(e)); } } @@ -513,18 +513,18 @@ public class VirtualNodeProvisioningTest { 2, 1, 20, 16, 50, 1.0, app1, cluster1); - var newMinResources = new NodeResources( 5, 6, 11, 1); - var newMaxResources = new NodeResources(20, 10, 30, 1); + var newMinResources = new NodeResources( 5, 6, 18, 1); + var newMaxResources = new NodeResources(20, 10, 90, 1); tester.activate(app1, cluster1, Capacity.from(new ClusterResources(7, 1, newMinResources), new ClusterResources(7, 1, newMaxResources))); tester.assertNodes("New allocation preserves total (redundancy adjusted) resources", - 7, 1, 5, 6.0, 11, 1.0, + 7, 1, 5, 6.0, 18, 1.0, app1, cluster1); tester.activate(app1, cluster1, Capacity.from(new ClusterResources(7, 1, newMinResources), new ClusterResources(7, 1, newMaxResources))); tester.assertNodes("Redeploying does not cause changes", - 7, 1, 5, 6.0, 11, 1.0, + 7, 1, 5, 6.0, 18, 1.0, app1, cluster1); } |