summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config-model-api/abi-spec.json3
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java27
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java3
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java31
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerCluster.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/DefaultPublicConsumer.java4
-rw-r--r--config-model/src/main/javacc/SDParser.jj2
-rw-r--r--config-model/src/test/derived/tensor/attributes.cfg21
-rw-r--r--config-model/src/test/derived/tensor/documenttypes.cfg6
-rw-r--r--config-model/src/test/derived/tensor/rank-profiles.cfg23
-rw-r--r--config-model/src/test/derived/tensor/summary.cfg10
-rw-r--r--config-model/src/test/derived/tensor/tensor.sd13
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java3
-rwxr-xr-xconfigserver/src/main/sh/vespa-configserver-remove-state5
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java80
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/NodeRepositoryClientInterface.java58
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java3
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneApi.java35
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneReference.java64
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/package-info.java5
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java302
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReference.java27
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReferences.java31
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/package-info.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java13
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java10
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java34
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java40
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostApiHandler.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostCalculator.java7
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java15
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryClientMock.java54
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java36
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java10
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-metering.json34
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_tensor_view.h1
-rw-r--r--metrics-proxy/pom.xml12
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ErrorResponse.java33
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/GenericMetricsHandler.java100
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/JsonResponse.java33
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/MetricsHandler.java99
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java65
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingException.java30
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/ErrorResponseTest.java (renamed from metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingExceptionTest.java)13
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/MetricsHandlerTest.java (renamed from metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/GenericMetricsHandlerTest.java)43
-rw-r--r--model-integration/src/main/java/ai/vespa/rankingexpression/importer/onnx/TypeConverter.java16
-rw-r--r--model-integration/src/main/java/ai/vespa/rankingexpression/importer/tensorflow/TypeConverter.java28
-rw-r--r--model-integration/src/test/java/ai/vespa/rankingexpression/importer/onnx/OnnxMnistSoftmaxImportTestCase.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainer.java446
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTest.java171
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTester.java290
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json3
-rw-r--r--node-repository/src/test/resources/zookeeper_dump.json1
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp12
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/TensorType.java7
-rw-r--r--zkfacade/CMakeLists.txt8
-rwxr-xr-xzkfacade/src/main/sh/vespa-zkcat (renamed from zkfacade/src/main/sh/zkcat)2
-rwxr-xr-xzkfacade/src/main/sh/vespa-zkcli (renamed from zkfacade/src/main/sh/zkcli)20
-rwxr-xr-xzkfacade/src/main/sh/vespa-zkctl (renamed from zkfacade/src/main/sh/zkctl)2
-rwxr-xr-xzkfacade/src/main/sh/vespa-zkls (renamed from zkfacade/src/main/sh/zkls)2
62 files changed, 1660 insertions, 820 deletions
diff --git a/config-model-api/abi-spec.json b/config-model-api/abi-spec.json
index 28c04f38da5..9f86fe4dea2 100644
--- a/config-model-api/abi-spec.json
+++ b/config-model-api/abi-spec.json
@@ -326,7 +326,8 @@
"public java.lang.String containerId()",
"public java.util.Set regions()",
"public boolean equals(java.lang.Object)",
- "public int hashCode()"
+ "public int hashCode()",
+ "public com.yahoo.config.application.api.Endpoint withRegions(java.util.Set)"
],
"fields": []
},
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java
index ada5ee23a7c..5b5f89fd8d1 100644
--- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java
@@ -74,11 +74,36 @@ public class DeploymentSpec {
this.athenzDomain = athenzDomain;
this.athenzService = athenzService;
this.notifications = notifications;
- this.endpoints = List.copyOf(Objects.requireNonNull(endpoints, "Missing endpoints parameter"));
+ this.endpoints = ImmutableList.copyOf(validateEndpoints(endpoints, this.steps));
validateZones(this.steps);
validateAthenz();
validateEndpoints(this.steps, globalServiceId, this.endpoints);
}
+
+ /** Validates the endpoints and makes sure default values are respected */
+ private List<Endpoint> validateEndpoints(List<Endpoint> endpoints, List<Step> steps) {
+ Objects.requireNonNull(endpoints, "Missing endpoints parameter");
+
+ var productionRegions = steps.stream()
+ .filter(step -> step.deploysTo(Environment.prod))
+ .flatMap(step -> step.zones().stream())
+ .flatMap(zone -> zone.region().stream())
+ .map(RegionName::value)
+ .collect(Collectors.toSet());
+
+ var rebuiltEndpointsList = new ArrayList<Endpoint>();
+
+ for (var endpoint : endpoints) {
+ if (endpoint.regions().isEmpty()) {
+ var rebuiltEndpoint = endpoint.withRegions(productionRegions);
+ rebuiltEndpointsList.add(rebuiltEndpoint);
+ } else {
+ rebuiltEndpointsList.add(endpoint);
+ }
+ }
+
+ return ImmutableList.copyOf(rebuiltEndpointsList);
+ }
/** Throw an IllegalArgumentException if the total delay exceeds 24 hours */
private void validateTotalDelay(List<Step> steps) {
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java b/config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java
index 158fbfb175f..e47dcd78219 100644
--- a/config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java
@@ -75,4 +75,7 @@ public class Endpoint {
return Objects.hash(endpointId, containerId, regions);
}
+ public Endpoint withRegions(Set<String> regions) {
+ return new Endpoint(endpointId, containerId, regions);
+ }
}
diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java
index 8120c82e8f4..47eaf7a515a 100644
--- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java
+++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java
@@ -14,6 +14,7 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static com.yahoo.config.application.api.Notifications.Role.author;
import static com.yahoo.config.application.api.Notifications.When.failing;
@@ -516,6 +517,28 @@ public class DeploymentSpecTest {
assertEquals(List.of("fooooooooooo"), endpointIds("<endpoint id='fooooooooooo' container-id='qrs'/>"));
}
+ @Test
+ public void endpointDefaultRegions() {
+ var spec = DeploymentSpec.fromXml("" +
+ "<deployment>" +
+ " <prod>" +
+ " <region active=\"true\">us-east</region>" +
+ " <region active=\"true\">us-west</region>" +
+ " </prod>" +
+ " <endpoints>" +
+ " <endpoint id=\"foo\" container-id=\"bar\">" +
+ " <region>us-east</region>" +
+ " </endpoint>" +
+ " <endpoint id=\"nalle\" container-id=\"frosk\" />" +
+ " <endpoint container-id=\"quux\" />" +
+ " </endpoints>" +
+ "</deployment>");
+
+ assertEquals(Set.of("us-east"), endpointRegions("foo", spec));
+ assertEquals(Set.of("us-east", "us-west"), endpointRegions("nalle", spec));
+ assertEquals(Set.of("us-east", "us-west"), endpointRegions("default", spec));
+ }
+
private static void assertInvalid(String endpointTag) {
try {
endpointIds(endpointTag);
@@ -523,6 +546,14 @@ public class DeploymentSpecTest {
} catch (IllegalArgumentException ignored) {}
}
+ private static Set<String> endpointRegions(String endpointId, DeploymentSpec spec) {
+ return spec.endpoints().stream()
+ .filter(endpoint -> endpoint.endpointId().equals(endpointId))
+ .flatMap(endpoint -> endpoint.regions().stream())
+ .map(RegionName::value)
+ .collect(Collectors.toSet());
+ }
+
private static List<String> endpointIds(String endpointTag) {
var xml = "<deployment>" +
" <prod>" +
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 f290911c6bd..34a7d3c16cf 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
@@ -9,7 +9,7 @@ import ai.vespa.metricsproxy.core.MetricsConsumers;
import ai.vespa.metricsproxy.core.MetricsManager;
import ai.vespa.metricsproxy.core.MonitoringConfig;
import ai.vespa.metricsproxy.core.VespaMetrics;
-import ai.vespa.metricsproxy.http.GenericMetricsHandler;
+import ai.vespa.metricsproxy.http.MetricsHandler;
import ai.vespa.metricsproxy.metric.ExternalMetrics;
import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensions;
import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensionsConfig;
@@ -49,8 +49,8 @@ import static com.yahoo.vespa.model.admin.metricsproxy.MetricsProxyContainerClus
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.admin.monitoring.DefaultPublicConsumer.getDefaultPublicConsumer;
-import static com.yahoo.vespa.model.admin.monitoring.VespaMetricsConsumer.getVespaMetricsConsumer;
import static com.yahoo.vespa.model.admin.monitoring.MetricSet.emptyMetricSet;
+import static com.yahoo.vespa.model.admin.monitoring.VespaMetricsConsumer.getVespaMetricsConsumer;
import static com.yahoo.vespa.model.container.xml.BundleMapper.JarSuffix.JAR_WITH_DEPS;
import static com.yahoo.vespa.model.container.xml.BundleMapper.absoluteBundlePath;
@@ -71,7 +71,7 @@ public class MetricsProxyContainerCluster extends ContainerCluster<MetricsProxyC
static final Path METRICS_PROXY_BUNDLE_FILE = absoluteBundlePath((Paths.get(METRICS_PROXY_NAME + JAR_WITH_DEPS.suffix)));
static final String METRICS_PROXY_BUNDLE_NAME = "com.yahoo.vespa." + METRICS_PROXY_NAME;
- private static final String METRICS_HANDLER_BINDING = "/metrics/v1/values";
+ private static final String METRICS_HANDLER_BINDING = "/metrics/v1";
static final class AppDimensionNames {
static final String ZONE = "zone";
@@ -113,7 +113,7 @@ public class MetricsProxyContainerCluster extends ContainerCluster<MetricsProxyC
private void addGenericMetricsHandler() {
Handler<AbstractConfigProducer<?>> metricsHandler = new Handler<>(
- new ComponentModel(GenericMetricsHandler.class.getName(), null, METRICS_PROXY_BUNDLE_NAME, null));
+ new ComponentModel(MetricsHandler.class.getName(), null, METRICS_PROXY_BUNDLE_NAME, null));
metricsHandler.addServerBindings("http://*" + METRICS_HANDLER_BINDING,
"http://*" + METRICS_HANDLER_BINDING + "/*");
addComponent(metricsHandler);
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/DefaultPublicConsumer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/DefaultPublicConsumer.java
index fbd1c7455dd..9c75b80c2f4 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/DefaultPublicConsumer.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/DefaultPublicConsumer.java
@@ -4,7 +4,7 @@
package com.yahoo.vespa.model.admin.monitoring;
-import ai.vespa.metricsproxy.http.GenericMetricsHandler;
+import ai.vespa.metricsproxy.http.ValuesFetcher;
import com.google.common.collect.ImmutableList;
import static com.yahoo.vespa.model.admin.monitoring.DefaultPublicMetrics.defaultPublicMetricSet;
@@ -17,7 +17,7 @@ import static java.util.Collections.emptyList;
*/
public class DefaultPublicConsumer {
- public static final String DEFAULT_PUBLIC_CONSUMER_ID = GenericMetricsHandler.DEFAULT_PUBLIC_CONSUMER_ID.id;
+ public static final String DEFAULT_PUBLIC_CONSUMER_ID = ValuesFetcher.DEFAULT_PUBLIC_CONSUMER_ID.id;
private static final MetricSet publicConsumerMetrics = new MetricSet("public-consumer-metrics",
emptyList(),
diff --git a/config-model/src/main/javacc/SDParser.jj b/config-model/src/main/javacc/SDParser.jj
index 6dde12f0fac..3141f7f7164 100644
--- a/config-model/src/main/javacc/SDParser.jj
+++ b/config-model/src/main/javacc/SDParser.jj
@@ -297,7 +297,7 @@ TOKEN :
| < MUTABLE: "mutable" >
| < FASTSEARCH: "fast-search" >
| < HUGE: "huge" >
-| < TENSOR_TYPE: "tensor(" (~["(",")"])+ ")" >
+| < TENSOR_TYPE: "tensor" ("<" (~["<",">"])+ ">")? "(" (~["(",")"])+ ")" >
| < TENSOR_VALUE_SL: "value" (" ")* ":" (" ")* ("{"<BRACE_SL_LEVEL_1>) ("\n")? >
| < TENSOR_VALUE_ML: "value" (<SEARCHLIB_SKIP>)? "{" (["\n"," "])* ("{"<BRACE_ML_LEVEL_1>) (["\n"," "])* "}" ("\n")? >
| < COMPRESSION: "compression" >
diff --git a/config-model/src/test/derived/tensor/attributes.cfg b/config-model/src/test/derived/tensor/attributes.cfg
index 4b54e67f8b8..f1c95da7084 100644
--- a/config-model/src/test/derived/tensor/attributes.cfg
+++ b/config-model/src/test/derived/tensor/attributes.cfg
@@ -61,3 +61,24 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype "tensor(x[10],y[20])"
attribute[].imported false
+attribute[].name "f5"
+attribute[].datatype TENSOR
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch false
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype "tensor<float>(x[10])"
+attribute[].imported false
diff --git a/config-model/src/test/derived/tensor/documenttypes.cfg b/config-model/src/test/derived/tensor/documenttypes.cfg
index 3b85e9b3a58..0b75644f4ae 100644
--- a/config-model/src/test/derived/tensor/documenttypes.cfg
+++ b/config-model/src/test/derived/tensor/documenttypes.cfg
@@ -40,6 +40,11 @@ documenttype[].datatype[].sstruct.field[].id 1224191509
documenttype[].datatype[].sstruct.field[].id_v6 1039544782
documenttype[].datatype[].sstruct.field[].datatype 21
documenttype[].datatype[].sstruct.field[].detailedtype "tensor(x[10],y[20])"
+documenttype[].datatype[].sstruct.field[].name "f5"
+documenttype[].datatype[].sstruct.field[].id 329055840
+documenttype[].datatype[].sstruct.field[].id_v6 105711688
+documenttype[].datatype[].sstruct.field[].datatype 21
+documenttype[].datatype[].sstruct.field[].detailedtype "tensor<float>(x[10])"
documenttype[].datatype[].id -1903234535
documenttype[].datatype[].type STRUCT
documenttype[].datatype[].array.element.id 0
@@ -59,3 +64,4 @@ documenttype[].fieldsets{[document]}.fields[] "f1"
documenttype[].fieldsets{[document]}.fields[] "f2"
documenttype[].fieldsets{[document]}.fields[] "f3"
documenttype[].fieldsets{[document]}.fields[] "f4"
+documenttype[].fieldsets{[document]}.fields[] "f5"
diff --git a/config-model/src/test/derived/tensor/rank-profiles.cfg b/config-model/src/test/derived/tensor/rank-profiles.cfg
index 471343da63c..87c0b6fab42 100644
--- a/config-model/src/test/derived/tensor/rank-profiles.cfg
+++ b/config-model/src/test/derived/tensor/rank-profiles.cfg
@@ -5,6 +5,8 @@ rankprofile[].fef.property[].name "vespa.type.attribute.f3"
rankprofile[].fef.property[].value "tensor(x{})"
rankprofile[].fef.property[].name "vespa.type.attribute.f4"
rankprofile[].fef.property[].value "tensor(x[10],y[20])"
+rankprofile[].fef.property[].name "vespa.type.attribute.f5"
+rankprofile[].fef.property[].value "tensor<float>(x[10])"
rankprofile[].name "unranked"
rankprofile[].fef.property[].name "vespa.rank.firstphase"
rankprofile[].fef.property[].value "value(0)"
@@ -20,6 +22,8 @@ rankprofile[].fef.property[].name "vespa.type.attribute.f3"
rankprofile[].fef.property[].value "tensor(x{})"
rankprofile[].fef.property[].name "vespa.type.attribute.f4"
rankprofile[].fef.property[].value "tensor(x[10],y[20])"
+rankprofile[].fef.property[].name "vespa.type.attribute.f5"
+rankprofile[].fef.property[].value "tensor<float>(x[10])"
rankprofile[].name "profile1"
rankprofile[].fef.property[].name "vespa.rank.firstphase"
rankprofile[].fef.property[].value "rankingExpression(firstphase)"
@@ -31,6 +35,8 @@ rankprofile[].fef.property[].name "vespa.type.attribute.f3"
rankprofile[].fef.property[].value "tensor(x{})"
rankprofile[].fef.property[].name "vespa.type.attribute.f4"
rankprofile[].fef.property[].value "tensor(x[10],y[20])"
+rankprofile[].fef.property[].name "vespa.type.attribute.f5"
+rankprofile[].fef.property[].value "tensor<float>(x[10])"
rankprofile[].name "profile2"
rankprofile[].fef.property[].name "vespa.rank.firstphase"
rankprofile[].fef.property[].value "rankingExpression(firstphase)"
@@ -42,6 +48,8 @@ rankprofile[].fef.property[].name "vespa.type.attribute.f3"
rankprofile[].fef.property[].value "tensor(x{})"
rankprofile[].fef.property[].name "vespa.type.attribute.f4"
rankprofile[].fef.property[].value "tensor(x[10],y[20])"
+rankprofile[].fef.property[].name "vespa.type.attribute.f5"
+rankprofile[].fef.property[].value "tensor<float>(x[10])"
rankprofile[].name "profile3"
rankprofile[].fef.property[].name "rankingExpression(joinedtensors).rankingScript"
rankprofile[].fef.property[].value "tensor(i[10])(i) * attribute(f4)"
@@ -57,3 +65,18 @@ rankprofile[].fef.property[].name "vespa.type.attribute.f3"
rankprofile[].fef.property[].value "tensor(x{})"
rankprofile[].fef.property[].name "vespa.type.attribute.f4"
rankprofile[].fef.property[].value "tensor(x[10],y[20])"
+rankprofile[].fef.property[].name "vespa.type.attribute.f5"
+rankprofile[].fef.property[].value "tensor<float>(x[10])"
+rankprofile[].name "profile4"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(attribute(f5), sum)"
+rankprofile[].fef.property[].name "vespa.type.attribute.f2"
+rankprofile[].fef.property[].value "tensor(x[2],y[])"
+rankprofile[].fef.property[].name "vespa.type.attribute.f3"
+rankprofile[].fef.property[].value "tensor(x{})"
+rankprofile[].fef.property[].name "vespa.type.attribute.f4"
+rankprofile[].fef.property[].value "tensor(x[10],y[20])"
+rankprofile[].fef.property[].name "vespa.type.attribute.f5"
+rankprofile[].fef.property[].value "tensor<float>(x[10])"
diff --git a/config-model/src/test/derived/tensor/summary.cfg b/config-model/src/test/derived/tensor/summary.cfg
index 5e5507836b0..903b6033297 100644
--- a/config-model/src/test/derived/tensor/summary.cfg
+++ b/config-model/src/test/derived/tensor/summary.cfg
@@ -1,5 +1,5 @@
-defaultsummaryid 289405525
-classes[].id 289405525
+defaultsummaryid 898020074
+classes[].id 898020074
classes[].name "default"
classes[].fields[].name "f1"
classes[].fields[].type "tensor"
@@ -7,13 +7,15 @@ classes[].fields[].name "f3"
classes[].fields[].type "tensor"
classes[].fields[].name "f4"
classes[].fields[].type "tensor"
+classes[].fields[].name "f5"
+classes[].fields[].type "tensor"
classes[].fields[].name "rankfeatures"
classes[].fields[].type "featuredata"
classes[].fields[].name "summaryfeatures"
classes[].fields[].type "featuredata"
classes[].fields[].name "documentid"
classes[].fields[].type "longstring"
-classes[].id 1860420340
+classes[].id 193983608
classes[].name "attributeprefetch"
classes[].fields[].name "f2"
classes[].fields[].type "tensor"
@@ -21,6 +23,8 @@ classes[].fields[].name "f3"
classes[].fields[].type "tensor"
classes[].fields[].name "f4"
classes[].fields[].type "tensor"
+classes[].fields[].name "f5"
+classes[].fields[].type "tensor"
classes[].fields[].name "rankfeatures"
classes[].fields[].type "featuredata"
classes[].fields[].name "summaryfeatures"
diff --git a/config-model/src/test/derived/tensor/tensor.sd b/config-model/src/test/derived/tensor/tensor.sd
index e3e8cf43347..622be033229 100644
--- a/config-model/src/test/derived/tensor/tensor.sd
+++ b/config-model/src/test/derived/tensor/tensor.sd
@@ -8,12 +8,15 @@ search tensor {
field f2 type tensor(x[2],y[]) {
indexing: attribute
}
- field f3 type tensor(x{}) {
+ field f3 type tensor<double>(x{}) {
indexing: attribute | summary
}
field f4 type tensor(x[10],y[20]) {
indexing: attribute | summary
}
+ field f5 type tensor<float>(x[10]) {
+ indexing: attribute | summary
+ }
}
rank-profile profile1 {
@@ -44,4 +47,12 @@ search tensor {
}
+ rank-profile profile4 {
+
+ first-phase {
+ expression: sum(attribute(f5))
+ }
+
+ }
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index c8640a6e074..192488c11ab 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -462,6 +462,9 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
long sessionId = getSessionIdForApplication(tenant, applicationId);
RemoteSession session = tenant.getRemoteSessionRepo().getSession(sessionId, 0);
return session.ensureApplicationLoaded().getForVersionOrLatest(version, clock.instant());
+ } catch (NotFoundException e) {
+ log.log(LogLevel.WARNING, "Failed getting application for '" + applicationId + "': " + e.getMessage());
+ throw e;
} catch (Exception e) {
log.log(LogLevel.WARNING, "Failed getting application for '" + applicationId + "'", e);
throw e;
diff --git a/configserver/src/main/sh/vespa-configserver-remove-state b/configserver/src/main/sh/vespa-configserver-remove-state
index faac37d48d4..c5cee479388 100755
--- a/configserver/src/main/sh/vespa-configserver-remove-state
+++ b/configserver/src/main/sh/vespa-configserver-remove-state
@@ -80,6 +80,9 @@ usage() {
echo "The following options are recognized:"
echo ""
+ echo "-h|-help) print this help text"
+ echo "-nosudo do not use sudo when running command"
+ echo "-sudo use sudo when running command"
echo "-force do not ask for confirmation before removal"
) >&2
}
@@ -101,7 +104,7 @@ while [ $# -gt 0 ]; do
-h|-help) usage; exit 0;;
-nosudo) shift; sudo="" ;;
-sudo) shift; sudo="sudo" ;;
- -force) shift; ask=false ;;
+ -force) shift; ask=false ;;
*) echo "Unrecognized option '$1'" >&2; usage; exit 1;;
esac
done
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java
index 95544c23db5..916a388692e 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java
@@ -5,8 +5,13 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeList;
+import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode;
+import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState;
+import java.util.Collection;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -17,8 +22,38 @@ import java.util.stream.Collectors;
*/
public interface NodeRepository {
+ void addNodes(ZoneId zone, Collection<NodeRepositoryNode> nodes);
+
+ void deleteNode(ZoneId zone, String hostname);
+
+ void setState(ZoneId zone, NodeState nodeState, String nodename);
+
+ NodeRepositoryNode getNode(ZoneId zone, String hostname);
+
+ NodeList listNodes(ZoneId zone);
+
+ NodeList listNodes(ZoneId zone, ApplicationId application);
+
/** List all nodes in zone owned by given application */
- List<Node> list(ZoneId zone, ApplicationId application);
+ default List<Node> list(ZoneId zone, ApplicationId application) {
+ return listNodes(zone, application).nodes().stream()
+ .map(n -> new Node(com.yahoo.config.provision.HostName.from(n.getHostname()),
+ fromJacksonState(n.getState()),
+ fromJacksonType(n.getType()), Optional.of(application),
+ Version.fromString(n.getVespaVersion()),
+ Version.fromString(n.getWantedVespaVersion()),
+ Version.fromString(n.getCurrentOsVersion()),
+ Version.fromString(n.getWantedOsVersion()),
+ fromBoolean(n.getAllowedToBeDown()),
+ n.getCurrentRestartGeneration(),
+ n.getRestartGeneration(),
+ n.getCurrentRebootGeneration(),
+ n.getRebootGeneration(),
+ n.getCanonicalFlavor(),
+ n.getMembership().clusterid,
+ clusterTypeOf(n.getMembership().clustertype)))
+ .collect(Collectors.toUnmodifiableList());
+ }
/** List all nodes in states, in zone owned by given application */
default List<Node> list(ZoneId zone, ApplicationId application, Set<Node.State> states) {
@@ -39,4 +74,47 @@ public interface NodeRepository {
/** Cancels firmware checks on all hosts in the given zone. */
void cancelFirmwareCheck(ZoneId zone);
+
+
+ private Node.ClusterType clusterTypeOf(String type) {
+ switch (type) {
+ case "admin": return Node.ClusterType.admin;
+ case "content": return Node.ClusterType.content;
+ case "container": return Node.ClusterType.container;
+ default: throw new IllegalArgumentException("Unknown cluster type '" + type + "'.");
+ }
+ }
+
+ // Convert Jackson type to config.provision type
+ private static NodeType fromJacksonType(com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeType nodeType) {
+ switch (nodeType) {
+ case tenant: return NodeType.tenant;
+ case host: return NodeType.host;
+ case proxy: return NodeType.proxy;
+ case proxyhost: return NodeType.proxyhost;
+ case config: return NodeType.config;
+ case confighost: return NodeType.confighost;
+ default: throw new IllegalArgumentException("Unknown type: " + nodeType);
+ }
+ }
+
+ private static com.yahoo.vespa.hosted.controller.api.integration.configserver.Node.State fromJacksonState(NodeState state) {
+ switch (state) {
+ case provisioned: return Node.State.provisioned;
+ case ready: return Node.State.ready;
+ case reserved: return Node.State.reserved;
+ case active: return Node.State.active;
+ case inactive: return Node.State.inactive;
+ case dirty: return Node.State.dirty;
+ case failed: return Node.State.failed;
+ case parked: return Node.State.parked;
+ default: throw new IllegalArgumentException("Unknown state: " + state);
+ }
+ }
+
+ private static Node.ServiceState fromBoolean(Boolean allowedDown) {
+ return (allowedDown == null)
+ ? Node.ServiceState.unorchestrated
+ : allowedDown ? Node.ServiceState.allowedDown : Node.ServiceState.expectedUp;
+ }
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/NodeRepositoryClientInterface.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/NodeRepositoryClientInterface.java
deleted file mode 100644
index 4b495ebf331..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/NodeRepositoryClientInterface.java
+++ /dev/null
@@ -1,58 +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.hosted.controller.api.integration.noderepository;
-
-import com.yahoo.config.provision.zone.ZoneId;
-
-import java.io.IOException;
-import java.util.Collection;
-
-/**
- * A complete client for the node repository REST API.
- *
- * @author smorgrav
- * @author bjorncs
- */
-// TODO: Get rid of all the checked exceptions
-// TODO: Replace remaining controller-server usages of this with
-// com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository and move this package back to internal
-// repo
-public interface NodeRepositoryClientInterface {
-
- enum WantTo {
- Retire,
- Deprovision
- }
-
- void addNodes(ZoneId zone, Collection<NodeRepositoryNode> nodes) throws IOException;
-
- NodeRepositoryNode getNode(ZoneId zone, String hostname) throws IOException;
-
- void deleteNode(ZoneId zone, String hostname) throws IOException;
-
- NodeList listNodes(ZoneId zone, boolean recursive) throws IOException;
-
- NodeList listNodes(ZoneId zone, String tenant, String applicationId, String instance) throws IOException;
-
- String resetFailureInformation(ZoneId zone, String nodename) throws IOException;
-
- String restart(ZoneId zone, String nodename) throws IOException;
-
- String reboot(ZoneId zone, String nodename) throws IOException;
-
- String cancelReboot(ZoneId zone, String nodename) throws IOException;
-
- String wantTo(ZoneId zone, String nodename, WantTo... actions) throws IOException;
-
- String cancelRestart(ZoneId zone, String nodename) throws IOException;
-
- String setHardwareFailureDescription(ZoneId zone, String nodename, String hardwareFailureDescription) throws IOException;
-
- void setState(ZoneId zone, NodeState nodeState, String nodename) throws IOException;
-
- String enableMaintenanceJob(ZoneId zone, String jobName) throws IOException;
-
- String disableMaintenanceJob(ZoneId zone, String jobName) throws IOException;
-
- MaintenanceJobList listMaintenanceJobs(ZoneId zone) throws IOException;
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
index 1ec75e0c998..08702027264 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
@@ -76,7 +76,8 @@ enum PathGroup {
"/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/logs",
"/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/suspended",
"/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/service/{*}",
- "/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/global-rotation/{*}"),
+ "/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/global-rotation/{*}",
+ "/application/v4/tenant/{tenant}/application/{application}/metering"),
/** Path used to restart development nodes. */
developmentRestart(Matcher.tenant,
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneApi.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneApi.java
deleted file mode 100644
index 7bb4bfc6467..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneApi.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.zone.v1;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import java.util.List;
-
-/**
- * Used by build system and command-line tool.
- *
- * @author smorgrav
- */
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-@Path(ZoneApi.API_VERSION)
-public interface ZoneApi {
-
- String API_VERSION = "v1";
-
- @GET
- @Path("")
- List<ZoneReference.Environment> listEnvironments();
-
- @GET
- @Path("/environment/{environment}")
- List<ZoneReference.Region> listRegions(@PathParam("environment") String env);
-
- @GET
- @Path("/environment/{environment}/default")
- ZoneReference.Region defaultRegion(@PathParam("environment") String env);
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneReference.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneReference.java
deleted file mode 100644
index 82d03d72acd..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/ZoneReference.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.zone.v1;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.net.URI;
-
-/**
- * @author smorgrav
- */
-public class ZoneReference {
-
- public static class Environment {
- @JsonProperty("name")
- private String name;
-
- @JsonProperty("url")
- private URI url;
-
- public String getName() {
- return name;
- }
-
- public Environment setName(String name) {
- this.name = name;
- return this;
- }
-
- public URI getUrl() {
- return url;
- }
-
- public Environment setUrl(URI url) {
- this.url = url;
- return this;
- }
- }
-
- public static class Region {
- @JsonProperty("name")
- private String name;
-
- @JsonProperty("url")
- private URI url;
-
- public String getName() {
- return name;
- }
-
- public Region setName(String name) {
- this.name = name;
- return this;
- }
-
- public URI getUrl() {
- return url;
- }
-
- public Region setUrl(URI url) {
- this.url = url;
- return this;
- }
- }
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/package-info.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/package-info.java
deleted file mode 100644
index e3275ff35fa..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v1/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@ExportPackage
-package com.yahoo.vespa.hosted.controller.api.zone.v1;
-
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java
deleted file mode 100644
index a6d7614e862..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.zone.v2;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId;
-import com.yahoo.vespa.hosted.controller.api.identifiers.EnvironmentId;
-import com.yahoo.vespa.hosted.controller.api.identifiers.InstanceId;
-import com.yahoo.vespa.hosted.controller.api.identifiers.RegionId;
-import com.yahoo.vespa.hosted.controller.api.identifiers.TenantId;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.MaintenanceJobList;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeList;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState;
-import com.yahoo.vespa.hosted.controller.api.integration.routing.RotationStatus;
-import com.yahoo.vespa.hosted.controller.api.integration.routing.status.StatusReply;
-import com.yahoo.vespa.hosted.controller.api.integration.routing.status.ZoneStatusReply;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Aka the controller proxy service.
- *
- * Proxies calls to correct config server with the additional feature of
- * retry and fail detection (ping).
- */
-@Path(ZoneApiV2.API_VERSION)
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-public interface ZoneApiV2 {
-
- String API_VERSION = "v2";
-
- @GET
- @Path("/")
- ZoneReferences listZones();
-
- @GET
- @Path("/{environment}/{region}/{proxy_request: .+}")
- Response proxyGet(
- @PathParam("environment") String env,
- @PathParam("region") String region,
- @PathParam("proxy_request") String proxyRequest);
-
- @POST
- @Path("/{environment}/{region}/{proxy_request: .+}")
- Response proxyPost(
- @PathParam("environment") String env,
- @PathParam("region") String region,
- @PathParam("proxy_request") String proxyRequest);
-
- @PUT
- @Path("/{environment}/{region}/{proxy_request: .+}")
- Response proxyPut(
- @PathParam("environment") String env,
- @PathParam("region") String region,
- @PathParam("proxy_request") String proxyRequest);
-
- @DELETE
- @Path("/{environment}/{region}/{proxy_request: .+}")
- Response proxyDelete(
- @PathParam("environment") String env,
- @PathParam("region") String region,
- @PathParam("proxy_request") String proxyRequest);
-
- // Explicit mappings of some proxy requests (to enable creation of proxy clients with javax.ws.rs)
-
- @GET
- @Path("/{environmentId}/{regionId}/application/v2/tenant/{tenantId}/application/{applicationId}/environment/{environmentId}/region/{regionId}/instance/{instanceId}/serviceconverge")
- Response waitForConfigConvergeV2(@PathParam("tenantId") TenantId tenantId,
- @PathParam("applicationId") ApplicationId applicationId,
- @PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("instanceId") InstanceId instanceId,
- @QueryParam("timeout") long timeoutInSeconds);
- @GET
- @Path("/{environmentId}/{regionId}/application/v2/tenant/{tenantId}/application/{applicationId}/environment/{environmentId}/region/{regionId}/instance/{instanceId}/serviceconverge/{host}")
- Response waitForConfigConvergeV2(@PathParam("tenantId") TenantId tenantId,
- @PathParam("applicationId") ApplicationId applicationId,
- @PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("instanceId") InstanceId instanceId,
- @PathParam("host") String host,
- @QueryParam("timeout") long timeoutInSeconds);
-
- @GET
- @Path("/{environmentId}/{regionId}/config/v2/tenant/{tenantId}/application/{applicationId}/prelude.fastsearch.documentdb-info/{clusterid}/search/cluster.{clusterid}")
- JsonNode getConfigWithDocumentTypes(@PathParam("tenantId") TenantId tenantId,
- @PathParam("applicationId") ApplicationId applicationId,
- @PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("clusterid") String clusterid,
- @QueryParam("timeout") long timeoutInSeconds);
-
- @GET
- @Path("/{environmentId}/{regionId}/config/v2/tenant/{tenantId}/application/{applicationId}/environment/{environmentId}/region/{regionId}/instance/{instanceId}/cloud.config.cluster-list")
- JsonNode getVespaConfigClusterList(@PathParam("tenantId") TenantId tenantId,
- @PathParam("applicationId") ApplicationId applicationId,
- @PathParam("instanceId") InstanceId instanceId,
- @PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @QueryParam("timeout") long timeoutInSeconds);
-
-
- @POST
- @Path("/{environmentId}/{regionId}/nodes/v2/node")
- String addNodes(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- Collection<NodeRepositoryNode> node);
-
- @DELETE
- @Path("/{environmentId}/{regionId}/nodes/v2/node/{hostname}")
- String deleteNode(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("hostname") String hostname);
-
- @GET
- @Path("/{environmentId}/{regionId}/nodes/v2/node/{hostname}")
- NodeRepositoryNode getNode(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("hostname") String hostname);
-
- @POST
- @Path("/{environmentId}/{regionId}/nodes/v2/node/{hostname}")
- String patchNode(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("hostname") String hostname,
- NodeRepositoryNode patchValues,
- @HeaderParam("X-HTTP-Method-Override") String patchOverride);
-
- @GET
- @Path("/{environmentId}/{regionId}/nodes/v2/node/")
- NodeList listNodes(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @QueryParam("recursive") boolean recursive);
-
- @GET
- @Path("/{environmentId}/{regionId}/nodes/v2/node/")
- NodeList listNodes(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @QueryParam("application") String applicationString,
- @QueryParam("recursive") boolean recursive);
-
- @PUT
- @Path("/{environmentId}/{regionId}/nodes/v2/state/{state}/{hostname}")
- String setNodeState(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("state") NodeState state,
- @PathParam("hostname") String hostname);
-
- @POST
- @Path("/{environmentId}/{regionId}/nodes/v2/command/reboot")
- String rebootNode(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @QueryParam("hostname") String hostname);
-
- @POST
- @Path("/{environmentId}/{regionId}/nodes/v2/command/restart")
- String restartNode(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @QueryParam("hostname") String hostname);
-
- @GET
- @Path("/{environmentId}/{regionId}/nodes/v2/maintenance/")
- MaintenanceJobList listMaintenanceJobs(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId);
-
- @POST
- @Path("/{environmentId}/{regionId}/nodes/v2/maintenance/inactive/{jobname}")
- String disableMaintenanceJob(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("jobname") String jobname);
-
- @DELETE
- @Path("/{environmentId}/{regionId}/nodes/v2/maintenance/inactive/{jobname}")
- String enableMaintenanceJob(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("jobname") String jobname);
-
-
- @GET
- @Path("/{environmentId}/{regionId}/orchestrator/v1/suspensions/applications")
- Set<String> getApplications(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId);
-
- @GET
- @Path("/{environmentId}/{regionId}/orchestrator/v1/suspensions/applications/{application}")
- void getApplication(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("application") String applicationIdString);
-
- @POST
- @Path("/{environmentId}/{regionId}/orchestrator/v1/suspensions/applications")
- void suspendApplication(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- String applicationIdString);
-
- @DELETE
- @Path("/{environmentId}/{regionId}/orchestrator/v1/suspensions/applications/{application}")
- void resumeApplication(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("application") String applicationIdString);
-
- /**
- * Get names of all rotations with the status OUT
- *
- * @return List of rotation names.
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/{environmentId}/{regionId}/routing/v1/status")
- List<String> listRotations(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId);
-
- /**
- * Get the status of a rotation
- *
- * @param rotation The name of a rotation.
- * @return The current status of the rotation, wrapped into a {@link StatusReply} object. The value is {@link
- * RotationStatus#IN} for any rotation that has not been explicitly set to {@link RotationStatus#OUT} using {@link
- * #setRotationStatus(EnvironmentId, RegionId, String, StatusReply)}.
- */
- @GET
- @Path("/{environmentId}/{regionId}/routing/v1/status/{rotation}")
- @Produces(MediaType.APPLICATION_JSON)
- StatusReply getRotationStatus(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("rotation") String rotation);
-
- /**
- * Set or modify rotation status according to payload
- *
- * @param rotation The rotation (endpoint) to modify
- * @param payload The name/status/agent/reason to set
- * @return The updated status of the rotation wrapped into a {@link StatusReply} object.
- */
- @PUT
- @Path("/{environmentId}/{regionId}/routing/v1/status/{rotation}")
- @Produces(MediaType.APPLICATION_JSON)
- @Consumes(MediaType.APPLICATION_JSON)
- StatusReply setRotationStatus(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("rotation") String rotation,
- StatusReply payload);
-
- /**
- * Set the status of a rotation to IN
- *
- * @param rotation The name of a rotation.
- * @return The updated status of the rotation wrapped into a {@link StatusReply} object.
- */
- @DELETE
- @Path("/{environmentId}/{regionId}/routing/v1/status/{rotation}")
- @Produces(MediaType.APPLICATION_JSON)
- @Deprecated
- StatusReply unsetRotation(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId,
- @PathParam("rotation") String rotation);
-
- /**
- * Set the status of the zone to OUT
- * @return The updated status of the zone wrapped into a {@link ZoneStatusReply} object.
- */
- @PUT
- @Path("/{environmentId}/{regionId}/routing/v1/status/zone")
- @Produces(MediaType.APPLICATION_JSON)
- ZoneStatusReply setZoneRotationInactive(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId);
-
- /**
- * Clears the status of the zone. The routing check will fall back to check individual rotations.
- * @return The updated status of the zone wrapped into a {@link ZoneStatusReply} object.
- */
- @DELETE
- @Path("/{environmentId}/{regionId}/routing/v1/status/zone")
- @Produces(MediaType.APPLICATION_JSON)
- ZoneStatusReply unsetZoneRotationInactive(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId);
-
- /**
- * Get the status of the zone
- * @return The status of the zone wrapped into a {@link ZoneStatusReply} object.
- */
- @GET
- @Path("/{environmentId}/{regionId}/routing/v1/status/zone")
- @Produces(MediaType.APPLICATION_JSON)
- ZoneStatusReply getZoneRotationStatus(@PathParam("environmentId") EnvironmentId environmentId,
- @PathParam("regionId") RegionId regionId);
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReference.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReference.java
deleted file mode 100644
index 95dc1c2ee7c..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReference.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.zone.v2;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.yahoo.vespa.hosted.controller.api.configserver.Environment;
-import com.yahoo.vespa.hosted.controller.api.configserver.Region;
-
-/**
- * @author mpolden
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class ZoneReference {
-
- @JsonProperty("environment")
- public final Environment environment;
- @JsonProperty("region")
- public final Region region;
-
- @JsonCreator
- public ZoneReference(@JsonProperty("environment") Environment environment, @JsonProperty("region") Region region) {
- this.environment = environment;
- this.region = region;
- }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReferences.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReferences.java
deleted file mode 100644
index 3a219afa0a6..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneReferences.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.zone.v2;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Wire format for listing the controller URIs for all the available zones
- *
- * @author smorgrav
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class ZoneReferences {
-
- @JsonProperty("uris")
- public final List<String> uris;
-
- @JsonProperty("zones")
- public final List<ZoneReference> zones;
-
- @JsonCreator
- public ZoneReferences(@JsonProperty("uris") List<String> uris, @JsonProperty("zones") List<ZoneReference> zones) {
- this.uris = Collections.unmodifiableList(uris);
- this.zones = Collections.unmodifiableList(zones);
- }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/package-info.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/package-info.java
deleted file mode 100644
index 5d4b1310981..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@ExportPackage
-package com.yahoo.vespa.hosted.controller.api.zone.v2;
-
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java
index c99e4f5951b..d9aaef6ef3b 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java
@@ -5,8 +5,8 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeList;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryClientInterface;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode;
import com.yahoo.vespa.hosted.controller.application.ClusterInfo;
import com.yahoo.vespa.hosted.controller.application.Deployment;
@@ -31,13 +31,13 @@ public class ClusterInfoMaintainer extends Maintainer {
private static final Logger log = Logger.getLogger(ClusterInfoMaintainer.class.getName());
private final Controller controller;
- private final NodeRepositoryClientInterface nodeRepositoryClient;
+ private final NodeRepository nodeRepository;
ClusterInfoMaintainer(Controller controller, Duration duration, JobControl jobControl,
- NodeRepositoryClientInterface nodeRepositoryClient) {
+ NodeRepository nodeRepository) {
super(controller, duration, jobControl);
this.controller = controller;
- this.nodeRepositoryClient = nodeRepositoryClient;
+ this.nodeRepository = nodeRepository;
}
private static String clusterId(NodeRepositoryNode node) {
@@ -81,10 +81,7 @@ public class ClusterInfoMaintainer extends Maintainer {
for (Deployment deployment : application.deployments().values()) {
DeploymentId deploymentId = new DeploymentId(application.id(), deployment.zone());
try {
- NodeList nodes = nodeRepositoryClient.listNodes(deploymentId.zoneId(),
- deploymentId.applicationId().tenant().value(),
- deploymentId.applicationId().application().value(),
- deploymentId.applicationId().instance().value());
+ NodeList nodes = nodeRepository.listNodes(deploymentId.zoneId(), deploymentId.applicationId());
Map<ClusterSpec.Id, ClusterInfo> clusterInfo = getClusterInfo(nodes);
controller().applications().lockIfPresent(application.id(), lockedApplication ->
controller.applications().store(lockedApplication.withClusterInfo(deployment.zone(), clusterInfo)));
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
index f34c24c497a..116ea532a11 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
@@ -5,8 +5,8 @@ import com.yahoo.component.AbstractComponent;
import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.jdisc.Metric;
import com.yahoo.vespa.hosted.controller.Controller;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
import com.yahoo.vespa.hosted.controller.api.integration.dns.NameService;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryClientInterface;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Billing;
import com.yahoo.vespa.hosted.controller.api.integration.organization.ContactRetriever;
import com.yahoo.vespa.hosted.controller.api.integration.organization.DeploymentIssues;
@@ -60,7 +60,7 @@ public class ControllerMaintenance extends AbstractComponent {
public ControllerMaintenance(MaintainerConfig maintainerConfig, ApiAuthorityConfig apiAuthorityConfig, Controller controller, CuratorDb curator,
JobControl jobControl, Metric metric,
DeploymentIssues deploymentIssues, OwnershipIssues ownershipIssues,
- NameService nameService, NodeRepositoryClientInterface nodeRepositoryClient,
+ NameService nameService, NodeRepository nodeRepository,
ContactRetriever contactRetriever,
CostReportConsumer reportConsumer,
ResourceSnapshotConsumer resourceSnapshotConsumer,
@@ -75,7 +75,7 @@ public class ControllerMaintenance extends AbstractComponent {
versionStatusUpdater = new VersionStatusUpdater(controller, Duration.ofMinutes(1), jobControl);
upgrader = new Upgrader(controller, maintenanceInterval, jobControl, curator);
readyJobsTrigger = new ReadyJobsTrigger(controller, Duration.ofMinutes(1), jobControl);
- clusterInfoMaintainer = new ClusterInfoMaintainer(controller, Duration.ofHours(2), jobControl, nodeRepositoryClient);
+ clusterInfoMaintainer = new ClusterInfoMaintainer(controller, Duration.ofHours(2), jobControl, nodeRepository);
clusterUtilizationMaintainer = new ClusterUtilizationMaintainer(controller, Duration.ofHours(2), jobControl);
deploymentMetricsMaintainer = new DeploymentMetricsMaintainer(controller, Duration.ofMinutes(5), jobControl);
applicationOwnershipConfirmer = new ApplicationOwnershipConfirmer(controller, Duration.ofHours(12), jobControl, ownershipIssues);
@@ -84,8 +84,8 @@ public class ControllerMaintenance extends AbstractComponent {
osUpgraders = osUpgraders(controller, jobControl);
osVersionStatusUpdater = new OsVersionStatusUpdater(controller, maintenanceInterval, jobControl);
contactInformationMaintainer = new ContactInformationMaintainer(controller, Duration.ofHours(12), jobControl, contactRetriever);
- costReportMaintainer = new CostReportMaintainer(controller, Duration.ofHours(2), reportConsumer, jobControl, nodeRepositoryClient, Clock.systemUTC(), selfHostedCostConfig);
- resourceMeterMaintainer = new ResourceMeterMaintainer(controller, Duration.ofMinutes(60), jobControl, nodeRepositoryClient, Clock.systemUTC(), metric, resourceSnapshotConsumer);
+ costReportMaintainer = new CostReportMaintainer(controller, Duration.ofHours(2), reportConsumer, jobControl, nodeRepository, Clock.systemUTC(), selfHostedCostConfig);
+ resourceMeterMaintainer = new ResourceMeterMaintainer(controller, Duration.ofMinutes(60), jobControl, nodeRepository, Clock.systemUTC(), metric, resourceSnapshotConsumer);
nameServiceDispatcher = new NameServiceDispatcher(controller, Duration.ofSeconds(10), jobControl, nameService);
billingMaintainer = new BillingMaintainer(controller, Duration.ofDays(3), jobControl, billing);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java
index 30bca180c0f..f3dac2be22e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java
@@ -5,7 +5,7 @@ import com.google.inject.Inject;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.vespa.hosted.controller.Controller;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryClientInterface;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
import com.yahoo.vespa.hosted.controller.restapi.cost.CostCalculator;
import com.yahoo.vespa.hosted.controller.restapi.cost.CostReportConsumer;
import com.yahoo.vespa.hosted.controller.restapi.cost.config.SelfHostedCostConfig;
@@ -27,7 +27,7 @@ public class CostReportMaintainer extends Maintainer {
private static final Logger log = Logger.getLogger(CostReportMaintainer.class.getName());
private final CostReportConsumer consumer;
- private final NodeRepositoryClientInterface nodeRepository;
+ private final NodeRepository nodeRepository;
private final Clock clock;
private final SelfHostedCostConfig selfHostedCostConfig;
@@ -36,7 +36,7 @@ public class CostReportMaintainer extends Maintainer {
public CostReportMaintainer(Controller controller, Duration interval,
CostReportConsumer consumer,
JobControl jobControl,
- NodeRepositoryClientInterface nodeRepository,
+ NodeRepository nodeRepository,
Clock clock,
SelfHostedCostConfig selfHostedCostConfig) {
super(controller, interval, jobControl, "CostReportMaintainer", EnumSet.of(SystemName.main));
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
index c4f0597572b..5e2ba48da3f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
@@ -1,29 +1,28 @@
// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.maintenance;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.SystemName;
-import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.jdisc.Metric;
import com.yahoo.vespa.hosted.controller.Controller;
-import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeOwner;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryClientInterface;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState;
+import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceAllocation;
import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot;
import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshotConsumer;
-import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceAllocation;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
-import java.util.*;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import static com.yahoo.yolean.Exceptions.uncheck;
-
/**
* Creates a ResourceSnapshot per application, which is then passed on to a ResourceSnapshotConsumer
* TODO: Write JSON blob of node repo somewhere
@@ -34,7 +33,7 @@ public class ResourceMeterMaintainer extends Maintainer {
private final Clock clock;
private final Metric metric;
- private final NodeRepositoryClientInterface nodeRepository;
+ private final NodeRepository nodeRepository;
private final ResourceSnapshotConsumer resourceSnapshotConsumer;
private static final String metering_last_reported = "metering_last_reported";
@@ -44,7 +43,7 @@ public class ResourceMeterMaintainer extends Maintainer {
public ResourceMeterMaintainer(Controller controller,
Duration interval,
JobControl jobControl,
- NodeRepositoryClientInterface nodeRepository,
+ NodeRepository nodeRepository,
Clock clock,
Metric metric,
ResourceSnapshotConsumer resourceSnapshotConsumer) {
@@ -83,24 +82,17 @@ public class ResourceMeterMaintainer extends Maintainer {
return controller().zoneRegistry().zones()
.ofCloud(CloudName.from("aws"))
.reachable().zones().stream()
- .flatMap(zone -> uncheck(() -> nodeRepository.listNodes(zone.getId(), true).nodes().stream()))
+ .flatMap(zone -> nodeRepository.listNodes(zone.getId()).nodes().stream())
.filter(node -> node.getOwner() != null && !node.getOwner().getTenant().equals("hosted-vespa"))
.filter(node -> node.getState() == NodeState.active)
.collect(Collectors.toList());
}
private Map<ApplicationId, ResourceAllocation> getResourceAllocationByApplication(List<NodeRepositoryNode> nodes) {
- Map<ApplicationId, List<NodeRepositoryNode>> applicationNodes = new HashMap<>();
-
- nodes.stream().forEach(node -> applicationNodes.computeIfAbsent(applicationIdFromNodeOwner(node.getOwner()), n -> new ArrayList<>()).add(node));
-
- return applicationNodes.entrySet().stream()
- .collect(
- Collectors.toMap(
- entry -> entry.getKey(),
- entry -> ResourceAllocation.from(entry.getValue())
- )
- );
+ return nodes.stream()
+ .collect(Collectors.groupingBy(
+ node -> applicationIdFromNodeOwner(node.getOwner()),
+ Collectors.collectingAndThen(Collectors.toList(), ResourceAllocation::from)));
}
private ApplicationId applicationIdFromNodeOwner(NodeOwner owner) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 9c320df2f6c..868272e5051 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -176,6 +176,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
if (path.matches("/application/v4/tenant/{tenant}/application/{application}")) return application(path.get("tenant"), path.get("application"), "default", request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying")) return deploying(path.get("tenant"), path.get("application"), "default", request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying/pin")) return deploying(path.get("tenant"), path.get("application"), "default", request);
+ if (path.matches("/application/v4/tenant/{tenant}/application/{application}/metering")) return metering(path.get("tenant"), path.get("application"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/nodes")) return nodes(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"));
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/logs")) return logs(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"), request.propertyMap());
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance")) return applications(path.get("tenant"), Optional.of(path.get("application")), request);
@@ -772,6 +773,45 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new SlimeJsonResponse(slime);
}
+ private HttpResponse metering(String tenant, String application, HttpRequest request) {
+ Slime slime = new Slime();
+ Cursor root = slime.setObject();
+
+ Cursor currentRate = root.setObject("currentrate");
+ currentRate.setDouble("cpu", 0);
+ currentRate.setDouble("mem", 0);
+ currentRate.setDouble("disk", 0);
+
+ Cursor thismonth = root.setObject("thismonth");
+ thismonth.setDouble("cpu", 0);
+ thismonth.setDouble("mem", 0);
+ thismonth.setDouble("disk", 0);
+
+ Cursor lastmonth = root.setObject("lastmonth");
+ lastmonth.setDouble("cpu", 0);
+ lastmonth.setDouble("mem", 0);
+ lastmonth.setDouble("disk", 0);
+
+ Cursor details = root.setObject("details");
+
+ Cursor detailsCpu = details.setObject("cpu");
+ Cursor detailsCpuDummyApp = detailsCpu.setObject("dummy");
+ Cursor detailsCpuDummyData = detailsCpuDummyApp.setArray("data");
+
+ // The data array should be filled with objects like: { unixms: <number>, valur: <number }
+
+ Cursor detailsMem = details.setObject("mem");
+ Cursor detailsMemDummyApp = detailsMem.setObject("dummy");
+ Cursor detailsMemDummyData = detailsMemDummyApp.setArray("data");
+
+ Cursor detailsDisk = details.setObject("disk");
+ Cursor detailsDiskDummyApp = detailsDisk.setObject("dummy");
+ Cursor detailsDiskDummyData = detailsDiskDummyApp.setArray("data");
+
+
+ return new SlimeJsonResponse(slime);
+ }
+
private HttpResponse deploying(String tenant, String application, String instance, HttpRequest request) {
Application app = controller.applications().require(ApplicationId.from(tenant, application, instance));
Slime slime = new Slime();
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostApiHandler.java
index bae790a49ad..796f786d823 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostApiHandler.java
@@ -6,7 +6,7 @@ import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.container.jdisc.LoggingRequestHandler;
import com.yahoo.restapi.Path;
import com.yahoo.vespa.hosted.controller.Controller;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryClientInterface;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
import com.yahoo.vespa.hosted.controller.restapi.ErrorResponse;
import com.yahoo.vespa.hosted.controller.restapi.StringResponse;
import com.yahoo.vespa.hosted.controller.restapi.cost.config.SelfHostedCostConfig;
@@ -19,10 +19,10 @@ import static com.yahoo.jdisc.http.HttpRequest.Method.GET;
public class CostApiHandler extends LoggingRequestHandler {
private final Controller controller;
- private final NodeRepositoryClientInterface nodeRepository;
+ private final NodeRepository nodeRepository;
private final SelfHostedCostConfig selfHostedCostConfig;
- public CostApiHandler(Context ctx, Controller controller, NodeRepositoryClientInterface nodeRepository, SelfHostedCostConfig selfHostedCostConfig) {
+ public CostApiHandler(Context ctx, Controller controller, NodeRepository nodeRepository, SelfHostedCostConfig selfHostedCostConfig) {
super(ctx);
this.controller = controller;
this.nodeRepository = nodeRepository;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostCalculator.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostCalculator.java
index c44a80f7a20..919cade1b05 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostCalculator.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/cost/CostCalculator.java
@@ -2,11 +2,10 @@ package com.yahoo.vespa.hosted.controller.restapi.cost;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
-import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.api.identifiers.Property;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeOwner;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryClientInterface;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode;
import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceAllocation;
import com.yahoo.vespa.hosted.controller.restapi.cost.config.SelfHostedCostConfig;
@@ -26,7 +25,7 @@ public class CostCalculator {
private static final double SELF_HOSTED_DISCOUNT = .5;
- public static String resourceShareByPropertyToCsv(NodeRepositoryClientInterface nodeRepository,
+ public static String resourceShareByPropertyToCsv(NodeRepository nodeRepository,
Controller controller,
Clock clock,
SelfHostedCostConfig selfHostedCostConfig,
@@ -36,7 +35,7 @@ public class CostCalculator {
List<NodeRepositoryNode> nodes = controller.zoneRegistry().zones()
.reachable().in(Environment.prod).ofCloud(cloudName).zones().stream()
- .flatMap(zone -> uncheck(() -> nodeRepository.listNodes(zone.getId(), true).nodes().stream()))
+ .flatMap(zone -> uncheck(() -> nodeRepository.listNodes(zone.getId()).nodes().stream()))
.filter(node -> node.getOwner() != null && !node.getOwner().getTenant().equals("hosted-vespa"))
.collect(Collectors.toList());
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
index c26f1879f6a..0cf54db4d3a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
@@ -43,6 +43,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -358,6 +359,7 @@ public class ControllerTest {
.environment(Environment.prod)
.endpoint("foobar", "qrs", "us-west-1", "us-central-1")
.endpoint("default", "qrs", "us-west-1", "us-central-1")
+ .endpoint("all", "qrs")
.region("us-west-1")
.region("us-central-1")
.build();
@@ -370,24 +372,31 @@ public class ControllerTest {
Set.of(
"rotation-id-01",
"rotation-id-02",
+ "rotation-id-03",
"app1--tenant1.global.vespa.oath.cloud",
- "foobar--app1--tenant1.global.vespa.oath.cloud"
+ "foobar--app1--tenant1.global.vespa.oath.cloud",
+ "all--app1--tenant1.global.vespa.oath.cloud"
),
tester.configServer().rotationNames().get(new DeploymentId(application.id(), deployment.zone())));
}
tester.flushDnsRequests();
- assertEquals(2, tester.controllerTester().nameService().records().size());
+ assertEquals(3, tester.controllerTester().nameService().records().size());
var record1 = tester.controllerTester().findCname("app1--tenant1.global.vespa.oath.cloud");
assertTrue(record1.isPresent());
assertEquals("app1--tenant1.global.vespa.oath.cloud", record1.get().name().asString());
- assertEquals("rotation-fqdn-02.", record1.get().data().asString());
+ assertEquals("rotation-fqdn-03.", record1.get().data().asString());
var record2 = tester.controllerTester().findCname("foobar--app1--tenant1.global.vespa.oath.cloud");
assertTrue(record2.isPresent());
assertEquals("foobar--app1--tenant1.global.vespa.oath.cloud", record2.get().name().asString());
assertEquals("rotation-fqdn-01.", record2.get().data().asString());
+
+ var record3 = tester.controllerTester().findCname("all--app1--tenant1.global.vespa.oath.cloud");
+ assertTrue(record3.isPresent());
+ assertEquals("all--app1--tenant1.global.vespa.oath.cloud", record3.get().name().asString());
+ assertEquals("rotation-fqdn-02.", record3.get().data().asString());
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryClientMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryClientMock.java
index 1c7abd2489d..4f2d85adfbe 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryClientMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryClientMock.java
@@ -1,14 +1,16 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.integration;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.MaintenanceJobList;
+import com.yahoo.component.Version;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeList;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeMembership;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeOwner;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryClientInterface;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode;
import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState;
-import com.yahoo.config.provision.zone.ZoneId;
import java.util.Collection;
import java.util.List;
@@ -16,7 +18,7 @@ import java.util.List;
/**
* @author bjorncs
*/
-public class NodeRepositoryClientMock implements NodeRepositoryClientInterface {
+public class NodeRepositoryClientMock implements NodeRepository {
@Override
public void addNodes(ZoneId zone, Collection<NodeRepositoryNode> nodes) {
@@ -34,14 +36,14 @@ public class NodeRepositoryClientMock implements NodeRepositoryClientInterface {
}
@Override
- public NodeList listNodes(ZoneId zone, boolean recursive) {
+ public NodeList listNodes(ZoneId zone) {
NodeRepositoryNode nodeA = createNodeA();
NodeRepositoryNode nodeB = createNodeB();
return new NodeList(List.of(nodeA, nodeB));
}
@Override
- public NodeList listNodes(ZoneId zone, String tenant, String applicationId, String instance) {
+ public NodeList listNodes(ZoneId zone, ApplicationId application) {
NodeRepositoryNode nodeA = createNodeA();
NodeRepositoryNode nodeB = createNodeB();
return new NodeList(List.of(nodeA, nodeB));
@@ -90,57 +92,27 @@ public class NodeRepositoryClientMock implements NodeRepositoryClientInterface {
}
@Override
- public String resetFailureInformation(ZoneId zone, String nodename) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String restart(ZoneId zone, String nodename) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String reboot(ZoneId zone, String nodename) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String cancelReboot(ZoneId zone, String nodename) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String wantTo(ZoneId zone, String nodename, WantTo... actions) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String cancelRestart(ZoneId zone, String nodename) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String setHardwareFailureDescription(ZoneId zone, String nodename, String hardwareFailureDescription) {
+ public void setState(ZoneId zone, NodeState nodeState, String nodename) {
throw new UnsupportedOperationException();
}
@Override
- public void setState(ZoneId zone, NodeState nodeState, String nodename) {
+ public void upgrade(ZoneId zone, NodeType type, Version version) {
throw new UnsupportedOperationException();
}
@Override
- public String enableMaintenanceJob(ZoneId zone, String jobName) {
+ public void upgradeOs(ZoneId zone, NodeType type, Version version) {
throw new UnsupportedOperationException();
}
@Override
- public String disableMaintenanceJob(ZoneId zone, String jobName) {
+ public void requestFirmwareCheck(ZoneId zone) {
throw new UnsupportedOperationException();
}
@Override
- public MaintenanceJobList listMaintenanceJobs(ZoneId zone) {
+ public void cancelFirmwareCheck(ZoneId zone) {
throw new UnsupportedOperationException();
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
index 49bc910ac33..45c2df5cb77 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
@@ -5,11 +5,15 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
-import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeList;
+import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode;
+import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -56,6 +60,36 @@ public class NodeRepositoryMock implements NodeRepository {
}
@Override
+ public void addNodes(ZoneId zone, Collection<NodeRepositoryNode> nodes) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void deleteNode(ZoneId zone, String hostname) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setState(ZoneId zone, NodeState nodeState, String nodename) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public NodeRepositoryNode getNode(ZoneId zone, String hostname) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public NodeList listNodes(ZoneId zone) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public NodeList listNodes(ZoneId zone, ApplicationId application) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public List<Node> list(ZoneId zone, ApplicationId application) {
return nodeRepository.getOrDefault(zone, Collections.emptyMap()).values().stream()
.filter(node -> node.owner().map(application::equals).orElse(false))
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index 29931a1f626..577b8491bd2 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -856,7 +856,15 @@ public class ApplicationApiTest extends ControllerContainerTest {
.userIdentity(USER_ID),
new File("application-without-change-multiple-deployments.json"));
}
-
+
+ @Test
+ public void testMeteringResponses() {
+ tester.assertResponse(request("/application/v4/tenant/doesnotexist/application/doesnotexist/metering", GET)
+ .userIdentity(USER_ID)
+ .oktaAccessToken(OKTA_AT),
+ new File("application1-metering.json"));
+ }
+
@Test
public void testErrorResponses() throws Exception {
tester.computeVersionStatus();
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-metering.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-metering.json
new file mode 100644
index 00000000000..63e1c1ebbd1
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-metering.json
@@ -0,0 +1,34 @@
+{
+ "currentrate": {
+ "cpu": 0.0,
+ "mem": 0.0,
+ "disk": 0.0
+ },
+ "thismonth": {
+ "cpu": 0.0,
+ "mem": 0.0,
+ "disk": 0.0
+ },
+ "lastmonth": {
+ "cpu": 0.0,
+ "mem": 0.0,
+ "disk": 0.0
+ },
+ "details": {
+ "cpu": {
+ "dummy": {
+ "data": []
+ }
+ },
+ "mem": {
+ "dummy": {
+ "data": []
+ }
+ },
+ "disk": {
+ "dummy": {
+ "data": []
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_view.h b/eval/src/vespa/eval/tensor/dense/dense_tensor_view.h
index 60f85c38659..c09202e50d0 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_tensor_view.h
+++ b/eval/src/vespa/eval/tensor/dense/dense_tensor_view.h
@@ -46,6 +46,7 @@ public:
void accept(TensorVisitor &visitor) const override;
protected:
void initCellsRef(TypedCells cells_in) {
+ assert(_typeRef.cell_type() == cells_in.type);
_cellsRef = cells_in;
}
private:
diff --git a/metrics-proxy/pom.xml b/metrics-proxy/pom.xml
index 3cfe1d2f568..26caa3f66af 100644
--- a/metrics-proxy/pom.xml
+++ b/metrics-proxy/pom.xml
@@ -79,6 +79,12 @@
</dependency>
<dependency>
<groupId>com.yahoo.vespa</groupId>
+ <artifactId>jdisc_http_service</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
<artifactId>jrt</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
@@ -110,12 +116,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>com.yahoo.vespa</groupId>
- <artifactId>jdisc_http_service</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ErrorResponse.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ErrorResponse.java
new file mode 100644
index 00000000000..679bae84f8e
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ErrorResponse.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.http;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.util.Map;
+import java.util.logging.Logger;
+
+import static java.util.logging.Level.WARNING;
+
+/**
+ * @author gjoranv
+ */
+class ErrorResponse extends JsonResponse {
+ private static Logger log = Logger.getLogger(ErrorResponse.class.getName());
+
+ ErrorResponse(int code, String message) {
+ super(code, asErrorJson(message));
+ }
+
+ static String asErrorJson(String message) {
+ try {
+ return new ObjectMapper().writeValueAsString(Map.of("error", message));
+ } catch (JsonProcessingException e) {
+ log.log(WARNING, "Could not encode error message to json:", e);
+ return "Could not encode error message to json, check the log for details.";
+ }
+ }
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/GenericMetricsHandler.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/GenericMetricsHandler.java
deleted file mode 100644
index f61a96917a9..00000000000
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/GenericMetricsHandler.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
- */
-
-package ai.vespa.metricsproxy.http;
-
-import ai.vespa.metricsproxy.core.MetricsConsumers;
-import ai.vespa.metricsproxy.core.MetricsManager;
-import ai.vespa.metricsproxy.metric.model.ConsumerId;
-import ai.vespa.metricsproxy.metric.model.MetricsPacket;
-import ai.vespa.metricsproxy.metric.model.json.JsonRenderingException;
-import ai.vespa.metricsproxy.service.VespaServices;
-import com.google.inject.Inject;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.time.Instant;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-import static ai.vespa.metricsproxy.metric.model.ConsumerId.toConsumerId;
-import static ai.vespa.metricsproxy.metric.model.json.GenericJsonUtil.toGenericJsonModel;
-
-/**
- * Http handler that exposes the generic metrics format.
- *
- * @author gjoranv
- */
-public class GenericMetricsHandler extends ThreadedHttpRequestHandler {
- private static final Logger log = Logger.getLogger(GenericMetricsHandler.class.getName());
-
- public static final ConsumerId DEFAULT_PUBLIC_CONSUMER_ID = toConsumerId("default");
-
- private final MetricsConsumers metricsConsumers;
- private final MetricsManager metricsManager;
- private final VespaServices vespaServices;
-
- @Inject
- public GenericMetricsHandler(Executor executor,
- MetricsManager metricsManager,
- VespaServices vespaServices,
- MetricsConsumers metricsConsumers) {
- super(executor);
- this.metricsConsumers = metricsConsumers;
- this.metricsManager = metricsManager;
- this.vespaServices = vespaServices;
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- try {
- ConsumerId consumer = getConsumerOrDefault(request.getProperty("consumer"));
-
- List<MetricsPacket> metrics = metricsManager.getMetrics(vespaServices.getVespaServices(), Instant.now())
- .stream()
- .filter(metricsPacket -> metricsPacket.consumers().contains(consumer))
- .collect(Collectors.toList());
- return new Response(200, toGenericJsonModel(metrics).serialize());
- } catch (JsonRenderingException e) {
- return new Response(500, e.getMessageAsJson());
- }
- }
-
- private ConsumerId getConsumerOrDefault(String consumer) {
- if (consumer == null) return DEFAULT_PUBLIC_CONSUMER_ID;
-
- ConsumerId consumerId = toConsumerId(consumer);
- if (! metricsConsumers.getAllConsumers().contains(consumerId)) {
- log.info("No consumer with id '" + consumer + "' - using the default consumer instead.");
- return DEFAULT_PUBLIC_CONSUMER_ID;
- }
- return consumerId;
- }
-
- private static class Response extends HttpResponse {
- private final byte[] data;
-
- Response(int code, String data) {
- super(code);
- this.data = data.getBytes(Charset.forName(DEFAULT_CHARACTER_ENCODING));
- }
-
- @Override
- public String getContentType() {
- return "application/json";
- }
-
- @Override
- public void render(OutputStream outputStream) throws IOException {
- outputStream.write(data);
- }
- }
-
-}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/JsonResponse.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/JsonResponse.java
new file mode 100644
index 00000000000..758a043a823
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/JsonResponse.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.http;
+
+import com.yahoo.container.jdisc.HttpResponse;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+
+/**
+ * @author gjoranv
+ */
+class JsonResponse extends HttpResponse {
+ private final byte[] data;
+
+ JsonResponse(int code, String data) {
+ super(code);
+ this.data = data.getBytes(Charset.forName(DEFAULT_CHARACTER_ENCODING));
+ }
+
+ @Override
+ public String getContentType() {
+ return "application/json";
+ }
+
+ @Override
+ public void render(OutputStream outputStream) throws IOException {
+ outputStream.write(data);
+ }
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/MetricsHandler.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/MetricsHandler.java
new file mode 100644
index 00000000000..1d7206f177d
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/MetricsHandler.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.http;
+
+import ai.vespa.metricsproxy.core.MetricsConsumers;
+import ai.vespa.metricsproxy.core.MetricsManager;
+import ai.vespa.metricsproxy.metric.model.json.JsonRenderingException;
+import ai.vespa.metricsproxy.service.VespaServices;
+import com.google.inject.Inject;
+import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
+import com.yahoo.restapi.Path;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.URI;
+import java.util.concurrent.Executor;
+
+import static com.yahoo.jdisc.Response.Status.INTERNAL_SERVER_ERROR;
+import static com.yahoo.jdisc.Response.Status.METHOD_NOT_ALLOWED;
+import static com.yahoo.jdisc.Response.Status.NOT_FOUND;
+import static com.yahoo.jdisc.Response.Status.OK;
+import static com.yahoo.jdisc.http.HttpRequest.Method.GET;
+
+/**
+ * Http handler for the metrics/v1 rest api.
+ *
+ * @author gjoranv
+ */
+public class MetricsHandler extends ThreadedHttpRequestHandler {
+
+ static final String V1_PATH = "/metrics/v1";
+ static final String VALUES_PATH = V1_PATH + "/values";
+
+ private final ValuesFetcher valuesFetcher;
+
+ @Inject
+ public MetricsHandler(Executor executor,
+ MetricsManager metricsManager,
+ VespaServices vespaServices,
+ MetricsConsumers metricsConsumers) {
+ super(executor);
+ valuesFetcher = new ValuesFetcher(metricsManager, vespaServices, metricsConsumers);
+ }
+
+ @Override
+ public HttpResponse handle(HttpRequest request) {
+ if (request.getMethod() != GET) return new JsonResponse(METHOD_NOT_ALLOWED, "Only GET is supported");
+
+ Path path = new Path(request.getUri());
+
+ if (path.matches(V1_PATH)) return v1Response(request.getUri());
+ if (path.matches(VALUES_PATH)) return valuesResponse(request);
+
+ return new ErrorResponse(NOT_FOUND, "No content at given path");
+ }
+
+ private JsonResponse v1Response(URI requestUri) {
+ try {
+ return new JsonResponse(OK, v1Content(requestUri));
+ } catch (JSONException e) {
+ log.warning("Bad JSON construction in " + V1_PATH + " response: " + e.getMessage());
+ return new ErrorResponse(INTERNAL_SERVER_ERROR,
+ "An error occurred, please try path '" + VALUES_PATH + "'");
+ }
+ }
+
+ private JsonResponse valuesResponse(HttpRequest request) {
+ try {
+ return new JsonResponse(OK, valuesFetcher.fetch(request.getProperty("consumer")));
+ } catch (JsonRenderingException e) {
+ return new ErrorResponse(INTERNAL_SERVER_ERROR, e.getMessage());
+ }
+ }
+
+ // TODO: Use jackson with a "Resources" class instead of JSONObject
+ private String v1Content(URI requestUri) throws JSONException {
+ int port = requestUri.getPort();
+ String host = requestUri.getHost();
+ StringBuilder base = new StringBuilder("http://");
+ base.append(host);
+ if (port >= 0) {
+ base.append(":").append(port);
+ }
+ String uriBase = base.toString();
+ JSONArray linkList = new JSONArray();
+ for (String api : new String[] {VALUES_PATH}) {
+ JSONObject resource = new JSONObject();
+ resource.put("url", uriBase + api);
+ linkList.put(resource);
+ }
+ return new JSONObject().put("resources", linkList).toString(4);
+ }
+
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java
new file mode 100644
index 00000000000..4686d9c1751
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.http;
+
+import ai.vespa.metricsproxy.core.MetricsConsumers;
+import ai.vespa.metricsproxy.core.MetricsManager;
+import ai.vespa.metricsproxy.metric.model.ConsumerId;
+import ai.vespa.metricsproxy.metric.model.MetricsPacket;
+import ai.vespa.metricsproxy.metric.model.json.JsonRenderingException;
+import ai.vespa.metricsproxy.service.VespaServices;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import static ai.vespa.metricsproxy.metric.model.ConsumerId.toConsumerId;
+import static ai.vespa.metricsproxy.metric.model.json.GenericJsonUtil.toGenericJsonModel;
+
+/**
+ * Generates metrics values in json format for the metrics/v1 rest api.
+ *
+ * @author gjoranv
+ */
+public class ValuesFetcher {
+ private static final Logger log = Logger.getLogger(ValuesFetcher.class.getName());
+
+ public static final ConsumerId DEFAULT_PUBLIC_CONSUMER_ID = toConsumerId("default");
+
+ private final MetricsManager metricsManager;
+ private final VespaServices vespaServices;
+ private final MetricsConsumers metricsConsumers;
+
+ ValuesFetcher(MetricsManager metricsManager,
+ VespaServices vespaServices,
+ MetricsConsumers metricsConsumers) {
+ this.metricsManager = metricsManager;
+ this.vespaServices = vespaServices;
+ this.metricsConsumers = metricsConsumers;
+ }
+
+ public String fetch(String requestedConsumer) throws JsonRenderingException {
+ ConsumerId consumer = getConsumerOrDefault(requestedConsumer);
+
+ List<MetricsPacket> metrics = metricsManager.getMetrics(vespaServices.getVespaServices(), Instant.now())
+ .stream()
+ .filter(metricsPacket -> metricsPacket.consumers().contains(consumer))
+ .collect(Collectors.toList());
+ return toGenericJsonModel(metrics).serialize();
+ }
+
+ private ConsumerId getConsumerOrDefault(String consumer) {
+ if (consumer == null) return DEFAULT_PUBLIC_CONSUMER_ID;
+
+ ConsumerId consumerId = toConsumerId(consumer);
+ if (! metricsConsumers.getAllConsumers().contains(consumerId)) {
+ log.info("No consumer with id '" + consumer + "' - using the default consumer instead.");
+ return DEFAULT_PUBLIC_CONSUMER_ID;
+ }
+ return consumerId;
+ }
+
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingException.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingException.java
index 4c1d42d75ee..02292cea164 100644
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingException.java
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingException.java
@@ -4,43 +4,15 @@
package ai.vespa.metricsproxy.metric.model.json;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.util.Map;
-import java.util.logging.Logger;
-
-import static java.util.logging.Level.WARNING;
-
/**
- * An exception to be thrown upon errors in json rendering, and that can deliver its message wrapped
- * in an "error" json object.
+ * An unchecked exception to be thrown upon errors in json rendering.
*
* @author gjoranv
*/
public class JsonRenderingException extends RuntimeException {
- private static Logger log = Logger.getLogger(JsonRenderingException.class.getName());
-
JsonRenderingException(String message) {
super(message);
}
- /**
- * Returns the message wrapped in an "error" json object. In the unlikely case that json rendering of the
- * error message fails, a plain text string will be returned instead.
- */
- public String getMessageAsJson() {
- return wrap(getMessage());
- }
-
- private static String wrap(String message) {
- try {
- return new ObjectMapper().writeValueAsString(Map.of("error", message));
- } catch (JsonProcessingException e) {
- log.log(WARNING, "Could not encode error message to json:", e);
- return "Could not encode error message to json, check the log for details.";
- }
- }
-
}
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingExceptionTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/ErrorResponseTest.java
index 9b502d3f67a..ad2e06da19c 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/JsonRenderingExceptionTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/ErrorResponseTest.java
@@ -2,7 +2,7 @@
* Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
*/
-package ai.vespa.metricsproxy.metric.model.json;
+package ai.vespa.metricsproxy.http;
import org.junit.Test;
@@ -11,17 +11,18 @@ import static org.junit.Assert.assertEquals;
/**
* @author gjoranv
*/
-public class JsonRenderingExceptionTest {
+public class ErrorResponseTest {
@Test
public void error_message_is_wrapped_in_json_object() {
- var exception = new JsonRenderingException("bad");
- assertEquals("{\"error\":\"bad\"}", exception.getMessageAsJson());
+ var json = ErrorResponse.asErrorJson("bad");
+ assertEquals("{\"error\":\"bad\"}", json);
}
@Test
public void quotes_are_escaped() {
- var exception = new JsonRenderingException("Message \" with \" embedded quotes.");
- assertEquals("{\"error\":\"Message \\\" with \\\" embedded quotes.\"}", exception.getMessageAsJson());
+ var json = ErrorResponse.asErrorJson("Message \" with \" embedded quotes.");
+ assertEquals("{\"error\":\"Message \\\" with \\\" embedded quotes.\"}", json);
}
+
}
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/GenericMetricsHandlerTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/MetricsHandlerTest.java
index dc89e5bb9f2..66220464e3e 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/GenericMetricsHandlerTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/MetricsHandlerTest.java
@@ -26,6 +26,8 @@ import ai.vespa.metricsproxy.service.VespaServices;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.yahoo.container.jdisc.RequestHandlerTestDriver;
+import org.json.JSONArray;
+import org.json.JSONObject;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
@@ -36,9 +38,10 @@ import java.util.List;
import java.util.concurrent.Executors;
import static ai.vespa.metricsproxy.core.VespaMetrics.INSTANCE_DIMENSION_ID;
-import static ai.vespa.metricsproxy.http.GenericMetricsHandler.DEFAULT_PUBLIC_CONSUMER_ID;
+import static ai.vespa.metricsproxy.http.MetricsHandler.V1_PATH;
+import static ai.vespa.metricsproxy.http.MetricsHandler.VALUES_PATH;
+import static ai.vespa.metricsproxy.http.ValuesFetcher.DEFAULT_PUBLIC_CONSUMER_ID;
import static ai.vespa.metricsproxy.metric.ExternalMetrics.VESPA_NODE_SERVICE_ID;
-import static ai.vespa.metricsproxy.metric.model.ServiceId.toServiceId;
import static ai.vespa.metricsproxy.metric.model.StatusCode.DOWN;
import static ai.vespa.metricsproxy.metric.model.json.JacksonUtil.createObjectMapper;
import static ai.vespa.metricsproxy.service.DummyService.METRIC_1;
@@ -46,13 +49,14 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author gjoranv
*/
@SuppressWarnings("UnstableApiUsage")
-public class GenericMetricsHandlerTest {
+public class MetricsHandlerTest {
private static final List<VespaService> testServices = ImmutableList.of(
new DummyService(0, ""),
@@ -66,7 +70,9 @@ public class GenericMetricsHandlerTest {
private static final String CPU_METRIC = "cpu";
- private static final String URI = "http://localhost/metrics/v1/values";
+ private static final String URI_BASE = "http://localhost";
+ private static final String V1_URI = URI_BASE + V1_PATH;
+ private static final String VALUES_URI = URI_BASE + VALUES_PATH;
private static RequestHandlerTestDriver testDriver;
@@ -78,12 +84,12 @@ public class GenericMetricsHandlerTest {
new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID)
.timestamp(Instant.now().getEpochSecond())
.putMetrics(ImmutableList.of(new Metric(CPU_METRIC, 12.345)))));
- GenericMetricsHandler handler = new GenericMetricsHandler(Executors.newSingleThreadExecutor(), metricsManager, vespaServices, getMetricsConsumers());
+ MetricsHandler handler = new MetricsHandler(Executors.newSingleThreadExecutor(), metricsManager, vespaServices, getMetricsConsumers());
testDriver = new RequestHandlerTestDriver(handler);
}
private GenericJsonModel getResponseAsJsonModel(String consumer) {
- String response = testDriver.sendRequest(URI + "?consumer=" + consumer).readAll();
+ String response = testDriver.sendRequest(VALUES_URI + "?consumer=" + consumer).readAll();
try {
return createObjectMapper().readValue(response, GenericJsonModel.class);
} catch (IOException e) {
@@ -92,10 +98,23 @@ public class GenericMetricsHandlerTest {
}
}
+ @Test
+ public void v1_response_contains_values_uri() throws Exception {
+ String response = testDriver.sendRequest(V1_URI).readAll();
+ JSONObject root = new JSONObject(response);
+ assertTrue(root.has("resources"));
+
+ JSONArray resources = root.getJSONArray("resources");
+ assertEquals(1, resources.length());
+
+ JSONObject valuesUrl = resources.getJSONObject(0);
+ assertEquals(VALUES_URI, valuesUrl.getString("url"));
+ }
+
@Ignore
@Test
- public void visually_inspect_response() throws Exception{
- String response = testDriver.sendRequest(URI+ "?consumer=default").readAll();
+ public void visually_inspect_values_response() throws Exception{
+ String response = testDriver.sendRequest(VALUES_URI).readAll();
ObjectMapper mapper = createObjectMapper();
var jsonModel = mapper.readValue(response, GenericJsonModel.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonModel));
@@ -103,15 +122,15 @@ public class GenericMetricsHandlerTest {
@Test
public void no_explicit_consumer_gives_the_default_consumer() {
- String responseDefaultConsumer = testDriver.sendRequest(URI + "?consumer=default").readAll();
- String responseNoConsumer = testDriver.sendRequest(URI).readAll();
+ String responseDefaultConsumer = testDriver.sendRequest(VALUES_URI + "?consumer=default").readAll();
+ String responseNoConsumer = testDriver.sendRequest(VALUES_URI).readAll();
assertEqualsExceptTimestamps(responseDefaultConsumer, responseNoConsumer);
}
@Test
public void unknown_consumer_gives_the_default_consumer() {
- String response = testDriver.sendRequest(URI).readAll();
- String responseUnknownConsumer = testDriver.sendRequest(URI + "?consumer=not_defined").readAll();
+ String response = testDriver.sendRequest(VALUES_URI).readAll();
+ String responseUnknownConsumer = testDriver.sendRequest(VALUES_URI + "?consumer=not_defined").readAll();
assertEqualsExceptTimestamps(response, responseUnknownConsumer);
}
diff --git a/model-integration/src/main/java/ai/vespa/rankingexpression/importer/onnx/TypeConverter.java b/model-integration/src/main/java/ai/vespa/rankingexpression/importer/onnx/TypeConverter.java
index 29d600fa7c6..8c9fe60e1d4 100644
--- a/model-integration/src/main/java/ai/vespa/rankingexpression/importer/onnx/TypeConverter.java
+++ b/model-integration/src/main/java/ai/vespa/rankingexpression/importer/onnx/TypeConverter.java
@@ -53,17 +53,17 @@ class TypeConverter {
private static TensorType.Value toValueType(Onnx.TensorProto.DataType dataType) {
switch (dataType) {
- case FLOAT: return TensorType.Value.FLOAT;
+ case FLOAT: return TensorType.Value.DOUBLE;
case DOUBLE: return TensorType.Value.DOUBLE;
// Imperfect conversion, for now:
- case BOOL: return TensorType.Value.FLOAT;
- case INT8: return TensorType.Value.FLOAT;
- case INT16: return TensorType.Value.FLOAT;
- case INT32: return TensorType.Value.FLOAT;
+ case BOOL: return TensorType.Value.DOUBLE;
+ case INT8: return TensorType.Value.DOUBLE;
+ case INT16: return TensorType.Value.DOUBLE;
+ case INT32: return TensorType.Value.DOUBLE;
case INT64: return TensorType.Value.DOUBLE;
- case UINT8: return TensorType.Value.FLOAT;
- case UINT16: return TensorType.Value.FLOAT;
- case UINT32: return TensorType.Value.FLOAT;
+ case UINT8: return TensorType.Value.DOUBLE;
+ case UINT16: return TensorType.Value.DOUBLE;
+ case UINT32: return TensorType.Value.DOUBLE;
case UINT64: return TensorType.Value.DOUBLE;
default: throw new IllegalArgumentException("A ONNX tensor with data type " + dataType +
" cannot be converted to a Vespa tensor type");
diff --git a/model-integration/src/main/java/ai/vespa/rankingexpression/importer/tensorflow/TypeConverter.java b/model-integration/src/main/java/ai/vespa/rankingexpression/importer/tensorflow/TypeConverter.java
index d8ddb01b650..08c0564ed8a 100644
--- a/model-integration/src/main/java/ai/vespa/rankingexpression/importer/tensorflow/TypeConverter.java
+++ b/model-integration/src/main/java/ai/vespa/rankingexpression/importer/tensorflow/TypeConverter.java
@@ -85,19 +85,19 @@ class TypeConverter {
private static TensorType.Value toValueType(DataType dataType) {
switch (dataType) {
- case DT_FLOAT: return TensorType.Value.FLOAT;
+ case DT_FLOAT: return TensorType.Value.DOUBLE;
case DT_DOUBLE: return TensorType.Value.DOUBLE;
// Imperfect conversion, for now:
- case DT_BOOL: return TensorType.Value.FLOAT;
- case DT_BFLOAT16: return TensorType.Value.FLOAT;
- case DT_HALF: return TensorType.Value.FLOAT;
- case DT_INT8: return TensorType.Value.FLOAT;
- case DT_INT16: return TensorType.Value.FLOAT;
- case DT_INT32: return TensorType.Value.FLOAT;
+ case DT_BOOL: return TensorType.Value.DOUBLE;
+ case DT_BFLOAT16: return TensorType.Value.DOUBLE;
+ case DT_HALF: return TensorType.Value.DOUBLE;
+ case DT_INT8: return TensorType.Value.DOUBLE;
+ case DT_INT16: return TensorType.Value.DOUBLE;
+ case DT_INT32: return TensorType.Value.DOUBLE;
case DT_INT64: return TensorType.Value.DOUBLE;
- case DT_UINT8: return TensorType.Value.FLOAT;
- case DT_UINT16: return TensorType.Value.FLOAT;
- case DT_UINT32: return TensorType.Value.FLOAT;
+ case DT_UINT8: return TensorType.Value.DOUBLE;
+ case DT_UINT16: return TensorType.Value.DOUBLE;
+ case DT_UINT32: return TensorType.Value.DOUBLE;
case DT_UINT64: return TensorType.Value.DOUBLE;
default: throw new IllegalArgumentException("A TensorFlow tensor with data type " + dataType +
" cannot be converted to a Vespa tensor type");
@@ -106,12 +106,12 @@ class TypeConverter {
private static TensorType.Value toValueType(org.tensorflow.DataType dataType) {
switch (dataType) {
- case FLOAT: return TensorType.Value.FLOAT;
+ case FLOAT: return TensorType.Value.DOUBLE;
case DOUBLE: return TensorType.Value.DOUBLE;
// Imperfect conversion, for now:
- case BOOL: return TensorType.Value.FLOAT;
- case INT32: return TensorType.Value.FLOAT;
- case UINT8: return TensorType.Value.FLOAT;
+ case BOOL: return TensorType.Value.DOUBLE;
+ case INT32: return TensorType.Value.DOUBLE;
+ case UINT8: return TensorType.Value.DOUBLE;
case INT64: return TensorType.Value.DOUBLE;
default: throw new IllegalArgumentException("A TensorFlow tensor with data type " + dataType +
" cannot be converted to a Vespa tensor type");
diff --git a/model-integration/src/test/java/ai/vespa/rankingexpression/importer/onnx/OnnxMnistSoftmaxImportTestCase.java b/model-integration/src/test/java/ai/vespa/rankingexpression/importer/onnx/OnnxMnistSoftmaxImportTestCase.java
index 07814687dc6..424e4d6c57c 100644
--- a/model-integration/src/test/java/ai/vespa/rankingexpression/importer/onnx/OnnxMnistSoftmaxImportTestCase.java
+++ b/model-integration/src/test/java/ai/vespa/rankingexpression/importer/onnx/OnnxMnistSoftmaxImportTestCase.java
@@ -43,14 +43,14 @@ public class OnnxMnistSoftmaxImportTestCase {
// Check inputs
assertEquals(1, model.inputs().size());
assertTrue(model.inputs().containsKey("Placeholder"));
- assertEquals(TensorType.fromSpec("tensor<float>(d0[],d1[784])"), model.inputs().get("Placeholder"));
+ assertEquals(TensorType.fromSpec("tensor(d0[],d1[784])"), model.inputs().get("Placeholder"));
// Check signature
ImportedMlFunction output = model.defaultSignature().outputFunction("add", "add");
assertNotNull(output);
assertEquals("join(reduce(join(rename(Placeholder, (d0, d1), (d0, d2)), constant(test_Variable), f(a,b)(a * b)), sum, d2), constant(test_Variable_1), f(a,b)(a + b))",
output.expression());
- assertEquals(TensorType.fromSpec("tensor<float>(d0[],d1[784])"),
+ assertEquals(TensorType.fromSpec("tensor(d0[],d1[784])"),
model.inputs().get(model.defaultSignature().inputs().get("Placeholder")));
assertEquals("{Placeholder=tensor(d0[],d1[784])}", output.argumentTypes().toString());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainer.java
new file mode 100644
index 00000000000..44d43081ef2
--- /dev/null
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainer.java
@@ -0,0 +1,446 @@
+package com.yahoo.vespa.hosted.provision.maintenance;
+
+import com.yahoo.config.provision.NodeResources;
+import com.yahoo.config.provision.NodeType;
+import com.yahoo.jdisc.Metric;
+import com.yahoo.log.LogLevel;
+import com.yahoo.vespa.hosted.provision.Node;
+import com.yahoo.vespa.hosted.provision.NodeRepository;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import com.yahoo.vespa.hosted.provision.node.Allocation;
+
+import java.util.*;
+import java.util.function.Function;
+
+/**
+ * Performs analysis on the node repository to produce metrics that pertain to the capacity of the node repository.
+ * These metrics include:
+ * Spare host capacity, or how many hosts the repository can stand to lose without ending up in a situation where it's
+ * unable to find a new home for orphaned tenants.
+ * Overcommitted hosts, which tracks if there are any hosts whose capacity is less than the sum of its children's.
+ *
+ * @author mgimle
+ */
+public class CapacityReportMaintainer extends Maintainer {
+
+ private final Metric metric;
+ private final NodeRepository nodeRepository;
+ private static final Logger log = Logger.getLogger(CapacityReportMaintainer.class.getName());
+
+ CapacityReportMaintainer(NodeRepository nodeRepository,
+ Metric metric,
+ Duration interval) {
+ super(nodeRepository, interval);
+ this.nodeRepository = nodeRepository;
+ this.metric = Objects.requireNonNull(metric);
+ }
+
+ @Override
+ protected void maintain() {
+ metric.set("overcommittedHosts", countOvercommittedHosts(), null);
+
+ Optional<HostFailurePath> failurePath = worstCaseHostLossLeadingToFailure();
+ if (failurePath.isPresent()) {
+ int worstCaseHostLoss = failurePath.get().hostsCausingFailure.size();
+ metric.set("spareHostCapacity", worstCaseHostLoss - 1, null);
+ }
+ }
+
+ protected Optional<HostFailurePath> worstCaseHostLossLeadingToFailure() {
+ List<Node> hosts = getHosts();
+ List<Node> tenants = getTenants(hosts);
+ Map<String, Node> nodeMap = constructHostnameToNodeMap(hosts);
+ Map<Node, List<Node>> nodeChildren = constructNodeChildrenMap(tenants, hosts, nodeMap);
+ Map<Node, AllocationResources> availableResources = constructAvailableResourcesMap(hosts, nodeChildren);
+
+ Map<Node, Integer> timesNodeCanBeRemoved = computeMaximalRepeatedRemovals(hosts, nodeChildren, availableResources);
+ return greedyHeuristicFindFailurePath(timesNodeCanBeRemoved, hosts, nodeChildren, availableResources);
+ }
+
+ // We only care about nodes in one of these states.
+ private Node.State[] relevantNodeStates = {
+ Node.State.active,
+ Node.State.inactive,
+ Node.State.dirty,
+ Node.State.provisioned,
+ Node.State.ready,
+ Node.State.reserved
+ };
+
+ private List<Node> getHosts() {
+ return nodeRepository.getNodes(NodeType.host, relevantNodeStates);
+ }
+
+ private List<Node> getTenants(List<Node> hosts) {
+ var parentNames = hosts.stream().map(Node::hostname).collect(Collectors.toSet());
+ return nodeRepository.getNodes(NodeType.tenant, relevantNodeStates).stream()
+ .filter(t -> parentNames.contains(t.parentHostname().orElse("")))
+ .collect(Collectors.toList());
+ }
+
+ private Optional<HostFailurePath> greedyHeuristicFindFailurePath(Map<Node, Integer> heuristic, List<Node> hosts,
+ Map<Node, List<Node>> nodeChildren,
+ Map<Node, AllocationResources> availableResources) {
+ if (hosts.size() == 0) return Optional.empty();
+ List<Node> parentRemovalPriorityList = heuristic.entrySet().stream()
+ .sorted(Comparator.comparingInt(Map.Entry::getValue))
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+ for (int i = 1; i <= parentRemovalPriorityList.size(); i++) {
+ List<Node> hostsToRemove = parentRemovalPriorityList.subList(0, i);
+ var hostRemovalFailure = findHostRemovalFailure(hostsToRemove, hosts, nodeChildren, availableResources);
+ if (hostRemovalFailure.isPresent()) {
+ HostFailurePath failurePath = new HostFailurePath();
+ failurePath.hostsCausingFailure = hostsToRemove;
+ failurePath.failureReason = hostRemovalFailure.get();
+ return Optional.of(failurePath);
+ }
+ }
+
+ throw new IllegalStateException("No path to failure found. This should be impossible!");
+ }
+
+ protected int countOvercommittedHosts() {
+ List<Node> hosts = getHosts();
+ List<Node> tenants = getTenants(hosts);
+ var nodeMap = constructHostnameToNodeMap(hosts);
+ var nodeChildren = constructNodeChildrenMap(tenants, hosts, nodeMap);
+ var availableResources = constructAvailableResourcesMap(hosts, nodeChildren);
+
+ List<Node> overcommittedNodes = findOvercommittedNodes(availableResources);
+ if (overcommittedNodes.size() != 0) {
+ log.log(LogLevel.WARNING, String.format("%d nodes are overcommitted! [ %s ]", overcommittedNodes.size(),
+ overcommittedNodes.stream().map(Node::hostname).collect(Collectors.joining(", "))));
+ }
+ return overcommittedNodes.size();
+ }
+
+ private Map<String, Node> constructHostnameToNodeMap(List<Node> nodes) {
+ return nodes.stream().collect(Collectors.toMap(Node::hostname, n -> n));
+ }
+
+ private Map<Node, List<Node>> constructNodeChildrenMap(List<Node> tenants, List<Node> hosts, Map<String, Node> hostnameToNode) {
+ Map<Node, List<Node>> nodeChildren = tenants.stream()
+ .filter(n -> n.parentHostname().isPresent())
+ .filter(n -> hostnameToNode.containsKey(n.parentHostname().get()))
+ .collect(Collectors.groupingBy(
+ n -> hostnameToNode.get(n.parentHostname().orElseThrow())));
+
+ for (var host : hosts) nodeChildren.putIfAbsent(host, List.of());
+
+ return nodeChildren;
+ }
+
+ private Map<Node, AllocationResources> constructAvailableResourcesMap(List<Node> hosts, Map<Node, List<Node>> nodeChildren) {
+ Map<Node, AllocationResources> availableResources = new HashMap<>();
+ for (var host : hosts) {
+ NodeResources hostResources = host.flavor().resources();
+ int occupiedIps = 0;
+ Set<String> ipPool = host.ipAddressPool().asSet();
+ for (var child : nodeChildren.get(host)) {
+ hostResources = hostResources.subtract(child.flavor().resources());
+ occupiedIps += child.ipAddresses().stream().filter(ipPool::contains).count();
+ }
+ availableResources.put(host, new AllocationResources(hostResources, host.ipAddressPool().asSet().size() - occupiedIps));
+ }
+
+ return availableResources;
+ }
+
+ /**
+ * Computes a heuristic for each host, with a lower score indicating a higher perceived likelihood that removing
+ * the host causes an unrecoverable state
+ */
+ private Map<Node, Integer> computeMaximalRepeatedRemovals(List<Node> hosts, Map<Node, List<Node>> nodeChildren,
+ Map<Node, AllocationResources> availableResources) {
+ Map<Node, Integer> timesNodeCanBeRemoved = hosts.stream().collect(Collectors.toMap(
+ Function.identity(),
+ _x -> Integer.MAX_VALUE
+ ));
+ for (Node host : hosts) {
+ List<Node> children = nodeChildren.get(host);
+ if (children.size() == 0) continue;
+ Map<Node, AllocationResources> resourceMap = new HashMap<>(availableResources);
+ Map<Node, List<Allocation>> containedAllocations = collateAllocations(nodeChildren);
+
+ int timesHostCanBeRemoved = 0;
+ Optional<Node> unallocatedTenant;
+ while (timesHostCanBeRemoved < 1000) { // Arbritrary upper bound
+ unallocatedTenant = tryAllocateNodes(nodeChildren.get(host), hosts, resourceMap, containedAllocations);
+ if (unallocatedTenant.isEmpty()) {
+ timesHostCanBeRemoved++;
+ } else break;
+ }
+ timesNodeCanBeRemoved.put(host, timesHostCanBeRemoved);
+ }
+
+ return timesNodeCanBeRemoved;
+ }
+
+ private List<Node> findOvercommittedNodes(Map<Node, AllocationResources> availableResources) {
+ List<Node> overcommittedNodes = new ArrayList<>();
+ for (var entry : availableResources.entrySet()) {
+ var resources = entry.getValue().nodeResources;
+ if (resources.vcpu() < 0 || resources.memoryGb() < 0 || resources.diskGb() < 0) {
+ overcommittedNodes.add(entry.getKey());
+ }
+ }
+ return overcommittedNodes;
+ }
+
+ private Map<Node, List<Allocation>> collateAllocations(Map<Node, List<Node>> nodeChildren) {
+ return nodeChildren.entrySet().stream().collect(Collectors.toMap(
+ Map.Entry::getKey,
+ e -> e.getValue().stream()
+ .map(Node::allocation).flatMap(Optional::stream)
+ .collect(Collectors.toList())
+ ));
+ }
+
+ /**
+ * Tests whether it's possible to remove the provided hosts.
+ * Does not mutate any input variable.
+ * @return Empty optional if removal is possible, information on what caused the failure otherwise
+ */
+ private Optional<HostRemovalFailure> findHostRemovalFailure(List<Node> hostsToRemove, List<Node> allHosts,
+ Map<Node, List<Node>> nodechildren,
+ Map<Node, AllocationResources> availableResources) {
+ var containedAllocations = collateAllocations(nodechildren);
+ var resourceMap = new HashMap<>(availableResources);
+ List<Node> validAllocationTargets = allHosts.stream()
+ .filter(h -> !hostsToRemove.contains(h))
+ .collect(Collectors.toList());
+ if (validAllocationTargets.size() == 0) {
+ return Optional.of(HostRemovalFailure.none());
+ }
+
+ for (var host : hostsToRemove) {
+ Optional<Node> unallocatedNode = tryAllocateNodes(nodechildren.get(host),
+ validAllocationTargets, resourceMap, containedAllocations);
+
+ if (unallocatedNode.isPresent()) {
+ AllocationFailureReasonList failures = collateAllocationFailures(unallocatedNode.get(),
+ validAllocationTargets, resourceMap, containedAllocations);
+ return Optional.of(HostRemovalFailure.create(host, unallocatedNode.get(), failures));
+ }
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * Attempts to allocate the listed nodes to a new host, mutating availableResources and containedAllocations,
+ * optionally returning the first node to fail, if one does.
+ * */
+ private Optional<Node> tryAllocateNodes(List<Node> nodes, List<Node> hosts,
+ Map<Node, AllocationResources> availableResources,
+ Map<Node, List<Allocation>> containedAllocations) {
+ for (var node : nodes) {
+ if (!tryAllocateNode(node, hosts, availableResources, containedAllocations)) {
+ return Optional.of(node);
+ }
+ }
+ return Optional.empty();
+ }
+
+ private boolean tryAllocateNode(Node node, List<Node> hosts,
+ Map<Node, AllocationResources> availableResources,
+ Map<Node, List<Allocation>> containedAllocations) {
+ AllocationResources requiredNodeResources = AllocationResources.from(node.flavor().resources());
+ for (var host : hosts) {
+ var availableHostResources = availableResources.get(host);
+ if (violatesParentHostPolicy(node, host, containedAllocations)) {
+ continue;
+ }
+ if (availableHostResources.satisfies(requiredNodeResources)) {
+ availableResources.put(host, availableHostResources.subtract(requiredNodeResources));
+ if (node.allocation().isPresent()) {
+ containedAllocations.get(host).add(node.allocation().get());
+ }
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean violatesParentHostPolicy(Node node, Node host, Map<Node, List<Allocation>> containedAllocations) {
+ if (node.allocation().isEmpty()) return false;
+ Allocation nodeAllocation = node.allocation().get();
+ for (var allocation : containedAllocations.get(host)) {
+ if (allocation.membership().cluster().equalsIgnoringGroupAndVespaVersion(nodeAllocation.membership().cluster())
+ && allocation.owner().equals(nodeAllocation.owner())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private AllocationFailureReasonList collateAllocationFailures(Node node, List<Node> hosts,
+ Map<Node, AllocationResources> availableResources,
+ Map<Node, List<Allocation>> containedAllocations) {
+ List<AllocationFailureReason> allocationFailureReasons = new ArrayList<>();
+ for (var host : hosts) {
+ AllocationFailureReason reason = new AllocationFailureReason(host);
+ var availableHostResources = availableResources.get(host);
+ reason.violatesParentHostPolicy = violatesParentHostPolicy(node, host, containedAllocations);
+
+ NodeResources l = availableHostResources.nodeResources;
+ NodeResources r = node.flavor().resources();
+ if (l.vcpu() < r.vcpu()) { reason.insufficientVcpu = true; }
+ if (l.memoryGb() < r.memoryGb()) { reason.insufficientMemoryGb = true; }
+ if (l.diskGb() < r.diskGb()) { reason.insufficientDiskGb = true; }
+ if (r.diskSpeed() != NodeResources.DiskSpeed.any && r.diskSpeed() != l.diskSpeed())
+ { reason.incompatibleDiskSpeed = true; }
+ if (availableHostResources.availableIPs < 1) { reason.insufficientAvailableIPs = true; }
+
+ allocationFailureReasons.add(reason);
+ }
+
+ return new AllocationFailureReasonList(allocationFailureReasons);
+ }
+
+ /**
+ * Contains the list of hosts that, upon being removed, caused an unrecoverable state,
+ * as well as the specific host and tenant which caused it.
+ */
+ public static class HostFailurePath {
+ List<Node> hostsCausingFailure;
+ HostRemovalFailure failureReason;
+ }
+
+ /**
+ * Data class used for detailing why removing the given tenant from the given host was unsuccessful.
+ * A failure might not be caused by failing to allocate a specific tenant, in which case the fields
+ * will be empty.
+ */
+ public static class HostRemovalFailure {
+ Optional<Node> host;
+ Optional<Node> tenant;
+ AllocationFailureReasonList failureReasons;
+ public static HostRemovalFailure none() {
+ return new HostRemovalFailure(
+ Optional.empty(),
+ Optional.empty(),
+ new AllocationFailureReasonList(List.of()));
+ }
+ public static HostRemovalFailure create(Node host, Node tenant, AllocationFailureReasonList failureReasons) {
+ return new HostRemovalFailure(
+ Optional.of(host),
+ Optional.of(tenant),
+ failureReasons);
+ }
+ private HostRemovalFailure(Optional<Node> host, Optional<Node> tenant, AllocationFailureReasonList failureReasons) {
+ this.host = host;
+ this.tenant = tenant;
+ this.failureReasons = failureReasons;
+ }
+ }
+
+ /**
+ * Used to describe the resources required for a tenant, and available to a host.
+ */
+ private static class AllocationResources {
+ NodeResources nodeResources;
+ int availableIPs;
+
+ public static AllocationResources from(NodeResources nodeResources) {
+ return new AllocationResources(nodeResources, 1);
+ }
+
+ public AllocationResources(NodeResources nodeResources, int availableIPs) {
+ this.nodeResources = nodeResources;
+ this.availableIPs = availableIPs;
+ }
+
+ public boolean satisfies(AllocationResources other) {
+ if (!this.nodeResources.satisfies(other.nodeResources)) return false;
+ return this.availableIPs >= other.availableIPs;
+ }
+
+ public AllocationResources subtract(AllocationResources other) {
+ return new AllocationResources(this.nodeResources.subtract(other.nodeResources), this.availableIPs - other.availableIPs);
+ }
+ }
+
+ /**
+ * Keeps track of the reason why a host rejected an allocation.
+ */
+ private class AllocationFailureReason {
+ Node host;
+ public AllocationFailureReason (Node host) {
+ this.host = host;
+ }
+ public boolean insufficientVcpu = false;
+ public boolean insufficientMemoryGb = false;
+ public boolean insufficientDiskGb = false;
+ public boolean incompatibleDiskSpeed = false;
+ public boolean insufficientAvailableIPs = false;
+ public boolean violatesParentHostPolicy = false;
+
+ public int numberOfReasons() {
+ int n = 0;
+ if (insufficientVcpu) n++;
+ if (insufficientMemoryGb) n++;
+ if (insufficientDiskGb) n++;
+ if (incompatibleDiskSpeed) n++;
+ if (insufficientAvailableIPs) n++;
+ if (violatesParentHostPolicy) n++;
+ return n;
+ }
+
+ @Override
+ public String toString() {
+ List<String> reasons = new ArrayList<>();
+ if (insufficientVcpu) reasons.add("insufficientVcpu");
+ if (insufficientMemoryGb) reasons.add("insufficientMemoryGb");
+ if (insufficientDiskGb) reasons.add("insufficientDiskGb");
+ if (incompatibleDiskSpeed) reasons.add("incompatibleDiskSpeed");
+ if (insufficientAvailableIPs) reasons.add("insufficientAvailableIPs");
+ if (violatesParentHostPolicy) reasons.add("violatesParentHostPolicy");
+
+ return String.format("[%s]", String.join(", ", reasons));
+ }
+ }
+
+ /**
+ * Provides convenient methods for tallying failures.
+ */
+ public static class AllocationFailureReasonList {
+ private List<AllocationFailureReason> allocationFailureReasons;
+ public AllocationFailureReasonList(List<AllocationFailureReason> allocationFailureReasons) {
+ this.allocationFailureReasons = allocationFailureReasons;
+ }
+
+ long insufficientVcpu() { return allocationFailureReasons.stream().filter(r -> r.insufficientVcpu).count(); }
+ long insufficientMemoryGb() { return allocationFailureReasons.stream().filter(r -> r.insufficientMemoryGb).count(); }
+ long insufficientDiskGb() { return allocationFailureReasons.stream().filter(r -> r.insufficientDiskGb).count(); }
+ long incompatibleDiskSpeed() { return allocationFailureReasons.stream().filter(r -> r.incompatibleDiskSpeed).count(); }
+ long insufficientAvailableIps() { return allocationFailureReasons.stream().filter(r -> r.insufficientAvailableIPs).count(); }
+ long violatesParentHostPolicy() { return allocationFailureReasons.stream().filter(r -> r.violatesParentHostPolicy).count(); }
+
+ public AllocationFailureReasonList singularReasonFailures() {
+ return new AllocationFailureReasonList(allocationFailureReasons.stream()
+ .filter(reason -> reason.numberOfReasons() == 1).collect(Collectors.toList()));
+ }
+ public AllocationFailureReasonList multipleReasonFailures() {
+ return new AllocationFailureReasonList(allocationFailureReasons.stream()
+ .filter(reason -> reason.numberOfReasons() > 1).collect(Collectors.toList()));
+ }
+ public long size() {
+ return allocationFailureReasons.size();
+ }
+ @Override
+ public String toString() {
+ return String.format("CPU (%3d), Memory (%3d), Disk size (%3d), Disk speed (%3d), IP (%3d), Parent-Host Policy (%3d)",
+ insufficientVcpu(), insufficientMemoryGb(), insufficientDiskGb(),
+ incompatibleDiskSpeed(), insufficientAvailableIps(), violatesParentHostPolicy());
+ }
+ }
+}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
index b9b1200d473..f661977d933 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
@@ -46,6 +46,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
private final Optional<LoadBalancerExpirer> loadBalancerExpirer;
private final Optional<HostProvisionMaintainer> hostProvisionMaintainer;
private final Optional<HostDeprovisionMaintainer> hostDeprovisionMaintainer;
+ private final CapacityReportMaintainer capacityReportMaintainer;
@Inject
public NodeRepositoryMaintenance(NodeRepository nodeRepository, Deployer deployer, InfraDeployer infraDeployer,
@@ -81,6 +82,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
new HostProvisionMaintainer(nodeRepository, durationFromEnv("host_provisioner_interval").orElse(defaults.hostProvisionerInterval), hostProvisioner, flagSource));
hostDeprovisionMaintainer = provisionServiceProvider.getHostProvisioner().map(hostProvisioner ->
new HostDeprovisionMaintainer(nodeRepository, durationFromEnv("host_deprovisioner_interval").orElse(defaults.hostDeprovisionerInterval), hostProvisioner, flagSource));
+ capacityReportMaintainer = new CapacityReportMaintainer(nodeRepository, metric, durationFromEnv("alert_interval").orElse(defaults.nodeAlerterInterval));
// The DuperModel is filled with infrastructure applications by the infrastructure provisioner, so explicitly run that now
infrastructureProvisioner.maintain();
@@ -97,6 +99,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
failedExpirer.deconstruct();
dirtyExpirer.deconstruct();
nodeRebooter.deconstruct();
+ capacityReportMaintainer.deconstruct();
provisionedExpirer.deconstruct();
metricsReporter.deconstruct();
infrastructureProvisioner.deconstruct();
@@ -140,6 +143,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
private final Duration dirtyExpiry;
private final Duration provisionedExpiry;
private final Duration rebootInterval;
+ private final Duration nodeAlerterInterval;
private final Duration metricsInterval;
private final Duration retiredInterval;
private final Duration infrastructureProvisionInterval;
@@ -158,6 +162,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
failedExpirerInterval = Duration.ofMinutes(10);
provisionedExpiry = Duration.ofHours(4);
rebootInterval = Duration.ofDays(30);
+ nodeAlerterInterval = Duration.ofHours(1);
metricsInterval = Duration.ofMinutes(1);
infrastructureProvisionInterval = Duration.ofMinutes(1);
throttlePolicy = NodeFailer.ThrottlePolicy.hosted;
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTest.java
new file mode 100644
index 00000000000..a486f8619c5
--- /dev/null
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTest.java
@@ -0,0 +1,171 @@
+package com.yahoo.vespa.hosted.provision.maintenance;
+
+import com.yahoo.config.provision.NodeResources;
+import com.yahoo.config.provision.NodeType;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.*;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
+
+/**
+ * @author mgimle
+ */
+public class CapacityReportMaintainerTest {
+ private CapacityReportMaintainerTester tester;
+ private CapacityReportMaintainer capacityReporter;
+
+ @Before
+ public void setup() {
+ tester = new CapacityReportMaintainerTester();
+ capacityReporter = tester.makeCapacityReportMaintainer();
+ }
+
+ @Test
+ public void testWithRealData() throws IOException {
+ String path = "./src/test/resources/zookeeper_dump.json";
+
+ tester.cleanRepository();
+ tester.restoreNodeRepositoryFromJsonFile(Paths.get(path));
+ var failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ if (failurePath.isPresent()) {
+ assertTrue(tester.nodeRepository.getNodes(NodeType.host).containsAll(failurePath.get().hostsCausingFailure));
+ } else fail();
+ }
+
+ @Test
+ public void testOvercommittedHosts() {
+ tester.createNodes(7, 4,
+ 10, new NodeResources(-1, 10, 100), 10,
+ 0, new NodeResources(1, 10, 100), 10);
+ int overcommittedHosts = capacityReporter.countOvercommittedHosts();
+ assertEquals(tester.nodeRepository.getNodes(NodeType.host).size(), overcommittedHosts);
+ }
+
+ @Test
+ public void testEdgeCaseFailurePaths() {
+ tester.createNodes(1, 1,
+ 0, new NodeResources(1, 10, 100), 10,
+ 0, new NodeResources(1, 10, 100), 10);
+ var failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertFalse("Computing worst case host loss with no hosts should return an empty optional.", failurePath.isPresent());
+
+ // Odd edge case that should never be able to occur in prod
+ tester.createNodes(1, 10,
+ 10, new NodeResources(10, 1000, 10000), 100,
+ 1, new NodeResources(10, 1000, 10000), 100);
+ failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ assertTrue("Computing worst case host loss if all hosts have to be removed should result in an non-empty failureReason with empty nodes.",
+ failurePath.get().failureReason.tenant.isEmpty() && failurePath.get().failureReason.host.isEmpty());
+ assertEquals(tester.nodeRepository.getNodes(NodeType.host).size(), failurePath.get().hostsCausingFailure.size());
+
+ tester.createNodes(3, 30,
+ 10, new NodeResources(0, 0, 10000), 1000,
+ 0, new NodeResources(0, 0, 0), 0);
+ failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertEquals("When there are multiple lacking resources, all failures are multipleReasonFailures",
+ failureReasons.size(), failureReasons.multipleReasonFailures().size());
+ assertEquals(0, failureReasons.singularReasonFailures().size());
+ } else fail();
+ }
+
+ @Test
+ public void testIpFailurePaths() {
+ tester.createNodes(1, 10,
+ 10, new NodeResources(10, 1000, 10000), 1,
+ 10, new NodeResources(10, 1000, 10000), 1);
+ var failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertEquals("All failures should be due to hosts having a lack of available ip addresses.",
+ failureReasons.singularReasonFailures().insufficientAvailableIps(), failureReasons.size());
+ } else fail();
+
+ }
+
+ @Test
+ public void testNodeResourceFailurePaths() {
+ tester.createNodes(1, 10,
+ 10, new NodeResources(1, 100, 1000), 100,
+ 10, new NodeResources(0, 100, 1000), 100);
+ var failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertEquals("All failures should be due to hosts lacking cpu cores.",
+ failureReasons.singularReasonFailures().insufficientVcpu(), failureReasons.size());
+ } else fail();
+
+ tester.createNodes(1, 10,
+ 10, new NodeResources(10, 1, 1000), 100,
+ 10, new NodeResources(10, 0, 1000), 100);
+ failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertEquals("All failures should be due to hosts lacking memory.",
+ failureReasons.singularReasonFailures().insufficientMemoryGb(), failureReasons.size());
+ } else fail();
+
+ tester.createNodes(1, 10,
+ 10, new NodeResources(10, 100, 10), 100,
+ 10, new NodeResources(10, 100, 0), 100);
+ failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertEquals("All failures should be due to hosts lacking disk space.",
+ failureReasons.singularReasonFailures().insufficientDiskGb(), failureReasons.size());
+ } else fail();
+
+ int emptyHostsWithSlowDisk = 10;
+ tester.createNodes(1, 10, List.of(new NodeResources(1, 10, 100)),
+ 10, new NodeResources(0, 0, 0), 100,
+ 10, new NodeResources(10, 1000, 10000, NodeResources.DiskSpeed.slow), 100);
+ failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertEquals("All empty hosts should be invalid due to having incompatible disk speed.",
+ failureReasons.singularReasonFailures().incompatibleDiskSpeed(), emptyHostsWithSlowDisk);
+ } else fail();
+
+ }
+
+
+ @Test
+ public void testParentHostPolicyIntegrityFailurePaths() {
+ tester.createNodes(1, 1,
+ 10, new NodeResources(1, 100, 1000), 100,
+ 10, new NodeResources(10, 1000, 10000), 100);
+ var failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertEquals("With only one type of tenant, all failures should be due to violation of the parent host policy.",
+ failureReasons.singularReasonFailures().violatesParentHostPolicy(), failureReasons.size());
+ } else fail();
+
+ tester.createNodes(1, 2,
+ 10, new NodeResources(10, 100, 1000), 1,
+ 0, new NodeResources(0, 0, 0), 0);
+ failurePath = capacityReporter.worstCaseHostLossLeadingToFailure();
+ assertTrue(failurePath.isPresent());
+ if (failurePath.get().failureReason.tenant.isPresent()) {
+ var failureReasons = failurePath.get().failureReason.failureReasons;
+ assertNotEquals("Fewer distinct children than hosts should result in some parent host policy violations.",
+ failureReasons.size(), failureReasons.singularReasonFailures().violatesParentHostPolicy());
+ assertNotEquals(0, failureReasons.singularReasonFailures().violatesParentHostPolicy());
+ } else fail();
+ }
+}
+
+
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTester.java
new file mode 100644
index 00000000000..ccea4691f10
--- /dev/null
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityReportMaintainerTester.java
@@ -0,0 +1,290 @@
+package com.yahoo.vespa.hosted.provision.maintenance;
+
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.yahoo.collections.Tuple2;
+import com.yahoo.component.Version;
+import com.yahoo.config.provision.*;
+import com.yahoo.test.ManualClock;
+import com.yahoo.vespa.curator.Curator;
+import com.yahoo.vespa.curator.mock.MockCurator;
+import com.yahoo.vespa.hosted.provision.Node;
+import com.yahoo.vespa.hosted.provision.NodeRepository;
+import com.yahoo.vespa.hosted.provision.node.IP;
+import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
+import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * @author mgimle
+ */
+public class CapacityReportMaintainerTester {
+ public static final Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
+
+ // Components with state
+ public final ManualClock clock = new ManualClock();
+ public final NodeRepository nodeRepository;
+
+ CapacityReportMaintainerTester() {
+ Curator curator = new MockCurator();
+ NodeFlavors f = new NodeFlavors(new FlavorConfigBuilder().build());
+ nodeRepository = new NodeRepository(f, curator, clock, zone, new MockNameResolver().mockAnyLookup(),
+ DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa"), true);
+ }
+
+ CapacityReportMaintainer makeCapacityReportMaintainer() {
+ return new CapacityReportMaintainer(nodeRepository, new MetricsReporterTest.TestMetric(), Duration.ofDays(1));
+ }
+
+ List<NodeModel> createDistinctChildren(int amount, List<NodeResources> childResources) {
+ String wantedVespaVersion = "7.67.9";
+ List<String> tenants = List.of("foocom", "barinc");
+ List<String> applications = List.of("ranking", "search");
+ List<Tuple2<ClusterSpec.Type, String>> clusterSpecs = List.of(
+ new Tuple2<>(ClusterSpec.Type.content, "content"),
+ new Tuple2<>(ClusterSpec.Type.container, "suggest"),
+ new Tuple2<>(ClusterSpec.Type.admin, "log"));
+ int childCombinations = tenants.size() * applications.size() * clusterSpecs.size();
+ List<NodeModel> distinctChildren = new ArrayList<>();
+
+ for (int j = 0; j < amount;)
+ for (var tenant : tenants)
+ for (var application : applications)
+ for (var clusterSpec : clusterSpecs) {
+ if (j >= amount) continue;
+ NodeModel child = new NodeModel();
+ child.type = NodeType.tenant;
+ NodeResources cnr = childResources.get(j % childResources.size());
+ child.minCpuCores = cnr.vcpu();
+ child.minMainMemoryAvailableGb = cnr.memoryGb();
+ child.minDiskAvailableGb = cnr.diskGb();
+ child.fastDisk = true;
+ child.ipAddresses = Set.of();
+ child.additionalIpAddresses = Set.of();
+ child.owner = new NodeModel.OwnerModel();
+ child.owner.tenant = tenant + j / childCombinations;
+ child.owner.application = application;
+ child.owner.instance = "default";
+ child.membership = NodeModel.MembershipModel.from(clusterSpec.first, clusterSpec.second, 0);
+ child.wantedVespaVersion = wantedVespaVersion;
+ child.state = Node.State.active;
+ child.environment = Flavor.Type.DOCKER_CONTAINER;
+
+ distinctChildren.add(child);
+ j++;
+ }
+
+ return distinctChildren;
+ }
+
+ List<Node> createHostsWithChildren(int childrenPerHost, List<NodeModel> distinctChildren, int amount, NodeResources excessCapacity, int excessIps) {
+ List<Node> hosts = new ArrayList<>();
+ int j = 0;
+ for (int i = 0; i < amount; i++) {
+ String parentRoot = ".not.a.real.hostname.yahoo.com";
+ String parentName = "parent" + i;
+ String hostname = parentName + parentRoot;
+
+ List<NodeResources> childResources = new ArrayList<>();
+ for (int k = 0; k < childrenPerHost; k++, j++) {
+ NodeModel childModel = distinctChildren.get(j % distinctChildren.size());
+ String childHostName = parentName + "-v6-" + k + parentRoot;
+ childModel.id = childHostName;
+ childModel.hostname = childHostName;
+ childModel.ipAddresses = Set.of(String.format("%04X::%04X", i, k));
+ childModel.membership.index = j / distinctChildren.size();
+ childModel.parentHostname = Optional.of(hostname);
+
+ Node childNode = createNodeFromModel(childModel);
+ childResources.add(childNode.flavor().resources());
+ hosts.add(childNode);
+ }
+
+ final int hostindex = i;
+ Set<String> availableIps = IntStream.range(0, childrenPerHost + excessIps)
+ .mapToObj(n -> String.format("%04X::%04X", hostindex, n))
+ .collect(Collectors.toSet());
+
+ NodeResources nr = containingNodeResources(childResources,
+ excessCapacity);
+ Node node = nodeRepository.createNode(hostname, hostname,
+ new IP.Config(Set.of("::"), availableIps), Optional.empty(),
+ Optional.empty(), new Flavor(nr), NodeType.host);
+ hosts.add(node);
+ }
+ return hosts;
+ }
+
+ List<Node> createEmptyHosts(int baseIndex, int amount, NodeResources capacity, int ips) {
+ List<Node> hosts = new ArrayList<>();
+ for (int i = baseIndex; i < baseIndex + amount; i++) {
+ String parentRoot = ".empty.not.a.real.hostname.yahoo.com";
+ String parentName = "parent" + i;
+ String hostname = parentName + parentRoot;
+
+ final int hostid = i;
+ Set<String> availableIps = IntStream.range(0, ips)
+ .mapToObj(n -> String.format("%04X::%04X", hostid, n))
+ .collect(Collectors.toSet());
+ Node node = nodeRepository.createNode(hostname, hostname,
+ new IP.Config(Set.of("::"), availableIps), Optional.empty(),
+ Optional.empty(), new Flavor(capacity), NodeType.host);
+ hosts.add(node);
+ }
+ return hosts;
+ }
+
+ void createNodes(int childrenPerHost, int numDistinctChildren,
+ int numHosts, NodeResources hostExcessCapacity, int hostExcessIps,
+ int numEmptyHosts, NodeResources emptyHostExcessCapacity, int emptyHostExcessIps) {
+ List<NodeResources> childResources = List.of(
+ new NodeResources(1, 10, 100)
+
+ );
+ createNodes(childrenPerHost, numDistinctChildren, childResources,
+ numHosts, hostExcessCapacity, hostExcessIps,
+ numEmptyHosts, emptyHostExcessCapacity, emptyHostExcessIps);
+ }
+ void createNodes(int childrenPerHost, int numDistinctChildren, List<NodeResources> childResources,
+ int numHosts, NodeResources hostExcessCapacity, int hostExcessIps,
+ int numEmptyHosts, NodeResources emptyHostExcessCapacity, int emptyHostExcessIps) {
+ cleanRepository();
+ List<NodeModel> possibleChildren = createDistinctChildren(numDistinctChildren, childResources);
+
+ List<Node> nodes = new ArrayList<>();
+ nodes.addAll(createHostsWithChildren(childrenPerHost, possibleChildren, numHosts, hostExcessCapacity, hostExcessIps));
+ nodes.addAll(createEmptyHosts(numHosts, numEmptyHosts, emptyHostExcessCapacity, emptyHostExcessIps));
+
+ nodeRepository.addNodes(nodes);
+ }
+
+
+ NodeResources containingNodeResources(List<NodeResources> resources, NodeResources excessCapacity) {
+ NodeResources usedByChildren = resources.stream()
+ .reduce(new NodeResources(0, 0, 0), NodeResources::add);
+ return usedByChildren.add(excessCapacity);
+ }
+
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ static class NodeModel {
+ static class MembershipModel {
+ @JsonProperty ClusterSpec.Type clustertype;
+ @JsonProperty String clusterid;
+ @JsonProperty String group;
+ @JsonProperty int index;
+ @JsonProperty boolean retired;
+
+ public static MembershipModel from(ClusterSpec.Type type, String id, int index) {
+ MembershipModel m = new MembershipModel();
+ m.clustertype = type;
+ m.clusterid = id;
+ m.group = "0";
+ m.index = index;
+ m.retired = false;
+ return m;
+ }
+ public String toString() {
+ return String.format("%s/%s/%s/%d%s", clustertype, clusterid, group, index, retired ? "/retired" : "");
+ }
+ }
+ static class OwnerModel {
+ @JsonProperty String tenant;
+ @JsonProperty String application;
+ @JsonProperty String instance;
+ }
+
+ @JsonProperty String id;
+ @JsonProperty String hostname;
+ @JsonProperty NodeType type;
+ Optional<String> parentHostname = Optional.empty();
+ @JsonSetter("parentHostname")
+ private void setParentHostname(String name) { this.parentHostname = Optional.ofNullable(name); }
+ @JsonGetter("parentHostname")
+ String getParentHostname() { return parentHostname.orElse(null); }
+ @JsonProperty double minDiskAvailableGb;
+ @JsonProperty double minMainMemoryAvailableGb;
+ @JsonProperty double minCpuCores;
+ @JsonProperty boolean fastDisk;
+ @JsonProperty Set<String> ipAddresses;
+ @JsonProperty Set<String> additionalIpAddresses;
+
+ @JsonProperty OwnerModel owner;
+ @JsonProperty MembershipModel membership;
+ @JsonProperty String wantedVespaVersion;
+ @JsonProperty Node.State state;
+ @JsonProperty Flavor.Type environment;
+ }
+
+ static class NodeRepositoryModel {
+ @JsonProperty
+ List<NodeModel> nodes;
+ }
+
+ Node createNodeFromModel(NodeModel nodeModel) {
+ ClusterMembership membership = null;
+ ApplicationId owner = null;
+ if (nodeModel.membership != null && nodeModel.owner != null) {
+ membership = ClusterMembership.from(
+ nodeModel.membership.toString(),
+ Version.fromString(nodeModel.wantedVespaVersion));
+ owner = ApplicationId.from(nodeModel.owner.tenant, nodeModel.owner.application, nodeModel.owner.instance);
+ }
+
+ NodeResources.DiskSpeed diskSpeed;
+ // According to @kraune, container tenants are not fuzzy about disk type
+ if (membership != null && nodeModel.type == NodeType.tenant && membership.cluster().type() == ClusterSpec.Type.container) {
+ diskSpeed = NodeResources.DiskSpeed.any;
+ } else {
+ diskSpeed = nodeModel.fastDisk ? NodeResources.DiskSpeed.fast : NodeResources.DiskSpeed.slow;
+ }
+ NodeResources nr = new NodeResources(nodeModel.minCpuCores, nodeModel.minMainMemoryAvailableGb,
+ nodeModel.minDiskAvailableGb, diskSpeed);
+ Flavor f = new Flavor(nr);
+
+ Node node = nodeRepository.createNode(nodeModel.id, nodeModel.hostname,
+ new IP.Config(nodeModel.ipAddresses, nodeModel.additionalIpAddresses),
+ nodeModel.parentHostname, Optional.empty(), f, nodeModel.type);
+
+ if (membership != null) {
+ return node.allocate(owner, membership, Instant.now());
+ } else {
+ return node;
+ }
+ }
+
+ public void restoreNodeRepositoryFromJsonFile(Path path) throws IOException {
+ byte[] jsonData = Files.readAllBytes(path);
+ ObjectMapper om = new ObjectMapper();
+
+ NodeRepositoryModel repositoryModel = om.readValue(jsonData, NodeRepositoryModel.class);
+ List<NodeModel> nmods = repositoryModel.nodes;
+
+ List<Node> nodes = new ArrayList<>();
+ for (var nmod : nmods) {
+ if (nmod.type != NodeType.host && nmod.type != NodeType.tenant) continue;
+
+ nodes.add(createNodeFromModel(nmod));
+ }
+
+ nodeRepository.addNodes(nodes);
+ }
+
+ void cleanRepository() {
+ nodeRepository.getNodes(NodeType.host).forEach(n -> nodeRepository.removeRecursively(n, true));
+ nodeRepository.getNodes().forEach(n -> nodeRepository.removeRecursively(n, true));
+ if (nodeRepository.getNodes().size() != 0) {
+ throw new IllegalStateException("Cleaning repository didn't remove all nodes! [" + nodeRepository.getNodes().size() + "]");
+ }
+ }
+}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json
index b72523963c0..28881717e7c 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json
@@ -1,6 +1,9 @@
{
"jobs": [
{
+ "name": "CapacityReportMaintainer"
+ },
+ {
"name": "DirtyExpirer"
},
{
diff --git a/node-repository/src/test/resources/zookeeper_dump.json b/node-repository/src/test/resources/zookeeper_dump.json
new file mode 100644
index 00000000000..40786cc95dd
--- /dev/null
+++ b/node-repository/src/test/resources/zookeeper_dump.json
@@ -0,0 +1 @@
+{"nodes":[{"id":"2132864288","hostname":"2132864288","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c27::10e0"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":34,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"399083239"},{"id":"-167779330","hostname":"-167779330","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c2a::105c","1.1.77.48"],"additionalIpAddresses":["c2a::1064","c2a::1063","c2a::1062","c2a::1061","c2a::1060","c2a::106f","c2a::106e","c2a::107c","c2a::107b","c2a::107a","c2a::1069","c2a::1068","c2a::1067","c2a::1066","c2a::1065","c2a::1075","c2a::1074","c2a::1073","c2a::1072","c2a::1071","c2a::1070","c2a::105f","c2a::105e","c2a::105d","c2a::106d","c2a::106c","c2a::106b","c2a::106a","c2a::1079","c2a::1078","c2a::1077","c2a::1076"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":22,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"119146780","hostname":"119146780","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c40::10c1"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"50511102","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"578117757","hostname":"578117757","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2a::1046"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":37,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"547954621"},{"id":"-727133536","hostname":"-727133536","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c28::10b4"],"additionalIpAddresses":[],"owner":{"tenant":"-2059328563","application":"-2059328563","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"661679481","hostname":"661679481","type":"host","minDiskAvailableGb":480.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.75.240","c26::1006"],"additionalIpAddresses":["c26::100a","c26::100e","c26::100d","c26::100c","c26::100b","c26::1009","c26::1008","c26::1007"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1882495550","hostname":"-1882495550","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.90.177","c40::1099"],"additionalIpAddresses":["c40::10ac","c40::10ad","c40::10ae","c40::10af","c40::10a0","c40::10a1","c40::10a2","c40::10a3","c40::10a4","c40::10a5","c40::10a6","c40::10a7","c40::10a8","c40::10a9","c40::109a","c40::109b","c40::109c","c40::109d","c40::109e","c40::109f","c40::10b0","c40::10b1","c40::10b2","c40::10b3","c40::10b4","c40::10b5","c40::10b6","c40::10b7","c40::10b8","c40::10b9","c40::10aa","c40::10ab"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":33,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1139644897","hostname":"-1139644897","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::100c"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1028554796","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1921643747"},{"id":"-160875418","hostname":"-160875418","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c40::103a"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-348618915"},{"id":"952554185","hostname":"952554185","type":"proxy","minDiskAvailableGb":380.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.177","c29::100e"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"1385652422","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1385652422","group":"0","index":11,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-2012135647"},{"id":"1388729559","hostname":"1388729559","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.77.114","c2b::10c0"],"additionalIpAddresses":["c2b::10cf","c2b::10ce","c2b::10cb","c2b::10ca","c2b::10cd","c2b::10cc","c2b::10e0","c2b::10d7","c2b::10d6","c2b::10d9","c2b::10d8","c2b::10d3","c2b::10d2","c2b::10d5","c2b::10d4","c2b::10df","c2b::10dc","c2b::10db","c2b::10de","c2b::10dd","c2b::10d1","c2b::10d0","c2b::10c6","c2b::10c5","c2b::10c8","c2b::10c7","c2b::10c2","c2b::10c1","c2b::10c4","c2b::10c3","c2b::10da","c2b::10c9"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":29,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-59894657","hostname":"-59894657","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2a::1068"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-989926828","group":"3","index":13,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-167779330"},{"id":"1334604191","hostname":"1334604191","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c45::106e"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3020272","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"948605591","hostname":"948605591","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c40::10bc"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"-721473314","hostname":"-721473314","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c45::10a6"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":23,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-496292156"},{"id":"1522752738","hostname":"1522752738","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c28::107c"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1207107937"},{"id":"-614255295","hostname":"-614255295","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2a::1001"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"-1025299769","hostname":"-1025299769","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c28::103e"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":31,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"514006240"},{"id":"-1475643347","hostname":"-1475643347","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.90.166","c40::1073"],"additionalIpAddresses":["c40::1079","c40::107a","c40::107b","c40::1074","c40::1075","c40::1076","c40::1077","c40::1078"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1069032350","hostname":"1069032350","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2a::109e"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":38,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1229740191"},{"id":"1978709977","hostname":"1978709977","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c27::10cc"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":34,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"2047882875"},{"id":"-802112485","hostname":"-802112485","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c40::107b"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":48,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1475643347"},{"id":"364514184","hostname":"364514184","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c40::103d"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":59,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1867043290"},{"id":"-1443714106","hostname":"-1443714106","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::1006"],"additionalIpAddresses":[],"owner":{"tenant":"-1983508318","application":"-1983508318","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1983508318","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"-213243522","hostname":"-213243522","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::106b"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"509174424","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"20489253","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"-2112448477","hostname":"-2112448477","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2b::104a"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":30,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1649000480"},{"id":"740337689","hostname":"740337689","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c27::10ab"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":18,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-838248773"},{"id":"505145380","hostname":"505145380","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1073"],"additionalIpAddresses":[],"owner":{"tenant":"223606124","application":"222116894","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"-1622997757","hostname":"-1622997757","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c27::10aa"],"additionalIpAddresses":[],"owner":{"tenant":"-2059328563","application":"-2059328563","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"2142745311","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-838248773"},{"id":"771948099","hostname":"771948099","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c2a::1003"],"additionalIpAddresses":[],"owner":{"tenant":"-2059328563","application":"-2059328563","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"514006240","hostname":"514006240","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.111","c28::1037"],"additionalIpAddresses":["c28::103a","c28::103b","c28::103c","c28::103d","c28::103e","c28::103f","c28::1040","c28::1041","c28::1042","c28::1043","c28::1044","c28::1045","c28::1046","c28::1047","c28::1048","c28::1049","c28::104a","c28::104b","c28::104c","c28::104d","c28::104e","c28::104f","c28::1050","c28::1051","c28::1052","c28::1053","c28::1054","c28::1055","c28::1056","c28::1057","c28::1038","c28::1039"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":15,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"616215289","hostname":"616215289","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1066"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-267429795","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1609604578","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"599368188","hostname":"599368188","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::107d"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-1937557253","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"2083350634","hostname":"2083350634","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c27::1059"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":15,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1354781178"},{"id":"446594262","hostname":"446594262","type":"config","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["1.1.88.253","c2f::101c"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"-1457980858","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1457980858","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1735904210"},{"id":"-2023242964","hostname":"-2023242964","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2b::10c3"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":11,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1388729559"},{"id":"-1679023711","hostname":"-1679023711","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.113","c28::1058"],"additionalIpAddresses":["c28::105a","c28::105b","c28::105c","c28::105d","c28::105e","c28::105f","c28::1060","c28::1061","c28::1062","c28::1063","c28::1064","c28::1065","c28::1066","c28::1067","c28::1068","c28::1069","c28::106a","c28::106b","c28::106c","c28::106d","c28::106e","c28::106f","c28::1070","c28::1071","c28::1072","c28::1073","c28::1074","c28::1075","c28::1076","c28::1077","c28::1078","c28::1059"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":25,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-57510712","hostname":"-57510712","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::1008"],"additionalIpAddresses":[],"owner":{"tenant":"-1983508318","application":"-1983508318","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"1428826999","hostname":"1428826999","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1078"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-267429795","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1609604578","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"-881058014","hostname":"-881058014","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1071"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"-1267056614","hostname":"-1267056614","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c40::10bf"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1281572300","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"-348618915","hostname":"-348618915","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.90.176","c40::1016"],"additionalIpAddresses":["c40::1038","c40::108a","c40::108b","c40::108c","c40::108d","c40::108e","c40::108f","c40::1080","c40::1081","c40::1082","c40::1083","c40::1084","c40::1085","c40::1020","c40::1086","c40::1087","c40::1088","c40::1089","c40::107c","c40::107d","c40::103a","c40::107e","c40::107f","c40::1090","c40::1091","c40::1092","c40::1093","c40::1094","c40::1095","c40::1096","c40::1097","c40::1098"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":38,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1637544448","hostname":"-1637544448","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2a::1049"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-354378891","group":"0","index":14,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"547954621"},{"id":"1902610178","hostname":"1902610178","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2b::10ab"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1909456459","group":"0","index":27,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1248447295"},{"id":"-1820717283","hostname":"-1820717283","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c40::1060"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":51,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1444436682"},{"id":"1649000480","hostname":"1649000480","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.77.112","c2b::103c"],"additionalIpAddresses":["c2b::1058","c2b::1057","c2b::1059","c2b::1054","c2b::1053","c2b::1056","c2b::1055","c2b::104a","c2b::103f","c2b::103e","c2b::105c","c2b::103d","c2b::1050","c2b::1052","c2b::1051","c2b::1047","c2b::1046","c2b::1049","c2b::1048","c2b::1043","c2b::1042","c2b::1045","c2b::1044","c2b::105b","c2b::105a","c2b::104f","c2b::104c","c2b::104b","c2b::104e","c2b::104d","c2b::1041","c2b::1040"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":31,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1921643747","hostname":"1921643747","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.77.33","c2a::100a"],"additionalIpAddresses":["c2a::100f","c2a::100e","c2a::100d","c2a::100c","c2a::100b","c2a::1012","c2a::1011","c2a::1010"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":12,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1964321151","hostname":"1964321151","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2a::1048"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":36,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"547954621"},{"id":"2047882875","hostname":"2047882875","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c27::10b8","1.1.76.48"],"additionalIpAddresses":["c27::10ce","c27::10cd","c27::10cf","c27::10ca","c27::10cc","c27::10cb","c27::10c5","c27::10c4","c27::10c7","c27::10c6","c27::10c9","c27::10c8","c27::10c1","c27::10c0","c27::10c3","c27::10c2","c27::10bd","c27::10bc","c27::10bf","c27::10be","c27::10bb","c27::10ba","c27::10d6","c27::10d5","c27::10d8","c27::10d7","c27::10b9","c27::10d0","c27::10d2","c27::10d1","c27::10d4","c27::10d3"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":20,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1546836058","hostname":"-1546836058","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c28::109c"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"20489253","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"235035247","hostname":"235035247","type":"confighost","minDiskAvailableGb":500.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":false,"ipAddresses":["c18::101c","1.1.72.112"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"1456486768","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1456486768","group":"0","index":2,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1890405598","hostname":"1890405598","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2b::108a"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":44,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-156463203"},{"id":"600750011","hostname":"600750011","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::105a"],"additionalIpAddresses":[],"owner":{"tenant":"223606124","application":"222116894","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1115596927","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"547954621"},{"id":"311892192","hostname":"311892192","type":"proxyhost","minDiskAvailableGb":480.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.176","c29::100b"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"-1907449433","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-1907449433","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"364756938","hostname":"364756938","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c26::1009"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"661679481"},{"id":"1918672427","hostname":"1918672427","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c28::10a1"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"-37262403","hostname":"-37262403","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2a::107c"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-633292731","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-167779330"},{"id":"-1883322427","hostname":"-1883322427","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c45::108b"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1909456459","group":"5","index":32,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1189393853"},{"id":"-2107433954","hostname":"-2107433954","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c28::10bc"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1701655965"},{"id":"664730080","hostname":"664730080","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":8.0,"fastDisk":true,"ipAddresses":["c45::10a8"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":11,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-496292156"},{"id":"-272869570","hostname":"-272869570","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c40::106b"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":49,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"887692099"},{"id":"-1386011164","hostname":"-1386011164","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c28::107e"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-989926828","group":"2","index":12,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1207107937"},{"id":"-7467260","hostname":"-7467260","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::103c"],"additionalIpAddresses":[],"owner":{"tenant":"-2059328563","application":"-2059328563","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":4,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"547954621"},{"id":"-1574159711","hostname":"-1574159711","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1070"],"additionalIpAddresses":[],"owner":{"tenant":"-1983508318","application":"-1983508318","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1983508318","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"1357831777","hostname":"1357831777","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c45::10a9"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":12,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-496292156"},{"id":"1750960332","hostname":"1750960332","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c26::100b"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":11,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"661679481"},{"id":"1867043290","hostname":"1867043290","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.90.178","c40::103b"],"additionalIpAddresses":["c40::1057","c40::1058","c40::1059","c40::104a","c40::104b","c40::104c","c40::104d","c40::104e","c40::104f","c40::1040","c40::1041","c40::1042","c40::1043","c40::1044","c40::1045","c40::1046","c40::1047","c40::1048","c40::1049","c40::105a","c40::105b","c40::103c","c40::103d","c40::103e","c40::103f","c40::1050","c40::1051","c40::1052","c40::1053","c40::1054","c40::1055","c40::1056"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":36,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1207107937","hostname":"1207107937","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.114","c28::1079"],"additionalIpAddresses":["c28::107a","c28::107b","c28::107c","c28::107d","c28::107e","c28::107f","c28::1090","c28::1080","c28::1081","c28::1082","c28::1083","c28::1084","c28::1085","c28::1086","c28::1087","c28::1088","c28::1089","c28::108a","c28::108b","c28::108c","c28::108d","c28::108e","c28::108f","c28::1091","c28::1092","c28::1093","c28::1094","c28::1095","c28::1096","c28::1097","c28::1098","c28::1099"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":16,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1584485603","hostname":"1584485603","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2b::105f"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1909456459","group":"1","index":33,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"955898783"},{"id":"-1684989694","hostname":"-1684989694","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2b::103e"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":19,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1649000480"},{"id":"532469033","hostname":"532469033","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c28::109f"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":39,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"-86489022","hostname":"-86489022","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.91.230","c45::106d"],"additionalIpAddresses":["c45::1073","c45::1072","c45::1071","c45::1070","c45::106f","c45::106e","c45::1075","c45::1074"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1900209634","hostname":"1900209634","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c2a::109f","1.1.77.50"],"additionalIpAddresses":["c2a::10a9","c2a::10a8","c2a::10a7","c2a::10a6","c2a::10a5","c2a::10a4","c2a::10a3","c2a::10a2","c2a::10a1","c2a::10a0","c2a::10b0","c2a::10bf","c2a::10be","c2a::10bd","c2a::10bc","c2a::10bb","c2a::10ba","c2a::10b9","c2a::10b8","c2a::10b7","c2a::10b6","c2a::10b5","c2a::10b4","c2a::10b3","c2a::10b2","c2a::10b1","c2a::10af","c2a::10ae","c2a::10ad","c2a::10ac","c2a::10ab","c2a::10aa"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":17,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"2002418683","hostname":"2002418683","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":8.0,"fastDisk":true,"ipAddresses":["c45::1068"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"-1711460001","hostname":"-1711460001","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2b::108b"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-633292731","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-156463203"},{"id":"-2017379996","hostname":"-2017379996","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2b::1060"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":58,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"955898783"},{"id":"-1735904210","hostname":"-1735904210","type":"confighost","minDiskAvailableGb":500.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":false,"ipAddresses":["1.1.88.253","c2f::101c"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"1456486768","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1456486768","group":"0","index":3,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1929743267","hostname":"1929743267","type":"proxyhost","minDiskAvailableGb":480.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c26::1019","1.1.75.239"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"-1907449433","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-1907449433","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1225570730","hostname":"1225570730","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c28::10a0"],"additionalIpAddresses":[],"owner":{"tenant":"-1983508318","application":"-1983508318","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"-85024190","hostname":"-85024190","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c28::10d0"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-633292731","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1701655965"},{"id":"-1547078812","hostname":"-1547078812","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c40::1020"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"103891066","group":"0","index":38,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-348618915"},{"id":"-496292156","hostname":"-496292156","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c45::10a4","1.1.91.241"],"additionalIpAddresses":["c45::10b9","c45::10b8","c45::10b7","c45::10b6","c45::10b5","c45::10b4","c45::10b3","c45::10b2","c45::10b1","c45::10b0","c45::10bf","c45::10be","c45::10bd","c45::10bc","c45::10bb","c45::10ba","c45::10a9","c45::10a8","c45::10a7","c45::10a6","c45::10a5","c45::10c4","c45::10c3","c45::10c2","c45::10c1","c45::10c0","c45::10af","c45::10ae","c45::10ad","c45::10ac","c45::10ab","c45::10aa"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":35,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1536527140","hostname":"1536527140","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2b::107f"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":3,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-156463203"},{"id":"1854900286","hostname":"1854900286","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c45::101e"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":22,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1189393853"},{"id":"-838248773","hostname":"-838248773","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c27::1097","1.1.76.51"],"additionalIpAddresses":["c27::10ac","c27::10ab","c27::10ae","c27::10ad","c27::10af","c27::1099","c27::10aa","c27::1098","c27::10a3","c27::10a2","c27::10a5","c27::10a4","c27::10a7","c27::10a6","c27::10a9","c27::10a8","c27::10a1","c27::10a0","c27::109a","c27::10b4","c27::10b3","c27::10b6","c27::10b5","c27::10b7","c27::109c","c27::109b","c27::109e","c27::109d","c27::10b0","c27::109f","c27::10b2","c27::10b1"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":27,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1960158311","hostname":"-1960158311","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c40::10be"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-1937557253","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"-1106087263","hostname":"-1106087263","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2a::10bf"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":42,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1900209634"},{"id":"-926263172","hostname":"-926263172","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c45::1033"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-354378891","group":"0","index":18,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1041720612"},{"id":"-707456158","hostname":"-707456158","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2a::107f"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1229740191"},{"id":"-236952228","hostname":"-236952228","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c27::10cf"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":35,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"2047882875"},{"id":"1578622635","hostname":"1578622635","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2b::10c2"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":4,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1388729559"},{"id":"1162041343","hostname":"1162041343","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2a::10a0"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":2,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1900209634"},{"id":"633207040","hostname":"633207040","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2a::1069"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":33,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-167779330"},{"id":"1916875905","hostname":"1916875905","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2b::103d"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1649000480"},{"id":"1641707288","hostname":"1641707288","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c40::10bd"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"-1334376780","hostname":"-1334376780","type":"host","minDiskAvailableGb":3840.0,"minMainMemoryAvailableGb":384.0,"minCpuCores":72.0,"fastDisk":true,"ipAddresses":["1.1.108.16","c6e::1000"],"additionalIpAddresses":["c6e::1030","c6e::101e","c6e::101d","c6e::101f","c6e::101a","c6e::101c","c6e::101b","c6e::1019","c6e::1018","c6e::1015","c6e::1014","c6e::1017","c6e::1016","c6e::1011","c6e::1010","c6e::1013","c6e::1012","c6e::1020","c6e::100d","c6e::102f","c6e::100c","c6e::102e","c6e::100f","c6e::100e","c6e::102b","c6e::102a","c6e::100b","c6e::102d","c6e::100a","c6e::102c","c6e::1008","c6e::1007","c6e::1029","c6e::1009","c6e::1004","c6e::1026","c6e::1003","c6e::1025","c6e::1006","c6e::1028","c6e::1005","c6e::1027","c6e::1022","c6e::1021","c6e::1002","c6e::1024","c6e::1001","c6e::1023"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":40,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-160632664","hostname":"-160632664","type":"tenant","minDiskAvailableGb":200.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c28::109e"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"20489253","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"20489253","group":"1","index":11,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"1791360512","hostname":"1791360512","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::10b3"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1298275357","group":"0","index":2,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1900209634"},{"id":"-14354461","hostname":"-14354461","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2a::1080"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":20,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1229740191"},{"id":"1301179204","hostname":"1301179204","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c28::10d2"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":43,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1701655965"},{"id":"1444436682","hostname":"1444436682","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.90.167","c40::101a"],"additionalIpAddresses":["c40::1035","c40::2005","c40::1060","c40::105c","c40::105d","c40::1033","c40::105e","c40::105f"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":4,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1599446916","hostname":"-1599446916","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1069"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-267429795","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"4045543","hostname":"4045543","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c27::1056"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"20489253","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1354781178"},{"id":"-1799188960","hostname":"-1799188960","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2a::10be"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-633292731","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1900209634"},{"id":"588123629","hostname":"588123629","type":"confighost","minDiskAvailableGb":500.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":false,"ipAddresses":["1.1.88.118","c2e::1024"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"1456486768","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1456486768","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-233161475","hostname":"-233161475","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1034"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"20489253","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1041720612"},{"id":"-41196190","hostname":"-41196190","type":"proxyhost","minDiskAvailableGb":480.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.175","c29::100c"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"-1907449433","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-1907449433","group":"0","index":2,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1802676639","hostname":"1802676639","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2a::10bd"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1900209634"},{"id":"885520938","hostname":"885520938","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2b::10c1"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-633292731","group":"0","index":11,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1388729559"},{"id":"599465803","hostname":"599465803","type":"proxy","minDiskAvailableGb":380.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c26::1019","1.1.75.239"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"1385652422","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1385652422","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1929743267"},{"id":"-1701655965","hostname":"-1701655965","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c28::10bb","1.1.76.115"],"additionalIpAddresses":["c28::10d0","c28::10d1","c28::10d2","c28::10d3","c28::10d4","c28::10d5","c28::10d6","c28::10d7","c28::10d8","c28::10d9","c28::10da","c28::10db","c28::10bc","c28::10bd","c28::10be","c28::10bf","c28::10c0","c28::10c1","c28::10c2","c28::10c3","c28::10c4","c28::10c5","c28::10c6","c28::10c7","c28::10c8","c28::10c9","c28::10ca","c28::10cb","c28::10cc","c28::10cd","c28::10ce","c28::10cf"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":18,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1088285226","hostname":"-1088285226","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2b::10e0"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":45,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1388729559"},{"id":"-1324278299","hostname":"-1324278299","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2b::1061"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-354378891","group":"0","index":19,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"955898783"},{"id":"-853977115","hostname":"-853977115","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c40::1038"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":61,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-348618915"},{"id":"2027705888","hostname":"2027705888","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::106f"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-1937557253","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-989926828","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"-325256607","hostname":"-325256607","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2b::108d"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-156463203"},{"id":"608077507","hostname":"608077507","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c28::10d1"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1701655965"},{"id":"946330777","hostname":"946330777","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c27::106a"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-354378891","group":"0","index":16,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1354781178"},{"id":"1057615881","hostname":"1057615881","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c40::103e"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1867043290"},{"id":"-1683193172","hostname":"-1683193172","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c28::10a2"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-267429795","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"-750612409","hostname":"-750612409","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::1007"],"additionalIpAddresses":[],"owner":{"tenant":"223606124","application":"222116894","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"-906345219","hostname":"-906345219","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::106a"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3020272","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":4,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"-1877433577","hostname":"-1877433577","type":"config","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c18::101c","1.1.72.112"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"-1457980858","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1457980858","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"235035247"},{"id":"-28371617","hostname":"-28371617","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c45::10a7"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"103891066","group":"0","index":35,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-496292156"},{"id":"-93733509","hostname":"-93733509","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::107c"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"509174424","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"20489253","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"-76886408","hostname":"-76886408","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1065"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"509174424","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":4,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"829651041","hostname":"829651041","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c28::107b"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":19,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1207107937"},{"id":"-2027478477","hostname":"-2027478477","type":"host","minDiskAvailableGb":3840.0,"minMainMemoryAvailableGb":384.0,"minCpuCores":72.0,"fastDisk":true,"ipAddresses":["c6d::1000","1.1.107.211"],"additionalIpAddresses":["c6d::100f","c6d::100d","c6d::102f","c6d::100e","c6d::100b","c6d::102d","c6d::100c","c6d::102e","c6d::102b","c6d::100a","c6d::102c","c6d::1020","c6d::1021","c6d::1006","c6d::1028","c6d::1007","c6d::1029","c6d::1004","c6d::1026","c6d::1005","c6d::1027","c6d::1002","c6d::1024","c6d::1003","c6d::1025","c6d::1022","c6d::1001","c6d::1023","c6d::1008","c6d::1009","c6d::101e","c6d::101f","c6d::101c","c6d::101d","c6d::101a","c6d::101b","c6d::1010","c6d::1030","c6d::1017","c6d::1018","c6d::1015","c6d::1016","c6d::1013","c6d::1014","c6d::1011","c6d::1012","c6d::102a","c6d::1019"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":39,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"547954621","hostname":"547954621","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.77.52","c2a::103b"],"additionalIpAddresses":["c2a::1042","c2a::1041","c2a::1040","c2a::104f","c2a::104e","c2a::104d","c2a::104c","c2a::105b","c2a::105a","c2a::1049","c2a::1048","c2a::1047","c2a::1046","c2a::1045","c2a::1044","c2a::1043","c2a::1053","c2a::1052","c2a::1051","c2a::1050","c2a::103f","c2a::103e","c2a::103d","c2a::103c","c2a::104b","c2a::104a","c2a::1059","c2a::1058","c2a::1057","c2a::1056","c2a::1055","c2a::1054"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":28,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1623155622","hostname":"-1623155622","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c27::10cd"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-354378891","group":"0","index":17,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"2047882875"},{"id":"1163357258","hostname":"1163357258","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.90.165","c40::10bb"],"additionalIpAddresses":["c40::10bd","c40::10be","c40::10bf","c40::10c0","c40::10c1","c40::10c2","c40::10c3","c40::10bc"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1377413432","hostname":"1377413432","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.52","c27::1076"],"additionalIpAddresses":["c27::1079","c27::1078","c27::1093","c27::1092","c27::1095","c27::1094","c27::1096","c27::1077","c27::1080","c27::108b","c27::108a","c27::108d","c27::108c","c27::108f","c27::108e","c27::1089","c27::1082","c27::1081","c27::1084","c27::1083","c27::1086","c27::1085","c27::1088","c27::1087","c27::1091","c27::1090","c27::107a","c27::107c","c27::107b","c27::107e","c27::107d","c27::107f"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":26,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1293851708","hostname":"1293851708","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::105b"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":2,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"547954621"},{"id":"-328344759","hostname":"-328344759","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c26::1008"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"661679481"},{"id":"-872134365","hostname":"-872134365","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c28::105c"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":35,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1679023711"},{"id":"735725302","hostname":"735725302","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1077"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-267429795","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"957646904","hostname":"957646904","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c27::1074"],"additionalIpAddresses":[],"owner":{"tenant":"-1983508318","application":"-1983508318","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1983508318","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1354781178"},{"id":"1752827223","hostname":"1752827223","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c45::105e"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":52,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1464327220"},{"id":"399083239","hostname":"399083239","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["c27::10d9","1.1.76.34"],"additionalIpAddresses":["c27::10df","c27::10de","c27::10e1","c27::10e0","c27::10db","c27::10da","c27::10dd","c27::10dc"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":13,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-2012135647","hostname":"-2012135647","type":"proxyhost","minDiskAvailableGb":480.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.177","c29::100e"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"-1907449433","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-1907449433","group":"0","index":3,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-156463203","hostname":"-156463203","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c2b::107e","1.1.77.116"],"additionalIpAddresses":["c2b::1098","c2b::1097","c2b::1099","c2b::108c","c2b::108b","c2b::108e","c2b::108d","c2b::108a","c2b::107f","c2b::1094","c2b::1093","c2b::1096","c2b::1095","c2b::1090","c2b::1092","c2b::1091","c2b::1087","c2b::1086","c2b::1089","c2b::1088","c2b::109d","c2b::109c","c2b::109e","c2b::109b","c2b::109a","c2b::108f","c2b::1083","c2b::1082","c2b::1085","c2b::1084","c2b::1081","c2b::1080"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":23,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1157803570","hostname":"-1157803570","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c26::100d"],"additionalIpAddresses":[],"owner":{"tenant":"223606124","application":"222116894","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1115596927","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"661679481"},{"id":"-1041720612","hostname":"-1041720612","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c45::1009","1.1.91.242"],"additionalIpAddresses":["c45::2004","c45::2005","c45::101d","c45::101c","c45::101a","c45::103b","c45::103a","c45::1025","c45::1024","c45::1023","c45::1022","c45::1021","c45::1020","c45::100d","c45::102f","c45::100c","c45::102e","c45::100b","c45::102d","c45::100a","c45::102c","c45::1019","c45::1039","c45::1038","c45::1037","c45::1036","c45::1035","c45::1034","c45::1033","c45::1032","c45::1031","c45::1030"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":37,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1390248937","hostname":"1390248937","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c27::1058"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"103891066","group":"0","index":33,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1354781178"},{"id":"1354781178","hostname":"1354781178","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.49","c27::1055"],"additionalIpAddresses":["c27::1057","c27::1056","c27::1059","c27::1058","c27::1071","c27::1070","c27::1073","c27::1072","c27::1075","c27::1074","c27::106b","c27::106a","c27::106d","c27::106c","c27::106f","c27::106e","c27::1068","c27::1067","c27::1069","c27::1060","c27::1062","c27::1061","c27::1064","c27::1063","c27::1066","c27::1065","c27::105f","c27::105a","c27::105c","c27::105b","c27::105e","c27::105d"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":19,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-853734361","hostname":"-853734361","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c28::109d"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"-1113612637","hostname":"-1113612637","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c45::1099"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":56,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1189393853"},{"id":"-141137706","hostname":"-141137706","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c27::108a"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1909456459","group":"2","index":29,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1377413432"},{"id":"891383906","hostname":"891383906","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2b::105e"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"103891066","group":"0","index":36,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"955898783"},{"id":"1153041919","hostname":"1153041919","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1036"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1041720612"},{"id":"1057858635","hostname":"1057858635","type":"tenant","minDiskAvailableGb":200.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c26::100a"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"20489253","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"20489253","group":"0","index":12,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"661679481"},{"id":"-918737798","hostname":"-918737798","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c27::10d8"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"2047882875"},{"id":"-1420235233","hostname":"-1420235233","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c28::10b3"],"additionalIpAddresses":[],"owner":{"tenant":"-2059328563","application":"-2059328563","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"2142745311","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"-1371473654","hostname":"-1371473654","type":"proxy","minDiskAvailableGb":380.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.175","c29::100c"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"1385652422","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1385652422","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-41196190"},{"id":"-573954917","hostname":"-573954917","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c40::10c0"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1028554796","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"-1248447295","hostname":"-1248447295","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.77.111","c2b::109f"],"additionalIpAddresses":["c2b::10ad","c2b::10ac","c2b::10af","c2b::10ae","c2b::10ab","c2b::10aa","c2b::10b5","c2b::10b4","c2b::10b7","c2b::10b6","c2b::10b1","c2b::10b0","c2b::10b3","c2b::10b2","c2b::10b9","c2b::10b8","c2b::10be","c2b::10bd","c2b::10bf","c2b::10ba","c2b::10bc","c2b::10bb","c2b::10a4","c2b::10a3","c2b::10a6","c2b::10a5","c2b::10a0","c2b::10a2","c2b::10a1","c2b::10a8","c2b::10a7","c2b::10a9"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":32,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1189393853","hostname":"-1189393853","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c45::101b","1.1.91.240"],"additionalIpAddresses":["c45::1095","c45::1094","c45::1093","c45::1092","c45::1091","c45::1090","c45::101f","c45::101e","c45::109f","c45::109e","c45::109d","c45::109c","c45::109b","c45::109a","c45::1089","c45::1088","c45::10a3","c45::10a2","c45::102b","c45::10a1","c45::102a","c45::10a0","c45::108f","c45::108e","c45::108d","c45::108c","c45::108b","c45::108a","c45::1099","c45::1098","c45::1097","c45::1096"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":34,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"2055029541","hostname":"2055029541","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c28::109b"],"additionalIpAddresses":[],"owner":{"tenant":"223606124","application":"222116894","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"685634437","hostname":"685634437","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::103d"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"547954621"},{"id":"-1714276213","hostname":"-1714276213","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.91.215","c45::1076"],"additionalIpAddresses":["c45::107c","c45::107b","c45::107a","c45::1079","c45::1078","c45::1077","c45::107e","c45::107d"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1832746594","hostname":"-1832746594","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::100b"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"50511102","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1921643747"},{"id":"-1746965313","hostname":"-1746965313","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c45::101f"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"103891066","group":"0","index":34,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1189393853"},{"id":"497260739","hostname":"497260739","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c28::103a"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-989926828","group":"1","index":11,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"514006240"},{"id":"479858175","hostname":"479858175","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::106c"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-1937557253","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":4,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"955898783","hostname":"955898783","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c2b::105d","1.1.77.113"],"additionalIpAddresses":["c2b::1079","c2b::1076","c2b::1075","c2b::1078","c2b::1077","c2b::106a","c2b::106c","c2b::106b","c2b::105f","c2b::105e","c2b::1072","c2b::1071","c2b::1074","c2b::1073","c2b::1070","c2b::1069","c2b::1068","c2b::1065","c2b::1064","c2b::1067","c2b::1066","c2b::107b","c2b::107a","c2b::107d","c2b::107c","c2b::106e","c2b::106d","c2b::106f","c2b::1061","c2b::1060","c2b::1063","c2b::1062"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":30,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-328587513","hostname":"-328587513","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c40::103c"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"103891066","group":"0","index":37,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1867043290"},{"id":"-187956317","hostname":"-187956317","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1072"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1298275357","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"829408287","hostname":"829408287","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c40::109a"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1882495550"},{"id":"1309316986","hostname":"1309316986","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1067"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3020272","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"470255561"},{"id":"-2079112861","hostname":"-2079112861","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c28::107d"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1909456459","group":"4","index":31,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1207107937"},{"id":"78846402","hostname":"78846402","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c2a::1002"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"-1464327220","hostname":"-1464327220","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["c45::1026","1.1.91.231"],"additionalIpAddresses":["c45::1062","c45::1061","c45::1060","c45::1027","c45::105f","c45::105e","c45::105d","c45::1063"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1292469885","hostname":"1292469885","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::107e"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"509174424","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"-782222819","hostname":"-782222819","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c27::10af"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1909456459","group":"3","index":30,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-838248773"},{"id":"1785286633","hostname":"1785286633","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.76.33","c27::1000"],"additionalIpAddresses":["c27::1002","c27::1001","c27::1004","c27::1003","c27::1006","c27::1005","c27::1008","c27::1007"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":14,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"752622429","hostname":"752622429","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c40::1062"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":50,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1580793796"},{"id":"2121928696","hostname":"2121928696","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":8.0,"fastDisk":true,"ipAddresses":["c45::1079"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"-839959959","hostname":"-839959959","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c27::1077"],"additionalIpAddresses":[],"owner":{"tenant":"-828802209","application":"-1480249367","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1281572300","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1377413432"},{"id":"1883464133","hostname":"1883464133","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":16.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c28::103c"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-1117571703","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-633292731","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"514006240"},{"id":"-1475324516","hostname":"-1475324516","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c27::10ae"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":41,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-838248773"},{"id":"246558497","hostname":"246558497","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2a::100e"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1921643747"},{"id":"-726245083","hostname":"-726245083","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2b::104c"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":16,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1649000480"},{"id":"-1518514965","hostname":"-1518514965","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c27::105a"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":1,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1354781178"},{"id":"1465049796","hostname":"1465049796","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c2a::1004"],"additionalIpAddresses":[],"owner":{"tenant":"20489253","application":"509174424","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"-493022966","hostname":"-493022966","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c27::10bd"],"additionalIpAddresses":[],"owner":{"tenant":"-1983508318","application":"-1983508318","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"2047882875"},{"id":"-1553982724","hostname":"-1553982724","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c28::109a","1.1.76.116"],"additionalIpAddresses":["c28::109b","c28::109c","c28::109d","c28::109e","c28::109f","c28::10b0","c28::10b1","c28::10b2","c28::10b3","c28::10b4","c28::10b5","c28::10b6","c28::10b7","c28::10b8","c28::10b9","c28::10a9","c28::10ba","c28::10a0","c28::10a1","c28::10a2","c28::10a3","c28::10a4","c28::10a5","c28::10a6","c28::10a7","c28::10a8","c28::10aa","c28::10ab","c28::10ac","c28::10ad","c28::10ae","c28::10af"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":21,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1891348774","hostname":"1891348774","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::1075"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"1505350174","hostname":"1505350174","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c40::10c3"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"-714928956","hostname":"-714928956","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":8.0,"fastDisk":true,"ipAddresses":["c2b::1056"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1649000480"},{"id":"2091475201","hostname":"2091475201","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2b::10a1"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1248447295"},{"id":"887692099","hostname":"887692099","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.90.164","c40::106a"],"additionalIpAddresses":["c40::1070","c40::1071","c40::1072","c40::106b","c40::106c","c40::106d","c40::106e","c40::106f"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":2,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1479936903","hostname":"-1479936903","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::107a"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3020272","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"-1524345195","hostname":"-1524345195","type":"config","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["1.1.88.118","c2e::1024"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"-1457980858","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1457980858","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"588123629"},{"id":"283824987","hostname":"283824987","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c45::1082"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":54,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-222846136"},{"id":"551963991","hostname":"551963991","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c27::108b"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":17,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1377413432"},{"id":"1343527840","hostname":"1343527840","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c28::1059"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":60,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1679023711"},{"id":"1614460806","hostname":"1614460806","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c2a::109b"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":37,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1229740191"},{"id":"-1608048742","hostname":"-1608048742","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":48.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c45::2004"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-989926828","group":"0","index":10,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1041720612"},{"id":"-1419346780","hostname":"-1419346780","type":"tenant","minDiskAvailableGb":100.0,"minMainMemoryAvailableGb":32.0,"minCpuCores":6.0,"fastDisk":true,"ipAddresses":["c2b::104b"],"additionalIpAddresses":[],"owner":{"tenant":"1914981343","application":"-354378891","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-354378891","group":"0","index":15,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1649000480"},{"id":"-446543200","hostname":"-446543200","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":8.0,"fastDisk":true,"ipAddresses":["c2a::100d"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1921643747"},{"id":"-1018385272","hostname":"-1018385272","type":"proxy","minDiskAvailableGb":380.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["1.1.76.176","c29::100b"],"additionalIpAddresses":[],"owner":{"tenant":"-1802291313","application":"1385652422","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1385652422","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"311892192"},{"id":"470255561","hostname":"470255561","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.91.229","c45::1064"],"additionalIpAddresses":["c45::106b","c45::106a","c45::1069","c45::1068","c45::1067","c45::1066","c45::1065","c45::106c"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":8,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1198247077","hostname":"1198247077","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c45::1074"],"additionalIpAddresses":[],"owner":{"tenant":"-840754951","application":"-594933386","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-86489022"},{"id":"1229740191","hostname":"1229740191","type":"host","minDiskAvailableGb":1920.0,"minMainMemoryAvailableGb":256.0,"minCpuCores":48.0,"fastDisk":true,"ipAddresses":["c2a::107e","1.1.77.49"],"additionalIpAddresses":["c2a::1086","c2a::1085","c2a::1084","c2a::1083","c2a::1082","c2a::1081","c2a::1080","c2a::109e","c2a::109d","c2a::109c","c2a::109b","c2a::109a","c2a::1089","c2a::1088","c2a::1087","c2a::1097","c2a::1096","c2a::1095","c2a::1094","c2a::1093","c2a::1092","c2a::1091","c2a::1090","c2a::107f","c2a::108f","c2a::108e","c2a::108d","c2a::108c","c2a::108b","c2a::108a","c2a::1099","c2a::1098"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":24,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-1718401466","hostname":"-1718401466","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":8.0,"fastDisk":true,"ipAddresses":["c28::103d"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"514006240"},{"id":"-1021446456","hostname":"-1021446456","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c26::1007"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"661679481"},{"id":"-146858262","hostname":"-146858262","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c27::1078"],"additionalIpAddresses":[],"owner":{"tenant":"-2059328563","application":"-2059328563","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"2142745311","group":"0","index":6,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1377413432"},{"id":"1398373504","hostname":"1398373504","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c2b::10a0"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":47,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1248447295"},{"id":"25238104","hostname":"25238104","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c27::1001"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":41,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1785286633"},{"id":"-188953757","hostname":"-188953757","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":8.0,"fastDisk":true,"ipAddresses":["c2a::105d"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-989926828","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":9,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-167779330"},{"id":"-786835206","hostname":"-786835206","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c45::107b"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3020272","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-1938379550","group":"0","index":5,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1714276213"},{"id":"546243435","hostname":"546243435","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c27::1079"],"additionalIpAddresses":[],"owner":{"tenant":"103891066","application":"103891066","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1544803905","group":"0","index":21,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1377413432"},{"id":"-2136815803","hostname":"-2136815803","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":1.5,"fastDisk":true,"ipAddresses":["c2a::1005"],"additionalIpAddresses":[],"owner":{"tenant":"-989926828","application":"-1937557253","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"-989926828","group":"0","index":4,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-157661344"},{"id":"1722396485","hostname":"1722396485","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c45::100a"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":40,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1041720612"},{"id":"1245065688","hostname":"1245065688","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c27::108c"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":40,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1377413432"},{"id":"921359109","hostname":"921359109","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":8.0,"minCpuCores":4.0,"fastDisk":true,"ipAddresses":["c2a::109a"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"-410956671","group":"0","index":20,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1229740191"},{"id":"-1414575011","hostname":"-1414575011","type":"tenant","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":24.0,"fastDisk":true,"ipAddresses":["c45::10a5"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"987366342","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"987366342","group":"0","index":57,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-496292156"},{"id":"812248477","hostname":"812248477","type":"tenant","minDiskAvailableGb":50.0,"minMainMemoryAvailableGb":3.0,"minCpuCores":0.5,"fastDisk":true,"ipAddresses":["c40::10c2"],"additionalIpAddresses":[],"owner":{"tenant":"-1938379550","application":"3449687","instance":"1544803905"},"membership":{"clustertype":"admin","clusterid":"-1440395385","group":"0","index":0,"retired":false},"wantedVespaVersion":"7.72.36","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"1163357258"},{"id":"795426972","hostname":"795426972","type":"tenant","minDiskAvailableGb":800.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":12.0,"fastDisk":true,"ipAddresses":["c28::10b0"],"additionalIpAddresses":[],"owner":{"tenant":"1010990605","application":"1080688167","instance":"1544803905"},"membership":{"clustertype":"content","clusterid":"1080688167","group":"0","index":38,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"DOCKER_CONTAINER","parentHostname":"-1553982724"},{"id":"-157661344","hostname":"-157661344","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.77.34","c2a::1000"],"additionalIpAddresses":["c2a::1008","c2a::1007","c2a::1006","c2a::1005","c2a::1004","c2a::1003","c2a::1002","c2a::1001"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":11,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"1580793796","hostname":"1580793796","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["c40::1061","1.1.90.137"],"additionalIpAddresses":["c40::1068","c40::1069","c40::1062","c40::1063","c40::1064","c40::1065","c40::1066","c40::1067"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":3,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null},{"id":"-222846136","hostname":"-222846136","type":"host","minDiskAvailableGb":960.0,"minMainMemoryAvailableGb":64.0,"minCpuCores":64.0,"fastDisk":true,"ipAddresses":["1.1.91.228","c45::107f"],"additionalIpAddresses":["c45::1084","c45::1083","c45::1082","c45::1081","c45::1080","c45::1087","c45::1086","c45::1085"],"owner":{"tenant":"-1802291313","application":"1843333355","instance":"1544803905"},"membership":{"clustertype":"container","clusterid":"1843333355","group":"0","index":7,"retired":false},"wantedVespaVersion":"7.73.13","state":"active","environment":"BARE_METAL","parentHostname":null}]} \ No newline at end of file
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
index f741002ea5e..11a6839ca59 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
@@ -13,6 +13,7 @@ using vespalib::tensor::Tensor;
using vespalib::tensor::DenseTensorView;
using vespalib::tensor::MutableDenseTensorView;
using vespalib::eval::ValueType;
+using CellType = vespalib::eval::ValueType::CellType;
namespace search::tensor {
@@ -21,12 +22,20 @@ namespace {
constexpr size_t MIN_BUFFER_ARRAYS = 1024;
constexpr size_t DENSE_TENSOR_ALIGNMENT = 32;
+size_t size_of(CellType type) {
+ switch (type) {
+ case CellType::DOUBLE: return sizeof(double);
+ case CellType::FLOAT: return sizeof(float);
+ }
+ abort();
+}
+
}
DenseTensorStore::TensorSizeCalc::TensorSizeCalc(const ValueType &type)
: _numBoundCells(1u),
_numUnboundDims(0u),
- _cellSize(sizeof(double))
+ _cellSize(size_of(type.cell_type()))
{
for (const auto & dim : type.dimensions()) {
if (dim.is_bound()) {
@@ -237,6 +246,7 @@ checkMatchingType(const ValueType &lhs, const ValueType &rhs, size_t numCells)
checkNumCells *= rhsItr->size;
++rhsItr;
}
+ assert(lhs.cell_type() == rhs.cell_type());
assert(numCells == checkNumCells);
assert(rhsItr == rhsItrEnd);
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java b/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java
index 8e566fac0b6..9869f1e908c 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java
@@ -168,7 +168,11 @@ public class TensorType {
@Override
public String toString() {
- return "tensor(" + dimensions.stream().map(Dimension::toString).collect(Collectors.joining(",")) + ")";
+ if ((rank() == 0) || (valueType == Value.DOUBLE)) {
+ return "tensor(" + dimensions.stream().map(Dimension::toString).collect(Collectors.joining(",")) + ")";
+ } else {
+ return "tensor<" + valueType + ">(" + dimensions.stream().map(Dimension::toString).collect(Collectors.joining(",")) + ")";
+ }
}
@Override
@@ -177,6 +181,7 @@ public class TensorType {
if (o == null || getClass() != o.getClass()) return false;
TensorType other = (TensorType)o;
+ if ( (this.rank() == 0) && (other.rank() == 0)) return true;
if ( this.valueType != other.valueType) return false;
if ( ! this.dimensions.equals(other.dimensions)) return false;
return true;
diff --git a/zkfacade/CMakeLists.txt b/zkfacade/CMakeLists.txt
index cf02f163e67..52eae58e108 100644
--- a/zkfacade/CMakeLists.txt
+++ b/zkfacade/CMakeLists.txt
@@ -2,7 +2,7 @@
install_fat_java_artifact(zkfacade)
install_fat_java_artifact(zkctl)
-vespa_install_script(src/main/sh/zkcat vespa-zkcat bin)
-vespa_install_script(src/main/sh/zkcli vespa-zkcli bin)
-vespa_install_script(src/main/sh/zkctl vespa-zkctl bin)
-vespa_install_script(src/main/sh/zkls vespa-zkls bin)
+vespa_install_script(src/main/sh/vespa-zkcat vespa-zkcat bin)
+vespa_install_script(src/main/sh/vespa-zkcli vespa-zkcli bin)
+vespa_install_script(src/main/sh/vespa-zkctl vespa-zkctl bin)
+vespa_install_script(src/main/sh/vespa-zkls vespa-zkls bin)
diff --git a/zkfacade/src/main/sh/zkcat b/zkfacade/src/main/sh/vespa-zkcat
index 675aeabbcfb..ba8924b456f 100755
--- a/zkfacade/src/main/sh/zkcat
+++ b/zkfacade/src/main/sh/vespa-zkcat
@@ -70,4 +70,4 @@ findhost
# END environment bootstrap section
-$VESPA_HOME/bin/zkctl get $@
+$VESPA_HOME/bin/vespa-zkctl get $@
diff --git a/zkfacade/src/main/sh/zkcli b/zkfacade/src/main/sh/vespa-zkcli
index cbc356ae9e1..318836ec574 100755
--- a/zkfacade/src/main/sh/zkcli
+++ b/zkfacade/src/main/sh/vespa-zkcli
@@ -70,7 +70,25 @@ findhost
# END environment bootstrap section
-sudo -u ${VESPA_USER} java \
+usage() {
+ echo "Run Zookeeper command-line client"
+ echo "The following options are recognized:"
+ echo ""
+
+ echo "-h|-help) print this help text"
+ echo "-nosudo do not use sudo when running command"
+}
+
+sudo="sudo -u ${VESPA_USER}"
+while [ $# -gt 0 ]; do
+ case $1 in
+ -h|-help) usage; exit 0;;
+ -nosudo) shift; sudo="" ;;
+ *) echo "Unrecognized option '$1'" >&2; exit 1;;
+ esac
+done
+
+$sudo java \
-cp $VESPA_HOME/lib/jars/zkctl-jar-with-dependencies.jar \
-Dlog4j.configuration=file:$VESPA_HOME/etc/log4j-vespa.properties \
org.apache.zookeeper.ZooKeeperMain "$@"
diff --git a/zkfacade/src/main/sh/zkctl b/zkfacade/src/main/sh/vespa-zkctl
index 721becf8c79..43112abd925 100755
--- a/zkfacade/src/main/sh/zkctl
+++ b/zkfacade/src/main/sh/vespa-zkctl
@@ -71,4 +71,4 @@ findhost
# END environment bootstrap section
# Get rid of the interactive zkcli prompt by running it in a subshell
-(echo "$@" | $VESPA_HOME/bin/zkcli)
+(echo "$@" | $VESPA_HOME/bin/vespa-zkcli)
diff --git a/zkfacade/src/main/sh/zkls b/zkfacade/src/main/sh/vespa-zkls
index c75f63efbde..5ab1204cea8 100755
--- a/zkfacade/src/main/sh/zkls
+++ b/zkfacade/src/main/sh/vespa-zkls
@@ -70,4 +70,4 @@ findhost
# END environment bootstrap section
-$VESPA_HOME/bin/zkctl ls $@
+$VESPA_HOME/bin/vespa-zkctl ls $@