aboutsummaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorgjoranv <gv@verizonmedia.com>2019-04-04 11:00:19 +0200
committergjoranv <gv@verizonmedia.com>2019-05-02 16:14:08 +0200
commit680f2e880caacc040a0e766db890033f0181f6c2 (patch)
tree6d2057b3776f2aa8cd9273de1c3699bff201e2dd /config-model
parent099bde8f27218e97c5da33ce8bde5a796a1c0f5a (diff)
Install metrics-proxy on MetricsProxyContainerClusters.
* Add metrics-proxy dep to config-model. * Install metrics-proxy bundle for MPConatinerClusters. * Add metrics-proxy components and generate configs. * Put node specific components to the Container, not the cluster.
Diffstat (limited to 'config-model')
-rw-r--r--config-model/pom.xml6
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/ConsumersConfigGenerator.java88
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java76
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerCluster.java162
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/VespaServicesConfigGenerator.java46
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/Container.java13
-rwxr-xr-xconfig-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java17
9 files changed, 405 insertions, 7 deletions
diff --git a/config-model/pom.xml b/config-model/pom.xml
index 715718f8bb5..0e5769e64e5 100644
--- a/config-model/pom.xml
+++ b/config-model/pom.xml
@@ -96,6 +96,12 @@
</dependency>
<dependency>
<groupId>com.yahoo.vespa</groupId>
+ <artifactId>metrics-proxy</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
<artifactId>container-disc</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java
index dd27dd176e0..e0956097c84 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java
@@ -207,7 +207,7 @@ public class Admin extends AbstractConfigProducer implements Serializable {
var metricsProxyCluster = new MetricsProxyContainerCluster(this, "metrics", deployState);
int index = 0;
for (var host : hosts) {
- var container = new MetricsProxyContainer(metricsProxyCluster, index++);
+ var container = new MetricsProxyContainer(metricsProxyCluster, index++, deployState.isHosted());
addAndInitializeService(deployState.getDeployLogger(), host, container);
metricsProxyCluster.addContainer(container);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/ConsumersConfigGenerator.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/ConsumersConfigGenerator.java
new file mode 100644
index 00000000000..2df4008214a
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/ConsumersConfigGenerator.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package com.yahoo.vespa.model.admin.metricsproxy;
+
+import ai.vespa.metricsproxy.core.ConsumersConfig.Consumer;
+import com.yahoo.vespa.model.admin.monitoring.Metric;
+import com.yahoo.vespa.model.admin.monitoring.MetricSet;
+import com.yahoo.vespa.model.admin.monitoring.MetricsConsumer;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static com.yahoo.vespa.model.admin.monitoring.DefaultMetricsConsumer.VESPA_CONSUMER_ID;
+import static com.yahoo.vespa.model.admin.monitoring.DefaultMetricsConsumer.getDefaultMetricsConsumer;
+
+/**
+ * Helper class to generate config for metrics consumers.
+ *
+ * @author gjoranv
+ */
+class ConsumersConfigGenerator {
+
+ /**
+ * @param userConsumers The consumers set up by the user in services.xml
+ * @return A list of consumer builders (a mapping from consumer to its metrics)
+ */
+ static List<Consumer.Builder> generate(Map<String, MetricsConsumer> userConsumers) {
+ // Normally, the user given consumers should not contain VESPA_CONSUMER_ID, but it's allowed for some internally used applications.
+ var allConsumers = new LinkedHashMap<>(userConsumers);
+ allConsumers.put(VESPA_CONSUMER_ID, combineConsumers(getDefaultMetricsConsumer(), allConsumers.get(VESPA_CONSUMER_ID)));
+
+ return allConsumers.values().stream()
+ .map(ConsumersConfigGenerator::toConsumerBuilder)
+ .collect(Collectors.toList());
+ }
+
+ /*
+ * Returns a new consumer that is a combination of the two given consumers
+ * (ignoring the id of the consumers' metric sets).
+ * If a metric with the same id exists in both consumers, output name and
+ * dimensions from the 'overriding' consumer is used, but dimensions from 'original'
+ * are added if they don't exist in 'overriding'.
+ */
+ private static MetricsConsumer combineConsumers(MetricsConsumer original, MetricsConsumer overriding) {
+ if (overriding == null) return original;
+ return addMetrics(original, overriding.getMetrics());
+ }
+
+ private static MetricsConsumer addMetrics(MetricsConsumer original, Map<String, Metric> metrics) {
+ Map<String, Metric> combinedMetrics = new LinkedHashMap<>(original.getMetrics());
+ metrics.forEach((name, newMetric) ->
+ combinedMetrics.put(name, combineMetrics(original.getMetrics().get(name), newMetric)));
+
+ return new MetricsConsumer(original.getId(),
+ new MetricSet(original.getMetricSet().getId(), combinedMetrics.values()));
+ }
+
+ private static Metric combineMetrics(@Nullable Metric original, Metric newMetric) {
+ return original != null ? newMetric.addDimensionsFrom(original) : newMetric;
+ }
+
+ private static Consumer.Builder toConsumerBuilder(MetricsConsumer consumer) {
+ Consumer.Builder builder = new Consumer.Builder().name(consumer.getId());
+ consumer.getMetrics().values().forEach(metric -> builder.metric(toConsumerMetricBuilder(metric)));
+ return builder;
+ }
+
+ private static Consumer.Metric.Builder toConsumerMetricBuilder(Metric metric) {
+ Consumer.Metric.Builder builder = new Consumer.Metric.Builder().name(metric.name)
+ .outputname(metric.outputName)
+ .description(metric.description);
+ metric.dimensions.forEach((name, value) -> builder.dimension(toMetricDimensionBuilder(name, value)));
+ return builder;
+ }
+
+ private static Consumer.Metric.Dimension.Builder toMetricDimensionBuilder(String name, String value) {
+ return new Consumer.Metric.Dimension.Builder()
+ .key(name)
+ .value(value);
+ }
+
+}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java
index 742196c91d1..5aef2a2db1d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java
@@ -1,22 +1,62 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
package com.yahoo.vespa.model.admin.metricsproxy;
+import ai.vespa.metricsproxy.metric.dimensions.NodeDimensions;
+import ai.vespa.metricsproxy.metric.dimensions.NodeDimensionsConfig;
+import ai.vespa.metricsproxy.rpc.RpcConnector;
+import ai.vespa.metricsproxy.rpc.RpcConnectorConfig;
+import ai.vespa.metricsproxy.service.VespaServices;
+import ai.vespa.metricsproxy.service.VespaServicesConfig;
import com.yahoo.config.model.api.container.ContainerServiceType;
import com.yahoo.config.model.producer.AbstractConfigProducer;
+import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.vespa.model.container.Container;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
import static com.yahoo.config.model.api.container.ContainerServiceType.METRICS_PROXY_CONTAINER;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainer.NodeDimensionNames.CANONICAL_FLAVOR;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainer.NodeDimensionNames.CLUSTER_ID;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainer.NodeDimensionNames.CLUSTER_TYPE;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainer.NodeDimensionNames.FLAVOR;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerCluster.METRICS_PROXY_BUNDLE_NAME;
/**
* Container running a metrics proxy.
*
* @author gjoranv
*/
-public class MetricsProxyContainer extends Container {
+public class MetricsProxyContainer extends Container implements
+ NodeDimensionsConfig.Producer,
+ RpcConnectorConfig.Producer,
+ VespaServicesConfig.Producer
+{
+
+ static final class NodeDimensionNames {
+ static final String FLAVOR = "flavor";
+ static final String CANONICAL_FLAVOR = "canonicalFlavor";
+ static final String CLUSTER_TYPE = "clustertype";
+ static final String CLUSTER_ID = "clusterid";
+ }
+
+ private final boolean isHostedVespa;
- public MetricsProxyContainer(AbstractConfigProducer parent, int index) {
+ public MetricsProxyContainer(AbstractConfigProducer parent, int index, boolean isHostedVespa) {
super(parent, "" + index, index);
+ this.isHostedVespa = isHostedVespa;
setProp("clustertype", "admin");
setProp("index", String.valueOf(index));
+ addNodeSpecificComponents();
+ }
+
+ private void addNodeSpecificComponents() {
+ addMetricsProxyComponent(NodeDimensions.class);
+ addMetricsProxyComponent(RpcConnector.class);
+ addMetricsProxyComponent(VespaServices.class);
}
@Override
@@ -45,4 +85,36 @@ public class MetricsProxyContainer extends Container {
portsMeta.on(numHttpServerPorts).tag("rpc").tag("metrics");
}
+ @Override
+ public void getConfig(RpcConnectorConfig.Builder builder) {
+ builder.port(getRelativePort(0));
+ }
+
+ @Override
+ public void getConfig(VespaServicesConfig.Builder builder) {
+ builder.service.addAll(VespaServicesConfigGenerator.generate(getHostResource().getServices()));
+ }
+
+ @Override
+ public void getConfig(NodeDimensionsConfig.Builder builder) {
+ Map<String, String> dimensions = new LinkedHashMap<>();
+ if (isHostedVespa) {
+ getHostResource().getFlavor().ifPresent(flavor -> {
+ dimensions.put(FLAVOR, flavor.name());
+ dimensions.put(CANONICAL_FLAVOR, flavor.canonicalName());
+ });
+
+ getHostResource().primaryClusterMembership().map(ClusterMembership::cluster).ifPresent(cluster -> {
+ dimensions.put(CLUSTER_TYPE, cluster.type().name());
+ dimensions.put(CLUSTER_ID, cluster.id().value());
+ });
+
+ builder.dimensions(dimensions);
+ }
+ }
+
+ private void addMetricsProxyComponent(Class<?> componentClass) {
+ addSimpleComponent(componentClass.getName(), null, METRICS_PROXY_BUNDLE_NAME);
+ }
+
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerCluster.java
index 437df42d531..d9a969ab7c9 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerCluster.java
@@ -1,23 +1,183 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
package com.yahoo.vespa.model.admin.metricsproxy;
+import ai.vespa.metricsproxy.core.MetricsConsumers;
+import ai.vespa.metricsproxy.core.ConsumersConfig;
+import ai.vespa.metricsproxy.core.MetricsManager;
+import ai.vespa.metricsproxy.metric.ExternalMetrics;
+import ai.vespa.metricsproxy.core.VespaMetrics;
+import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensions;
+import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensionsConfig;
+import ai.vespa.metricsproxy.rpc.RpcServer;
+import ai.vespa.metricsproxy.core.MonitoringConfig;
+import ai.vespa.metricsproxy.service.SystemPollerProvider;
+import ai.vespa.metricsproxy.service.ConfigSentinelClient;
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.ApplicationId;
+import com.yahoo.config.provision.Zone;
+import com.yahoo.vespa.model.VespaModel;
+import com.yahoo.vespa.model.admin.Admin;
+import com.yahoo.vespa.model.admin.monitoring.MetricsConsumer;
+import com.yahoo.vespa.model.admin.monitoring.Monitoring;
+import com.yahoo.vespa.model.admin.monitoring.builder.Metrics;
import com.yahoo.vespa.model.container.ContainerCluster;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerCluster.AppDimensionNames.APPLICATION;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerCluster.AppDimensionNames.APPLICATION_ID;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerCluster.AppDimensionNames.INSTANCE;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerCluster.AppDimensionNames.LEGACY_APPLICATION;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerCluster.AppDimensionNames.TENANT;
+import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerCluster.AppDimensionNames.ZONE;
+import static com.yahoo.vespa.model.container.xml.BundleMapper.JarSuffix.JAR_WITH_DEPS;
+import static com.yahoo.vespa.model.container.xml.BundleMapper.bundlePathFromName;
+
/**
* Container cluster for metrics proxy containers.
*
* @author gjoranv
*/
-public class MetricsProxyContainerCluster extends ContainerCluster<MetricsProxyContainer> {
+public class MetricsProxyContainerCluster extends ContainerCluster<MetricsProxyContainer> implements
+ ApplicationDimensionsConfig.Producer,
+ ConsumersConfig.Producer,
+ MonitoringConfig.Producer
+{
+ public static final Logger log = Logger.getLogger(MetricsProxyContainerCluster.class.getName());
+
+ private static final String METRICS_PROXY_NAME = "metrics-proxy";
+ private static final Path METRICS_PROXY_BUNDLE_FILE = bundlePathFromName(METRICS_PROXY_NAME, JAR_WITH_DEPS);
+ static final String METRICS_PROXY_BUNDLE_NAME = "com.yahoo.vespa." + METRICS_PROXY_NAME;
+
+ static final String DEFAULT_NAME_IN_MONITORING_SYSTEM = "vespa";
+ static final int DEFAULT_MONITORING_INTERVAL = 1;
+
+ static final class AppDimensionNames {
+ static final String ZONE = "zone";
+ static final String APPLICATION_ID = "applicationId"; // tenant.app.instance
+ static final String TENANT = "tenantName";
+ static final String APPLICATION = "applicationName";
+ static final String INSTANCE = "instanceName";
+ static final String LEGACY_APPLICATION = "app"; // app.instance
+ }
+
+ private final AbstractConfigProducer<?> parent;
+ private final ApplicationId applicationId;
public MetricsProxyContainerCluster(AbstractConfigProducer<?> parent, String name, DeployState deployState) {
super(parent, name, name, deployState);
+ this.parent = parent;
+ applicationId = deployState.getProperties().applicationId();
+
setRpcServerEnabled(false);
addDefaultHandlersExceptStatus();
+
+ addPlatformBundle(METRICS_PROXY_BUNDLE_FILE);
+ addClusterComponents();
+ }
+
+ private void addClusterComponents() {
+ addMetricsProxyComponent(ApplicationDimensions.class);
+ addMetricsProxyComponent(ConfigSentinelClient.class);
+ addMetricsProxyComponent(ExternalMetrics.class);
+ addMetricsProxyComponent(MetricsConsumers.class);
+ addMetricsProxyComponent(MetricsManager.class);
+ addMetricsProxyComponent(RpcServer.class);
+ addMetricsProxyComponent(SystemPollerProvider.class);
+ addMetricsProxyComponent(VespaMetrics.class);
}
@Override
protected void doPrepare(DeployState deployState) { }
+ @Override
+ public void getConfig(MonitoringConfig.Builder builder) {
+ builder.systemName(getSystemName())
+ .intervalMinutes(getIntervalMinutes());
+ }
+
+ @Override
+ public void getConfig(ConsumersConfig.Builder builder) {
+ builder.consumer.addAll(ConsumersConfigGenerator.generate(getUserMetricsConsumers()));
+ }
+
+ @Override
+ public void getConfig(ApplicationDimensionsConfig.Builder builder) {
+ if (isHostedVespa()) {
+ builder.dimensions(applicationDimensions());
+ }
+ }
+
+ // Returns the metricConsumers from services.xml
+ private Map<String, MetricsConsumer> getUserMetricsConsumers() {
+ return getAdmin()
+ .map(this::consumersInAdmin)
+ .orElse(Collections.emptyMap());
+ }
+
+ private Map<String, MetricsConsumer> consumersInAdmin(Admin admin) {
+ Metrics metrics = admin.getUserMetrics();
+ return metrics.getConsumers();
+ }
+
+ private Optional<Admin> getAdmin() {
+ if (parent != null) {
+ AbstractConfigProducerRoot r = parent.getRoot();
+ if (r instanceof VespaModel) {
+ VespaModel model = (VespaModel) r;
+ return Optional.ofNullable(model.getAdmin());
+ }
+ }
+ return Optional.empty();
+ }
+
+ private String getSystemName() {
+ Monitoring monitoring = getMonitoringService();
+ if (monitoring != null && ! monitoring.getClustername().equals(""))
+ return monitoring.getClustername();
+ return DEFAULT_NAME_IN_MONITORING_SYSTEM;
+ }
+
+ private int getIntervalMinutes() {
+ Monitoring monitoring = getMonitoringService();
+ if (monitoring != null && monitoring.getInterval() != null) {
+ return monitoring.getInterval();
+ }
+ return DEFAULT_MONITORING_INTERVAL;
+ }
+
+ private void addMetricsProxyComponent(Class<?> componentClass) {
+ addSimpleComponent(componentClass.getName(), null, METRICS_PROXY_BUNDLE_NAME);
+ }
+
+ private Map<String, String> applicationDimensions() {
+ Map<String, String> dimensions = new LinkedHashMap<>();
+ dimensions.put(ZONE, zoneString(getZone()));
+ dimensions.put(APPLICATION_ID, serializeWithDots(applicationId));
+ dimensions.put(TENANT, applicationId.tenant().value());
+ dimensions.put(APPLICATION, applicationId.application().value());
+ dimensions.put(INSTANCE, applicationId.instance().value());
+ dimensions.put(LEGACY_APPLICATION, applicationId.application().value() + "." + applicationId.instance().value());
+ return dimensions;
+ }
+
+ // ApplicationId uses ':' as separator.
+ private static String serializeWithDots(ApplicationId applicationId) {
+ return applicationId.serializedForm().replace(':', '.');
+ }
+
+ static String zoneString(Zone zone) {
+ return zone.environment().value() + "." + zone.region().value();
+ }
+
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/VespaServicesConfigGenerator.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/VespaServicesConfigGenerator.java
new file mode 100644
index 00000000000..08a81fad0a3
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/VespaServicesConfigGenerator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package com.yahoo.vespa.model.admin.metricsproxy;
+
+import ai.vespa.metricsproxy.service.VespaServicesConfig;
+import com.yahoo.vespa.model.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author gjoranv
+ */
+public class VespaServicesConfigGenerator {
+
+ public static List<VespaServicesConfig.Service.Builder> generate(List<Service> services) {
+ return services.stream()
+ .filter(VespaServicesConfigGenerator::doIncludeServiceMetrics)
+ .map(VespaServicesConfigGenerator::toServiceBuilder)
+ .collect(Collectors.toList());
+ }
+
+ private static boolean doIncludeServiceMetrics(Service s) {
+ return s.getStartupCommand() != null || s.getServiceType().equals("configserver") || s.getServiceType().equals("config-sentinel");
+ }
+
+ private static VespaServicesConfig.Service.Builder toServiceBuilder(Service service) {
+ VespaServicesConfig.Service.Builder builder = new VespaServicesConfig.Service.Builder()
+ .configId(service.getConfigId())
+ .name(service.getServiceName())
+ .port(service.getHealthPort())
+ .healthport(service.getHealthPort());
+
+ service.getDefaultMetricDimensions().forEach((name, value) -> builder.dimension(toServiceDimensionBuilder(name, value)));
+ return builder;
+ }
+
+ private static VespaServicesConfig.Service.Dimension.Builder toServiceDimensionBuilder(String name, String value) {
+ return new VespaServicesConfig.Service.Dimension.Builder()
+ .key(name)
+ .value(value);
+ }
+
+}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java
index f449feb5fc1..f2bd67cdd81 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java
@@ -10,6 +10,7 @@ import com.yahoo.container.QrConfig;
import com.yahoo.container.core.ContainerHttpConfig;
import com.yahoo.container.jdisc.ContainerMbusConfig;
import com.yahoo.container.jdisc.JdiscBindingsConfig;
+import com.yahoo.osgi.provider.model.ComponentModel;
import com.yahoo.search.config.QrStartConfig;
import com.yahoo.vespa.defaults.Defaults;
import com.yahoo.vespa.model.AbstractService;
@@ -36,6 +37,10 @@ import static com.yahoo.container.QrConfig.Filedistributor;
import static com.yahoo.container.QrConfig.Rpc;
/**
+ * Note about components: In general, all components should belong to the cluster and not the container. However,
+ * components that need node specific config must be added at the container level, along with the node-specific
+ * parts of the config generation (getConfig).
+ *
* @author gjoranv
* @author Einar M R Rosenvinge
* @author Tony Vaagenes
@@ -107,11 +112,15 @@ public abstract class Container extends AbstractService implements
return components;
}
- public void addComponent(Component c) {
+ public final void addComponent(Component c) {
components.addComponent(c);
}
- public void addHandler(Handler h) {
+ public final void addSimpleComponent(String idSpec, String classSpec, String bundleSpec) {
+ addComponent(new SimpleComponent(new ComponentModel(idSpec, classSpec, bundleSpec)));
+ }
+
+ public final void addHandler(Handler h) {
handlers.addComponent(h);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
index ad087288799..1f0c3d6f84e 100755
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
@@ -200,7 +200,7 @@ public abstract class ContainerCluster<CONTAINER extends Container>
addVipHandler();
}
- public void addDefaultHandlersExceptStatus() {
+ public final void addDefaultHandlersExceptStatus() {
addDefaultRootHandler();
addMetricStateHandler();
addApplicationStatusHandler();
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java
index 11d467a61d5..4c5c14dad87 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java
@@ -15,7 +15,20 @@ import java.util.Optional;
*/
public class BundleMapper {
+ public enum JarSuffix {
+ JAR_WITH_DEPS("-jar-with-dependencies.jar"),
+ DEPLOY("-deploy.jar");
+
+ private final String suffix;
+
+ JarSuffix(String suffix) {
+ this.suffix = suffix;
+ }
+ }
+
public static final Path LIBRARY_PATH = Paths.get(Defaults.getDefaults().underVespaHome("lib/jars"));
+
+
public static final String searchAndDocprocBundle = "container-search-and-docproc";
private static final Map<String, String> bundleFromClass;
@@ -34,6 +47,10 @@ public class BundleMapper {
return LIBRARY_PATH.resolve(fileName);
}
+ public static Path bundlePathFromName(String name, JarSuffix suffix) {
+ return Paths.get(Defaults.getDefaults().underVespaHome(LIBRARY_PATH + name + suffix.suffix));
+ }
+
/**
* TODO: This is a temporary hack to ensure that users can use our internal components without
* specifying the bundle in which the components reside. Ideally, this information