aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@verizonmedia.com>2019-05-02 21:29:29 +0200
committerJon Bratseth <bratseth@verizonmedia.com>2019-05-02 21:29:29 +0200
commit8457cd74f0ac3d876d1f7fd6cd7ea7b503cae491 (patch)
tree4a2eb5ed891f5da85397797fc4c943c33ade8b65
parent75e2698805c454d54afb4b5a8bc62b046c4e3246 (diff)
Allow continuous node resource specs
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java11
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java5
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java6
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java126
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java42
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/BucketSplitting.java11
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/ClusterControllerConfig.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java14
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/Distributor.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/DistributorCluster.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java14
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/StorageNode.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java24
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DocumentSelectionBuilder.java6
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomContentSearchBuilder.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomDispatchBuilder.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomResourceLimitsBuilder.java6
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomSearchCoverageBuilder.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomTuningDispatchBuilder.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/EngineFactoryBuilder.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/GlobalDistributionBuilder.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/SearchDefinitionBuilder.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/FileStorProducer.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/PersistenceProducer.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorServerProducer.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorVisitorProducer.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/search/SearchDefinitionXMLHandler.java5
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java19
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java28
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/FlavorSpec.java107
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/NodeFlavors.java33
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java1
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java27
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java18
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java34
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java5
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java71
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ResourceCapacity.java5
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java67
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java19
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirerTest.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java30
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java1
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java15
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java38
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java19
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java203
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java30
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java24
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/docker-container1.json11
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node11.json11
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json11
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5-after-changes.json11
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json11
61 files changed, 732 insertions, 505 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java
index 3a9a5d59b1a..bae9c52b06e 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java
@@ -14,7 +14,6 @@ import com.yahoo.vespa.model.admin.Admin;
import com.yahoo.vespa.model.admin.Configserver;
import com.yahoo.vespa.model.admin.LogForwarder;
import com.yahoo.vespa.model.admin.ModelConfigProvider;
-import com.yahoo.vespa.model.admin.monitoring.MetricsConsumer;
import com.yahoo.vespa.model.admin.monitoring.DefaultMonitoring;
import com.yahoo.vespa.model.admin.monitoring.Monitoring;
import com.yahoo.vespa.model.admin.monitoring.builder.Metrics;
@@ -26,10 +25,8 @@ import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import static com.yahoo.vespa.model.admin.monitoring.builder.PredefinedMetricSets.predefinedMetricSets;
-import static java.util.logging.Level.WARNING;
/**
* A base class for admin model builders, to support common functionality across versions.
@@ -116,11 +113,11 @@ public abstract class DomAdminBuilderBase extends VespaDomBuilder.DomConfigProdu
void addLogForwarders(ModelElement logForwardingElement, Admin admin) {
if (logForwardingElement == null) return;
- for (ModelElement e : logForwardingElement.getChildren("splunk")) {
+ for (ModelElement e : logForwardingElement.children("splunk")) {
LogForwarder.Config cfg = LogForwarder.cfg()
- .withSplunkHome(e.getStringAttribute("splunk-home"))
- .withDeploymentServer(e.getStringAttribute("deployment-server"))
- .withClientName(e.getStringAttribute("client-name"));
+ .withSplunkHome(e.stringAttribute("splunk-home"))
+ .withDeploymentServer(e.stringAttribute("deployment-server"))
+ .withClientName(e.stringAttribute("client-name"));
admin.setLogForwarderConfig(cfg);
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java
index 3a16264b148..1b0e04b50a8 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java
@@ -17,7 +17,6 @@ import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerCluster;
import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainer;
import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainerCluster;
import com.yahoo.vespa.model.builder.xml.dom.VespaDomBuilder.DomConfigProducerBuilder;
-import com.yahoo.vespa.model.container.xml.ContainerModelBuilder;
import org.w3c.dom.Element;
import java.util.List;
@@ -51,9 +50,9 @@ public class DomAdminV2Builder extends DomAdminBuilderBase {
admin.setClusterControllers(addConfiguredClusterControllers(deployState, admin, adminE));
ModelElement adminElement = new ModelElement(adminE);
- addLogForwarders(adminElement.getChild("logforwarding"), admin);
+ addLogForwarders(adminElement.child("logforwarding"), admin);
- if (adminElement.getChild("filedistribution") != null) {
+ if (adminElement.child("filedistribution") != null) {
deployState.getDeployLogger().log(LogLevel.WARNING, "'filedistribution' element is deprecated and ignored");
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
index 8980c7db93d..71ce6492b09 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
@@ -54,14 +54,14 @@ public class DomAdminV4Builder extends DomAdminBuilderBase {
// Note: These two elements only exists in admin version 4.0
// This build handles admin version 3.0 by ignoring its content (as the content is not useful)
Optional<NodesSpecification> requestedSlobroks =
- NodesSpecification.optionalDedicatedFromParent(adminElement.getChild("slobroks"), context);
+ NodesSpecification.optionalDedicatedFromParent(adminElement.child("slobroks"), context);
Optional<NodesSpecification> requestedLogservers =
- NodesSpecification.optionalDedicatedFromParent(adminElement.getChild("logservers"), context);
+ NodesSpecification.optionalDedicatedFromParent(adminElement.child("logservers"), context);
assignSlobroks(deployState.getDeployLogger(), requestedSlobroks.orElse(NodesSpecification.nonDedicated(3, context)), admin);
assignLogserver(deployState, requestedLogservers.orElse(createNodesSpecificationForLogserver()), admin);
- addLogForwarders(adminElement.getChild("logforwarding"), admin);
+ addLogForwarders(adminElement.child("logforwarding"), admin);
}
private void assignSlobroks(DeployLogger deployLogger, NodesSpecification nodesSpecification, Admin admin) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java
index 1fc70e343f3..1f649b122fa 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java
@@ -20,54 +20,38 @@ public class ModelElement {
private final Element xml;
public ModelElement(Element xml) {
+ if (xml == null) throw new NullPointerException("Can not create ModelElement with null element");
+ if (xml.getNodeName() == null) throw new NullPointerException("Can not create ModelElement with unnamed element");
this.xml = xml;
- if (xml == null) {
- throw new NullPointerException("Can not create ModelElement with null element");
- }
- if (xml.getNodeName() == null) {
- throw new NullPointerException("Can not create ModelElement with unnamed element");
- }
}
- public Element getXml() {
- return xml;
- }
+ public Element getXml() { return xml; }
- /**
- * If not found, return null.
- */
- public ModelElement getChild(String name) {
+ /** Returns the child with the given name, or null if none. */
+ public ModelElement child(String name) {
Element e = XML.getChild(xml, name);
-
- if (e != null) {
- return new ModelElement(e);
- }
-
- return null;
+ if (e == null) return null;
+ return new ModelElement(e);
}
- /**
- * If not found, return empty list
- */
- public List<ModelElement> getChildren(String name) {
+ /** If not found, return empty list. */
+ public List<ModelElement> children(String name) {
List<Element> e = XML.getChildren(xml, name);
List<ModelElement> list = new ArrayList<>();
e.forEach(element -> list.add(new ModelElement(element)));
-
return list;
}
- public ModelElement getChildByPath(String path) {
+ public ModelElement childByPath(String path) {
StringTokenizer tokenizer = new StringTokenizer(path, ".");
ModelElement curElem = this;
while (tokenizer.hasMoreTokens() && curElem != null) {
String pathElem = tokenizer.nextToken();
- ModelElement child = curElem.getChild(pathElem);
+ ModelElement child = curElem.child(pathElem);
if (!tokenizer.hasMoreTokens()) {
- if (child != null) {
+ if (child != null)
return child;
- }
}
curElem = child;
}
@@ -79,9 +63,9 @@ public class ModelElement {
ModelElement curElem = this;
while (tokenizer.hasMoreTokens() && curElem != null) {
String pathElem = tokenizer.nextToken();
- ModelElement child = curElem.getChild(pathElem);
+ ModelElement child = curElem.child(pathElem);
if (!tokenizer.hasMoreTokens()) {
- String attr = curElem.getStringAttribute(pathElem);
+ String attr = curElem.stringAttribute(pathElem);
if (attr != null) {
return attr;
} else if (child != null) {
@@ -111,97 +95,84 @@ public class ModelElement {
public Long childAsLong(String path) {
String child = childAsString(path);
- if (child == null) {
- return null;
- }
+ if (child == null) return null;
return Long.parseLong(child.trim());
}
public Integer childAsInteger(String path) {
String child = childAsString(path);
- if (child == null) {
- return null;
- }
+ if (child == null) return null;
return Integer.parseInt(child.trim());
}
public Double childAsDouble(String path) {
String child = childAsString(path);
- if (child == null) {
- return null;
- }
+ if (child == null) return null;
return Double.parseDouble(child.trim());
}
public Boolean childAsBoolean(String path) {
String child = childAsString(path);
- if (child == null) {
- return null;
- }
+ if (child == null) return null;
return Boolean.parseBoolean(child.trim());
}
public Duration childAsDuration(String path) {
String child = childAsString(path);
- if (child == null) {
- return null;
- }
+ if (child == null) return null;
return new Duration(child);
}
/** Returns the given attribute or throws IllegalArgumentException if not present */
public int requiredIntegerAttribute(String name) {
- if (getStringAttribute(name) == null)
+ if (stringAttribute(name) == null)
throw new IllegalArgumentException("Required attribute '" + name + "' is missing");
- return getIntegerAttribute(name, null);
+ return integerAttribute(name, null);
}
/** Returns the value of this attribute or null if not present */
- public Integer getIntegerAttribute(String name) {
- return getIntegerAttribute(name, null);
+ public Integer integerAttribute(String name) {
+ return integerAttribute(name, null);
}
- public Integer getIntegerAttribute(String name, Integer defaultValue) {
- String value = getStringAttribute(name);
- if (value == null) {
- return defaultValue;
- }
+ public Integer integerAttribute(String name, Integer defaultValue) {
+ String value = stringAttribute(name);
+ if (value == null) return defaultValue;
return (int) BinaryUnit.valueOf(value);
}
- public boolean getBooleanAttribute(String name) {
- return getBooleanAttribute(name, false);
+ public boolean booleanAttribute(String name) {
+ return booleanAttribute(name, false);
}
- public boolean getBooleanAttribute(String name, boolean defaultValue) {
- String value = getStringAttribute(name);
- if (value == null) {
- return defaultValue;
- }
+ public boolean booleanAttribute(String name, boolean defaultValue) {
+ String value = stringAttribute(name);
+ if (value == null) return defaultValue;
return Boolean.parseBoolean(value);
}
- public Long getLongAttribute(String name) {
- String value = getStringAttribute(name);
- if (value == null) {
- return null;
- }
+ public Long longAttribute(String name) {
+ String value = stringAttribute(name);
+ if (value == null) return null;
return (long) BinaryUnit.valueOf(value);
}
- public Double getDoubleAttribute(String name) {
- String value = getStringAttribute(name);
- if (value == null) {
- return null;
- }
+ public Double doubleAttribute(String name) {
+ String value = stringAttribute(name);
+ if (value == null) return null;
return Double.parseDouble(value);
}
- public String getStringAttribute(String name) {
- if (!xml.hasAttribute(name)) {
- return null;
- }
+ /** Returns the given attribute or throws IllegalArgumentException if not present */
+ public double requiredDoubleAttribute(String name) {
+ if (stringAttribute(name) == null)
+ throw new IllegalArgumentException("Required attribute '" + name + "' is missing");
+ return doubleAttribute(name);
+ }
+ /** Returns the content of the attribute with the given name, or null if none */
+ public String stringAttribute(String name) {
+ if ( ! xml.hasAttribute(name)) return null;
return xml.getAttribute(name);
}
@@ -209,10 +180,8 @@ public class ModelElement {
List<Element> elements = XML.getChildren(xml, name);
List<ModelElement> helpers = new ArrayList<>();
- for (Element e : elements) {
+ for (Element e : elements)
helpers.add(new ModelElement(e));
- }
-
return helpers;
}
@@ -220,4 +189,5 @@ public class ModelElement {
public String toString() {
return xml.getNodeName();
}
+
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java
index 84fdbf0a75c..1031ae7b787 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java
@@ -7,6 +7,7 @@ import com.yahoo.config.model.ConfigModelContext;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.RotationName;
import com.yahoo.vespa.model.HostResource;
import com.yahoo.vespa.model.HostSystem;
@@ -44,14 +45,14 @@ public class NodesSpecification {
private final boolean exclusive;
/** The flavor the nodes should have, or empty to use the default */
- private final Optional<String> flavor;
+ private final Optional<FlavorSpec> flavor;
/** The identifier of the custom docker image layer to use (not supported yet) */
private final Optional<String> dockerImage;
private NodesSpecification(boolean dedicated, int count, int groups, Version version,
boolean required, boolean canFail, boolean exclusive,
- Optional<String> flavor, Optional<String> dockerImage) {
+ Optional<FlavorSpec> flavor, Optional<String> dockerImage) {
this.dedicated = dedicated;
this.count = count;
this.groups = groups;
@@ -66,18 +67,16 @@ public class NodesSpecification {
private NodesSpecification(boolean dedicated, boolean canFail, Version version, ModelElement nodesElement) {
this(dedicated,
nodesElement.requiredIntegerAttribute("count"),
- nodesElement.getIntegerAttribute("groups", 1),
+ nodesElement.integerAttribute("groups", 1),
version,
- nodesElement.getBooleanAttribute("required", false),
+ nodesElement.booleanAttribute("required", false),
canFail,
- nodesElement.getBooleanAttribute("exclusive", false),
- Optional.ofNullable(nodesElement.getStringAttribute("flavor")),
- Optional.ofNullable(nodesElement.getStringAttribute("docker-image")));
+ nodesElement.booleanAttribute("exclusive", false),
+ getFlavor(nodesElement),
+ Optional.ofNullable(nodesElement.stringAttribute("docker-image")));
}
- /**
- * Returns a requirement for dedicated nodes taken from the given <code>nodes</code> element
- */
+ /** Returns a requirement for dedicated nodes taken from the given <code>nodes</code> element */
public static NodesSpecification from(ModelElement nodesElement, ConfigModelContext context) {
return new NodesSpecification(true,
! context.getDeployState().getProperties().isBootstrap(),
@@ -92,7 +91,7 @@ public class NodesSpecification {
*/
public static Optional<NodesSpecification> fromParent(ModelElement parentElement, ConfigModelContext context) {
if (parentElement == null) return Optional.empty();
- ModelElement nodesElement = parentElement.getChild("nodes");
+ ModelElement nodesElement = parentElement.child("nodes");
if (nodesElement == null) return Optional.empty();
return Optional.of(from(nodesElement, context));
}
@@ -105,9 +104,9 @@ public class NodesSpecification {
public static Optional<NodesSpecification> optionalDedicatedFromParent(ModelElement parentElement,
ConfigModelContext context) {
if (parentElement == null) return Optional.empty();
- ModelElement nodesElement = parentElement.getChild("nodes");
+ ModelElement nodesElement = parentElement.child("nodes");
if (nodesElement == null) return Optional.empty();
- return Optional.of(new NodesSpecification(nodesElement.getBooleanAttribute("dedicated", false),
+ return Optional.of(new NodesSpecification(nodesElement.booleanAttribute("dedicated", false),
! context.getDeployState().getProperties().isBootstrap(),
context.getDeployState().getWantedNodeVespaVersion(),
nodesElement));
@@ -171,7 +170,22 @@ public class NodesSpecification {
DeployLogger logger,
Set<RotationName> rotations) {
ClusterSpec cluster = ClusterSpec.request(clusterType, clusterId, version, exclusive, rotations);
- return hostSystem.allocateHosts(cluster, Capacity.fromNodeCount(count, flavor, required, canFail), groups, logger);
+ return hostSystem.allocateHosts(cluster, Capacity.fromCount(count, flavor, required, canFail), groups, logger);
+ }
+
+ private static Optional<FlavorSpec> getFlavor(ModelElement nodesElement) {
+ ModelElement flavor = nodesElement.child("flavor");
+ if (flavor != null) {
+ return Optional.of(new FlavorSpec(flavor.requiredDoubleAttribute("cpus"),
+ flavor.requiredDoubleAttribute("memory"),
+ flavor.requiredDoubleAttribute("disk")));
+ }
+ else if (nodesElement.stringAttribute("flavor") != null) { // legacy fallback
+ return Optional.of(FlavorSpec.fromLegacyFlavorName(nodesElement.stringAttribute("flavor")));
+ }
+ else { // Get the default
+ return Optional.empty();
+ }
}
@Override
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/BucketSplitting.java b/config-model/src/main/java/com/yahoo/vespa/model/content/BucketSplitting.java
index 9f7494f470d..cb588f20f0e 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/BucketSplitting.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/BucketSplitting.java
@@ -3,7 +3,6 @@ package com.yahoo.vespa.model.content;
import com.yahoo.vespa.config.content.core.StorDistributormanagerConfig;
import com.yahoo.vespa.model.builder.xml.dom.ModelElement;
-import com.yahoo.vespa.model.content.cluster.ContentCluster;
/**
* Represents configuration for bucket splitting.
@@ -15,16 +14,16 @@ public class BucketSplitting implements StorDistributormanagerConfig.Producer {
public static class Builder {
public BucketSplitting build(ModelElement clusterElem) {
- ModelElement tuning = clusterElem.getChild("tuning");
+ ModelElement tuning = clusterElem.child("tuning");
if (tuning == null) {
return new BucketSplitting(null, null, null);
}
- ModelElement bucketSplitting = tuning.getChild("bucket-splitting");
+ ModelElement bucketSplitting = tuning.child("bucket-splitting");
if (bucketSplitting != null) {
- Integer maxDocuments = bucketSplitting.getIntegerAttribute("max-documents");
- Integer splitSize = bucketSplitting.getIntegerAttribute("max-size");
- Integer minSplitCount = bucketSplitting.getIntegerAttribute("minimum-bits");
+ Integer maxDocuments = bucketSplitting.integerAttribute("max-documents");
+ Integer splitSize = bucketSplitting.integerAttribute("max-size");
+ Integer minSplitCount = bucketSplitting.integerAttribute("minimum-bits");
return new BucketSplitting(maxDocuments, splitSize, minSplitCount);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterControllerConfig.java b/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterControllerConfig.java
index 176ba31857b..1b0af3e9046 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterControllerConfig.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterControllerConfig.java
@@ -31,11 +31,11 @@ public class ClusterControllerConfig extends AbstractConfigProducer implements F
protected ClusterControllerConfig doBuild(DeployState deployState, AbstractConfigProducer ancestor, Element producerSpec) {
ModelElement tuning = null;
- ModelElement clusterTuning = clusterElement.getChild("tuning");
+ ModelElement clusterTuning = clusterElement.child("tuning");
Integer bucketSplittingMinimumBits = null;
Double minNodeRatioPerGroup = null;
if (clusterTuning != null) {
- tuning = clusterTuning.getChild("cluster-controller");
+ tuning = clusterTuning.child("cluster-controller");
minNodeRatioPerGroup = clusterTuning.childAsDouble("min-node-ratio-per-group");
bucketSplittingMinimumBits = clusterTuning.childAsInteger("bucket-splitting.minimum-bits");
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
index 219c8a01afe..db7b4a88721 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
@@ -86,11 +86,11 @@ public class ContentSearchCluster extends AbstractConfigProducer implements Prot
ContentSearchCluster search = new ContentSearchCluster(ancestor, clusterName, documentDefinitions, globallyDistributedDocuments,
getFlushOnShutdown(flushOnShutdownElem, deployState));
- ModelElement tuning = clusterElem.getChildByPath("engine.proton.tuning");
+ ModelElement tuning = clusterElem.childByPath("engine.proton.tuning");
if (tuning != null) {
search.setTuning(new DomSearchTuningBuilder().build(deployState, search, tuning.getXml()));
}
- ModelElement protonElem = clusterElem.getChildByPath("engine.proton");
+ ModelElement protonElem = clusterElem.childByPath("engine.proton");
if (protonElem != null) {
search.setResourceLimits(DomResourceLimitsBuilder.build(protonElem));
}
@@ -112,14 +112,14 @@ public class ContentSearchCluster extends AbstractConfigProducer implements Prot
}
private void buildAllStreamingSearchClusters(DeployState deployState, ModelElement clusterElem, String clusterName, ContentSearchCluster search) {
- ModelElement docElem = clusterElem.getChild("documents");
+ ModelElement docElem = clusterElem.child("documents");
if (docElem == null) {
return;
}
for (ModelElement docType : docElem.subElements("document")) {
- String mode = docType.getStringAttribute("mode");
+ String mode = docType.stringAttribute("mode");
if ("streaming".equals(mode)) {
buildStreamingSearchCluster(deployState, clusterElem, clusterName, search, docType);
}
@@ -128,7 +128,7 @@ public class ContentSearchCluster extends AbstractConfigProducer implements Prot
private void buildStreamingSearchCluster(DeployState deployState, ModelElement clusterElem, String clusterName,
ContentSearchCluster search, ModelElement docType) {
- String docTypeName = docType.getStringAttribute("type");
+ String docTypeName = docType.stringAttribute("type");
StreamingSearchCluster cluster = new StreamingSearchCluster(search, clusterName + "." + docTypeName, 0, docTypeName, clusterName);
search.addSearchCluster(deployState, cluster, getQueryTimeout(clusterElem), Arrays.asList(docType));
}
@@ -151,13 +151,13 @@ public class ContentSearchCluster extends AbstractConfigProducer implements Prot
private List<ModelElement> getIndexedSearchDefinitions(ModelElement clusterElem) {
List<ModelElement> indexedDefs = new ArrayList<>();
- ModelElement docElem = clusterElem.getChild("documents");
+ ModelElement docElem = clusterElem.child("documents");
if (docElem == null) {
return indexedDefs;
}
for (ModelElement docType : docElem.subElements("document")) {
- String mode = docType.getStringAttribute("mode");
+ String mode = docType.stringAttribute("mode");
if ("index".equals(mode)) {
indexedDefs.add(docType);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/Distributor.java b/config-model/src/main/java/com/yahoo/vespa/model/content/Distributor.java
index ddc816d2c17..c55548cfd2b 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/Distributor.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/Distributor.java
@@ -27,8 +27,8 @@ public class Distributor extends ContentNode {
@Override
protected Distributor doBuild(DeployState deployState, AbstractConfigProducer ancestor, Element producerSpec) {
- return new Distributor((DistributorCluster)ancestor, new ModelElement(producerSpec).getIntegerAttribute("distribution-key"),
- clusterXml.getIntegerAttribute("distributor-base-port"), persistenceProvider);
+ return new Distributor((DistributorCluster)ancestor, new ModelElement(producerSpec).integerAttribute("distribution-key"),
+ clusterXml.integerAttribute("distributor-base-port"), persistenceProvider);
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/DistributorCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/DistributorCluster.java
index ad067d6faed..cd790a67742 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/DistributorCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/DistributorCluster.java
@@ -52,7 +52,7 @@ public class DistributorCluster extends AbstractConfigProducer<Distributor> impl
DocumentSelector s = new DocumentSelector(selStr);
boolean enableGC = false;
if (documentNode != null) {
- enableGC = documentNode.getBooleanAttribute("garbage-collection", false);
+ enableGC = documentNode.booleanAttribute("garbage-collection", false);
}
if (!enableGC) {
return null;
@@ -64,7 +64,7 @@ public class DistributorCluster extends AbstractConfigProducer<Distributor> impl
private int getGCInterval(ModelElement documentNode) {
int gcInterval = 3600;
if (documentNode != null) {
- gcInterval = documentNode.getIntegerAttribute("garbage-collection-interval", gcInterval);
+ gcInterval = documentNode.integerAttribute("garbage-collection-interval", gcInterval);
}
return gcInterval;
}
@@ -90,13 +90,13 @@ public class DistributorCluster extends AbstractConfigProducer<Distributor> impl
private boolean clusterContainsIndexedDocumentType(ModelElement documentsNode) {
return documentsNode != null
&& documentsNode.subElements("document").stream()
- .anyMatch(node -> documentModeImpliesIndexing(node.getStringAttribute("mode")));
+ .anyMatch(node -> documentModeImpliesIndexing(node.stringAttribute("mode")));
}
@Override
protected DistributorCluster doBuild(DeployState deployState, AbstractConfigProducer ancestor, Element producerSpec) {
final ModelElement clusterElement = new ModelElement(producerSpec);
- final ModelElement documentsNode = clusterElement.getChild("documents");
+ final ModelElement documentsNode = clusterElement.child("documents");
final GcOptions gc = parseGcOptions(documentsNode);
final boolean hasIndexedDocumentType = clusterContainsIndexedDocumentType(documentsNode);
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java
index 17ff15d3a77..84132427427 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java
@@ -204,12 +204,12 @@ public class StorageGroup {
}
public StorageGroup buildRootGroup(DeployState deployState) {
- Optional<ModelElement> group = Optional.ofNullable(clusterElement.getChild("group"));
+ Optional<ModelElement> group = Optional.ofNullable(clusterElement.child("group"));
Optional<ModelElement> nodes = getNodes(clusterElement);
if (group.isPresent() && nodes.isPresent())
throw new IllegalStateException("Both group and nodes exists, only one of these tags is legal");
- if (group.isPresent() && (group.get().getStringAttribute("name") != null || group.get().getIntegerAttribute("distribution-key") != null))
+ if (group.isPresent() && (group.get().stringAttribute("name") != null || group.get().integerAttribute("distribution-key") != null))
deployState.getDeployLogger().log(LogLevel.INFO, "'distribution-key' attribute on a content cluster's root group is ignored");
GroupBuilder groupBuilder = collectGroup(group, nodes, null, null);
@@ -409,7 +409,7 @@ public class StorageGroup {
throw new IllegalArgumentException("A group can contain either explicit subgroups or a nodes specification, but not both.");
Optional<NodesSpecification> nodeRequirement;
- if (nodesElement.isPresent() && nodesElement.get().getStringAttribute("count") != null ) // request these nodes
+ if (nodesElement.isPresent() && nodesElement.get().stringAttribute("count") != null ) // request these nodes
nodeRequirement = Optional.of(NodesSpecification.from(nodesElement.get(), context));
else if (! nodesElement.isPresent() && subGroups.isEmpty() && context.getDeployState().isHosted()) // request one node
nodeRequirement = Optional.of(NodesSpecification.nonDedicated(1, context));
@@ -434,12 +434,12 @@ public class StorageGroup {
private boolean booleanAttributeOr(Optional<ModelElement> element, String attributeName, boolean defaultValue) {
if ( ! element.isPresent()) return defaultValue;
- return element.get().getBooleanAttribute(attributeName, defaultValue);
+ return element.get().booleanAttribute(attributeName, defaultValue);
}
private Optional<ModelElement> getNodes(ModelElement groupOrNodesElement) {
if (groupOrNodesElement.getXml().getTagName().equals("nodes")) return Optional.of(groupOrNodesElement);
- return Optional.ofNullable(groupOrNodesElement.getChild("nodes"));
+ return Optional.ofNullable(groupOrNodesElement.child("nodes"));
}
private List<XmlNodeBuilder> collectExplicitNodes(Optional<ModelElement> groupOrNodesElement) {
@@ -461,8 +461,8 @@ public class StorageGroup {
indexPrefix = parentGroup.index + ".";
}
for (ModelElement g : subGroupElements) {
- subGroups.add(collectGroup(Optional.of(g), Optional.ofNullable(g.getChild("nodes")), g.getStringAttribute("name"),
- indexPrefix + g.getIntegerAttribute("distribution-key")));
+ subGroups.add(collectGroup(Optional.of(g), Optional.ofNullable(g.child("nodes")), g.stringAttribute("name"),
+ indexPrefix + g.integerAttribute("distribution-key")));
}
return subGroups;
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageNode.java b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageNode.java
index 9ea92048f3b..c8220071373 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageNode.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageNode.java
@@ -32,7 +32,7 @@ public class StorageNode extends ContentNode implements StorServerConfig.Produce
@Override
protected StorageNode doBuild(DeployState deployState, AbstractConfigProducer ancestor, Element producerSpec) {
ModelElement e = new ModelElement(producerSpec);
- return new StorageNode((StorageCluster)ancestor, e.getDoubleAttribute("capacity"), e.getIntegerAttribute("distribution-key"), false);
+ return new StorageNode((StorageCluster)ancestor, e.doubleAttribute("capacity"), e.integerAttribute("distribution-key"), false);
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
index 79675febe2f..833afb67f58 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
@@ -119,7 +119,7 @@ public class ContentCluster extends AbstractConfigProducer implements
ModelElement contentElement = new ModelElement(w3cContentElement);
DeployState deployState = context.getDeployState();
- ModelElement documentsElement = contentElement.getChild("documents");
+ ModelElement documentsElement = contentElement.child("documents");
Map<String, NewDocumentType> documentDefinitions =
new SearchDefinitionBuilder().build(deployState.getDocumentModel().getDocumentManager(), documentsElement);
@@ -150,7 +150,7 @@ public class ContentCluster extends AbstractConfigProducer implements
}
if (documentsElement != null) {
- ModelElement e = documentsElement.getChild("document-processing");
+ ModelElement e = documentsElement.child("document-processing");
if (e != null) {
setupDocumentProcessing(c, e);
}
@@ -158,11 +158,11 @@ public class ContentCluster extends AbstractConfigProducer implements
throw new IllegalArgumentException("The specified content engine requires the <documents> element to be specified.");
}
- ModelElement tuning = contentElement.getChild("tuning");
+ ModelElement tuning = contentElement.child("tuning");
if (tuning != null) {
setupTuning(c, tuning);
}
- ModelElement experimental = contentElement.getChild("experimental");
+ ModelElement experimental = contentElement.child("experimental");
if (experimental != null) {
setupExperimental(c, experimental);
}
@@ -217,7 +217,7 @@ public class ContentCluster extends AbstractConfigProducer implements
}
private void setupDocumentProcessing(ContentCluster c, ModelElement e) {
- String docprocCluster = e.getStringAttribute("cluster");
+ String docprocCluster = e.stringAttribute("cluster");
if (docprocCluster != null) {
docprocCluster = docprocCluster.trim();
}
@@ -227,7 +227,7 @@ public class ContentCluster extends AbstractConfigProducer implements
}
}
- String docprocChain = e.getStringAttribute("chain");
+ String docprocChain = e.stringAttribute("chain");
if (docprocChain != null) {
docprocChain = docprocChain.trim();
}
@@ -239,9 +239,9 @@ public class ContentCluster extends AbstractConfigProducer implements
}
private void setupTuning(ContentCluster c, ModelElement tuning) {
- ModelElement distribution = tuning.getChild("distribution");
+ ModelElement distribution = tuning.child("distribution");
if (distribution != null) {
- String attr = distribution.getStringAttribute("type");
+ String attr = distribution.stringAttribute("type");
if (attr != null) {
if (attr.toLowerCase().equals("strict")) {
c.distributionMode = DistributionMode.STRICT;
@@ -254,9 +254,9 @@ public class ContentCluster extends AbstractConfigProducer implements
}
}
}
- ModelElement merges = tuning.getChild("merges");
+ ModelElement merges = tuning.child("merges");
if (merges != null) {
- Integer attr = merges.getIntegerAttribute("max-nodes-per-merge");
+ Integer attr = merges.integerAttribute("max-nodes-per-merge");
if (attr != null) {
c.maxNodesPerMerge = attr;
}
@@ -307,7 +307,7 @@ public class ContentCluster extends AbstractConfigProducer implements
else if (admin.multitenant()) {
String clusterName = contentClusterName + "-controllers";
NodesSpecification nodesSpecification =
- NodesSpecification.optionalDedicatedFromParent(contentElement.getChild("controllers"), context)
+ NodesSpecification.optionalDedicatedFromParent(contentElement.child("controllers"), context)
.orElse(NodesSpecification.nonDedicated(3, context));
Collection<HostResource> hosts = nodesSpecification.isDedicated() ?
getControllerHosts(nodesSpecification, admin, clusterName, context) :
@@ -520,7 +520,7 @@ public class ContentCluster extends AbstractConfigProducer implements
}
public static String getClusterName(ModelElement clusterElem) {
- String clusterName = clusterElem.getStringAttribute("id");
+ String clusterName = clusterElem.stringAttribute("id");
if (clusterName == null) {
clusterName = "content";
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DocumentSelectionBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DocumentSelectionBuilder.java
index c6008ef4084..07b87a41b2f 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DocumentSelectionBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DocumentSelectionBuilder.java
@@ -54,9 +54,9 @@ public class DocumentSelectionBuilder {
sb.append(" OR ");
}
sb.append('(');
- String type = e.getStringAttribute("type");
+ String type = e.stringAttribute("type");
sb.append(type);
- String selection = e.getStringAttribute("selection");
+ String selection = e.stringAttribute("selection");
if (selection != null) {
validateSelectionExpression(selection, type);
sb.append(" AND (");
@@ -66,7 +66,7 @@ public class DocumentSelectionBuilder {
sb.append(')');
}
- String globalSelection = elem.getStringAttribute("selection");
+ String globalSelection = elem.stringAttribute("selection");
if (globalSelection != null) {
validateSelectionExpression(globalSelection, null);
StringBuilder global = new StringBuilder();
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomContentSearchBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomContentSearchBuilder.java
index 9ef64e0b288..40bfa3241e2 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomContentSearchBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomContentSearchBuilder.java
@@ -11,7 +11,7 @@ public class DomContentSearchBuilder {
public static ContentSearch build(ModelElement contentXml) {
ContentSearch.Builder builder = new ContentSearch.Builder();
- ModelElement searchElement = contentXml.getChild("search");
+ ModelElement searchElement = contentXml.child("search");
if (searchElement == null) {
return builder.build();
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomDispatchBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomDispatchBuilder.java
index 3d06d120b09..ffe07a00775 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomDispatchBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomDispatchBuilder.java
@@ -17,7 +17,7 @@ public class DomDispatchBuilder {
public static DispatchSpec build(ModelElement contentXml) {
DispatchSpec.Builder builder = new DispatchSpec.Builder();
- ModelElement dispatchElement = contentXml.getChild("dispatch");
+ ModelElement dispatchElement = contentXml.child("dispatch");
if (dispatchElement == null) {
return builder.build();
}
@@ -48,6 +48,6 @@ public class DomDispatchBuilder {
}
private static DispatchSpec.Node buildNode(ModelElement nodeElement) {
- return new DispatchSpec.Node(nodeElement.getIntegerAttribute("distribution-key"));
+ return new DispatchSpec.Node(nodeElement.integerAttribute("distribution-key"));
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomResourceLimitsBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomResourceLimitsBuilder.java
index 87412ad3596..61bf42af379 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomResourceLimitsBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomResourceLimitsBuilder.java
@@ -13,14 +13,14 @@ public class DomResourceLimitsBuilder {
public static ResourceLimits build(ModelElement contentXml) {
ResourceLimits.Builder builder = new ResourceLimits.Builder();
- ModelElement resourceLimits = contentXml.getChild("resource-limits");
+ ModelElement resourceLimits = contentXml.child("resource-limits");
if (resourceLimits == null) {
return builder.build();
}
- if (resourceLimits.getChild("disk") != null) {
+ if (resourceLimits.child("disk") != null) {
builder.setDiskLimit(resourceLimits.childAsDouble("disk"));
}
- if (resourceLimits.getChild("memory") != null) {
+ if (resourceLimits.child("memory") != null) {
builder.setMemoryLimit(resourceLimits.childAsDouble("memory"));
}
return builder.build();
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomSearchCoverageBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomSearchCoverageBuilder.java
index cfc110d7a13..64953deb36e 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomSearchCoverageBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomSearchCoverageBuilder.java
@@ -11,11 +11,11 @@ public class DomSearchCoverageBuilder {
public static SearchCoverage build(ModelElement contentXml) {
SearchCoverage.Builder builder = new SearchCoverage.Builder();
- ModelElement searchElement = contentXml.getChild("search");
+ ModelElement searchElement = contentXml.child("search");
if (searchElement == null) {
return builder.build();
}
- ModelElement coverageElement = searchElement.getChild("coverage");
+ ModelElement coverageElement = searchElement.child("coverage");
if (coverageElement == null) {
return builder.build();
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomTuningDispatchBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomTuningDispatchBuilder.java
index f470e75abf0..5f26b0628c2 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomTuningDispatchBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/DomTuningDispatchBuilder.java
@@ -11,11 +11,11 @@ public class DomTuningDispatchBuilder {
public static TuningDispatch build(ModelElement contentXml) {
TuningDispatch.Builder builder = new TuningDispatch.Builder();
- ModelElement tuningElement = contentXml.getChild("tuning");
+ ModelElement tuningElement = contentXml.child("tuning");
if (tuningElement == null) {
return builder.build();
}
- ModelElement dispatchElement = tuningElement.getChild("dispatch");
+ ModelElement dispatchElement = tuningElement.child("dispatch");
if (dispatchElement == null) {
return builder.build();
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/EngineFactoryBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/EngineFactoryBuilder.java
index 83e9553ebd5..e31e9703f11 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/EngineFactoryBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/EngineFactoryBuilder.java
@@ -9,15 +9,15 @@ import com.yahoo.vespa.model.content.engines.*;
*/
public class EngineFactoryBuilder {
public PersistenceEngine.PersistenceFactory build(ModelElement clusterElem, ContentCluster c) {
- ModelElement persistence = clusterElem.getChild("engine");
+ ModelElement persistence = clusterElem.child("engine");
if (persistence != null) {
- if (c.getSearch().hasIndexedCluster() && persistence.getChild("proton") == null) {
+ if (c.getSearch().hasIndexedCluster() && persistence.child("proton") == null) {
throw new IllegalArgumentException("Persistence engine does not allow for indexed search. Please use <proton> as your engine.");
}
- if (persistence.getChild("proton") != null) {
+ if (persistence.child("proton") != null) {
return new ProtonEngine.Factory(c.getSearch());
- } else if (persistence.getChild("dummy") != null) {
+ } else if (persistence.child("dummy") != null) {
return new com.yahoo.vespa.model.content.engines.DummyPersistence.Factory();
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/GlobalDistributionBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/GlobalDistributionBuilder.java
index bdc15074258..1adb5d6d2d5 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/GlobalDistributionBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/GlobalDistributionBuilder.java
@@ -36,11 +36,11 @@ public class GlobalDistributionBuilder {
}
private static boolean isGloballyDistributed(ModelElement e) {
- return e.getBooleanAttribute("global", false);
+ return e.booleanAttribute("global", false);
}
private static String getDocumentName(ModelElement e) {
- return e.getStringAttribute("type");
+ return e.stringAttribute("type");
}
private NewDocumentType getDocumentType(String name) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java
index e1675007bbc..fe73fcc904b 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java
@@ -14,9 +14,9 @@ public class RedundancyBuilder {
Integer finalRedundancy = 3;
Integer readyCopies = 2;
- ModelElement redundancyElement = clusterXml.getChild("redundancy");
+ ModelElement redundancyElement = clusterXml.child("redundancy");
if (redundancyElement != null) {
- initialRedundancy = redundancyElement.getIntegerAttribute("reply-after");
+ initialRedundancy = redundancyElement.integerAttribute("reply-after");
finalRedundancy = (int)redundancyElement.asLong();
if (initialRedundancy == null) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/SearchDefinitionBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/SearchDefinitionBuilder.java
index 53220268bf8..44cb9cb96dd 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/SearchDefinitionBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/SearchDefinitionBuilder.java
@@ -21,7 +21,7 @@ public class SearchDefinitionBuilder {
if (elem != null) {
for (ModelElement e : elem.subElements("document")) {
- String name = e.getStringAttribute("type"); // Schema-guaranteed presence
+ String name = e.stringAttribute("type"); // Schema-guaranteed presence
NewDocumentType documentType = repo.getDocumentType(name);
if (documentType != null) {
docTypes.put(documentType.getName(), documentType);
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/FileStorProducer.java b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/FileStorProducer.java
index 0cc62fb6680..785088e96fc 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/FileStorProducer.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/FileStorProducer.java
@@ -16,16 +16,16 @@ public class FileStorProducer implements StorFilestorConfig.Producer {
}
private Integer getThreads(ModelElement clusterElem) {
- ModelElement tuning = clusterElem.getChild("tuning");
+ ModelElement tuning = clusterElem.child("tuning");
if (tuning == null) {
return null;
}
- ModelElement threads = tuning.getChild("persistence-threads");
+ ModelElement threads = tuning.child("persistence-threads");
if (threads == null) {
return null;
}
- Integer count = threads.getIntegerAttribute("count");
+ Integer count = threads.integerAttribute("count");
if (count != null) {
return count;
}
@@ -33,7 +33,7 @@ public class FileStorProducer implements StorFilestorConfig.Producer {
// Backward compatible fallback
int numThreads = 0;
for (ModelElement thread : threads.subElements("thread")) {
- count = thread.getIntegerAttribute("count");
+ count = thread.integerAttribute("count");
numThreads += (count == null) ? 1 : count;
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/PersistenceProducer.java b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/PersistenceProducer.java
index dabfbd4f75d..749cf8f374e 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/PersistenceProducer.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/PersistenceProducer.java
@@ -12,7 +12,7 @@ public class PersistenceProducer implements PersistenceConfig.Producer {
public static class Builder {
public PersistenceProducer build(ModelElement element) {
- ModelElement persistence = element.getChild("engine");
+ ModelElement persistence = element.child("engine");
if (persistence == null) {
return new PersistenceProducer();
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorServerProducer.java b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorServerProducer.java
index baebbcd3f65..51fc610bf28 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorServerProducer.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorServerProducer.java
@@ -11,20 +11,20 @@ import com.yahoo.vespa.model.builder.xml.dom.ModelElement;
public class StorServerProducer implements StorServerConfig.Producer {
public static class Builder {
StorServerProducer build(ModelElement element) {
- ModelElement tuning = element.getChild("tuning");
+ ModelElement tuning = element.child("tuning");
if (tuning == null) {
return new StorServerProducer(ContentCluster.getClusterName(element), null, null);
}
- ModelElement merges = tuning.getChild("merges");
+ ModelElement merges = tuning.child("merges");
if (merges == null) {
return new StorServerProducer(ContentCluster.getClusterName(element), null, null);
}
return new StorServerProducer(ContentCluster.getClusterName(element),
- merges.getIntegerAttribute("max-per-node"),
- merges.getIntegerAttribute("max-queue-size"));
+ merges.integerAttribute("max-per-node"),
+ merges.integerAttribute("max-queue-size"));
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorVisitorProducer.java b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorVisitorProducer.java
index a831d3866d0..ec93881aae7 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorVisitorProducer.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/storagecluster/StorVisitorProducer.java
@@ -10,18 +10,18 @@ import com.yahoo.vespa.model.builder.xml.dom.ModelElement;
public class StorVisitorProducer implements StorVisitorConfig.Producer {
public static class Builder {
public StorVisitorProducer build(ModelElement element) {
- ModelElement tuning = element.getChild("tuning");
+ ModelElement tuning = element.child("tuning");
if (tuning == null) {
return new StorVisitorProducer();
}
- ModelElement visitors = tuning.getChild("visitors");
+ ModelElement visitors = tuning.child("visitors");
if (visitors == null) {
return new StorVisitorProducer();
}
- return new StorVisitorProducer(visitors.getIntegerAttribute("thread-count"),
- visitors.getIntegerAttribute("max-queue-size"),
+ return new StorVisitorProducer(visitors.integerAttribute("thread-count"),
+ visitors.integerAttribute("max-queue-size"),
visitors.childAsInteger("max-concurrent.fixed"),
visitors.childAsInteger("max-concurrent.variable"));
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/search/SearchDefinitionXMLHandler.java b/config-model/src/main/java/com/yahoo/vespa/model/search/SearchDefinitionXMLHandler.java
index 11758284a31..1054253e3f0 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/search/SearchDefinitionXMLHandler.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/search/SearchDefinitionXMLHandler.java
@@ -2,7 +2,6 @@
package com.yahoo.vespa.model.search;
import com.yahoo.vespa.model.builder.xml.dom.ModelElement;
-import org.w3c.dom.Element;
import java.io.Serializable;
import java.util.List;
@@ -17,9 +16,9 @@ public class SearchDefinitionXMLHandler implements Serializable {
private String sdName;
public SearchDefinitionXMLHandler(ModelElement elem) {
- sdName = elem.getStringAttribute("name");
+ sdName = elem.stringAttribute("name");
if (sdName == null) {
- sdName = elem.getStringAttribute("type");
+ sdName = elem.stringAttribute("type");
}
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java
index 6df617ea335..f635b986558 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java
@@ -17,11 +17,11 @@ public final class Capacity {
private final boolean canFail;
- private final Optional<String> flavor;
+ private final Optional<FlavorSpec> flavor;
private final NodeType type;
- private Capacity(int nodeCount, Optional<String> flavor, boolean required, boolean canFail, NodeType type) {
+ private Capacity(int nodeCount, Optional<FlavorSpec> flavor, boolean required, boolean canFail, NodeType type) {
this.nodeCount = nodeCount;
this.required = required;
this.canFail = canFail;
@@ -36,7 +36,10 @@ public final class Capacity {
* The node flavor requested, or empty if no particular flavor is specified.
* This may be satisfied by the requested flavor or a suitable replacement
*/
- public Optional<String> flavor() { return flavor; }
+ public Optional<String> flavor() { return flavor.map(FlavorSpec::legacyFlavorName); }
+
+ /** Returns the capacity specified for each node, or empty to leave this decision to provisioning */
+ public Optional<FlavorSpec> flavorSpec() { return flavor; }
/** Returns whether the requested number of nodes must be met exactly for a request for this to succeed */
public boolean isRequired() { return required; }
@@ -65,10 +68,18 @@ public final class Capacity {
return fromNodeCount(capacity, Optional.empty(), false, true);
}
- public static Capacity fromNodeCount(int nodeCount, Optional<String> flavor, boolean required, boolean canFail) {
+ public static Capacity fromCount(int nodeCount, FlavorSpec flavor, boolean required, boolean canFail) {
+ return new Capacity(nodeCount, Optional.of(flavor), required, canFail, NodeType.tenant);
+ }
+
+ public static Capacity fromCount(int nodeCount, Optional<FlavorSpec> flavor, boolean required, boolean canFail) {
return new Capacity(nodeCount, flavor, required, canFail, NodeType.tenant);
}
+ public static Capacity fromNodeCount(int nodeCount, Optional<String> flavor, boolean required, boolean canFail) {
+ return new Capacity(nodeCount, flavor.map(FlavorSpec::fromLegacyFlavorName), required, canFail, NodeType.tenant);
+ }
+
/** Creates this from a node type */
public static Capacity fromRequiredNodeType(NodeType type) {
return new Capacity(0, Optional.empty(), true, false, type);
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
index 79a17c23dd7..8b6fa863af6 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
@@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableList;
import com.yahoo.config.provisioning.FlavorsConfig;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -31,6 +32,7 @@ public class Flavor {
/**
* Creates a Flavor, but does not set the replacesFlavors.
+ *
* @param flavorConfig config to be used for Flavor.
*/
public Flavor(FlavorsConfig.Flavor flavorConfig) {
@@ -49,6 +51,25 @@ public class Flavor {
this.idealHeadroom = flavorConfig.idealHeadroom();
}
+ /** Create a Flavor from a Flavor spec and all other fields set to Docker defaults */
+ public Flavor(FlavorSpec spec) {
+ if (spec.allocateByLegacyName())
+ throw new IllegalArgumentException("Can not create flavor '" + spec.legacyFlavorName() + "' from a spec: " +
+ "Non-docker flavors must be of a configured flavor");
+ this.name = spec.legacyFlavorName();
+ this.cost = 0;
+ this.isStock = true;
+ this.type = Type.DOCKER_CONTAINER;
+ this.minCpuCores = spec.cpuCores();
+ this.minMainMemoryAvailableGb = spec.memoryGb();
+ this.minDiskAvailableGb = spec.diskGb();
+ this.fastDisk = true;
+ this.bandwidth = 1;
+ this.description = "";
+ this.retired = false;
+ this.replacesFlavors = Collections.emptyList();
+ }
+
/** Returns the unique identity of this flavor */
public String name() { return name; }
@@ -147,6 +168,13 @@ public class Flavor {
this.fastDisk || ! other.fastDisk;
}
+ public FlavorSpec asSpec() {
+ if (isDocker())
+ return new FlavorSpec(minCpuCores, minMainMemoryAvailableGb, minDiskAvailableGb);
+ else
+ return FlavorSpec.fromLegacyFlavorName(name);
+ }
+
@Override
public int hashCode() { return name.hashCode(); }
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/FlavorSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/FlavorSpec.java
new file mode 100644
index 00000000000..62cfb59c51c
--- /dev/null
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/FlavorSpec.java
@@ -0,0 +1,107 @@
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.provision;
+
+import java.util.Objects;
+
+/**
+ * The node capacity specified by an application, which is matched to an actual flavor during provisioning.
+ *
+ * @author bratseth
+ */
+public class FlavorSpec {
+
+ private final double cpuCores;
+ private final double memoryGb;
+ private final double diskGb;
+
+ private final boolean allocateByLegacyName;
+ private final String legacyFlavorName;
+
+ public FlavorSpec(double cpuCores, double memoryGb, double diskGb) {
+ this.cpuCores = cpuCores;
+ this.memoryGb = memoryGb;
+ this.diskGb = diskGb;
+ this.allocateByLegacyName = false;
+ this.legacyFlavorName = null;
+ }
+
+ private FlavorSpec(double cpuCores, double memoryGb, double diskGb, boolean allocateByLegacyName, String legacyFlavorName) {
+ this.cpuCores = cpuCores;
+ this.memoryGb = memoryGb;
+ this.diskGb = diskGb;
+ this.allocateByLegacyName = allocateByLegacyName;
+ this.legacyFlavorName = legacyFlavorName;
+ }
+
+ public double cpuCores() { return cpuCores; }
+ public double memoryGb() { return memoryGb; }
+ public double diskGb() { return diskGb; }
+
+ /**
+ * If this is true, a non-docker legacy name was used to specify this and we'll respect that by mapping directly.
+ * The other getters of this will return 0.
+ */
+ public boolean allocateByLegacyName() { return allocateByLegacyName; }
+
+ /** Returns the legacy flavor string of this. This is never null. */
+ public String legacyFlavorName() {
+ if (legacyFlavorName != null)
+ return legacyFlavorName;
+ else
+ return "d-" + (int)Math.ceil(cpuCores) + "-" + (int)Math.ceil(memoryGb) + "-" + (int)Math.ceil(diskGb);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if ( ! (o instanceof FlavorSpec)) return false;
+ FlavorSpec other = (FlavorSpec)o;
+ if (allocateByLegacyName) {
+ return this.legacyFlavorName.equals(other.legacyFlavorName);
+ }
+ else {
+ if (this.cpuCores != other.cpuCores) return false;
+ if (this.memoryGb != other.memoryGb) return false;
+ if (this.diskGb != other.diskGb) return false;
+ return true;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ if (allocateByLegacyName)
+ return legacyFlavorName.hashCode();
+ else
+ return (int)(2503 * cpuCores + 22123 * memoryGb + 26987 * diskGb);
+ }
+
+ @Override
+ public String toString() {
+ if (allocateByLegacyName)
+ return "flavor '" + legacyFlavorName + "'";
+ else
+ return "cpu cores: " + cpuCores + ", memory: " + memoryGb + " Gb, disk " + diskGb + " Gb";
+ }
+
+ /**
+ * Create this from a legacy flavor string.
+ *
+ * @throws IllegalArgumentException if the given string does not map to a legacy flavor
+ */
+ public static FlavorSpec fromLegacyFlavorName(String flavorString) {
+ if (flavorString.startsWith("d-")) { // A docker flavor
+ String[] parts = flavorString.split("-");
+ double cpu = Integer.parseInt(parts[1]);
+ double mem = Integer.parseInt(parts[2]);
+ double dsk = Integer.parseInt(parts[3]);
+ if (cpu == 0) cpu = 0.5;
+ if (cpu == 2 && mem == 8 ) cpu = 1.5;
+ if (cpu == 2 && mem == 12 ) cpu = 2.3;
+ return new FlavorSpec(cpu, mem, dsk, false, flavorString);
+ }
+ else {
+ return new FlavorSpec(0, 0, 0, true, flavorString);
+ }
+ }
+
+}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/NodeFlavors.java b/config-provisioning/src/main/java/com/yahoo/config/provision/NodeFlavors.java
index e64028e216f..b87f6eeec31 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/NodeFlavors.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/NodeFlavors.java
@@ -20,34 +20,49 @@ import java.util.stream.Collectors;
*/
public class NodeFlavors {
- /** Flavors <b>which are configured</b> in this zone */
- private final ImmutableMap<String, Flavor> flavors;
+ /** Flavors which are configured in this zone */
+ private final ImmutableMap<String, Flavor> configuredFlavors;
@Inject
public NodeFlavors(FlavorsConfig config) {
ImmutableMap.Builder<String, Flavor> b = new ImmutableMap.Builder<>();
for (Flavor flavor : toFlavors(config))
b.put(flavor.name(), flavor);
- this.flavors = b.build();
+ this.configuredFlavors = b.build();
}
public List<Flavor> getFlavors() {
- return new ArrayList<>(flavors.values());
+ return new ArrayList<>(configuredFlavors.values());
}
- /** Returns a flavor by name, or empty if there is no flavor with this name. */
+ /** Returns a flavor by name, or empty if there is no flavor with this name and it cannot be created on the fly. */
public Optional<Flavor> getFlavor(String name) {
- return Optional.ofNullable(flavors.get(name));
+ if (configuredFlavors.containsKey(name))
+ return Optional.of(configuredFlavors.get(name));
+
+ FlavorSpec flavorSpec = FlavorSpec.fromLegacyFlavorName(name);
+ if (flavorSpec.allocateByLegacyName())
+ return Optional.empty();
+ else
+ return Optional.of(new Flavor(flavorSpec));
}
- /** Returns the flavor with the given name or throws an IllegalArgumentException if it does not exist */
+ /**
+ * Returns the flavor with the given name or throws an IllegalArgumentException if it does not exist
+ * and cannot be created on the fly.
+ */
public Flavor getFlavorOrThrow(String flavorName) {
return getFlavor(flavorName).orElseThrow(() -> new IllegalArgumentException("Unknown flavor '" + flavorName +
- "'. Flavors are " + canonicalFlavorNames()));
+ "'. Flavors are " + canonicalFlavorNames()));
+ }
+
+ /** Returns true if this flavor is configured or can be created on the fly */
+ public boolean exists(String flavorName) {
+ return getFlavor(flavorName).isPresent();
}
private List<String> canonicalFlavorNames() {
- return flavors.values().stream().map(Flavor::canonicalName).distinct().sorted().collect(Collectors.toList());
+ return configuredFlavors.values().stream().map(Flavor::canonicalName).distinct().sorted().collect(Collectors.toList());
}
private static Collection<Flavor> toFlavors(FlavorsConfig config) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
index 5ba56dfa8ed..3831bfc55c1 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NetworkPortsSerializer;
import com.yahoo.config.provision.NodeFlavors;
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
index e437badf0dc..654a73ee3cd 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
@@ -41,19 +42,23 @@ public class CapacityPolicies {
}
}
- public Flavor decideFlavor(Capacity requestedCapacity, ClusterSpec cluster) {
- // for now, always use the requested flavor if a docker flavor is requested
- Optional<String> requestedFlavor = requestedCapacity.flavor();
- if (requestedFlavor.isPresent() &&
- flavors.getFlavorOrThrow(requestedFlavor.get()).getType() == Flavor.Type.DOCKER_CONTAINER)
- return flavors.getFlavorOrThrow(requestedFlavor.get());
+ public FlavorSpec decideFlavor(Capacity requestedCapacity, ClusterSpec cluster) {
+ Optional<FlavorSpec> requestedFlavor = requestedCapacity.flavorSpec();
+ if (requestedFlavor.isPresent() && ! requestedFlavor.get().allocateByLegacyName())
+ return requestedFlavor.get();
- String defaultFlavorName = zone.defaultFlavor(cluster.type());
+ FlavorSpec defaultFlavor = FlavorSpec.fromLegacyFlavorName(zone.defaultFlavor(cluster.type()));
+ if ( requestedFlavor.isEmpty())
+ return defaultFlavor;
+
+ // Flavor is specified and is allocateByLegacyName: Handle legacy flavor specs
if (zone.system() == SystemName.cd)
- return flavors.getFlavorOrThrow(requestedFlavor.orElse(defaultFlavorName));
- switch(zone.environment()) {
- case dev : case test : case staging : return flavors.getFlavorOrThrow(defaultFlavorName);
- default : return flavors.getFlavorOrThrow(requestedFlavor.orElse(defaultFlavorName));
+ return flavors.exists(requestedFlavor.get().legacyFlavorName()) ? requestedFlavor.get() : defaultFlavor;
+ else {
+ switch (zone.environment()) {
+ case dev: case test: case staging: return defaultFlavor;
+ default: return flavors.getFlavorOrThrow(requestedFlavor.get().legacyFlavorName()).asSpec();
+ }
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
index a8b48751d23..5db9eaf3d08 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.OutOfCapacityException;
import com.yahoo.lang.MutableInteger;
import com.yahoo.transaction.Mutex;
@@ -64,7 +65,8 @@ public class GroupPreparer {
// Create a prioritized set of nodes
NodeList nodeList = nodeRepository.list();
NodePrioritizer prioritizer = new NodePrioritizer(
- nodeList, application, cluster, requestedNodes, spareCount, nodeRepository.nameResolver());
+ nodeList, application, cluster, requestedNodes, spareCount, nodeRepository.nameResolver(),
+ nodeRepository.getAvailableFlavors());
prioritizer.addApplicationNodes();
prioritizer.addSurplusNodes(surplusActiveNodes);
@@ -73,14 +75,14 @@ public class GroupPreparer {
// Allocate from the prioritized list
NodeAllocation allocation = new NodeAllocation(nodeList, application, cluster, requestedNodes,
- highestIndex, nodeRepository.zone(), nodeRepository.clock());
+ highestIndex, nodeRepository.getAvailableFlavors(),
+ nodeRepository.zone(), nodeRepository.clock());
allocation.offer(prioritizer.prioritize());
if (dynamicProvisioningEnabled) {
List<ProvisionedHost> provisionedHosts = allocation.getFulfilledDockerDeficit()
- .map(deficit -> hostProvisioner.get().provisionHosts(
- nodeRepository.database().getProvisionIndexes(deficit.getCount()),
- deficit.getFlavor()))
+ .map(deficit -> hostProvisioner.get().provisionHosts(nodeRepository.database().getProvisionIndexes(deficit.getCount()),
+ deficit.getFlavor()))
.orElseGet(List::of);
// At this point we have started provisioning of the hosts, the first priority is to make sure that
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java
index 79296e58045..4defaaef57c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.vespa.hosted.provision.Node;
import java.util.List;
@@ -19,11 +20,11 @@ public interface HostProvisioner {
*
* @param provisionIndexes List of unique provision indexes which will be used to generate the host hostnames
* on the form of <code>[prefix][index].[domain]</code>
- * @param nodeFlavor Vespa flavor of the node that will run on this host. The resulting provisioned host
- * will be of a flavor that is at least as big or bigger than this.
+ * @param flavor the spec of the flavor (capacity) to provision. The resulting provisioned host
+ * will be of a flavor that is at least as big or bigger than this.
* @return list of {@link ProvisionedHost} describing the provisioned hosts and nodes on them.
*/
- List<ProvisionedHost> provisionHosts(List<Integer> provisionIndexes, Flavor nodeFlavor);
+ List<ProvisionedHost> provisionHosts(List<Integer> provisionIndexes, FlavorSpec flavor);
/**
* Continue provisioning of given list of Nodes.
@@ -47,4 +48,5 @@ public interface HostProvisioner {
* @param host host to deprovision.
*/
void deprovision(Node host);
+
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
index dcc3c4a0ef8..219ba759e24 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
@@ -5,6 +5,8 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
@@ -67,17 +69,18 @@ class NodeAllocation {
/** The next membership index to assign to a new node */
private final MutableInteger highestIndex;
+ private final NodeFlavors flavors;
private final Zone zone;
-
private final Clock clock;
NodeAllocation(NodeList allNodes, ApplicationId application, ClusterSpec cluster, NodeSpec requestedNodes,
- MutableInteger highestIndex, Zone zone, Clock clock) {
+ MutableInteger highestIndex, NodeFlavors flavors, Zone zone, Clock clock) {
this.allNodes = allNodes;
this.application = application;
this.cluster = cluster;
this.requestedNodes = requestedNodes;
this.highestIndex = highestIndex;
+ this.flavors = flavors;
this.zone = zone;
this.clock = clock;
}
@@ -217,7 +220,7 @@ class NodeAllocation {
}
private boolean hasCompatibleFlavor(Node node) {
- return requestedNodes.isCompatible(node.flavor());
+ return requestedNodes.isCompatible(node.flavor().asSpec(), flavors);
}
private Node acceptNode(PrioritizableNode prioritizableNode, boolean wantToRetire) {
@@ -285,7 +288,7 @@ class NodeAllocation {
.filter(NodeSpec.CountNodeSpec.class::isInstance)
.map(NodeSpec.CountNodeSpec.class::cast)
.map(spec -> new FlavorCount(spec.getFlavor(), spec.fulfilledDeficitCount(acceptedOfRequestedFlavor)))
- .filter(flavorCount -> flavorCount.getFlavor().getType() == Flavor.Type.DOCKER_CONTAINER)
+ .filter(flavorCount -> ! flavorCount.getFlavor().allocateByLegacyName())
.filter(flavorCount -> flavorCount.getCount() > 0);
}
@@ -364,15 +367,16 @@ class NodeAllocation {
}
static class FlavorCount {
- private final Flavor flavor;
+
+ private final FlavorSpec flavor;
private final int count;
- private FlavorCount(Flavor flavor, int count) {
+ private FlavorCount(FlavorSpec flavor, int count) {
this.flavor = flavor;
this.count = count;
}
- Flavor getFlavor() {
+ FlavorSpec getFlavor() {
return flavor;
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java
index 5a3f0380fa2..13006dd6ef7 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java
@@ -4,6 +4,8 @@ package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.log.LogLevel;
import com.yahoo.transaction.Mutex;
@@ -44,21 +46,22 @@ class NodePrioritizer {
private final ApplicationId appId;
private final ClusterSpec clusterSpec;
private final NameResolver nameResolver;
+ private final NodeFlavors flavors;
private final boolean isDocker;
private final boolean isAllocatingForReplacement;
private final Set<Node> spareHosts;
NodePrioritizer(NodeList allNodes, ApplicationId appId, ClusterSpec clusterSpec, NodeSpec nodeSpec,
- int spares, NameResolver nameResolver) {
+ int spares, NameResolver nameResolver, NodeFlavors flavors) {
this.allNodes = allNodes;
this.capacity = new DockerHostCapacity(allNodes);
this.requestedNodes = nodeSpec;
this.clusterSpec = clusterSpec;
this.appId = appId;
this.nameResolver = nameResolver;
+ this.flavors = flavors;
this.spareHosts = findSpareHosts(allNodes, capacity, spares);
-
int nofFailedNodes = (int) allNodes.asList().stream()
.filter(node -> node.state().equals(Node.State.failed))
.filter(node -> node.allocation().isPresent())
@@ -143,7 +146,7 @@ class NodePrioritizer {
}
void addNewDockerNodesOn(Mutex allocationLock, NodeList candidates) {
- if (!isDocker) return;
+ if ( ! isDocker) return;
ResourceCapacity wantedResourceCapacity = ResourceCapacity.of(getFlavor(requestedNodes));
for (Node node : candidates) {
@@ -171,10 +174,10 @@ class NodePrioritizer {
Collections.emptySet(),
allocation.get().hostname(),
Optional.of(node.hostname()),
- getFlavor(requestedNodes),
+ new Flavor(getFlavor(requestedNodes)),
NodeType.tenant);
PrioritizableNode nodePri = toNodePriority(newNode, false, true);
- if (!nodePri.violatesSpares || isAllocatingForReplacement) {
+ if ( ! nodePri.violatesSpares || isAllocatingForReplacement) {
log.log(LogLevel.DEBUG, "Adding new Docker node " + newNode);
nodes.put(newNode, nodePri);
}
@@ -215,8 +218,7 @@ class NodePrioritizer {
PrioritizableNode.Builder builder = new PrioritizableNode.Builder(node)
.withSurplusNode(isSurplusNode)
.withNewNode(isNewNode)
- .withPreferredOnFlavor(
- requestedNodes.specifiesNonStockFlavor() && node.flavor().equals(getFlavor(requestedNodes)));
+ .withPreferredOnFlavor(preferredOnFlavor(node));
allNodes.parentOf(node).ifPresent(parent -> {
builder.withParent(parent).withFreeParentCapacity(capacity.freeCapacityOf(parent, false));
@@ -229,6 +231,18 @@ class NodePrioritizer {
return builder.build();
}
+ /** Needed to handle requests for legacy non-docker nodes only */
+ private boolean preferredOnFlavor(Node node) {
+ if (requestedNodes instanceof NodeSpec.CountNodeSpec) {
+ FlavorSpec requestedFlavorSpec = ((NodeSpec.CountNodeSpec)requestedNodes).getFlavor();
+ if (requestedFlavorSpec.allocateByLegacyName()) {
+ Flavor requestedFlavor = flavors.getFlavorOrThrow(requestedFlavorSpec.legacyFlavorName());
+ return ! requestedFlavor.isStock() && node.flavor().equals(requestedFlavor);
+ }
+ }
+ return false;
+ }
+
static boolean isPreferredNodeToBeRelocated(List<Node> nodes, Node node, Node parent) {
NodeList list = new NodeList(nodes);
return list.childrenOf(parent).asList().stream()
@@ -243,7 +257,7 @@ class NodePrioritizer {
return requestedNodes.fulfilledBy(nofNodesInCluster - nodeFailedNodes);
}
- private static Flavor getFlavor(NodeSpec requestedNodes) {
+ private static FlavorSpec getFlavor(NodeSpec requestedNodes) {
if (requestedNodes instanceof NodeSpec.CountNodeSpec) {
NodeSpec.CountNodeSpec countSpec = (NodeSpec.CountNodeSpec) requestedNodes;
return countSpec.getFlavor();
@@ -252,8 +266,8 @@ class NodePrioritizer {
}
private boolean isDocker() {
- Flavor flavor = getFlavor(requestedNodes);
- return (flavor != null) && flavor.getType().equals(Flavor.Type.DOCKER_CONTAINER);
+ FlavorSpec flavor = getFlavor(requestedNodes);
+ return (flavor != null) && ! flavor.allocateByLegacyName();
}
private static int compareForRelocation(Node a, Node b) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
index c91d28e17ce..44ca50a29a6 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
@@ -7,6 +7,7 @@ import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeFlavors;
@@ -86,7 +87,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
log.log(zone.system() == SystemName.cd ? Level.INFO : LogLevel.DEBUG,
() -> "Received deploy prepare request for " + requestedCapacity + " in " +
- wantedGroups + " groups for application " + application + ", cluster " + cluster);
+ wantedGroups + " groups for application " + application + ", cluster " + cluster);
int effectiveGroups;
NodeSpec requestedNodes;
@@ -96,7 +97,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
if (zone.environment().isManuallyDeployed() && nodeCount < requestedCapacity.nodeCount())
logger.log(Level.INFO, "Requested " + requestedCapacity.nodeCount() + " nodes for " + cluster +
", downscaling to " + nodeCount + " nodes in " + zone.environment());
- Flavor flavor = capacityPolicies.decideFlavor(requestedCapacity, cluster);
+ FlavorSpec flavor = capacityPolicies.decideFlavor(requestedCapacity, cluster);
log.log(LogLevel.DEBUG, () -> "Decided flavor for requested tenant nodes: " + flavor);
boolean exclusive = capacityPolicies.decideExclusivity(cluster.isExclusive());
effectiveGroups = wantedGroups > nodeCount ? nodeCount : wantedGroups; // cannot have more groups than nodes
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
index e033d994f24..ed95a76a997 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
@@ -1,6 +1,8 @@
// 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.provision.provisioning;
+import com.yahoo.config.provision.FlavorSpec;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Flavor;
import com.yahoo.vespa.hosted.provision.Node;
@@ -26,13 +28,7 @@ public interface NodeSpec {
boolean isExclusive();
/** Returns whether the given flavor is compatible with this spec */
- boolean isCompatible(Flavor flavor);
-
- /** Returns whether the given flavor is exactly specified by this node spec */
- boolean matchesExactly(Flavor flavor);
-
- /** Returns whether this requests a non-stock flavor */
- boolean specifiesNonStockFlavor();
+ boolean isCompatible(FlavorSpec flavor, NodeFlavors flavors);
/** Returns whether the given node count is sufficient to consider this spec fulfilled to the maximum amount */
boolean saturatedBy(int count);
@@ -61,7 +57,7 @@ public interface NodeSpec {
*/
Node assignRequestedFlavor(Node node);
- static NodeSpec from(int nodeCount, Flavor flavor, boolean exclusive, boolean canFail) {
+ static NodeSpec from(int nodeCount, FlavorSpec flavor, boolean exclusive, boolean canFail) {
return new CountNodeSpec(nodeCount, flavor, exclusive, canFail);
}
@@ -73,20 +69,20 @@ public interface NodeSpec {
class CountNodeSpec implements NodeSpec {
private final int count;
- private final Flavor requestedFlavor;
+ private final FlavorSpec requestedFlavorSpec;
private final boolean exclusive;
private final boolean canFail;
- CountNodeSpec(int count, Flavor flavor, boolean exclusive, boolean canFail) {
+ CountNodeSpec(int count, FlavorSpec flavor, boolean exclusive, boolean canFail) {
this.count = count;
- this.requestedFlavor = Objects.requireNonNull(flavor, "A flavor must be specified");
+ this.requestedFlavorSpec = Objects.requireNonNull(flavor, "A flavor must be specified");
this.exclusive = exclusive;
this.canFail = canFail;
}
// TODO: Remove usage of this
- public Flavor getFlavor() {
- return requestedFlavor;
+ public FlavorSpec getFlavor() {
+ return requestedFlavorSpec;
}
@Override
@@ -96,16 +92,18 @@ public interface NodeSpec {
public NodeType type() { return NodeType.tenant; }
@Override
- public boolean isCompatible(Flavor flavor) {
- if (flavor.satisfies(requestedFlavor)) return true;
- return requestedFlavorCanBeAchievedByResizing(flavor);
- }
-
- @Override
- public boolean matchesExactly(Flavor flavor) { return flavor.equals(this.requestedFlavor); }
+ public boolean isCompatible(FlavorSpec flavorSpec, NodeFlavors flavors) {
+ if (flavorSpec.allocateByLegacyName()) {
+ Flavor flavor = flavors.getFlavorOrThrow(flavorSpec.legacyFlavorName());
+ Flavor requestedFlavor = flavors.getFlavorOrThrow(requestedFlavorSpec.legacyFlavorName());
+ if (flavor.satisfies(requestedFlavor)) return true;
+ }
+ else {
+ if (flavorSpec.equals(requestedFlavorSpec)) return true;
+ }
- @Override
- public boolean specifiesNonStockFlavor() { return ! requestedFlavor.isStock(); }
+ return requestedFlavorCanBeAchievedByResizing(flavorSpec);
+ }
@Override
public boolean saturatedBy(int count) { return fulfilledBy(count); } // min=max for count specs
@@ -123,23 +121,22 @@ public interface NodeSpec {
@Override
public NodeSpec fraction(int divisor) {
- return new CountNodeSpec(count/divisor, requestedFlavor, exclusive, canFail);
+ return new CountNodeSpec(count/divisor, requestedFlavorSpec, exclusive, canFail);
}
@Override
public Node assignRequestedFlavor(Node node) {
- // Docker nodes can change flavor in place
- if (requestedFlavorCanBeAchievedByResizing(node.flavor()))
- return node.with(requestedFlavor);
-
+ // Docker nodes can change flavor in place - disabled - see below
+ // if (requestedFlavorCanBeAchievedByResizing(node.flavor()))
+ // return node.with(requestedFlavor);
return node;
}
@Override
- public String toString() { return "request for " + count + " nodes of " + requestedFlavor; }
+ public String toString() { return "request for " + count + " nodes with " + requestedFlavorSpec; }
/** Docker nodes can be downsized in place */
- private boolean requestedFlavorCanBeAchievedByResizing(Flavor flavor) {
+ private boolean requestedFlavorCanBeAchievedByResizing(FlavorSpec flavor) {
// TODO: Enable this when we can do it safely
// Then also re-enable ProvisioningTest.application_deployment_with_inplace_downsize()
// return flavor.isDocker() && requestedFlavor.isDocker() && flavor.isLargerThan(requestedFlavor);
@@ -164,13 +161,7 @@ public interface NodeSpec {
public boolean isExclusive() { return false; }
@Override
- public boolean isCompatible(Flavor flavor) { return true; }
-
- @Override
- public boolean matchesExactly(Flavor flavor) { return false; }
-
- @Override
- public boolean specifiesNonStockFlavor() { return false; }
+ public boolean isCompatible(FlavorSpec flavor, NodeFlavors flavors) { return true; }
@Override
public boolean saturatedBy(int count) { return false; }
@@ -180,11 +171,9 @@ public interface NodeSpec {
@Override
public int idealRetiredCount(int acceptedCount, int currentRetiredCount) {
- /*
- * All nodes marked with wantToRetire get marked as retired just before this function is called,
- * the job of this function is to throttle the retired count. If no nodes are marked as retired
- * then continue this way, otherwise allow only 1 node to be retired
- */
+ // All nodes marked with wantToRetire get marked as retired just before this function is called,
+ // the job of this function is to throttle the retired count. If no nodes are marked as retired
+ // then continue this way, otherwise allow only 1 node to be retired
return Math.min(1, currentRetiredCount);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
index e0cf882fffa..4f729bdd03b 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
@@ -15,6 +15,7 @@ import java.util.Set;
* @author freva
*/
public class ProvisionedHost {
+
private final String id;
private final String hostHostname;
private final Flavor hostFlavor;
@@ -86,4 +87,5 @@ public class ProvisionedHost {
", nodeFlavor=" + nodeFlavor +
'}';
}
+
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ResourceCapacity.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ResourceCapacity.java
index 903951ef93b..4c52f739c40 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ResourceCapacity.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ResourceCapacity.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.vespa.hosted.provision.Node;
/**
@@ -31,6 +32,10 @@ public class ResourceCapacity {
flavor.getMinMainMemoryAvailableGb(), flavor.getMinCpuCores(), flavor.getMinDiskAvailableGb());
}
+ static ResourceCapacity of(FlavorSpec flavor) {
+ return new ResourceCapacity(flavor.memoryGb(), flavor.cpuCores(), flavor.diskGb());
+ }
+
static ResourceCapacity of(Node node) {
return ResourceCapacity.of(node.flavor());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
index b9fb88e900e..b8b17011a8e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
@@ -8,6 +8,8 @@ import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.DockerImage;
+import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
@@ -35,7 +37,7 @@ import java.util.Set;
/**
* A mock repository prepopulated with some applications.
- * Instantiated by DI from application package above.
+ * Instantiated by DI.
*/
public class MockNodeRepository extends NodeRepository {
@@ -59,36 +61,47 @@ public class MockNodeRepository extends NodeRepository {
}
private void populate() {
- NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(this, flavors, Zone.defaultZone(),
- new MockProvisionServiceProvider(), new InMemoryFlagSource());
+ NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(this,
+ flavors,
+ Zone.defaultZone(),
+ new MockProvisionServiceProvider(),
+ new InMemoryFlagSource());
List<Node> nodes = new ArrayList<>();
// Regular nodes
Set<String> ipAddresses = ImmutableSet.of("::1", "127.0.0.1");
Set<String> ipAddressPool = ImmutableSet.of("::2", "::3", "::4");
- nodes.add(createNode("node1", "host1.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
- nodes.add(createNode("node2", "host2.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
- nodes.add(createNode("node3", "host3.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("expensive"), NodeType.tenant));
+ nodes.add(createNode("node1", "host1.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("default"), NodeType.tenant));
+ nodes.add(createNode("node2", "host2.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("default"), NodeType.tenant));
+ nodes.add(createNode("node3", "host3.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("expensive"), NodeType.tenant));
- Node node4 = createNode("node4", "host4.yahoo.com", ipAddresses, Optional.of("dockerhost1.yahoo.com"), flavors.getFlavorOrThrow("docker"), NodeType.tenant);
+ Node node4 = createNode("node4", "host4.yahoo.com", ipAddresses, Optional.of("dockerhost1.yahoo.com"),
+ new Flavor(new FlavorSpec(1, 1, 100)), NodeType.tenant);
node4 = node4.with(node4.status()
.withVespaVersion(new Version("6.41.0"))
.withDockerImage(DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa:6.41.0")));
nodes.add(node4);
- Node node5 = createNode("node5", "host5.yahoo.com", ipAddresses, Optional.of("dockerhost2.yahoo.com"), flavors.getFlavorOrThrow("docker"), NodeType.tenant);
+ Node node5 = createNode("node5", "host5.yahoo.com", ipAddresses, Optional.of("dockerhost2.yahoo.com"),
+ new Flavor(new FlavorSpec(1, 1, 100)), NodeType.tenant);
nodes.add(node5.with(node5.status()
.withVespaVersion(new Version("1.2.3"))
.withDockerImage(DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa:1.2.3"))));
- nodes.add(createNode("node6", "host6.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
- Node node7 = createNode("node7", "host7.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant);
+ nodes.add(createNode("node6", "host6.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("default"), NodeType.tenant));
+ Node node7 = createNode("node7", "host7.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("default"), NodeType.tenant);
nodes.add(node7);
// 8, 9, 11 and 12 are added by web service calls
- Node node10 = createNode("node10", "host10.yahoo.com", ipAddresses, Optional.of("parent1.yahoo.com"), flavors.getFlavorOrThrow("default"), NodeType.tenant);
+ Node node10 = createNode("node10", "host10.yahoo.com", ipAddresses, Optional.of("parent1.yahoo.com"),
+ flavors.getFlavorOrThrow("default"), NodeType.tenant);
Status node10newStatus = node10.status();
node10newStatus = node10newStatus
.withVespaVersion(Version.fromString("5.104.142"))
@@ -96,24 +109,34 @@ public class MockNodeRepository extends NodeRepository {
node10 = node10.with(node10newStatus);
nodes.add(node10);
- Node node13 = createNode("node13", "host13.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("large"), NodeType.tenant);
- Node node14 = createNode("node14", "host14.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("large"), NodeType.tenant);
+ Node node13 = createNode("node13", "host13.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("large"), NodeType.tenant);
+ Node node14 = createNode("node14", "host14.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("large"), NodeType.tenant);
nodes.add(node13);
nodes.add(node14);
- Node node55 = createNode("node55", "host55.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant);
+ Node node55 = createNode("node55", "host55.yahoo.com", ipAddresses, Optional.empty(),
+ flavors.getFlavorOrThrow("default"), NodeType.tenant);
nodes.add(node55.with(node55.status().withWantToRetire(true).withWantToDeprovision(true)));
/* Setup docker hosts (two of these will be reserved for spares */
- nodes.add(createNode("dockerhost1", "dockerhost1.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(), flavors.getFlavorOrThrow("large"), NodeType.host));
- nodes.add(createNode("dockerhost2", "dockerhost2.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(), flavors.getFlavorOrThrow("large"), NodeType.host));
- nodes.add(createNode("dockerhost3", "dockerhost3.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(), flavors.getFlavorOrThrow("large"), NodeType.host));
- nodes.add(createNode("dockerhost4", "dockerhost4.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(), flavors.getFlavorOrThrow("large"), NodeType.host));
- nodes.add(createNode("dockerhost5", "dockerhost5.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(), flavors.getFlavorOrThrow("large"), NodeType.host));
+ nodes.add(createNode("dockerhost1", "dockerhost1.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(),
+ flavors.getFlavorOrThrow("large"), NodeType.host));
+ nodes.add(createNode("dockerhost2", "dockerhost2.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(),
+ flavors.getFlavorOrThrow("large"), NodeType.host));
+ nodes.add(createNode("dockerhost3", "dockerhost3.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(),
+ flavors.getFlavorOrThrow("large"), NodeType.host));
+ nodes.add(createNode("dockerhost4", "dockerhost4.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(),
+ flavors.getFlavorOrThrow("large"), NodeType.host));
+ nodes.add(createNode("dockerhost5", "dockerhost5.yahoo.com", ipAddresses, ipAddressPool, Optional.empty(), Optional.empty(),
+ flavors.getFlavorOrThrow("large"), NodeType.host));
// Config servers
- nodes.add(createNode("cfg1", "cfg1.yahoo.com", Collections.singleton("127.0.1.1"), Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.config));
- nodes.add(createNode("cfg2", "cfg2.yahoo.com", Collections.singleton("127.0.1.2"), Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.config));
+ nodes.add(createNode("cfg1", "cfg1.yahoo.com", Collections.singleton("127.0.1.1"), Optional.empty(),
+ flavors.getFlavorOrThrow("default"), NodeType.config));
+ nodes.add(createNode("cfg2", "cfg2.yahoo.com", Collections.singleton("127.0.1.2"), Optional.empty(),
+ flavors.getFlavorOrThrow("default"), NodeType.config));
// Ready all nodes, except 7 and 55
nodes = addNodes(nodes);
@@ -152,7 +175,7 @@ public class MockNodeRepository extends NodeRepository {
ClusterSpec.Id.from("id3"),
Version.fromString("6.42"),
false, Collections.emptySet());
- activate(provisioner.prepare(app3, cluster3, Capacity.fromNodeCount(2, Optional.of("docker"), false, true), 1, null), app3, provisioner);
+ activate(provisioner.prepare(app3, cluster3, Capacity.fromCount(2, new FlavorSpec(1, 1, 100), false, true), 1, null), app3, provisioner);
ApplicationId app4 = ApplicationId.from(TenantName.from("tenant4"), ApplicationName.from("application4"), InstanceName.from("instance4"));
ClusterSpec cluster4 = ClusterSpec.request(ClusterSpec.Type.container,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java
index a1a959b6438..d727ad68425 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java
@@ -9,6 +9,7 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
@@ -89,7 +90,7 @@ public class FailedExpirerTest {
scenario.clock().advance(Duration.ofDays(2));
scenario.expirer().run();
- scenario.assertNodesIn(Node.State.failed, "node1");
+ scenario.assertNodesIn(Node.State.dirty, "node1");
scenario.assertNodesIn(Node.State.parked, "node2", "node3");
}
@@ -125,7 +126,7 @@ public class FailedExpirerTest {
scenario.clock().advance(Duration.ofHours(2));
scenario.expirer().run();
- scenario.assertNodesIn(Node.State.failed, "node1");
+ scenario.assertNodesIn(Node.State.dirty, "node1");
scenario.assertNodesIn(Node.State.parked, "node2", "node3");
}
@@ -232,8 +233,8 @@ public class FailedExpirerTest {
private static class FailureScenario {
private static final NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default", "docker");
- public static final Flavor defaultFlavor = nodeFlavors.getFlavorOrThrow("default");
- public static final Flavor dockerFlavor = nodeFlavors.getFlavorOrThrow("docker");
+ public static final FlavorSpec defaultFlavor = new FlavorSpec(2, 2, 2);
+ public static final FlavorSpec dockerFlavor = new FlavorSpec(1, 1, 1);
private final MockCurator curator = new MockCurator();
private final ManualClock clock = new ManualClock();
@@ -269,15 +270,15 @@ public class FailedExpirerTest {
.orElseThrow(() -> new IllegalArgumentException("No such node: " + hostname));
}
- public FailureScenario withNode(NodeType type, Flavor flavor, String hostname, String parentHostname) {
+ public FailureScenario withNode(NodeType type, FlavorSpec flavor, String hostname, String parentHostname) {
nodeRepository.addNodes(Collections.singletonList(
nodeRepository.createNode(UUID.randomUUID().toString(), hostname,
- Optional.ofNullable(parentHostname), flavor, type)
+ Optional.ofNullable(parentHostname), new Flavor(flavor), type)
));
return this;
}
- public FailureScenario withNode(NodeType type, Flavor flavor, String hostname) {
+ public FailureScenario withNode(NodeType type, FlavorSpec flavor, String hostname) {
return withNode(type, flavor, hostname, null);
}
@@ -317,13 +318,13 @@ public class FailedExpirerTest {
return allocate(clusterType, defaultFlavor, hostname);
}
- public FailureScenario allocate(ClusterSpec.Type clusterType, Flavor flavor, String... hostname) {
+ public FailureScenario allocate(ClusterSpec.Type clusterType, FlavorSpec flavor, String... hostname) {
ClusterSpec clusterSpec = ClusterSpec.request(clusterType,
ClusterSpec.Id.from("test"),
Version.fromString("6.42"),
false,
Collections.emptySet());
- Capacity capacity = Capacity.fromNodeCount(hostname.length, Optional.of(flavor.name()), false, true);
+ Capacity capacity = Capacity.fromCount(hostname.length, Optional.of(flavor), false, true);
return allocate(applicationId, clusterSpec, capacity);
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirerTest.java
index 52d297232de..3b37c46add5 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirerTest.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.maintenance;
import com.yahoo.component.Vtag;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.hosted.provision.lb.LoadBalancer;
@@ -77,11 +78,11 @@ public class LoadBalancerExpirerTest {
}
private void deployApplication(ApplicationId application, ClusterSpec.Id cluster) {
- tester.makeReadyNodes(10, "default");
+ tester.makeReadyNodes(10, "d-1-1-1");
List<HostSpec> hosts = tester.prepare(application, ClusterSpec.request(ClusterSpec.Type.container, cluster,
Vtag.currentVersion, false, Collections.emptySet()),
2, 1,
- "default");
+ new FlavorSpec(1, 1, 1));
tester.activate(application, hosts);
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java
index 77f6a801d04..8b69fb63aed 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java
@@ -10,6 +10,7 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
@@ -30,6 +31,7 @@ import com.yahoo.vespa.hosted.provision.monitoring.MetricsReporterTest;
import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
+import com.yahoo.vespa.hosted.provision.provisioning.NodeSpec;
import com.yahoo.vespa.hosted.provision.testutils.MockDeployer;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
import com.yahoo.vespa.hosted.provision.testutils.MockProvisionServiceProvider;
@@ -129,7 +131,7 @@ public class NodeFailTester {
List<Node> hosts = tester.createHostNodes(numberOfHosts);
for (int i = 0; i < hosts.size(); i++) {
tester.createReadyNodes(nodesPerHost, i * nodesPerHost, Optional.of("parent" + i),
- nodeFlavors.getFlavorOrThrow("docker"), NodeType.tenant);
+ nodeFlavors.getFlavorOrThrow("d-1-1-1"), NodeType.tenant);
}
// Create applications
@@ -137,8 +139,8 @@ public class NodeFailTester {
ClusterSpec clusterApp1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.75.0"), false, Collections.emptySet());
ClusterSpec clusterApp2 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.75.0"), false, Collections.emptySet());
Capacity allHosts = Capacity.fromRequiredNodeType(NodeType.host);
- Capacity capacity1 = Capacity.fromNodeCount(3, Optional.of("docker"), false, true);
- Capacity capacity2 = Capacity.fromNodeCount(5, Optional.of("docker"), false, true);
+ Capacity capacity1 = Capacity.fromCount(3, new FlavorSpec(1, 1, 1), false, true);
+ Capacity capacity2 = Capacity.fromCount(5, new FlavorSpec(1, 1, 1), false, true);
tester.activate(nodeAdminApp, clusterNodeAdminApp, allHosts);
tester.activate(app1, clusterApp1, capacity1);
tester.activate(app2, clusterApp2, capacity2);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java
index a55211a112a..04014b3fa46 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java
@@ -6,6 +6,7 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.hosted.provision.Node;
@@ -15,6 +16,7 @@ import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -36,26 +38,26 @@ public class AclProvisioningTest {
@Test
public void trusted_nodes_for_allocated_node() {
- List<Node> configServers = tester.makeConfigServers(3, "default", Version.fromString("6.123.456"));
+ List<Node> configServers = tester.makeConfigServers(3, "d-1-1-1", Version.fromString("6.123.456"));
// Populate repo
- tester.makeReadyNodes(10, "default");
- List<Node> dockerHost = tester.makeReadyNodes(1, "default", NodeType.host);
+ tester.makeReadyNodes(10, "d-1-1-1");
+ List<Node> dockerHost = tester.makeReadyNodes(1, "d-1-1-1", NodeType.host);
ApplicationId zoneApplication = tester.makeApplicationId();
deploy(zoneApplication, Capacity.fromRequiredNodeType(NodeType.host));
- tester.makeReadyVirtualDockerNodes(1, "default", dockerHost.get(0).hostname());
- List<Node> proxyNodes = tester.makeReadyNodes(3, "default", NodeType.proxy);
+ tester.makeReadyVirtualDockerNodes(1, FlavorSpec.fromLegacyFlavorName("d-1-1-1"), dockerHost.get(0).hostname());
+ List<Node> proxyNodes = tester.makeReadyNodes(3, "d-1-1-1", NodeType.proxy);
// Allocate 2 nodes
ApplicationId application = tester.makeApplicationId();
- List<Node> activeNodes = deploy(application, 2);
+ List<Node> activeNodes = deploy(application, Capacity.fromCount(2, FlavorSpec.fromLegacyFlavorName("d-1-1-1"), false, true));
assertEquals(2, activeNodes.size());
// Get trusted nodes for the first active node
Node node = activeNodes.get(0);
Supplier<List<NodeAcl>> nodeAcls = () -> tester.nodeRepository().getNodeAcls(node, false);
- // Trusted nodes is active nodes in same application, proxy nodes and config servers
+ // Trusted nodes are active nodes in same application, proxy nodes and config servers
assertAcls(Arrays.asList(activeNodes, proxyNodes, configServers, dockerHost),
ImmutableSet.of("10.2.3.0/24", "10.4.5.0/24"),
nodeAcls.get());
@@ -130,7 +132,7 @@ public class AclProvisioningTest {
// Populate repo
List<Node> dockerHostNodes = tester.makeReadyNodes(2, "default", NodeType.host);
Node dockerHostNodeUnderTest = dockerHostNodes.get(0);
- List<Node> dockerNodes = tester.makeReadyVirtualDockerNodes(5, "dockerSmall",
+ List<Node> dockerNodes = tester.makeReadyVirtualDockerNodes(5, new FlavorSpec(1, 1, 1),
dockerHostNodeUnderTest.hostname());
List<NodeAcl> acls = tester.nodeRepository().getNodeAcls(dockerHostNodeUnderTest, true);
@@ -211,12 +213,16 @@ public class AclProvisioningTest {
}
private static void assertAcls(List<List<Node>> expectedNodes, Set<String> expectedNetworks, List<NodeAcl> actual) {
- Set<Node> expectedTrustedNodes = expectedNodes.stream()
+ List<Node> expectedTrustedNodes = expectedNodes.stream()
.flatMap(Collection::stream)
- .collect(Collectors.toSet());
- Set<Node> actualTrustedNodes = actual.stream()
+ .distinct()
+ .sorted(Comparator.comparing(Node::hostname))
+ .collect(Collectors.toList());
+ List<Node> actualTrustedNodes = actual.stream()
.flatMap(acl -> acl.trustedNodes().stream())
- .collect(Collectors.toSet());
+ .distinct()
+ .sorted(Comparator.comparing(Node::hostname))
+ .collect(Collectors.toList());
assertEquals(expectedTrustedNodes, actualTrustedNodes);
Set<String> actualTrustedNetworks = actual.stream()
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
index 78fbca554f0..242bb7df146 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
@@ -118,7 +118,6 @@ public class AllocationSimulator {
public void addCluster(String task, int count, Flavor flavor, String id) {
// TODO: Implement
- NodeSpec.CountNodeSpec nodeSpec = new NodeSpec.CountNodeSpec(count, flavor, false, true);
nodes = new NodeList(nodes.asList());
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java
index 0fdf857e97f..da32939dfd6 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java
@@ -7,6 +7,7 @@ import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeType;
@@ -36,7 +37,7 @@ import static org.junit.Assert.fail;
*/
public class DockerProvisioningTest {
- private static final String dockerFlavor = "dockerSmall";
+ private static final FlavorSpec dockerFlavor = new FlavorSpec(1, 1, 1);
@Test
public void docker_application_deployment() {
@@ -55,7 +56,7 @@ public class DockerProvisioningTest {
NodeList nodes = tester.getNodes(application1, Node.State.active);
assertEquals(nodeCount, nodes.size());
- assertEquals(dockerFlavor, nodes.asList().get(0).flavor().canonicalName());
+ assertEquals(dockerFlavor, nodes.asList().get(0).flavor().asSpec());
// Upgrade Vespa version on nodes
Version upgradedWantedVespaVersion = Version.fromString("6.40");
@@ -65,7 +66,7 @@ public class DockerProvisioningTest {
tester.activate(application1, new HashSet<>(upgradedHosts));
NodeList upgradedNodes = tester.getNodes(application1, Node.State.active);
assertEquals(nodeCount, upgradedNodes.size());
- assertEquals(dockerFlavor, upgradedNodes.asList().get(0).flavor().canonicalName());
+ assertEquals(dockerFlavor, upgradedNodes.asList().get(0).flavor().asSpec());
assertEquals(hosts, upgradedHosts);
}
@@ -74,7 +75,7 @@ public class DockerProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId zoneApplication = tester.makeApplicationId();
- List<Node> parents = tester.makeReadyVirtualDockerHosts(10, "large");
+ List<Node> parents = tester.makeReadyVirtualDockerHosts(10, new FlavorSpec(2, 2, 2));
for (Node parent : parents)
tester.makeReadyVirtualDockerNodes(1, dockerFlavor, parent.hostname());
@@ -204,7 +205,7 @@ public class DockerProvisioningTest {
}
catch (Exception e) {
assertEquals("No room for 3 nodes as 2 of 4 hosts are exclusive",
- "Could not satisfy request for 3 nodes of flavor 'dockerSmall' for container cluster 'myContainer' group 0 6.39 in tenant1.app1: Not enough nodes available due to host exclusivity constraints.",
+ "Could not satisfy request for 3 nodes with cpu cores: 1.0, memory: 1.0 Gb, disk 1.0 Gb for container cluster 'myContainer' group 0 6.39 in tenant1.app1: Not enough nodes available due to host exclusivity constraints.",
e.getMessage());
}
@@ -225,7 +226,7 @@ public class DockerProvisioningTest {
NodeList nodes = tester.getNodes(application1, Node.State.active);
assertEquals(1, nodes.size());
- assertEquals(dockerFlavor, nodes.asList().get(0).flavor().canonicalName());
+ assertEquals(dockerFlavor.legacyFlavorName(), nodes.asList().get(0).flavor().canonicalName());
}
private Set<String> hostsOf(NodeList nodes) {
@@ -235,7 +236,7 @@ public class DockerProvisioningTest {
private void prepareAndActivate(ApplicationId application, int nodeCount, boolean exclusive, ProvisioningTester tester) {
Set<HostSpec> hosts = new HashSet<>(tester.prepare(application,
ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer"), Version.fromString("6.39"), exclusive, Collections.emptySet()),
- Capacity.fromNodeCount(nodeCount, Optional.of(dockerFlavor), false, true),
+ Capacity.fromCount(nodeCount, Optional.of(dockerFlavor), false, true),
1));
tester.activate(application, hosts);
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
index 74541677714..3e72b332077 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
@@ -9,6 +9,7 @@ import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.OutOfCapacityException;
@@ -64,7 +65,7 @@ public class DynamicDockerAllocationTest {
tester.makeReadyNodes(4, "host-small", NodeType.host, 32);
deployZoneApp(tester);
List<Node> dockerHosts = tester.nodeRepository().getNodes(NodeType.host, Node.State.active);
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-1");
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
// Application 1
ApplicationId application1 = makeApplicationId("t1", "a1");
@@ -107,7 +108,7 @@ public class DynamicDockerAllocationTest {
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
deployZoneApp(tester);
List<Node> dockerHosts = tester.nodeRepository().getNodes(NodeType.host, Node.State.active);
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-1");
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
// Application 1
ApplicationId application1 = makeApplicationId("t1", "a1");
@@ -164,7 +165,7 @@ public class DynamicDockerAllocationTest {
tester.makeReadyNodes(2, "host-small", NodeType.host, 32);
deployZoneApp(tester);
List<Node> dockerHosts = tester.nodeRepository().getNodes(NodeType.host, Node.State.active);
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-1");
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
// Application 1
ApplicationId application1 = makeApplicationId("t1", "a1");
@@ -190,11 +191,10 @@ public class DynamicDockerAllocationTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
deployZoneApp(tester);
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-1");
//Deploy an application having 6 nodes (3 nodes in 2 groups). We only have 5 docker hosts available
ApplicationId application1 = tester.makeApplicationId();
- tester.prepare(application1, clusterSpec("myContent.t1.a1"), 6, 2, flavor.canonicalName());
+ tester.prepare(application1, clusterSpec("myContent.t1.a1"), 6, 2, new FlavorSpec(1, 1, 1));
fail("Two groups have been allocated to the same parent host");
}
@@ -212,27 +212,27 @@ public class DynamicDockerAllocationTest {
ApplicationId application1 = tester.makeApplicationId();
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
deployZoneApp(tester);
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-3");
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
// Deploy initial state (can max deploy 3 nodes due to redundancy requirements)
ClusterSpec clusterSpec = clusterSpec("myContent.t1.a1");
- List<HostSpec> hosts = tester.prepare(application1, clusterSpec, 3, 1, flavor.canonicalName());
+ List<HostSpec> hosts = tester.prepare(application1, clusterSpec, 3, 1, flavor);
tester.activate(application1, ImmutableSet.copyOf(hosts));
DockerHostCapacity capacity = new DockerHostCapacity(tester.nodeRepository().getNodes(Node.State.values()));
- assertThat(capacity.freeCapacityInFlavorEquivalence(flavor), greaterThan(0));
+ assertThat(capacity.freeCapacityInFlavorEquivalence(new Flavor(flavor)), greaterThan(0));
List<Node> initialSpareCapacity = findSpareCapacity(tester);
assertThat(initialSpareCapacity.size(), is(2));
try {
- hosts = tester.prepare(application1, clusterSpec, 4, 1, flavor.canonicalName());
+ hosts = tester.prepare(application1, clusterSpec, 4, 1, flavor);
fail("Was able to deploy with 4 nodes, should not be able to use spare capacity");
} catch (OutOfCapacityException e) {
}
tester.fail(hosts.get(0));
- hosts = tester.prepare(application1, clusterSpec, 3, 1, flavor.canonicalName());
+ hosts = tester.prepare(application1, clusterSpec, 3, 1, flavor);
tester.activate(application1, ImmutableSet.copyOf(hosts));
List<Node> finalSpareCapacity = findSpareCapacity(tester);
@@ -245,10 +245,8 @@ public class DynamicDockerAllocationTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.perf, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(3, "host-small", NodeType.host, 32);
deployZoneApp(tester);
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-3");
-
ApplicationId application1 = tester.makeApplicationId();
- List<HostSpec> hosts = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 3, 1, flavor.canonicalName());
+ List<HostSpec> hosts = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 3, 1, new FlavorSpec(1, 1, 1));
tester.activate(application1, ImmutableSet.copyOf(hosts));
List<Node> initialSpareCapacity = findSpareCapacity(tester);
@@ -262,8 +260,7 @@ public class DynamicDockerAllocationTest {
deployZoneApp(tester);
ApplicationId application = tester.makeApplicationId();
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-3");
- tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor.canonicalName());
+ tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, new FlavorSpec(1, 1, 1));
}
@Test
@@ -273,8 +270,7 @@ public class DynamicDockerAllocationTest {
deployZoneApp(tester);
ApplicationId application = tester.makeApplicationId();
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-3");
- List<HostSpec> hosts = tester.prepare(application, clusterSpec("myContent.t1.a1"), 2, 1, flavor.canonicalName());
+ List<HostSpec> hosts = tester.prepare(application, clusterSpec("myContent.t1.a1"), 2, 1, new FlavorSpec(1, 1, 1));
tester.activate(application, hosts);
List<Node> activeNodes = tester.nodeRepository().getNodes(application);
@@ -286,13 +282,13 @@ public class DynamicDockerAllocationTest {
return ApplicationId.from(tenant, appName, "default");
}
- private void deployApp(ApplicationId id, ClusterSpec spec, Flavor flavor, ProvisioningTester tester, int nodeCount) {
- List<HostSpec> hostSpec = tester.prepare(id, spec, nodeCount, 1, flavor.canonicalName());
+ private void deployApp(ApplicationId id, ClusterSpec spec, FlavorSpec flavor, ProvisioningTester tester, int nodeCount) {
+ List<HostSpec> hostSpec = tester.prepare(id, spec, nodeCount, 1, flavor);
tester.activate(id, new HashSet<>(hostSpec));
}
- private void addAndAssignNode(ApplicationId id, String hostname, String parentHostname, ClusterSpec clusterSpec, Flavor flavor, int index, ProvisioningTester tester) {
- Node node1a = Node.create("open1", Collections.singleton("127.0.0.100"), new HashSet<>(), hostname, Optional.of(parentHostname), Optional.empty(), flavor, NodeType.tenant);
+ private void addAndAssignNode(ApplicationId id, String hostname, String parentHostname, ClusterSpec clusterSpec, FlavorSpec flavor, int index, ProvisioningTester tester) {
+ Node node1a = Node.create("open1", Collections.singleton("127.0.0.100"), new HashSet<>(), hostname, Optional.of(parentHostname), Optional.empty(), new Flavor(flavor), NodeType.tenant);
ClusterMembership clusterMembership1 = ClusterMembership.from(
clusterSpec.with(Optional.of(ClusterSpec.Group.from(0))), index); // Need to add group here so that group is serialized in node allocation
Node node1aAllocation = node1a.allocate(id, clusterMembership1, Instant.now());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java
index 60e9289b9bf..7c7892055e2 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java
@@ -7,6 +7,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.flags.Flags;
@@ -44,10 +45,10 @@ public class DynamicDockerProvisionTest {
assertEquals(0, tester.nodeRepository().list().size());
ApplicationId application1 = tester.makeApplicationId();
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("dockerSmall");
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small"));
- List<HostSpec> hostSpec = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 4, 1, flavor.canonicalName());
+ List<HostSpec> hostSpec = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 4, 1, flavor);
verify(hostProvisioner).provisionHosts(List.of(100, 101, 102, 103), flavor);
// Total of 8 nodes should now be in node-repo, 4 hosts in state provisioned, and 4 reserved nodes
@@ -64,21 +65,21 @@ public class DynamicDockerProvisionTest {
deployZoneApp(tester);
ApplicationId application = tester.makeApplicationId();
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("dockerSmall");
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small"));
- tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor.canonicalName());
+ tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor);
verify(hostProvisioner).provisionHosts(List.of(100, 101), flavor);
}
@Test
public void allocates_to_hosts_already_hosting_nodes_by_this_tenant() {
ApplicationId application = tester.makeApplicationId();
- Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("dockerSmall");
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
List<Integer> expectedProvisionIndexes = List.of(100, 101);
mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("large"));
- tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor.canonicalName());
+ tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor);
verify(hostProvisioner).provisionHosts(expectedProvisionIndexes, flavor);
// Ready the provisioned hosts, add an IP addreses to pool and activate them
@@ -92,7 +93,7 @@ public class DynamicDockerProvisionTest {
deployZoneApp(tester);
mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small"));
- tester.prepare(application, clusterSpec("another-id"), 2, 1, flavor.canonicalName());
+ tester.prepare(application, clusterSpec("another-id"), 2, 1, flavor);
// Verify there was only 1 call to provision hosts (during the first prepare)
verify(hostProvisioner).provisionHosts(any(), any());
@@ -124,9 +125,9 @@ public class DynamicDockerProvisionTest {
private static void mockHostProvisioner(HostProvisioner hostProvisioner, Flavor hostFlavor) {
doAnswer(invocation -> {
List<Integer> provisionIndexes = (List<Integer>) invocation.getArguments()[0];
- Flavor nodeFlavor = (Flavor) invocation.getArguments()[1];
+ FlavorSpec nodeFlavor = (FlavorSpec) invocation.getArguments()[1];
return provisionIndexes.stream()
- .map(i -> new ProvisionedHost("id-" + i, "host-" + i, hostFlavor, "host-" + i + "-1", nodeFlavor))
+ .map(i -> new ProvisionedHost("id-" + i, "host-" + i, hostFlavor, "host-" + i + "-1", new Flavor(nodeFlavor)))
.collect(Collectors.toList());
}).when(hostProvisioner).provisionHosts(any(), any());
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java
index 4f7e09d0bd7..d982669413e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java
@@ -5,6 +5,7 @@ import com.google.common.collect.Iterators;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.RotationName;
@@ -136,10 +137,10 @@ public class LoadBalancerProvisionerTest {
}
private Set<HostSpec> prepare(ApplicationId application, ClusterSpec... specs) {
- tester.makeReadyNodes(specs.length * 2, "default");
+ tester.makeReadyNodes(specs.length * 2, "d-1-1-1");
Set<HostSpec> allNodes = new LinkedHashSet<>();
for (ClusterSpec spec : specs) {
- allNodes.addAll(tester.prepare(application, spec, 2, 1, "default"));
+ allNodes.addAll(tester.prepare(application, spec, 2, 1, new FlavorSpec(1, 1, 1)));
}
return allNodes;
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
index 0eca5e25d85..953bce6b6b2 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
@@ -10,10 +10,12 @@ import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
+import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.OutOfCapacityException;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.TenantName;
@@ -66,37 +68,37 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
ApplicationId application2 = tester.makeApplicationId();
- tester.makeReadyNodes(21, "default");
+ tester.makeReadyNodes(21, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state1 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// redeploy
- SystemState state2 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state2 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
state2.assertEquals(state1);
tester.activate(application1, state2.allHosts);
// deploy another application
- SystemState state1App2 = prepare(application2, 2, 2, 3, 3, "default", tester);
+ SystemState state1App2 = prepare(application2, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
assertFalse("Hosts to different apps are disjunct", state1App2.allHosts.removeAll(state1.allHosts));
tester.activate(application2, state1App2.allHosts);
// prepare twice
- SystemState state3 = prepare(application1, 2, 2, 3, 3, "default", tester);
- SystemState state4 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state3 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
+ SystemState state4 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
state3.assertEquals(state2);
state4.assertEquals(state3);
tester.activate(application1, state4.allHosts);
// remove nodes before deploying
- SystemState state5 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state5 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
HostSpec removed = tester.removeOne(state5.allHosts);
tester.activate(application1, state5.allHosts);
assertEquals(removed.hostname(), tester.nodeRepository().getNodes(application1, Node.State.inactive).get(0).hostname());
// remove some of the clusters
- SystemState state6 = prepare(application1, 0, 2, 0, 3, "default", tester);
+ SystemState state6 = prepare(application1, 0, 2, 0, 3, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state6.allHosts);
assertEquals(5, tester.getNodes(application1, Node.State.active).size());
assertEquals(5, tester.getNodes(application1, Node.State.inactive).size());
@@ -115,14 +117,14 @@ public class ProvisioningTest {
HostSpec failed = tester.removeOne(state1App2.allHosts);
tester.fail(failed);
assertEquals(9, tester.getNodes(application2, Node.State.active).size());
- SystemState state2App2 = prepare(application2, 2, 2, 3, 3, "default", tester);
+ SystemState state2App2 = prepare(application2, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
assertFalse("Hosts to different apps are disjunct", state2App2.allHosts.removeAll(state1.allHosts));
assertEquals("A new node was reserved to replace the failed one", 10, state2App2.allHosts.size());
assertFalse("The new host is not the failed one", state2App2.allHosts.contains(failed));
tester.activate(application2, state2App2.allHosts);
// deploy first app again
- SystemState state7 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state7 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
state7.assertEquals(state1);
tester.activate(application1, state7.allHosts);
assertEquals(0, tester.getNodes(application1, Node.State.inactive).size());
@@ -146,10 +148,10 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyNodes(4, "default");
+ tester.makeReadyNodes(4, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 1, 1, 1, 1, "default", tester);
+ SystemState state1 = prepare(application1, 1, 1, 1, 1, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
HostSpec host1 = state1.container0.iterator().next();
@@ -158,7 +160,7 @@ public class ProvisioningTest {
tester.nodeRepository().write(node1.with(node1.status().withVespaVersion(Version.fromString("1.2.3"))));
// redeploy
- SystemState state2 = prepare(application1, 1, 1, 1, 1, "default", tester);
+ SystemState state2 = prepare(application1, 1, 1, 1, 1, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state2.allHosts);
host1 = state2.container0.iterator().next();
@@ -171,20 +173,20 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyNodes(24, "default");
+ tester.makeReadyNodes(24, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state1 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// redeploy with increased sizes
- SystemState state2 = prepare(application1, 3, 4, 4, 5, "default", tester);
+ SystemState state2 = prepare(application1, 3, 4, 4, 5, new FlavorSpec(1, 1, 1), tester);
state2.assertExtends(state1);
assertEquals("New nodes are reserved", 6, tester.getNodes(application1, Node.State.reserved).size());
tester.activate(application1, state2.allHosts);
// decrease again
- SystemState state3 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state3 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state3.allHosts);
assertEquals("Superfluous container nodes are deactivated",
3-2 + 4-2, tester.getNodes(application1, Node.State.inactive).size());
@@ -192,7 +194,7 @@ public class ProvisioningTest {
4-3 + 5-3, tester.getNodes(application1, Node.State.active).retired().size());
// increase even more, and remove one node before deploying
- SystemState state4 = prepare(application1, 4, 5, 5, 6, "default", tester);
+ SystemState state4 = prepare(application1, 4, 5, 5, 6, new FlavorSpec(1, 1, 1), tester);
assertEquals("Inactive nodes are reused", 0, tester.getNodes(application1, Node.State.inactive).size());
assertEquals("Earlier retired nodes are not unretired before activate",
4-3 + 5-3, tester.getNodes(application1, Node.State.active).retired().size());
@@ -208,7 +210,7 @@ public class ProvisioningTest {
0, tester.getNodes(application1, Node.State.active).retired().size());
// decrease again
- SystemState state5 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state5 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state5.allHosts);
assertEquals("Superfluous container nodes are also deactivated",
4-2 + 5-2 + 1, tester.getNodes(application1, Node.State.inactive).size()); //
@@ -216,13 +218,13 @@ public class ProvisioningTest {
5-3 + 6-3 - 1, tester.getNodes(application1, Node.State.active).retired().size());
// increase content slightly
- SystemState state6 = prepare(application1, 2, 2, 4, 3, "default", tester);
+ SystemState state6 = prepare(application1, 2, 2, 4, 3, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state6.allHosts);
assertEquals("One content node is unretired",
5-4 + 6-3 - 1, tester.getNodes(application1, Node.State.active).retired().size());
// Then reserve more
- SystemState state7 = prepare(application1, 8, 2, 2, 2, "default", tester);
+ SystemState state7 = prepare(application1, 8, 2, 2, 2, new FlavorSpec(1, 1, 1), tester);
// delete app
NestedTransaction removeTransaction = new NestedTransaction();
@@ -238,27 +240,27 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyNodes(12, "small");
- tester.makeReadyNodes(16, "large");
+ tester.makeReadyNodes(12, "d-1-1-1");
+ tester.makeReadyNodes(16, "d-2-2-2");
// deploy
- SystemState state1 = prepare(application1, 2, 2, 4, 4, "small", tester);
+ SystemState state1 = prepare(application1, 2, 2, 4, 4, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// redeploy with reduced size (to cause us to have retired nodes before switching flavor)
- SystemState state2 = prepare(application1, 2, 2, 3, 3, "small", tester);
+ SystemState state2 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state2.allHosts);
// redeploy with increased sizes and new flavor
- SystemState state3 = prepare(application1, 3, 4, 4, 5, "large", tester);
+ SystemState state3 = prepare(application1, 3, 4, 4, 5, new FlavorSpec(2, 2, 2), tester);
assertEquals("New nodes are reserved", 16, tester.nodeRepository().getNodes(application1, Node.State.reserved).size());
tester.activate(application1, state3.allHosts);
assertEquals("'small' container nodes are retired because we are swapping the entire cluster",
- 2 + 2, tester.getNodes(application1, Node.State.active).retired().type(ClusterSpec.Type.container).flavor("small").size());
+ 2 + 2, tester.getNodes(application1, Node.State.active).retired().type(ClusterSpec.Type.container).flavor("d-1-1-1").size());
assertEquals("'small' content nodes are retired",
- 4 + 4, tester.getNodes(application1, Node.State.active).retired().type(ClusterSpec.Type.content).flavor("small").size());
+ 4 + 4, tester.getNodes(application1, Node.State.active).retired().type(ClusterSpec.Type.content).flavor("d-1-1-1").size());
assertEquals("No 'large' content nodes are retired",
- 0, tester.getNodes(application1, Node.State.active).retired().flavor("large").size());
+ 0, tester.getNodes(application1, Node.State.active).retired().flavor("d-2-2-2").size());
}
// TODO: Enable when this feature is re-enabled
@@ -269,14 +271,14 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyNodes(14, "dockerLarge");
+ tester.makeReadyNodes(14, "d-2-2-2", NodeType.host);
// deploy
- SystemState state1 = prepare(application1, 2, 2, 4, 4, "dockerLarge", tester);
+ SystemState state1 = prepare(application1, 2, 2, 4, 4, new FlavorSpec(2, 2, 2), tester);
tester.activate(application1, state1.allHosts);
// redeploy with smaller docker flavor - causes in-place flavor change
- SystemState state2 = prepare(application1, 2, 2, 4, 4, "dockerSmall", tester);
+ SystemState state2 = prepare(application1, 2, 2, 4, 4, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state2.allHosts);
assertEquals(12, tester.getNodes(application1, Node.State.active).size());
@@ -321,11 +323,13 @@ public class ProvisioningTest {
tester.makeReadyNodes(8, "large-variant");
// deploy with flavor which will be fulfilled by some old and new nodes
- SystemState state1 = prepare(application1, 2, 2, 4, 4, "old-large1", tester);
+ SystemState state1 = prepare(application1, 2, 2, 4, 4,
+ FlavorSpec.fromLegacyFlavorName("old-large1"), tester);
tester.activate(application1, state1.allHosts);
// redeploy with increased sizes, this will map to the remaining old/new nodes
- SystemState state2 = prepare(application1, 3, 4, 4, 5, "old-large2", tester);
+ SystemState state2 = prepare(application1, 3, 4, 4, 5,
+ FlavorSpec.fromLegacyFlavorName("old-large2"), tester);
assertEquals("New nodes are reserved", 4, tester.getNodes(application1, Node.State.reserved).size());
tester.activate(application1, state2.allHosts);
assertEquals("All nodes are used",
@@ -334,12 +338,14 @@ public class ProvisioningTest {
0, tester.getNodes(application1, Node.State.active).retired().size());
// This is a noop as we are already using large nodes and nodes which replace large
- SystemState state3 = prepare(application1, 3, 4, 4, 5, "large", tester);
+ SystemState state3 = prepare(application1, 3, 4, 4, 5,
+ FlavorSpec.fromLegacyFlavorName("large"), tester);
assertEquals("Noop", 0, tester.getNodes(application1, Node.State.reserved).size());
tester.activate(application1, state3.allHosts);
try {
- SystemState state4 = prepare(application1, 3, 4, 4, 5, "large-variant", tester);
+ SystemState state4 = prepare(application1, 3, 4, 4, 5,
+ FlavorSpec.fromLegacyFlavorName("large-variant"), tester);
fail("Should fail as we don't have that many large-variant nodes");
}
catch (OutOfCapacityException expected) {
@@ -347,7 +353,8 @@ public class ProvisioningTest {
// make enough nodes to complete the switch to large-variant
tester.makeReadyNodes(8, "large-variant");
- SystemState state4 = prepare(application1, 3, 4, 4, 5, "large-variant", tester);
+ SystemState state4 = prepare(application1, 3, 4, 4, 5,
+ FlavorSpec.fromLegacyFlavorName("large-variant"), tester);
assertEquals("New 'large-variant' nodes are reserved", 8, tester.getNodes(application1, Node.State.reserved).size());
tester.activate(application1, state4.allHosts);
// (we can not check for the precise state here without carrying over from earlier as the distribution of
@@ -360,22 +367,25 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyNodes(5, "default");
+ tester.makeReadyNodes(5, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 2, 0, 3, 0, "default", tester);
+ SystemState state1 = prepare(application1, 2, 0, 3, 0,
+ new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// redeploy a too large application
try {
- SystemState state2 = prepare(application1, 3, 0, 3, 0, "default", tester);
+ SystemState state2 = prepare(application1, 3, 0, 3, 0,
+ new FlavorSpec(1, 1, 1), tester);
fail("Expected out of capacity exception");
}
catch (OutOfCapacityException expected) {
}
// deploy first state again
- SystemState state3 = prepare(application1, 2, 0, 3, 0, "default", tester);
+ SystemState state3 = prepare(application1, 2, 0, 3, 0,
+ new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state3.allHosts);
}
@@ -384,8 +394,9 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(4, "default");
- SystemState state = prepare(application, 2, 2, 3, 3, "default", tester);
+ tester.makeReadyNodes(4, "d-1-1-1");
+ SystemState state = prepare(application, 2, 2, 3, 3,
+ new FlavorSpec(1, 1, 1), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -395,8 +406,8 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(4, "default");
- SystemState state = prepare(application, 2, 2, 3, 3, "default", Version.fromString("6.91"), tester);
+ tester.makeReadyNodes(4, "d-1-1-1");
+ SystemState state = prepare(application, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), Version.fromString("6.91"), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -406,8 +417,9 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.test, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(4, "default");
- SystemState state = prepare(application, 2, 2, 3, 3, "default", tester);
+ tester.makeReadyNodes(4, "d-1-1-1");
+ SystemState state = prepare(application, 2, 2, 3, 3,
+ new FlavorSpec(1, 1, 1), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -417,8 +429,9 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(10, "default");
- prepare(application, 1, 2, 3, 3, "default", tester);
+ tester.makeReadyNodes(10, "d-1-1-1");
+ prepare(application, 1, 2, 3, 3,
+ new FlavorSpec(1, 1, 1), tester);
}
/** Dev always uses the zone default flavor */
@@ -427,8 +440,9 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(4, "default");
- SystemState state = prepare(application, 2, 2, 3, 3, "large", tester);
+ tester.makeReadyNodes(4, "d-2-2-2");
+ SystemState state = prepare(application, 2, 2, 3, 3,
+ new FlavorSpec(2, 2, 2), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -439,8 +453,9 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.test, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(4, "default");
- SystemState state = prepare(application, 2, 2, 3, 3, "large", tester);
+ tester.makeReadyNodes(4, "d-2-2-2");
+ SystemState state = prepare(application, 2, 2, 3, 3,
+ new FlavorSpec(2, 2, 2), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -450,8 +465,9 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.staging, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(14, "default");
- SystemState state = prepare(application, 1, 1, 1, 64, "default", tester); // becomes 1, 1, 1, 6
+ tester.makeReadyNodes(14, "d-1-1-1");
+ SystemState state = prepare(application, 1, 1, 1, 64,
+ new FlavorSpec(1, 1, 1), tester); // becomes 1, 1, 1, 6
assertEquals(9, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -460,9 +476,10 @@ public class ProvisioningTest {
public void activate_after_reservation_timeout() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
- tester.makeReadyNodes(10, "default");
+ tester.makeReadyNodes(10, "d-1-1-1");
ApplicationId application = tester.makeApplicationId();
- SystemState state = prepare(application, 2, 2, 3, 3, "default", tester);
+ SystemState state = prepare(application, 2, 2, 3, 3,
+ new FlavorSpec(1, 1, 1), tester);
// Simulate expiry
NestedTransaction deactivateTransaction = new NestedTransaction();
@@ -482,10 +499,11 @@ public class ProvisioningTest {
public void out_of_capacity() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
- tester.makeReadyNodes(9, "default"); // need 2+2+3+3=10
+ tester.makeReadyNodes(9, "d-1-1-1"); // need 2+2+3+3=10
ApplicationId application = tester.makeApplicationId();
try {
- prepare(application, 2, 2, 3, 3, "default", tester);
+ prepare(application, 2, 2, 3, 3,
+ new FlavorSpec(1, 1, 1), tester);
fail("Expected exception");
}
catch (OutOfCapacityException e) {
@@ -496,7 +514,7 @@ public class ProvisioningTest {
@Test
public void out_of_capacity_but_cannot_fail() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
- tester.makeReadyNodes(4, "default");
+ tester.makeReadyNodes(4, "d-1-1-1");
ApplicationId application = tester.makeApplicationId();
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content,
ClusterSpec.Id.from("music"),
@@ -514,11 +532,12 @@ public class ProvisioningTest {
tester.makeReadyNodes( 9, "large"); // need 2+2+3+3=10
ApplicationId application = tester.makeApplicationId();
try {
- prepare(application, 2, 2, 3, 3, "large", tester);
+ prepare(application, 2, 2, 3, 3,
+ FlavorSpec.fromLegacyFlavorName("large"), tester);
fail("Expected exception");
}
catch (OutOfCapacityException e) {
- assertTrue(e.getMessage().startsWith("Could not satisfy request for 3 nodes of flavor 'large'"));
+ assertTrue(e.getMessage().startsWith("Could not satisfy request for 3 nodes with flavor 'large'"));
}
}
@@ -538,8 +557,8 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
try {
- prepare(application, 2, 0, 2, 0, flavorToRetire,
- tester);
+ prepare(application, 2, 0, 2, 0,
+ FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
fail("Expected exception");
} catch (OutOfCapacityException e) {
assertTrue(e.getMessage().startsWith("Could not satisfy request"));
@@ -552,11 +571,12 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
// Flag all nodes for retirement
- List<Node> readyNodes = tester.makeReadyNodes(5, "default");
+ List<Node> readyNodes = tester.makeReadyNodes(5, "d-1-1-1");
readyNodes.forEach(node -> tester.patchNode(node.with(node.status().withWantToRetire(true))));
try {
- prepare(application, 2, 0, 2, 0, "default", tester);
+ prepare(application, 2, 0, 2, 0,
+ new FlavorSpec(1, 1, 1), tester);
fail("Expected exception");
} catch (OutOfCapacityException e) {
assertTrue(e.getMessage().startsWith("Could not satisfy request"));
@@ -569,7 +589,8 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
try {
- prepare(application, 2, 2, 3, 3, "nonexisting", tester);
+ prepare(application, 2, 2, 3, 3,
+ FlavorSpec.fromLegacyFlavorName("nonexisting"), tester);
fail("Expected exception");
}
catch (IllegalArgumentException e) {
@@ -583,14 +604,14 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyNodes(14, "default");
+ tester.makeReadyNodes(14, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 3, 3, 4, 4, "default", tester);
+ SystemState state1 = prepare(application1, 3, 3, 4, 4, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// decrease cluster sizes
- SystemState state2 = prepare(application1, 2, 2, 2, 2, "default", tester);
+ SystemState state2 = prepare(application1, 2, 2, 2, 2, new FlavorSpec(1, 1, 1), tester);
tester.activate(application1, state2.allHosts);
// content0
@@ -608,12 +629,12 @@ public class ProvisioningTest {
@Test
public void application_deployment_prefers_cheapest_stock_nodes() {
- assertCorrectFlavorPreferences(true);
+ assertCorrectBareMetalFlavorPreferences(true);
}
@Test
public void application_deployment_prefers_exact_nonstock_nodes() {
- assertCorrectFlavorPreferences(false);
+ assertCorrectBareMetalFlavorPreferences(false);
}
@Test
@@ -636,7 +657,7 @@ public class ProvisioningTest {
.flavorsConfig(b.build()).curator(curator).nameResolver(nameResolver).build();
tester.makeReadyNodes(4, flavorToRetire);
SystemState state = prepare(application, 2, 0, 2, 0,
- flavorToRetire, tester);
+ FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
tester.activate(application, state.allHosts);
}
@@ -656,7 +677,7 @@ public class ProvisioningTest {
tester.makeReadyNodes(4, replacementFlavor);
SystemState state = prepare(application, 2, 0, 2, 0,
- flavorToRetire, tester);
+ FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
tester.activate(application, state.allHosts);
@@ -687,7 +708,7 @@ public class ProvisioningTest {
tester.makeReadyNodes(4, replacementFlavor);
SystemState state = prepare(application, 2, 0, 2, 0,
- flavorToRetire, tester);
+ FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
tester.activate(application, state.allHosts);
@@ -701,12 +722,12 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(10, "default");
+ tester.makeReadyNodes(10, "d-1-1-1");
// Deploy application
{
SystemState state = prepare(application, 2, 0, 2, 0,
- "default", tester);
+ new FlavorSpec(1, 1, 1), tester);
tester.activate(application, state.allHosts);
assertEquals(4, tester.getNodes(application, Node.State.active).size());
}
@@ -716,7 +737,7 @@ public class ProvisioningTest {
List<Node> nodesToRetire = tester.getNodes(application, Node.State.active).asList().subList(0, 2);
nodesToRetire.forEach(node -> tester.patchNode(node.with(node.status().withWantToRetire(true))));
- SystemState state = prepare(application, 2, 0, 2, 0, "default", tester);
+ SystemState state = prepare(application, 2, 0, 2, 0, new FlavorSpec(1, 1, 1), tester);
tester.activate(application, state.allHosts);
List<Node> retiredNodes = tester.getNodes(application).retired().asList();
@@ -730,24 +751,24 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyNodes(2, "default");
+ tester.makeReadyNodes(2, "d-1-1-1");
// Deploy fails with out of capacity
try {
prepare(application, 2, 0, 2, 0,
- "default", tester);
+ new FlavorSpec(1, 1, 1), tester);
fail("Expected exception");
} catch (OutOfCapacityException ignored) {}
assertEquals("Reserved a subset of required nodes", 2,
tester.getNodes(application, Node.State.reserved).size());
// Enough nodes become available
- tester.makeReadyNodes(2, "default");
+ tester.makeReadyNodes(2, "d-1-1-1");
// Deploy is retried after a few minutes
tester.clock().advance(Duration.ofMinutes(2));
SystemState state = prepare(application, 2, 0, 2, 0,
- "default", tester);
+ new FlavorSpec(1, 1, 1), tester);
List<Node> reserved = tester.getNodes(application, Node.State.reserved).asList();
assertEquals("Reserved required nodes", 4, reserved.size());
assertTrue("Time of event is updated for all nodes",
@@ -774,12 +795,12 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
try {
- prepare(application, 1, 0, 1, 0, true, "default", Version.fromString("6.42"), tester);
+ prepare(application, 1, 0, 1, 0, true, new FlavorSpec(1, 1, 1), Version.fromString("6.42"), tester);
fail("Expected exception");
} catch (IllegalArgumentException ignored) {}
}
- private void assertCorrectFlavorPreferences(boolean largeIsStock) {
+ private void assertCorrectBareMetalFlavorPreferences(boolean largeIsStock) {
FlavorConfigBuilder b = new FlavorConfigBuilder();
b.addFlavor("large", 4., 8., 100, Flavor.Type.BARE_METAL).cost(10).stock(largeIsStock);
FlavorsConfig.Flavor.Builder largeVariant = b.addFlavor("large-variant", 3., 9., 101, Flavor.Type.BARE_METAL).cost(9);
@@ -797,8 +818,10 @@ public class ProvisioningTest {
ClusterSpec contentClusterSpec = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.42"), false, Collections.emptySet());
ClusterSpec containerClusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer"), Version.fromString("6.42"), false, Collections.emptySet());
- List<HostSpec> containerNodes = tester.prepare(applicationId, containerClusterSpec, 5, 1, "large");
- List<HostSpec> contentNodes = tester.prepare(applicationId, contentClusterSpec, 10, 1, "large");
+ List<HostSpec> containerNodes = tester.prepare(applicationId, containerClusterSpec, 5, 1,
+ FlavorSpec.fromLegacyFlavorName("large"));
+ List<HostSpec> contentNodes = tester.prepare(applicationId, contentClusterSpec, 10, 1,
+ FlavorSpec.fromLegacyFlavorName("large"));
if (largeIsStock) { // 'large' is replaced by 'large-variant' when possible, as it is cheaper
tester.assertNumberOfNodesWithFlavor(containerNodes, "large-variant", 5);
@@ -815,19 +838,19 @@ public class ProvisioningTest {
}
private SystemState prepare(ApplicationId application, int container0Size, int container1Size, int content0Size,
- int content1Size, String flavor, ProvisioningTester tester) {
+ int content1Size, FlavorSpec flavor, ProvisioningTester tester) {
return prepare(application, container0Size, container1Size, content0Size, content1Size, flavor,
Version.fromString("6.42"), tester);
}
private SystemState prepare(ApplicationId application, int container0Size, int container1Size, int content0Size,
- int content1Size, String flavor, Version wantedVersion, ProvisioningTester tester) {
+ int content1Size, FlavorSpec flavor, Version wantedVersion, ProvisioningTester tester) {
return prepare(application, container0Size, container1Size, content0Size, content1Size, false, flavor,
wantedVersion, tester);
}
private SystemState prepare(ApplicationId application, int container0Size, int container1Size, int content0Size,
- int content1Size, boolean required, String flavor, Version wantedVersion,
+ int content1Size, boolean required, FlavorSpec flavor, Version wantedVersion,
ProvisioningTester tester) {
// "deploy prepare" with a two container clusters and a storage cluster having of two groups
ClusterSpec containerCluster0 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("container0"), wantedVersion, false, Collections.emptySet());
@@ -870,7 +893,7 @@ public class ProvisioningTest {
}
private Set<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups,
- boolean required, String flavor, ProvisioningTester tester) {
+ boolean required, FlavorSpec flavor, ProvisioningTester tester) {
if (nodeCount == 0) return Collections.emptySet(); // this is a shady practice
return new HashSet<>(tester.prepare(application, cluster, nodeCount, groups, required, flavor));
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
index 8e41ddc0c0c..6f026181510 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
@@ -129,12 +130,12 @@ public class ProvisioningTester {
public void patchNode(Node node) { nodeRepository.write(node); }
- public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, String flavor) {
+ public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, FlavorSpec flavor) {
return prepare(application, cluster, nodeCount, groups, false, flavor);
}
- public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, boolean required, String flavor) {
- return prepare(application, cluster, Capacity.fromNodeCount(nodeCount, Optional.ofNullable(flavor), required, true), groups);
+ public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, boolean required, FlavorSpec flavor) {
+ return prepare(application, cluster, Capacity.fromCount(nodeCount, Optional.ofNullable(flavor), required, true), groups);
}
public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, Capacity capacity, int groups) {
@@ -234,7 +235,7 @@ public class ProvisioningTester {
return makeProvisionedNodes(count, flavor, type, ipAddressPoolSize, false);
}
- public List<Node> makeProvisionedNodes(int n, String flavor, NodeType type, int ipAddressPoolSize, boolean dualStack) {
+ public List<Node> makeProvisionedNodes(int n, String flavorName, NodeType type, int ipAddressPoolSize, boolean dualStack) {
List<Node> nodes = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
@@ -271,6 +272,13 @@ public class ProvisioningTester {
nameResolver.addRecord(String.format("node-%d-of-%s", poolIp, hostname), ipv4Addr);
}
}
+ Optional<Flavor> flavor = nodeFlavors.getFlavor(flavorName);
+ if (flavor.isEmpty()) {
+ if (type == NodeType.tenant) // Tenant nodes can have any (docker) flavor
+ flavor = Optional.of(new Flavor(FlavorSpec.fromLegacyFlavorName(flavorName)));
+ else
+ throw new IllegalArgumentException("No flavor '" + flavorName + "'");
+ }
nodes.add(nodeRepository.createNode(hostname,
hostname,
@@ -278,7 +286,7 @@ public class ProvisioningTester {
ipAddressPool,
Optional.empty(),
Optional.empty(),
- nodeFlavors.getFlavorOrThrow(flavor),
+ flavor.get(),
type));
}
nodes = nodeRepository.addNodes(nodes);
@@ -328,37 +336,37 @@ public class ProvisioningTester {
}
/** Creates a set of virtual docker hosts */
- public List<Node> makeReadyVirtualDockerHosts(int n, String flavor) {
+ public List<Node> makeReadyVirtualDockerHosts(int n, FlavorSpec flavor) {
return makeReadyVirtualNodes(n, 1, flavor, Optional.empty(),
i -> "dockerHost" + i, NodeType.host);
}
/** Creates a set of virtual docker nodes on a single docker host starting with index 1 and increasing */
- public List<Node> makeReadyVirtualDockerNodes(int n, String flavor, String dockerHostId) {
+ public List<Node> makeReadyVirtualDockerNodes(int n, FlavorSpec flavor, String dockerHostId) {
return makeReadyVirtualNodes(n, 1, flavor, Optional.of(dockerHostId),
i -> String.format("%s-%03d", dockerHostId, i), NodeType.tenant);
}
/** Creates a single of virtual docker node on a single parent host */
- public List<Node> makeReadyVirtualDockerNode(int index, String flavor, String dockerHostId) {
+ public List<Node> makeReadyVirtualDockerNode(int index, FlavorSpec flavor, String dockerHostId) {
return makeReadyVirtualNodes(1, index, flavor, Optional.of(dockerHostId),
i -> String.format("%s-%03d", dockerHostId, i), NodeType.tenant);
}
/** Creates a set of virtual nodes without a parent host */
- public List<Node> makeReadyVirtualNodes(int n, String flavor) {
+ public List<Node> makeReadyVirtualNodes(int n, FlavorSpec flavor) {
return makeReadyVirtualNodes(n, 0, flavor, Optional.empty(),
i -> UUID.randomUUID().toString(), NodeType.tenant);
}
/** Creates a set of virtual nodes on a single parent host */
- private List<Node> makeReadyVirtualNodes(int count, int startIndex, String flavor, Optional<String> parentHostId,
+ private List<Node> makeReadyVirtualNodes(int count, int startIndex, FlavorSpec flavor, Optional<String> parentHostId,
Function<Integer, String> nodeNamer, NodeType nodeType) {
List<Node> nodes = new ArrayList<>(count);
for (int i = startIndex; i < count + startIndex; i++) {
String hostname = nodeNamer.apply(i);
nodes.add(nodeRepository.createNode("openstack-id", hostname, parentHostId,
- nodeFlavors.getFlavorOrThrow(flavor), nodeType));
+ new Flavor(flavor), nodeType));
}
nodes = nodeRepository.addNodes(nodes);
nodes = nodeRepository.setDirty(nodes, Agent.system, getClass().getSimpleName());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
index 0d9ce179d5c..5482731bfb6 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
@@ -5,6 +5,7 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.FlavorSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.OutOfCapacityException;
import com.yahoo.config.provision.RegionName;
@@ -34,7 +35,7 @@ import static org.junit.Assert.assertNotNull;
// to remove these tests
public class VirtualNodeProvisioningTest {
- private static final String flavor = "v-4-8-100";
+ private static final FlavorSpec flavor = new FlavorSpec(4, 8, 100);
private static final ClusterSpec contentClusterSpec = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.42"), false, Collections.emptySet());
private static final ClusterSpec containerClusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer"), Version.fromString("6.42"), false, Collections.emptySet());
@@ -63,13 +64,13 @@ public class VirtualNodeProvisioningTest {
// Go down to 3 nodes in container cluster
List<HostSpec> containerHosts2 = prepare(containerClusterSpec, containerNodeCount - 1, groups);
activate(containerHosts2);
- final List<Node> nodes2 = getNodes(applicationId);
+ List<Node> nodes2 = getNodes(applicationId);
assertDistinctParentHosts(nodes2, ClusterSpec.Type.container, containerNodeCount - 1);
// Go up to 4 nodes again in container cluster
List<HostSpec> containerHosts3 = prepare(containerClusterSpec, containerNodeCount, groups);
activate(containerHosts3);
- final List<Node> nodes3 = getNodes(applicationId);
+ List<Node> nodes3 = getNodes(applicationId);
assertDistinctParentHosts(nodes3, ClusterSpec.Type.container, containerNodeCount);
}
@@ -81,11 +82,12 @@ public class VirtualNodeProvisioningTest {
// Allowed to use same parent host for several nodes in same cluster in dev
{
+ FlavorSpec flavor = new FlavorSpec(1, 1, 1);
tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
- tester.makeReadyVirtualDockerNodes(4, "default", "parentHost1");
+ tester.makeReadyVirtualDockerNodes(4, flavor, "parentHost1");
- List<HostSpec> containerHosts = prepare(containerClusterSpec, containerNodeCount, groups);
- List<HostSpec> contentHosts = prepare(contentClusterSpec, contentNodeCount, groups);
+ List<HostSpec> containerHosts = prepare(containerClusterSpec, containerNodeCount, groups, flavor);
+ List<HostSpec> contentHosts = prepare(contentClusterSpec, contentNodeCount, groups, flavor);
activate(containerHosts, contentHosts);
// downscaled to 1 node per cluster in dev, so 2 in total
@@ -251,9 +253,9 @@ public class VirtualNodeProvisioningTest {
public void unknown_distribution_with_known_and_unknown_ready_nodes() {
tester.makeReadyVirtualNodes(3, flavor);
- final int contentNodeCount = 3;
- final int groups = 1;
- final List<HostSpec> contentHosts = prepare(contentClusterSpec, contentNodeCount, groups);
+ int contentNodeCount = 3;
+ int groups = 1;
+ List<HostSpec> contentHosts = prepare(contentClusterSpec, contentNodeCount, groups);
activate(contentHosts);
assertEquals(3, getNodes(applicationId).size());
@@ -293,6 +295,10 @@ public class VirtualNodeProvisioningTest {
return tester.prepare(applicationId, clusterSpec, nodeCount, groups, flavor);
}
+ private List<HostSpec> prepare(ClusterSpec clusterSpec, int nodeCount, int groups, FlavorSpec flavor) {
+ return tester.prepare(applicationId, clusterSpec, nodeCount, groups, flavor);
+ }
+
@SafeVarargs
private final void activate(List<HostSpec>... hostLists) {
HashSet<HostSpec> hosts = new HashSet<>();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
index 75995245274..d75cdaa3a2b 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
@@ -798,7 +798,7 @@ public class RestApiTest {
return "{\"hostname\":\"" + hostname + "\", \"parentHostname\":\"" + parentHostname + "\"," +
createIpAddresses(ipAddress) +
createAdditionalIpAddresses(additionalIpCount) +
- "\"openStackId\":\"" + hostname + "\",\"flavor\":\"docker\"}";
+ "\"openStackId\":\"" + hostname + "\",\"flavor\":\"d-1-1-100\"}";
}
private String asNodeJson(String hostname, String flavor, String... ipAddress) {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/docker-container1.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/docker-container1.json
index c98fbb46ff8..86565780cfe 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/docker-container1.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/docker-container1.json
@@ -6,14 +6,13 @@
"hostname": "test-container-1",
"parentHostname": "dockerhost3.yahoo.com",
"openStackId": "fake-test-container-1",
- "flavor": "docker",
- "canonicalFlavor": "docker",
+ "flavor": "d-1-1-100",
+ "canonicalFlavor": "d-1-1-100",
"minDiskAvailableGb": 100.0,
- "minMainMemoryAvailableGb": 0.5,
- "description": "Flavor-name-is-docker",
- "minCpuCores": 0.2,
+ "minMainMemoryAvailableGb": 1.0,
+ "minCpuCores": 1.0,
"fastDisk": true,
- "bandwidth":0.0,
+ "bandwidth":1.0,
"environment": "DOCKER_CONTAINER",
"owner": {
"tenant": "tenant3",
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node11.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node11.json
index b1329eebb2d..40e34891545 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node11.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node11.json
@@ -6,14 +6,13 @@
"hostname": "host11.yahoo.com",
"parentHostname": "parent.host.yahoo.com",
"openStackId": "host11.yahoo.com",
- "flavor": "docker",
- "canonicalFlavor": "docker",
+ "flavor": "d-1-1-100",
+ "canonicalFlavor": "d-1-1-100",
"minDiskAvailableGb": 100.0,
- "minMainMemoryAvailableGb": 0.5,
- "description": "Flavor-name-is-docker",
- "minCpuCores": 0.2,
+ "minMainMemoryAvailableGb": 1.0,
+ "minCpuCores": 1.0,
"fastDisk": true,
- "bandwidth":0.0,
+ "bandwidth":1.0,
"environment": "DOCKER_CONTAINER",
"rebootGeneration": 0,
"currentRebootGeneration": 0,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json
index a02035efd88..9a3c45c709f 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json
@@ -6,14 +6,13 @@
"hostname": "host4.yahoo.com",
"parentHostname": "dockerhost1.yahoo.com",
"openStackId": "node4",
- "flavor": "docker",
- "canonicalFlavor": "docker",
+ "flavor": "d-1-1-100",
+ "canonicalFlavor": "d-1-1-100",
"minDiskAvailableGb": 100.0,
- "minMainMemoryAvailableGb": 0.5,
- "description": "Flavor-name-is-docker",
- "minCpuCores": 0.2,
+ "minMainMemoryAvailableGb": 1.0,
+ "minCpuCores": 1.0,
"fastDisk": true,
- "bandwidth":0.0,
+ "bandwidth":1.0,
"environment": "DOCKER_CONTAINER",
"owner": {
"tenant": "tenant3",
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5-after-changes.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5-after-changes.json
index 8eb3a74ce2a..f7b920490a6 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5-after-changes.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5-after-changes.json
@@ -6,14 +6,13 @@
"hostname": "host5.yahoo.com",
"parentHostname": "dockerhost2.yahoo.com",
"openStackId": "node5",
- "flavor": "docker",
- "canonicalFlavor": "docker",
+ "flavor": "d-1-1-100",
+ "canonicalFlavor": "d-1-1-100",
"minDiskAvailableGb": 100.0,
- "minMainMemoryAvailableGb": 0.5,
- "description": "Flavor-name-is-docker",
- "minCpuCores": 0.2,
+ "minMainMemoryAvailableGb": 1.0,
+ "minCpuCores": 1.0,
"fastDisk": true,
- "bandwidth":0.0,
+ "bandwidth": 1.0,
"environment": "DOCKER_CONTAINER",
"rebootGeneration": 1,
"currentRebootGeneration": 0,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json
index a14443e096d..4376b27cd5a 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json
@@ -6,14 +6,13 @@
"hostname": "host5.yahoo.com",
"parentHostname": "dockerhost2.yahoo.com",
"openStackId": "node5",
- "flavor": "docker",
- "canonicalFlavor": "docker",
+ "flavor": "d-1-1-100",
+ "canonicalFlavor": "d-1-1-100",
"minDiskAvailableGb": 100.0,
- "minMainMemoryAvailableGb": 0.5,
- "description": "Flavor-name-is-docker",
- "minCpuCores": 0.2,
+ "minMainMemoryAvailableGb": 1.0,
+ "minCpuCores": 1.0,
"fastDisk": true,
- "bandwidth":0.0,
+ "bandwidth": 1.0,
"environment": "DOCKER_CONTAINER",
"rebootGeneration": 1,
"currentRebootGeneration": 0,