diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-08-28 11:36:17 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-08-28 11:36:17 +0200 |
commit | 7f823af00d35de249501b6c4e00e89ad862ef787 (patch) | |
tree | eefad75d79a64e4d9255b63e3763510912f5c659 | |
parent | fc2f74f461fe2a049f3c7c362f83b48c0d3ae68b (diff) |
Allocation consistency between model versions
20 files changed, 121 insertions, 76 deletions
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 215aa6c2f7f..1f52d9db818 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 @@ -34,7 +34,7 @@ import java.util.logging.Logger; /** * Factory for creating {@link VespaModel} instances. * - * @author lulf + * @author Ulf Lilleengen */ public class VespaModelFactory implements ModelFactory { diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java index 4506f52e085..a09e198dbf1 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java @@ -9,6 +9,7 @@ import com.yahoo.slime.Slime; import com.yahoo.vespa.config.SlimeUtils; import java.io.IOException; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Optional; diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java index 980cd4a00b9..6be1d49ebd3 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java @@ -9,8 +9,7 @@ import java.util.List; /** * Interface used by the config system to acquire hosts. * - * @author lulf - * @since 5.11 + * @author Ulf Lilleengen */ public interface Provisioner { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java index 1bda8dcb69a..4f26cfa265b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java @@ -19,8 +19,7 @@ import java.util.Optional; /** * Interface representing all global config server components used within the config server. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public interface GlobalComponentRegistry { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java index f88a0ef1a2d..fa5224732f6 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java @@ -22,8 +22,7 @@ import java.util.Optional; /** * Registry containing all the "static"/"global" components in a config server in one place. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public class InjectedGlobalComponentRegistry implements GlobalComponentRegistry { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java index 94abbc10046..0435c8e59db 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java @@ -9,8 +9,7 @@ import java.util.List; /** * The applications of a tenant * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public interface TenantApplications { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java index ac318aba8e8..5260dd9228c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java @@ -29,8 +29,7 @@ import java.util.logging.Logger; * Each application is stored as a single file, named the same as the application id and containing the id * of the session storing the content of the application. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ // TODO: Merge into interface and separate out curator layer instead public class ZKTenantApplications implements TenantApplications, PathChildrenCacheListener { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java index 86187a08d17..3c26ce1b76b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java @@ -48,7 +48,6 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { private final long appGeneration; private final SessionZooKeeperClient zkClient; private final Optional<PermanentApplicationPackage> permanentApplicationPackage; - private final Optional<com.yahoo.config.provision.Provisioner> hostProvisioner; private final ConfigserverConfig configserverConfig; private final ConfigDefinitionRepo configDefinitionRepo; private final Metrics metrics; @@ -57,7 +56,8 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { private final DeployLogger logger; public ActivatedModelsBuilder(TenantName tenant, long appGeneration, SessionZooKeeperClient zkClient, GlobalComponentRegistry globalComponentRegistry) { - super(globalComponentRegistry.getModelFactoryRegistry()); + super(globalComponentRegistry.getModelFactoryRegistry(), + globalComponentRegistry.getHostProvisioner().isPresent()); this.tenant = tenant; this.appGeneration = appGeneration; this.zkClient = zkClient; @@ -65,7 +65,6 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { this.configserverConfig = globalComponentRegistry.getConfigserverConfig(); this.configDefinitionRepo = globalComponentRegistry.getConfigDefinitionRepo(); this.metrics = globalComponentRegistry.getMetrics(); - this.hostProvisioner = globalComponentRegistry.getHostProvisioner(); this.curator = globalComponentRegistry.getCurator(); this.zone = globalComponentRegistry.getZone(); this.logger = new SilentDeployLogger(); @@ -76,6 +75,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { ApplicationPackage applicationPackage, ApplicationId applicationId, com.yahoo.component.Version wantedNodeVespaVersion, + SettableOptional<ProvisionInfo> ignored, // Ignored since we have this in the app package for activated models Instant now) { log.log(LogLevel.DEBUG, String.format("Loading model version %s for session %s application %s", modelFactory.getVersion(), appGeneration, applicationId)); @@ -97,17 +97,6 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { applicationMetricUpdater, applicationId); } - private Optional<HostProvisioner> createHostProvisioner(Optional<ProvisionInfo> provisionInfo) { - if (hostProvisioner.isPresent() && provisionInfo.isPresent()) { - return Optional.of(createStaticProvisioner(provisionInfo.get())); - } - return Optional.empty(); - } - - private HostProvisioner createStaticProvisioner(ProvisionInfo provisionInfo) { - return new StaticProvisioner(provisionInfo); - } - private static <T> Optional<T> getForVersionOrLatest(Map<Version, T> map, Version version) { if (map.isEmpty()) { return Optional.empty(); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java index ab1c84eb5dd..1c2c9c731d1 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java @@ -13,7 +13,7 @@ import java.util.*; * A registry of model factories. Allows querying for a specific version of a {@link ModelFactory} or * simply returning all of them. Keeps track of the latest {@link com.yahoo.config.provision.Version} supported. * - * @author lulf + * @author Ulf Lilleengen */ public class ModelFactoryRegistry { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java index 509a26370ff..84316d0688a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java @@ -3,16 +3,20 @@ package com.yahoo.vespa.config.server.modelfactory; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.config.application.api.ApplicationPackage; +import com.yahoo.config.model.api.HostProvisioner; import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.model.api.ModelFactory; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.OutOfCapacityException; +import com.yahoo.config.provision.ProvisionInfo; +import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.Rotation; import com.yahoo.config.provision.Version; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.server.ConfigServerSpec; import com.yahoo.vespa.config.server.deploy.ModelContextImpl; import com.yahoo.vespa.config.server.http.UnknownVespaVersionException; +import com.yahoo.vespa.config.server.provision.StaticProvisioner; import java.time.Instant; import java.util.ArrayList; @@ -38,8 +42,12 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { private final ModelFactoryRegistry modelFactoryRegistry; - protected ModelsBuilder(ModelFactoryRegistry modelFactoryRegistry) { + /** True if we are running in hosted mode */ + private final boolean hosted; + + protected ModelsBuilder(ModelFactoryRegistry modelFactoryRegistry, boolean hosted) { this.modelFactoryRegistry = modelFactoryRegistry; + this.hosted = hosted; } public List<MODELRESULT> buildModels(ApplicationId applicationId, @@ -53,7 +61,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { if (requestedMajorVersion.isPresent()) versions = filterByMajorVersion(requestedMajorVersion.get(), versions); - // Load models by one major version at the time as new major versions are allowed to be unloadable + // Load models by one major version at the time as new major versions are allowed to be non-loadable // in the case where an existing application is incompatible with a new major version // (which is possible by the definition of major) List<Integer> majorVersions = versions.stream() @@ -62,11 +70,14 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); + // The newest version (major and minor) (which is loaded first) decides the allocated hosts + SettableOptional<ProvisionInfo> allocatedHosts = new SettableOptional(); List<MODELRESULT> allApplicationModels = new ArrayList<>(); for (int i = 0; i < majorVersions.size(); i++) { try { allApplicationModels.addAll(buildModelVersion(filterByMajorVersion(majorVersions.get(i), versions), - applicationId, wantedNodeVespaVersion, applicationPackage, now)); + applicationId, wantedNodeVespaVersion, applicationPackage, + allocatedHosts, now)); // skip old config models if requested after we have found a major version which works if (allApplicationModels.size() > 0 && allApplicationModels.get(0).getModel().skipOldConfigModels(now)) @@ -92,6 +103,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { private List<MODELRESULT> buildModelVersion(Set<Version> versions, ApplicationId applicationId, com.yahoo.component.Version wantedNodeVespaVersion, ApplicationPackage applicationPackage, + SettableOptional<ProvisionInfo> allocatedHosts, Instant now) { Version latest = findLatest(versions); // load latest application version @@ -99,23 +111,33 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { applicationPackage, applicationId, wantedNodeVespaVersion, + allocatedHosts, now); - if (latestApplicationVersion.getModel().skipOldConfigModels(now)) { + if ( ! allocatedHosts.isPresent()) + allocatedHosts.set(latestApplicationVersion.getModel().provisionInfo()); + + if (latestApplicationVersion.getModel().skipOldConfigModels(now)) return Collections.singletonList(latestApplicationVersion); + + // load old model versions + List<MODELRESULT> allApplicationVersions = new ArrayList<>(); + allApplicationVersions.add(latestApplicationVersion); + + // TODO: We use the allocated hosts from the newest version when building older model versions. + // This is correct except for the case where an old model specifies a cluster which the new version + // does not. In that case we really want to extend the set of allocated hosts to include those of that + // cluster as well. To do that, create a new provisioner which uses static provisioning for known + // clusters and the node repository provisioner as fallback. + for (Version version : versions) { + if (version.equals(latest)) continue; // already loaded + allApplicationVersions.add(buildModelVersion(modelFactoryRegistry.getFactory(version), + applicationPackage, + applicationId, + wantedNodeVespaVersion, + allocatedHosts, + now)); } - else { // load old model versions - List<MODELRESULT> allApplicationVersions = new ArrayList<>(); - allApplicationVersions.add(latestApplicationVersion); - for (Version version : versions) { - if (version.equals(latest)) continue; // already loaded - allApplicationVersions.add(buildModelVersion(modelFactoryRegistry.getFactory(version), - applicationPackage, - applicationId, - wantedNodeVespaVersion, - now)); - } - return allApplicationVersions; - } + return allApplicationVersions; } private Set<Version> filterByMajorVersion(int majorVersion, Set<Version> versions) { @@ -134,6 +156,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { protected abstract MODELRESULT buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage, ApplicationId applicationId, com.yahoo.component.Version wantedNodeVespaVersion, + SettableOptional<ProvisionInfo> allocatedHosts, Instant now); protected ModelContext.Properties createModelContextProperties(ApplicationId applicationId, @@ -148,4 +171,41 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { rotations); } + /** + * Returns a host provisioner returning the previously allocated hosts if available and when on hosted Vespa, + * returns empty otherwise. + */ + protected Optional<HostProvisioner> createHostProvisioner(Optional<ProvisionInfo> provisionInfo) { + if (hosted && provisionInfo.isPresent()) + return Optional.of(new StaticProvisioner(provisionInfo.get())); + return Optional.empty(); + } + + /** An optional which contains a settable value */ + protected static final class SettableOptional<T> { + + private T value = null; + + /** Creates a new empty settable optional */ + private SettableOptional() {} + + /** Creates a new settable optional with the given value */ + private SettableOptional(T value) { this.value = value; } + + public boolean isPresent() { + return value != null; + } + + public T get() { + if (value == null) + throw new NoSuchElementException("No value present"); + return value; + } + + public void set(T value) { + this.value = value; + } + + } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java index 98741c631b1..27de7f2b2e1 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java @@ -13,6 +13,7 @@ import com.yahoo.config.model.api.ModelCreateResult; import com.yahoo.config.model.api.ModelFactory; import com.yahoo.config.model.application.provider.FilesApplicationPackage; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ProvisionInfo; import com.yahoo.config.provision.Version; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.server.application.ApplicationSet; @@ -61,7 +62,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P PrepareParams params, Optional<ApplicationSet> currentActiveApplicationSet, ModelContext.Properties properties) { - super(modelFactoryRegistry); + super(modelFactoryRegistry, properties.hostedVespa()); this.permanentApplicationPackage = permanentApplicationPackage; this.configDefinitionRepo = configDefinitionRepo; @@ -80,14 +81,19 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P protected PreparedModelResult buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage, ApplicationId applicationId, - com.yahoo.component.Version wantedNodeVespaVersion, Instant now) { + com.yahoo.component.Version wantedNodeVespaVersion, + SettableOptional<ProvisionInfo> activatedHosts, + Instant now) { Version modelVersion = modelFactory.getVersion(); log.log(LogLevel.DEBUG, "Start building model for Vespa version " + modelVersion); FileDistributionProvider fileDistributionProvider = fileDistributionFactory.createProvider( context.getServerDBSessionDir(), applicationId); - Optional<HostProvisioner> hostProvisioner = createHostProvisionerAdapter(properties); + // Use already allocated hosts if available, create connection to a host provisioner otherwise + Optional<HostProvisioner> hostProvisioner = + activatedHosts.isPresent() ? createHostProvisioner(Optional.of(activatedHosts.get())) : + createHostProvisionerAdapter(properties); Optional<Model> previousModel = currentActiveApplicationSet .map(set -> set.getForVersionOrLatest(Optional.of(modelVersion), now).getModel()); ModelContext modelContext = new ModelContextImpl( diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java index 4cf2204c086..32a641a3bc7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java @@ -13,20 +13,18 @@ import java.util.logging.Logger; /** * This class is necessary to support both having and not having a host provisioner. We inject * a component registry here, which then enables us to check whether or not we have a provisioner available. + * We only have a provisioner if we are running in hosted mode. * - * @author lulf + * @author Ulf Lilleengen */ public class HostProvisionerProvider { - private static final Logger log = Logger.getLogger(HostProvisionerProvider.class.getName()); private final Optional<Provisioner> hostProvisioner; public HostProvisionerProvider(ComponentRegistry<Provisioner> hostProvisionerRegistry, ConfigserverConfig configserverConfig) { if (hostProvisionerRegistry.allComponents().isEmpty() || ! configserverConfig.hostedVespa()) { - log.info("Host provisioner is missing, provisioner component count: " + hostProvisionerRegistry.allComponents().size() + ", is hosted Vespa: " + configserverConfig.hostedVespa()); hostProvisioner = Optional.empty(); } else { - log.log(LogLevel.DEBUG, "Host provisioner injected. Will be used for all deployments"); hostProvisioner = Optional.of(hostProvisionerRegistry.allComponents().get(0)); } } @@ -35,6 +33,7 @@ public class HostProvisionerProvider { this(componentRegistry, new ConfigserverConfig(new ConfigserverConfig.Builder())); } + /** Returns the host provisioner, or empty if we are not in hosted mode */ public Optional<Provisioner> getHostProvisioner() { return hostProvisioner; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java index c20f6e0b853..d5ed84f44f0 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java @@ -19,8 +19,7 @@ import java.util.logging.Logger; * A RemoteSession represents a session created on another config server. This session can * be regarded as read only, and this interface only allows reading information about a session. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public class RemoteSession extends Session { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java index 0f1e65aaf2b..298acaca901 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java @@ -12,8 +12,7 @@ import com.yahoo.vespa.curator.Curator; import java.time.Clock; /** - * @author lulf - * @since 5.1.24 + * @author Ulf Lilleengen */ public class RemoteSessionFactory { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java index a840e5d5a97..323c2667d30 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java @@ -12,8 +12,7 @@ import java.io.File; /** * The dependencies needed for a local session to be edited and prepared. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public class SessionContext { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java index 19651041ea4..c2655d1a1b3 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java @@ -170,7 +170,8 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { defRepo, serverId, nodeFlavors); - SessionContext context = new SessionContext(applicationPackage, sessionZKClient, sessionDir, applicationRepo, hostRegistry, superModelGenerationCounter); + SessionContext context = new SessionContext(applicationPackage, sessionZKClient, sessionDir, applicationRepo, + hostRegistry, superModelGenerationCounter); return new LocalSession(tenant, sessionId, sessionPreparer, context); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java index 3b96069c4e7..3dc0eb4f1b5 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java @@ -252,11 +252,8 @@ public class SessionPreparer { private final ImmutableList<PreparedModelsBuilder.PreparedModelResult> results; - private final ReconciliatedHostAllocations reconciliatedHostAllocations; - public PrepareResult(List<PreparedModelsBuilder.PreparedModelResult> results) { this.results = ImmutableList.copyOf(results); - reconciliatedHostAllocations = new ReconciliatedHostAllocations(results); } /** Returns the results for each model as an immutable list */ @@ -264,7 +261,7 @@ public class SessionPreparer { /** Returns the host allocations resulting from this preparation. */ public ProvisionInfo getProvisionInfo() { - return reconciliatedHostAllocations.allocatedHosts(); + return results.asList().get(0).getModel().provisionInfo(); // All have the same provision info } public Map<Version, FileRegistry> getFileRegistries() { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java index 144bbf10dc6..f4a5e941ac2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java @@ -27,8 +27,7 @@ import java.util.concurrent.Executors; /** * Builder for helping out with tenant creation. Each of a tenants dependencies may be overridden for testing. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public class TenantBuilder { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java index 28bae587e2a..377b3997e43 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java @@ -48,12 +48,12 @@ import java.util.logging.Logger; * Once a tenant is deleted from zookeeper, the zookeeper watcher thread will get notified on all configservers, and * shutdown and delete any per-configserver state. * - * @author vegardh - * @author lulf - * @since 5.1.26 + * @author Vegard Havdal + * @author Ulf Lilleengen */ //TODO Rename to TenantRepository public class Tenants implements ConnectionStateListener, PathChildrenCacheListener { + public static final TenantName HOSTED_VESPA_TENANT = TenantName.from("hosted-vespa"); private static final TenantName DEFAULT_TENANT = TenantName.defaultName(); private static final List<TenantName> SYSTEM_TENANT_NAMES = Arrays.asList( diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java index 4aa4fc32483..7e82b6bf649 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.config.server.zookeeper; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationMetaData; import com.yahoo.config.application.api.ComponentInfo; @@ -11,6 +12,7 @@ import com.yahoo.config.codegen.DefParser; import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.application.provider.*; +import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.ProvisionInfo; import com.yahoo.io.IOUtils; @@ -35,7 +37,7 @@ import java.util.Optional; /** * Represents an application residing in zookeeper. * - * @author tonytv + * @author Tony Vaagenes */ public class ZKApplicationPackage implements ApplicationPackage { @@ -62,7 +64,7 @@ public class ZKApplicationPackage implements ApplicationPackage { Optional<ProvisionInfo> provisionInfo = readProvisionInfo(allocatedHostsPath, nodeFlavors); if ( ! provisionInfo.isPresent()) { // Read from legacy location. TODO: Remove when 6.142 is in production everywhere List<String> provisionInfoByVersionNodes = liveApp.getChildren(allocatedHostsPath); - provisionInfo = newestOf(readProvisionInfosByVersion(provisionInfoByVersionNodes, nodeFlavors)); + provisionInfo = merge(readProvisionInfosByVersion(provisionInfoByVersionNodes, nodeFlavors)); } return provisionInfo; } @@ -79,17 +81,16 @@ public class ZKApplicationPackage implements ApplicationPackage { return provisionInfoMap; } - private Optional<ProvisionInfo> newestOf(Map<Version, ProvisionInfo> provisionInfoMap) { + private Optional<ProvisionInfo> merge(Map<Version, ProvisionInfo> provisionInfoMap) { + // Merge the provision infos in any order. This is wrong but preserves current behavior (modulo order differences) if (provisionInfoMap.isEmpty()) return Optional.empty(); - Version newestVersion = null; - ProvisionInfo newestInfo = null; + + Map<String, HostSpec> merged = new HashMap<>(); for (Map.Entry<Version, ProvisionInfo> entry : provisionInfoMap.entrySet()) { - if (newestVersion == null || newestVersion.isBefore(entry.getKey())) { - newestVersion = entry.getKey(); - newestInfo = entry.getValue(); - } + for (HostSpec host : entry.getValue().getHosts()) + merged.put(host.hostname(), host); } - return Optional.of(newestInfo); + return Optional.of(ProvisionInfo.withHosts(ImmutableSet.copyOf(merged.values()))); } /** |