diff options
Diffstat (limited to 'config-model/src/main')
8 files changed, 159 insertions, 22 deletions
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 c52ea1ef092..070a389b3ac 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 @@ -17,6 +17,7 @@ import com.yahoo.config.model.api.HostProvisioner; import com.yahoo.config.model.api.Model; import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.model.api.Provisioned; +import com.yahoo.config.model.api.Reindexing; import com.yahoo.config.model.api.ValidationParameters; import com.yahoo.config.model.application.provider.BaseDeployLogger; import com.yahoo.config.model.application.provider.MockFileRegistry; @@ -50,6 +51,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -82,6 +84,7 @@ public class DeployState implements ConfigDefinitionStore { private final Instant now; private final HostProvisioner provisioner; private final Provisioned provisioned; + private final Reindexing reindexing; public static DeployState createTestState() { return new Builder().build(); @@ -115,7 +118,8 @@ public class DeployState implements ConfigDefinitionStore { Instant now, Version wantedNodeVespaVersion, boolean accessLoggingEnabledByDefault, - Optional<DockerImage> wantedDockerImageRepo) { + Optional<DockerImage> wantedDockerImageRepo, + Reindexing reindexing) { this.logger = deployLogger; this.fileRegistry = fileRegistry; this.rankProfileRegistry = rankProfileRegistry; @@ -147,6 +151,7 @@ public class DeployState implements ConfigDefinitionStore { this.wantedNodeVespaVersion = wantedNodeVespaVersion; this.now = now; this.wantedDockerImageRepo = wantedDockerImageRepo; + this.reindexing = reindexing; } public static HostProvisioner getDefaultModelHostProvisioner(ApplicationPackage applicationPackage) { @@ -289,6 +294,8 @@ public class DeployState implements ConfigDefinitionStore { } } + public Optional<Reindexing> reindexing() { return Optional.ofNullable(reindexing); } + public static class Builder { private ApplicationPackage applicationPackage = MockApplicationPackage.createEmpty(); @@ -308,6 +315,7 @@ public class DeployState implements ConfigDefinitionStore { private Version wantedNodeVespaVersion = Vtag.currentVersion; private boolean accessLoggingEnabledByDefault = true; private Optional<DockerImage> wantedDockerImageRepo = Optional.empty(); + private Reindexing reindexing = null; public Builder applicationPackage(ApplicationPackage applicationPackage) { this.applicationPackage = applicationPackage; @@ -398,6 +406,8 @@ public class DeployState implements ConfigDefinitionStore { return this; } + public Builder reindexing(Reindexing reindexing) { this.reindexing = Objects.requireNonNull(reindexing); return this; } + public DeployState build() { return build(new ValidationParameters()); } @@ -427,7 +437,8 @@ public class DeployState implements ConfigDefinitionStore { now, wantedNodeVespaVersion, accessLoggingEnabledByDefault, - wantedDockerImageRepo); + wantedDockerImageRepo, + reindexing); } private SearchDocumentModel createSearchDocumentModel(RankProfileRegistry rankProfileRegistry, 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 6a2ba5ed005..c2a4b1f3bbf 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 @@ -154,6 +154,7 @@ public class VespaModelFactory implements ModelFactory { .wantedNodeVespaVersion(modelContext.wantedNodeVespaVersion()) .wantedDockerImageRepo(modelContext.wantedDockerImageRepo()); modelContext.previousModel().ifPresent(builder::previousModel); + modelContext.reindexing().ifPresent(builder::reindexing); return builder.build(validationParameters); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java index 8bd4506aedc..bb2f64daec5 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java @@ -6,6 +6,7 @@ import com.yahoo.component.ComponentSpecification; import com.yahoo.config.model.api.container.ContainerServiceType; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.container.bundle.BundleInstantiationSpecification; +import com.yahoo.container.core.documentapi.DocumentAccessProvider; import com.yahoo.container.di.config.PlatformBundlesConfig; import com.yahoo.osgi.provider.model.ComponentModel; import com.yahoo.vespa.config.content.FleetcontrollerConfig; @@ -14,6 +15,7 @@ import com.yahoo.vespa.model.container.Container; import com.yahoo.vespa.model.container.component.AccessLogComponent; import com.yahoo.vespa.model.container.component.Component; import com.yahoo.vespa.model.container.component.Handler; +import com.yahoo.vespa.model.container.component.SimpleComponent; import com.yahoo.vespa.model.container.component.SystemBindingPattern; import com.yahoo.vespa.model.container.xml.PlatformBundles; @@ -33,7 +35,12 @@ public class ClusterControllerContainer extends Container implements private final Set<String> bundles = new TreeSet<>(); - public ClusterControllerContainer(AbstractConfigProducer parent, int index, boolean runStandaloneZooKeeper, boolean isHosted) { + public ClusterControllerContainer( + AbstractConfigProducer<?> parent, + int index, + boolean runStandaloneZooKeeper, + boolean isHosted, + ReindexingContext reindexingContext) { super(parent, "" + index, index, isHosted); addHandler("clustercontroller-status", "com.yahoo.vespa.clustercontroller.apps.clustercontroller.StatusHandler", @@ -49,6 +56,11 @@ public class ClusterControllerContainer extends Container implements "com.yahoo.vespa.clustercontroller.apps.clustercontroller.StandaloneZooKeeperProvider", CLUSTERCONTROLLER_BUNDLE); } else { + // TODO bjorncs/jonmv: remove extraneous ZooKeeperProvider layer + addComponent( + "clustercontroller-zkrunner", + "com.yahoo.vespa.zookeeper.DummyVespaZooKeeperServer", + new ComponentSpecification("zookeeper-server-common")); addComponent("clustercontroller-zkprovider", "com.yahoo.vespa.clustercontroller.apps.clustercontroller.DummyZooKeeperProvider", CLUSTERCONTROLLER_BUNDLE); @@ -61,6 +73,7 @@ public class ClusterControllerContainer extends Container implements addFileBundle("clustercontroller-core"); addFileBundle("clustercontroller-utils"); addFileBundle("zookeeper-server"); + configureReindexing(reindexingContext); } @Override @@ -101,6 +114,15 @@ public class ClusterControllerContainer extends Container implements addHandler(new Handler(createComponentModel(id, className, CLUSTERCONTROLLER_BUNDLE)), path); } + private void configureReindexing(ReindexingContext context) { + if (context != null) { + addFileBundle(ReindexingController.REINDEXING_CONTROLLER_BUNDLE); + addComponent(new ReindexingController(context)); + addComponent(new SimpleComponent(DocumentAccessProvider.class.getName())); + } + } + + @Override public void getConfig(PlatformBundlesConfig.Builder builder) { bundles.forEach(builder::bundlePaths); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java index 5cee73dff1b..3ee2a840f20 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java @@ -20,6 +20,6 @@ public class ClusterControllerContainerCluster extends ContainerCluster<ClusterC @Override protected void doPrepare(DeployState deployState) { } - protected boolean messageBusEnabled() { return false; } + @Override protected boolean messageBusEnabled() { return false; } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java new file mode 100644 index 00000000000..fdd12088d04 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java @@ -0,0 +1,33 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.model.admin.clustercontroller; + +import com.yahoo.config.model.api.Reindexing; +import com.yahoo.documentmodel.NewDocumentType; + +import java.util.Collection; +import java.util.Objects; + +/** + * Context required to configure automatic reindexing for a given cluster controller cluster (for a given content cluster). + * + * @author bjorncs + */ +public class ReindexingContext { + + private final Reindexing reindexing; + private final String contentClusterName; + private final Collection<NewDocumentType> documentTypes; + + public ReindexingContext( + Reindexing reindexing, + String contentClusterName, + Collection<NewDocumentType> documentTypes) { + this.reindexing = Objects.requireNonNull(reindexing); + this.contentClusterName = Objects.requireNonNull(contentClusterName); + this.documentTypes = Objects.requireNonNull(documentTypes); + } + + public Reindexing reindexing() { return reindexing; } + public String contentClusterName() { return contentClusterName; } + public Collection<NewDocumentType> documentTypes() { return documentTypes; } +} diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingController.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingController.java new file mode 100644 index 00000000000..24909ddbc8d --- /dev/null +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingController.java @@ -0,0 +1,48 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.model.admin.clustercontroller; + +import com.yahoo.config.model.api.Reindexing; +import com.yahoo.container.bundle.BundleInstantiationSpecification; +import com.yahoo.documentmodel.NewDocumentType; +import com.yahoo.osgi.provider.model.ComponentModel; +import com.yahoo.vespa.config.content.reindexing.ReindexingConfig; +import com.yahoo.vespa.model.container.component.SimpleComponent; + +import java.util.Collection; + +/** + * @author bjorncs + */ +class ReindexingController extends SimpleComponent implements ReindexingConfig.Producer { + + static final String REINDEXING_CONTROLLER_BUNDLE = "clustercontroller-reindexer"; + + private final Reindexing reindexing; + private final String contentClusterName; + private final Collection<NewDocumentType> documentTypes; + + ReindexingController(ReindexingContext context) { + super(new ComponentModel( + BundleInstantiationSpecification.getFromStrings( + "reindexing-maintainer", + "ai.vespa.reindexing.ReindexingMaintainer", + REINDEXING_CONTROLLER_BUNDLE))); + this.reindexing = context.reindexing(); + this.contentClusterName = context.contentClusterName(); + this.documentTypes = context.documentTypes(); + } + + @Override + public void getConfig(ReindexingConfig.Builder builder) { + builder.clusterName(contentClusterName); + builder.enabled(reindexing.enabled()); + for (NewDocumentType type : documentTypes) { + String typeName = type.getFullName().getName(); + reindexing.status(contentClusterName, typeName).ifPresent(status -> + builder.status( + typeName, + new ReindexingConfig.Status.Builder() + .readyAtMillis(status.ready().toEpochMilli()))); + } + } +} diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java index 706311dcdbf..3719c8a43a2 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java @@ -7,7 +7,6 @@ import com.yahoo.config.model.api.ConfigServerSpec; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.text.XML; -import java.util.logging.Level; import com.yahoo.vespa.model.SimpleConfigProducer; import com.yahoo.vespa.model.admin.Admin; import com.yahoo.vespa.model.admin.Configserver; @@ -19,8 +18,8 @@ import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainerC import com.yahoo.vespa.model.builder.xml.dom.VespaDomBuilder.DomConfigProducerBuilder; import org.w3c.dom.Element; -import java.util.List; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.logging.Level; @@ -208,7 +207,7 @@ public class DomAdminV2Builder extends DomAdminBuilderBase { @Override protected ClusterControllerContainer doBuild(DeployState deployState, AbstractConfigProducer parent, Element spec) { - return new ClusterControllerContainer(parent, i, runStandaloneZooKeeper, deployState.isHosted()); + return new ClusterControllerContainer(parent, i, runStandaloneZooKeeper, deployState.isHosted(), /*reindexingContext*/null); } } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java index 66a96690dab..16ccbad00c0 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java @@ -5,35 +5,37 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.ConfigModelContext; +import com.yahoo.config.model.api.Reindexing; import com.yahoo.config.model.deploy.DeployState; +import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.config.model.producer.AbstractConfigProducerRoot; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.config.content.MessagetyperouteselectorpolicyConfig; +import com.yahoo.documentapi.messagebus.protocol.DocumentProtocol; +import com.yahoo.documentmodel.NewDocumentType; +import com.yahoo.metrics.MetricsmanagerConfig; +import com.yahoo.vespa.config.content.AllClustersBucketSpacesConfig; import com.yahoo.vespa.config.content.FleetcontrollerConfig; +import com.yahoo.vespa.config.content.MessagetyperouteselectorpolicyConfig; import com.yahoo.vespa.config.content.StorDistributionConfig; -import com.yahoo.vespa.config.content.AllClustersBucketSpacesConfig; import com.yahoo.vespa.config.content.core.BucketspacesConfig; import com.yahoo.vespa.config.content.core.StorDistributormanagerConfig; -import com.yahoo.documentmodel.NewDocumentType; -import com.yahoo.documentapi.messagebus.protocol.DocumentProtocol; -import com.yahoo.metrics.MetricsmanagerConfig; -import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.vespa.model.HostResource; import com.yahoo.vespa.model.Service; import com.yahoo.vespa.model.admin.Admin; -import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainerCluster; -import com.yahoo.vespa.model.admin.monitoring.Monitoring; import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerCluster; import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerComponent; import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerConfigurer; import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainer; +import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainerCluster; +import com.yahoo.vespa.model.admin.clustercontroller.ReindexingContext; +import com.yahoo.vespa.model.admin.monitoring.Monitoring; import com.yahoo.vespa.model.builder.xml.dom.ModelElement; import com.yahoo.vespa.model.builder.xml.dom.NodesSpecification; +import com.yahoo.vespa.model.container.ApplicationContainerCluster; import com.yahoo.vespa.model.container.Container; import com.yahoo.vespa.model.container.ContainerCluster; -import com.yahoo.vespa.model.container.ApplicationContainerCluster; import com.yahoo.vespa.model.container.ContainerModel; import com.yahoo.vespa.model.content.ClusterControllerConfig; import com.yahoo.vespa.model.content.ContentSearch; @@ -163,7 +165,7 @@ public class ContentCluster extends AbstractConfigProducer implements if (context.getParentProducer().getRoot() == null) return c; - addClusterControllers(containers, context, c.rootGroup, contentElement, c.clusterId, c); + addClusterControllers(containers, context, c.rootGroup, contentElement, c.clusterId, c, documentDefinitions); return c; } @@ -278,13 +280,15 @@ public class ContentCluster extends AbstractConfigProducer implements private void addClusterControllers(Collection<ContainerModel> containers, ConfigModelContext context, StorageGroup rootGroup, ModelElement contentElement, - String contentClusterName, ContentCluster contentCluster) { + String contentClusterName, ContentCluster contentCluster, + Map<String, NewDocumentType> documentDefinitions) { if (admin == null) return; // only in tests if (contentCluster.getPersistence() == null) return; ClusterControllerContainerCluster clusterControllers; ContentCluster overlappingCluster = findOverlappingCluster(context.getParentProducer().getRoot(), contentCluster); + if (overlappingCluster != null && overlappingCluster.getClusterControllers() != null) { // Borrow the cluster controllers of the other cluster in this case. // This condition only obtains on non-hosted systems with a shared config server, @@ -299,11 +303,13 @@ public class ContentCluster extends AbstractConfigProducer implements Collection<HostResource> hosts = nodesSpecification.isDedicated() ? getControllerHosts(nodesSpecification, admin, clusterName, context) : drawControllerHosts(nodesSpecification.minResources().nodes(), rootGroup, containers); + ReindexingContext reindexingContext = createReindexingContent(context, contentClusterName, documentDefinitions); clusterControllers = createClusterControllers(new ClusterControllerCluster(contentCluster, "standalone"), hosts, clusterName, true, - context.getDeployState()); + context.getDeployState(), + reindexingContext); contentCluster.clusterControllers = clusterControllers; } else { @@ -314,7 +320,8 @@ public class ContentCluster extends AbstractConfigProducer implements context.getDeployState().getDeployLogger().log(Level.INFO, "When having content cluster(s) and more than 1 config server it is recommended to configure cluster controllers explicitly."); } - clusterControllers = createClusterControllers(admin, hosts, "cluster-controllers", false, context.getDeployState()); + ReindexingContext reindexingContext = createReindexingContent(context, contentClusterName, documentDefinitions); + clusterControllers = createClusterControllers(admin, hosts, "cluster-controllers", false, context.getDeployState(), reindexingContext); admin.setClusterControllers(clusterControllers); } } @@ -322,6 +329,15 @@ public class ContentCluster extends AbstractConfigProducer implements addClusterControllerComponentsForThisCluster(clusterControllers, contentCluster); } + private static ReindexingContext createReindexingContent( + ConfigModelContext ctx, String contentClusterName, Map<String, NewDocumentType> documentDefinitions) { + class DisabledReindexing implements Reindexing {} + Reindexing reindexing = ctx.properties().featureFlags().enableAutomaticReindexing() + ? ctx.getDeployState().reindexing().orElse(new DisabledReindexing()) + : new DisabledReindexing(); + return new ReindexingContext(reindexing, contentClusterName, documentDefinitions.values()); + } + /** Returns any other content cluster which shares nodes with this, or null if none are built */ private ContentCluster findOverlappingCluster(AbstractConfigProducerRoot root, ContentCluster contentCluster) { for (ContentCluster otherContentCluster : root.getChildrenByTypeRecursive(ContentCluster.class)) { @@ -452,14 +468,21 @@ public class ContentCluster extends AbstractConfigProducer implements Collection<HostResource> hosts, String name, boolean multitenant, - DeployState deployState) { + DeployState deployState, + ReindexingContext reindexingContext) { var clusterControllers = new ClusterControllerContainerCluster(parent, name, name, deployState); List<ClusterControllerContainer> containers = new ArrayList<>(); // Add a cluster controller on each config server (there is always at least one). if (clusterControllers.getContainers().isEmpty()) { int index = 0; for (HostResource host : hosts) { - var clusterControllerContainer = new ClusterControllerContainer(clusterControllers, index, multitenant, deployState.isHosted()); + var clusterControllerContainer = + new ClusterControllerContainer( + clusterControllers, + index, + multitenant, + deployState.isHosted(), + reindexingContext); clusterControllerContainer.setHostResource(host); clusterControllerContainer.initService(deployState.getDeployLogger()); clusterControllerContainer.setProp("clustertype", "admin") |