From dec25d5ab61a9e574a8b41853caa879adfccf894 Mon Sep 17 00:00:00 2001 From: HÃ¥kon Hallingstad Date: Sat, 18 May 2024 23:38:02 +0200 Subject: Remove flags dependency from config-model --- application/pom.xml | 6 --- config-model-api/abi-spec.json | 4 +- .../com/yahoo/config/model/api/ModelContext.java | 5 +++ config-model/pom.xml | 6 --- .../com/yahoo/config/model/deploy/DeployState.java | 14 ------- .../com/yahoo/vespa/model/VespaModelFactory.java | 10 +---- .../application/validation/QuotaValidator.java | 9 ++--- config-provisioning/pom.xml | 6 --- .../yahoo/config/provision/CapacityPolicies.java | 46 +++++++++------------- .../com/yahoo/config/provision/Exclusivity.java | 15 +++---- .../com/yahoo/config/provision/SharedHosts.java | 30 ++++++++++++++ .../config/server/deploy/ModelContextImpl.java | 9 +++++ .../vespa/hosted/provision/NodeRepository.java | 14 +++++++ .../hosted/provision/autoscale/ClusterModel.java | 8 ++-- .../vespa/hosted/provision/autoscale/Limits.java | 7 ++-- .../provisioning/NodeRepositoryProvisioner.java | 29 +++++++------- .../provision/testutils/MockNodeRepository.java | 3 +- .../hosted/provision/NodeRepositoryTester.java | 3 +- .../provision/autoscale/AutoscalingTest.java | 11 ++---- .../vespa/hosted/provision/autoscale/Fixture.java | 12 +++--- .../maintenance/CapacityCheckerTester.java | 6 +-- .../maintenance/SpareCapacityMaintainerTest.java | 6 +-- .../provisioning/DynamicProvisioningTest.java | 4 +- .../provisioning/DynamicProvisioningTester.java | 13 +++--- .../provision/provisioning/ProvisioningTester.java | 20 ++++++---- standalone-container/pom.xml | 7 ---- 26 files changed, 153 insertions(+), 150 deletions(-) create mode 100644 config-provisioning/src/main/java/com/yahoo/config/provision/SharedHosts.java diff --git a/application/pom.xml b/application/pom.xml index cbe04038df9..f5704541308 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -34,12 +34,6 @@ config-model-api ${project.version} - - com.yahoo.vespa - flags - ${project.version} - provided - com.yahoo.vespa http-utils diff --git a/config-model-api/abi-spec.json b/config-model-api/abi-spec.json index c0139c87349..b86b5fd9b99 100644 --- a/config-model-api/abi-spec.json +++ b/config-model-api/abi-spec.json @@ -1326,7 +1326,9 @@ "public boolean alwaysMarkPhraseExpensive()", "public boolean sortBlueprintsByCost()", "public int persistenceThreadMaxFeedOpBatchSize()", - "public boolean logserverOtelCol()" + "public boolean logserverOtelCol()", + "public com.yahoo.config.provision.SharedHosts sharedHosts()", + "public com.yahoo.config.provision.NodeResources$Architecture adminClusterArchitecture()" ], "fields" : [ ] }, diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java index ad5ab5b7ee4..67735329287 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java @@ -12,6 +12,9 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.DataplaneToken; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.HostName; +import com.yahoo.config.provision.NodeResources; +import com.yahoo.config.provision.NodeResources.Architecture; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.Zone; import java.io.File; @@ -114,6 +117,8 @@ public interface ModelContext { @ModelFeatureFlag(owners = {"baldersheim"}) default boolean sortBlueprintsByCost() { return false; } @ModelFeatureFlag(owners = {"vekterli"}) default int persistenceThreadMaxFeedOpBatchSize() { return 1; } @ModelFeatureFlag(owners = {"olaa"}) default boolean logserverOtelCol() { return false; } + @ModelFeatureFlag(owners = {"bratseth"}) default SharedHosts sharedHosts() { return SharedHosts.empty(); } + @ModelFeatureFlag(owners = {"bratseth"}) default Architecture adminClusterArchitecture() { return Architecture.x86_64; } } /** Warning: As elsewhere in this package, do not make backwards incompatible changes that will break old config models! */ diff --git a/config-model/pom.xml b/config-model/pom.xml index 751d3de63ef..a0bda542d5f 100644 --- a/config-model/pom.xml +++ b/config-model/pom.xml @@ -24,12 +24,6 @@ ${project.version} provided - - com.yahoo.vespa - flags - ${project.version} - provided - com.yahoo.vespa provided-dependencies diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java index 0e4e296f5a1..57a75bd8a38 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java @@ -39,8 +39,6 @@ import com.yahoo.vespa.config.ConfigDefinition; import com.yahoo.vespa.config.ConfigDefinitionBuilder; import com.yahoo.vespa.config.ConfigDefinitionKey; import com.yahoo.vespa.documentmodel.DocumentModel; -import com.yahoo.vespa.flags.FlagSource; -import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.model.container.search.QueryProfiles; import com.yahoo.vespa.model.container.search.QueryProfilesBuilder; import com.yahoo.vespa.model.container.search.SemanticRules; @@ -81,7 +79,6 @@ public class DeployState implements ConfigDefinitionStore { private final Version vespaVersion; private final Set endpoints; private final Zone zone; // TODO: Zone is set separately both here and in properties - private final FlagSource flagSource; private final QueryProfiles queryProfiles; private final SemanticRules semanticRules; private final ImportedMlModels importedModels; @@ -121,7 +118,6 @@ public class DeployState implements ConfigDefinitionStore { Set endpoints, Collection modelImporters, Zone zone, - FlagSource flagSource, QueryProfiles queryProfiles, SemanticRules semanticRules, Instant now, @@ -147,7 +143,6 @@ public class DeployState implements ConfigDefinitionStore { this.configDefinitionRepo = configDefinitionRepo; this.endpoints = Set.copyOf(endpoints); this.zone = zone; - this.flagSource = flagSource; this.queryProfiles = queryProfiles; // TODO: Remove this by seeing how pagetemplates are propagated this.semanticRules = semanticRules; // TODO: Remove this by seeing how pagetemplates are propagated this.importedModels = importMlModels(applicationPackage, modelImporters, executor); @@ -278,8 +273,6 @@ public class DeployState implements ConfigDefinitionStore { /** Returns the zone in which this is currently running */ public Zone zone() { return zone; } - public FlagSource flagSource() { return flagSource; } - public QueryProfiles getQueryProfiles() { return queryProfiles; } public SemanticRules getSemanticRules() { return semanticRules; } @@ -337,7 +330,6 @@ public class DeployState implements ConfigDefinitionStore { private Set endpoints = Set.of(); private Collection modelImporters = List.of(); private Zone zone = Zone.defaultZone(); - private FlagSource flagSource = new InMemoryFlagSource(); private Instant now = Instant.now(); private Version wantedNodeVespaVersion = Vtag.currentVersion; private boolean accessLoggingEnabledByDefault = true; @@ -415,11 +407,6 @@ public class DeployState implements ConfigDefinitionStore { return this; } - public Builder flagSource(FlagSource flagSource) { - this.flagSource = flagSource; - return this; - } - public Builder now(Instant now) { this.now = now; return this; @@ -496,7 +483,6 @@ public class DeployState implements ConfigDefinitionStore { endpoints, modelImporters, zone, - flagSource, queryProfiles, semanticRules, now, diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java index efe83fb4e91..c876976917b 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java @@ -28,8 +28,6 @@ import com.yahoo.config.provision.QuotaExceededException; import com.yahoo.config.provision.TransientException; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.VespaVersion; -import com.yahoo.vespa.flags.FlagSource; -import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.model.application.validation.Validation; import com.yahoo.vespa.model.application.validation.Validator; import org.xml.sax.SAXException; @@ -54,7 +52,6 @@ public class VespaModelFactory implements ModelFactory { private final ConfigModelRegistry configModelRegistry; private final Collection modelImporters; private final Zone zone; - private final FlagSource flagSource; private final Clock clock; private final Version version; private final List additionalValidators; @@ -63,7 +60,7 @@ public class VespaModelFactory implements ModelFactory { @Inject public VespaModelFactory(ComponentRegistry pluginRegistry, ComponentRegistry additionalValidators, - Zone zone, FlagSource flagSource) { + Zone zone) { this.version = new Version(VespaVersion.major, VespaVersion.minor, VespaVersion.micro); List> modelBuilders = new ArrayList<>(); for (ConfigModelPlugin plugin : pluginRegistry.allComponents()) { @@ -79,7 +76,6 @@ public class VespaModelFactory implements ModelFactory { new XGBoostImporter(), new LightGBMImporter()); this.zone = zone; - this.flagSource = flagSource; this.additionalValidators = List.copyOf(additionalValidators.allComponents()); this.clock = Clock.systemUTC(); @@ -88,7 +84,7 @@ public class VespaModelFactory implements ModelFactory { // For testing only protected VespaModelFactory(ConfigModelRegistry configModelRegistry) { this(new Version(VespaVersion.major, VespaVersion.minor, VespaVersion.micro), configModelRegistry, - Clock.systemUTC(), Zone.defaultZone()); + Clock.systemUTC(), Zone.defaultZone()); } private VespaModelFactory(Version version, ConfigModelRegistry configModelRegistry, Clock clock, Zone zone) { @@ -102,7 +98,6 @@ public class VespaModelFactory implements ModelFactory { this.modelImporters = List.of(); this.additionalValidators = List.of(); this.zone = zone; - this.flagSource = new InMemoryFlagSource(); this.clock = clock; } @@ -197,7 +192,6 @@ public class VespaModelFactory implements ModelFactory { .endpoints(modelContext.properties().endpoints()) .modelImporters(modelImporters) .zone(zone) - .flagSource(flagSource) .now(clock.instant()) .wantedNodeVespaVersion(modelContext.wantedNodeVespaVersion()) .wantedDockerImageRepo(modelContext.wantedDockerImageRepo()) diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java index 0984770ef49..ea579aaf5d1 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java @@ -1,7 +1,6 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.application.validation; -import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.CapacityPolicies; import com.yahoo.config.provision.ClusterResources; @@ -10,7 +9,6 @@ import com.yahoo.config.provision.Exclusivity; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.QuotaExceededException; import com.yahoo.config.provision.SystemName; -import com.yahoo.config.provision.Zone; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.application.validation.Validation.Context; @@ -35,8 +33,9 @@ public class QuotaValidator implements Validator { @Override public void validate(Context context) { var zone = context.deployState().zone(); - var flagSource = context.deployState().flagSource(); - var capacityPolicies = new CapacityPolicies(zone, new Exclusivity(zone, flagSource), flagSource); + var exclusivity = new Exclusivity(zone, context.deployState().featureFlags().sharedHosts()); + var capacityPolicies = new CapacityPolicies(zone, exclusivity, context.model().applicationPackage().getApplicationId(), + context.deployState().featureFlags().adminClusterArchitecture()); var quota = context.deployState().getProperties().quota(); quota.maxClusterSize().ifPresent(maxClusterSize -> validateMaxClusterSize(maxClusterSize, context.model())); quota.budgetAsDecimal().ifPresent(budget -> validateBudget(budget, context, capacityPolicies)); @@ -52,7 +51,7 @@ public class QuotaValidator implements Validator { if (adminClusterIds(context.model()).contains(id)) continue; var cluster = context.model().provisioned().clusters().get(id); var capacity = context.model().provisioned().capacities().getOrDefault(id, zeroCapacity); - maxSpend += capacityPolicies.applyOn(capacity, application, cluster.isExclusive()).maxResources().cost(); + maxSpend += capacityPolicies.applyOn(capacity, cluster.isExclusive()).maxResources().cost(); } var actualSpend = context.model().allocatedHosts().getHosts().stream() diff --git a/config-provisioning/pom.xml b/config-provisioning/pom.xml index 63fb2f30ba6..75047ac8efa 100644 --- a/config-provisioning/pom.xml +++ b/config-provisioning/pom.xml @@ -52,12 +52,6 @@ ${project.version} provided - - com.yahoo.vespa - flags - ${project.version} - provided - com.yahoo.vespa testutil diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/CapacityPolicies.java b/config-provisioning/src/main/java/com/yahoo/config/provision/CapacityPolicies.java index dec2984846e..818a448187c 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/CapacityPolicies.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/CapacityPolicies.java @@ -3,15 +3,11 @@ package com.yahoo.config.provision; import com.yahoo.component.Version; import com.yahoo.config.provision.NodeResources.DiskSpeed; -import com.yahoo.vespa.flags.FlagSource; -import com.yahoo.vespa.flags.PermanentFlags; -import com.yahoo.vespa.flags.StringFlag; import java.util.Map; import java.util.TreeMap; import static com.yahoo.config.provision.NodeResources.Architecture; -import static com.yahoo.vespa.flags.Dimension.INSTANCE_ID; import static java.util.Objects.requireNonNull; /** @@ -23,24 +19,26 @@ public class CapacityPolicies { private final Zone zone; private final Exclusivity exclusivity; - private final StringFlag adminClusterNodeArchitecture; + private final ApplicationId applicationId; + private final Architecture adminClusterArchitecture; - public CapacityPolicies(Zone zone, Exclusivity exclusivity, FlagSource flagSource) { + public CapacityPolicies(Zone zone, Exclusivity exclusivity, ApplicationId applicationId, Architecture adminClusterArchitecture) { this.zone = zone; this.exclusivity = exclusivity; - this.adminClusterNodeArchitecture = PermanentFlags.ADMIN_CLUSTER_NODE_ARCHITECTURE.bindTo(flagSource); + this.applicationId = applicationId; + this.adminClusterArchitecture = adminClusterArchitecture; } - public Capacity applyOn(Capacity capacity, ApplicationId application, boolean exclusive) { - var min = applyOn(capacity.minResources(), capacity, application, exclusive); - var max = applyOn(capacity.maxResources(), capacity, application, exclusive); + public Capacity applyOn(Capacity capacity, boolean exclusive) { + var min = applyOn(capacity.minResources(), capacity, exclusive); + var max = applyOn(capacity.maxResources(), capacity, exclusive); var groupSize = capacity.groupSize().fromAtMost(max.nodes() / min.groups()) .toAtLeast(min.nodes() / max.groups()); return capacity.withLimits(min, max, groupSize); } - private ClusterResources applyOn(ClusterResources resources, Capacity capacity, ApplicationId application, boolean exclusive) { - int nodes = decideCount(resources.nodes(), capacity.isRequired(), application.instance().isTester()); + private ClusterResources applyOn(ClusterResources resources, Capacity capacity, boolean exclusive) { + int nodes = decideCount(resources.nodes(), capacity.isRequired(), applicationId.instance().isTester()); int groups = decideGroups(resources.nodes(), resources.groups(), nodes); var nodeResources = decideNodeResources(resources.nodeResources(), capacity.isRequired(), exclusive); return new ClusterResources(nodes, groups, nodeResources); @@ -85,31 +83,29 @@ public class CapacityPolicies { return target; } - public ClusterResources specifyFully(ClusterResources resources, ClusterSpec clusterSpec, ApplicationId applicationId) { - return resources.with(specifyFully(resources.nodeResources(), clusterSpec, applicationId)); + public ClusterResources specifyFully(ClusterResources resources, ClusterSpec clusterSpec) { + return resources.with(specifyFully(resources.nodeResources(), clusterSpec)); } - public NodeResources specifyFully(NodeResources resources, ClusterSpec clusterSpec, ApplicationId applicationId) { - return resources.withUnspecifiedFieldsFrom(defaultResources(clusterSpec, applicationId).with(DiskSpeed.any)); + public NodeResources specifyFully(NodeResources resources, ClusterSpec clusterSpec) { + return resources.withUnspecifiedFieldsFrom(defaultResources(clusterSpec).with(DiskSpeed.any)); } - private NodeResources defaultResources(ClusterSpec clusterSpec, ApplicationId applicationId) { + private NodeResources defaultResources(ClusterSpec clusterSpec) { if (clusterSpec.type() == ClusterSpec.Type.admin) { - Architecture architecture = adminClusterArchitecture(applicationId); - if (exclusivity.allocation(clusterSpec)) { - return smallestExclusiveResources().with(architecture); + return smallestExclusiveResources().with(adminClusterArchitecture); } if (clusterSpec.id().value().equals("cluster-controllers")) { - return clusterControllerResources(clusterSpec, architecture).with(architecture); + return clusterControllerResources(clusterSpec, adminClusterArchitecture).with(adminClusterArchitecture); } if (clusterSpec.id().value().equals("logserver")) { - return logserverResources(architecture).with(architecture); + return logserverResources(adminClusterArchitecture).with(adminClusterArchitecture); } - return versioned(clusterSpec, Map.of(new Version(0), smallestSharedResources())).with(architecture); + return versioned(clusterSpec, Map.of(new Version(0), smallestSharedResources())).with(adminClusterArchitecture); } if (clusterSpec.type() == ClusterSpec.Type.content) { @@ -148,10 +144,6 @@ public class CapacityPolicies { : new NodeResources(0.5, 2, 50, 0.3); } - private Architecture adminClusterArchitecture(ApplicationId instance) { - return Architecture.valueOf(adminClusterNodeArchitecture.with(INSTANCE_ID, instance.serializedForm()).value()); - } - // The lowest amount of resources that can be exclusive allocated (i.e. a matching host flavor for this exists) private NodeResources smallestExclusiveResources() { return zone.cloud().name() == CloudName.AZURE || zone.cloud().name() == CloudName.GCP diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Exclusivity.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Exclusivity.java index 40122c17c3f..6aafb20bee2 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/Exclusivity.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Exclusivity.java @@ -1,10 +1,5 @@ package com.yahoo.config.provision; -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; - /** * A class which can be asked if allocations should be exclusive. * @@ -13,16 +8,16 @@ import com.yahoo.vespa.flags.custom.SharedHost; public class Exclusivity { private final Zone zone; - private final JacksonFlag sharedHosts; + private final SharedHosts sharedHost; - public Exclusivity(Zone zone, FlagSource flagSource) { + public Exclusivity(Zone zone, SharedHosts sharedHost) { this.zone = zone; - this.sharedHosts = PermanentFlags.SHARED_HOST.bindTo(flagSource); + this.sharedHost = sharedHost; } /** Returns whether nodes must be allocated to hosts that are exclusive to the cluster type. */ public boolean clusterType(ClusterSpec cluster) { - return sharedHosts.value().hasClusterType(cluster.type().name()); + return sharedHost.hasClusterType(cluster.type()); } /** Returns whether the nodes of this cluster must be running on hosts that are specifically provisioned for the application. */ @@ -38,7 +33,7 @@ public class Exclusivity { public boolean allocation(ClusterSpec clusterSpec) { return clusterSpec.isExclusive() || ( clusterSpec.type().isContainer() && zone.system().isPublic() && !zone.environment().isTest() ) || - ( !zone.cloud().allowHostSharing() && !sharedHosts.value().supportsClusterType(clusterSpec.type().name())); + ( !zone.cloud().allowHostSharing() && !sharedHost.supportsClusterType(clusterSpec.type())); } } diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/SharedHosts.java b/config-provisioning/src/main/java/com/yahoo/config/provision/SharedHosts.java new file mode 100644 index 00000000000..44a91d2861d --- /dev/null +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/SharedHosts.java @@ -0,0 +1,30 @@ +package com.yahoo.config.provision; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * @author hakonhall + */ +public interface SharedHosts { + static SharedHosts empty() { + return new SharedHosts() { + @Override public boolean supportsClusterType(ClusterSpec.Type clusterType) { return false; } + @Override public boolean hasClusterType(ClusterSpec.Type clusterType) { return false; } + }; + } + + static SharedHosts ofConstant(boolean supportsClusterType, boolean hasClusterType) { + return new SharedHosts() { + @Override public boolean supportsClusterType(ClusterSpec.Type clusterType) { return supportsClusterType; } + @Override public boolean hasClusterType(ClusterSpec.Type clusterType) { return hasClusterType; } + }; + } + + /** Whether there are any shared hosts specifically for the given cluster type, or without a cluster type restriction. */ + @JsonIgnore + boolean supportsClusterType(ClusterSpec.Type clusterType); + + /** Whether there are any shared hosts specifically for the given cluster type. */ + @JsonIgnore + boolean hasClusterType(ClusterSpec.Type clusterType); +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java index 7189ae12c66..e418a432366 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java @@ -25,6 +25,7 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.DataplaneToken; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.HostName; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.Zone; import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.vespa.config.server.tenant.SecretStoreExternalIdRetriever; @@ -34,6 +35,7 @@ import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.flags.StringFlag; import com.yahoo.vespa.flags.UnboundFlag; +import com.yahoo.vespa.flags.custom.SharedHost; import java.io.File; import java.net.URI; @@ -208,6 +210,7 @@ public class ModelContextImpl implements ModelContext { private final int searchHandlerThreadpool; private final int persistenceThreadMaxFeedOpBatchSize; private final boolean logserverOtelCol; + private final SharedHosts sharedHosts; public FeatureFlags(FlagSource source, ApplicationId appId, Version version) { this.defaultTermwiseLimit = flagValue(source, appId, version, Flags.DEFAULT_TERM_WISE_LIMIT); @@ -252,6 +255,11 @@ public class ModelContextImpl implements ModelContext { this.sortBlueprintsByCost = flagValue(source, appId, version, Flags.SORT_BLUEPRINTS_BY_COST); this.persistenceThreadMaxFeedOpBatchSize = flagValue(source, appId, version, Flags.PERSISTENCE_THREAD_MAX_FEED_OP_BATCH_SIZE); this.logserverOtelCol = flagValue(source, appId, version, Flags.LOGSERVER_OTELCOL_AGENT); + SharedHost sharedHost = flagValue(source, appId, version, PermanentFlags.SHARED_HOST); + this.sharedHosts = new SharedHosts() { + @Override public boolean supportsClusterType(ClusterSpec.Type clusterType) { return sharedHost.supportsClusterType(clusterType.name()); } + @Override public boolean hasClusterType(ClusterSpec.Type clusterType) { return sharedHost.hasClusterType(clusterType.name()); } + }; } @Override public int heapSizePercentage() { return heapPercentage; } @@ -304,6 +312,7 @@ public class ModelContextImpl implements ModelContext { @Override public boolean sortBlueprintsByCost() { return sortBlueprintsByCost; } @Override public int persistenceThreadMaxFeedOpBatchSize() { return persistenceThreadMaxFeedOpBatchSize; } @Override public boolean logserverOtelCol() { return logserverOtelCol; } + @Override public SharedHosts sharedHosts() { return sharedHosts; } private static V flagValue(FlagSource source, ApplicationId appId, Version vespaVersion, UnboundFlag flag) { return flag.bindTo(source) 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 086f66fd16b..cc46fc381f0 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 @@ -4,16 +4,20 @@ package com.yahoo.vespa.hosted.provision; import com.yahoo.component.AbstractComponent; import com.yahoo.component.annotation.Inject; import com.yahoo.concurrent.maintenance.JobControl; +import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationTransaction; +import com.yahoo.config.provision.CapacityPolicies; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.EndpointsChecker.HealthChecker; import com.yahoo.config.provision.EndpointsChecker.HealthCheckerProvider; import com.yahoo.config.provision.Exclusivity; import com.yahoo.config.provision.NodeFlavors; +import com.yahoo.config.provision.NodeResources.Architecture; 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.PermanentFlags; import com.yahoo.vespa.hosted.provision.Node.State; import com.yahoo.vespa.hosted.provision.applications.Applications; import com.yahoo.vespa.hosted.provision.archive.ArchiveUriManager; @@ -41,6 +45,8 @@ import java.time.Clock; import java.util.List; import java.util.Optional; +import static com.yahoo.vespa.flags.Dimension.INSTANCE_ID; + /** * The top level singleton in the node repo, providing access to all its state as child objects. * @@ -209,6 +215,14 @@ public class NodeRepository extends AbstractComponent implements HealthCheckerPr public Exclusivity exclusivity() { return exclusivity; } + public CapacityPolicies capacityPoliciesFor(ApplicationId applicationId) { + String adminClusterNodeArchitecture = PermanentFlags.ADMIN_CLUSTER_NODE_ARCHITECTURE + .bindTo(flagSource) + .with(INSTANCE_ID, applicationId.serializedForm()) + .value(); + return new CapacityPolicies(zone, exclusivity, applicationId, Architecture.valueOf(adminClusterNodeArchitecture)); + } + /** * Returns ACLs for the children of the given host. * diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java index 5310ecaa1c2..504965f1992 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java @@ -85,7 +85,7 @@ public class ClusterModel { MetricsDb metricsDb, Clock clock) { this.nodeRepository = nodeRepository; - this.capacityPolicies = new CapacityPolicies(nodeRepository.zone(), nodeRepository.exclusivity(), nodeRepository.flagSource()); + this.capacityPolicies = nodeRepository.capacityPoliciesFor(application.id()); this.application = application; this.clusterSpec = clusterSpec; this.cluster = cluster; @@ -110,7 +110,7 @@ public class ClusterModel { ClusterTimeseries clusterTimeseries, ClusterNodesTimeseries nodeTimeseries) { this.nodeRepository = nodeRepository; - this.capacityPolicies = new CapacityPolicies(nodeRepository.zone(), nodeRepository.exclusivity(), nodeRepository.flagSource()); + this.capacityPolicies = nodeRepository.capacityPoliciesFor(application.id()); this.application = application; this.clusterSpec = clusterSpec; this.cluster = cluster; @@ -439,9 +439,7 @@ public class ClusterModel { double averageReal() { if (nodes.isEmpty()) { // we're estimating - var initialResources = capacityPolicies.specifyFully(cluster.minResources().nodeResources(), - clusterSpec, - application.id()); + var initialResources = capacityPolicies.specifyFully(cluster.minResources().nodeResources(), clusterSpec); return nodeRepository.resourcesCalculator().requestToReal(initialResources, cloudAccount(), nodeRepository.exclusivity().allocation(clusterSpec), 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 54e611eef18..51046df90af 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 @@ -9,7 +9,6 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.NodeResources; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.applications.Cluster; -import com.yahoo.config.provision.CapacityPolicies; import java.util.Objects; @@ -68,9 +67,9 @@ 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 capacityPolicies = new CapacityPolicies(nodeRepository.zone(), nodeRepository.exclusivity(), nodeRepository.flagSource()); - return new Limits(capacityPolicies.specifyFully(min, clusterSpec, applicationId), - capacityPolicies.specifyFully(max, clusterSpec, applicationId), + var capacityPolicies = nodeRepository.capacityPoliciesFor(applicationId); + return new Limits(capacityPolicies.specifyFully(min, clusterSpec), + capacityPolicies.specifyFully(max, clusterSpec), groupSize); } 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 44750988a3e..9a90a1670c3 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 @@ -54,7 +54,6 @@ public class NodeRepositoryProvisioner implements Provisioner { private final NodeRepository nodeRepository; private final AllocationOptimizer allocationOptimizer; - private final CapacityPolicies capacityPolicies; private final Zone zone; private final Preparer preparer; private final Activator activator; @@ -67,7 +66,6 @@ public class NodeRepositoryProvisioner implements Provisioner { Metric metric) { this.nodeRepository = nodeRepository; this.allocationOptimizer = new AllocationOptimizer(nodeRepository); - this.capacityPolicies = new CapacityPolicies(nodeRepository.zone(), nodeRepository.exclusivity(), nodeRepository.flagSource()); this.zone = zone; this.loadBalancerProvisioner = provisionServiceProvider.getLoadBalancerService() .map(lbService -> new LoadBalancerProvisioner(nodeRepository, lbService)); @@ -89,23 +87,24 @@ public class NodeRepositoryProvisioner implements Provisioner { " for application " + application + ", cluster " + cluster); validate(application, cluster, requested, logger); + var capacityPolicies = nodeRepository.capacityPoliciesFor(application); NodeResources resources; NodeSpec nodeSpec; if (requested.type() == NodeType.tenant) { cluster = capacityPolicies.decideExclusivity(requested, cluster); - Capacity actual = capacityPolicies.applyOn(requested, application, cluster.isExclusive()); - ClusterResources target = decideTargetResources(application, cluster, actual); + Capacity actual = capacityPolicies.applyOn(requested, cluster.isExclusive()); + ClusterResources target = decideTargetResources(application, cluster, actual, capacityPolicies); validate(actual, target, cluster, application); logIfDownscaled(requested.minResources().nodes(), actual.minResources().nodes(), cluster, logger); - resources = getNodeResources(cluster, target.nodeResources(), application); + resources = getNodeResources(cluster, target.nodeResources(), application, capacityPolicies); nodeSpec = NodeSpec.from(target.nodes(), target.groups(), resources, cluster.isExclusive(), actual.canFail(), requested.cloudAccount().orElse(nodeRepository.zone().cloud().account()), requested.clusterInfo().hostTTL()); } else { cluster = cluster.withExclusivity(true); - resources = getNodeResources(cluster, requested.minResources().nodeResources(), application); + resources = getNodeResources(cluster, requested.minResources().nodeResources(), application, capacityPolicies); nodeSpec = NodeSpec.from(requested.type(), nodeRepository.zone().cloud().account()); } return asSortedHosts(preparer.prepare(application, cluster, nodeSpec), @@ -134,8 +133,8 @@ public class NodeRepositoryProvisioner implements Provisioner { } } - private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId) { - return capacityPolicies.specifyFully(nodeResources, cluster, applicationId); + private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId, CapacityPolicies capacityPolicies) { + return capacityPolicies.specifyFully(nodeResources, cluster); } @Override @@ -167,13 +166,14 @@ public class NodeRepositoryProvisioner implements Provisioner { * Returns the target cluster resources, a value between the min and max in the requested capacity, * and updates the application store with the received min and max. */ - private ClusterResources decideTargetResources(ApplicationId applicationId, ClusterSpec clusterSpec, Capacity requested) { + private ClusterResources decideTargetResources(ApplicationId applicationId, ClusterSpec clusterSpec, Capacity requested, + CapacityPolicies capacityPolicies) { try (Mutex lock = nodeRepository.applications().lock(applicationId)) { var application = nodeRepository.applications().get(applicationId).orElse(Application.empty(applicationId)) .withCluster(clusterSpec.id(), clusterSpec.isExclusive(), requested); nodeRepository.applications().put(application, lock); var cluster = application.cluster(clusterSpec.id()).get(); - return cluster.target().resources().orElseGet(() -> currentResources(application, clusterSpec, cluster, requested)); + return cluster.target().resources().orElseGet(() -> currentResources(application, clusterSpec, cluster, requested, capacityPolicies)); } } @@ -181,7 +181,8 @@ public class NodeRepositoryProvisioner implements Provisioner { private ClusterResources currentResources(Application application, ClusterSpec clusterSpec, Cluster cluster, - Capacity requested) { + Capacity requested, + CapacityPolicies capacityPolicies) { NodeList nodes = nodeRepository.nodes().list(Node.State.active).owner(application.id()) .cluster(clusterSpec.id()) .not().retired() @@ -189,15 +190,15 @@ public class NodeRepositoryProvisioner implements Provisioner { boolean firstDeployment = nodes.isEmpty(); var current = firstDeployment // start at min, preserve current resources otherwise - ? new AllocatableResources(initialResourcesFrom(requested, clusterSpec, application.id()), clusterSpec, + ? new AllocatableResources(initialResourcesFrom(requested, clusterSpec, application.id(), capacityPolicies), clusterSpec, nodeRepository, requested.cloudAccount().orElse(CloudAccount.empty)) : new AllocatableResources(nodes, nodeRepository); var model = new ClusterModel(nodeRepository, application, clusterSpec, cluster, nodes, current, nodeRepository.metricsDb(), nodeRepository.clock()); return within(Limits.of(requested), model, firstDeployment); } - private ClusterResources initialResourcesFrom(Capacity requested, ClusterSpec clusterSpec, ApplicationId applicationId) { - return capacityPolicies.specifyFully(requested.minResources(), clusterSpec, applicationId); + private ClusterResources initialResourcesFrom(Capacity requested, ClusterSpec clusterSpec, ApplicationId applicationId, CapacityPolicies capacityPolicies) { + return capacityPolicies.specifyFully(requested.minResources(), clusterSpec); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java index 17b7dd6c307..c085a3ed27c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java @@ -20,6 +20,7 @@ import com.yahoo.config.provision.IntRange; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.WireguardKey; import com.yahoo.config.provision.WireguardKeyWithTimestamp; @@ -91,7 +92,7 @@ public class MockNodeRepository extends NodeRepository { curator, Clock.fixed(Instant.ofEpochMilli(123), ZoneId.of("Z")), zone, - new Exclusivity(zone, new InMemoryFlagSource()), + new Exclusivity(zone, SharedHosts.empty()), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), Optional.empty(), 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 b9b3d9b1268..fb96d6f798e 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 @@ -6,6 +6,7 @@ import com.yahoo.config.provision.Exclusivity; import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.Zone; import com.yahoo.config.provisioning.FlavorsConfig; import com.yahoo.test.ManualClock; @@ -47,7 +48,7 @@ public class NodeRepositoryTester { curator, clock, zone, - new Exclusivity(zone, flagSource), + new Exclusivity(zone, SharedHosts.empty()), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), Optional.empty(), 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 6316adae887..e0c8199a882 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 @@ -13,7 +13,6 @@ import com.yahoo.config.provision.NodeResources.DiskSpeed; import com.yahoo.config.provision.NodeResources.StorageType; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.Zone; -import com.yahoo.config.provision.CapacityPolicies; import com.yahoo.vespa.hosted.provision.provisioning.DynamicProvisioningTester; import org.junit.Test; @@ -162,7 +161,7 @@ public class AutoscalingTest { .awsProdSetup(false) .capacity(Capacity.from(min, max)) .initialResources(Optional.empty()) - .hostSharingFlag() + .hostSharing() .build(); fixture.tester().assertResources("Initial resources at min, since flag turns on host sharing", 7, 1, 2.0, 10.0, 384.0, @@ -178,7 +177,7 @@ public class AutoscalingTest { .clusterType(ClusterSpec.Type.container) .capacity(Capacity.from(min, max)) .initialResources(Optional.empty()) - .hostSharingFlag() + .hostSharing() .build(); fixture.tester().assertResources("Initial resources at min, since flag turns on host sharing", 1, 1, 0.5, 4.0, 10.0, @@ -389,10 +388,8 @@ public class AutoscalingTest { .build(); NodeResources defaultResources = - new CapacityPolicies(fixture.tester().nodeRepository().zone(), - fixture.tester().nodeRepository().exclusivity(), - fixture.tester().nodeRepository().flagSource()) - .specifyFully(NodeResources.unspecified(), fixture.clusterSpec, fixture.applicationId); + fixture.tester().nodeRepository().capacityPoliciesFor(fixture.applicationId) + .specifyFully(NodeResources.unspecified(), fixture.clusterSpec); 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/Fixture.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java index 4ce909fece3..f9f3ca9db8d 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 @@ -11,12 +11,10 @@ import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.SharedHosts; 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; @@ -51,7 +49,7 @@ public class Fixture { applicationId = builder.application; clusterSpec = builder.cluster; capacity = builder.capacity; - tester = new DynamicProvisioningTester(builder.zone, builder.resourceCalculator, builder.hostFlavors, builder.flagSource, hostCount); + tester = new DynamicProvisioningTester(builder.zone, builder.resourceCalculator, builder.hostFlavors, builder.flagSource, builder.sharedHosts, hostCount); var deployCapacity = initialResources.isPresent() ? Capacity.from(initialResources.get()) : capacity; tester.deploy(builder.application, builder.cluster, deployCapacity); this.loader = new Loader(this); @@ -178,6 +176,7 @@ public class Fixture { HostResourcesCalculator resourceCalculator = new DynamicProvisioningTester.MockHostResourcesCalculator(zone); final InMemoryFlagSource flagSource = new InMemoryFlagSource(); int hostCount = 0; + SharedHosts sharedHosts = SharedHosts.empty(); public Fixture.Builder zone(Zone zone) { this.zone = zone; @@ -283,9 +282,8 @@ 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)), SharedHost.class); + public Fixture.Builder hostSharing() { + sharedHosts = SharedHosts.ofConstant(true, false); return this; } 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 ca1e47f8ea2..68303535f8c 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 @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.provision.maintenance; import com.yahoo.config.provision.Exclusivity; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.json.Jackson; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -64,18 +65,17 @@ public class CapacityCheckerTester { CapacityCheckerTester() { Curator curator = new MockCurator(); NodeFlavors f = new NodeFlavors(new FlavorConfigBuilder().build()); - var flagSource = new InMemoryFlagSource(); nodeRepository = new NodeRepository(f, new EmptyProvisionServiceProvider(), curator, clock, zone, - new Exclusivity(zone, flagSource), + new Exclusivity(zone, SharedHosts.empty()), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), Optional.empty(), Optional.empty(), - flagSource, + new InMemoryFlagSource(), new MemoryMetricsDb(clock), new OrchestratorMock(), true, diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java index 78f5d8c9b65..dd43a27b0c3 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java @@ -14,6 +14,7 @@ import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.ApplicationMutex; import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.Zone; import com.yahoo.test.ManualClock; import com.yahoo.transaction.NestedTransaction; @@ -260,18 +261,17 @@ public class SpareCapacityMaintainerTest { NodeFlavors flavors = new NodeFlavors(new FlavorConfigBuilder().build()); ManualClock clock = new ManualClock(); var zone = new Zone(Environment.prod, RegionName.from("us-east-3")); - var flagSource = new InMemoryFlagSource(); nodeRepository = new NodeRepository(flavors, new EmptyProvisionServiceProvider(), new MockCurator(), clock, zone, - new Exclusivity(zone, flagSource), + new Exclusivity(zone, SharedHosts.empty()), new MockNameResolver().mockAnyLookup(), DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), Optional.empty(), Optional.empty(), - flagSource, + new InMemoryFlagSource(), new MemoryMetricsDb(clock), new OrchestratorMock(), true, 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 78a34326949..3a9d03ed6b5 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 @@ -16,6 +16,7 @@ import com.yahoo.config.provision.NodeResources.DiskSpeed; import com.yahoo.config.provision.NodeResources.StorageType; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.flags.InMemoryFlagSource; @@ -207,9 +208,8 @@ public class DynamicProvisioningTest { private void assertHostSharing(Environment environment, ClusterSpec.Type clusterType, boolean expectShared) { Zone zone = new Zone(Cloud.builder().dynamicProvisioning(true).allowHostSharing(false).build(), SystemName.Public, environment, RegionName.defaultName()); MockHostProvisioner hostProvisioner = new MockHostProvisioner(new NodeFlavors(ProvisioningTester.createConfig()).getFlavors(), nameResolver, 0); - ProvisioningTester tester = new ProvisioningTester.Builder().zone(zone).hostProvisioner(hostProvisioner).nameResolver(nameResolver).build(); + ProvisioningTester tester = new ProvisioningTester.Builder().zone(zone).hostProvisioner(hostProvisioner).nameResolver(nameResolver).sharedHosts(SharedHosts.ofConstant(true, false)).build(); tester.makeReadyHosts(2, new NodeResources(12, 12, 200, 12)); - tester.flagSource().withJacksonFlag(PermanentFlags.SHARED_HOST.id(), new SharedHost(List.of(new HostResources(4.0, 16.0, 50.0, 0.3, "fast", "local", null, 10, "x86_64"))), SharedHost.class); ApplicationId application = applicationId(); ClusterSpec cluster = ClusterSpec.request(clusterType, ClusterSpec.Id.from("default")).vespaVersion("6.42").build(); 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 45004ad41ec..4cfb366f7d5 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 @@ -11,6 +11,7 @@ import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.Zone; import com.yahoo.test.ManualClock; import com.yahoo.transaction.Mutex; @@ -52,16 +53,15 @@ public class DynamicProvisioningTester { private final ProvisioningTester provisioningTester; private final Autoscaler autoscaler; private final HostResourcesCalculator hostResourcesCalculator; - private final CapacityPolicies capacityPolicies; - public DynamicProvisioningTester(Zone zone, HostResourcesCalculator resourcesCalculator, List hostFlavors, InMemoryFlagSource flagSource, int hostCount) { - this(zone, hostFlavors, resourcesCalculator, flagSource); + public DynamicProvisioningTester(Zone zone, HostResourcesCalculator resourcesCalculator, List hostFlavors, InMemoryFlagSource flagSource, SharedHosts sharedHosts, int hostCount) { + this(zone, hostFlavors, resourcesCalculator, flagSource, sharedHosts); for (Flavor flavor : hostFlavors) provisioningTester.makeReadyNodes(hostCount, flavor.name(), NodeType.host, 8); provisioningTester.activateTenantHosts(); } - private DynamicProvisioningTester(Zone zone, List flavors, HostResourcesCalculator resourcesCalculator, InMemoryFlagSource flagSource) { + private DynamicProvisioningTester(Zone zone, List flavors, HostResourcesCalculator resourcesCalculator, InMemoryFlagSource flagSource, SharedHosts sharedHosts) { MockHostProvisioner hostProvisioner = null; if (zone.cloud().dynamicProvisioning()) { hostProvisioner = new MockHostProvisioner(flavors); @@ -74,11 +74,11 @@ public class DynamicProvisioningTester { .resourcesCalculator(resourcesCalculator) .flagSource(flagSource) .hostProvisioner(hostProvisioner) + .sharedHosts(sharedHosts) .build(); hostResourcesCalculator = resourcesCalculator; autoscaler = new Autoscaler(nodeRepository()); - capacityPolicies = new CapacityPolicies(zone, provisioningTester.nodeRepository().exclusivity(), flagSource); } public InMemoryProvisionLogger provisionLogger() { return provisioningTester.provisionLogger(); } @@ -159,7 +159,8 @@ public class DynamicProvisioningTester { } public Autoscaling autoscale(ApplicationId applicationId, ClusterSpec cluster, Capacity capacity) { - capacity = capacityPolicies.applyOn(capacity, applicationId, capacityPolicies.decideExclusivity(capacity, cluster).isExclusive()); + var capacityPolicies = provisioningTester.nodeRepository().capacityPoliciesFor(applicationId); + capacity = capacityPolicies.applyOn(capacity, 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)) { 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 8b49e5e5223..390da7c719a 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 @@ -26,6 +26,7 @@ import com.yahoo.config.provision.NodeResources.DiskSpeed; import com.yahoo.config.provision.NodeResources.StorageType; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.SharedHosts; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; @@ -94,7 +95,6 @@ public class ProvisioningTester { private final NodeRepository nodeRepository; private final HostProvisioner hostProvisioner; private final NodeRepositoryProvisioner provisioner; - private final CapacityPolicies capacityPolicies; private final InMemoryProvisionLogger provisionLogger; private final LoadBalancerServiceMock loadBalancerService; @@ -112,7 +112,8 @@ public class ProvisioningTester { LoadBalancerServiceMock loadBalancerService, FlagSource flagSource, int spareCount, - ManualClock clock) { + ManualClock clock, + SharedHosts sharedHosts) { this.curator = curator; this.nodeFlavors = nodeFlavors; this.clock = clock; @@ -123,7 +124,7 @@ public class ProvisioningTester { curator, clock, zone, - new Exclusivity(zone, flagSource), + new Exclusivity(zone, sharedHosts), nameResolver, containerImage, Optional.empty(), @@ -134,7 +135,6 @@ public class ProvisioningTester { true, spareCount); this.provisioner = new NodeRepositoryProvisioner(nodeRepository, zone, provisionServiceProvider, new MockMetric()); - this.capacityPolicies = new CapacityPolicies(zone, nodeRepository.exclusivity(), flagSource); this.provisionLogger = new InMemoryProvisionLogger(); this.loadBalancerService = loadBalancerService; } @@ -162,14 +162,13 @@ public class ProvisioningTester { public NodeRepositoryProvisioner provisioner() { return provisioner; } public HostProvisioner hostProvisioner() { return hostProvisioner; } public LoadBalancerServiceMock loadBalancerService() { return loadBalancerService; } - 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) { - return capacityPolicies.applyOn(capacity, application, false).minResources().nodes(); + return nodeRepository.capacityPoliciesFor(application).applyOn(capacity, false).minResources().nodes(); } public Node patchNode(Node node, UnaryOperator patcher) { @@ -664,6 +663,7 @@ public class ProvisioningTester { private int spareCount = 0; private ManualClock clock = new ManualClock(); private DockerImage defaultImage = DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"); + private SharedHosts sharedHosts = SharedHosts.empty(); public Builder curator(Curator curator) { this.curator = curator; @@ -745,6 +745,11 @@ public class ProvisioningTester { return this; } + public Builder sharedHosts(SharedHosts sharedHosts) { + this.sharedHosts = sharedHosts; + return this; + } + private FlagSource defaultFlagSource() { return new InMemoryFlagSource(); } @@ -761,7 +766,8 @@ public class ProvisioningTester { new LoadBalancerServiceMock(), Optional.ofNullable(flagSource).orElse(defaultFlagSource()), spareCount, - clock); + clock, + sharedHosts); } private static FlavorsConfig asConfig(List flavors) { diff --git a/standalone-container/pom.xml b/standalone-container/pom.xml index b8379fc8ef5..92faa1ae670 100644 --- a/standalone-container/pom.xml +++ b/standalone-container/pom.xml @@ -55,12 +55,6 @@ ${project.version} provided - - com.yahoo.vespa - flags - ${project.version} - provided - com.yahoo.vespa zkfacade @@ -105,7 +99,6 @@ config-bundle-jar-with-dependencies.jar, config-model-api-jar-with-dependencies.jar, config-model-jar-with-dependencies.jar, - flags-jar-with-dependencies.jar, container-disc-jar-with-dependencies.jar, -- cgit v1.2.3