summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java48
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java63
-rw-r--r--config-model/src/main/resources/schema/common.rnc9
-rw-r--r--config-model/src/main/resources/schema/containercluster.rnc1
-rw-r--r--config-model/src/main/resources/schema/content.rnc1
-rw-r--r--config-model/src/main/resources/schema/docproc.rnc1
-rw-r--r--config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java4
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java21
-rw-r--r--config-model/src/test/schema-test-files/services-hosted.xml8
-rw-r--r--config-provisioning/abi-spec.json49
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java30
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java39
-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.java6
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/NodeResources.java106
-rw-r--r--document/src/main/java/com/yahoo/document/StructDataType.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeList.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java35
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java19
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java5
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java16
-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.java40
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ResourceCapacity.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java12
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirerTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java7
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java14
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java22
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java10
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java137
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java18
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/docker-container1.json4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node11.json4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5-after-changes.json4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json4
44 files changed, 521 insertions, 397 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java
index c744c509b9a..2439475e95c 100644
--- a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java
+++ b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.HostSpec;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.ProvisionLogger;
import java.util.ArrayList;
@@ -42,42 +43,47 @@ public class InMemoryProvisioner implements HostProvisioner {
/** Hosts which should be returned as retired */
private final Set<String> retiredHostNames;
- /** Free hosts of each flavor */
- private final ListMap<String, Host> freeNodes = new ListMap<>();
+ /** Free hosts of each resource size */
+ private final ListMap<NodeResources, Host> freeNodes = new ListMap<>();
private final Map<String, HostSpec> legacyMapping = new LinkedHashMap<>();
private final Map<ClusterSpec, List<HostSpec>> allocations = new LinkedHashMap<>();
/** Indexes must be unique across all groups in a cluster */
- private final Map<Pair<ClusterSpec.Type,ClusterSpec.Id>, Integer> nextIndexInCluster = new HashMap<>();
+ private final Map<Pair<ClusterSpec.Type, ClusterSpec.Id>, Integer> nextIndexInCluster = new HashMap<>();
/** Use this index as start index for all clusters */
private final int startIndexForClusters;
/** Creates this with a number of nodes of the flavor 'default' */
public InMemoryProvisioner(int nodeCount) {
- this(Collections.singletonMap("default", createHostInstances(nodeCount)), true, 0);
+ this(Collections.singletonMap(NodeResources.fromLegacyName("default"),
+ createHostInstances(nodeCount)), true, 0);
}
/** Creates this with a set of host names of the flavor 'default' */
public InMemoryProvisioner(boolean failOnOutOfCapacity, String... hosts) {
- this(Collections.singletonMap("default", toHostInstances(hosts)), failOnOutOfCapacity, 0);
+ this(Collections.singletonMap(NodeResources.fromLegacyName("default"),
+ toHostInstances(hosts)), failOnOutOfCapacity, 0);
}
/** Creates this with a set of hosts of the flavor 'default' */
public InMemoryProvisioner(Hosts hosts, boolean failOnOutOfCapacity, String ... retiredHostNames) {
- this(Collections.singletonMap("default", hosts.asCollection()), failOnOutOfCapacity, 0, retiredHostNames);
+ this(Collections.singletonMap(NodeResources.fromLegacyName("default"),
+ hosts.asCollection()), failOnOutOfCapacity, 0, retiredHostNames);
}
/** Creates this with a set of hosts of the flavor 'default' */
public InMemoryProvisioner(Hosts hosts, boolean failOnOutOfCapacity, int startIndexForClusters, String ... retiredHostNames) {
- this(Collections.singletonMap("default", hosts.asCollection()), failOnOutOfCapacity, startIndexForClusters, retiredHostNames);
+ this(Collections.singletonMap(NodeResources.fromLegacyName("default"),
+ hosts.asCollection()), failOnOutOfCapacity, startIndexForClusters, retiredHostNames);
}
- public InMemoryProvisioner(Map<String, Collection<Host>> hosts, boolean failOnOutOfCapacity, int startIndexForClusters, String ... retiredHostNames) {
+ public InMemoryProvisioner(Map<NodeResources, Collection<Host>> hosts, boolean failOnOutOfCapacity,
+ int startIndexForClusters, String ... retiredHostNames) {
this.failOnOutOfCapacity = failOnOutOfCapacity;
- for (Map.Entry<String, Collection<Host>> hostsOfFlavor : hosts.entrySet())
- for (Host host : hostsOfFlavor.getValue())
- freeNodes.put(hostsOfFlavor.getKey(), host);
+ for (Map.Entry<NodeResources, Collection<Host>> hostsWithResources : hosts.entrySet())
+ for (Host host : hostsWithResources.getValue())
+ freeNodes.put(hostsWithResources.getKey(), host);
this.retiredHostNames = new HashSet<>(Arrays.asList(retiredHostNames));
this.startIndexForClusters = startIndexForClusters;
}
@@ -104,9 +110,9 @@ public class InMemoryProvisioner implements HostProvisioner {
@Override
public HostSpec allocateHost(String alias) {
if (legacyMapping.containsKey(alias)) return legacyMapping.get(alias);
- List<Host> defaultHosts = freeNodes.get("default");
+ List<Host> defaultHosts = freeNodes.get(NodeResources.fromLegacyName("default"));
if (defaultHosts.isEmpty()) throw new IllegalArgumentException("No more hosts of default flavor available");
- Host newHost = freeNodes.removeValue("default", 0);
+ Host newHost = freeNodes.removeValue(NodeResources.fromLegacyName("default"), 0);
HostSpec hostSpec = new HostSpec(newHost.hostname(), newHost.aliases(), newHost.flavor(), Optional.empty(), newHost.version());
legacyMapping.put(alias, hostSpec);
return hostSpec;
@@ -122,16 +128,16 @@ public class InMemoryProvisioner implements HostProvisioner {
int capacity = failOnOutOfCapacity || requestedCapacity.isRequired()
? requestedCapacity.nodeCount()
- : Math.min(requestedCapacity.nodeCount(), freeNodes.get("default").size() + totalAllocatedTo(cluster));
+ : Math.min(requestedCapacity.nodeCount(), freeNodes.get(NodeResources.fromLegacyName("default")).size() + totalAllocatedTo(cluster));
if (groups > capacity)
groups = capacity;
- String flavor = requestedCapacity.flavor().orElse("default");
+ NodeResources nodeResources = requestedCapacity.nodeResources().orElse(NodeResources.fromLegacyName("default"));
List<HostSpec> allocation = new ArrayList<>();
if (groups == 1) {
allocation.addAll(allocateHostGroup(cluster.with(Optional.of(ClusterSpec.Group.from(0))),
- flavor,
+ nodeResources,
capacity,
startIndexForClusters,
requestedCapacity.canFail()));
@@ -139,7 +145,7 @@ public class InMemoryProvisioner implements HostProvisioner {
else {
for (int i = 0; i < groups; i++) {
allocation.addAll(allocateHostGroup(cluster.with(Optional.of(ClusterSpec.Group.from(i))),
- flavor,
+ nodeResources,
capacity / groups,
allocation.size(),
requestedCapacity.canFail()));
@@ -161,19 +167,19 @@ public class InMemoryProvisioner implements HostProvisioner {
host.version());
}
- private List<HostSpec> allocateHostGroup(ClusterSpec clusterGroup, String flavor, int nodesInGroup, int startIndex, boolean canFail) {
+ private List<HostSpec> allocateHostGroup(ClusterSpec clusterGroup, NodeResources nodeResources, int nodesInGroup, int startIndex, boolean canFail) {
List<HostSpec> allocation = allocations.getOrDefault(clusterGroup, new ArrayList<>());
allocations.put(clusterGroup, allocation);
int nextIndex = nextIndexInCluster.getOrDefault(new Pair<>(clusterGroup.type(), clusterGroup.id()), startIndex);
while (allocation.size() < nodesInGroup) {
- if (freeNodes.get(flavor).isEmpty()) {
+ if (freeNodes.get(nodeResources).isEmpty()) {
if (canFail)
- throw new IllegalArgumentException("Insufficient capacity of flavor '" + flavor + "'");
+ throw new IllegalArgumentException("Insufficient capacity of for " + nodeResources);
else
break;
}
- Host newHost = freeNodes.removeValue(flavor, 0);
+ Host newHost = freeNodes.removeValue(nodeResources, 0);
ClusterMembership membership = ClusterMembership.from(clusterGroup, nextIndex++);
allocation.add(new HostSpec(newHost.hostname(), newHost.aliases(), newHost.flavor(), Optional.of(membership), newHost.version()));
}
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 1f649b122fa..d34a11abdf4 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
@@ -176,6 +176,14 @@ public class ModelElement {
return xml.getAttribute(name);
}
+ /** Returns the content of the attribute with the given name or throws IllegalArgumentException if not present */
+ public String requiredStringAttribute(String name) {
+ if (stringAttribute(name) == null)
+ throw new IllegalArgumentException("Required attribute '" + name + "' is missing");
+ return stringAttribute(name);
+ }
+
+
public List<ModelElement> subElements(String name) {
List<Element> elements = XML.getChildren(xml, name);
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 1031ae7b787..7864623f251 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,7 +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.NodeResources;
import com.yahoo.config.provision.RotationName;
import com.yahoo.vespa.model.HostResource;
import com.yahoo.vespa.model.HostSystem;
@@ -44,15 +44,15 @@ public class NodesSpecification {
private final boolean exclusive;
- /** The flavor the nodes should have, or empty to use the default */
- private final Optional<FlavorSpec> flavor;
+ /** The resources each node should have, or empty to use the default */
+ private final Optional<NodeResources> resources;
/** 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<FlavorSpec> flavor, Optional<String> dockerImage) {
+ Optional<NodeResources> resources, Optional<String> dockerImage) {
this.dedicated = dedicated;
this.count = count;
this.groups = groups;
@@ -60,7 +60,7 @@ public class NodesSpecification {
this.required = required;
this.canFail = canFail;
this.exclusive = exclusive;
- this.flavor = flavor;
+ this.resources = resources;
this.dockerImage = dockerImage;
}
@@ -170,28 +170,65 @@ public class NodesSpecification {
DeployLogger logger,
Set<RotationName> rotations) {
ClusterSpec cluster = ClusterSpec.request(clusterType, clusterId, version, exclusive, rotations);
- return hostSystem.allocateHosts(cluster, Capacity.fromCount(count, flavor, required, canFail), groups, logger);
+ return hostSystem.allocateHosts(cluster, Capacity.fromCount(count, resources, required, canFail), groups, logger);
}
- private static Optional<FlavorSpec> getFlavor(ModelElement nodesElement) {
- ModelElement flavor = nodesElement.child("flavor");
+ private static Optional<NodeResources> getFlavor(ModelElement nodesElement) {
+ ModelElement flavor = nodesElement.child("resources");
if (flavor != null) {
- return Optional.of(new FlavorSpec(flavor.requiredDoubleAttribute("cpus"),
- flavor.requiredDoubleAttribute("memory"),
- flavor.requiredDoubleAttribute("disk")));
+ return Optional.of(new NodeResources(flavor.requiredDoubleAttribute("vcpu"),
+ parseGbAmount(flavor.requiredStringAttribute("memory")),
+ parseGbAmount(flavor.requiredStringAttribute("disk"))));
}
else if (nodesElement.stringAttribute("flavor") != null) { // legacy fallback
- return Optional.of(FlavorSpec.fromLegacyFlavorName(nodesElement.stringAttribute("flavor")));
+ return Optional.of(NodeResources.fromLegacyName(nodesElement.stringAttribute("flavor")));
}
else { // Get the default
return Optional.empty();
}
}
+ private static double parseGbAmount(String byteAmount) {
+ byteAmount = byteAmount.strip();
+ byteAmount = byteAmount.toUpperCase();
+ if (byteAmount.endsWith("B"))
+ byteAmount = byteAmount.substring(0, byteAmount.length() -1);
+
+ double multiplier = 1/1000^3;
+ if (byteAmount.endsWith("K"))
+ multiplier = 1/1000^2;
+ else if (byteAmount.endsWith("M"))
+ multiplier = 1/1000;
+ else if (byteAmount.endsWith("G"))
+ multiplier = 1;
+ else if (byteAmount.endsWith("T"))
+ multiplier = 1000;
+ else if (byteAmount.endsWith("P"))
+ multiplier = 1000^2;
+ else if (byteAmount.endsWith("E"))
+ multiplier = 1000^3;
+ else if (byteAmount.endsWith("Z"))
+ multiplier = 1000^4;
+ else if (byteAmount.endsWith("Y"))
+ multiplier = 1000^5;
+ else
+ throw new IllegalArgumentException("Invalid byte amount '" + byteAmount +
+ "': Must end with k, M, G, T, P, E, Z or Y");
+
+ byteAmount = byteAmount.substring(0, byteAmount.length() -1 ).strip();
+ try {
+ return Double.parseDouble(byteAmount) * multiplier;
+ }
+ catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid byte amount '" + byteAmount +
+ "': Must be a floating point number followed by k, M, G, T, P, E, Z or Y");
+ }
+ }
+
@Override
public String toString() {
return "specification of " + count + (dedicated ? " dedicated " : " ") + "nodes" +
- (flavor.isPresent() ? " of flavor " + flavor.get() : "") +
+ (resources.isPresent() ? " with resources " + resources.get() : "") +
(groups > 1 ? " in " + groups + " groups" : "");
}
diff --git a/config-model/src/main/resources/schema/common.rnc b/config-model/src/main/resources/schema/common.rnc
index 73882da2b01..59b40f433b5 100644
--- a/config-model/src/main/resources/schema/common.rnc
+++ b/config-model/src/main/resources/schema/common.rnc
@@ -19,7 +19,14 @@ JavaId = xsd:string { pattern = "([a-zA-Z_$][a-zA-Z\d_$]*\.)*[a-zA-Z_$][a-zA-Z\d
Nodes = element nodes {
attribute count { xsd:positiveInteger } &
attribute flavor { xsd:string }? &
- attribute docker-image { xsd:string }?
+ attribute docker-image { xsd:string }? &
+ Resources?
+}
+
+Resources = element resources {
+ attribute vcpu { xsd:double { minExclusive = "0.0" } } &
+ attribute memory { xsd:string } &
+ attribute disk { xsd:string }
}
OptionalDedicatedNodes = element nodes {
diff --git a/config-model/src/main/resources/schema/containercluster.rnc b/config-model/src/main/resources/schema/containercluster.rnc
index 6bc54c433f3..d3a3b26c635 100644
--- a/config-model/src/main/resources/schema/containercluster.rnc
+++ b/config-model/src/main/resources/schema/containercluster.rnc
@@ -215,6 +215,7 @@ NodesOfContainerCluster = element nodes {
attribute preload { text }? &
attribute allocated-memory { text }? &
attribute cpu-socket-affinity { xsd:boolean }? &
+ Resources? &
element environment-variables {
anyElement +
} ? &
diff --git a/config-model/src/main/resources/schema/content.rnc b/config-model/src/main/resources/schema/content.rnc
index c23f99518cb..0686708a8a1 100644
--- a/config-model/src/main/resources/schema/content.rnc
+++ b/config-model/src/main/resources/schema/content.rnc
@@ -208,6 +208,7 @@ ContentNode = element node {
}
ContentNodes = element nodes {
+ Resources? &
attribute cpu-socket-affinity { xsd:string }? &
attribute mmap-core-limit { xsd:nonNegativeInteger }? &
attribute core-on-oom { xsd:boolean }? &
diff --git a/config-model/src/main/resources/schema/docproc.rnc b/config-model/src/main/resources/schema/docproc.rnc
index b5bd85ba095..3ee249c89d4 100644
--- a/config-model/src/main/resources/schema/docproc.rnc
+++ b/config-model/src/main/resources/schema/docproc.rnc
@@ -37,6 +37,7 @@ ClusterV3 = element cluster {
DocprocClusterAttributes? &
element nodes {
+ Resources? &
attribute jvmargs { text }? &
attribute preload { text }? &
element node {
diff --git a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java
index 6c9b9fdc084..06c9f78456c 100644
--- a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java
+++ b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java
@@ -704,7 +704,7 @@ public class ModelProvisioningTest {
}
@Test
- public void testSlobroksClustersAreExpandedToIncludeRetiredNodesWhenRetiredComesLast() throws ParseException {
+ public void testSlobroksClustersAreExpandedToIncludeRetiredNodesWhenRetiredComesLast() {
String services =
"<?xml version='1.0' encoding='utf-8' ?>\n" +
"<services>" +
@@ -718,7 +718,7 @@ public class ModelProvisioningTest {
VespaModelTester tester = new VespaModelTester();
tester.addHosts(numberOfHosts);
VespaModel model = tester.createModel(services, true, "default09", "default08");
- assertThat(model.getRoot().getHostSystem().getHosts().size(), is(numberOfHosts));
+ assertEquals(numberOfHosts, model.getRoot().getHostSystem().getHosts().size());
// Check slobroks clusters
assertEquals("Includes retired node", 3+2, model.getAdmin().getSlobroks().size());
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java
index 801e138f3c7..866c4027711 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java
@@ -14,6 +14,7 @@ import com.yahoo.config.model.provision.InMemoryProvisioner;
import com.yahoo.config.model.provision.SingleNodeProvisioner;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.test.utils.ApplicationPackageUtils;
@@ -44,7 +45,7 @@ public class VespaModelTester {
private final ConfigModelRegistry configModelRegistry;
private boolean hosted = true;
- private Map<String, Collection<Host>> hostsByFlavor = new HashMap<>();
+ private Map<NodeResources, Collection<Host>> hostsByResources = new HashMap<>();
private ApplicationId applicationId = ApplicationId.defaultId();
private boolean useDedicatedNodeForLogserver = false;
private boolean enableMetricsProxyContainer = false;
@@ -62,24 +63,30 @@ public class VespaModelTester {
/** Adds some hosts to this system */
public Hosts addHosts(String flavor, int count) {
- return addHosts(Optional.empty(), flavor, count);
+ return addHosts(Optional.empty(), NodeResources.fromLegacyName(flavor), count);
}
public void addHosts(Flavor flavor, int count) {
- addHosts(Optional.of(flavor), flavor.name(), count);
+ addHosts(Optional.of(flavor), NodeResources.fromLegacyName(flavor.name()), count);
}
- private Hosts addHosts(Optional<Flavor> flavor, String flavorName, int count) {
+ public void addHosts(NodeResources resources, int count) {
+ addHosts(Optional.of(new Flavor(resources)), resources, count);
+ }
+
+ private Hosts addHosts(Optional<Flavor> flavor, NodeResources resources, int count) {
List<Host> hosts = new ArrayList<>();
for (int i = 0; i < count; ++i) {
// Let host names sort in the opposite order of the order the hosts are added
// This allows us to test index vs. name order selection when subsets of hosts are selected from a cluster
// (for e.g cluster controllers and slobrok nodes)
- String hostname = String.format("%s%02d", flavorName, count - i);
+ String hostname = String.format("%s%02d",
+ resources.allocateByLegacyName() ? resources.legacyName().get() : resources.toString(),
+ count - i);
hosts.add(new Host(hostname, ImmutableList.of(), flavor));
}
- this.hostsByFlavor.put(flavorName, hosts);
+ this.hostsByResources.put(resources, hosts);
if (hosts.size() > 100)
throw new IllegalStateException("The host naming scheme is nameNN. To test more than 100 hosts, change to nameNNN");
@@ -135,7 +142,7 @@ public class VespaModelTester {
ApplicationPackage appPkg = modelCreatorWithMockPkg.appPkg;
HostProvisioner provisioner = hosted ?
- new InMemoryProvisioner(hostsByFlavor, failOnOutOfCapacity, startIndexForClusters, retiredHostNames) :
+ new InMemoryProvisioner(hostsByResources, failOnOutOfCapacity, startIndexForClusters, retiredHostNames) :
new SingleNodeProvisioner();
TestProperties properties = new TestProperties()
diff --git a/config-model/src/test/schema-test-files/services-hosted.xml b/config-model/src/test/schema-test-files/services-hosted.xml
index e9b1672ce7d..f7f20d003ee 100644
--- a/config-model/src/test/schema-test-files/services-hosted.xml
+++ b/config-model/src/test/schema-test-files/services-hosted.xml
@@ -7,7 +7,9 @@
</admin>
<jdisc id="container1" version="1.0">
- <nodes count="5" flavor="medium" required="true"/>
+ <nodes count="5" required="true">
+ <resources vcpu="1.2" memory="10Gb" disk="0.3 TB"/>
+ </nodes>
</jdisc>
<jdisc id="container1" version="1.0">
@@ -28,7 +30,9 @@
<content id="search" version="1.0">
<redundancy>2</redundancy>
- <nodes count="7" flavor="large" groups="12"/>
+ <nodes count="7" flavor="large" groups="12">
+ <resources vcpu="3.0" memory="32000.0Mb" disk="300 Gb"/>
+ </nodes>
</content>
</services>
diff --git a/config-provisioning/abi-spec.json b/config-provisioning/abi-spec.json
index 684b260c98c..b71aa9976a7 100644
--- a/config-provisioning/abi-spec.json
+++ b/config-provisioning/abi-spec.json
@@ -135,13 +135,13 @@
"methods": [
"public int nodeCount()",
"public java.util.Optional flavor()",
- "public java.util.Optional flavorSpec()",
+ "public java.util.Optional nodeResources()",
"public boolean isRequired()",
"public boolean canFail()",
"public com.yahoo.config.provision.NodeType type()",
"public java.lang.String toString()",
"public static com.yahoo.config.provision.Capacity fromNodeCount(int)",
- "public static com.yahoo.config.provision.Capacity fromCount(int, com.yahoo.config.provision.FlavorSpec, boolean, boolean)",
+ "public static com.yahoo.config.provision.Capacity fromCount(int, com.yahoo.config.provision.NodeResources, boolean, boolean)",
"public static com.yahoo.config.provision.Capacity fromCount(int, java.util.Optional, boolean, boolean)",
"public static com.yahoo.config.provision.Capacity fromNodeCount(int, java.util.Optional, boolean, boolean)",
"public static com.yahoo.config.provision.Capacity fromRequiredNodeType(com.yahoo.config.provision.NodeType)"
@@ -380,7 +380,7 @@
],
"methods": [
"public void <init>(com.yahoo.config.provisioning.FlavorsConfig$Flavor)",
- "public void <init>(com.yahoo.config.provision.FlavorSpec)",
+ "public void <init>(com.yahoo.config.provision.NodeResources)",
"public java.lang.String name()",
"public int cost()",
"public boolean isStock()",
@@ -400,33 +400,14 @@
"public boolean satisfies(com.yahoo.config.provision.Flavor)",
"public void freeze()",
"public boolean isLargerThan(com.yahoo.config.provision.Flavor)",
- "public com.yahoo.config.provision.FlavorSpec asSpec()",
+ "public boolean isConfigured()",
+ "public com.yahoo.config.provision.NodeResources resources()",
"public int hashCode()",
"public boolean equals(java.lang.Object)",
"public java.lang.String toString()"
],
"fields": []
},
- "com.yahoo.config.provision.FlavorSpec": {
- "superClass": "java.lang.Object",
- "interfaces": [],
- "attributes": [
- "public"
- ],
- "methods": [
- "public void <init>(double, double, double)",
- "public double cpuCores()",
- "public double memoryGb()",
- "public double diskGb()",
- "public boolean allocateByLegacyName()",
- "public java.lang.String legacyFlavorName()",
- "public boolean equals(java.lang.Object)",
- "public int hashCode()",
- "public java.lang.String toString()",
- "public static com.yahoo.config.provision.FlavorSpec fromLegacyFlavorName(java.lang.String)"
- ],
- "fields": []
- },
"com.yahoo.config.provision.HostFilter": {
"superClass": "java.lang.Object",
"interfaces": [],
@@ -590,6 +571,26 @@
],
"fields": []
},
+ "com.yahoo.config.provision.NodeResources": {
+ "superClass": "java.lang.Object",
+ "interfaces": [],
+ "attributes": [
+ "public"
+ ],
+ "methods": [
+ "public void <init>(double, double, double)",
+ "public double vcpu()",
+ "public double memoryGb()",
+ "public double diskGb()",
+ "public boolean allocateByLegacyName()",
+ "public java.util.Optional legacyName()",
+ "public boolean equals(java.lang.Object)",
+ "public int hashCode()",
+ "public java.lang.String toString()",
+ "public static com.yahoo.config.provision.NodeResources fromLegacyName(java.lang.String)"
+ ],
+ "fields": []
+ },
"com.yahoo.config.provision.NodeType": {
"superClass": "java.lang.Enum",
"interfaces": [],
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 f635b986558..60ce73be234 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,15 +17,15 @@ public final class Capacity {
private final boolean canFail;
- private final Optional<FlavorSpec> flavor;
+ private final Optional<NodeResources> nodeResources;
private final NodeType type;
- private Capacity(int nodeCount, Optional<FlavorSpec> flavor, boolean required, boolean canFail, NodeType type) {
+ private Capacity(int nodeCount, Optional<NodeResources> nodeResources, boolean required, boolean canFail, NodeType type) {
this.nodeCount = nodeCount;
this.required = required;
this.canFail = canFail;
- this.flavor = flavor;
+ this.nodeResources = nodeResources;
this.type = type;
}
@@ -33,13 +33,19 @@ public final class Capacity {
public int nodeCount() { return nodeCount; }
/**
- * The node flavor requested, or empty if no particular flavor is specified.
- * This may be satisfied by the requested flavor or a suitable replacement
+ * The node flavor requested, or empty if no legacy flavor name has been used.
+ * This may be satisfied by the requested flavor or a suitable replacement.
+ *
+ * @deprecated use nodeResources instead
*/
- public Optional<String> flavor() { return flavor.map(FlavorSpec::legacyFlavorName); }
+ @Deprecated
+ public Optional<String> flavor() {
+ if (nodeResources().isEmpty()) return Optional.empty();
+ return nodeResources.get().legacyName();
+ }
- /** Returns the capacity specified for each node, or empty to leave this decision to provisioning */
- public Optional<FlavorSpec> flavorSpec() { return flavor; }
+ /** Returns the resources requested for each node, or empty to leave this decision to provisioning */
+ public Optional<NodeResources> nodeResources() { return nodeResources; }
/** Returns whether the requested number of nodes must be met exactly for a request for this to succeed */
public boolean isRequired() { return required; }
@@ -60,7 +66,7 @@ public final class Capacity {
@Override
public String toString() {
- return nodeCount + " nodes " + ( flavor.isPresent() ? "of flavor " + flavor.get() : "(default flavor)" );
+ return nodeCount + " nodes " + (nodeResources.isPresent() ? "of flavor " + nodeResources.get() : "(default flavor)" );
}
/** Creates this from a desired node count: The request may be satisfied with a smaller number of nodes. */
@@ -68,16 +74,16 @@ public final class Capacity {
return fromNodeCount(capacity, Optional.empty(), false, true);
}
- public static Capacity fromCount(int nodeCount, FlavorSpec flavor, boolean required, boolean canFail) {
+ public static Capacity fromCount(int nodeCount, NodeResources 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) {
+ public static Capacity fromCount(int nodeCount, Optional<NodeResources> 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);
+ return new Capacity(nodeCount, flavor.map(NodeResources::fromLegacyName), required, canFail, NodeType.tenant);
}
/** Creates this from a node 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 8b6fa863af6..189d49e5c80 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
@@ -7,6 +7,7 @@ import com.yahoo.config.provisioning.FlavorsConfig;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
/**
* A host flavor (type). This is a value object where the identity is the name.
@@ -16,6 +17,11 @@ import java.util.List;
*/
public class Flavor {
+ private boolean configured;
+
+ /** The hardware resources of this flavor */
+ private NodeResources resources;
+
private final String name;
private final int cost;
private final boolean isStock;
@@ -36,6 +42,7 @@ public class Flavor {
* @param flavorConfig config to be used for Flavor.
*/
public Flavor(FlavorsConfig.Flavor flavorConfig) {
+ this.configured = true;
this.name = flavorConfig.name();
this.replacesFlavors = new ArrayList<>();
this.cost = flavorConfig.cost();
@@ -49,25 +56,28 @@ public class Flavor {
this.description = flavorConfig.description();
this.retired = flavorConfig.retired();
this.idealHeadroom = flavorConfig.idealHeadroom();
+ this.resources = new NodeResources(minCpuCores, minMainMemoryAvailableGb, minDiskAvailableGb);
}
/** 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: " +
+ public Flavor(NodeResources resources) {
+ if (resources.allocateByLegacyName())
+ throw new IllegalArgumentException("Can not create flavor '" + resources.legacyName() + "' from a flavor: " +
"Non-docker flavors must be of a configured flavor");
- this.name = spec.legacyFlavorName();
+ this.configured = false;
+ this.name = resources.legacyName().orElse(resources.toString());
this.cost = 0;
this.isStock = true;
this.type = Type.DOCKER_CONTAINER;
- this.minCpuCores = spec.cpuCores();
- this.minMainMemoryAvailableGb = spec.memoryGb();
- this.minDiskAvailableGb = spec.diskGb();
+ this.minCpuCores = resources.vcpu();
+ this.minMainMemoryAvailableGb = resources.memoryGb();
+ this.minDiskAvailableGb = resources.diskGb();
this.fastDisk = true;
this.bandwidth = 1;
this.description = "";
this.retired = false;
this.replacesFlavors = Collections.emptyList();
+ this.resources = resources;
}
/** Returns the unique identity of this flavor */
@@ -160,7 +170,7 @@ public class Flavor {
replacesFlavors = ImmutableList.copyOf(replacesFlavors);
}
- /** Returns whether this flavor has at least as much as each hardware resource as the given flavor */
+ /** Returns whether this flavor has at least as much of each hardware resource as the given flavor */
public boolean isLargerThan(Flavor other) {
return this.minCpuCores >= other.minCpuCores &&
this.minDiskAvailableGb >= other.minDiskAvailableGb &&
@@ -168,12 +178,13 @@ public class Flavor {
this.fastDisk || ! other.fastDisk;
}
- public FlavorSpec asSpec() {
- if (isDocker())
- return new FlavorSpec(minCpuCores, minMainMemoryAvailableGb, minDiskAvailableGb);
- else
- return FlavorSpec.fromLegacyFlavorName(name);
- }
+ /**
+ * True if this is a configured flavor used for hosts,
+ * false if it is a virtual flavor created on the fly from node resources
+ */
+ public boolean isConfigured() { return configured; }
+
+ public NodeResources resources() { return resources; }
@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
deleted file mode 100644
index 62cfb59c51c..00000000000
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/FlavorSpec.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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 b87f6eeec31..1d29ed85c08 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
@@ -40,11 +40,11 @@ public class NodeFlavors {
if (configuredFlavors.containsKey(name))
return Optional.of(configuredFlavors.get(name));
- FlavorSpec flavorSpec = FlavorSpec.fromLegacyFlavorName(name);
- if (flavorSpec.allocateByLegacyName())
+ NodeResources nodeResources = NodeResources.fromLegacyName(name);
+ if (nodeResources.allocateByLegacyName())
return Optional.empty();
else
- return Optional.of(new Flavor(flavorSpec));
+ return Optional.of(new Flavor(nodeResources));
}
/**
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/NodeResources.java b/config-provisioning/src/main/java/com/yahoo/config/provision/NodeResources.java
new file mode 100644
index 00000000000..005bfac6b5c
--- /dev/null
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/NodeResources.java
@@ -0,0 +1,106 @@
+// 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.Optional;
+
+/**
+ * The node resources required by an application cluster
+ *
+ * @author bratseth
+ */
+public class NodeResources {
+
+ private final double vcpu;
+ private final double memoryGb;
+ private final double diskGb;
+
+ private final boolean allocateByLegacyName;
+
+ /** The legacy (flavor) name of this, or null if none */
+ private final String legacyName;
+
+ public NodeResources(double vcpu, double memoryGb, double diskGb) {
+ this.vcpu = vcpu;
+ this.memoryGb = memoryGb;
+ this.diskGb = diskGb;
+ this.allocateByLegacyName = false;
+ this.legacyName = null;
+ }
+
+ private NodeResources(double vcpu, double memoryGb, double diskGb, boolean allocateByLegacyName, String legacyName) {
+ this.vcpu = vcpu;
+ this.memoryGb = memoryGb;
+ this.diskGb = diskGb;
+ this.allocateByLegacyName = allocateByLegacyName;
+ this.legacyName = legacyName;
+ }
+
+ public double vcpu() { return vcpu; }
+ 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 name of this, or empty if none. */
+ public Optional<String> legacyName() {
+ return Optional.ofNullable(legacyName);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if ( ! (o instanceof NodeResources)) return false;
+ NodeResources other = (NodeResources)o;
+ if (allocateByLegacyName) {
+ return this.legacyName.equals(other.legacyName);
+ }
+ else {
+ if (this.vcpu != other.vcpu) 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 legacyName.hashCode();
+ else
+ return (int)(2503 * vcpu + 22123 * memoryGb + 26987 * diskGb);
+ }
+
+ @Override
+ public String toString() {
+ if (allocateByLegacyName)
+ return "flavor '" + legacyName + "'";
+ else
+ return "[vcpu: " + vcpu + ", memory: " + memoryGb + " Gb, disk " + diskGb + " Gb]";
+ }
+
+ /**
+ * Create this from serial form.
+ *
+ * @throws IllegalArgumentException if the given string cannot be parsed as a serial form of this
+ */
+ public static NodeResources fromLegacyName(String flavorString) {
+ if (flavorString.startsWith("d-")) { // A legacy docker flavor: We still allocate by numbers
+ 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 NodeResources(cpu, mem, dsk, false, flavorString);
+ }
+ else { // Another legacy flavor: Allocate by direct matching
+ return new NodeResources(0, 0, 0, true, flavorString);
+ }
+ }
+
+}
diff --git a/document/src/main/java/com/yahoo/document/StructDataType.java b/document/src/main/java/com/yahoo/document/StructDataType.java
index e39049c2b05..fc4792726c6 100644
--- a/document/src/main/java/com/yahoo/document/StructDataType.java
+++ b/document/src/main/java/com/yahoo/document/StructDataType.java
@@ -11,7 +11,7 @@ import java.util.Collection;
import java.util.Collections;
/**
- * @author <a href="mailto:einarmr@yahoo-inc.com">Einar M R Rosenvinge</a>
+ * @author Einar M R Rosenvinge
*/
public class StructDataType extends BaseStructDataType {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeList.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeList.java
index bfb7bfe9dae..7058917d351 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeList.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeList.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision;
import com.google.common.collect.ImmutableList;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import java.util.Collection;
@@ -44,6 +45,9 @@ public class NodeList implements Iterable<Node> {
return filter(node -> ! node.allocation().get().membership().retired());
}
+ /** Returns the subset of nodes having exactly the given resources */
+ public NodeList resources(NodeResources resources) { return filter(node -> node.flavor().resources().equals(resources)); }
+
/** Returns the subset of nodes of the given flavor */
public NodeList flavor(String flavor) {
return filter(node -> node.flavor().name().equals(flavor));
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 3831bfc55c1..bd2ce3a5f5e 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,10 +8,10 @@ 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;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.TenantName;
import com.yahoo.slime.ArrayTraverser;
@@ -70,8 +70,14 @@ public class NodeSerializer {
private static final String reportsKey = "reports";
private static final String modelNameKey = "modelName";
- // Configuration fields
+ // Node resource fields
+ // ...for hosts and nodes allocated by legacy flavor specs
private static final String flavorKey = "flavor";
+ // ...for nodes allocated by resources
+ private static final String resourcesKey = "resources";
+ private static final String vcpuKey = "vcpu";
+ private static final String memoryKey = "memory";
+ private static final String diskKey = "disk";
// Allocation fields
private static final String tenantIdKey = "tenantId";
@@ -115,7 +121,7 @@ public class NodeSerializer {
toSlime(node.ipAddressPool().asSet(), object.setArray(ipAddressPoolKey), IP::requireAddressPool);
object.setString(idKey, node.id());
node.parentHostname().ifPresent(hostname -> object.setString(parentHostnameKey, hostname));
- object.setString(flavorKey, node.flavor().name());
+ toSlime(node.flavor(), object);
object.setLong(rebootGenerationKey, node.status().reboot().wanted());
object.setLong(currentRebootGenerationKey, node.status().reboot().current());
node.status().vespaVersion().ifPresent(version -> object.setString(vespaVersionKey, version.toString()));
@@ -135,6 +141,19 @@ public class NodeSerializer {
node.modelName().ifPresent(modelName -> object.setString(modelNameKey, modelName));
}
+ private void toSlime(Flavor flavor, Cursor object) {
+ if (flavor.isConfigured()) {
+ object.setString(flavorKey, flavor.name());
+ }
+ else {
+ NodeResources resources = flavor.resources();
+ Cursor resourcesObject = object.setObject(resourcesKey);
+ resourcesObject.setDouble(vcpuKey, resources.vcpu());
+ resourcesObject.setDouble(memoryKey, resources.memoryGb());
+ resourcesObject.setDouble(diskKey, resources.diskGb());
+ }
+ }
+
private void toSlime(Allocation allocation, Cursor object) {
object.setString(tenantIdKey, allocation.owner().tenant().value());
object.setString(applicationIdKey, allocation.owner().application().value());
@@ -199,7 +218,15 @@ public class NodeSerializer {
}
private Flavor flavorFromSlime(Inspector object) {
- return flavors.getFlavorOrThrow(object.field(flavorKey).asString());
+ if (object.field(flavorKey).valid()) {
+ return flavors.getFlavorOrThrow(object.field(flavorKey).asString());
+ }
+ else {
+ Inspector resources = object.field(resourcesKey);
+ return new Flavor(new NodeResources(resources.field(vcpuKey).asDouble(),
+ resources.field(memoryKey).asDouble(),
+ resources.field(diskKey).asDouble()));
+ }
}
private Optional<Allocation> allocationFromSlime(Inspector object) {
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 36972cdcade..dbeed0c3e76 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,11 +4,10 @@ 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.NodeResources;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
-import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeFlavors;
import java.util.Arrays;
@@ -42,22 +41,28 @@ public class CapacityPolicies {
}
}
- public FlavorSpec decideFlavor(Capacity requestedCapacity, ClusterSpec cluster) {
- Optional<FlavorSpec> requestedFlavor = requestedCapacity.flavorSpec();
+ public NodeResources decideFlavor(Capacity requestedCapacity, ClusterSpec cluster) {
+ Optional<NodeResources> requestedFlavor = requestedCapacity.nodeResources();
if (requestedFlavor.isPresent() && ! requestedFlavor.get().allocateByLegacyName())
return requestedFlavor.get();
- FlavorSpec defaultFlavor = FlavorSpec.fromLegacyFlavorName(zone.defaultFlavor(cluster.type()));
+ NodeResources defaultFlavor = NodeResources.fromLegacyName(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.exists(requestedFlavor.get().legacyFlavorName()) ? requestedFlavor.get() : defaultFlavor;
+ return flavors.exists(requestedFlavor.get().legacyName().get()) ? requestedFlavor.get() : defaultFlavor;
else {
switch (zone.environment()) {
case dev: case test: case staging: return defaultFlavor;
- default: return flavors.getFlavorOrThrow(requestedFlavor.get().legacyFlavorName()).asSpec();
+ default:
+ // Check existence of the legacy specified flavor
+ flavors.getFlavorOrThrow(requestedFlavor.get().legacyName().get());
+ // Return this spec containing the legacy flavor name, not the flavor's capacity object
+ // which describes the flavors capacity, as the point of legacy allocation is to match
+ // by name, not by resources
+ return requestedFlavor.get();
}
}
}
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 4defaaef57c..d2ea0a1f3c8 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
@@ -1,8 +1,7 @@
// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.provisioning;
-import com.yahoo.config.provision.Flavor;
-import com.yahoo.config.provision.FlavorSpec;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.vespa.hosted.provision.Node;
import java.util.List;
@@ -24,7 +23,7 @@ public interface HostProvisioner {
* 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, FlavorSpec flavor);
+ List<ProvisionedHost> provisionHosts(List<Integer> provisionIndexes, NodeResources flavor);
/**
* Continue provisioning of given list of Nodes.
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 219ba759e24..22242cf8963 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
@@ -4,8 +4,7 @@ package com.yahoo.vespa.hosted.provision.provisioning;
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.NodeResources;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
@@ -220,7 +219,7 @@ class NodeAllocation {
}
private boolean hasCompatibleFlavor(Node node) {
- return requestedNodes.isCompatible(node.flavor().asSpec(), flavors);
+ return requestedNodes.isCompatible(node.flavor(), flavors);
}
private Node acceptNode(PrioritizableNode prioritizableNode, boolean wantToRetire) {
@@ -368,15 +367,15 @@ class NodeAllocation {
static class FlavorCount {
- private final FlavorSpec flavor;
+ private final NodeResources flavor;
private final int count;
- private FlavorCount(FlavorSpec flavor, int count) {
+ private FlavorCount(NodeResources flavor, int count) {
this.flavor = flavor;
this.count = count;
}
- FlavorSpec getFlavor() {
+ NodeResources 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 13006dd6ef7..d7fe7301b3a 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,7 +4,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.Flavor;
-import com.yahoo.config.provision.FlavorSpec;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.log.LogLevel;
@@ -218,7 +218,7 @@ class NodePrioritizer {
PrioritizableNode.Builder builder = new PrioritizableNode.Builder(node)
.withSurplusNode(isSurplusNode)
.withNewNode(isNewNode)
- .withPreferredOnFlavor(preferredOnFlavor(node));
+ .withPreferredOnFlavor(preferredOnLegacyFlavor(node));
allNodes.parentOf(node).ifPresent(parent -> {
builder.withParent(parent).withFreeParentCapacity(capacity.freeCapacityOf(parent, false));
@@ -232,11 +232,11 @@ class NodePrioritizer {
}
/** Needed to handle requests for legacy non-docker nodes only */
- private boolean preferredOnFlavor(Node node) {
+ private boolean preferredOnLegacyFlavor(Node node) {
if (requestedNodes instanceof NodeSpec.CountNodeSpec) {
- FlavorSpec requestedFlavorSpec = ((NodeSpec.CountNodeSpec)requestedNodes).getFlavor();
- if (requestedFlavorSpec.allocateByLegacyName()) {
- Flavor requestedFlavor = flavors.getFlavorOrThrow(requestedFlavorSpec.legacyFlavorName());
+ NodeResources requestedNodeResources = ((NodeSpec.CountNodeSpec)requestedNodes).getFlavor();
+ if (requestedNodeResources.allocateByLegacyName()) {
+ Flavor requestedFlavor = flavors.getFlavorOrThrow(requestedNodeResources.legacyName().get());
return ! requestedFlavor.isStock() && node.flavor().equals(requestedFlavor);
}
}
@@ -257,7 +257,7 @@ class NodePrioritizer {
return requestedNodes.fulfilledBy(nofNodesInCluster - nodeFailedNodes);
}
- private static FlavorSpec getFlavor(NodeSpec requestedNodes) {
+ private static NodeResources getFlavor(NodeSpec requestedNodes) {
if (requestedNodes instanceof NodeSpec.CountNodeSpec) {
NodeSpec.CountNodeSpec countSpec = (NodeSpec.CountNodeSpec) requestedNodes;
return countSpec.getFlavor();
@@ -266,7 +266,7 @@ class NodePrioritizer {
}
private boolean isDocker() {
- FlavorSpec flavor = getFlavor(requestedNodes);
+ NodeResources flavor = getFlavor(requestedNodes);
return (flavor != null) && ! flavor.allocateByLegacyName();
}
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 44ca50a29a6..057748ee7a2 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
@@ -6,8 +6,7 @@ import com.yahoo.config.provision.ApplicationId;
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.NodeResources;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeFlavors;
@@ -97,7 +96,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());
- FlavorSpec flavor = capacityPolicies.decideFlavor(requestedCapacity, cluster);
+ NodeResources 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 ed95a76a997..4cc7ed7898b 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,7 +1,7 @@
// 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.NodeResources;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Flavor;
@@ -28,7 +28,7 @@ public interface NodeSpec {
boolean isExclusive();
/** Returns whether the given flavor is compatible with this spec */
- boolean isCompatible(FlavorSpec flavor, NodeFlavors flavors);
+ boolean isCompatible(Flavor flavor, NodeFlavors flavors);
/** Returns whether the given node count is sufficient to consider this spec fulfilled to the maximum amount */
boolean saturatedBy(int count);
@@ -57,7 +57,7 @@ public interface NodeSpec {
*/
Node assignRequestedFlavor(Node node);
- static NodeSpec from(int nodeCount, FlavorSpec flavor, boolean exclusive, boolean canFail) {
+ static NodeSpec from(int nodeCount, NodeResources flavor, boolean exclusive, boolean canFail) {
return new CountNodeSpec(nodeCount, flavor, exclusive, canFail);
}
@@ -69,20 +69,19 @@ public interface NodeSpec {
class CountNodeSpec implements NodeSpec {
private final int count;
- private final FlavorSpec requestedFlavorSpec;
+ private final NodeResources requestedNodeResources;
private final boolean exclusive;
private final boolean canFail;
- CountNodeSpec(int count, FlavorSpec flavor, boolean exclusive, boolean canFail) {
+ CountNodeSpec(int count, NodeResources flavor, boolean exclusive, boolean canFail) {
this.count = count;
- this.requestedFlavorSpec = Objects.requireNonNull(flavor, "A flavor must be specified");
+ this.requestedNodeResources = Objects.requireNonNull(flavor, "A flavor must be specified");
this.exclusive = exclusive;
this.canFail = canFail;
}
- // TODO: Remove usage of this
- public FlavorSpec getFlavor() {
- return requestedFlavorSpec;
+ public NodeResources getFlavor() {
+ return requestedNodeResources;
}
@Override
@@ -92,17 +91,16 @@ public interface NodeSpec {
public NodeType type() { return NodeType.tenant; }
@Override
- 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;
+ public boolean isCompatible(Flavor flavor, NodeFlavors flavors) {
+ if (requestedNodeResources.allocateByLegacyName() && flavor.isConfigured()) {
+ if (flavor.satisfies(flavors.getFlavorOrThrow(requestedNodeResources.legacyName().get())))
+ return true;
}
else {
- if (flavorSpec.equals(requestedFlavorSpec)) return true;
+ if (requestedNodeResources.equals(flavor.resources()))
+ return true;
}
-
- return requestedFlavorCanBeAchievedByResizing(flavorSpec);
+ return requestedFlavorCanBeAchievedByResizing(flavor);
}
@Override
@@ -121,7 +119,7 @@ public interface NodeSpec {
@Override
public NodeSpec fraction(int divisor) {
- return new CountNodeSpec(count/divisor, requestedFlavorSpec, exclusive, canFail);
+ return new CountNodeSpec(count/divisor, requestedNodeResources, exclusive, canFail);
}
@Override
@@ -133,10 +131,10 @@ public interface NodeSpec {
}
@Override
- public String toString() { return "request for " + count + " nodes with " + requestedFlavorSpec; }
+ public String toString() { return "request for " + count + " nodes with " + requestedNodeResources; }
/** Docker nodes can be downsized in place */
- private boolean requestedFlavorCanBeAchievedByResizing(FlavorSpec flavor) {
+ private boolean requestedFlavorCanBeAchievedByResizing(Flavor 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);
@@ -161,7 +159,7 @@ public interface NodeSpec {
public boolean isExclusive() { return false; }
@Override
- public boolean isCompatible(FlavorSpec flavor, NodeFlavors flavors) { return true; }
+ public boolean isCompatible(Flavor flavor, NodeFlavors flavors) { return true; }
@Override
public boolean saturatedBy(int count) { return false; }
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 4c52f739c40..8a87d66f72b 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,7 +2,7 @@
package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.Flavor;
-import com.yahoo.config.provision.FlavorSpec;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.vespa.hosted.provision.Node;
/**
@@ -32,8 +32,8 @@ 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(NodeResources flavor) {
+ return new ResourceCapacity(flavor.memoryGb(), flavor.vcpu(), flavor.diskGb());
}
static ResourceCapacity of(Node node) {
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 b8b17011a8e..9fccdfda9fe 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
@@ -9,7 +9,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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
@@ -80,14 +80,14 @@ public class MockNodeRepository extends NodeRepository {
flavors.getFlavorOrThrow("expensive"), NodeType.tenant));
Node node4 = createNode("node4", "host4.yahoo.com", ipAddresses, Optional.of("dockerhost1.yahoo.com"),
- new Flavor(new FlavorSpec(1, 1, 100)), NodeType.tenant);
+ new Flavor(new NodeResources(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"),
- new Flavor(new FlavorSpec(1, 1, 100)), NodeType.tenant);
+ new Flavor(new NodeResources(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"))));
@@ -175,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.fromCount(2, new FlavorSpec(1, 1, 100), false, true), 1, null), app3, provisioner);
+ activate(provisioner.prepare(app3, cluster3, Capacity.fromCount(2, new NodeResources(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 d727ad68425..cc48c615864 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
@@ -233,8 +233,8 @@ public class FailedExpirerTest {
private static class FailureScenario {
private static final NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default", "docker");
- public static final FlavorSpec defaultFlavor = new FlavorSpec(2, 2, 2);
- public static final FlavorSpec dockerFlavor = new FlavorSpec(1, 1, 1);
+ public static final NodeResources defaultFlavor = new NodeResources(2, 2, 2);
+ public static final NodeResources dockerFlavor = new NodeResources(1, 1, 1);
private final MockCurator curator = new MockCurator();
private final ManualClock clock = new ManualClock();
@@ -270,7 +270,7 @@ public class FailedExpirerTest {
.orElseThrow(() -> new IllegalArgumentException("No such node: " + hostname));
}
- public FailureScenario withNode(NodeType type, FlavorSpec flavor, String hostname, String parentHostname) {
+ public FailureScenario withNode(NodeType type, NodeResources flavor, String hostname, String parentHostname) {
nodeRepository.addNodes(Collections.singletonList(
nodeRepository.createNode(UUID.randomUUID().toString(), hostname,
Optional.ofNullable(parentHostname), new Flavor(flavor), type)
@@ -278,7 +278,7 @@ public class FailedExpirerTest {
return this;
}
- public FailureScenario withNode(NodeType type, FlavorSpec flavor, String hostname) {
+ public FailureScenario withNode(NodeType type, NodeResources flavor, String hostname) {
return withNode(type, flavor, hostname, null);
}
@@ -318,7 +318,7 @@ public class FailedExpirerTest {
return allocate(clusterType, defaultFlavor, hostname);
}
- public FailureScenario allocate(ClusterSpec.Type clusterType, FlavorSpec flavor, String... hostname) {
+ public FailureScenario allocate(ClusterSpec.Type clusterType, NodeResources flavor, String... hostname) {
ClusterSpec clusterSpec = ClusterSpec.request(clusterType,
ClusterSpec.Id.from("test"),
Version.fromString("6.42"),
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 3b37c46add5..dd8929d562b 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.hosted.provision.lb.LoadBalancer;
@@ -82,7 +82,7 @@ public class LoadBalancerExpirerTest {
List<HostSpec> hosts = tester.prepare(application, ClusterSpec.request(ClusterSpec.Type.container, cluster,
Vtag.currentVersion, false, Collections.emptySet()),
2, 1,
- new FlavorSpec(1, 1, 1));
+ new NodeResources(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 8b69fb63aed..024bb7261bf 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
@@ -31,7 +31,6 @@ 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;
@@ -139,8 +138,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.fromCount(3, new FlavorSpec(1, 1, 1), false, true);
- Capacity capacity2 = Capacity.fromCount(5, new FlavorSpec(1, 1, 1), false, true);
+ Capacity capacity1 = Capacity.fromCount(3, new NodeResources(1, 1, 1), false, true);
+ Capacity capacity2 = Capacity.fromCount(5, new NodeResources(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 04014b3fa46..9d61f5414d6 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.hosted.provision.Node;
@@ -45,12 +45,12 @@ public class AclProvisioningTest {
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, FlavorSpec.fromLegacyFlavorName("d-1-1-1"), dockerHost.get(0).hostname());
+ tester.makeReadyVirtualDockerNodes(1, NodeResources.fromLegacyName("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, Capacity.fromCount(2, FlavorSpec.fromLegacyFlavorName("d-1-1-1"), false, true));
+ List<Node> activeNodes = deploy(application, Capacity.fromCount(2, NodeResources.fromLegacyName("d-1-1-1"), false, true));
assertEquals(2, activeNodes.size());
// Get trusted nodes for the first active node
@@ -132,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, new FlavorSpec(1, 1, 1),
+ List<Node> dockerNodes = tester.makeReadyVirtualDockerNodes(5, new NodeResources(1, 1, 1),
dockerHostNodeUnderTest.hostname());
List<NodeAcl> acls = tester.nodeRepository().getNodeAcls(dockerHostNodeUnderTest, true);
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 da32939dfd6..003593a7d1d 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeType;
@@ -37,7 +37,7 @@ import static org.junit.Assert.fail;
*/
public class DockerProvisioningTest {
- private static final FlavorSpec dockerFlavor = new FlavorSpec(1, 1, 1);
+ private static final NodeResources dockerFlavor = new NodeResources(1, 1, 1);
@Test
public void docker_application_deployment() {
@@ -56,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().asSpec());
+ assertEquals(dockerFlavor, nodes.asList().get(0).flavor().resources());
// Upgrade Vespa version on nodes
Version upgradedWantedVespaVersion = Version.fromString("6.40");
@@ -66,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().asSpec());
+ assertEquals(dockerFlavor, upgradedNodes.asList().get(0).flavor().resources());
assertEquals(hosts, upgradedHosts);
}
@@ -75,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, new FlavorSpec(2, 2, 2));
+ List<Node> parents = tester.makeReadyVirtualDockerHosts(10, new NodeResources(2, 2, 2));
for (Node parent : parents)
tester.makeReadyVirtualDockerNodes(1, dockerFlavor, parent.hostname());
@@ -205,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 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.",
+ "Could not satisfy request for 3 nodes with [vcpu: 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());
}
@@ -226,7 +226,7 @@ public class DockerProvisioningTest {
NodeList nodes = tester.getNodes(application1, Node.State.active);
assertEquals(1, nodes.size());
- assertEquals(dockerFlavor.legacyFlavorName(), nodes.asList().get(0).flavor().canonicalName());
+ assertEquals("[vcpu: 1.0, memory: 1.0 Gb, disk 1.0 Gb]", nodes.asList().get(0).flavor().canonicalName());
}
private Set<String> hostsOf(NodeList nodes) {
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 3e72b332077..76425fb5d4a 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.OutOfCapacityException;
@@ -65,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);
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
// Application 1
ApplicationId application1 = makeApplicationId("t1", "a1");
@@ -108,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);
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
// Application 1
ApplicationId application1 = makeApplicationId("t1", "a1");
@@ -165,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);
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
// Application 1
ApplicationId application1 = makeApplicationId("t1", "a1");
@@ -194,7 +194,7 @@ public class DynamicDockerAllocationTest {
//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, new FlavorSpec(1, 1, 1));
+ tester.prepare(application1, clusterSpec("myContent.t1.a1"), 6, 2, new NodeResources(1, 1, 1));
fail("Two groups have been allocated to the same parent host");
}
@@ -212,7 +212,7 @@ public class DynamicDockerAllocationTest {
ApplicationId application1 = tester.makeApplicationId();
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
deployZoneApp(tester);
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
// Deploy initial state (can max deploy 3 nodes due to redundancy requirements)
ClusterSpec clusterSpec = clusterSpec("myContent.t1.a1");
@@ -246,7 +246,7 @@ public class DynamicDockerAllocationTest {
tester.makeReadyNodes(3, "host-small", NodeType.host, 32);
deployZoneApp(tester);
ApplicationId application1 = tester.makeApplicationId();
- List<HostSpec> hosts = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 3, 1, new FlavorSpec(1, 1, 1));
+ List<HostSpec> hosts = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 3, 1, new NodeResources(1, 1, 1));
tester.activate(application1, ImmutableSet.copyOf(hosts));
List<Node> initialSpareCapacity = findSpareCapacity(tester);
@@ -260,7 +260,7 @@ public class DynamicDockerAllocationTest {
deployZoneApp(tester);
ApplicationId application = tester.makeApplicationId();
- tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, new FlavorSpec(1, 1, 1));
+ tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, new NodeResources(1, 1, 1));
}
@Test
@@ -270,7 +270,7 @@ public class DynamicDockerAllocationTest {
deployZoneApp(tester);
ApplicationId application = tester.makeApplicationId();
- List<HostSpec> hosts = tester.prepare(application, clusterSpec("myContent.t1.a1"), 2, 1, new FlavorSpec(1, 1, 1));
+ List<HostSpec> hosts = tester.prepare(application, clusterSpec("myContent.t1.a1"), 2, 1, new NodeResources(1, 1, 1));
tester.activate(application, hosts);
List<Node> activeNodes = tester.nodeRepository().getNodes(application);
@@ -282,12 +282,12 @@ public class DynamicDockerAllocationTest {
return ApplicationId.from(tenant, appName, "default");
}
- private void deployApp(ApplicationId id, ClusterSpec spec, FlavorSpec flavor, ProvisioningTester tester, int nodeCount) {
+ private void deployApp(ApplicationId id, ClusterSpec spec, NodeResources 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, FlavorSpec flavor, int index, ProvisioningTester tester) {
+ private void addAndAssignNode(ApplicationId id, String hostname, String parentHostname, ClusterSpec clusterSpec, NodeResources 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
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 7c7892055e2..5877de7913f 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.flags.Flags;
@@ -45,7 +45,7 @@ public class DynamicDockerProvisionTest {
assertEquals(0, tester.nodeRepository().list().size());
ApplicationId application1 = tester.makeApplicationId();
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small"));
List<HostSpec> hostSpec = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 4, 1, flavor);
@@ -65,7 +65,7 @@ public class DynamicDockerProvisionTest {
deployZoneApp(tester);
ApplicationId application = tester.makeApplicationId();
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("small"));
tester.prepare(application, clusterSpec("myContent.t2.a2"), 2, 1, flavor);
@@ -75,7 +75,7 @@ public class DynamicDockerProvisionTest {
@Test
public void allocates_to_hosts_already_hosting_nodes_by_this_tenant() {
ApplicationId application = tester.makeApplicationId();
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
List<Integer> expectedProvisionIndexes = List.of(100, 101);
mockHostProvisioner(hostProvisioner, tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("large"));
@@ -125,7 +125,7 @@ public class DynamicDockerProvisionTest {
private static void mockHostProvisioner(HostProvisioner hostProvisioner, Flavor hostFlavor) {
doAnswer(invocation -> {
List<Integer> provisionIndexes = (List<Integer>) invocation.getArguments()[0];
- FlavorSpec nodeFlavor = (FlavorSpec) invocation.getArguments()[1];
+ NodeResources nodeFlavor = (NodeResources) invocation.getArguments()[1];
return provisionIndexes.stream()
.map(i -> new ProvisionedHost("id-" + i, "host-" + i, hostFlavor, "host-" + i + "-1", new Flavor(nodeFlavor)))
.collect(Collectors.toList());
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 d982669413e..58c0b3ed9cc 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.RotationName;
@@ -140,7 +140,7 @@ public class LoadBalancerProvisionerTest {
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, new FlavorSpec(1, 1, 1)));
+ allNodes.addAll(tester.prepare(application, spec, 2, 1, new NodeResources(1, 1, 1)));
}
return allNodes;
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java
index aca3c884ffc..fcb4216e36c 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java
@@ -150,6 +150,8 @@ public class MultigroupProvisioningTest {
private void deploy(ApplicationId application, int nodeCount, int groupCount, ProvisioningTester tester) {
deploy(application, Capacity.fromNodeCount(nodeCount, Optional.of("default"), false, true), groupCount, tester);
}
+
+ @SuppressWarnings("deprecation") // TODO: Remove
private void deploy(ApplicationId application, Capacity capacity, int wantedGroups, ProvisioningTester tester) {
int nodeCount = capacity.nodeCount();
String flavor = capacity.flavor().get();
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 953bce6b6b2..1457c8841b2 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,7 +10,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.NodeResources;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
@@ -71,34 +71,34 @@ public class ProvisioningTest {
tester.makeReadyNodes(21, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
+ SystemState state1 = prepare(application1, 2, 2, 3, 3, new NodeResources(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// redeploy
- SystemState state2 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
+ SystemState state2 = prepare(application1, 2, 2, 3, 3, new NodeResources(1, 1, 1), tester);
state2.assertEquals(state1);
tester.activate(application1, state2.allHosts);
// deploy another application
- SystemState state1App2 = prepare(application2, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
+ SystemState state1App2 = prepare(application2, 2, 2, 3, 3, new NodeResources(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, new FlavorSpec(1, 1, 1), tester);
- SystemState state4 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
+ SystemState state3 = prepare(application1, 2, 2, 3, 3, new NodeResources(1, 1, 1), tester);
+ SystemState state4 = prepare(application1, 2, 2, 3, 3, new NodeResources(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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state5 = prepare(application1, 2, 2, 3, 3, new NodeResources(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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state6 = prepare(application1, 0, 2, 0, 3, new NodeResources(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());
@@ -117,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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state2App2 = prepare(application2, 2, 2, 3, 3, new NodeResources(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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state7 = prepare(application1, 2, 2, 3, 3, new NodeResources(1, 1, 1), tester);
state7.assertEquals(state1);
tester.activate(application1, state7.allHosts);
assertEquals(0, tester.getNodes(application1, Node.State.inactive).size());
@@ -151,7 +151,7 @@ public class ProvisioningTest {
tester.makeReadyNodes(4, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 1, 1, 1, 1, new FlavorSpec(1, 1, 1), tester);
+ SystemState state1 = prepare(application1, 1, 1, 1, 1, new NodeResources(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
HostSpec host1 = state1.container0.iterator().next();
@@ -160,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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state2 = prepare(application1, 1, 1, 1, 1, new NodeResources(1, 1, 1), tester);
tester.activate(application1, state2.allHosts);
host1 = state2.container0.iterator().next();
@@ -176,17 +176,17 @@ public class ProvisioningTest {
tester.makeReadyNodes(24, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 2, 2, 3, 3, new FlavorSpec(1, 1, 1), tester);
+ SystemState state1 = prepare(application1, 2, 2, 3, 3, new NodeResources(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// redeploy with increased sizes
- SystemState state2 = prepare(application1, 3, 4, 4, 5, new FlavorSpec(1, 1, 1), tester);
+ SystemState state2 = prepare(application1, 3, 4, 4, 5, new NodeResources(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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state3 = prepare(application1, 2, 2, 3, 3, new NodeResources(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());
@@ -194,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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state4 = prepare(application1, 4, 5, 5, 6, new NodeResources(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());
@@ -210,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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state5 = prepare(application1, 2, 2, 3, 3, new NodeResources(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()); //
@@ -218,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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state6 = prepare(application1, 2, 2, 4, 3, new NodeResources(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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state7 = prepare(application1, 8, 2, 2, 2, new NodeResources(1, 1, 1), tester);
// delete app
NestedTransaction removeTransaction = new NestedTransaction();
@@ -243,24 +243,27 @@ public class ProvisioningTest {
tester.makeReadyNodes(12, "d-1-1-1");
tester.makeReadyNodes(16, "d-2-2-2");
+ NodeResources small = new NodeResources(1, 1, 1);
+ NodeResources large = new NodeResources(2, 2, 2);
+
// deploy
- SystemState state1 = prepare(application1, 2, 2, 4, 4, new FlavorSpec(1, 1, 1), tester);
+ SystemState state1 = prepare(application1, 2, 2, 4, 4, small, 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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state2 = prepare(application1, 2, 2, 3, 3, small, tester);
tester.activate(application1, state2.allHosts);
// redeploy with increased sizes and new flavor
- SystemState state3 = prepare(application1, 3, 4, 4, 5, new FlavorSpec(2, 2, 2), tester);
+ SystemState state3 = prepare(application1, 3, 4, 4, 5, large, 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("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("d-1-1-1").size());
- assertEquals("No 'large' content nodes are retired",
- 0, tester.getNodes(application1, Node.State.active).retired().flavor("d-2-2-2").size());
+ 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).resources(small).size());
+ assertEquals("'small content nodes are retired",
+ 4 + 4, tester.getNodes(application1, Node.State.active).retired().type(ClusterSpec.Type.content).resources(small).size());
+ assertEquals("No large content nodes are retired",
+ 0, tester.getNodes(application1, Node.State.active).retired().resources(large).size());
}
// TODO: Enable when this feature is re-enabled
@@ -274,11 +277,11 @@ public class ProvisioningTest {
tester.makeReadyNodes(14, "d-2-2-2", NodeType.host);
// deploy
- SystemState state1 = prepare(application1, 2, 2, 4, 4, new FlavorSpec(2, 2, 2), tester);
+ SystemState state1 = prepare(application1, 2, 2, 4, 4, new NodeResources(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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state2 = prepare(application1, 2, 2, 4, 4, new NodeResources(1, 1, 1), tester);
tester.activate(application1, state2.allHosts);
assertEquals(12, tester.getNodes(application1, Node.State.active).size());
@@ -324,12 +327,12 @@ public class ProvisioningTest {
// deploy with flavor which will be fulfilled by some old and new nodes
SystemState state1 = prepare(application1, 2, 2, 4, 4,
- FlavorSpec.fromLegacyFlavorName("old-large1"), tester);
+ NodeResources.fromLegacyName("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,
- FlavorSpec.fromLegacyFlavorName("old-large2"), tester);
+ NodeResources.fromLegacyName("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",
@@ -339,13 +342,13 @@ public class ProvisioningTest {
// This is a noop as we are already using large nodes and nodes which replace large
SystemState state3 = prepare(application1, 3, 4, 4, 5,
- FlavorSpec.fromLegacyFlavorName("large"), tester);
+ NodeResources.fromLegacyName("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,
- FlavorSpec.fromLegacyFlavorName("large-variant"), tester);
+ NodeResources.fromLegacyName("large-variant"), tester);
fail("Should fail as we don't have that many large-variant nodes");
}
catch (OutOfCapacityException expected) {
@@ -354,7 +357,7 @@ 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,
- FlavorSpec.fromLegacyFlavorName("large-variant"), tester);
+ NodeResources.fromLegacyName("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
@@ -371,13 +374,13 @@ public class ProvisioningTest {
// deploy
SystemState state1 = prepare(application1, 2, 0, 3, 0,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// redeploy a too large application
try {
SystemState state2 = prepare(application1, 3, 0, 3, 0,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
fail("Expected out of capacity exception");
}
catch (OutOfCapacityException expected) {
@@ -385,7 +388,7 @@ public class ProvisioningTest {
// deploy first state again
SystemState state3 = prepare(application1, 2, 0, 3, 0,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
tester.activate(application1, state3.allHosts);
}
@@ -396,7 +399,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
tester.makeReadyNodes(4, "d-1-1-1");
SystemState state = prepare(application, 2, 2, 3, 3,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -407,7 +410,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
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);
+ SystemState state = prepare(application, 2, 2, 3, 3, new NodeResources(1, 1, 1), Version.fromString("6.91"), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -419,7 +422,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
tester.makeReadyNodes(4, "d-1-1-1");
SystemState state = prepare(application, 2, 2, 3, 3,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -431,7 +434,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
tester.makeReadyNodes(10, "d-1-1-1");
prepare(application, 1, 2, 3, 3,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
}
/** Dev always uses the zone default flavor */
@@ -442,7 +445,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
tester.makeReadyNodes(4, "d-2-2-2");
SystemState state = prepare(application, 2, 2, 3, 3,
- new FlavorSpec(2, 2, 2), tester);
+ new NodeResources(2, 2, 2), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -455,7 +458,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
tester.makeReadyNodes(4, "d-2-2-2");
SystemState state = prepare(application, 2, 2, 3, 3,
- new FlavorSpec(2, 2, 2), tester);
+ new NodeResources(2, 2, 2), tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -467,7 +470,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
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
+ new NodeResources(1, 1, 1), tester); // becomes 1, 1, 1, 6
assertEquals(9, state.allHosts.size());
tester.activate(application, state.allHosts);
}
@@ -479,7 +482,7 @@ public class ProvisioningTest {
tester.makeReadyNodes(10, "d-1-1-1");
ApplicationId application = tester.makeApplicationId();
SystemState state = prepare(application, 2, 2, 3, 3,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
// Simulate expiry
NestedTransaction deactivateTransaction = new NestedTransaction();
@@ -503,7 +506,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
try {
prepare(application, 2, 2, 3, 3,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
fail("Expected exception");
}
catch (OutOfCapacityException e) {
@@ -533,7 +536,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
try {
prepare(application, 2, 2, 3, 3,
- FlavorSpec.fromLegacyFlavorName("large"), tester);
+ NodeResources.fromLegacyName("large"), tester);
fail("Expected exception");
}
catch (OutOfCapacityException e) {
@@ -558,7 +561,7 @@ public class ProvisioningTest {
try {
prepare(application, 2, 0, 2, 0,
- FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
+ NodeResources.fromLegacyName(flavorToRetire), tester);
fail("Expected exception");
} catch (OutOfCapacityException e) {
assertTrue(e.getMessage().startsWith("Could not satisfy request"));
@@ -576,7 +579,7 @@ public class ProvisioningTest {
try {
prepare(application, 2, 0, 2, 0,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
fail("Expected exception");
} catch (OutOfCapacityException e) {
assertTrue(e.getMessage().startsWith("Could not satisfy request"));
@@ -590,7 +593,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
try {
prepare(application, 2, 2, 3, 3,
- FlavorSpec.fromLegacyFlavorName("nonexisting"), tester);
+ NodeResources.fromLegacyName("nonexisting"), tester);
fail("Expected exception");
}
catch (IllegalArgumentException e) {
@@ -607,11 +610,11 @@ public class ProvisioningTest {
tester.makeReadyNodes(14, "d-1-1-1");
// deploy
- SystemState state1 = prepare(application1, 3, 3, 4, 4, new FlavorSpec(1, 1, 1), tester);
+ SystemState state1 = prepare(application1, 3, 3, 4, 4, new NodeResources(1, 1, 1), tester);
tester.activate(application1, state1.allHosts);
// decrease cluster sizes
- SystemState state2 = prepare(application1, 2, 2, 2, 2, new FlavorSpec(1, 1, 1), tester);
+ SystemState state2 = prepare(application1, 2, 2, 2, 2, new NodeResources(1, 1, 1), tester);
tester.activate(application1, state2.allHosts);
// content0
@@ -657,7 +660,7 @@ public class ProvisioningTest {
.flavorsConfig(b.build()).curator(curator).nameResolver(nameResolver).build();
tester.makeReadyNodes(4, flavorToRetire);
SystemState state = prepare(application, 2, 0, 2, 0,
- FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
+ NodeResources.fromLegacyName(flavorToRetire), tester);
tester.activate(application, state.allHosts);
}
@@ -677,7 +680,7 @@ public class ProvisioningTest {
tester.makeReadyNodes(4, replacementFlavor);
SystemState state = prepare(application, 2, 0, 2, 0,
- FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
+ NodeResources.fromLegacyName(flavorToRetire), tester);
tester.activate(application, state.allHosts);
@@ -708,7 +711,7 @@ public class ProvisioningTest {
tester.makeReadyNodes(4, replacementFlavor);
SystemState state = prepare(application, 2, 0, 2, 0,
- FlavorSpec.fromLegacyFlavorName(flavorToRetire), tester);
+ NodeResources.fromLegacyName(flavorToRetire), tester);
tester.activate(application, state.allHosts);
@@ -727,7 +730,7 @@ public class ProvisioningTest {
// Deploy application
{
SystemState state = prepare(application, 2, 0, 2, 0,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
tester.activate(application, state.allHosts);
assertEquals(4, tester.getNodes(application, Node.State.active).size());
}
@@ -737,7 +740,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, new FlavorSpec(1, 1, 1), tester);
+ SystemState state = prepare(application, 2, 0, 2, 0, new NodeResources(1, 1, 1), tester);
tester.activate(application, state.allHosts);
List<Node> retiredNodes = tester.getNodes(application).retired().asList();
@@ -756,7 +759,7 @@ public class ProvisioningTest {
// Deploy fails with out of capacity
try {
prepare(application, 2, 0, 2, 0,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(1, 1, 1), tester);
fail("Expected exception");
} catch (OutOfCapacityException ignored) {}
assertEquals("Reserved a subset of required nodes", 2,
@@ -768,7 +771,7 @@ public class ProvisioningTest {
// Deploy is retried after a few minutes
tester.clock().advance(Duration.ofMinutes(2));
SystemState state = prepare(application, 2, 0, 2, 0,
- new FlavorSpec(1, 1, 1), tester);
+ new NodeResources(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",
@@ -795,7 +798,7 @@ 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, new FlavorSpec(1, 1, 1), Version.fromString("6.42"), tester);
+ prepare(application, 1, 0, 1, 0, true, new NodeResources(1, 1, 1), Version.fromString("6.42"), tester);
fail("Expected exception");
} catch (IllegalArgumentException ignored) {}
}
@@ -819,9 +822,9 @@ public class ProvisioningTest {
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,
- FlavorSpec.fromLegacyFlavorName("large"));
+ NodeResources.fromLegacyName("large"));
List<HostSpec> contentNodes = tester.prepare(applicationId, contentClusterSpec, 10, 1,
- FlavorSpec.fromLegacyFlavorName("large"));
+ NodeResources.fromLegacyName("large"));
if (largeIsStock) { // 'large' is replaced by 'large-variant' when possible, as it is cheaper
tester.assertNumberOfNodesWithFlavor(containerNodes, "large-variant", 5);
@@ -838,19 +841,19 @@ public class ProvisioningTest {
}
private SystemState prepare(ApplicationId application, int container0Size, int container1Size, int content0Size,
- int content1Size, FlavorSpec flavor, ProvisioningTester tester) {
+ int content1Size, NodeResources 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, FlavorSpec flavor, Version wantedVersion, ProvisioningTester tester) {
+ int content1Size, NodeResources 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, FlavorSpec flavor, Version wantedVersion,
+ int content1Size, boolean required, NodeResources 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());
@@ -893,7 +896,7 @@ public class ProvisioningTest {
}
private Set<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups,
- boolean required, FlavorSpec flavor, ProvisioningTester tester) {
+ boolean required, NodeResources 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 6f026181510..708ccf486f7 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
@@ -130,11 +130,11 @@ public class ProvisioningTester {
public void patchNode(Node node) { nodeRepository.write(node); }
- public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, FlavorSpec flavor) {
+ public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, NodeResources flavor) {
return prepare(application, cluster, nodeCount, groups, false, flavor);
}
- public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, boolean required, FlavorSpec flavor) {
+ public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, boolean required, NodeResources flavor) {
return prepare(application, cluster, Capacity.fromCount(nodeCount, Optional.ofNullable(flavor), required, true), groups);
}
@@ -275,7 +275,7 @@ public class ProvisioningTester {
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)));
+ flavor = Optional.of(new Flavor(NodeResources.fromLegacyName(flavorName)));
else
throw new IllegalArgumentException("No flavor '" + flavorName + "'");
}
@@ -336,31 +336,31 @@ public class ProvisioningTester {
}
/** Creates a set of virtual docker hosts */
- public List<Node> makeReadyVirtualDockerHosts(int n, FlavorSpec flavor) {
+ public List<Node> makeReadyVirtualDockerHosts(int n, NodeResources 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, FlavorSpec flavor, String dockerHostId) {
+ public List<Node> makeReadyVirtualDockerNodes(int n, NodeResources 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, FlavorSpec flavor, String dockerHostId) {
+ public List<Node> makeReadyVirtualDockerNode(int index, NodeResources 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, FlavorSpec flavor) {
+ public List<Node> makeReadyVirtualNodes(int n, NodeResources 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, FlavorSpec flavor, Optional<String> parentHostId,
+ private List<Node> makeReadyVirtualNodes(int count, int startIndex, NodeResources flavor, Optional<String> parentHostId,
Function<Integer, String> nodeNamer, NodeType nodeType) {
List<Node> nodes = new ArrayList<>(count);
for (int i = startIndex; i < count + startIndex; i++) {
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 5482731bfb6..1f03db8f7c2 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,7 +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.NodeResources;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.OutOfCapacityException;
import com.yahoo.config.provision.RegionName;
@@ -35,7 +35,7 @@ import static org.junit.Assert.assertNotNull;
// to remove these tests
public class VirtualNodeProvisioningTest {
- private static final FlavorSpec flavor = new FlavorSpec(4, 8, 100);
+ private static final NodeResources flavor = new NodeResources(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());
@@ -82,7 +82,7 @@ public class VirtualNodeProvisioningTest {
// Allowed to use same parent host for several nodes in same cluster in dev
{
- FlavorSpec flavor = new FlavorSpec(1, 1, 1);
+ NodeResources flavor = new NodeResources(1, 1, 1);
tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
tester.makeReadyVirtualDockerNodes(4, flavor, "parentHost1");
@@ -295,7 +295,7 @@ public class VirtualNodeProvisioningTest {
return tester.prepare(applicationId, clusterSpec, nodeCount, groups, flavor);
}
- private List<HostSpec> prepare(ClusterSpec clusterSpec, int nodeCount, int groups, FlavorSpec flavor) {
+ private List<HostSpec> prepare(ClusterSpec clusterSpec, int nodeCount, int groups, NodeResources flavor) {
return tester.prepare(applicationId, clusterSpec, nodeCount, groups, flavor);
}
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 86565780cfe..5c3829bd5ff 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,8 +6,8 @@
"hostname": "test-container-1",
"parentHostname": "dockerhost3.yahoo.com",
"openStackId": "fake-test-container-1",
- "flavor": "d-1-1-100",
- "canonicalFlavor": "d-1-1-100",
+ "flavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
+ "canonicalFlavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
"minDiskAvailableGb": 100.0,
"minMainMemoryAvailableGb": 1.0,
"minCpuCores": 1.0,
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 40e34891545..0733473c2fe 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,8 +6,8 @@
"hostname": "host11.yahoo.com",
"parentHostname": "parent.host.yahoo.com",
"openStackId": "host11.yahoo.com",
- "flavor": "d-1-1-100",
- "canonicalFlavor": "d-1-1-100",
+ "flavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
+ "canonicalFlavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
"minDiskAvailableGb": 100.0,
"minMainMemoryAvailableGb": 1.0,
"minCpuCores": 1.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 9a3c45c709f..1cb1f6657e4 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,8 +6,8 @@
"hostname": "host4.yahoo.com",
"parentHostname": "dockerhost1.yahoo.com",
"openStackId": "node4",
- "flavor": "d-1-1-100",
- "canonicalFlavor": "d-1-1-100",
+ "flavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
+ "canonicalFlavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
"minDiskAvailableGb": 100.0,
"minMainMemoryAvailableGb": 1.0,
"minCpuCores": 1.0,
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 f7b920490a6..8a5c80212c7 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,8 +6,8 @@
"hostname": "host5.yahoo.com",
"parentHostname": "dockerhost2.yahoo.com",
"openStackId": "node5",
- "flavor": "d-1-1-100",
- "canonicalFlavor": "d-1-1-100",
+ "flavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
+ "canonicalFlavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
"minDiskAvailableGb": 100.0,
"minMainMemoryAvailableGb": 1.0,
"minCpuCores": 1.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 4376b27cd5a..08817a67324 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,8 +6,8 @@
"hostname": "host5.yahoo.com",
"parentHostname": "dockerhost2.yahoo.com",
"openStackId": "node5",
- "flavor": "d-1-1-100",
- "canonicalFlavor": "d-1-1-100",
+ "flavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
+ "canonicalFlavor": "[vcpu: 1.0, memory: 1.0 Gb, disk 100.0 Gb]",
"minDiskAvailableGb": 100.0,
"minMainMemoryAvailableGb": 1.0,
"minCpuCores": 1.0,