From 4a974c3b9908c2a5e1c59b006d429e01d9837d05 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Tue, 22 Nov 2022 12:19:34 +0100 Subject: Revert "Merge pull request #24936 from vespa-engine/bratseth/exclusive-cleanup" This reverts commit b693d572df945b9e82798e0c40b8b7b565f6a4a8, reversing changes made to c2682820ae2567ae5479d89992439699a66962c0. --- .../com/yahoo/config/provision/ClusterSpec.java | 4 --- .../vespa/hosted/provision/NodeRepository.java | 9 +---- .../autoscale/AllocatableClusterResources.java | 8 ++--- .../vespa/hosted/provision/autoscale/Limits.java | 2 +- .../provision/provisioning/CapacityPolicies.java | 29 ++++++++++------ .../provisioning/NodeRepositoryProvisioner.java | 21 ++++++------ .../provision/provisioning/NodeResourceLimits.java | 40 +++++++++++----------- .../provision/autoscale/AutoscalingTest.java | 2 +- .../provision/autoscale/AutoscalingTester.java | 2 +- 9 files changed, 57 insertions(+), 60 deletions(-) diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java index 2dba42ce0d6..dd07b29c2de 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java @@ -84,10 +84,6 @@ public final class ClusterSpec { return new ClusterSpec(type, id, newGroup, vespaVersion, exclusive, combinedId, dockerImageRepo, stateful); } - public ClusterSpec withExclusivity(boolean exclusive) { - return new ClusterSpec(type, id, groupId, vespaVersion, exclusive, combinedId, dockerImageRepo, stateful); - } - public ClusterSpec exclusive(boolean exclusive) { return new ClusterSpec(type, id, groupId, vespaVersion, exclusive, combinedId, dockerImageRepo, stateful); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java index fb21b009a30..0bf32e534b7 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java @@ -7,15 +7,11 @@ import com.yahoo.concurrent.maintenance.JobControl; import com.yahoo.config.provision.ApplicationTransaction; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.DockerImage; -import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.Zone; import com.yahoo.config.provisioning.NodeRepositoryConfig; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.flags.FlagSource; -import com.yahoo.vespa.flags.JacksonFlag; -import com.yahoo.vespa.flags.PermanentFlags; -import com.yahoo.vespa.flags.custom.SharedHost; import com.yahoo.vespa.hosted.provision.Node.State; import com.yahoo.vespa.hosted.provision.applications.Applications; import com.yahoo.vespa.hosted.provision.autoscale.MetricsDb; @@ -66,7 +62,6 @@ public class NodeRepository extends AbstractComponent { private final MetricsDb metricsDb; private final Orchestrator orchestrator; private final int spareCount; - private final JacksonFlag sharedHosts; /** * Creates a node repository from a zookeeper provider. @@ -139,7 +134,6 @@ public class NodeRepository extends AbstractComponent { this.metricsDb = metricsDb; this.orchestrator = orchestrator; this.spareCount = spareCount; - this.sharedHosts = PermanentFlags.SHARED_HOST.bindTo(flagSource()); nodes.rewrite(); } @@ -203,8 +197,7 @@ public class NodeRepository extends AbstractComponent { * perfectly. */ public boolean exclusiveAllocation(ClusterSpec clusterSpec) { - return clusterSpec.isExclusive() || - ( !zone().cloud().allowHostSharing() && !sharedHosts.value().isEnabled(clusterSpec.type().name())); + return clusterSpec.isExclusive() || ! zone().cloud().allowHostSharing(); } /** diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java index 3d76c8e3f94..389be5b6652 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java @@ -164,10 +164,10 @@ public class AllocatableClusterResources { if (! exclusive) { // We decide resources: Add overhead to what we'll request (advertised) to make sure real becomes (at least) cappedNodeResources var advertisedResources = nodeRepository.resourcesCalculator().realToRequest(wantedResources.nodeResources(), exclusive); - advertisedResources = systemLimits.enlargeToLegal(advertisedResources, clusterSpec, exclusive); // Ask for something legal + advertisedResources = systemLimits.enlargeToLegal(advertisedResources, clusterSpec.type(), exclusive); // Ask for something legal advertisedResources = applicationLimits.cap(advertisedResources); // Overrides other conditions, even if it will then fail var realResources = nodeRepository.resourcesCalculator().requestToReal(advertisedResources, exclusive); // What we'll really get - if ( ! systemLimits.isWithinRealLimits(realResources, clusterSpec)) + if ( ! systemLimits.isWithinRealLimits(realResources, clusterSpec.type())) return Optional.empty(); if (anySatisfies(realResources, availableRealHostResources)) return Optional.of(new AllocatableClusterResources(wantedResources.with(realResources), @@ -187,7 +187,7 @@ public class AllocatableClusterResources { // Adjust where we don't need exact match to the flavor if (flavor.resources().storageType() == NodeResources.StorageType.remote) { - double diskGb = systemLimits.enlargeToLegal(cappedWantedResources, clusterSpec, exclusive).diskGb(); + double diskGb = systemLimits.enlargeToLegal(cappedWantedResources, clusterSpec.type(), exclusive).diskGb(); advertisedResources = advertisedResources.withDiskGb(diskGb); realResources = realResources.withDiskGb(diskGb); } @@ -197,7 +197,7 @@ public class AllocatableClusterResources { } if ( ! between(applicationLimits.min().nodeResources(), applicationLimits.max().nodeResources(), advertisedResources)) continue; - if ( ! systemLimits.isWithinRealLimits(realResources, clusterSpec)) continue; + if ( ! systemLimits.isWithinRealLimits(realResources, clusterSpec.type())) continue; var candidate = new AllocatableClusterResources(wantedResources.with(realResources), advertisedResources, wantedResources, diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java index cb5d8dd5042..36b32f0b099 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java @@ -63,7 +63,7 @@ public class Limits { public Limits fullySpecified(ClusterSpec clusterSpec, NodeRepository nodeRepository, ApplicationId applicationId) { if (this.isEmpty()) throw new IllegalStateException("Unspecified limits can not be made fully specified"); - var defaultResources = new CapacityPolicies(nodeRepository).defaultNodeResources(clusterSpec, applicationId); + var defaultResources = new CapacityPolicies(nodeRepository).defaultNodeResources(clusterSpec, applicationId, clusterSpec.isExclusive()); var specifiedMin = min.nodeResources().isUnspecified() ? min.with(defaultResources) : min; var specifiedMax = max.nodeResources().isUnspecified() ? max.with(defaultResources) : max; return new Limits(specifiedMin, specifiedMax); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java index a1400626658..8d6c6b4bb62 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java @@ -10,8 +10,10 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.flags.JacksonFlag; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.flags.StringFlag; +import com.yahoo.vespa.flags.custom.SharedHost; import com.yahoo.vespa.hosted.provision.NodeRepository; import java.util.Map; import java.util.TreeMap; @@ -28,13 +30,13 @@ import static java.util.Objects.requireNonNull; */ public class CapacityPolicies { - private final NodeRepository nodeRepository; private final Zone zone; + private final JacksonFlag sharedHosts; private final StringFlag adminClusterNodeArchitecture; public CapacityPolicies(NodeRepository nodeRepository) { - this.nodeRepository = nodeRepository; this.zone = nodeRepository.zone(); + this.sharedHosts = PermanentFlags.SHARED_HOST.bindTo(nodeRepository.flagSource()); this.adminClusterNodeArchitecture = PermanentFlags.ADMIN_CLUSTER_NODE_ARCHITECTURE.bindTo(nodeRepository.flagSource()); } @@ -77,15 +79,16 @@ public class CapacityPolicies { return target; } - public NodeResources defaultNodeResources(ClusterSpec clusterSpec, ApplicationId applicationId) { + public NodeResources defaultNodeResources(ClusterSpec clusterSpec, ApplicationId applicationId, boolean exclusive) { if (clusterSpec.type() == ClusterSpec.Type.admin) { Architecture architecture = adminClusterArchitecture(applicationId); if (clusterSpec.id().value().equals("cluster-controllers")) { - return clusterControllerResources(clusterSpec).with(architecture); + return clusterControllerResources(clusterSpec, exclusive) + .with(architecture); } - return (nodeRepository.exclusiveAllocation(clusterSpec) + return (requiresExclusiveHost(clusterSpec.type(), exclusive) ? versioned(clusterSpec, Map.of(new Version(0), smallestExclusiveResources())) : versioned(clusterSpec, Map.of(new Version(0), smallestSharedResources()))) .with(architecture); @@ -104,8 +107,8 @@ public class CapacityPolicies { } } - private NodeResources clusterControllerResources(ClusterSpec clusterSpec) { - if (nodeRepository.exclusiveAllocation(clusterSpec)) { + private NodeResources clusterControllerResources(ClusterSpec clusterSpec, boolean exclusive) { + if (requiresExclusiveHost(clusterSpec.type(), exclusive)) { return versioned(clusterSpec, Map.of(new Version(0), smallestExclusiveResources())); } return versioned(clusterSpec, Map.of(new Version(0), new NodeResources(0.25, 1.14, 10, 0.3))); @@ -115,6 +118,11 @@ public class CapacityPolicies { return Architecture.valueOf(adminClusterNodeArchitecture.with(APPLICATION_ID, instance.serializedForm()).value()); } + /** Returns whether an exclusive host is required for given cluster type and exclusivity requirement */ + private boolean requiresExclusiveHost(ClusterSpec.Type type, boolean exclusive) { + return ! zone.cloud().allowHostSharing() && (exclusive || !sharedHosts.value().isEnabled(type.name())); + } + /** Returns the resources for the newest version not newer than that requested in the cluster spec. */ static NodeResources versioned(ClusterSpec spec, Map resources) { return requireNonNull(new TreeMap<>(resources).floorEntry(spec.vespaVersion()), @@ -137,10 +145,9 @@ public class CapacityPolicies { } /** Returns whether the nodes requested can share physical host with other applications */ - public ClusterSpec decideExclusivity(Capacity capacity, ClusterSpec requestedCluster) { - if (capacity.cloudAccount().isPresent()) return requestedCluster.withExclusivity(true); // Implicit exclusive - boolean exclusive = requestedCluster.isExclusive() && (capacity.isRequired() || zone.environment() == Environment.prod); - return requestedCluster.withExclusivity(exclusive); + public boolean decideExclusivity(Capacity capacity, boolean requestedExclusivity) { + if (capacity.cloudAccount().isPresent()) return true; // Implicit exclusive when using custom cloud account + return requestedExclusivity && (capacity.isRequired() || zone.environment() == Environment.prod); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index c425c235d11..a2b479a6070 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -95,29 +95,28 @@ public class NodeRepositoryProvisioner implements Provisioner { NodeResources resources; NodeSpec nodeSpec; if (requested.type() == NodeType.tenant) { - cluster = capacityPolicies.decideExclusivity(requested, cluster); - Capacity actual = capacityPolicies.applyOn(requested, application, cluster.isExclusive()); + boolean exclusive = capacityPolicies.decideExclusivity(requested, cluster.isExclusive()); + Capacity actual = capacityPolicies.applyOn(requested, application, exclusive); ClusterResources target = decideTargetResources(application, cluster, actual); ensureRedundancy(target.nodes(), cluster, actual.canFail(), application); logIfDownscaled(requested.minResources().nodes(), actual.minResources().nodes(), cluster, logger); groups = target.groups(); - resources = getNodeResources(cluster, target.nodeResources(), application); - nodeSpec = NodeSpec.from(target.nodes(), resources, cluster.isExclusive(), actual.canFail(), + resources = getNodeResources(cluster, target.nodeResources(), application, exclusive); + nodeSpec = NodeSpec.from(target.nodes(), resources, exclusive, actual.canFail(), requested.cloudAccount().orElse(nodeRepository.zone().cloud().account())); } else { groups = 1; // type request with multiple groups is not supported - cluster = cluster.withExclusivity(true); - resources = getNodeResources(cluster, requested.minResources().nodeResources(), application); + resources = getNodeResources(cluster, requested.minResources().nodeResources(), application, true); nodeSpec = NodeSpec.from(requested.type(), nodeRepository.zone().cloud().account()); } return asSortedHosts(preparer.prepare(application, cluster, nodeSpec, groups), resources); } - private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId) { + private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId, boolean exclusive) { return nodeResources.isUnspecified() - ? capacityPolicies.defaultNodeResources(cluster, applicationId) + ? capacityPolicies.defaultNodeResources(cluster, applicationId, exclusive) : nodeResources; } @@ -178,7 +177,8 @@ public class NodeRepositoryProvisioner implements Provisioner { private ClusterResources initialResourcesFrom(Capacity requested, ClusterSpec clusterSpec, ApplicationId applicationId) { var initial = requested.minResources(); if (initial.nodeResources().isUnspecified()) - initial = initial.with(capacityPolicies.defaultNodeResources(clusterSpec, applicationId)); + initial = initial.with(capacityPolicies.defaultNodeResources(clusterSpec, applicationId, + capacityPolicies.decideExclusivity(requested, clusterSpec.isExclusive()))); return initial; } @@ -260,7 +260,8 @@ public class NodeRepositoryProvisioner implements Provisioner { private IllegalArgumentException newNoAllocationPossible(ClusterSpec spec, Limits limits) { StringBuilder message = new StringBuilder("No allocation possible within ").append(limits); - if (nodeRepository.exclusiveAllocation(spec)) + boolean exclusiveHosts = spec.isExclusive() || ! nodeRepository.zone().cloud().allowHostSharing(); + if (exclusiveHosts) message.append(". Nearest allowed node resources: ").append(findNearestNodeResources(limits)); return new IllegalArgumentException(message.toString()); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java index 66895867623..81dd852e2a1 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java @@ -28,10 +28,10 @@ public class NodeResourceLimits { public void ensureWithinAdvertisedLimits(String type, NodeResources requested, ClusterSpec cluster) { if (requested.isUnspecified()) return; - if (requested.vcpu() < minAdvertisedVcpu(cluster)) - illegal(type, "vcpu", "", cluster, requested.vcpu(), minAdvertisedVcpu(cluster)); - if (requested.memoryGb() < minAdvertisedMemoryGb(cluster)) - illegal(type, "memoryGb", "Gb", cluster, requested.memoryGb(), minAdvertisedMemoryGb(cluster)); + if (requested.vcpu() < minAdvertisedVcpu(cluster.type())) + illegal(type, "vcpu", "", cluster, requested.vcpu(), minAdvertisedVcpu(cluster.type())); + if (requested.memoryGb() < minAdvertisedMemoryGb(cluster.type())) + illegal(type, "memoryGb", "Gb", cluster, requested.memoryGb(), minAdvertisedMemoryGb(cluster.type())); if (requested.diskGb() < minAdvertisedDiskGb(requested, cluster.isExclusive())) illegal(type, "diskGb", "Gb", cluster, requested.diskGb(), minAdvertisedDiskGb(requested, cluster.isExclusive())); } @@ -40,36 +40,36 @@ public class NodeResourceLimits { public boolean isWithinRealLimits(NodeCandidate candidateNode, ClusterSpec cluster) { if (candidateNode.type() != NodeType.tenant) return true; // Resource limits only apply to tenant nodes return isWithinRealLimits(nodeRepository.resourcesCalculator().realResourcesOf(candidateNode, nodeRepository), - cluster); + cluster.type()); } /** Returns whether the real resources we'll end up with on a given tenant node are within limits */ - public boolean isWithinRealLimits(NodeResources realResources, ClusterSpec cluster) { + public boolean isWithinRealLimits(NodeResources realResources, ClusterSpec.Type clusterType) { if (realResources.isUnspecified()) return true; - if (realResources.vcpu() < minRealVcpu(cluster)) return false; - if (realResources.memoryGb() < minRealMemoryGb(cluster)) return false; + if (realResources.vcpu() < minRealVcpu(clusterType)) return false; + if (realResources.memoryGb() < minRealMemoryGb(clusterType)) return false; if (realResources.diskGb() < minRealDiskGb()) return false; return true; } - public NodeResources enlargeToLegal(NodeResources requested, ClusterSpec cluster, boolean exclusive) { + public NodeResources enlargeToLegal(NodeResources requested, ClusterSpec.Type clusterType, boolean exclusive) { if (requested.isUnspecified()) return requested; - return requested.withVcpu(Math.max(minAdvertisedVcpu(cluster), requested.vcpu())) - .withMemoryGb(Math.max(minAdvertisedMemoryGb(cluster), requested.memoryGb())) + return requested.withVcpu(Math.max(minAdvertisedVcpu(clusterType), requested.vcpu())) + .withMemoryGb(Math.max(minAdvertisedMemoryGb(clusterType), requested.memoryGb())) .withDiskGb(Math.max(minAdvertisedDiskGb(requested, exclusive), requested.diskGb())); } - private double minAdvertisedVcpu(ClusterSpec cluster) { - if (zone().environment() == Environment.dev && ! nodeRepository.exclusiveAllocation(cluster)) return 0.1; - if (cluster.type().isContent() && zone().environment().isProduction()) return 1.0; - if (cluster.type() == ClusterSpec.Type.admin) return 0.1; + private double minAdvertisedVcpu(ClusterSpec.Type clusterType) { + if (zone().environment() == Environment.dev && zone().cloud().allowHostSharing()) return 0.1; + if (clusterType.isContent() && zone().environment().isProduction()) return 1.0; + if (clusterType == ClusterSpec.Type.admin) return 0.1; return 0.5; } - private double minAdvertisedMemoryGb(ClusterSpec cluster) { - if (cluster.type() == ClusterSpec.Type.admin) return 1; + private double minAdvertisedMemoryGb(ClusterSpec.Type clusterType) { + if (clusterType == ClusterSpec.Type.admin) return 1; return 4; } @@ -85,10 +85,10 @@ public class NodeResourceLimits { return 4; } - private double minRealVcpu(ClusterSpec cluster) { return minAdvertisedVcpu(cluster); } + private double minRealVcpu(ClusterSpec.Type clusterType) { return minAdvertisedVcpu(clusterType); } - private double minRealMemoryGb(ClusterSpec cluster) { - return minAdvertisedMemoryGb(cluster) - 1.7; + private double minRealMemoryGb(ClusterSpec.Type clusterType) { + return minAdvertisedMemoryGb(clusterType) - 1.7; } private double minRealDiskGb() { return 6; } 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 21389a8745c..fa5502ebef9 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 @@ -273,7 +273,7 @@ public class AutoscalingTest { .build(); NodeResources defaultResources = - new CapacityPolicies(fixture.tester().nodeRepository()).defaultNodeResources(fixture.clusterSpec, fixture.applicationId); + new CapacityPolicies(fixture.tester().nodeRepository()).defaultNodeResources(fixture.clusterSpec, fixture.applicationId, false); fixture.tester().assertResources("Min number of nodes and default resources", 2, 1, defaultResources, 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 00797cd6305..3134d378c1c 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 @@ -142,7 +142,7 @@ class AutoscalingTester { } public Autoscaler.Advice autoscale(ApplicationId applicationId, ClusterSpec cluster, Capacity capacity) { - capacity = capacityPolicies.applyOn(capacity, applicationId, capacityPolicies.decideExclusivity(capacity, cluster).isExclusive()); + capacity = capacityPolicies.applyOn(capacity, applicationId, capacityPolicies.decideExclusivity(capacity, cluster.isExclusive())); Application application = nodeRepository().applications().get(applicationId).orElse(Application.empty(applicationId)) .withCluster(cluster.id(), false, capacity); try (Mutex lock = nodeRepository().applications().lock(applicationId)) { -- cgit v1.2.3 From 6af8feb54aabce61e264328bf572d02a63443f6c Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Tue, 22 Nov 2022 12:21:35 +0100 Subject: Test with shared hosts flag --- .../hosted/provision/autoscale/AutoscalingTest.java | 18 ++++++++++++++++++ .../hosted/provision/autoscale/AutoscalingTester.java | 15 ++++++++++++--- .../vespa/hosted/provision/autoscale/Fixture.java | 13 ++++++++++++- 3 files changed, 42 insertions(+), 4 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 fa5502ebef9..4bc947cf095 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 @@ -78,6 +78,24 @@ public class AutoscalingTest { fixture.autoscale()); } + @Test + public void initial_deployment_with_host_sharing_flag() { + var min = new ClusterResources(7, 1, new NodeResources(2.0, 10.0, 384.0, 0.1)); + var max = new ClusterResources(7, 1, new NodeResources(2.4, 32.0, 768.0, 0.1)); + var fixture = AutoscalingTester.fixture() + .awsProdSetup(false) + .capacity(Capacity.from(min, max)) + .initialResources(Optional.empty()) + .hostSharingFlag() + .build(); + // TODO: Not actually at min since flags are inconsistently handled + fixture.tester().assertResources("Initial resources at min, since flag turns on host sharing", + 7, 1, 2.0, 16.0, 384.0, + fixture.currentResources().advertisedResources()); + } + + + /** When scaling up, disregard underutilized dimensions (memory here) */ @Test public void test_only_autoscaling_up_quickly() { 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 3134d378c1c..7969864c063 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 @@ -13,6 +13,7 @@ import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.Zone; import com.yahoo.test.ManualClock; import com.yahoo.transaction.Mutex; +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.Nodelike; @@ -43,16 +44,24 @@ class AutoscalingTester { private final HostResourcesCalculator hostResourcesCalculator; private final CapacityPolicies capacityPolicies; - public AutoscalingTester(Zone zone, HostResourcesCalculator resourcesCalculator, List hostFlavors, int hostCount) { - this(zone, hostFlavors, resourcesCalculator); + public AutoscalingTester(Zone zone, + HostResourcesCalculator resourcesCalculator, + List hostFlavors, + InMemoryFlagSource flagSource, + int hostCount) { + this(zone, hostFlavors, resourcesCalculator, flagSource); for (Flavor flavor : hostFlavors) provisioningTester.makeReadyNodes(hostCount, flavor.name(), NodeType.host, 8); provisioningTester.activateTenantHosts(); } - private AutoscalingTester(Zone zone, List flavors, HostResourcesCalculator resourcesCalculator) { + private AutoscalingTester(Zone zone, + List flavors, + HostResourcesCalculator resourcesCalculator, + InMemoryFlagSource flagSource) { provisioningTester = new ProvisioningTester.Builder().zone(zone) .flavors(flavors) + .flagSource(flagSource) .resourcesCalculator(resourcesCalculator) .hostProvisioner(zone.cloud().dynamicProvisioning() ? new MockHostProvisioner(flavors, zone.cloud()) : null) .build(); 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 4828db4dfc8..0c146f525a2 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,6 +13,10 @@ import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.flags.InMemoryFlagSource; +import com.yahoo.vespa.flags.PermanentFlags; +import com.yahoo.vespa.flags.custom.HostResources; +import com.yahoo.vespa.flags.custom.SharedHost; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.applications.Application; @@ -46,7 +50,7 @@ public class Fixture { applicationId = builder.application; clusterSpec = builder.cluster; capacity = builder.capacity; - tester = new AutoscalingTester(builder.zone, builder.resourceCalculator, builder.hostFlavors, hostCount); + tester = new AutoscalingTester(builder.zone, builder.resourceCalculator, builder.hostFlavors, builder.flagSource, hostCount); var deployCapacity = initialResources.isPresent() ? Capacity.from(initialResources.get()) : capacity; tester.deploy(builder.application, builder.cluster, deployCapacity); this.loader = new Loader(this); @@ -142,6 +146,7 @@ public class Fixture { new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1, NodeResources.DiskSpeed.any))); HostResourcesCalculator resourceCalculator = new AutoscalingTester.MockHostResourcesCalculator(zone); + final InMemoryFlagSource flagSource = new InMemoryFlagSource(); int hostCount = 0; public Fixture.Builder zone(Zone zone) { @@ -230,6 +235,12 @@ public class Fixture { return this; } + public Fixture.Builder hostSharingFlag() { + var resources = new HostResources(8.0, 32.0, 100.0, 10.0, "fast", "local", null, 6, "x86_64"); + flagSource.withJacksonFlag(PermanentFlags.SHARED_HOST.id(), new SharedHost(List.of(resources), null), SharedHost.class); + return this; + } + public Fixture.Builder hostCount(int hostCount) { this.hostCount = hostCount; return this; -- cgit v1.2.3