diff options
Diffstat (limited to 'service-monitor')
25 files changed, 474 insertions, 217 deletions
diff --git a/service-monitor/pom.xml b/service-monitor/pom.xml index b8065ed3636..168af826b40 100644 --- a/service-monitor/pom.xml +++ b/service-monitor/pom.xml @@ -36,6 +36,12 @@ </dependency> <dependency> <groupId>com.yahoo.vespa</groupId> + <artifactId>flags</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> <artifactId>component</artifactId> <version>${project.version}</version> <scope>provided</scope> diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerApplication.java index 5ad38cebcfc..f1041835a39 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerApplication.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerApplication.java @@ -25,7 +25,7 @@ import java.util.Map; /** * A service/application model of the config server with health status. */ -public class ConfigServerApplication extends HostedVespaApplication { +public class ConfigServerApplication extends InfraApplication { public static final ConfigServerApplication CONFIG_SERVER_APPLICATION = new ConfigServerApplication(); public static final TenantId TENANT_ID = new TenantId(CONFIG_SERVER_APPLICATION.getApplicationId().tenant().value()); @@ -39,12 +39,12 @@ public class ConfigServerApplication extends HostedVespaApplication { return new ConfigId(CONFIG_ID_PREFIX + index); } - private ConfigServerApplication() { + public ConfigServerApplication() { super("zone-config-servers", NodeType.config, - ClusterSpec.Type.admin, ClusterSpec.Id.from("zone-config-servers")); + ClusterSpec.Type.admin, ClusterSpec.Id.from("zone-config-servers"), ServiceType.CONFIG_SERVER); } - public ApplicationInfo makeApplicationInfo(ConfigserverConfig config) { + public ApplicationInfo makeApplicationInfoFromConfig(ConfigserverConfig config) { List<HostInfo> hostInfos = new ArrayList<>(); List<ConfigserverConfig.Zookeeperserver> zooKeeperServers = config.zookeeperserver(); for (int index = 0; index < zooKeeperServers.size(); ++index) { diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerHostApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerHostApplication.java index 18420fe64a1..9925e2ac69b 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerHostApplication.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ConfigServerHostApplication.java @@ -3,13 +3,12 @@ package com.yahoo.vespa.service.monitor.application; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.applicationmodel.ServiceType; -public class ConfigServerHostApplication extends HostedVespaApplication { - - public static final ConfigServerHostApplication CONFIG_SERVER_HOST_APPLICATION = new ConfigServerHostApplication(); - - private ConfigServerHostApplication() { +public class ConfigServerHostApplication extends InfraApplication { + public ConfigServerHostApplication() { super("configserver-host", NodeType.confighost, - ClusterSpec.Type.container, ClusterSpec.Id.from("configserver-host")); + ClusterSpec.Type.container, ClusterSpec.Id.from("configserver-host"), + ServiceType.HOST_ADMIN); } } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerApplication.java index c1bc303e792..ec4cb73383e 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerApplication.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerApplication.java @@ -3,16 +3,15 @@ package com.yahoo.vespa.service.monitor.application; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.applicationmodel.ServiceType; /** * @author mpolden */ -public class ControllerApplication extends HostedVespaApplication { - - public static final ControllerApplication CONTROLLER_APPLICATION = new ControllerApplication(); - - private ControllerApplication() { - super("controller", NodeType.controller, ClusterSpec.Type.container, ClusterSpec.Id.from("controller")); +public class ControllerApplication extends InfraApplication { + public ControllerApplication() { + super("controller", NodeType.controller, ClusterSpec.Type.container, + ClusterSpec.Id.from("controller"), ServiceType.CONTROLLER); } } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerHostApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerHostApplication.java index 8311919d570..c23794b3835 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerHostApplication.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ControllerHostApplication.java @@ -3,16 +3,14 @@ package com.yahoo.vespa.service.monitor.application; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.applicationmodel.ServiceType; /** * @author mpolden */ -public class ControllerHostApplication extends HostedVespaApplication { - - public static final ControllerHostApplication CONTROLLER_HOST_APPLICATION = new ControllerHostApplication(); - - protected ControllerHostApplication() { - super("controller-host", NodeType.controllerhost, ClusterSpec.Type.container, ClusterSpec.Id.from("controller-host")); +public class ControllerHostApplication extends InfraApplication { + public ControllerHostApplication() { + super("controller-host", NodeType.controllerhost, ClusterSpec.Type.container, + ClusterSpec.Id.from("controller-host"), ServiceType.HOST_ADMIN); } - } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModel.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModel.java new file mode 100644 index 00000000000..b28b37006ed --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModel.java @@ -0,0 +1,140 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.application; + +import com.google.inject.Inject; +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.HostName; +import com.yahoo.vespa.flags.FeatureFlag; +import com.yahoo.vespa.flags.FlagSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * The {@code DuperModel} unites the {@link com.yahoo.config.model.api.SuperModel SuperModel} + * with synthetic applications like the config server application. + * + * @author hakon + */ +public class DuperModel implements DuperModelInfraApi { + // Infrastructure applications + private static final ConfigServerApplication configServerApplication = new ConfigServerApplication(); + private static final ConfigServerHostApplication configServerHostApplication = new ConfigServerHostApplication(); + private static final ProxyHostApplication proxyHostApplication = new ProxyHostApplication(); + private static final ControllerApplication controllerApplication = new ControllerApplication(); + private static final ControllerHostApplication controllerHostApplication = new ControllerHostApplication(); + + private static final Map<ApplicationId, InfraApplication> supportedInfraApplications = Stream.of( + configServerApplication, + configServerHostApplication, + proxyHostApplication, + controllerApplication, + controllerHostApplication) + .collect(Collectors.toMap(InfraApplication::getApplicationId, Function.identity())); + + private final boolean containsInfra; + private final boolean useConfigserverConfig; + + // Each of the above infrastructure applications may be active, in case their ApplicationInfo is present here + private final ConcurrentHashMap<ApplicationId, ApplicationInfo> infraInfos = + new ConcurrentHashMap<>(2 * supportedInfraApplications.size()); + + // ApplicationInfo known at construction time + private final List<ApplicationInfo> staticInfos = new ArrayList<>(); + + @Inject + public DuperModel(ConfigserverConfig configServerConfig, FlagSource flagSource) { + this( + // Whether to include activate infrastructure applications in the DuperModel. + new FeatureFlag("dupermodel-contains-infra", true, flagSource).value(), + + // Whether to base the ApplicationInfo for the config server on ConfigserverConfig or InfrastructureProvisioner: + // - ConfigserverConfig: The list of config servers comes from VESPA_CONFIGSERVERS environment variable. + // - InfrastructureProvisioner: The list of config servers comes from the node repository. + // + // The goal is to use InfrastructureProvisioner like other infrastructure applications. + new FeatureFlag("dupermodel-use-configserverconfig", true, flagSource).value(), + configServerConfig.multitenant(), + configServerApplication.makeApplicationInfoFromConfig(configServerConfig)); + } + + /** For testing */ + public DuperModel(boolean containsInfra, + boolean useConfigserverConfig, + boolean multitenant, + ApplicationInfo configServerApplicationInfo) { + this.containsInfra = containsInfra; + this.useConfigserverConfig = useConfigserverConfig; + + // Single-tenant applications have the config server as part of the application model. + // TODO: Add health monitoring for config server when part of application model. + if (useConfigserverConfig && multitenant) { + staticInfos.add(configServerApplicationInfo); + } + } + + public ConfigServerApplication getConfigServerApplication() { + return configServerApplication; + } + + public ConfigServerHostApplication getConfigServerHostApplication() { + return configServerHostApplication; + } + + public ProxyHostApplication getProxyHostApplication() { + return proxyHostApplication; + } + + public ControllerApplication getControllerApplication() { + return controllerApplication; + } + + public ControllerHostApplication getControllerHostApplication() { + return controllerHostApplication; + } + + @Override + public List<InfraApplicationApi> getSupportedInfraApplications() { + return new ArrayList<>(supportedInfraApplications.values()); + } + + @Override + public boolean infraApplicationIsActive(ApplicationId applicationId) { + return infraInfos.containsKey(applicationId); + } + + @Override + public void infraApplicationActivated(ApplicationId applicationId, List<HostName> hostnames) { + InfraApplication application = supportedInfraApplications.get(applicationId); + if (application == null) { + throw new IllegalArgumentException("There is no infrastructure application with ID '" + applicationId + "'"); + } + + if (useConfigserverConfig && application.equals(configServerApplication)) { + return; + } + + infraInfos.put(application.getApplicationId(), application.makeApplicationInfo(hostnames)); + } + + @Override + public void infraApplicationRemoved(ApplicationId applicationId) { + infraInfos.remove(applicationId); + } + + public List<ApplicationInfo> getApplicationInfos(SuperModel superModelSnapshot) { + List<ApplicationInfo> allApplicationInfos = new ArrayList<>(); + allApplicationInfos.addAll(staticInfos); + if (containsInfra) allApplicationInfos.addAll(infraInfos.values()); + allApplicationInfos.addAll(superModelSnapshot.getAllApplicationInfos()); + return allApplicationInfos; + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModelInfraApi.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModelInfraApi.java new file mode 100644 index 00000000000..2faeca55fa4 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModelInfraApi.java @@ -0,0 +1,26 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.application; + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.HostName; + +import java.util.List; + +/** + * The DuperModel's API for infrastructure applications. + * + * @author hakonhall + */ +public interface DuperModelInfraApi { + /** Returns the list of supported infrastructure applications. */ + List<InfraApplicationApi> getSupportedInfraApplications(); + + /** Returns true if the DuperModel has registered the infrastructure application as active. */ + boolean infraApplicationIsActive(ApplicationId applicationId); + + /** Update the DuperModel: A supported infrastructure application has been activated or is active. */ + void infraApplicationActivated(ApplicationId applicationId, List<HostName> hostnames); + + /** Update the DuperModel: A supported infrastructure application has been removed or is not active. */ + void infraApplicationRemoved(ApplicationId applicationId); +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/DuperModelListener.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModelListener.java index 235c7db5c36..34b8109ce53 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/DuperModelListener.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/DuperModelListener.java @@ -1,5 +1,5 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.service.monitor.internal; +package com.yahoo.vespa.service.monitor.application; import com.yahoo.config.model.api.ApplicationInfo; import com.yahoo.config.model.api.SuperModel; diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/HostedVespaApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/HostedVespaApplication.java deleted file mode 100644 index 23fafa701d9..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/HostedVespaApplication.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.service.monitor.application; - -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Capacity; -import com.yahoo.config.provision.ClusterSpec; -import com.yahoo.config.provision.NodeType; -import com.yahoo.config.provision.TenantName; -import com.yahoo.component.Version; - -/** - * @author freva - */ -public abstract class HostedVespaApplication { - - public static final TenantName TENANT_NAME = TenantName.from("hosted-vespa"); - - private final ApplicationId applicationId; - private final Capacity capacity; - private final ClusterSpec.Type clusterType; - private final ClusterSpec.Id clusterId; - - protected HostedVespaApplication(String applicationName, NodeType nodeType, - ClusterSpec.Type clusterType, ClusterSpec.Id clusterId) { - this(createHostedVespaApplicationId(applicationName), Capacity.fromRequiredNodeType(nodeType), - clusterType, clusterId); - } - - protected HostedVespaApplication(ApplicationId applicationId, Capacity capacity, - ClusterSpec.Type clusterType, ClusterSpec.Id clusterId) { - this.applicationId = applicationId; - this.capacity = capacity; - this.clusterType = clusterType; - this.clusterId = clusterId; - } - - public ApplicationId getApplicationId() { - return applicationId; - } - - public Capacity getCapacity() { - return capacity; - } - - public ClusterSpec getClusterSpecWithVersion(Version version) { - return ClusterSpec.request(clusterType, clusterId, version, true); - } - - public ClusterSpec.Type getClusterType() { - return clusterType; - } - - public ClusterSpec.Id getClusterId() { - return clusterId; - } - - public static ApplicationId createHostedVespaApplicationId(String applicationName) { - return new ApplicationId.Builder() - .tenant(TENANT_NAME) - .applicationName(applicationName) - .build(); - } - - @Override - public String toString() { - return applicationId.toString(); - } - -} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/InfraApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/InfraApplication.java new file mode 100644 index 00000000000..1c4f6ea3d2a --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/InfraApplication.java @@ -0,0 +1,142 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.application; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.HostInfo; +import com.yahoo.config.model.api.PortInfo; +import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Capacity; +import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.HostName; +import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.TenantName; +import com.yahoo.component.Version; +import com.yahoo.vespa.applicationmodel.ConfigId; +import com.yahoo.vespa.applicationmodel.ServiceType; +import com.yahoo.vespa.service.monitor.internal.ModelGenerator; +import com.yahoo.vespa.service.monitor.internal.health.ApplicationHealthMonitor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @author freva + */ +public abstract class InfraApplication implements InfraApplicationApi { + static final int HEALTH_PORT = 8080; + + private static final TenantName TENANT_NAME = TenantName.from("hosted-vespa"); + private static final String CONFIG_ID_PREFIX = "configid."; + + private final ApplicationId applicationId; + private final Capacity capacity; + private final ClusterSpec.Type clusterType; + private final ClusterSpec.Id clusterId; + private final ServiceType serviceType; + + public static ApplicationId createHostedVespaApplicationId(String applicationName) { + return new ApplicationId.Builder() + .tenant(TENANT_NAME) + .applicationName(applicationName) + .build(); + } + + protected InfraApplication(String applicationName, + NodeType nodeType, + ClusterSpec.Type clusterType, + ClusterSpec.Id clusterId, + ServiceType serviceType) { + this.applicationId = createHostedVespaApplicationId(applicationName); + this.capacity = Capacity.fromRequiredNodeType(nodeType); + this.clusterType = clusterType; + this.clusterId = clusterId; + this.serviceType = serviceType; + } + + @Override + public ApplicationId getApplicationId() { + return applicationId; + } + + @Override + public Capacity getCapacity() { + return capacity; + } + + @Override + public ClusterSpec getClusterSpecWithVersion(Version version) { + return ClusterSpec.request(clusterType, clusterId, version, true); + } + + public ClusterSpec.Type getClusterType() { + return clusterType; + } + + public ClusterSpec.Id getClusterId() { + return clusterId; + } + + public ApplicationInfo makeApplicationInfo(List<HostName> hostnames) { + List<HostInfo> hostInfos = new ArrayList<>(); + for (int index = 0; index < hostnames.size(); ++index) { + hostInfos.add(makeHostInfo(hostnames.get(index), HEALTH_PORT, index, serviceType, clusterId)); + } + + return new ApplicationInfo(applicationId, 0, new HostsModel(hostInfos)); + } + + private static HostInfo makeHostInfo(HostName hostname, int port, int configIndex, ServiceType serviceType, ClusterSpec.Id clusterId) { + PortInfo portInfo = new PortInfo(port, ApplicationHealthMonitor.PORT_TAGS_HEALTH); + + Map<String, String> properties = new HashMap<>(); + properties.put(ModelGenerator.CLUSTER_ID_PROPERTY_NAME, clusterId.value()); + + ServiceInfo serviceInfo = new ServiceInfo( + // service name == service type for the first service of each type on each host + serviceType.s(), + serviceType.s(), + Collections.singletonList(portInfo), + properties, + configIdFrom(configIndex).s(), + hostname.value()); + + return new HostInfo(hostname.value(), Collections.singletonList(serviceInfo)); + } + + private static ConfigId configIdFrom(int index) { + return new ConfigId(CONFIG_ID_PREFIX + index); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InfraApplication that = (InfraApplication) o; + return Objects.equals(applicationId, that.applicationId) && + Objects.equals(capacity, that.capacity) && + clusterType == that.clusterType && + Objects.equals(clusterId, that.clusterId) && + Objects.equals(serviceType, that.serviceType); + } + + @Override + public int hashCode() { + return Objects.hash(applicationId, capacity, clusterType, clusterId, serviceType); + } + + @Override + public String toString() { + return "InfraApplication{" + + "applicationId=" + applicationId + + ", capacity=" + capacity + + ", clusterType=" + clusterType + + ", clusterId=" + clusterId + + ", serviceType=" + serviceType + + '}'; + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/InfraApplicationApi.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/InfraApplicationApi.java new file mode 100644 index 00000000000..3777a50b531 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/InfraApplicationApi.java @@ -0,0 +1,22 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.application; + +import com.yahoo.component.Version; +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Capacity; +import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.HostName; + +import java.util.List; + +/** + * API of infrastructure application that is accessible via DuperModelInfraApi. + * + * @author hakonhall + */ +public interface InfraApplicationApi { + ApplicationId getApplicationId(); + Capacity getCapacity(); + ClusterSpec getClusterSpecWithVersion(Version version); +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ProxyHostApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ProxyHostApplication.java index c1af7a0977e..2debec5d299 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ProxyHostApplication.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ProxyHostApplication.java @@ -3,12 +3,11 @@ package com.yahoo.vespa.service.monitor.application; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.applicationmodel.ServiceType; -public class ProxyHostApplication extends HostedVespaApplication { - - public static final ProxyHostApplication PROXY_HOST_APPLICATION = new ProxyHostApplication(); - - private ProxyHostApplication() { - super("proxy-host", NodeType.proxyhost, ClusterSpec.Type.container, ClusterSpec.Id.from("proxy-host")); +public class ProxyHostApplication extends InfraApplication { + public ProxyHostApplication() { + super("proxy-host", NodeType.proxyhost, ClusterSpec.Type.container, + ClusterSpec.Id.from("proxy-host"), ServiceType.HOST_ADMIN); } } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/TenantHostApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/TenantHostApplication.java deleted file mode 100644 index 27879a03c08..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/TenantHostApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.service.monitor.application; - -import com.yahoo.config.provision.ClusterSpec; -import com.yahoo.config.provision.NodeType; - -public class TenantHostApplication extends HostedVespaApplication { - - public static final TenantHostApplication TENANT_HOST_APPLICATION = new TenantHostApplication(); - - private TenantHostApplication() { - super("tenant-host", NodeType.host, ClusterSpec.Type.container, ClusterSpec.Id.from("tenant-host")); - } -} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ZoneApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ZoneApplication.java index c10015d3bfa..4a4189cddd7 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ZoneApplication.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/application/ZoneApplication.java @@ -10,14 +10,14 @@ import java.util.Objects; /** * @author hakon * - * TODO: This does not extend HostedVespaApplication because + * TODO: This does not extend InfraApplication because * 1) It is not deployed same as the other HostedVespaApplications * 2) ZoneApplication has multiple clusters */ public class ZoneApplication { private ZoneApplication() {} - public static final ApplicationId ZONE_APPLICATION_ID = HostedVespaApplication + public static final ApplicationId ZONE_APPLICATION_ID = InfraApplication .createHostedVespaApplicationId("routing"); public static boolean isNodeAdminService(ApplicationId applicationId, diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/DuperModel.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/DuperModel.java deleted file mode 100644 index 80e0bfd2710..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/DuperModel.java +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.service.monitor.internal; - -import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.config.model.api.ApplicationInfo; -import com.yahoo.config.model.api.SuperModel; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static com.yahoo.vespa.service.monitor.application.ConfigServerApplication.CONFIG_SERVER_APPLICATION; - -/** - * The {@code DuperModel} unites the {@link com.yahoo.config.model.api.SuperModel SuperModel} - * with the synthetically produced applications like the config server application. - * - * @author hakon - */ -public class DuperModel { - private final List<ApplicationInfo> staticApplicationInfos = new ArrayList<>(); - - public DuperModel(ConfigserverConfig configServerConfig) { - // Single-tenant applications have the config server as part of the application model. - // TODO: Add health monitoring for config server when part of application model. - if (configServerConfig.multitenant()) { - staticApplicationInfos.add(CONFIG_SERVER_APPLICATION.makeApplicationInfo(configServerConfig)); - } - } - - /** For testing. */ - DuperModel(ApplicationInfo... staticApplicationInfos) { - this.staticApplicationInfos.addAll(Arrays.asList(staticApplicationInfos)); - } - - public List<ApplicationInfo> getApplicationInfos(SuperModel superModelSnapshot) { - List<ApplicationInfo> allApplicationInfos = new ArrayList<>(); - allApplicationInfos.addAll(staticApplicationInfos); - allApplicationInfos.addAll(superModelSnapshot.getAllApplicationInfos()); - return allApplicationInfos; - } -} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/MonitorManager.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/MonitorManager.java index 1edf3a18215..965c425b91e 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/MonitorManager.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/MonitorManager.java @@ -1,6 +1,7 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.service.monitor.internal; +import com.yahoo.vespa.service.monitor.application.DuperModelListener; import com.yahoo.vespa.service.monitor.ServiceStatusProvider; /** diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java index eb346cf40c1..728c761c71d 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java @@ -9,6 +9,7 @@ import com.yahoo.jdisc.Metric; import com.yahoo.jdisc.Timer; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; +import com.yahoo.vespa.service.monitor.application.DuperModel; import com.yahoo.vespa.service.monitor.ServiceModel; import com.yahoo.vespa.service.monitor.ServiceMonitor; import com.yahoo.vespa.service.monitor.internal.health.HealthMonitorManager; @@ -26,12 +27,11 @@ public class ServiceMonitorImpl implements ServiceMonitor { HealthMonitorManager healthMonitorManager, Metric metric, Timer timer, - Zone zone) { + Zone zone, + DuperModel duperModel) { ServiceMonitorMetrics metrics = new ServiceMonitorMetrics(metric, timer); - DuperModel duperModel = new DuperModel(configserverConfig); - UnionMonitorManager monitorManager = - new UnionMonitorManager(slobrokMonitorManager, healthMonitorManager); + UnionMonitorManager monitorManager = new UnionMonitorManager(slobrokMonitorManager, healthMonitorManager); SuperModelListenerImpl superModelListener = new SuperModelListenerImpl( monitorManager, diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java index f509809c33d..7e2b61af090 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java @@ -7,6 +7,7 @@ import com.yahoo.config.model.api.SuperModelListener; import com.yahoo.config.model.api.SuperModelProvider; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.service.monitor.application.DuperModel; import com.yahoo.vespa.service.monitor.ServiceModel; import com.yahoo.vespa.service.monitor.ServiceStatusProvider; diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/application/ApplicationInstanceGeneratorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/application/ApplicationInstanceGeneratorTest.java index 899cc59bb34..4608e8b0aa8 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/application/ApplicationInstanceGeneratorTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/application/ApplicationInstanceGeneratorTest.java @@ -42,7 +42,7 @@ public class ApplicationInstanceGeneratorTest { configServer2, configServer3); Zone zone = mock(Zone.class); - ApplicationInfo configServer = CONFIG_SERVER_APPLICATION.makeApplicationInfo(config); + ApplicationInfo configServer = CONFIG_SERVER_APPLICATION.makeApplicationInfoFromConfig(config); ApplicationInstance applicationInstance = new ApplicationInstanceGenerator(configServer, zone) .makeApplicationInstance(statusProvider); diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/application/DuperModelTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/application/DuperModelTest.java new file mode 100644 index 00000000000..40204c0de8e --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/application/DuperModelTest.java @@ -0,0 +1,95 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.application; + +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.HostName; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import com.yahoo.vespa.service.monitor.ServiceStatusProvider; +import com.yahoo.vespa.service.monitor.internal.ConfigserverUtil; +import org.junit.Before; +import org.junit.Test; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author hakon + */ +public class DuperModelTest { + private final ServiceStatusProvider statusProvider = mock(ServiceStatusProvider.class); + private final ConfigserverConfig configserverConfig = ConfigserverUtil.createExampleConfigserverConfig(); + private final ApplicationInfo configServerApplicationInfo = new ConfigServerApplication().makeApplicationInfoFromConfig(configserverConfig); + private final SuperModel superModel = mock(SuperModel.class); + + @Before + public void setUp() { + when(statusProvider.getStatus(any(), any(), any(), any())).thenReturn(ServiceStatus.NOT_CHECKED); + } + + @Test + public void toApplicationInstance() { + DuperModel duperModel = new DuperModel(false, true, true, configServerApplicationInfo); + ApplicationInfo superModelApplicationInfo = mock(ApplicationInfo.class); + when(superModel.getAllApplicationInfos()).thenReturn(Collections.singletonList(superModelApplicationInfo)); + List<ApplicationInfo> applicationInfos = duperModel.getApplicationInfos(superModel); + assertEquals(2, applicationInfos.size()); + assertEquals(ConfigServerApplication.CONFIG_SERVER_APPLICATION.getApplicationId(), applicationInfos.get(0).getApplicationId()); + assertSame(superModelApplicationInfo, applicationInfos.get(1)); + } + + @Test + public void toApplicationInstanceInSingleTenantMode() { + DuperModel duperModel = new DuperModel(false, true, false, configServerApplicationInfo); + ApplicationInfo superModelApplicationInfo = mock(ApplicationInfo.class); + when(superModel.getAllApplicationInfos()).thenReturn(Collections.singletonList(superModelApplicationInfo)); + List<ApplicationInfo> applicationInfos = duperModel.getApplicationInfos(superModel); + assertEquals(1, applicationInfos.size()); + assertSame(superModelApplicationInfo, applicationInfos.get(0)); + } + + @Test + public void testInfraApplications() { + DuperModel duperModel = new DuperModel(true, true, true, configServerApplicationInfo); + ApplicationInfo infraApplicationInfo = mock(ApplicationInfo.class); + when(superModel.getAllApplicationInfos()).thenReturn(Collections.emptyList()); + + List<ApplicationInfo> applicationInfos = duperModel.getApplicationInfos(superModel); + assertEquals(1, applicationInfos.size()); + assertEquals(duperModel.getConfigServerApplication().getApplicationId(), applicationInfos.get(0).getApplicationId()); + + List<InfraApplicationApi> infraApis = duperModel.getSupportedInfraApplications(); + assertEquals(5, infraApis.size()); + + InfraApplication proxyHostApp = duperModel.getProxyHostApplication(); + assertFalse(duperModel.infraApplicationIsActive(proxyHostApp.getApplicationId())); + + List<HostName> hostnames = Stream.of("host1").map(HostName::from).collect(Collectors.toList()); + duperModel.infraApplicationActivated(proxyHostApp.getApplicationId(), hostnames); + + assertTrue(duperModel.infraApplicationIsActive(proxyHostApp.getApplicationId())); + applicationInfos = duperModel.getApplicationInfos(superModel); + assertEquals(2, applicationInfos.size()); + List<ApplicationId> applicationIds = applicationInfos.stream() + .map(ApplicationInfo::getApplicationId) + .collect(Collectors.toList()); + assertThat(applicationIds, hasItem(proxyHostApp.getApplicationId())); + + duperModel.infraApplicationRemoved(proxyHostApp.getApplicationId()); + assertFalse(duperModel.infraApplicationIsActive(proxyHostApp.getApplicationId())); + } +} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigserverUtil.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigserverUtil.java index 85df02949a6..16963797ac8 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigserverUtil.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigserverUtil.java @@ -38,7 +38,7 @@ public class ConfigserverUtil { String configServerHostname1, String configServerHostname2, String configServerHostname3) { - return ConfigServerApplication.CONFIG_SERVER_APPLICATION.makeApplicationInfo(create( + return ConfigServerApplication.CONFIG_SERVER_APPLICATION.makeApplicationInfoFromConfig(create( true, true, configServerHostname1, diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/DuperModelTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/DuperModelTest.java deleted file mode 100644 index c9d19d0ccd9..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/DuperModelTest.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.service.monitor.internal; - -import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.config.model.api.ApplicationInfo; -import com.yahoo.config.model.api.SuperModel; -import com.yahoo.vespa.applicationmodel.ServiceStatus; -import com.yahoo.vespa.service.monitor.ServiceStatusProvider; -import com.yahoo.vespa.service.monitor.application.ConfigServerApplication; -import org.junit.Test; - -import java.util.Collections; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author hakon - */ -public class DuperModelTest { - private final ServiceStatusProvider statusProvider = mock(ServiceStatusProvider.class); - - @Test - public void toApplicationInstance() { - when(statusProvider.getStatus(any(), any(), any(), any())).thenReturn(ServiceStatus.NOT_CHECKED); - ConfigserverConfig config = ConfigserverUtil.createExampleConfigserverConfig(); - DuperModel duperModel = new DuperModel(config); - SuperModel superModel = mock(SuperModel.class); - ApplicationInfo superModelApplicationInfo = mock(ApplicationInfo.class); - when(superModel.getAllApplicationInfos()).thenReturn(Collections.singletonList(superModelApplicationInfo)); - List<ApplicationInfo> applicationInfos = duperModel.getApplicationInfos(superModel); - assertEquals(2, applicationInfos.size()); - assertEquals(ConfigServerApplication.CONFIG_SERVER_APPLICATION.getApplicationId(), applicationInfos.get(0).getApplicationId()); - assertSame(superModelApplicationInfo, applicationInfos.get(1)); - } - - @Test - public void toApplicationInstanceInSingleTenantMode() { - when(statusProvider.getStatus(any(), any(), any(), any())).thenReturn(ServiceStatus.NOT_CHECKED); - ConfigserverConfig config = ConfigserverUtil.createExampleConfigserverConfig(true, false); - DuperModel duperModel = new DuperModel(config); - SuperModel superModel = mock(SuperModel.class); - ApplicationInfo superModelApplicationInfo = mock(ApplicationInfo.class); - when(superModel.getAllApplicationInfos()).thenReturn(Collections.singletonList(superModelApplicationInfo)); - List<ApplicationInfo> applicationInfos = duperModel.getApplicationInfos(superModel); - assertEquals(1, applicationInfos.size()); - assertSame(superModelApplicationInfo, applicationInfos.get(0)); - } -} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java index 5a57451a298..275fa8568c2 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.service.monitor.internal; import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.model.api.ApplicationInfo; import com.yahoo.config.model.api.SuperModel; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.RegionName; @@ -11,6 +12,7 @@ import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; import com.yahoo.vespa.applicationmodel.ServiceCluster; import com.yahoo.vespa.applicationmodel.ServiceInstance; import com.yahoo.vespa.applicationmodel.ServiceStatus; +import com.yahoo.vespa.service.monitor.application.DuperModel; import com.yahoo.vespa.service.monitor.ServiceModel; import com.yahoo.vespa.service.monitor.application.ConfigServerApplication; import com.yahoo.vespa.service.monitor.internal.slobrok.SlobrokMonitorManagerImpl; @@ -36,7 +38,8 @@ public class ModelGeneratorTest { SuperModel superModel = ExampleModel.createExampleSuperModelWithOneRpcPort(HOSTNAME, PORT); ConfigserverConfig config = ConfigserverUtil.createExampleConfigserverConfig(); - DuperModel duperModel = new DuperModel(config); + ApplicationInfo configServerInfo = new ConfigServerApplication().makeApplicationInfoFromConfig(config); + DuperModel duperModel = new DuperModel(false, true, true, configServerInfo); ModelGenerator modelGenerator = new ModelGenerator(); Zone zone = new Zone(Environment.from(ENVIRONMENT), RegionName.from(REGION)); diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java index eb6d6d583f7..e2da7b98f56 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java @@ -5,6 +5,7 @@ import com.yahoo.config.model.api.ApplicationInfo; import com.yahoo.config.model.api.SuperModel; import com.yahoo.config.model.api.SuperModelProvider; import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.service.monitor.application.DuperModel; import com.yahoo.vespa.service.monitor.ServiceModel; import com.yahoo.vespa.service.monitor.internal.slobrok.SlobrokMonitorManagerImpl; import org.junit.Test; diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/health/ApplicationHealthMonitorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/health/ApplicationHealthMonitorTest.java index b0fdb14726f..945d6c633af 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/health/ApplicationHealthMonitorTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/health/ApplicationHealthMonitorTest.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.service.monitor.internal.health; import com.yahoo.vespa.applicationmodel.ServiceStatus; import com.yahoo.vespa.service.monitor.application.ConfigServerApplication; +import com.yahoo.vespa.service.monitor.application.DuperModel; import com.yahoo.vespa.service.monitor.internal.ConfigserverUtil; import org.junit.Test; @@ -36,6 +37,8 @@ public class ApplicationHealthMonitorTest { ConfigserverUtil.makeExampleConfigServer(), monitorFactory); + ConfigServerApplication configServerApplication = new ConfigServerApplication(); + ServiceStatus status1 = applicationMonitor.getStatus( ConfigServerApplication.CONFIG_SERVER_APPLICATION.getApplicationId(), ConfigServerApplication.CLUSTER_ID, |