diff options
author | Harald Musum <musum@verizonmedia.com> | 2020-05-12 07:18:29 +0200 |
---|---|---|
committer | Harald Musum <musum@verizonmedia.com> | 2020-05-12 07:18:29 +0200 |
commit | 26fa530aedff254dc8871f7395b54c8d3487f336 (patch) | |
tree | 15554afef8d9f5884b5998a19147ffe927017f8c /configserver | |
parent | 3da1c0480f2f12e63abee601ba630f42e966e6de (diff) |
Distribute application package to other config servers
Diffstat (limited to 'configserver')
5 files changed, 43 insertions, 35 deletions
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 b8e7d68ea5e..fb2ba9324e8 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 @@ -6,6 +6,7 @@ import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.api.ConfigDefinitionRepo; +import com.yahoo.config.model.api.HostInfo; import com.yahoo.config.model.api.HostProvisioner; import com.yahoo.config.model.api.Model; import com.yahoo.config.model.api.ModelContext; @@ -22,13 +23,12 @@ import com.yahoo.config.provision.DockerImage; import java.util.logging.Level; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider; import com.yahoo.vespa.config.server.host.HostValidator; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.deploy.ModelContextImpl; -import com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.provision.StaticProvisioner; -import com.yahoo.vespa.config.server.session.FileDistributionFactory; import com.yahoo.vespa.config.server.session.PrepareParams; import com.yahoo.vespa.config.server.session.SessionContext; @@ -52,14 +52,14 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P private final SessionContext context; private final DeployLogger logger; private final PrepareParams params; - private final FileDistributionFactory fileDistributionFactory; + private final FileDistributionProvider fileDistributionProvider; private final Optional<ApplicationSet> currentActiveApplicationSet; private final ModelContext.Properties properties; public PreparedModelsBuilder(ModelFactoryRegistry modelFactoryRegistry, PermanentApplicationPackage permanentApplicationPackage, ConfigDefinitionRepo configDefinitionRepo, - FileDistributionFactory fileDistributionFactory, + FileDistributionProvider fileDistributionProvider, HostProvisionerProvider hostProvisionerProvider, SessionContext context, DeployLogger logger, @@ -70,14 +70,11 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P super(modelFactoryRegistry, configserverConfig, properties.zone(), hostProvisionerProvider); this.permanentApplicationPackage = permanentApplicationPackage; this.configDefinitionRepo = configDefinitionRepo; - - this.fileDistributionFactory = fileDistributionFactory; - + this.fileDistributionProvider = fileDistributionProvider; this.context = context; this.logger = logger; this.params = params; this.currentActiveApplicationSet = currentActiveApplicationSet; - this.properties = properties; } @@ -91,7 +88,6 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P Instant now) { Version modelVersion = modelFactory.version(); log.log(Level.FINE, "Building model " + modelVersion + " for " + applicationId); - FileDistributionProvider fileDistributionProvider = fileDistributionFactory.createProvider(context.getServerDBSessionDir()); // Use empty on non-hosted systems, use already allocated hosts if available, create connection to a host provisioner otherwise Provisioned provisioned = new Provisioned(); @@ -120,7 +116,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P } private Optional<Model> modelOf(Version version) { - if ( ! currentActiveApplicationSet.isPresent()) return Optional.empty(); + if (currentActiveApplicationSet.isEmpty()) return Optional.empty(); return currentActiveApplicationSet.get().get(version).map(Application::getModel); } @@ -130,12 +126,12 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P Provisioned provisioned) { Optional<HostProvisioner> nodeRepositoryProvisioner = createNodeRepositoryProvisioner(properties.applicationId(), provisioned); - if ( ! allocatedHosts.isPresent()) return nodeRepositoryProvisioner; + if (allocatedHosts.isEmpty()) return nodeRepositoryProvisioner; Optional<HostProvisioner> staticProvisioner = createStaticProvisioner(allocatedHosts, properties.applicationId(), provisioned); - if ( ! staticProvisioner.isPresent()) return Optional.empty(); // Since we have hosts allocated this means we are on non-hosted + if (staticProvisioner.isEmpty()) return Optional.empty(); // Since we have hosts allocated this means we are on non-hosted // Nodes are already allocated by a model and we should use them unless this model requests hosts from a // previously unallocated cluster. This allows future models to stop allocate certain clusters. @@ -153,7 +149,8 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P } private void validateModelHosts(HostValidator<ApplicationId> hostValidator, ApplicationId applicationId, Model model) { - hostValidator.verifyHosts(applicationId, model.getHosts().stream().map(hostInfo -> hostInfo.getHostname()) + hostValidator.verifyHosts(applicationId, model.getHosts().stream() + .map(HostInfo::getHostname) .collect(Collectors.toList())); } @@ -162,11 +159,11 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P public final Version version; public final Model model; - public final FileDistributionProvider fileDistributionProvider; + public final com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider fileDistributionProvider; public final List<ConfigChangeAction> actions; public PreparedModelResult(Version version, Model model, - FileDistributionProvider fileDistributionProvider, List<ConfigChangeAction> actions) { + com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider fileDistributionProvider, List<ConfigChangeAction> actions) { this.version = version; this.model = model; this.fileDistributionProvider = fileDistributionProvider; 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 00cafb77f6d..c882f10ab68 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 @@ -7,12 +7,14 @@ import com.google.inject.Inject; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.component.Version; import com.yahoo.component.Vtag; +import com.yahoo.config.FileReference; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.application.api.FileRegistry; import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.model.api.ContainerEndpoint; import com.yahoo.config.model.api.EndpointCertificateMetadata; +import com.yahoo.config.model.api.FileDistribution; import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.model.api.EndpointCertificateSecrets; import com.yahoo.config.provision.AllocatedHosts; @@ -23,6 +25,7 @@ import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.Zone; import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.lang.SettableOptional; + import java.util.logging.Level; import com.yahoo.path.Path; import com.yahoo.vespa.config.server.ConfigServerSpec; @@ -31,6 +34,7 @@ import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.deploy.ModelContextImpl; import com.yahoo.vespa.config.server.deploy.ZooKeeperDeployer; +import com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider; import com.yahoo.vespa.config.server.http.InvalidApplicationException; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.modelfactory.PreparedModelsBuilder; @@ -112,6 +116,7 @@ public class SessionPreparer { Optional<ApplicationSet> currentActiveApplicationSet, Path tenantPath, Instant now) { Preparation preparation = new Preparation(context, logger, params, currentActiveApplicationSet, tenantPath); + preparation.distributeApplicationPackage(); preparation.preprocess(); try { AllocatedHosts allocatedHosts = preparation.buildModels(now); @@ -161,6 +166,7 @@ public class SessionPreparer { private PrepareResult prepareResult; private final PreparedModelsBuilder preparedModelsBuilder; + private final FileDistributionProvider fileDistributionProvider; Preparation(SessionContext context, DeployLogger logger, PrepareParams params, Optional<ApplicationSet> currentActiveApplicationSet, Path tenantPath) { @@ -169,24 +175,19 @@ public class SessionPreparer { this.params = params; this.currentActiveApplicationSet = currentActiveApplicationSet; this.tenantPath = tenantPath; - this.applicationId = params.getApplicationId(); this.dockerImageRepository = params.dockerImageRepository(); this.vespaVersion = params.vespaVersion().orElse(Vtag.currentVersion); this.containerEndpoints = new ContainerEndpointsCache(tenantPath, curator); this.endpointCertificateMetadataStore = new EndpointCertificateMetadataStore(curator, tenantPath); this.endpointCertificateRetriever = new EndpointCertificateRetriever(secretStore); - this.endpointCertificateMetadata = params.endpointCertificateMetadata() .or(() -> params.tlsSecretsKeyName().map(EndpointCertificateMetadataSerializer::fromString)); - endpointCertificateSecrets = endpointCertificateMetadata .or(() -> endpointCertificateMetadataStore.readEndpointCertificateMetadata(applicationId)) .flatMap(endpointCertificateRetriever::readEndpointCertificateSecrets); - this.endpointsSet = getEndpoints(params.containerEndpoints()); this.athenzDomain = params.athenzDomain(); - this.properties = new ModelContextImpl.Properties(params.getApplicationId(), configserverConfig.multitenant(), ConfigServerSpec.fromConfig(configserverConfig), @@ -197,14 +198,15 @@ public class SessionPreparer { zone, endpointsSet, params.isBootstrap(), - ! currentActiveApplicationSet.isPresent(), + currentActiveApplicationSet.isEmpty(), context.getFlagSource(), endpointCertificateSecrets, athenzDomain); + this.fileDistributionProvider = fileDistributionFactory.createProvider(context.getServerDBSessionDir()); this.preparedModelsBuilder = new PreparedModelsBuilder(modelFactoryRegistry, permanentApplicationPackage, configDefinitionRepo, - fileDistributionFactory, + fileDistributionProvider, hostProvisionerProvider, context, logger, @@ -221,6 +223,16 @@ public class SessionPreparer { } } + void distributeApplicationPackage() { + FileRegistry fileRegistry = fileDistributionProvider.getFileRegistry(); + FileReference fileReference = fileRegistry.addFile(""); + FileDistribution fileDistribution = fileDistributionProvider.getFileDistribution(); + log.log(Level.INFO, "Distribute application package for " + applicationId + " (" + fileReference + ") to other config servers"); + properties.configServerSpecs().stream() + .filter(spec -> ! spec.getHostName().equals(fileRegistry.fileSourceHost())) + .forEach(spec -> fileDistribution.startDownload(spec.getHostName(), spec.getConfigServerPort(), Set.of(fileReference))); + } + void preprocess() { try { this.applicationPackage = context.getApplicationPackage().preprocess(properties.zone(), logger); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java index a304f74858b..d73dc7c8a35 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java @@ -50,7 +50,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry { private final TenantListener tenantListener; private final PermanentApplicationPackage permanentApplicationPackage; private final HostRegistries hostRegistries; - private final FileDistributionFactory fileDistributionFactory; + private final FileDistributionFactory fileDistributionProvider; private final ModelFactoryRegistry modelFactoryRegistry; private final Optional<Provisioner> hostProvisioner; private final Zone zone; @@ -63,7 +63,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry { private TestComponentRegistry(Curator curator, ConfigCurator configCurator, Metrics metrics, ModelFactoryRegistry modelFactoryRegistry, PermanentApplicationPackage permanentApplicationPackage, - FileDistributionFactory fileDistributionFactory, + FileDistributionFactory fileDistributionProvider, HostRegistries hostRegistries, ConfigserverConfig configserverConfig, SessionPreparer sessionPreparer, @@ -83,7 +83,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry { this.defRepo = defRepo; this.permanentApplicationPackage = permanentApplicationPackage; this.hostRegistries = hostRegistries; - this.fileDistributionFactory = fileDistributionFactory; + this.fileDistributionProvider = fileDistributionProvider; this.modelFactoryRegistry = modelFactoryRegistry; this.hostProvisioner = hostProvisioner; this.sessionPreparer = sessionPreparer; @@ -158,17 +158,17 @@ public class TestComponentRegistry implements GlobalComponentRegistry { public TestComponentRegistry build() { final PermanentApplicationPackage permApp = this.permanentApplicationPackage .orElse(new PermanentApplicationPackage(configserverConfig)); - FileDistributionFactory fileDistributionFactory = this.fileDistributionFactory + FileDistributionFactory fileDistributionProvider = this.fileDistributionFactory .orElse(new MockFileDistributionFactory(configserverConfig)); HostProvisionerProvider hostProvisionerProvider = hostProvisioner. map(HostProvisionerProvider::withProvisioner).orElseGet(HostProvisionerProvider::empty); SecretStore secretStore = new MockSecretStore(); - SessionPreparer sessionPreparer = new SessionPreparer(modelFactoryRegistry, fileDistributionFactory, + SessionPreparer sessionPreparer = new SessionPreparer(modelFactoryRegistry, fileDistributionProvider, hostProvisionerProvider, permApp, configserverConfig, defRepo, curator, zone, new InMemoryFlagSource(), secretStore); return new TestComponentRegistry(curator, ConfigCurator.create(curator), metrics, modelFactoryRegistry, - permApp, fileDistributionFactory, hostRegistries, configserverConfig, + permApp, fileDistributionProvider, hostRegistries, configserverConfig, sessionPreparer, hostProvisioner, defRepo, reloadListener, tenantListener, zone, clock, secretStore); } @@ -227,6 +227,6 @@ public class TestComponentRegistry implements GlobalComponentRegistry { return secretStore; } - public FileDistributionFactory getFileDistributionFactory() { return fileDistributionFactory; } + public FileDistributionFactory getFileDistributionProvider() { return fileDistributionProvider; } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockFileDistributionFactory.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockFileDistributionFactory.java index e1874c622c2..ae626499d30 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockFileDistributionFactory.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockFileDistributionFactory.java @@ -2,7 +2,6 @@ package com.yahoo.vespa.config.server.session; import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider; import com.yahoo.vespa.config.server.filedistribution.MockFileDistributionProvider; import java.io.File; @@ -20,7 +19,7 @@ public class MockFileDistributionFactory extends FileDistributionFactory { } @Override - public FileDistributionProvider createProvider(File applicationFile) { + public com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider createProvider(File applicationFile) { return mockFileDistributionProvider; } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java index cdf57b68814..2657f4b46e3 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java @@ -104,7 +104,7 @@ public class SessionPreparerTest { curator = new MockCurator(); configCurator = ConfigCurator.create(curator); componentRegistry = new TestComponentRegistry.Builder().curator(curator).build(); - fileDistributionFactory = (MockFileDistributionFactory)componentRegistry.getFileDistributionFactory(); + fileDistributionFactory = (MockFileDistributionFactory)componentRegistry.getFileDistributionProvider(); preparer = createPreparer(); } @@ -122,7 +122,7 @@ public class SessionPreparerTest { HostProvisionerProvider hostProvisionerProvider) { return new SessionPreparer( modelFactoryRegistry, - componentRegistry.getFileDistributionFactory(), + componentRegistry.getFileDistributionProvider(), hostProvisionerProvider, new PermanentApplicationPackage(componentRegistry.getConfigserverConfig()), componentRegistry.getConfigserverConfig(), @@ -152,13 +152,13 @@ public class SessionPreparerTest { @Test public void require_that_filedistribution_is_ignored_on_dryrun() throws IOException { prepare(testApp, new PrepareParams.Builder().dryRun(true).timeoutBudget(TimeoutBudgetTest.day()).build()); - assertThat(fileDistributionFactory.mockFileDistributionProvider.timesCalled, is(0)); + assertThat(fileDistributionFactory.mockFileDistributionProvider.timesCalled, is(0 + 1)); // App is distributed to other config servers } @Test public void require_that_application_is_prepared() throws Exception { prepare(testApp); - assertThat(fileDistributionFactory.mockFileDistributionProvider.timesCalled, is(1)); // Only builds the newest version + assertThat(fileDistributionFactory.mockFileDistributionProvider.timesCalled, is(1 + 1)); // Only builds the newest version, + 1 because app is distributed to other config servers assertTrue(configCurator.exists(sessionsPath.append(ConfigCurator.USERAPP_ZK_SUBPATH).append("services.xml").getAbsolute())); } |