diff options
Diffstat (limited to 'node-repository/src/test/java/com/yahoo')
22 files changed, 308 insertions, 120 deletions
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java index ddbbb8e4482..88804576310 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java @@ -10,6 +10,7 @@ import com.yahoo.config.provisioning.FlavorsConfig; import com.yahoo.test.ManualClock; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.hosted.provision.node.Agent; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; @@ -33,7 +34,11 @@ public class NodeRepositoryTester { clock = new ManualClock(); curator = new MockCurator(); curator.setZooKeeperEnsembleConnectionSpec("server1:1234,server2:5678"); - nodeRepository = new NodeRepository(nodeFlavors, curator, clock, Zone.defaultZone(), + nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + Zone.defaultZone(), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); 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 b4f6adc2d26..032375943c8 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 @@ -35,7 +35,7 @@ public class AutoscalingIntegrationTest { NodeMetricsFetcher fetcher = new NodeMetricsFetcher(tester.nodeRepository(), new OrchestratorMock(), new MockHttpClient(tester.clock())); - Autoscaler autoscaler = new Autoscaler(new MockHostResourcesCalculator(), tester.nodeMetricsDb(), tester.nodeRepository()); + Autoscaler autoscaler = new Autoscaler(tester.nodeMetricsDb(), tester.nodeRepository()); ApplicationId application1 = tester.applicationId("test1"); ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "test"); @@ -123,14 +123,4 @@ public class AutoscalingIntegrationTest { } - private static class MockHostResourcesCalculator implements HostResourcesCalculator { - - @Override - public NodeResources realResourcesOf(Node node) { return node.flavor().resources(); } - - @Override - public NodeResources advertisedResourcesOf(Flavor flavor) { return flavor.resources(); } - - } - } 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 f98d55511ec..39a848a17f5 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java @@ -269,9 +269,9 @@ public class AutoscalingTest { // deploy tester.deploy(application1, cluster1, 6, 1, resources); - tester.addMeasurements(Resource.memory, 0.02f, 1f, 120, application1); + tester.addMeasurements(Resource.memory, 0.02f, 0.95f, 120, application1); tester.assertResources("Scaling down", - 6, 1, 3.0, 4.0, 100.0, + 6, 1, 2.8, 4.0, 95.0, tester.autoscale(application1, cluster1.id(), min, max)); } @@ -291,7 +291,7 @@ public class AutoscalingTest { ApplicationId application1 = tester.applicationId("application1"); ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1"); - // deploy (Why 83 Gb memory? See AutoscalingTester.MockHostResourcesCalculator + // deploy (Why 103 Gb memory? See AutoscalingTester.MockHostResourcesCalculator tester.deploy(application1, cluster1, 5, 1, new NodeResources(3, 103, 100, 1)); tester.addMeasurements(Resource.memory, 0.9f, 0.6f, 120, application1); 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 49bb51c1d79..a5b60ae6e16 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 @@ -47,28 +47,28 @@ class AutoscalingTester { /** Creates an autoscaling tester with a single host type ready */ public AutoscalingTester(NodeResources hostResources) { - this(new Zone(Environment.prod, RegionName.from("us-east")), null, null, asConfig(hostResources)); - provisioningTester.makeReadyNodes(20, "hostFlavor", NodeType.host, 8); // "hostFlavor" generated by asConfig + this(new Zone(Environment.prod, RegionName.from("us-east")), List.of(new Flavor("hostFlavor", hostResources)), null); + provisioningTester.makeReadyNodes(20, "hostFlavor", NodeType.host, 8); provisioningTester.deployZoneApp(); } public AutoscalingTester(Zone zone, List<Flavor> flavors) { this(zone, flavors, - new InMemoryFlagSource().withBooleanFlag(Flags.ENABLE_DYNAMIC_PROVISIONING.id(), true), - asConfig(flavors)); + new InMemoryFlagSource().withBooleanFlag(Flags.ENABLE_DYNAMIC_PROVISIONING.id(), true)); } - private AutoscalingTester(Zone zone, List<Flavor> flavors, FlagSource flagSource, FlavorsConfig flavorsConfig) { + private AutoscalingTester(Zone zone, List<Flavor> flavors, FlagSource flagSource) { provisioningTester = new ProvisioningTester.Builder().zone(zone) - .flavorsConfig(flavorsConfig) + .flavors(flavors) + .resourcesCalculator(new MockHostResourcesCalculator(zone)) .hostProvisioner(new MockHostProvisioner(flavors)) .flagSource(flagSource) .build(); hostResourcesCalculator = new MockHostResourcesCalculator(zone); db = new NodeMetricsDb(); - autoscaler = new Autoscaler(hostResourcesCalculator, db, nodeRepository()); + autoscaler = new Autoscaler(db, nodeRepository()); } public ApplicationId applicationId(String applicationName) { @@ -196,31 +196,6 @@ class AutoscalingTester { public NodeMetricsDb nodeMetricsDb() { return db; } - private static FlavorsConfig asConfig(NodeResources hostResources) { - FlavorsConfig.Builder b = new FlavorsConfig.Builder(); - b.flavor(asFlavorConfig("hostFlavor", hostResources)); - return b.build(); - } - - private static FlavorsConfig asConfig(List<Flavor> flavors) { - FlavorsConfig.Builder b = new FlavorsConfig.Builder(); - for (Flavor flavor : flavors) - b.flavor(asFlavorConfig(flavor.name(), flavor.resources())); - return b.build(); - } - - private static FlavorsConfig.Flavor.Builder asFlavorConfig(String flavorName, NodeResources resources) { - FlavorsConfig.Flavor.Builder flavor = new FlavorsConfig.Flavor.Builder(); - flavor.name(flavorName); - flavor.minCpuCores(resources.vcpu()); - flavor.minMainMemoryAvailableGb(resources.memoryGb()); - flavor.minDiskAvailableGb(resources.diskGb()); - flavor.bandwidth(resources.bandwidthGbps() * 1000); - flavor.fastDisk(resources.diskSpeed().compatibleWith(NodeResources.DiskSpeed.fast)); - flavor.remoteStorage(resources.storageType().compatibleWith(NodeResources.StorageType.remote)); - return flavor; - } - private static class MockHostResourcesCalculator implements HostResourcesCalculator { private final Zone zone; @@ -230,7 +205,7 @@ class AutoscalingTester { } @Override - public NodeResources realResourcesOf(Node node) { + public NodeResources realResourcesOf(Node node, NodeRepository nodeRepository) { if (zone.cloud().value().equals("aws")) return node.flavor().resources().withMemoryGb(node.flavor().resources().memoryGb() - 3); else diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerServiceTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerServiceTest.java index 402eaf37529..e70fc184b87 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerServiceTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerServiceTest.java @@ -21,7 +21,7 @@ public class PassthroughLoadBalancerServiceTest { var real = new Real(HostName.from("host1.example.com"), "192.0.2.10"); var reals = Set.of(real, new Real(HostName.from("host2.example.com"), "192.0.2.11")); var instance = lbService.create(ApplicationId.from("tenant1", "app1", "default"), - ClusterSpec.Id.from("c1"), reals, false); + ClusterSpec.Id.from("c1"), reals, false, null); assertEquals(real.hostname(), instance.hostname()); assertEquals(Set.of(real.port()), instance.ports()); assertEquals(Set.of(real.ipAddress() + "/32"), instance.networks()); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java index 1829a93c34f..64d189b9111 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; public class SharedLoadBalancerServiceTest { private final ProvisioningTester tester = new ProvisioningTester.Builder().build(); - private final SharedLoadBalancerService loadBalancerService = new SharedLoadBalancerService(tester.nodeRepository()); + private final SharedLoadBalancerService loadBalancerService = new SharedLoadBalancerService(); private final ApplicationId applicationId = ApplicationId.from("tenant1", "application1", "default"); private final ClusterSpec.Id clusterId = ClusterSpec.Id.from("qrs1"); private final Set<Real> reals = Set.of( @@ -30,7 +30,7 @@ public class SharedLoadBalancerServiceTest { @Test public void test_create_lb() { tester.makeReadyNodes(2, "default", NodeType.proxy); - var lb = loadBalancerService.create(applicationId, clusterId, reals, false); + var lb = loadBalancerService.create(applicationId, clusterId, reals, false, tester.nodeRepository()); assertEquals(HostName.from("host-1.yahoo.com"), lb.hostname()); assertEquals(Optional.empty(), lb.dnsZone()); @@ -40,7 +40,7 @@ public class SharedLoadBalancerServiceTest { @Test(expected = IllegalStateException.class) public void test_exception_on_missing_proxies() { - loadBalancerService.create(applicationId, clusterId, reals, false); + loadBalancerService.create(applicationId, clusterId, reals, false, tester.nodeRepository()); } @Test diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java index 8f8f8d0f38b..4dab064ce1e 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java @@ -56,7 +56,6 @@ public class AutoscalingMaintainerTest { NodeMetricsDb nodeMetricsDb = new NodeMetricsDb(); AutoscalingMaintainer maintainer = new AutoscalingMaintainer(tester.nodeRepository(), - tester.identityHostResourcesCalculator(), nodeMetricsDb, deployer, new TestMetric(), diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java index 0bc4d2c65a1..b1f6eaea502 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java @@ -26,6 +26,7 @@ import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.IP; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; @@ -54,8 +55,14 @@ public class CapacityCheckerTester { CapacityCheckerTester() { Curator curator = new MockCurator(); NodeFlavors f = new NodeFlavors(new FlavorConfigBuilder().build()); - nodeRepository = new NodeRepository(f, curator, clock, zone, new MockNameResolver().mockAnyLookup(), - DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); + nodeRepository = new NodeRepository(f, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + zone, + new MockNameResolver().mockAnyLookup(), + DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), + true); } private void updateCapacityChecker() { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java index ebec07fe5dc..6fca4b98409 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java @@ -27,6 +27,7 @@ import com.yahoo.vespa.hosted.provision.node.History; import com.yahoo.vespa.hosted.provision.node.IP; import com.yahoo.vespa.hosted.provision.node.Reports; import com.yahoo.vespa.hosted.provision.node.Status; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FatalProvisioningException; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.HostProvisioner; @@ -70,12 +71,15 @@ public class DynamicProvisioningMaintainerTest { private final HostProvisionerTester tester = new HostProvisionerTester(); private final HostProvisioner hostProvisioner = mock(HostProvisioner.class); - private final HostResourcesCalculator hostResourcesCalculator = mock(HostResourcesCalculator.class); + private static final HostResourcesCalculator hostResourcesCalculator = mock(HostResourcesCalculator.class); private final InMemoryFlagSource flagSource = new InMemoryFlagSource() .withBooleanFlag(Flags.ENABLE_DYNAMIC_PROVISIONING.id(), true) .withListFlag(Flags.PREPROVISION_CAPACITY.id(), List.of(), PreprovisionCapacity.class); - private final DynamicProvisioningMaintainer maintainer = new DynamicProvisioningMaintainer( - tester.nodeRepository, Duration.ofDays(1), hostProvisioner, hostResourcesCalculator, flagSource); + private final DynamicProvisioningMaintainer maintainer = + new DynamicProvisioningMaintainer(tester.nodeRepository, + Duration.ofDays(1), + hostProvisioner, + flagSource); @Test public void delegates_to_host_provisioner_and_writes_back_result() { @@ -212,8 +216,12 @@ public class DynamicProvisioningMaintainerTest { private final ManualClock clock = new ManualClock(); private final Zone zone = new Zone(CloudName.from("aws"), SystemName.defaultSystem(), Environment.defaultEnvironment(), RegionName.defaultName()); - private final NodeRepository nodeRepository = new NodeRepository( - nodeFlavors, new MockCurator(), clock, zone, new MockNameResolver().mockAnyLookup(), + private final NodeRepository nodeRepository = new NodeRepository(nodeFlavors, + hostResourcesCalculator, + new MockCurator(), + clock, + zone, + new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-image"), true); Node addNode(String hostname, Optional<String> parentHostname, NodeType nodeType, Node.State state, Optional<ApplicationId> application) { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java index 17521261e1b..575d84c0129 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java @@ -28,6 +28,7 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.Report; import com.yahoo.vespa.hosted.provision.node.Reports; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; @@ -250,7 +251,11 @@ public class FailedExpirerTest { public FailureScenario(SystemName system, Environment environment) { Zone zone = new Zone(system, environment, RegionName.defaultName()); - this.nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, + this.nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + zone, new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-image"), true); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java index 664809dc3ab..11df6146b06 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java @@ -15,6 +15,7 @@ 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.node.Agent; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; @@ -36,7 +37,11 @@ public class MaintenanceTester { public final ManualClock clock = new ManualClock(Instant.ofEpochMilli(0L)); // determinism private final Zone zone = new Zone(Environment.prod, RegionName.from("us-east")); private final NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default"); - public final NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, + public final NodeRepository nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + zone, new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java index 665dd74176d..6dfb404d81a 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java @@ -23,6 +23,7 @@ import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.Allocation; import com.yahoo.vespa.hosted.provision.node.Generation; import com.yahoo.vespa.hosted.provision.node.IP; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; import com.yahoo.vespa.orchestrator.Orchestrator; @@ -76,7 +77,11 @@ public class MetricsReporterTest { public void test_registered_metric() { NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default"); Curator curator = new MockCurator(); - NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, Clock.systemUTC(), Zone.defaultZone(), + NodeRepository nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + Clock.systemUTC(), + Zone.defaultZone(), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); @@ -138,7 +143,11 @@ public class MetricsReporterTest { public void docker_metrics() { NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("host", "docker", "docker2"); Curator curator = new MockCurator(); - NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, Clock.systemUTC(), Zone.defaultZone(), + NodeRepository nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + Clock.systemUTC(), + Zone.defaultZone(), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); 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 ab97de80418..e33cc9e655e 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 @@ -24,6 +24,7 @@ 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.node.Agent; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; @@ -74,8 +75,14 @@ public class NodeFailTester { private NodeFailTester() { clock = new ManualClock(); curator = new MockCurator(); - nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, new MockNameResolver().mockAnyLookup(), - DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); + nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + zone, + new MockNameResolver().mockAnyLookup(), + DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), + true); provisioner = new NodeRepositoryProvisioner(nodeRepository, zone, new MockProvisionServiceProvider(), new InMemoryFlagSource()); hostLivenessTracker = new TestHostLivenessTracker(clock); orchestrator = new OrchestratorMock(); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java index eb2a1d4db68..e57d57d4c4c 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java @@ -23,6 +23,7 @@ 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.node.Agent; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; @@ -53,7 +54,11 @@ public class OperatorChangeApplicationMaintainerTest { ManualClock clock = new ManualClock(); Curator curator = new MockCurator(); Zone zone = new Zone(Environment.prod, RegionName.from("us-east")); - this.nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, + this.nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + zone, new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java index 91e4899e079..8a2a69bb437 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java @@ -25,6 +25,7 @@ import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.node.Agent; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; @@ -59,7 +60,11 @@ public class PeriodicApplicationMaintainerTest { Curator curator = new MockCurator(); Zone zone = new Zone(Environment.prod, RegionName.from("us-east")); this.clock = new ManualClock(); - this.nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, + this.nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + zone, new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java index d25ae234f35..e6609caa4bc 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java @@ -54,7 +54,6 @@ public class RebalancerTest { Rebalancer rebalancer = new Rebalancer(deployer, tester.nodeRepository(), - tester.identityHostResourcesCalculator(), Optional.empty(), metric, tester.clock(), diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java index 0fd967cad1b..59514cb3c95 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java @@ -18,6 +18,7 @@ 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.node.Agent; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; @@ -44,7 +45,11 @@ public class ReservationExpirerTest { public void ensure_reservation_times_out() { ManualClock clock = new ManualClock(); NodeFlavors flavors = FlavorConfigBuilder.createDummies("default"); - NodeRepository nodeRepository = new NodeRepository(flavors, curator, clock, Zone.defaultZone(), + NodeRepository nodeRepository = new NodeRepository(flavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + Zone.defaultZone(), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java index 7ece8cba65e..e57bae09280 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java @@ -27,6 +27,7 @@ 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.node.Agent; +import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; @@ -63,9 +64,14 @@ public class RetiredExpirerTest { private final ManualClock clock = new ManualClock(); private final Zone zone = new Zone(Environment.prod, RegionName.from("us-east")); private final NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default"); - private final NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, + private final NodeRepository nodeRepository = new NodeRepository(nodeFlavors, + new EmptyProvisionServiceProvider().getHostResourcesCalculator(), + curator, + clock, + zone, new MockNameResolver().mockAnyLookup(), - DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); + DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), + true); private final NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, zone, new MockProvisionServiceProvider(), new InMemoryFlagSource()); private final Orchestrator orchestrator = mock(Orchestrator.class); 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 40892d80759..59da88790d7 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 @@ -67,14 +67,13 @@ public class ScalingSuggestionsMaintainerTest { addMeasurements(Resource.disk, 0.99f, 500, app2, tester.nodeRepository(), nodeMetricsDb); ScalingSuggestionsMaintainer maintainer = new ScalingSuggestionsMaintainer(tester.nodeRepository(), - tester.identityHostResourcesCalculator(), nodeMetricsDb, Duration.ofMinutes(1)); maintainer.maintain(); - assertEquals("7 nodes with [vcpu: 15.3, memory: 5.1 Gb, disk 15.0 Gb, bandwidth: 0.1 Gbps]", + assertEquals("7 nodes with [vcpu: 15.3, memory: 5.1 Gb, disk 15.0 Gb, bandwidth: 0.1 Gbps, storage type: remote]", tester.nodeRepository().applications().get(app1).get().cluster(cluster1.id()).get().suggestedResources().get().toString()); - assertEquals("7 nodes with [vcpu: 16.8, memory: 5.7 Gb, disk 16.5 Gb, bandwidth: 0.1 Gbps]", + assertEquals("7 nodes with [vcpu: 16.8, memory: 5.7 Gb, disk 16.5 Gb, bandwidth: 0.1 Gbps, storage type: remote]", tester.nodeRepository().applications().get(app2).get().cluster(cluster2.id()).get().suggestedResources().get().toString()); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java index 8f207ff9531..c6e50555d81 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java @@ -2,6 +2,9 @@ package com.yahoo.vespa.hosted.provision.provisioning; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Capacity; +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; @@ -9,10 +12,12 @@ import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; 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.node.Agent; import com.yahoo.vespa.hosted.provision.node.IP; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; @@ -27,6 +32,7 @@ import java.util.stream.IntStream; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -51,7 +57,7 @@ public class DynamicDockerProvisionTest { ApplicationId application1 = tester.makeApplicationId(); NodeResources flavor = new NodeResources(1, 4, 10, 1); - mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small")); + mockHostProvisioner(hostProvisioner, tester.nodeRepository().flavors().getFlavorOrThrow("small")); List<HostSpec> hostSpec = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 4, 1, flavor); verify(hostProvisioner).provisionHosts(List.of(100, 101, 102, 103), flavor, application1); @@ -60,7 +66,7 @@ public class DynamicDockerProvisionTest { assertEquals(4, tester.nodeRepository().getNodes(NodeType.host, Node.State.provisioned).size()); assertEquals(4, tester.nodeRepository().getNodes(NodeType.tenant, Node.State.reserved).size()); assertEquals(List.of("host-100-1", "host-101-1", "host-102-1", "host-103-1"), - hostSpec.stream().map(HostSpec::hostname).collect(Collectors.toList())); + hostSpec.stream().map(HostSpec::hostname).collect(Collectors.toList())); } @Test @@ -71,7 +77,7 @@ public class DynamicDockerProvisionTest { ApplicationId application = tester.makeApplicationId(); NodeResources flavor = new NodeResources(1, 4, 10, 1); - mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small")); + mockHostProvisioner(hostProvisioner, tester.nodeRepository().flavors().getFlavorOrThrow("small")); tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor); verify(hostProvisioner).provisionHosts(List.of(100, 101), flavor, application); } @@ -82,7 +88,7 @@ public class DynamicDockerProvisionTest { NodeResources flavor = new NodeResources(1, 4, 10, 1); List<Integer> expectedProvisionIndexes = List.of(100, 101); - mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("large")); + mockHostProvisioner(hostProvisioner, tester.nodeRepository().flavors().getFlavorOrThrow("large")); tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor); verify(hostProvisioner).provisionHosts(expectedProvisionIndexes, flavor, application); @@ -96,7 +102,7 @@ public class DynamicDockerProvisionTest { } tester.deployZoneApp(); - mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small")); + mockHostProvisioner(hostProvisioner, tester.nodeRepository().flavors().getFlavorOrThrow("small")); tester.prepare(application, clusterSpec("another-id"), 2, 1, flavor); // Verify there was only 1 call to provision hosts (during the first prepare) verify(hostProvisioner).provisionHosts(any(), any(), any()); @@ -142,10 +148,92 @@ public class DynamicDockerProvisionTest { assertTrue(indices.containsAll(IntStream.range(0, 10).boxed().collect(Collectors.toList()))); } + @Test + public void test_changing_limits_on_aws() { + List<Flavor> flavors = List.of(new Flavor("1x", new NodeResources(1, 10, 100, 0.1)), + new Flavor("2x", new NodeResources(2, 20, 200, 0.1)), + new Flavor("4x", new NodeResources(4, 40, 400, 0.1))); + + mockHostProvisioner(hostProvisioner, flavors.get(0)); + ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(CloudName.from("aws"), + SystemName.main, + Environment.prod, + RegionName.from("us-east"))) + .flavors(flavors) + .hostProvisioner(hostProvisioner) + .flagSource(flagSource) + .nameResolver(nameResolver) + .resourcesCalculator(new MockResourcesCalculator()) + .build(); + + tester.deployZoneApp(); + + ApplicationId app1 = tester.makeApplicationId("app1"); + ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build(); + + // Limits where each number are within flavor limits but but which don't contain any flavor leads to an error + try { + tester.activate(app1, cluster1, Capacity.from(resources(8, 4, 3.8, 20, 40), + resources(10, 5, 5, 25, 50))); + fail("Expected exception"); + } + catch (IllegalArgumentException e) { + // success + } + + // Initial deployment + tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 0.5, 5, 20), + resources(6, 3, 4, 20, 40))); + tester.assertNodes("Initial allocation at first actual flavor above min (except for disk)", + 4, 2, 1, 10, 20, + app1, cluster1); + + + // Move window above current allocation + tester.activate(app1, cluster1, Capacity.from(resources(8, 4, 3.8, 20, 40), + resources(10, 5, 5, 45, 50))); + tester.assertNodes("New allocation at new smallest flavor above limits", + 8, 4, 4, 40, 40, + app1, cluster1); + + // Move window below current allocation + System.out.println("--------- Moving window down"); + tester.activate(app1, cluster1, Capacity.from(resources(4, 2, 2, 10, 20), + resources(6, 3, 3, 25, 25))); + tester.assertNodes("New allocation at new max", + 6, 3, 2, 20, 25, + app1, cluster1); + + // Widening window lets us find a cheaper alternative + tester.activate(app1, cluster1, Capacity.from(resources(2, 1, 1, 5, 15), + resources(8, 4, 4, 20, 30))); + tester.assertNodes("Cheaper allocation", + 8, 4, 1, 10, 25, + app1, cluster1); + + // Changing group size + tester.activate(app1, cluster1, Capacity.from(resources(6, 3, 0.5, 5, 5), + resources(9, 3, 5, 20, 15))); + tester.assertNodes("Groups changed", + 6, 3, 1, 10, 15, + 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("Minimal allocation", + 6, 3, 1, 10, 15, + app1, cluster1); + } + private static ClusterSpec clusterSpec(String clusterId) { return ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from(clusterId)).vespaVersion("6.42").build(); } + private ClusterResources resources(int nodes, int groups, double vcpu, double memory, double disk) { + return new ClusterResources(nodes, groups, new NodeResources(vcpu, memory, disk, 0.1)); + } + @SuppressWarnings("unchecked") private static void mockHostProvisioner(HostProvisioner hostProvisioner, Flavor hostFlavor) { doAnswer(invocation -> { @@ -157,4 +245,20 @@ public class DynamicDockerProvisionTest { }).when(hostProvisioner).provisionHosts(any(), any(), any()); } + private static class MockResourcesCalculator implements HostResourcesCalculator { + + @Override + public NodeResources realResourcesOf(Node node, NodeRepository nodeRepository) { + if (node.type() == NodeType.host) return node.flavor().resources(); + return node.flavor().resources().withMemoryGb(node.flavor().resources().memoryGb() - 3); + } + + @Override + public NodeResources advertisedResourcesOf(Flavor flavor) { + if (flavor.isConfigured()) return flavor.resources(); + return flavor.resources().withMemoryGb(flavor.resources().memoryGb() + 3); + } + + } + } 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 463a3ef3fb9..c9eb6466cd7 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 @@ -9,6 +9,7 @@ import com.yahoo.config.provision.ClusterResources; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.Environment; +import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.HostFilter; import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeResources; @@ -408,8 +409,11 @@ public class ProvisioningTest { @Test public void test_changing_limits() { - ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - tester.makeReadyHosts(30, new NodeResources(20, 40, 100, 4)).deployZoneApp(); + Flavor hostFlavor = new Flavor(new NodeResources(20, 40, 100, 4)); + ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))) + .flavors(List.of(hostFlavor)) + .build(); + tester.makeReadyHosts(30, hostFlavor.resources()).deployZoneApp(); ApplicationId app1 = tester.makeApplicationId("app1"); ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build(); @@ -453,7 +457,14 @@ public class ProvisioningTest { tester.activate(app1, cluster1, Capacity.from(resources(6, 3, 8, 25, 5), resources(9, 3, 12, 35, 15))); tester.assertNodes("Groups changed", - 6, 3, 10, 30, 10, + 6, 3, 8, 30, 10, + 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", + 6, 3, 8, 30, 10, app1, cluster1); } 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 cbb15311867..33f30a8ecd5 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 @@ -80,15 +80,26 @@ public class ProvisioningTester { private int nextHost = 0; private int nextIP = 0; - public ProvisioningTester( - Curator curator, NodeFlavors nodeFlavors, Zone zone, NameResolver nameResolver, - Orchestrator orchestrator, HostProvisioner hostProvisioner, - LoadBalancerServiceMock loadBalancerService, FlagSource flagSource) { + public ProvisioningTester(Curator curator, + NodeFlavors nodeFlavors, + HostResourcesCalculator resourcesCalculator, + Zone zone, + NameResolver nameResolver, + Orchestrator orchestrator, + HostProvisioner hostProvisioner, + LoadBalancerServiceMock loadBalancerService, + FlagSource flagSource) { this.curator = curator; this.nodeFlavors = nodeFlavors; this.clock = new ManualClock(); - this.nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, nameResolver, - DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true); + this.nodeRepository = new NodeRepository(nodeFlavors, + resourcesCalculator, + curator, + clock, + zone, + nameResolver, + DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), + true); this.orchestrator = orchestrator; ProvisionServiceProvider provisionServiceProvider = new MockProvisionServiceProvider(loadBalancerService, hostProvisioner); this.provisioner = new NodeRepositoryProvisioner(nodeRepository, zone, provisionServiceProvider, flagSource); @@ -150,7 +161,26 @@ public class ProvisioningTester { } public Collection<HostSpec> activate(ApplicationId application, ClusterSpec cluster, Capacity capacity) { - return activate(application, prepare(application, cluster, capacity, true)); + List<HostSpec> preparedNodes = prepare(application, cluster, capacity, true); + + // Add ip addresses and activate parent host if necessary + for (HostSpec prepared : preparedNodes) { + Node node = nodeRepository.getNode(prepared.hostname()).get(); + if (node.ipConfig().primary().isEmpty()) { + node = node.with(new IP.Config(Set.of("::" + 0 + ":0"), Set.of())); + nodeRepository.write(node, nodeRepository.lock(node)); + } + if (node.parentHostname().isEmpty()) continue; + Node parent = nodeRepository.getNode(node.parentHostname().get()).get(); + if (parent.state() == Node.State.active) continue; + NestedTransaction t = new NestedTransaction(); + if (parent.ipConfig().primary().isEmpty()) + parent = parent.with(new IP.Config(Set.of("::" + 0 + ":0"), Set.of("::" + 0 + ":2"))); + nodeRepository.activate(List.of(parent), t); + t.commit(); + } + + return activate(application, preparedNodes); } public Collection<HostSpec> activate(ApplicationId application, Collection<HostSpec> hosts) { @@ -211,10 +241,11 @@ public class ProvisioningTester { assertEquals(explanation + ": Group count", groups, nodeList.stream().map(n -> n.allocation().get().membership().cluster().group().get()).distinct().count()); - for (Node node : nodeList) - assertEquals(explanation + ": Resources", - new NodeResources(vcpu, memory, disk, 0.1), - node.flavor().resources()); + for (Node node : nodeList) { + var expected = new NodeResources(vcpu, memory, disk, 0.1); + assertTrue(explanation + ": Resources: Expected " + expected + " but was " + node.flavor().resources(), + expected.compatibleWith(node.flavor().resources())); + } } public void fail(HostSpec host) { @@ -480,6 +511,7 @@ public class ProvisioningTester { private Curator curator; private FlavorsConfig flavorsConfig; + private HostResourcesCalculator resourcesCalculator = new EmptyProvisionServiceProvider().getHostResourcesCalculator(); private Zone zone; private NameResolver nameResolver; private Orchestrator orchestrator; @@ -497,6 +529,16 @@ public class ProvisioningTester { return this; } + public Builder flavors(List<Flavor> flavors) { + this.flavorsConfig = asConfig(flavors); + return this; + } + + public Builder resourcesCalculator(HostResourcesCalculator resourcesCalculator) { + this.resourcesCalculator = resourcesCalculator; + return this; + } + public Builder zone(Zone zone) { this.zone = zone; return this; @@ -539,38 +581,40 @@ public class ProvisioningTester { return orch; }); - return new ProvisioningTester( - Optional.ofNullable(curator).orElseGet(MockCurator::new), - new NodeFlavors(Optional.ofNullable(flavorsConfig).orElseGet(ProvisioningTester::createConfig)), - Optional.ofNullable(zone).orElseGet(Zone::defaultZone), - Optional.ofNullable(nameResolver).orElseGet(() -> new MockNameResolver().mockAnyLookup()), - orchestrator, - hostProvisioner, - Optional.ofNullable(loadBalancerService).orElseGet(LoadBalancerServiceMock::new), - Optional.ofNullable(flagSource).orElseGet(InMemoryFlagSource::new)); + return new ProvisioningTester(Optional.ofNullable(curator).orElseGet(MockCurator::new), + new NodeFlavors(Optional.ofNullable(flavorsConfig).orElseGet(ProvisioningTester::createConfig)), + resourcesCalculator, + Optional.ofNullable(zone).orElseGet(Zone::defaultZone), + Optional.ofNullable(nameResolver).orElseGet(() -> new MockNameResolver().mockAnyLookup()), + orchestrator, + hostProvisioner, + Optional.ofNullable(loadBalancerService).orElseGet(LoadBalancerServiceMock::new), + Optional.ofNullable(flagSource).orElseGet(InMemoryFlagSource::new)); } - } - private static class NullProvisionLogger implements ProvisionLogger { - @Override public void log(Level level, String message) { } - } - - public IdentityHostResourcesCalculator identityHostResourcesCalculator() { - return new IdentityHostResourcesCalculator(); - } - - private static class IdentityHostResourcesCalculator implements HostResourcesCalculator { - - @Override - public NodeResources realResourcesOf(Node node) { - return node.flavor().resources(); + private static FlavorsConfig asConfig(List<Flavor> flavors) { + FlavorsConfig.Builder b = new FlavorsConfig.Builder(); + for (Flavor flavor : flavors) + b.flavor(asFlavorConfig(flavor.name(), flavor.resources())); + return b.build(); } - @Override - public NodeResources advertisedResourcesOf(Flavor flavor) { - return flavor.resources(); + private static FlavorsConfig.Flavor.Builder asFlavorConfig(String flavorName, NodeResources resources) { + FlavorsConfig.Flavor.Builder flavor = new FlavorsConfig.Flavor.Builder(); + flavor.name(flavorName); + flavor.minCpuCores(resources.vcpu()); + flavor.minMainMemoryAvailableGb(resources.memoryGb()); + flavor.minDiskAvailableGb(resources.diskGb()); + flavor.bandwidth(resources.bandwidthGbps() * 1000); + flavor.fastDisk(resources.diskSpeed().compatibleWith(NodeResources.DiskSpeed.fast)); + flavor.remoteStorage(resources.storageType().compatibleWith(NodeResources.StorageType.remote)); + return flavor; } } + private static class NullProvisionLogger implements ProvisionLogger { + @Override public void log(Level level, String message) { } + } + } |